Include expanded urls in social cards (#2427)
* include expanded urls in social cards (#2427) * break expandPostLinks into its own function, add bounds checkingzio/stable
parent
cdbdb37aac
commit
c58e65000d
|
@ -10,6 +10,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
@ -351,9 +352,54 @@ func (srv *Server) WebPost(c echo.Context) error {
|
||||||
data["imgThumbUrls"] = thumbUrls
|
data["imgThumbUrls"] = thumbUrls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data["postText"] = expandPostLinks(postView)
|
||||||
|
|
||||||
return c.Render(http.StatusOK, "post.html", data)
|
return c.Render(http.StatusOK, "post.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// function to expand shortened links in rich text back to full urls, replacing shortened urls in
|
||||||
|
// social card meta tags and the noscript output. this essentially reverses the effect
|
||||||
|
// of shortenLinks() in src/lib/strings/rich-text-manip.ts
|
||||||
|
func expandPostLinks(postView *appbsky.FeedDefs_PostView) string {
|
||||||
|
if postView.Record != nil {
|
||||||
|
rec := postView.Record.Val.(*appbsky.FeedPost)
|
||||||
|
postText := rec.Text
|
||||||
|
var charsAdded int64 = 0
|
||||||
|
// iterate over facets, check if they're link facets, and if found, grab the uri
|
||||||
|
for _, facet := range rec.Facets {
|
||||||
|
linkUri := ""
|
||||||
|
if slices.ContainsFunc(facet.Features, func(feat *appbsky.RichtextFacet_Features_Elem) bool {
|
||||||
|
if feat.RichtextFacet_Link != nil && feat.RichtextFacet_Link.LexiconTypeID == "app.bsky.richtext.facet#link" {
|
||||||
|
linkUri = feat.RichtextFacet_Link.Uri
|
||||||
|
// only expand uris that have been shortened (as opposed to those with non-uri anchor text)
|
||||||
|
if int64(len(postText)) >= facet.Index.ByteEnd+charsAdded &&
|
||||||
|
strings.HasSuffix(postText[facet.Index.ByteStart+charsAdded:facet.Index.ByteEnd+charsAdded], "...") &&
|
||||||
|
strings.Contains(linkUri, postText[facet.Index.ByteStart+charsAdded:(facet.Index.ByteEnd+charsAdded)-3]) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}) {
|
||||||
|
// replace the shortened uri with the full length one from the facet using utf8 byte offsets
|
||||||
|
if int64(len(postText)) >= facet.Index.ByteEnd+charsAdded {
|
||||||
|
postText = postText[0:facet.Index.ByteStart+charsAdded] + linkUri + postText[facet.Index.ByteEnd+charsAdded:]
|
||||||
|
charsAdded += int64(len(linkUri)) - (facet.Index.ByteEnd - facet.Index.ByteStart)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if the post has an embeded link and its url doesn't already appear in postText, append it to
|
||||||
|
// the end to avoid social cards with missing links
|
||||||
|
if postView.Embed != nil &&
|
||||||
|
postView.Embed.EmbedExternal_View != nil &&
|
||||||
|
!strings.Contains(postText, postView.Embed.EmbedExternal_View.External.Uri) {
|
||||||
|
postText = fmt.Sprintf("%s\n%s", postText, postView.Embed.EmbedExternal_View.External.Uri)
|
||||||
|
}
|
||||||
|
return postText
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *Server) WebProfile(c echo.Context) error {
|
func (srv *Server) WebProfile(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
data := pongo2.Context{}
|
data := pongo2.Context{}
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<meta property="og:title" content="@{{ postView.Author.Handle }}">
|
<meta property="og:title" content="@{{ postView.Author.Handle }}">
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{%- if postView.Record.Val.Text %}
|
{%- if postText %}
|
||||||
<meta name="description" content="{{ postView.Record.Val.Text }}">
|
<meta name="description" content="{{ postText }}">
|
||||||
<meta property="og:description" content="{{ postView.Record.Val.Text }}">
|
<meta property="og:description" content="{{ postText }}">
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
{%- if imgThumbUrls %}
|
{%- if imgThumbUrls %}
|
||||||
{% for imgThumbUrl in imgThumbUrls %}
|
{% for imgThumbUrl in imgThumbUrls %}
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
<p id="bsky_display_name">{{ postView.Author.DisplayName }}</p>
|
<p id="bsky_display_name">{{ postView.Author.DisplayName }}</p>
|
||||||
<p id="bsky_handle">{{ postView.Author.Handle }}</p>
|
<p id="bsky_handle">{{ postView.Author.Handle }}</p>
|
||||||
<p id="bsky_did">{{ postView.Author.Did }}</p>
|
<p id="bsky_did">{{ postView.Author.Did }}</p>
|
||||||
<p id="bsky_post_text">{{ postView.Record.Val.Text }}</p>
|
<p id="bsky_post_text">{{ postText }}</p>
|
||||||
<p id="bsky_post_indexedat">{{ postView.IndexedAt }}</p>
|
<p id="bsky_post_indexedat">{{ postView.IndexedAt }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif -%}
|
{% endif -%}
|
||||||
|
|
Loading…
Reference in New Issue