diff --git a/api/feed.go b/api/feed.go index 339557c5..12cbf919 100644 --- a/api/feed.go +++ b/api/feed.go @@ -47,7 +47,7 @@ func (h *handler) refreshFeed(w http.ResponseWriter, r *http.Request) { return } - err := feedHandler.RefreshFeed(h.store, userID, feedID) + err := feedHandler.RefreshFeed(h.store, userID, feedID, false) if err != nil { json.ServerError(w, r, err) return diff --git a/cli/refresh_feeds.go b/cli/refresh_feeds.go index 355c8287..63ef9efb 100644 --- a/cli/refresh_feeds.go +++ b/cli/refresh_feeds.go @@ -34,7 +34,7 @@ func refreshFeeds(store *storage.Storage) { defer wg.Done() for job := range jobQueue { logger.Info("[Cronjob] Refreshing feed #%d for user #%d in worker #%d", job.FeedID, job.UserID, workerID) - if err := feedHandler.RefreshFeed(store, job.UserID, job.FeedID); err != nil { + if err := feedHandler.RefreshFeed(store, job.UserID, job.FeedID, false); err != nil { logger.Error("[Cronjob] Refreshing the feed #%d returned this error: %v", job.FeedID, err) } } diff --git a/http/request/params.go b/http/request/params.go index dc7512b6..cd0eff38 100644 --- a/http/request/params.go +++ b/http/request/params.go @@ -107,6 +107,22 @@ func QueryInt64Param(r *http.Request, param string, defaultValue int64) int64 { return val } +// QueryBoolParam returns a query string parameter as bool. +func QueryBoolParam(r *http.Request, param string, defaultValue bool) bool { + value := r.URL.Query().Get(param) + if value == "" { + return defaultValue + } + + val, err := strconv.ParseBool(value) + + if err != nil { + return defaultValue + } + + return val +} + // HasQueryParam checks if the query string contains the given parameter. func HasQueryParam(r *http.Request, param string) bool { values := r.URL.Query() diff --git a/locale/translations/de_DE.json b/locale/translations/de_DE.json index dce26e84..d06830b8 100644 --- a/locale/translations/de_DE.json +++ b/locale/translations/de_DE.json @@ -1,5 +1,6 @@ { "confirm.question": "Sind Sie sicher?", + "confirm.question.refresh": "Möchten Sie eine erzwungene Aktualisierung durchführen?", "confirm.yes": "ja", "confirm.no": "nein", "confirm.loading": "In Arbeit...", diff --git a/locale/translations/el_EL.json b/locale/translations/el_EL.json index d504e409..e7774136 100644 --- a/locale/translations/el_EL.json +++ b/locale/translations/el_EL.json @@ -1,5 +1,6 @@ { "confirm.question": "Είστε σίγουροι;", + "confirm.question.refresh": "Θέλετε να επιτελέσετε μια υποχρεωτική ανανέωση;", "confirm.yes": "ναι", "confirm.no": "όχι", "confirm.loading": "Σε εξέλιξη...", diff --git a/locale/translations/en_US.json b/locale/translations/en_US.json index 7c144379..7b3e2ccf 100644 --- a/locale/translations/en_US.json +++ b/locale/translations/en_US.json @@ -1,5 +1,6 @@ { "confirm.question": "Are you sure?", + "confirm.question.refresh": "Are you want to force refresh?", "confirm.yes": "yes", "confirm.no": "no", "confirm.loading": "In progress…", diff --git a/locale/translations/es_ES.json b/locale/translations/es_ES.json index 8653aca0..d09be909 100644 --- a/locale/translations/es_ES.json +++ b/locale/translations/es_ES.json @@ -1,5 +1,6 @@ { "confirm.question": "¿Estás seguro?", + "confirm.question.refresh": "¿Quieres forzar la actualización?", "confirm.yes": "sí", "confirm.no": "no", "confirm.loading": "En progreso...", diff --git a/locale/translations/fi_FI.json b/locale/translations/fi_FI.json index b934bc4b..81fdb5e6 100644 --- a/locale/translations/fi_FI.json +++ b/locale/translations/fi_FI.json @@ -1,5 +1,6 @@ { "confirm.question": "Oletko varma?", + "confirm.question.refresh": "Haluatko pakottaa päivityksen?", "confirm.yes": "kyllä", "confirm.no": "ei", "confirm.loading": "Käynnissä...", diff --git a/locale/translations/fr_FR.json b/locale/translations/fr_FR.json index 43d181ab..cc024e18 100644 --- a/locale/translations/fr_FR.json +++ b/locale/translations/fr_FR.json @@ -1,5 +1,6 @@ { "confirm.question": "Êtes-vous sûr ?", + "confirm.question.refresh": "Voulez-vous forcer le rafraîchissement ?", "confirm.yes": "oui", "confirm.no": "non", "confirm.loading": "En cours...", diff --git a/locale/translations/hi_IN.json b/locale/translations/hi_IN.json index 27ab00b0..c56b275d 100644 --- a/locale/translations/hi_IN.json +++ b/locale/translations/hi_IN.json @@ -1,5 +1,6 @@ { "confirm.question": "मंजूर है?", + "confirm.question.refresh": "क्या आप बल द्वारा ताज़ा करना चाहते हैं?", "confirm.yes": "हाँ", "confirm.no": " नहीं", "confirm.loading": " प्रगति में है ...", diff --git a/locale/translations/id_ID.json b/locale/translations/id_ID.json index 7b62a2a7..f0c62fd5 100644 --- a/locale/translations/id_ID.json +++ b/locale/translations/id_ID.json @@ -1,5 +1,6 @@ { "confirm.question": "Apakah Anda yakin?", + "confirm.question.refresh": "Apakah Anda ingin memaksa penyegaran?", "confirm.yes": "ya", "confirm.no": "tidak", "confirm.loading": "Sedang progres...", diff --git a/locale/translations/it_IT.json b/locale/translations/it_IT.json index f4031ce8..e45754a7 100644 --- a/locale/translations/it_IT.json +++ b/locale/translations/it_IT.json @@ -1,5 +1,6 @@ { "confirm.question": "Sei sicuro?", + "confirm.question.refresh": "Vuoi forzare l'aggiornamento?", "confirm.yes": "sì", "confirm.no": "no", "confirm.loading": "In corso...", diff --git a/locale/translations/ja_JP.json b/locale/translations/ja_JP.json index 68ae1412..a7e88a40 100644 --- a/locale/translations/ja_JP.json +++ b/locale/translations/ja_JP.json @@ -1,5 +1,6 @@ { "confirm.question": "よろしいですか?", + "confirm.question.refresh": "強制的に更新しますか?", "confirm.yes": "はい", "confirm.no": "いいえ", "confirm.loading": "実行中…", diff --git a/locale/translations/nl_NL.json b/locale/translations/nl_NL.json index e74a482e..d401f98d 100644 --- a/locale/translations/nl_NL.json +++ b/locale/translations/nl_NL.json @@ -1,5 +1,6 @@ { "confirm.question": "Weet je het zeker?", + "confirm.question.refresh": "Wil je een gedwongen vernieuwing uitvoeren?", "confirm.yes": "ja", "confirm.no": "nee", "confirm.loading": "Bezig...", diff --git a/locale/translations/pl_PL.json b/locale/translations/pl_PL.json index d6147821..21f0c339 100644 --- a/locale/translations/pl_PL.json +++ b/locale/translations/pl_PL.json @@ -1,5 +1,6 @@ { "confirm.question": "Czy jesteś pewny?", + "confirm.question.refresh": "Czy chcesz wymusić odświeżenie?", "confirm.yes": "tak", "confirm.no": "nie", "confirm.loading": "W toku...", diff --git a/locale/translations/pt_BR.json b/locale/translations/pt_BR.json index 485034e8..e97089df 100644 --- a/locale/translations/pt_BR.json +++ b/locale/translations/pt_BR.json @@ -1,5 +1,6 @@ { "confirm.question": "Tem certeza?", + "confirm.question.refresh": "Você deseja forçar a atualização?", "confirm.yes": "Sim", "confirm.no": "Não", "confirm.loading": "Carregando...", diff --git a/locale/translations/ru_RU.json b/locale/translations/ru_RU.json index 3c334afe..a679cf81 100644 --- a/locale/translations/ru_RU.json +++ b/locale/translations/ru_RU.json @@ -1,5 +1,6 @@ { "confirm.question": "Вы уверены?", + "confirm.question.refresh": "Вы хотите выполнить принудительное обновление?", "confirm.yes": "да", "confirm.no": "нет", "confirm.loading": "В процессе…", diff --git a/locale/translations/tr_TR.json b/locale/translations/tr_TR.json index 88d60326..3fd475a4 100644 --- a/locale/translations/tr_TR.json +++ b/locale/translations/tr_TR.json @@ -1,5 +1,6 @@ { "confirm.question": "Emin misiniz?", + "confirm.question.refresh": "Zorla yenilemek istiyor musunuz?", "confirm.yes": "evet", "confirm.no": "hayır", "confirm.loading": "Devam ediyor...", diff --git a/locale/translations/uk_UA.json b/locale/translations/uk_UA.json index 103c05e1..5ba751d4 100644 --- a/locale/translations/uk_UA.json +++ b/locale/translations/uk_UA.json @@ -1,5 +1,6 @@ { "confirm.question": "Ви впевнені?", + "confirm.question.refresh": "Ви хочете змусити оновити?", "confirm.yes": "так", "confirm.no": "ні", "confirm.loading": "В процесі...", diff --git a/locale/translations/zh_CN.json b/locale/translations/zh_CN.json index 13e3d15b..a107a523 100644 --- a/locale/translations/zh_CN.json +++ b/locale/translations/zh_CN.json @@ -1,5 +1,6 @@ { "confirm.question": "您确认吗?", + "confirm.question.refresh": "您是否要强制刷新?", "confirm.yes": "是", "confirm.no": "否", "confirm.loading": "执行中…", diff --git a/locale/translations/zh_TW.json b/locale/translations/zh_TW.json index ce246288..e9c5f285 100644 --- a/locale/translations/zh_TW.json +++ b/locale/translations/zh_TW.json @@ -1,5 +1,6 @@ { "confirm.question": "您確認嗎?", + "confirm.question.refresh": "您想要強制刷新嗎?", "confirm.yes": "是", "confirm.no": "否", "confirm.loading": "執行中…", diff --git a/reader/handler/handler.go b/reader/handler/handler.go index b727ef90..03beee8f 100644 --- a/reader/handler/handler.go +++ b/reader/handler/handler.go @@ -83,7 +83,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model subscription.WithClientResponse(response) subscription.CheckedNow() - processor.ProcessFeedEntries(store, subscription, user) + processor.ProcessFeedEntries(store, subscription, user, true) if storeErr := store.CreateFeed(subscription); storeErr != nil { return nil, storeErr @@ -104,7 +104,7 @@ func CreateFeed(store *storage.Storage, userID int64, feedCreationRequest *model } // RefreshFeed refreshes a feed. -func RefreshFeed(store *storage.Storage, userID, feedID int64) error { +func RefreshFeed(store *storage.Storage, userID, feedID int64, forceRefresh bool) error { defer timer.ExecutionTime(time.Now(), fmt.Sprintf("[RefreshFeed] feedID=%d", feedID)) user, storeErr := store.UserByID(userID) if storeErr != nil { @@ -173,10 +173,11 @@ func RefreshFeed(store *storage.Storage, userID, feedID int64) error { } originalFeed.Entries = updatedFeed.Entries - processor.ProcessFeedEntries(store, originalFeed, user) + processor.ProcessFeedEntries(store, originalFeed, user, forceRefresh) - // We don't update existing entries when the crawler is enabled (we crawl only inexisting entries). - if storeErr := store.RefreshFeedEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, !originalFeed.Crawler); storeErr != nil { + // We don't update existing entries when the crawler is enabled (we crawl only inexisting entries). Unless it is forced to refresh + updateExistingEntries := forceRefresh || !originalFeed.Crawler + if storeErr := store.RefreshFeedEntries(originalFeed.UserID, originalFeed.ID, originalFeed.Entries, updateExistingEntries); storeErr != nil { originalFeed.WithError(storeErr.Error()) store.UpdateFeedError(originalFeed) return storeErr diff --git a/reader/processor/processor.go b/reader/processor/processor.go index e720e1cf..181eaa6d 100644 --- a/reader/processor/processor.go +++ b/reader/processor/processor.go @@ -38,7 +38,7 @@ var ( ) // ProcessFeedEntries downloads original web page for entries and apply filters. -func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.User) { +func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.User, forceRefresh bool) { var filteredEntries model.Entries // array used for bulk push @@ -56,7 +56,7 @@ func ProcessFeedEntries(store *storage.Storage, feed *model.Feed, user *model.Us url := getUrlFromEntry(feed, entry) entryIsNew := !store.EntryURLExists(feed.ID, entry.URL) - if feed.Crawler && entryIsNew { + if feed.Crawler && (entryIsNew || forceRefresh) { logger.Debug("[Processor] Crawling entry %q from feed %q", url, feed.FeedURL) startTime := time.Now() diff --git a/template/templates/views/edit_feed.html b/template/templates/views/edit_feed.html index af4a5b2a..12338ce3 100644 --- a/template/templates/views/edit_feed.html +++ b/template/templates/views/edit_feed.html @@ -11,7 +11,14 @@ {{ icon "entries" }}{{ t "menu.feed_entries" }}