mirror of
https://github.com/makew0rld/amfora.git
synced 2024-06-19 19:25:24 +00:00
Switch subscription-based naming
This commit is contained in:
parent
ba28b2b5f9
commit
f6e89fdaa1
2
NOTES.md
2
NOTES.md
|
@ -1,6 +1,6 @@
|
||||||
# Notes
|
# Notes
|
||||||
|
|
||||||
## Feeds (temp)
|
## Subscriptions (temp)
|
||||||
- TODO: remove all logger lines
|
- TODO: remove all logger lines
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
|
@ -128,9 +128,9 @@ Features in *italics* are in the master branch, but not in the latest release.
|
||||||
- Manage and browse them
|
- Manage and browse them
|
||||||
- Similar to [Kristall](https://github.com/MasterQ32/kristall)
|
- Similar to [Kristall](https://github.com/MasterQ32/kristall)
|
||||||
- https://lists.orbitalfox.eu/archives/gemini/2020/001400.html
|
- https://lists.orbitalfox.eu/archives/gemini/2020/001400.html
|
||||||
- [x] Subscribe to feeds and display them
|
- [x] Subscriptions
|
||||||
- Tracking page changes is also supported
|
|
||||||
- RSS, Atom, and [JSON Feeds](https://jsonfeed.org/) are all supported
|
- RSS, Atom, and [JSON Feeds](https://jsonfeed.org/) are all supported
|
||||||
|
- So is tracking any page to be notified when it changes
|
||||||
- [ ] Stream support
|
- [ ] Stream support
|
||||||
- [ ] Table of contents for pages
|
- [ ] Table of contents for pages
|
||||||
- [ ] History browser
|
- [ ] History browser
|
||||||
|
|
|
@ -7,8 +7,8 @@ import (
|
||||||
"github.com/makeworld-the-better-one/amfora/client"
|
"github.com/makeworld-the-better-one/amfora/client"
|
||||||
"github.com/makeworld-the-better-one/amfora/config"
|
"github.com/makeworld-the-better-one/amfora/config"
|
||||||
"github.com/makeworld-the-better-one/amfora/display"
|
"github.com/makeworld-the-better-one/amfora/display"
|
||||||
"github.com/makeworld-the-better-one/amfora/feeds"
|
|
||||||
"github.com/makeworld-the-better-one/amfora/logger"
|
"github.com/makeworld-the-better-one/amfora/logger"
|
||||||
|
"github.com/makeworld-the-better-one/amfora/subscriptions"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -45,9 +45,9 @@ func main() {
|
||||||
fmt.Fprintf(os.Stderr, "Config error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Config error: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
err = feeds.Init()
|
err = subscriptions.Init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "feeds.json error: %v\n", err)
|
fmt.Fprintf(os.Stderr, "subscriptions.json error: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,9 +39,9 @@ var bkmkPath string
|
||||||
|
|
||||||
var DownloadsDir string
|
var DownloadsDir string
|
||||||
|
|
||||||
// Feeds
|
// Subscriptions
|
||||||
var feedDir string
|
var subscriptionDir string
|
||||||
var FeedPath string
|
var SubscriptionPath string
|
||||||
|
|
||||||
// Command for opening HTTP(S) URLs in the browser, from "a-general.http" in config.
|
// Command for opening HTTP(S) URLs in the browser, from "a-general.http" in config.
|
||||||
var HTTPCommand []string
|
var HTTPCommand []string
|
||||||
|
@ -103,18 +103,18 @@ func Init() error {
|
||||||
// Feeds dir and path
|
// Feeds dir and path
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
// In APPDATA beside other Amfora files
|
// In APPDATA beside other Amfora files
|
||||||
feedDir = amforaAppData
|
subscriptionDir = amforaAppData
|
||||||
} else {
|
} else {
|
||||||
// XDG data dir on POSIX systems
|
// XDG data dir on POSIX systems
|
||||||
xdg_data, ok := os.LookupEnv("XDG_DATA_HOME")
|
xdg_data, ok := os.LookupEnv("XDG_DATA_HOME")
|
||||||
if ok && strings.TrimSpace(xdg_data) != "" {
|
if ok && strings.TrimSpace(xdg_data) != "" {
|
||||||
feedDir = filepath.Join(xdg_data, "amfora")
|
subscriptionDir = filepath.Join(xdg_data, "amfora")
|
||||||
} else {
|
} else {
|
||||||
// Default to ~/.local/share/amfora
|
// Default to ~/.local/share/amfora
|
||||||
feedDir = filepath.Join(home, ".local", "share", "amfora")
|
subscriptionDir = filepath.Join(home, ".local", "share", "amfora")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FeedPath = filepath.Join(feedDir, "feeds.json")
|
SubscriptionPath = filepath.Join(subscriptionDir, "subscriptions.json")
|
||||||
|
|
||||||
// *** Create necessary files and folders ***
|
// *** Create necessary files and folders ***
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ func Init() error {
|
||||||
f.Close()
|
f.Close()
|
||||||
}
|
}
|
||||||
// Feeds
|
// Feeds
|
||||||
err = os.MkdirAll(feedDir, 0755)
|
err = os.MkdirAll(subscriptionDir, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -234,9 +234,9 @@ func Init() error {
|
||||||
viper.SetDefault("url-handlers.other", "off")
|
viper.SetDefault("url-handlers.other", "off")
|
||||||
viper.SetDefault("cache.max_size", 0)
|
viper.SetDefault("cache.max_size", 0)
|
||||||
viper.SetDefault("cache.max_pages", 20)
|
viper.SetDefault("cache.max_pages", 20)
|
||||||
viper.SetDefault("feeds.popup", true)
|
viper.SetDefault("subscriptions.popup", true)
|
||||||
viper.SetDefault("feeds.update_interval", 1800)
|
viper.SetDefault("subscriptions.update_interval", 1800)
|
||||||
viper.SetDefault("feeds.workers", 3)
|
viper.SetDefault("subscriptions.workers", 3)
|
||||||
|
|
||||||
viper.SetConfigFile(configPath)
|
viper.SetConfigFile(configPath)
|
||||||
viper.SetConfigType("toml")
|
viper.SetConfigType("toml")
|
||||||
|
|
|
@ -135,22 +135,22 @@ max_pages = 30 # The maximum number of pages the cache will store
|
||||||
# Note that HTTP and HTTPS are treated as separate protocols here.
|
# Note that HTTP and HTTPS are treated as separate protocols here.
|
||||||
|
|
||||||
|
|
||||||
[feeds]
|
[subscriptions]
|
||||||
# For tracking feeds and pages
|
# For tracking feeds and pages
|
||||||
|
|
||||||
# Whether a pop-up appears when viewing a potential feed
|
# Whether a pop-up appears when viewing a potential feed
|
||||||
popup = true
|
popup = true
|
||||||
|
|
||||||
# How often to check for new feeds and pages in the background, in seconds.
|
# How often to check for updates to subscriptions in the background, in seconds.
|
||||||
# Note Amfora will check for updates on browser start anyway.
|
# Set it to 0 to disable this feature. You can still update individual feeds
|
||||||
# Set it to 0 or below to disable this feature. You can still update individual
|
# manually, or restart the browser.
|
||||||
# feeds manually, or just restart the browser to update all of them.
|
#
|
||||||
|
# Note Amfora will check for updates on browser start no matter what this setting is.
|
||||||
update_interval = 1800 # 30 mins
|
update_interval = 1800 # 30 mins
|
||||||
|
|
||||||
# How many pages/feeds can be checked at the same time when updating.
|
# How many subscriptions can be checked at the same time when updating.
|
||||||
# If you are tracking many feeds and pages you may want to increase this for
|
# If you have many subscriptions you may want to increase this for faster
|
||||||
# faster update times.
|
# update times. Any value below 1 will be corrected to 1.
|
||||||
# Any value below 1 will be corrected to 1.
|
|
||||||
workers = 3
|
workers = 3
|
||||||
|
|
||||||
|
|
||||||
|
@ -212,8 +212,8 @@ workers = 3
|
||||||
# yesno_modal_text
|
# yesno_modal_text
|
||||||
# tofu_modal_bg
|
# tofu_modal_bg
|
||||||
# tofu_modal_text
|
# tofu_modal_text
|
||||||
# feed_modal_bg
|
# subscription_modal_bg
|
||||||
# feed_modal_text
|
# subscription_modal_text
|
||||||
|
|
||||||
# input_modal_bg
|
# input_modal_bg
|
||||||
# input_modal_text
|
# input_modal_text
|
||||||
|
|
|
@ -26,20 +26,20 @@ var theme = map[string]tcell.Color{
|
||||||
"btn_bg": tcell.ColorNavy, // All modal buttons
|
"btn_bg": tcell.ColorNavy, // All modal buttons
|
||||||
"btn_text": tcell.ColorWhite,
|
"btn_text": tcell.ColorWhite,
|
||||||
|
|
||||||
"dl_choice_modal_bg": tcell.ColorPurple,
|
"dl_choice_modal_bg": tcell.ColorPurple,
|
||||||
"dl_choice_modal_text": tcell.ColorWhite,
|
"dl_choice_modal_text": tcell.ColorWhite,
|
||||||
"dl_modal_bg": tcell.Color130, // xterm:DarkOrange3, #af5f00
|
"dl_modal_bg": tcell.Color130, // xterm:DarkOrange3, #af5f00
|
||||||
"dl_modal_text": tcell.ColorWhite,
|
"dl_modal_text": tcell.ColorWhite,
|
||||||
"info_modal_bg": tcell.ColorGray,
|
"info_modal_bg": tcell.ColorGray,
|
||||||
"info_modal_text": tcell.ColorWhite,
|
"info_modal_text": tcell.ColorWhite,
|
||||||
"error_modal_bg": tcell.ColorMaroon,
|
"error_modal_bg": tcell.ColorMaroon,
|
||||||
"error_modal_text": tcell.ColorWhite,
|
"error_modal_text": tcell.ColorWhite,
|
||||||
"yesno_modal_bg": tcell.ColorPurple,
|
"yesno_modal_bg": tcell.ColorPurple,
|
||||||
"yesno_modal_text": tcell.ColorWhite,
|
"yesno_modal_text": tcell.ColorWhite,
|
||||||
"tofu_modal_bg": tcell.ColorMaroon,
|
"tofu_modal_bg": tcell.ColorMaroon,
|
||||||
"tofu_modal_text": tcell.ColorWhite,
|
"tofu_modal_text": tcell.ColorWhite,
|
||||||
"feed_modal_bg": tcell.Color61, // xterm:SlateBlue3, #5f5faf
|
"subscription_modal_bg": tcell.Color61, // xterm:SlateBlue3, #5f5faf
|
||||||
"feed_modal_text": tcell.ColorWhite,
|
"subscription_modal_text": tcell.ColorWhite,
|
||||||
|
|
||||||
"input_modal_bg": tcell.ColorGreen,
|
"input_modal_bg": tcell.ColorGreen,
|
||||||
"input_modal_text": tcell.ColorWhite,
|
"input_modal_text": tcell.ColorWhite,
|
||||||
|
|
|
@ -132,22 +132,22 @@ max_pages = 30 # The maximum number of pages the cache will store
|
||||||
# Note that HTTP and HTTPS are treated as separate protocols here.
|
# Note that HTTP and HTTPS are treated as separate protocols here.
|
||||||
|
|
||||||
|
|
||||||
[feeds]
|
[subscriptions]
|
||||||
# For tracking feeds and pages
|
# For tracking feeds and pages
|
||||||
|
|
||||||
# Whether a pop-up appears when viewing a potential feed
|
# Whether a pop-up appears when viewing a potential feed
|
||||||
popup = true
|
popup = true
|
||||||
|
|
||||||
# How often to check for new feeds and pages in the background, in seconds.
|
# How often to check for updates to subscriptions in the background, in seconds.
|
||||||
# Note Amfora will check for updates on browser start anyway.
|
# Set it to 0 to disable this feature. You can still update individual feeds
|
||||||
# Set it to 0 or below to disable this feature. You can still update individual
|
# manually, or restart the browser.
|
||||||
# feeds manually, or just restart the browser to update all of them.
|
#
|
||||||
|
# Note Amfora will check for updates on browser start no matter what this setting is.
|
||||||
update_interval = 1800 # 30 mins
|
update_interval = 1800 # 30 mins
|
||||||
|
|
||||||
# How many pages/feeds can be checked at the same time when updating.
|
# How many subscriptions can be checked at the same time when updating.
|
||||||
# If you are tracking many feeds and pages you may want to increase this for
|
# If you have many subscriptions you may want to increase this for faster
|
||||||
# faster update times.
|
# update times. Any value below 1 will be corrected to 1.
|
||||||
# Any value below 1 will be corrected to 1.
|
|
||||||
workers = 3
|
workers = 3
|
||||||
|
|
||||||
|
|
||||||
|
@ -209,8 +209,8 @@ workers = 3
|
||||||
# yesno_modal_text
|
# yesno_modal_text
|
||||||
# tofu_modal_bg
|
# tofu_modal_bg
|
||||||
# tofu_modal_text
|
# tofu_modal_text
|
||||||
# feed_modal_bg
|
# subscription_modal_bg
|
||||||
# feed_modal_text
|
# subscription_modal_text
|
||||||
|
|
||||||
# input_modal_bg
|
# input_modal_bg
|
||||||
# input_modal_text
|
# input_modal_text
|
||||||
|
|
|
@ -294,11 +294,11 @@ func Init() {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
case tcell.KeyCtrlA:
|
case tcell.KeyCtrlA:
|
||||||
Feeds(tabs[curTab])
|
Subscriptions(tabs[curTab])
|
||||||
tabs[curTab].addToHistory("about:feeds")
|
tabs[curTab].addToHistory("about:subscriptions")
|
||||||
return nil
|
return nil
|
||||||
case tcell.KeyCtrlX:
|
case tcell.KeyCtrlX:
|
||||||
go addFeed()
|
go addSubscription()
|
||||||
return nil
|
return nil
|
||||||
case tcell.KeyRune:
|
case tcell.KeyRune:
|
||||||
// Regular key was sent
|
// Regular key was sent
|
||||||
|
@ -583,9 +583,9 @@ func URL(u string) {
|
||||||
tabs[curTab].addToHistory("about:bookmarks")
|
tabs[curTab].addToHistory("about:bookmarks")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if u == "about:feeds" { //nolint:goconst
|
if u == "about:subscriptions" { //nolint:goconst
|
||||||
Feeds(tabs[curTab])
|
Subscriptions(tabs[curTab])
|
||||||
tabs[curTab].addToHistory("about:feeds")
|
tabs[curTab].addToHistory("about:subscriptions")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if u == "about:newtab" {
|
if u == "about:newtab" {
|
||||||
|
|
|
@ -42,8 +42,8 @@ Ctrl-R, R|Reload a page, discarding the cached version.
|
||||||
Ctrl-B|View bookmarks
|
Ctrl-B|View bookmarks
|
||||||
Ctrl-D|Add, change, or remove a bookmark for the current page.
|
Ctrl-D|Add, change, or remove a bookmark for the current page.
|
||||||
Ctrl-S|Save the current page to your downloads.
|
Ctrl-S|Save the current page to your downloads.
|
||||||
Ctrl-A|View tracked feeds and pages.
|
Ctrl-A|View subscriptions
|
||||||
Ctrl-X|Track or update the current feed/page.
|
Ctrl-X|Add or update a subscription
|
||||||
q, Ctrl-Q|Quit
|
q, Ctrl-Q|Quit
|
||||||
Ctrl-C|Hard quit. This can be used when in the middle of downloading,
|
Ctrl-C|Hard quit. This can be used when in the middle of downloading,
|
||||||
|for example.
|
|for example.
|
||||||
|
|
|
@ -18,7 +18,7 @@ You can customize this page by creating a gemtext file called newtab.gmi, in Amf
|
||||||
Happy browsing!
|
Happy browsing!
|
||||||
|
|
||||||
=> about:bookmarks Bookmarks
|
=> about:bookmarks Bookmarks
|
||||||
=> about:feeds Feed and Page Tracking
|
=> about:subscriptions Feed and Page Tracking
|
||||||
|
|
||||||
=> //gemini.circumlunar.space Project Gemini
|
=> //gemini.circumlunar.space Project Gemini
|
||||||
=> https://github.com/makeworld-the-better-one/amfora Amfora homepage [HTTPS]
|
=> https://github.com/makeworld-the-better-one/amfora Amfora homepage [HTTPS]
|
||||||
|
|
|
@ -16,9 +16,9 @@ import (
|
||||||
"github.com/makeworld-the-better-one/amfora/cache"
|
"github.com/makeworld-the-better-one/amfora/cache"
|
||||||
"github.com/makeworld-the-better-one/amfora/client"
|
"github.com/makeworld-the-better-one/amfora/client"
|
||||||
"github.com/makeworld-the-better-one/amfora/config"
|
"github.com/makeworld-the-better-one/amfora/config"
|
||||||
"github.com/makeworld-the-better-one/amfora/feeds"
|
|
||||||
"github.com/makeworld-the-better-one/amfora/renderer"
|
"github.com/makeworld-the-better-one/amfora/renderer"
|
||||||
"github.com/makeworld-the-better-one/amfora/structs"
|
"github.com/makeworld-the-better-one/amfora/structs"
|
||||||
|
"github.com/makeworld-the-better-one/amfora/subscriptions"
|
||||||
"github.com/makeworld-the-better-one/amfora/webbrowser"
|
"github.com/makeworld-the-better-one/amfora/webbrowser"
|
||||||
"github.com/makeworld-the-better-one/go-gemini"
|
"github.com/makeworld-the-better-one/go-gemini"
|
||||||
"github.com/makeworld-the-better-one/go-isemoji"
|
"github.com/makeworld-the-better-one/go-isemoji"
|
||||||
|
@ -39,9 +39,9 @@ func followLink(t *tab, prev, next string) {
|
||||||
t.addToHistory("about:bookmarks")
|
t.addToHistory("about:bookmarks")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if next == "about:feeds" {
|
if next == "about:subscriptions" {
|
||||||
Feeds(t)
|
Subscriptions(t)
|
||||||
t.addToHistory("about:feeds")
|
t.addToHistory("about:subscriptions")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(next, "about:") {
|
if strings.HasPrefix(next, "about:") {
|
||||||
|
@ -340,7 +340,7 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
|
||||||
t.mode = tabModeDone
|
t.mode = tabModeDone
|
||||||
|
|
||||||
go func(p *structs.Page) {
|
go func(p *structs.Page) {
|
||||||
if b && t.hasContent() && !feeds.IsTracked(s) && viper.GetBool("feeds.popup") {
|
if b && t.hasContent() && !subscriptions.IsSubscribed(s) && viper.GetBool("subscriptions.popup") {
|
||||||
// The current page might be an untracked feed, and the user wants
|
// The current page might be an untracked feed, and the user wants
|
||||||
// to be notified in such cases.
|
// to be notified in such cases.
|
||||||
|
|
||||||
|
@ -365,9 +365,9 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
|
||||||
Bookmarks(t)
|
Bookmarks(t)
|
||||||
return ret("about:bookmarks", true)
|
return ret("about:bookmarks", true)
|
||||||
}
|
}
|
||||||
if u == "about:feeds" {
|
if u == "about:subscriptions" {
|
||||||
Feeds(t)
|
Subscriptions(t)
|
||||||
return ret("about:feeds", true)
|
return ret("about:subscriptions", true)
|
||||||
}
|
}
|
||||||
|
|
||||||
u = normalizeURL(u)
|
u = normalizeURL(u)
|
||||||
|
@ -613,10 +613,10 @@ func handleURL(t *tab, u string, numRedirects int) (string, bool) {
|
||||||
// First see if it's a feed, and ask the user about adding it if it is
|
// First see if it's a feed, and ask the user about adding it if it is
|
||||||
filename := path.Base(parsed.Path)
|
filename := path.Base(parsed.Path)
|
||||||
mediatype, _, _ := mime.ParseMediaType(res.Meta)
|
mediatype, _, _ := mime.ParseMediaType(res.Meta)
|
||||||
feed, ok := feeds.GetFeed(mediatype, filename, res.Body)
|
feed, ok := subscriptions.GetFeed(mediatype, filename, res.Body)
|
||||||
if ok {
|
if ok {
|
||||||
go func() {
|
go func() {
|
||||||
added := addFeedDirect(u, feed, feeds.IsTracked(u))
|
added := addFeedDirect(u, feed, subscriptions.IsSubscribed(u))
|
||||||
if !added {
|
if !added {
|
||||||
// Otherwise offer download choices
|
// Otherwise offer download choices
|
||||||
go dlChoice("That file could not be displayed. What would you like to do?", u, res)
|
go dlChoice("That file could not be displayed. What would you like to do?", u, res)
|
||||||
|
|
|
@ -11,15 +11,15 @@ import (
|
||||||
"github.com/gdamore/tcell"
|
"github.com/gdamore/tcell"
|
||||||
"github.com/makeworld-the-better-one/amfora/cache"
|
"github.com/makeworld-the-better-one/amfora/cache"
|
||||||
"github.com/makeworld-the-better-one/amfora/config"
|
"github.com/makeworld-the-better-one/amfora/config"
|
||||||
"github.com/makeworld-the-better-one/amfora/feeds"
|
|
||||||
"github.com/makeworld-the-better-one/amfora/logger"
|
"github.com/makeworld-the-better-one/amfora/logger"
|
||||||
"github.com/makeworld-the-better-one/amfora/renderer"
|
"github.com/makeworld-the-better-one/amfora/renderer"
|
||||||
"github.com/makeworld-the-better-one/amfora/structs"
|
"github.com/makeworld-the-better-one/amfora/structs"
|
||||||
|
"github.com/makeworld-the-better-one/amfora/subscriptions"
|
||||||
"github.com/mmcdole/gofeed"
|
"github.com/mmcdole/gofeed"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var feedPageUpdated time.Time
|
var subscriptionPageUpdated time.Time
|
||||||
|
|
||||||
// toLocalDay truncates the provided time to a date only,
|
// toLocalDay truncates the provided time to a date only,
|
||||||
// but converts to the local time first.
|
// but converts to the local time first.
|
||||||
|
@ -29,21 +29,21 @@ func toLocalDay(t time.Time) time.Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Feeds displays the feeds page on the current tab.
|
// Feeds displays the feeds page on the current tab.
|
||||||
func Feeds(t *tab) {
|
func Subscriptions(t *tab) {
|
||||||
logger.Log.Println("display.Feeds called")
|
logger.Log.Println("display.Subscriptions called")
|
||||||
|
|
||||||
// Retrieve cached version if there hasn't been any updates
|
// Retrieve cached version if there hasn't been any updates
|
||||||
p, ok := cache.GetPage("about:feeds")
|
p, ok := cache.GetPage("about:subscriptions")
|
||||||
if feedPageUpdated.After(feeds.LastUpdated) && ok {
|
if subscriptionPageUpdated.After(subscriptions.LastUpdated) && ok {
|
||||||
logger.Log.Println("using cached feeds page")
|
logger.Log.Println("using cached subscriptions page")
|
||||||
setPage(t, p)
|
setPage(t, p)
|
||||||
t.applyBottomBar()
|
t.applyBottomBar()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Log.Println("started rendering feeds page")
|
logger.Log.Println("started rendering subscriptions page")
|
||||||
|
|
||||||
feedPageRaw := "# Feeds & Pages\n\n" +
|
subscriptionPageRaw := "# Subscriptions\n\n" +
|
||||||
"See the help (by pressing ?) for details on how to use this page.\n\n" +
|
"See the help (by pressing ?) for details on how to use this page.\n\n" +
|
||||||
"If you just opened Amfora then updates will appear incrementally. Reload the page to see them.\n"
|
"If you just opened Amfora then updates will appear incrementally. Reload the page to see them.\n"
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ func Feeds(t *tab) {
|
||||||
// the UTC timezone is specified. I believe gemfeed does this.
|
// the UTC timezone is specified. I believe gemfeed does this.
|
||||||
curDay := toLocalDay(time.Now()).Add(26 * time.Hour)
|
curDay := toLocalDay(time.Now()).Add(26 * time.Hour)
|
||||||
|
|
||||||
pe := feeds.GetPageEntries()
|
pe := subscriptions.GetPageEntries()
|
||||||
|
|
||||||
for _, entry := range pe.Entries { // From new to old
|
for _, entry := range pe.Entries { // From new to old
|
||||||
// Convert to local time, remove sub-day info
|
// Convert to local time, remove sub-day info
|
||||||
|
@ -67,24 +67,24 @@ func Feeds(t *tab) {
|
||||||
if pub.Before(curDay) {
|
if pub.Before(curDay) {
|
||||||
// This post is on a new day, add a day header
|
// This post is on a new day, add a day header
|
||||||
curDay = pub
|
curDay = pub
|
||||||
feedPageRaw += fmt.Sprintf("\n## %s\n\n", curDay.Format("Jan 02, 2006"))
|
subscriptionPageRaw += fmt.Sprintf("\n## %s\n\n", curDay.Format("Jan 02, 2006"))
|
||||||
}
|
}
|
||||||
if entry.Title == "" || entry.Title == "/" {
|
if entry.Title == "" || entry.Title == "/" {
|
||||||
// Just put author/title
|
// Just put author/title
|
||||||
// Mainly used for when you're tracking the root domain of a site
|
// Mainly used for when you're tracking the root domain of a site
|
||||||
feedPageRaw += fmt.Sprintf("=>%s %s\n", entry.URL, entry.Prefix)
|
subscriptionPageRaw += fmt.Sprintf("=>%s %s\n", entry.URL, entry.Prefix)
|
||||||
} else {
|
} else {
|
||||||
// Include title and dash
|
// Include title and dash
|
||||||
feedPageRaw += fmt.Sprintf("=>%s %s - %s\n", entry.URL, entry.Prefix, entry.Title)
|
subscriptionPageRaw += fmt.Sprintf("=>%s %s - %s\n", entry.URL, entry.Prefix, entry.Title)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
content, links := renderer.RenderGemini(feedPageRaw, textWidth(), leftMargin(), false)
|
content, links := renderer.RenderGemini(subscriptionPageRaw, textWidth(), leftMargin(), false)
|
||||||
page := structs.Page{
|
page := structs.Page{
|
||||||
Raw: feedPageRaw,
|
Raw: subscriptionPageRaw,
|
||||||
Content: content,
|
Content: content,
|
||||||
Links: links,
|
Links: links,
|
||||||
URL: "about:feeds",
|
URL: "about:subscriptions",
|
||||||
Width: termW,
|
Width: termW,
|
||||||
Mediatype: structs.TextGemini,
|
Mediatype: structs.TextGemini,
|
||||||
}
|
}
|
||||||
|
@ -92,26 +92,26 @@ func Feeds(t *tab) {
|
||||||
setPage(t, &page)
|
setPage(t, &page)
|
||||||
t.applyBottomBar()
|
t.applyBottomBar()
|
||||||
|
|
||||||
feedPageUpdated = time.Now()
|
subscriptionPageUpdated = time.Now()
|
||||||
|
|
||||||
logger.Log.Println("done rendering feeds page")
|
logger.Log.Println("done rendering subscriptions page")
|
||||||
}
|
}
|
||||||
|
|
||||||
// openFeedModal displays the "Add feed/page" modal
|
// openSubscriptionModal displays the "Add subscription" modal
|
||||||
// It returns whether the user wanted to add the feed/page.
|
// It returns whether the user wanted to subscribe to feed/page.
|
||||||
// The tracked arg specifies whether this feed/page is already
|
// The subscribed arg specifies whether this feed/page is already
|
||||||
// being tracked.
|
// subscribed to.
|
||||||
func openFeedModal(validFeed, tracked bool) bool {
|
func openSubscriptionModal(validFeed, subscribed bool) bool {
|
||||||
logger.Log.Println("display.openFeedModal called")
|
logger.Log.Println("display.openFeedModal called")
|
||||||
// Reuses yesNoModal
|
// Reuses yesNoModal
|
||||||
|
|
||||||
if viper.GetBool("a-general.color") {
|
if viper.GetBool("a-general.color") {
|
||||||
yesNoModal.
|
yesNoModal.
|
||||||
SetBackgroundColor(config.GetColor("feed_modal_bg")).
|
SetBackgroundColor(config.GetColor("subscription_modal_bg")).
|
||||||
SetTextColor(config.GetColor("feed_modal_text"))
|
SetTextColor(config.GetColor("subscription_modal_text"))
|
||||||
yesNoModal.GetFrame().
|
yesNoModal.GetFrame().
|
||||||
SetBorderColor(config.GetColor("feed_modal_text")).
|
SetBorderColor(config.GetColor("subscription_modal_text")).
|
||||||
SetTitleColor(config.GetColor("feed_modal_text"))
|
SetTitleColor(config.GetColor("subscription_modal_text"))
|
||||||
} else {
|
} else {
|
||||||
yesNoModal.
|
yesNoModal.
|
||||||
SetBackgroundColor(tcell.ColorBlack).
|
SetBackgroundColor(tcell.ColorBlack).
|
||||||
|
@ -121,18 +121,18 @@ func openFeedModal(validFeed, tracked bool) bool {
|
||||||
SetTitleColor(tcell.ColorWhite)
|
SetTitleColor(tcell.ColorWhite)
|
||||||
}
|
}
|
||||||
if validFeed {
|
if validFeed {
|
||||||
yesNoModal.GetFrame().SetTitle("Feed Tracking")
|
yesNoModal.GetFrame().SetTitle("Feed Subscription")
|
||||||
if tracked {
|
if subscribed {
|
||||||
yesNoModal.SetText("This is already being tracked. Would you like to manually update it?")
|
yesNoModal.SetText("You are already subscribed to this feed. Would you like to manually update it?")
|
||||||
} else {
|
} else {
|
||||||
yesNoModal.SetText("Would you like to start tracking this feed?")
|
yesNoModal.SetText("Would you like to subscribe to this feed?")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
yesNoModal.GetFrame().SetTitle("Page Tracking")
|
yesNoModal.GetFrame().SetTitle("Page Subscription")
|
||||||
if tracked {
|
if subscribed {
|
||||||
yesNoModal.SetText("This is already being tracked. Would you like to manually update it?")
|
yesNoModal.SetText("You are already subscribed to this page. Would you like to manually update it?")
|
||||||
} else {
|
} else {
|
||||||
yesNoModal.SetText("Would you like to start tracking this page?")
|
yesNoModal.SetText("Would you like to subscribe to this page?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,12 +148,12 @@ func openFeedModal(validFeed, tracked bool) bool {
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
// getFeedFromPage is like feeds.GetFeed but takes a structs.Page as input.
|
// getFeedFromPage is like subscriptions.GetFeed but takes a structs.Page as input.
|
||||||
func getFeedFromPage(p *structs.Page) (*gofeed.Feed, bool) {
|
func getFeedFromPage(p *structs.Page) (*gofeed.Feed, bool) {
|
||||||
parsed, _ := url.Parse(p.URL)
|
parsed, _ := url.Parse(p.URL)
|
||||||
filename := path.Base(parsed.Path)
|
filename := path.Base(parsed.Path)
|
||||||
r := strings.NewReader(p.Raw)
|
r := strings.NewReader(p.Raw)
|
||||||
return feeds.GetFeed(p.RawMediatype, filename, r)
|
return subscriptions.GetFeed(p.RawMediatype, filename, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// addFeedDirect is only for adding feeds, not pages.
|
// addFeedDirect is only for adding feeds, not pages.
|
||||||
|
@ -166,8 +166,8 @@ func getFeedFromPage(p *structs.Page) (*gofeed.Feed, bool) {
|
||||||
func addFeedDirect(u string, feed *gofeed.Feed, tracked bool) bool {
|
func addFeedDirect(u string, feed *gofeed.Feed, tracked bool) bool {
|
||||||
logger.Log.Println("display.addFeedDirect called")
|
logger.Log.Println("display.addFeedDirect called")
|
||||||
|
|
||||||
if openFeedModal(true, tracked) {
|
if openSubscriptionModal(true, tracked) {
|
||||||
err := feeds.AddFeed(u, feed)
|
err := subscriptions.AddFeed(u, feed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Error("Feed Error", err.Error())
|
Error("Feed Error", err.Error())
|
||||||
}
|
}
|
||||||
|
@ -176,10 +176,10 @@ func addFeedDirect(u string, feed *gofeed.Feed, tracked bool) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// addFeed goes through the process of tracking the current page/feed.
|
// addFeed goes through the process of subscribing to the current page/feed.
|
||||||
// It is the high-level way of doing it. It should be called in a goroutine.
|
// It is the high-level way of doing it. It should be called in a goroutine.
|
||||||
func addFeed() {
|
func addSubscription() {
|
||||||
logger.Log.Println("display.addFeed called")
|
logger.Log.Println("display.addSubscription called")
|
||||||
|
|
||||||
t := tabs[curTab]
|
t := tabs[curTab]
|
||||||
p := t.page
|
p := t.page
|
||||||
|
@ -190,15 +190,15 @@ func addFeed() {
|
||||||
}
|
}
|
||||||
|
|
||||||
feed, isFeed := getFeedFromPage(p)
|
feed, isFeed := getFeedFromPage(p)
|
||||||
tracked := feeds.IsTracked(p.URL)
|
tracked := subscriptions.IsSubscribed(p.URL)
|
||||||
|
|
||||||
if openFeedModal(isFeed, tracked) {
|
if openSubscriptionModal(isFeed, tracked) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if isFeed {
|
if isFeed {
|
||||||
err = feeds.AddFeed(p.URL, feed)
|
err = subscriptions.AddFeed(p.URL, feed)
|
||||||
} else {
|
} else {
|
||||||
err = feeds.AddPage(p.URL, strings.NewReader(p.Raw))
|
err = subscriptions.AddPage(p.URL, strings.NewReader(p.Raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -1,4 +1,4 @@
|
||||||
package feeds
|
package subscriptions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// This file contains funcs for creating PageEntries, which
|
// This file contains funcs for creating PageEntries, which
|
||||||
// are consumed by display/feeds.go
|
// are consumed by display/subscriptions.go
|
||||||
|
|
||||||
// getURL returns a URL to be used in a PageEntry, from a
|
// getURL returns a URL to be used in a PageEntry, from a
|
||||||
// list of URLs for that item. It prefers gemini URLs, then
|
// list of URLs for that item. It prefers gemini URLs, then
|
||||||
|
@ -42,7 +42,7 @@ func getURL(urls []string) string {
|
||||||
// so this function needs to be called again to get updates.
|
// so this function needs to be called again to get updates.
|
||||||
// It always returns sorted entries - by post time, from newest to oldest.
|
// It always returns sorted entries - by post time, from newest to oldest.
|
||||||
func GetPageEntries() *PageEntries {
|
func GetPageEntries() *PageEntries {
|
||||||
logger.Log.Println("feeds.GetPageEntries called")
|
logger.Log.Println("subscriptions.GetPageEntries called")
|
||||||
|
|
||||||
var pe PageEntries
|
var pe PageEntries
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package feeds
|
package subscriptions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -77,8 +77,8 @@ var data = jsonData{
|
||||||
Pages: make(map[string]*pageJSON),
|
Pages: make(map[string]*pageJSON),
|
||||||
}
|
}
|
||||||
|
|
||||||
// PageEntry is a single item on a feed page.
|
// PageEntry is a single item on a subscriptions page.
|
||||||
// It is used both for tracked feeds and pages.
|
// It is used for both feeds and pages.
|
||||||
type PageEntry struct {
|
type PageEntry struct {
|
||||||
Prefix string // Feed/log title, author, etc - something before the post title
|
Prefix string // Feed/log title, author, etc - something before the post title
|
||||||
Title string
|
Title string
|
||||||
|
@ -86,9 +86,10 @@ type PageEntry struct {
|
||||||
Published time.Time
|
Published time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
// PageEntries is new-to-old list of Entry structs, used to create a feed page.
|
// PageEntries is new-to-old list of Entry structs, used to create a
|
||||||
// It should always be assumed to be sorted when used in other packages.
|
// subscriptions page.
|
||||||
// Sorted by post time, from newest to oldest.
|
// It should always be assumed to be sorted when used in other packages,
|
||||||
|
// by post time, from newest to oldest.
|
||||||
type PageEntries struct {
|
type PageEntries struct {
|
||||||
Entries []*PageEntry
|
Entries []*PageEntry
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package feeds
|
package subscriptions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
@ -31,15 +31,15 @@ var (
|
||||||
ErrNotFeed = errors.New("not a valid feed")
|
ErrNotFeed = errors.New("not a valid feed")
|
||||||
)
|
)
|
||||||
|
|
||||||
var writeMu = sync.Mutex{} // Prevent concurrent writes to feeds.json file
|
var writeMu = sync.Mutex{} // Prevent concurrent writes to subscriptions.json file
|
||||||
|
|
||||||
// LastUpdated is the time when the in-memory data was last updated.
|
// LastUpdated is the time when the in-memory data was last updated.
|
||||||
// It can be used to know if the feed page should be regenerated.
|
// It can be used to know if the subscriptions page should be regenerated.
|
||||||
var LastUpdated time.Time
|
var LastUpdated time.Time
|
||||||
|
|
||||||
// Init should be called after config.Init.
|
// Init should be called after config.Init.
|
||||||
func Init() error {
|
func Init() error {
|
||||||
f, err := os.Open(config.FeedPath)
|
f, err := os.Open(config.SubscriptionPath)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
// File exists and could be opened
|
// File exists and could be opened
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
@ -50,26 +50,26 @@ func Init() error {
|
||||||
dec := json.NewDecoder(f)
|
dec := json.NewDecoder(f)
|
||||||
err = dec.Decode(&data)
|
err = dec.Decode(&data)
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return fmt.Errorf("feeds.json is corrupted: %w", err) //nolint:goerr113
|
return fmt.Errorf("subscriptions.json is corrupted: %w", err) //nolint:goerr113
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if !os.IsNotExist(err) {
|
} else if !os.IsNotExist(err) {
|
||||||
// There's an error opening the file, but it's not bc is doesn't exist
|
// There's an error opening the file, but it's not bc is doesn't exist
|
||||||
return fmt.Errorf("open feeds.json error: %w", err) //nolint:goerr113
|
return fmt.Errorf("open subscriptions.json error: %w", err) //nolint:goerr113
|
||||||
}
|
}
|
||||||
|
|
||||||
LastUpdated = time.Now()
|
LastUpdated = time.Now()
|
||||||
|
|
||||||
if viper.GetInt("feeds.update_interval") > 0 {
|
if viper.GetInt("subscriptions.update_interval") > 0 {
|
||||||
// Update feeds and pages every so often
|
// Update subscriptions every so often
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
updateAll()
|
updateAll()
|
||||||
time.Sleep(time.Duration(viper.GetInt("feeds.update_interval")) * time.Second)
|
time.Sleep(time.Duration(viper.GetInt("subscriptions.update_interval")) * time.Second)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
} else {
|
} else {
|
||||||
// User disabled automatic feed/page updates
|
// User disabled automatic updates
|
||||||
// So just update once at the beginning
|
// So just update once at the beginning
|
||||||
go updateAll()
|
go updateAll()
|
||||||
}
|
}
|
||||||
|
@ -77,9 +77,10 @@ func Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsTracked returns true if the feed/page URL is already being tracked.
|
// IsSubscribed returns true if the URL is already subscribed to,
|
||||||
func IsTracked(url string) bool {
|
// whether a feed or page.
|
||||||
logger.Log.Println("feeds.IsTracked called")
|
func IsSubscribed(url string) bool {
|
||||||
|
logger.Log.Println("subscriptions.IsSubscribed called")
|
||||||
|
|
||||||
data.feedMu.RLock()
|
data.feedMu.RLock()
|
||||||
for u := range data.Feeds {
|
for u := range data.Feeds {
|
||||||
|
@ -103,7 +104,7 @@ func IsTracked(url string) bool {
|
||||||
// GetFeed returns a Feed object and a bool indicating whether the passed
|
// GetFeed returns a Feed object and a bool indicating whether the passed
|
||||||
// content was actually recognized as a feed.
|
// content was actually recognized as a feed.
|
||||||
func GetFeed(mediatype, filename string, r io.Reader) (*gofeed.Feed, bool) {
|
func GetFeed(mediatype, filename string, r io.Reader) (*gofeed.Feed, bool) {
|
||||||
logger.Log.Println("feeds.GetFeed called")
|
logger.Log.Println("subscriptions.GetFeed called")
|
||||||
|
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
|
@ -124,14 +125,14 @@ func GetFeed(mediatype, filename string, r io.Reader) (*gofeed.Feed, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeJSON() error {
|
func writeJSON() error {
|
||||||
logger.Log.Println("feeds.writeJSON called")
|
logger.Log.Println("subscriptions.writeJSON called")
|
||||||
|
|
||||||
writeMu.Lock()
|
writeMu.Lock()
|
||||||
defer writeMu.Unlock()
|
defer writeMu.Unlock()
|
||||||
|
|
||||||
f, err := os.OpenFile(config.FeedPath, os.O_WRONLY|os.O_CREATE, 0666)
|
f, err := os.OpenFile(config.SubscriptionPath, os.O_WRONLY|os.O_CREATE, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Println("feeds.writeJSON error", err)
|
logger.Log.Println("subscriptions.writeJSON error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
@ -140,12 +141,12 @@ func writeJSON() error {
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
|
|
||||||
data.Lock()
|
data.Lock()
|
||||||
logger.Log.Println("feeds.writeJSON acquired data lock")
|
logger.Log.Println("subscriptions.writeJSON acquired data lock")
|
||||||
err = enc.Encode(&data)
|
err = enc.Encode(&data)
|
||||||
data.Unlock()
|
data.Unlock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Log.Println("feeds.writeJSON error", err)
|
logger.Log.Println("subscriptions.writeJSON error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@ -155,7 +156,7 @@ func writeJSON() error {
|
||||||
// It can be used to update a feed for a URL, although the package
|
// It can be used to update a feed for a URL, although the package
|
||||||
// will handle that on its own.
|
// will handle that on its own.
|
||||||
func AddFeed(url string, feed *gofeed.Feed) error {
|
func AddFeed(url string, feed *gofeed.Feed) error {
|
||||||
logger.Log.Println("feeds.AddFeed called")
|
logger.Log.Println("subscriptions.AddFeed called")
|
||||||
|
|
||||||
if feed == nil {
|
if feed == nil {
|
||||||
panic("feed is nil")
|
panic("feed is nil")
|
||||||
|
@ -205,7 +206,7 @@ func AddFeed(url string, feed *gofeed.Feed) error {
|
||||||
// It can be used to update the page as well, although the package
|
// It can be used to update the page as well, although the package
|
||||||
// will handle that on its own.
|
// will handle that on its own.
|
||||||
func AddPage(url string, r io.Reader) error {
|
func AddPage(url string, r io.Reader) error {
|
||||||
logger.Log.Println("feeds.AddPage called")
|
logger.Log.Println("subscriptions.AddPage called")
|
||||||
|
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil
|
return nil
|
||||||
|
@ -241,7 +242,7 @@ func AddPage(url string, r io.Reader) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateFeed(url string) error {
|
func updateFeed(url string) error {
|
||||||
logger.Log.Println("feeds.updateFeed called")
|
logger.Log.Println("subscriptions.updateFeed called")
|
||||||
|
|
||||||
res, err := client.Fetch(url)
|
res, err := client.Fetch(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -268,7 +269,7 @@ func updateFeed(url string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func updatePage(url string) error {
|
func updatePage(url string) error {
|
||||||
logger.Log.Println("feeds.updatePage called")
|
logger.Log.Println("subscriptions.updatePage called")
|
||||||
|
|
||||||
res, err := client.Fetch(url)
|
res, err := client.Fetch(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -286,10 +287,10 @@ func updatePage(url string) error {
|
||||||
return AddPage(url, res.Body)
|
return AddPage(url, res.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateAll updates all feeds and pages using workers.
|
// updateAll updates all subscriptions using workers.
|
||||||
// It only returns once all the workers are done.
|
// It only returns once all the workers are done.
|
||||||
func updateAll() {
|
func updateAll() {
|
||||||
logger.Log.Println("feeds.updateAll called")
|
logger.Log.Println("subscriptions.updateAll called")
|
||||||
|
|
||||||
// TODO: Is two goroutines the right amount?
|
// TODO: Is two goroutines the right amount?
|
||||||
|
|
||||||
|
@ -318,7 +319,7 @@ func updateAll() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
numWorkers := viper.GetInt("feeds.workers")
|
numWorkers := viper.GetInt("subscriptions.workers")
|
||||||
if numWorkers < 1 {
|
if numWorkers < 1 {
|
||||||
numWorkers = 1
|
numWorkers = 1
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user