modified internal/atproto/lexicon_external.go +25 -1
| @@ -3,7 +3,10 @@ |
| 3 | 3 | // See lexicon_test.go for the test ensuring these stay in sync with lexicons/. |
| 4 | 4 | package atproto |
| 5 | 5 | |
| 6 | | -import "encoding/json" |
| 6 | +import ( |
| 7 | + "encoding/json" |
| 8 | + "strings" |
| 9 | +) |
| 7 | 10 | |
| 8 | 11 | type FollowRecord struct { |
| 9 | 12 | Subject string `json:"subject"` |
| @@ -144,3 +147,24 @@ type StandardDocumentRecord struct { |
| 144 | 147 | Links json.RawMessage `json:"links,omitempty"` |
| 145 | 148 | Tags []string `json:"tags,omitempty"` |
| 146 | 149 | } |
| 150 | + |
| 151 | +type StandardDocumentLink struct { |
| 152 | + Rel string `json:"rel"` |
| 153 | + URI string `json:"uri"` |
| 154 | +} |
| 155 | + |
| 156 | +func (doc *StandardDocumentRecord) RelatedLinkURL() string { |
| 157 | + if len(doc.Links) == 0 { |
| 158 | + return "" |
| 159 | + } |
| 160 | + var links []StandardDocumentLink |
| 161 | + if err := json.Unmarshal(doc.Links, &links); err != nil { |
| 162 | + return "" |
| 163 | + } |
| 164 | + for _, l := range links { |
| 165 | + if l.Rel == "related" && strings.HasPrefix(l.URI, "http") { |
| 166 | + return l.URI |
| 167 | + } |
| 168 | + } |
| 169 | + return "" |
| 170 | +} |
| @@ -3,7 +3,10 @@ |
| 3 | // See lexicon_test.go for the test ensuring these stay in sync with lexicons/. | 3 | // See lexicon_test.go for the test ensuring these stay in sync with lexicons/. |
| 4 | package atproto | 4 | package atproto |
| 5 | | 5 | |
| 6 | -import "encoding/json" | 6 | +import ( |
| | 7 | + "encoding/json" |
| | 8 | + "strings" |
| | 9 | +) |
| 7 | | 10 | |
| 8 | type FollowRecord struct { | 11 | type FollowRecord struct { |
| 9 | Subject string `json:"subject"` | 12 | Subject string `json:"subject"` |
| @@ -144,3 +147,24 @@ type StandardDocumentRecord struct { |
| 144 | Links json.RawMessage `json:"links,omitempty"` | 147 | Links json.RawMessage `json:"links,omitempty"` |
| 145 | Tags []string `json:"tags,omitempty"` | 148 | Tags []string `json:"tags,omitempty"` |
| 146 | } | 149 | } |
| | 150 | + |
| | 151 | +type StandardDocumentLink struct { |
| | 152 | + Rel string `json:"rel"` |
| | 153 | + URI string `json:"uri"` |
| | 154 | +} |
| | 155 | + |
| | 156 | +func (doc *StandardDocumentRecord) RelatedLinkURL() string { |
| | 157 | + if len(doc.Links) == 0 { |
| | 158 | + return "" |
| | 159 | + } |
| | 160 | + var links []StandardDocumentLink |
| | 161 | + if err := json.Unmarshal(doc.Links, &links); err != nil { |
| | 162 | + return "" |
| | 163 | + } |
| | 164 | + for _, l := range links { |
| | 165 | + if l.Rel == "related" && strings.HasPrefix(l.URI, "http") { |
| | 166 | + return l.URI |
| | 167 | + } |
| | 168 | + } |
| | 169 | + return "" |
| | 170 | +} |
modified internal/atproto/standard_site_fetcher.go +6 -1
| @@ -91,11 +91,16 @@ func (f *StandardSiteFetcher) fetchDocuments(ctx context.Context, client *Client |
| 91 | 91 | published := parseRFC3339(doc.PublishedAt) |
| 92 | 92 | updated := parseRFC3339(doc.UpdatedAt) |
| 93 | 93 | |
| 94 | + articleURL := publicationURL + doc.Path |
| 95 | + if related := doc.RelatedLinkURL(); related != "" && articleURL == "" { |
| 96 | + articleURL = related |
| 97 | + } |
| 98 | + |
| 94 | 99 | articles = append(articles, feed.Article{ |
| 95 | 100 | FeedURL: publicationURI, |
| 96 | 101 | GUID: r.URI, |
| 97 | 102 | Title: doc.Title, |
| 98 | | - URL: publicationURL + doc.Path, |
| 103 | + URL: articleURL, |
| 99 | 104 | Author: firstContributor(doc.Contributors), |
| 100 | 105 | Content: doc.TextContent, |
| 101 | 106 | Summary: doc.Description, |
| @@ -91,11 +91,16 @@ func (f *StandardSiteFetcher) fetchDocuments(ctx context.Context, client *Client |
| 91 | published := parseRFC3339(doc.PublishedAt) | 91 | published := parseRFC3339(doc.PublishedAt) |
| 92 | updated := parseRFC3339(doc.UpdatedAt) | 92 | updated := parseRFC3339(doc.UpdatedAt) |
| 93 | | 93 | |
| | 94 | + articleURL := publicationURL + doc.Path |
| | 95 | + if related := doc.RelatedLinkURL(); related != "" && articleURL == "" { |
| | 96 | + articleURL = related |
| | 97 | + } |
| | 98 | + |
| 94 | articles = append(articles, feed.Article{ | 99 | articles = append(articles, feed.Article{ |
| 95 | FeedURL: publicationURI, | 100 | FeedURL: publicationURI, |
| 96 | GUID: r.URI, | 101 | GUID: r.URI, |
| 97 | Title: doc.Title, | 102 | Title: doc.Title, |
| 98 | - URL: publicationURL + doc.Path, | 103 | + URL: articleURL, |
| 99 | Author: firstContributor(doc.Contributors), | 104 | Author: firstContributor(doc.Contributors), |
| 100 | Content: doc.TextContent, | 105 | Content: doc.TextContent, |
| 101 | Summary: doc.Description, | 106 | Summary: doc.Description, |
modified internal/atproto/stream_handler.go +3 -0
| @@ -311,6 +311,9 @@ func (h *StreamDBHandler) handleStandardDocument(ctx context.Context, event *Eve |
| 311 | 311 | if f, err := h.articles.GetFeed(ctx, publicationURI); err == nil && f.SiteURL.Valid { |
| 312 | 312 | articleURL = f.SiteURL.String + doc.Path |
| 313 | 313 | } |
| 314 | + if related := doc.RelatedLinkURL(); related != "" && articleURL == "" { |
| 315 | + articleURL = related |
| 316 | + } |
| 314 | 317 | |
| 315 | 318 | articles := []feed.Article{{ |
| 316 | 319 | FeedURL: publicationURI, |
| @@ -311,6 +311,9 @@ func (h *StreamDBHandler) handleStandardDocument(ctx context.Context, event *Eve |
| 311 | if f, err := h.articles.GetFeed(ctx, publicationURI); err == nil && f.SiteURL.Valid { | 311 | if f, err := h.articles.GetFeed(ctx, publicationURI); err == nil && f.SiteURL.Valid { |
| 312 | articleURL = f.SiteURL.String + doc.Path | 312 | articleURL = f.SiteURL.String + doc.Path |
| 313 | } | 313 | } |
| | 314 | + if related := doc.RelatedLinkURL(); related != "" && articleURL == "" { |
| | 315 | + articleURL = related |
| | 316 | + } |
| 314 | | 317 | |
| 315 | articles := []feed.Article{{ | 318 | articles := []feed.Article{{ |
| 316 | FeedURL: publicationURI, | 319 | FeedURL: publicationURI, |