diff --git a/bskyweb/.gitignore b/bskyweb/.gitignore index 1d945e1dab..58c1ce5d51 100644 --- a/bskyweb/.gitignore +++ b/bskyweb/.gitignore @@ -3,6 +3,7 @@ test-coverage.out # Don't check in the binary. /bskyweb +/embedr # Don't accidentally commit JS-generated code static/js/*.js diff --git a/bskyweb/Makefile b/bskyweb/Makefile index 6f979fa849..bb2da525fe 100644 --- a/bskyweb/Makefile +++ b/bskyweb/Makefile @@ -14,6 +14,7 @@ help: ## Print info about all commands .PHONY: build build: ## Build all executables go build ./cmd/bskyweb + go build ./cmd/embedr .PHONY: test test: ## Run all tests @@ -43,3 +44,7 @@ check: ## Compile everything, checking syntax (does not output binaries) .PHONY: run-dev-bskyweb run-dev-bskyweb: .env ## Runs 'bskyweb' for local dev GOLOG_LOG_LEVEL=info go run ./cmd/bskyweb serve + +.PHONY: run-dev-embedr +run-dev-embedr: .env ## Runs 'embedr' for local dev + GOLOG_LOG_LEVEL=info go run ./cmd/embedr serve diff --git a/bskyweb/README.embed.md b/bskyweb/README.embed.md new file mode 100644 index 0000000000..8f19ef0226 --- /dev/null +++ b/bskyweb/README.embed.md @@ -0,0 +1,52 @@ + +## oEmbed + + + +* URL scheme: `https://bsky.app/profile/*/post/*` +* API endpoint: `https://embed.bsky.app/oembed` + +Request params: + +- `url` (required): support both AT-URI and bsky.app URL +- `maxwidth` (optional): [220..550], 325 is default +- `maxheight` (not supported!) +- `format` (optional): only `json` supported + +Response format: + +- `type` (required): "rich" +- `version` (required): "1.0" +- `author_name` (optional): display name +- `author_url` (optional): profile URL +- `provider_name` (optional): "Bluesky Social" +- `provider_url` (optional): "https://bsky.app" +- `cache_age` (optional, integer seconds): 86400 (24 hours) (?) +- `width` (required): ? +- `height` (required): ? + +Not used: + +- title (optional): A text title, describing the resource. +- thumbnail_url (optional): A URL to a thumbnail image representing the resource. The thumbnail must respect any maxwidth and maxheight parameters. If this parameter is present, thumbnail_width and thumbnail_height must also be present. +- thumbnail_width (optional): The width of the optional thumbnail. If this parameter is present, thumbnail_url and thumbnail_height must also be present. +- thumbnail_height (optional): The height of the optional thumbnail. If this parameter is present, thumbnail_url and thumbnail_width must also be present. + +Only `json` is supported; `xml` is a 501. + +``` + +``` + + +## iframe URL + +`https://embed.bsky.app/embed//app.bsky.feed.post/` +`https://embed.bsky.app/static/embed.js` + +``` +
+

{{ post-text }}

