Local mode, Makefile, image fixes, Pete avatar
- Add -local flag: web/RSS-only mode that skips Matrix login and posting, so the web UI can be exercised against live feeds without credentials - Add Makefile (build/local/seed/test/clean) that handles Tailwind + go build in one shot - Fix Guardian thumbnails: NormalizeImageURL was rewriting width=1200 onto signed i.guim.co.uk URLs, invalidating the s= signature and returning 401. Leave signed URLs alone and pick the widest media:content variant up front instead - Use pete.avif as the header logo, favicon, and footer mark; drop the unused leaf.svg
This commit is contained in:
@@ -6,10 +6,12 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mmcdole/gofeed"
|
||||
ext "github.com/mmcdole/gofeed/extensions"
|
||||
)
|
||||
|
||||
const userAgent = "Pete/1.0 (newsbot; +https://github.com/reala-misaki/pete)"
|
||||
@@ -88,21 +90,19 @@ func extractLede(desc string) string {
|
||||
// scraped from content:encoded / description (catches feeds like Ars that
|
||||
// embed the lead image in the article body but not as a media:* element).
|
||||
func extractImageURL(item *gofeed.Item) string {
|
||||
// Check media content (common in RSS 2.0 with media namespace)
|
||||
// Check media content (common in RSS 2.0 with media namespace).
|
||||
// When multiple media:content variants are advertised (Guardian RSS lists
|
||||
// 140/460/700/1200…) we want the widest signed URL we can find.
|
||||
if item.Extensions != nil {
|
||||
if media, ok := item.Extensions["media"]; ok {
|
||||
if contents, ok := media["content"]; ok {
|
||||
for _, c := range contents {
|
||||
if url := c.Attrs["url"]; url != "" {
|
||||
return url
|
||||
}
|
||||
if url := widestURL(contents); url != "" {
|
||||
return url
|
||||
}
|
||||
}
|
||||
if thumbs, ok := media["thumbnail"]; ok {
|
||||
for _, t := range thumbs {
|
||||
if url := t.Attrs["url"]; url != "" {
|
||||
return url
|
||||
}
|
||||
if url := widestURL(thumbs); url != "" {
|
||||
return url
|
||||
}
|
||||
}
|
||||
// media:group wraps nested media:content / media:thumbnail in some feeds
|
||||
@@ -143,6 +143,25 @@ func extractImageURL(item *gofeed.Item) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// widestURL picks the entry with the largest declared width attribute, falling
|
||||
// back to the first URL if none have a parsable width.
|
||||
func widestURL(entries []ext.Extension) string {
|
||||
best := ""
|
||||
bestW := -1
|
||||
for _, e := range entries {
|
||||
url := e.Attrs["url"]
|
||||
if url == "" {
|
||||
continue
|
||||
}
|
||||
w, _ := strconv.Atoi(e.Attrs["width"])
|
||||
if w > bestW {
|
||||
best = url
|
||||
bestW = w
|
||||
}
|
||||
}
|
||||
return best
|
||||
}
|
||||
|
||||
func firstImgSrc(htmlBody string) string {
|
||||
if htmlBody == "" {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user