Add favicon as profile picture for feed accounts

Fetches the site's favicon and uses it as the avatar when creating
or updating feed account profiles. Tries common favicon locations
(/favicon.ico, /favicon.png, /apple-touch-icon.png) then falls back
to Google's favicon service.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
primal
2026-01-28 21:05:50 -05:00
parent 9a43b69b4b
commit 4e4e8c939a
2 changed files with 63 additions and 5 deletions
+22 -5
View File
@@ -227,7 +227,15 @@ func (c *Crawler) StartPublishLoop() {
if len(description) > 256 {
description = description[:253] + "..."
}
if err := publisher.UpdateProfile(session, displayName, description, nil); err != nil {
// Fetch and upload favicon as avatar
var avatar *BlobRef
if feedInfo.SiteURL != "" {
faviconURL := publisher.FetchFavicon(feedInfo.SiteURL)
if faviconURL != "" {
avatar = publisher.fetchAndUploadImage(session, faviconURL)
}
}
if err := publisher.UpdateProfile(session, displayName, description, avatar); err != nil {
fmt.Printf("Publish: failed to set profile for %s: %v\n", account, err)
} else {
fmt.Printf("Publish: set profile for %s\n", account)
@@ -297,7 +305,7 @@ func (c *Crawler) getFeedInfo(feedURL string) *FeedInfo {
// RefreshAllProfiles updates profiles for all existing accounts with feed URLs
func (c *Crawler) RefreshAllProfiles(publisher *Publisher, feedPassword string) {
rows, err := c.db.Query(`
SELECT url, title, description, publish_account
SELECT url, title, description, site_url, publish_account
FROM feeds
WHERE publish_account IS NOT NULL AND publish_account <> ''
`)
@@ -309,8 +317,8 @@ func (c *Crawler) RefreshAllProfiles(publisher *Publisher, feedPassword string)
for rows.Next() {
var feedURL, account string
var title, description *string
if err := rows.Scan(&feedURL, &title, &description, &account); err != nil {
var title, description, siteURL *string
if err := rows.Scan(&feedURL, &title, &description, &siteURL, &account); err != nil {
continue
}
@@ -342,7 +350,16 @@ func (c *Crawler) RefreshAllProfiles(publisher *Publisher, feedPassword string)
desc = desc[:253] + "..."
}
if err := publisher.UpdateProfile(session, displayName, desc, nil); err != nil {
// Fetch and upload favicon as avatar
var avatar *BlobRef
if siteURL != nil && *siteURL != "" {
faviconURL := publisher.FetchFavicon(*siteURL)
if faviconURL != "" {
avatar = publisher.fetchAndUploadImage(session, faviconURL)
}
}
if err := publisher.UpdateProfile(session, displayName, desc, avatar); err != nil {
fmt.Printf("RefreshProfiles: update failed for %s: %v\n", account, err)
} else {
fmt.Printf("RefreshProfiles: updated %s\n", account)