about summary refs log tree commit diff
path: root/bskyweb
diff options
context:
space:
mode:
Diffstat (limited to 'bskyweb')
-rw-r--r--bskyweb/cmd/bskyweb/rss.go57
-rw-r--r--bskyweb/cmd/bskyweb/server.go9
-rw-r--r--bskyweb/static/apple-touch-icon.pngbin14742 -> 7783 bytes
-rw-r--r--bskyweb/static/favicon-16x16.pngbin316 -> 1731 bytes
-rw-r--r--bskyweb/static/favicon-32x32.pngbin769 -> 2240 bytes
-rw-r--r--bskyweb/static/favicon.icobin15406 -> 0 bytes
-rw-r--r--bskyweb/static/favicon.pngbin6405 -> 1412 bytes
-rw-r--r--bskyweb/static/social-card-default.pngbin23527 -> 16904 bytes
-rw-r--r--bskyweb/templates/post.html4
-rw-r--r--bskyweb/templates/profile.html4
10 files changed, 60 insertions, 14 deletions
diff --git a/bskyweb/cmd/bskyweb/rss.go b/bskyweb/cmd/bskyweb/rss.go
index f7caf8fe7..64e67fd22 100644
--- a/bskyweb/cmd/bskyweb/rss.go
+++ b/bskyweb/cmd/bskyweb/rss.go
@@ -1,8 +1,11 @@
 package main
 
 import (
+	"encoding/xml"
 	"fmt"
 	"net/http"
+	"strings"
+	"time"
 
 	appbsky "github.com/bluesky-social/indigo/api/bsky"
 	"github.com/bluesky-social/indigo/atproto/syntax"
@@ -10,6 +13,12 @@ import (
 	"github.com/labstack/echo/v4"
 )
 
+type ItemGUID struct {
+	XMLName xml.Name `xml:"guid"`
+	Value   string   `xml:",chardata"`
+	IsPerma bool     `xml:"isPermaLink,attr"`
+}
+
 // We don't actually populate the title for "posts".
 // Some background: https://book.micro.blog/rss-for-microblogs/
 type Item struct {
@@ -17,8 +26,7 @@ type Item struct {
 	Link        string `xml:"link,omitempty"`
 	Description string `xml:"description,omitempty"`
 	PubDate     string `xml:"pubDate,omitempty"`
-	Author      string `xml:"author,omitempty"`
-	GUID        string `xml:"guid,omitempty"`
+	GUID        ItemGUID
 }
 
 type rss struct {
@@ -32,11 +40,33 @@ type rss struct {
 
 func (srv *Server) WebProfileRSS(c echo.Context) error {
 	ctx := c.Request().Context()
+	req := c.Request()
+
+	identParam := c.Param("ident")
+
+	// if not a DID, try parsing as a handle and doing a redirect
+	if !strings.HasPrefix(identParam, "did:") {
+		handle, err := syntax.ParseHandle(identParam)
+		if err != nil {
+			return echo.NewHTTPError(400, fmt.Sprintf("not a valid handle: %s", identParam))
+		}
 
-	didParam := c.Param("did")
-	did, err := syntax.ParseDID(didParam)
+		// check that public view is Ok, and resolve DID
+		pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle.String())
+		if err != nil {
+			return echo.NewHTTPError(404, fmt.Sprintf("account not found: %s", handle))
+		}
+		for _, label := range pv.Labels {
+			if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
+				return echo.NewHTTPError(403, fmt.Sprintf("account does not allow public views: %s", handle))
+			}
+		}
+		return c.Redirect(http.StatusFound, fmt.Sprintf("/profile/%s/rss", pv.Did))
+	}
+
+	did, err := syntax.ParseDID(identParam)
 	if err != nil {
-		return echo.NewHTTPError(400, fmt.Sprintf("not a valid DID: %s", didParam))
+		return echo.NewHTTPError(400, fmt.Sprintf("not a valid DID: %s", identParam))
 	}
 
 	// check that public view is Ok
@@ -71,12 +101,19 @@ func (srv *Server) WebProfileRSS(c echo.Context) error {
 		if rec.Reply != nil {
 			continue
 		}
+		pubDate := ""
+		createdAt, err := syntax.ParseDatetimeLenient(rec.CreatedAt)
+		if nil == err {
+			pubDate = createdAt.Time().Format(time.RFC822Z)
+		}
 		posts = append(posts, Item{
-			Link:        fmt.Sprintf("https://bsky.app/profile/%s/post/%s", pv.Handle, aturi.RecordKey().String()),
+			Link:        fmt.Sprintf("https://%s/profile/%s/post/%s", req.Host, pv.Handle, aturi.RecordKey().String()),
 			Description: rec.Text,
-			PubDate:     rec.CreatedAt,
-			Author:      "@" + pv.Handle,
-			GUID:        aturi.String(),
+			PubDate:     pubDate,
+			GUID: ItemGUID{
+				Value:   aturi.String(),
+				IsPerma: false,
+			},
 		})
 	}
 
@@ -91,7 +128,7 @@ func (srv *Server) WebProfileRSS(c echo.Context) error {
 	feed := &rss{
 		Version:     "2.0",
 		Description: desc,
-		Link:        fmt.Sprintf("https://bsky.app/profile/%s", pv.Handle),
+		Link:        fmt.Sprintf("https://%s/profile/%s", req.Host, pv.Handle),
 		Title:       title,
 		Item:        posts,
 	}
diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go
index 5d9a481fe..7a3b8bf16 100644
--- a/bskyweb/cmd/bskyweb/server.go
+++ b/bskyweb/cmd/bskyweb/server.go
@@ -210,7 +210,7 @@ func serve(cctx *cli.Context) error {
 	e.GET("/profile/:handle/feed/:rkey/liked-by", server.WebGeneric)
 
 	// profile RSS feed (DID not handle)
-	e.GET("/profile/:did/rss", server.WebProfileRSS)
+	e.GET("/profile/:ident/rss", server.WebProfileRSS)
 
 	// post endpoints; only first populates info
 	e.GET("/profile/:handle/post/:rkey", server.WebPost)
@@ -336,7 +336,11 @@ func (srv *Server) WebPost(c echo.Context) error {
 	data["postView"] = postView
 	data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
 	if postView.Embed != nil && postView.Embed.EmbedImages_View != nil {
-		data["imgThumbUrl"] = postView.Embed.EmbedImages_View.Images[0].Thumb
+		var thumbUrls []string
+		for i := range postView.Embed.EmbedImages_View.Images {
+			thumbUrls = append(thumbUrls, postView.Embed.EmbedImages_View.Images[i].Thumb)
+		}
+		data["imgThumbUrls"] = thumbUrls
 	}
 	return c.Render(http.StatusOK, "post.html", data)
 }
@@ -370,6 +374,7 @@ func (srv *Server) WebProfile(c echo.Context) error {
 	req := c.Request()
 	data["profileView"] = pv
 	data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
+	data["requestHost"] = req.Host
 	return c.Render(http.StatusOK, "profile.html", data)
 }
 
diff --git a/bskyweb/static/apple-touch-icon.png b/bskyweb/static/apple-touch-icon.png
index 5ebb6787c..09393a741 100644
--- a/bskyweb/static/apple-touch-icon.png
+++ b/bskyweb/static/apple-touch-icon.png
Binary files differdiff --git a/bskyweb/static/favicon-16x16.png b/bskyweb/static/favicon-16x16.png
index 4267562b8..ea256e056 100644
--- a/bskyweb/static/favicon-16x16.png
+++ b/bskyweb/static/favicon-16x16.png
Binary files differdiff --git a/bskyweb/static/favicon-32x32.png b/bskyweb/static/favicon-32x32.png
index 869f6df5f..a5ca7eed1 100644
--- a/bskyweb/static/favicon-32x32.png
+++ b/bskyweb/static/favicon-32x32.png
Binary files differdiff --git a/bskyweb/static/favicon.ico b/bskyweb/static/favicon.ico
deleted file mode 100644
index b4290a797..000000000
--- a/bskyweb/static/favicon.ico
+++ /dev/null
Binary files differdiff --git a/bskyweb/static/favicon.png b/bskyweb/static/favicon.png
index 61cf7c943..ddf55f4c8 100644
--- a/bskyweb/static/favicon.png
+++ b/bskyweb/static/favicon.png
Binary files differdiff --git a/bskyweb/static/social-card-default.png b/bskyweb/static/social-card-default.png
index 3bb93c799..00a85b8cf 100644
--- a/bskyweb/static/social-card-default.png
+++ b/bskyweb/static/social-card-default.png
Binary files differdiff --git a/bskyweb/templates/post.html b/bskyweb/templates/post.html
index 55a0679fb..307f80bbb 100644
--- a/bskyweb/templates/post.html
+++ b/bskyweb/templates/post.html
@@ -25,8 +25,10 @@
   <meta name="description" content="{{ postView.Record.Val.Text }}">
   <meta property="og:description" content="{{ postView.Record.Val.Text }}">
   {% endif -%}
-  {%- if imgThumbUrl %}
+  {%- if imgThumbUrls %}
+  {% for imgThumbUrl in imgThumbUrls %}
   <meta property="og:image" content="{{ imgThumbUrl }}">
+  {% endfor %}
   <meta name="twitter:card" content="summary_large_image">
   {%- elif postView.Author.Avatar %}
   {# Don't use avatar image in cards; usually looks bad #}
diff --git a/bskyweb/templates/profile.html b/bskyweb/templates/profile.html
index 71c100327..551dc15a6 100644
--- a/bskyweb/templates/profile.html
+++ b/bskyweb/templates/profile.html
@@ -34,7 +34,9 @@
   {% endif %}
   <meta name="twitter:label1" content="Account DID">
   <meta name="twitter:value1" content="{{ profileView.Did }}">
-  <link rel="alternate" type="application/rss+xml" href="/profile/{{ profileView.Did }}/rss">
+  {%- if requestHost %}
+  <link rel="alternate" type="application/rss+xml" href="https://{{ requestHost }}/profile/{{ profileView.Did }}/rss">
+  {% endif %}
 {% endif -%}
 {%- endblock %}