From b4d303e24ef7c16ff9ba6bdeab704783040a770e Mon Sep 17 00:00:00 2001 From: nytpu Date: Thu, 18 Mar 2021 16:28:02 -0600 Subject: [PATCH] Write subscriptions --- comitium.go | 12 +++++- core/entries.go | 109 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 core/entries.go diff --git a/comitium.go b/comitium.go index 8e9c003..1dc25d8 100644 --- a/comitium.go +++ b/comitium.go @@ -57,6 +57,11 @@ func main() { case "refresh": argCheck(c.Args(), 0, false, "'refresh' doesn't take an argument!") fetch.RefreshAll(&core.Data, *refreshWorkersFlag) + err = core.Data.WriteSubs(dataPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error saving subscriptions: %v\n", err) + os.Exit(1) + } case "list": argCheck(c.Args(), 0, false, "'list' doesn't take an argument!") core.Data.Export(os.Stdout) @@ -78,6 +83,11 @@ func main() { fmt.Fprintf(os.Stderr, "Error adding URL: %v\n", err) os.Exit(1) } + err = core.Data.WriteSubs(dataPath) + if err != nil { + fmt.Fprintf(os.Stderr, "Error saving subscriptions: %v\n", err) + os.Exit(1) + } case "remove": argCheck(c.Args(), 1, true, "Please provide a URL to remove.") delete(core.Data.Feeds, c.Arg(0)) @@ -86,7 +96,7 @@ func main() { err = core.Data.WriteJSON(dataPath) if err != nil { - fmt.Fprintf(os.Stderr, "Error saving subscriptions: %v\n", err) + fmt.Fprintf(os.Stderr, "Error saving subscriptions json: %v\n", err) os.Exit(1) } } diff --git a/core/entries.go b/core/entries.go new file mode 100644 index 0000000..fb9ab25 --- /dev/null +++ b/core/entries.go @@ -0,0 +1,109 @@ +// Copyright (C) 2021 nytpu +// SPDX-License-Identifier: AGPL-3.0-or-later +// For more license details, see LICENSE or . + +// This file incorporates code from makeworld's amfora: +// https://github.com/makeworld-the-better-one/amfora/blob/master/subscriptions/structs.go +// Original source is Copyright 2020 makeworld and is licensed under the +// terms of the GNU General Public License Version 3.0. +// https://www.gnu.org/licenses/gpl-3.0-standalone.html + +package core + +import ( + "fmt" + "os" + "path/filepath" + "sort" + "time" +) + +// getPageEntries returns a full list of page entries from a FullData. It will +// always be sorted from newest to oldest. +func (d *FullData) getPageEntries() *PageEntries { + var pe PageEntries + + d.RLock() + for _, feed := range d.Feeds { + for _, item := range feed.Items { + // Ignore items without links + if item.Link == "" { + continue + } + + var prefix string + if feed.Title != "" { + prefix = feed.Title + } else { + prefix = feed.Link + } + pe.Entries = append(pe.Entries, &PageEntry{ + Prefix: prefix, + Title: item.Title, + Published: item.Published, + URL: item.Link, + }) + } + } + for _, page := range d.Pages { + var prefix string + if page.Title != "" { + prefix = page.Title + } else { + prefix = page.Link + } + pe.Entries = append(pe.Entries, &PageEntry{ + Prefix: prefix, + Published: page.Updated, + URL: page.Link, + }) + } + d.RUnlock() + + sort.Sort(&pe) + return &pe +} + +// toLocalDay truncates the provided time to a date only, but converts to the +// local time first. +func toLocalDay(t time.Time) time.Time { + t = t.Local() + return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) +} + +func (d *FullData) WriteSubs(dataPath string) error { + path := filepath.Join(dataPath, "subscriptions.gmi.new") + + d.RLock() + pe := d.getPageEntries() + d.RUnlock() + + rawPage := "# Subscriptions" + + if len(pe.Entries) > 0 { + curDay := toLocalDay(pe.Entries[0].Published) + rawPage += fmt.Sprintf("\n\n## %s\n\n", curDay.Format("2006-01-02")) + for _, entry := range pe.Entries { + // get just the date it was published + pub := toLocalDay(entry.Published) + if pub.Before(curDay) { + curDay = pub + rawPage += fmt.Sprintf("\n## %s\n\n", curDay.Format("2006-01-02")) + } + + if entry.Title == "" { + rawPage += fmt.Sprintf("=> %s %s\n", entry.URL, entry.Prefix) + } else { + rawPage += fmt.Sprintf("=> %s %s — %s\n", entry.URL, entry.Prefix, entry.Title) + } + } + } + + err := os.WriteFile(path, []byte(rawPage), 0666) + if err != nil { + return err + } + // if full write was successful then overwrite original + err = os.Rename(path, filepath.Join(dataPath, "subscriptions.gmi")) + return err +}