feat: add OpenGraph metadata for feed URLs in bskyweb
Enable rich link previews when feed URLs are shared in iMessage, Slack, and other social platforms. Adds feed title, description, creator info, and avatar images to improve sharing experience.
This commit is contained in:
@@ -313,7 +313,7 @@ func serve(cctx *cli.Context) error {
|
||||
e.GET("/profile/:handleOrDID/known-followers", server.WebGeneric)
|
||||
e.GET("/profile/:handleOrDID/search", server.WebGeneric)
|
||||
e.GET("/profile/:handleOrDID/lists/:rkey", server.WebGeneric)
|
||||
e.GET("/profile/:handleOrDID/feed/:rkey", server.WebGeneric)
|
||||
e.GET("/profile/:handleOrDID/feed/:rkey", server.WebFeed)
|
||||
e.GET("/profile/:handleOrDID/feed/:rkey/liked-by", server.WebGeneric)
|
||||
e.GET("/profile/:handleOrDID/labeler/liked-by", server.WebGeneric)
|
||||
|
||||
@@ -603,6 +603,57 @@ func (srv *Server) WebProfile(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
|
||||
func (srv *Server) WebFeed(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
data := srv.NewTemplateContext()
|
||||
|
||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||
rkeyParam := c.Param("rkey")
|
||||
rkey, err := syntax.ParseRecordKey(rkeyParam)
|
||||
if err != nil {
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
handleOrDIDParam := c.Param("handleOrDID")
|
||||
handleOrDID, err := syntax.ParseAtIdentifier(handleOrDIDParam)
|
||||
if err != nil {
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
|
||||
identifier := handleOrDID.Normalize().String()
|
||||
|
||||
// requires two fetches: first fetch profile to get DID
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, identifier)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch profile for: %s\t%v", identifier, err)
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
unauthedViewingOkay := true
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
unauthedViewingOkay = false
|
||||
}
|
||||
}
|
||||
|
||||
if !unauthedViewingOkay {
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
did := pv.Did
|
||||
data["did"] = did
|
||||
|
||||
// then fetch the feed generator
|
||||
feedURI := fmt.Sprintf("at://%s/app.bsky.feed.generator/%s", did, rkey)
|
||||
fgv, err := appbsky.FeedGetFeedGenerator(ctx, srv.xrpcc, feedURI)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch feed generator: %s\t%v", feedURI, err)
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
req := c.Request()
|
||||
data["feedView"] = fgv.View
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
|
||||
return c.Render(http.StatusOK, "feed.html", data)
|
||||
}
|
||||
|
||||
type IPCCRequest struct {
|
||||
IP string `json:"ip"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user