+ — US Department of the Interior (@Interior) May 5, 2014 +
+``` diff --git a/bskyweb/cmd/embedr/server.go b/bskyweb/cmd/embedr/server.go index c47aed9675..709cd009fd 100644 --- a/bskyweb/cmd/embedr/server.go +++ b/bskyweb/cmd/embedr/server.go @@ -85,7 +85,7 @@ func serve(cctx *cli.Context) error { e.HideBanner = true tmpl := &Template{ - templates: template.Must(template.ParseGlob("embed-templates/*.html")), + templates: template.Must(template.ParseFS(bskyweb.EmbedrTemplateFS, "embedr-templates/*.html")), } e.Renderer = tmpl e.HTTPErrorHandler = server.errorHandler @@ -104,7 +104,7 @@ func serve(cctx *cli.Context) error { e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ // Don't log requests for static content. Skipper: func(c echo.Context) bool { - return strings.HasPrefix(c.Request().URL.Path, "/embed-static") + return strings.HasPrefix(c.Request().URL.Path, "/embedr-static") }, })) e.Use(middleware.RateLimiterWithConfig(middleware.RateLimiterConfig{ @@ -174,7 +174,7 @@ func serve(cctx *cli.Context) error { e.GET("/", server.WebHome) e.GET("/embed.js", echo.WrapHandler(staticHandler)) e.GET("/oembed", server.WebOEmbed) - e.GET("/embed/did/app.bsky.feed.post/rkey", server.WebPostEmbed) + e.GET("/embed/:did/app.bsky.feed.post/:rkey", server.WebPostEmbed) // Start the server. log.Infof("starting server address=%s", httpAddress) @@ -253,18 +253,16 @@ func (srv *Server) WebPostEmbed(c echo.Context) error { if err != nil { return c.Render(http.StatusOK, "postEmbed.html", data) } - handleOrDIDParam := c.Param("handleOrDID") - handleOrDID, err := syntax.ParseAtIdentifier(handleOrDIDParam) + didParam := c.Param("did") + did, err := syntax.ParseDID(didParam) if err != nil { return c.Render(http.StatusOK, "postEmbed.html", data) } - identifier := handleOrDID.Normalize().String() - // requires two fetches: first fetch profile (!) - pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, identifier) + pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, did.String()) if err != nil { - log.Warnf("failed to fetch profile for: %s\t%v", identifier, err) + log.Warnf("failed to fetch profile for: %s\t%v", did, err) return c.Render(http.StatusOK, "postEmbed.html", data) } unauthedViewingOkay := true @@ -277,8 +275,7 @@ func (srv *Server) WebPostEmbed(c echo.Context) error { if !unauthedViewingOkay { return c.Render(http.StatusOK, "postEmbed.html", data) } - did := pv.Did - data["did"] = did + data["did"] = did.String() // then fetch the post thread (with extra context) uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", did, rkey) diff --git a/bskyweb/embed-static/.well-known/security.txt b/bskyweb/embedr-static/.well-known/security.txt similarity index 100% rename from bskyweb/embed-static/.well-known/security.txt rename to bskyweb/embedr-static/.well-known/security.txt diff --git a/bskyweb/embed-static/embed.js b/bskyweb/embedr-static/embed.js similarity index 100% rename from bskyweb/embed-static/embed.js rename to bskyweb/embedr-static/embed.js diff --git a/bskyweb/embed-static/favicon-16x16.png b/bskyweb/embedr-static/favicon-16x16.png similarity index 100% rename from bskyweb/embed-static/favicon-16x16.png rename to bskyweb/embedr-static/favicon-16x16.png diff --git a/bskyweb/embed-static/favicon-32x32.png b/bskyweb/embedr-static/favicon-32x32.png similarity index 100% rename from bskyweb/embed-static/favicon-32x32.png rename to bskyweb/embedr-static/favicon-32x32.png diff --git a/bskyweb/embed-static/favicon.png b/bskyweb/embedr-static/favicon.png similarity index 100% rename from bskyweb/embed-static/favicon.png rename to bskyweb/embedr-static/favicon.png diff --git a/bskyweb/embed-static/ips-v4 b/bskyweb/embedr-static/ips-v4 similarity index 100% rename from bskyweb/embed-static/ips-v4 rename to bskyweb/embedr-static/ips-v4 diff --git a/bskyweb/embed-static/ips-v6 b/bskyweb/embedr-static/ips-v6 similarity index 100% rename from bskyweb/embed-static/ips-v6 rename to bskyweb/embedr-static/ips-v6 diff --git a/bskyweb/embed-static/robots.txt b/bskyweb/embedr-static/robots.txt similarity index 100% rename from bskyweb/embed-static/robots.txt rename to bskyweb/embedr-static/robots.txt diff --git a/bskyweb/embed-templates/error.html b/bskyweb/embedr-templates/error.html similarity index 100% rename from bskyweb/embed-templates/error.html rename to bskyweb/embedr-templates/error.html diff --git a/bskyweb/embed-templates/home.html b/bskyweb/embedr-templates/home.html similarity index 100% rename from bskyweb/embed-templates/home.html rename to bskyweb/embedr-templates/home.html diff --git a/bskyweb/embed-templates/oembed.html b/bskyweb/embedr-templates/oembed.html similarity index 100% rename from bskyweb/embed-templates/oembed.html rename to bskyweb/embedr-templates/oembed.html diff --git a/bskyweb/embed-templates/postEmbed.html b/bskyweb/embedr-templates/postEmbed.html similarity index 100% rename from bskyweb/embed-templates/postEmbed.html rename to bskyweb/embedr-templates/postEmbed.html diff --git a/bskyweb/templates.go b/bskyweb/templates.go index ce3fa29af7..a66965aba4 100644 --- a/bskyweb/templates.go +++ b/bskyweb/templates.go @@ -4,3 +4,6 @@ import "embed" //go:embed templates/* var TemplateFS embed.FS + +//go:embed embedr-templates/* +var EmbedrTemplateFS embed.FS