Skip to content

Commit

Permalink
remove feed_icons table, add icon_id to feeds table, store icon_url a…
Browse files Browse the repository at this point in the history
…nd check for changes
  • Loading branch information
rystaf committed Oct 20, 2023
1 parent 9e38b66 commit 77cc9e4
Show file tree
Hide file tree
Showing 28 changed files with 40 additions and 51 deletions.
13 changes: 10 additions & 3 deletions internal/database/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,9 +801,16 @@ var migrations = []func(tx *sql.Tx) error{
},
func(tx *sql.Tx) (err error) {
sql := `
ALTER TABLE public.feed_icons DROP CONSTRAINT feed_icons_pkey;
ALTER TABLE public.feed_icons ADD CONSTRAINT feed_icons_pkey PRIMARY KEY (feed_id);
ALTER TABLE feeds ADD COLUMN refresh_icon bool default 'f';
ALTER TABLE feeds ADD COLUMN icon_id int REFERENCES icons(id) ON DELETE SET NULL;
ALTER TABLE feeds ADD COLUMN icon_url text default '';
UPDATE feeds
SET icon_id=subquery.icon_id
FROM (
SELECT f.id, fi.icon_id
FROM feeds f
LEFT JOIN feed_icons fi ON fi.feed_id = f.id) AS subquery
WHERE feeds.id=subquery.id;
--DROP TABLE feed_icons;
`
_, err = tx.Exec(sql)
return err
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/de_DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Dieses Abonnement nicht aktualisieren",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Einträge in der globalen Ungelesen-Liste ausblenden",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/el_EL.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Μη ανανέωση αυτής της ροής",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Απόκρυψη καταχωρήσεων σε γενική λίστα μη αναγνωσμένων",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Do not refresh this feed",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Hide entries in global unread list",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/es_ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "No actualice este feed",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Ocultar artículos en la lista global de no leídos",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/fi_FI.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Älä päivitä tätä syötettä",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Piilota artikkelit lukemattomien listassa",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/fr_FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Ne pas actualiser ce flux",
"form.feed.label.no_media_player": "Pas de lecteur multimedia (audio/vidéo)",
"form.feed.label.hide_globally": "Masquer les entrées dans la liste globale non lue",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "Général",
"form.feed.fieldset.rules": "Règles",
"form.feed.fieldset.network_settings": "Paramètres réseau",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/hi_IN.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "इस फ़ीड को रीफ़्रेश न करें",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "वैश्विक अपठित सूची में प्रविष्टियां छिपाएं",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/id_ID.json
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,6 @@
"form.feed.label.disabled": "Jangan perbarui umpan ini",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Sembunyikan entri di daftar belum dibaca global",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/it_IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Non aggiornare questo feed",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Nascondere le voci nella lista globale dei non letti",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/ja_JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "このフィードを更新しない",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "未読一覧に記事を表示しない",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/nl_NL.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Vernieuw deze feed niet",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Verberg items in de globale ongelezen lijst",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/pl_PL.json
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@
"form.feed.label.disabled": "Nie odświeżaj tego kanału",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Ukryj wpisy na globalnej liście nieprzeczytanych",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/pt_BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.fetch_via_proxy": "Buscar via proxy",
"form.feed.label.hide_globally": "Ocultar entradas na lista global não lida",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/ru_RU.json
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,6 @@
"form.feed.label.disabled": "Не обновлять эту подписку",
"form.feed.label.no_media_player": "Отключить медиаплеер (аудио и видео)",
"form.feed.label.hide_globally": "Скрыть записи в глобальном списке непрочитанных",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/tr_TR.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "Bu beslemeyi yenileme",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Genel okunmamış listesindeki girişleri gizle",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/uk_UA.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,6 @@
"form.feed.label.disabled": "Не оновлювати цю стрічку",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "Приховати записи в глобальному списку непрочитаного",
"form.feed.label.refresh_icon": "Refresh icon",
"form.category.label.title": "Назва",
"form.category.hide_globally": "Приховати записи в глобальному списку непрочитаного",
"form.feed.fieldset.general": "General",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,6 @@
"form.feed.label.disabled": "请勿刷新此源",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "隐藏全局未读列表中的文章",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/locale/translations/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@
"form.feed.label.disabled": "請勿重新整理此Feed",
"form.feed.label.no_media_player": "No media player (audio/video)",
"form.feed.label.hide_globally": "隱藏全域性未讀列表中的文章",
"form.feed.label.refresh_icon": "Refresh icon",
"form.feed.fieldset.general": "General",
"form.feed.fieldset.rules": "Rules",
"form.feed.fieldset.network_settings": "Network Settings",
Expand Down
1 change: 0 additions & 1 deletion internal/model/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ type Feed struct {
UnreadCount int `json:"-"`
ReadCount int `json:"-"`
AppriseServiceURLs string `json:"apprise_service_urls"`
RefreshIcon bool `json:"refresh_icon"`
}

type FeedCounters struct {
Expand Down
18 changes: 15 additions & 3 deletions internal/reader/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,12 +212,13 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool
// because some websites don't return the same headers when replying with a 304.
originalFeed.WithClientResponse(response)

if !store.HasIcon(originalFeed.ID) || originalFeed.RefreshIcon || forceRefresh {
if !store.HasIcon(originalFeed.ID) || forceRefresh || (updatedFeed.IconURL != originalFeed.IconURL) {
originalFeed.IconURL = updatedFeed.IconURL
checkFeedIcon(
store,
originalFeed.ID,
originalFeed.SiteURL,
updatedFeed.IconURL,
originalFeed.IconURL,
originalFeed.UserAgent,
originalFeed.FetchViaProxy,
originalFeed.AllowSelfSignedCertificates,
Expand All @@ -228,6 +229,17 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool
slog.Int64("user_id", userID),
slog.Int64("feed_id", feedID),
)
if forceRefresh {
checkFeedIcon(
store,
originalFeed.ID,
originalFeed.SiteURL,
originalFeed.IconURL,
originalFeed.UserAgent,
originalFeed.FetchViaProxy,
originalFeed.AllowSelfSignedCertificates,
)
}
}

originalFeed.ResetErrorCounter()
Expand Down Expand Up @@ -257,7 +269,7 @@ func checkFeedIcon(store *storage.Storage, feedID int64, websiteURL, feedIconURL
slog.String("feed_icon_url", feedIconURL),
)
} else if !store.HasIconHash(feedID, icon.Hash) {
if err := store.CreateFeedIcon(feedID, icon); err != nil {
if err := store.CreateFeedIcon(feedID, icon, feedIconURL); err != nil {
slog.Error("Unable to store feed icon",
slog.Int64("feed_id", feedID),
slog.String("website_url", websiteURL),
Expand Down
4 changes: 1 addition & 3 deletions internal/storage/entry_query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,16 +291,14 @@ func (e *EntryQueryBuilder) GetEntries() (model.Entries, error) {
f.cookie,
f.hide_globally,
f.no_media_player,
fi.icon_id,
f.icon_id,
u.timezone
FROM
entries e
LEFT JOIN
feeds f ON f.id=e.feed_id
LEFT JOIN
categories c ON c.id=f.category_id
LEFT JOIN
feed_icons fi ON fi.feed_id=f.id
LEFT JOIN
users u ON u.id=e.user_id
WHERE %s %s
Expand Down
8 changes: 4 additions & 4 deletions internal/storage/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
url_rewrite_rules,
no_media_player,
apprise_service_urls,
refresh_icon
icon_url
)
VALUES
($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)
Expand Down Expand Up @@ -274,7 +274,7 @@ func (s *Storage) CreateFeed(feed *model.Feed) error {
feed.UrlRewriteRules,
feed.NoMediaPlayer,
feed.AppriseServiceURLs,
feed.RefreshIcon,
feed.IconURL,
).Scan(&feed.ID)
if err != nil {
return fmt.Errorf(`store: unable to create feed %q: %v`, feed.FeedURL, err)
Expand Down Expand Up @@ -347,7 +347,7 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
url_rewrite_rules=$25,
no_media_player=$26,
apprise_service_urls=$27,
refresh_icon=$28
icon_url=$28
WHERE
id=$29 AND user_id=$30
`
Expand Down Expand Up @@ -379,7 +379,7 @@ func (s *Storage) UpdateFeed(feed *model.Feed) (err error) {
feed.UrlRewriteRules,
feed.NoMediaPlayer,
feed.AppriseServiceURLs,
feed.RefreshIcon,
feed.IconURL,
feed.ID,
feed.UserID,
)
Expand Down
8 changes: 3 additions & 5 deletions internal/storage/feed_query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,14 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
f.category_id,
c.title as category_title,
c.hide_globally as category_hidden,
fi.icon_id,
f.icon_id,
u.timezone,
f.apprise_service_urls,
f.refresh_icon
f.icon_url
FROM
feeds f
LEFT JOIN
categories c ON c.id=f.category_id
LEFT JOIN
feed_icons fi ON fi.feed_id=f.id
LEFT JOIN
users u ON u.id=f.user_id
WHERE %s
Expand Down Expand Up @@ -231,7 +229,7 @@ func (f *FeedQueryBuilder) GetFeeds() (model.Feeds, error) {
&iconID,
&tz,
&feed.AppriseServiceURLs,
&feed.RefreshIcon,
&feed.IconURL,
)

if err != nil {
Expand Down
16 changes: 7 additions & 9 deletions internal/storage/icon.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ import (
// HasIcon checks if the given feed has an icon.
func (s *Storage) HasIcon(feedID int64) bool {
var result bool
query := `SELECT true FROM feed_icons WHERE feed_id=$1`
query := `SELECT true FROM feeds WHERE id=$1 AND icon_id is not null`
s.db.QueryRow(query, feedID).Scan(&result)
return result
}

// HasIconHash checks if given feed has icon hash
func (s *Storage) HasIconHash(feedID int64, iconHash string) bool {
var result bool
query := `SELECT true FROM feed_icons
LEFT JOIN icons ON feed_icons.icon_id=icons.id
query := `SELECT true FROM feeds
LEFT JOIN icons ON icon_id=icons.id
WHERE feed_id=$1 AND icons.hash=$2`
s.db.QueryRow(query, feedID).Scan(&result)
return result
Expand Down Expand Up @@ -52,8 +52,7 @@ func (s *Storage) IconByFeedID(userID, feedID int64) (*model.Icon, error) {
icons.mime_type,
icons.content
FROM icons
LEFT JOIN feed_icons ON feed_icons.icon_id=icons.id
LEFT JOIN feeds ON feeds.id=feed_icons.feed_id
LEFT JOIN feeds ON icon_id=icons.id
WHERE
feeds.user_id=$1 AND feeds.id=$2
LIMIT 1
Expand Down Expand Up @@ -104,7 +103,7 @@ func (s *Storage) CreateIcon(icon *model.Icon) error {
}

// CreateFeedIcon creates an icon and associate the icon to the given feed.
func (s *Storage) CreateFeedIcon(feedID int64, icon *model.Icon) error {
func (s *Storage) CreateFeedIcon(feedID int64, icon *model.Icon, feedIconURL string) error {
err := s.IconByHash(icon)
if err != nil {
return err
Expand All @@ -117,7 +116,7 @@ func (s *Storage) CreateFeedIcon(feedID int64, icon *model.Icon) error {
}
}

_, err = s.db.Exec(`INSERT INTO feed_icons (feed_id, icon_id) VALUES ($1, $2) ON CONFLICT (feed_id) DO UPDATE SET icon_id = $2`, feedID, icon.ID)
_, err = s.db.Exec(`UPDATE feeds SET icon_id=$1, icon_url=$2 WHERE id=$3`, icon.ID, feedIconURL, feedID)
if err != nil {
return fmt.Errorf(`store: unable to create feed icon: %v`, err)
}
Expand All @@ -134,8 +133,7 @@ func (s *Storage) Icons(userID int64) (model.Icons, error) {
icons.mime_type,
icons.content
FROM icons
LEFT JOIN feed_icons ON feed_icons.icon_id=icons.id
LEFT JOIN feeds ON feeds.id=feed_icons.feed_id
LEFT JOIN feeds ON icon_id=icons.id
WHERE
feeds.user_id=$1
`
Expand Down
1 change: 0 additions & 1 deletion internal/template/templates/views/edit_feed.html
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ <h3>{{ t "page.edit_feed.last_parsing_error" }}</h3>
<label><input type="checkbox" name="crawler" value="1" {{ if .form.Crawler }}checked{{ end }}> {{ t "form.feed.label.crawler" }}</label>
<label><input type="checkbox" name="ignore_http_cache" value="1" {{ if .form.IgnoreHTTPCache }}checked{{ end }}> {{ t "form.feed.label.ignore_http_cache" }}</label>
<label><input type="checkbox" name="allow_self_signed_certificates" value="1" {{ if .form.AllowSelfSignedCertificates }}checked{{ end }}> {{ t "form.feed.label.allow_self_signed_certificates" }}</label>
<label><input type="checkbox" name="refresh_icon" value="1" {{ if .form.RefreshIcon }}checked{{ end }}> {{ t "form.feed.label.refresh_icon" }}</label>
{{ if .hasProxyConfigured }}
<label><input type="checkbox" name="fetch_via_proxy" value="1" {{ if .form.FetchViaProxy }}checked{{ end }}> {{ t "form.feed.label.fetch_via_proxy" }}</label>
{{ end }}
Expand Down
1 change: 0 additions & 1 deletion internal/ui/feed_edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ func (h *handler) showEditFeedPage(w http.ResponseWriter, r *http.Request) {
HideGlobally: feed.HideGlobally,
CategoryHidden: feed.Category.HideGlobally,
AppriseServiceURLs: feed.AppriseServiceURLs,
RefreshIcon: feed.RefreshIcon,
}

sess := session.New(h.store, request.SessionID(r))
Expand Down
3 changes: 0 additions & 3 deletions internal/ui/form/feed.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ type FeedForm struct {
HideGlobally bool
CategoryHidden bool // Category has "hide_globally"
AppriseServiceURLs string
RefreshIcon bool
}

// Merge updates the fields of the given feed.
Expand Down Expand Up @@ -62,7 +61,6 @@ func (f FeedForm) Merge(feed *model.Feed) *model.Feed {
feed.NoMediaPlayer = f.NoMediaPlayer
feed.HideGlobally = f.HideGlobally
feed.AppriseServiceURLs = f.AppriseServiceURLs
feed.RefreshIcon = f.RefreshIcon
return feed
}

Expand Down Expand Up @@ -94,6 +92,5 @@ func NewFeedForm(r *http.Request) *FeedForm {
NoMediaPlayer: r.FormValue("no_media_player") == "1",
HideGlobally: r.FormValue("hide_globally") == "1",
AppriseServiceURLs: r.FormValue("apprise_service_urls"),
RefreshIcon: r.FormValue("refresh_icon") == "1",
}
}

0 comments on commit 77cc9e4

Please sign in to comment.