// Copyright (C) 2021 nytpu // SPDX-License-Identifier: AGPL-3.0-only // 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" "io/ioutil" "os" "path/filepath" "sort" "time" "golang.nytpu.com/comitium/localizations" ) // 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()) } // genDay returns a string with the current date and time func genDay() string { return TranslateString("%s\n", "files.generated_on", &localizations.Replacements{"date": time.Now().Format("2006-01-02 at 15:04 MST")}) } // agplCompliance returns a string containing a footer linking to the source code func agplCompilance() string { return TranslateString("\n\n---\n\n=> https://git.nytpu.com/comitium/about/ %s\n", "files.comitium_footer", &localizations.Replacements{"version": Version, "commit": Commit}) } func (d *FullData) WriteSubs(dataPath string) error { path := filepath.Join(dataPath, "subscriptions.gmi.new") rawPage := TranslateString("# %s\n\n", "files.subscriptions_subscribed_feeds", nil) rawPage += genDay() rawPage += TranslateString("\n\n## %s\n\n", "files.subscriptions_feeds_title", nil) rawPage += TranslateString("%s\n\n\n", "files.subscriptions_feeds_subtitle", nil) d.FeedsMu.RLock() for _, v := range d.Feeds { var link string if v.FeedLink != "" { link = v.FeedLink } else { link = v.Link } rawPage += fmt.Sprintf("=> %v %v\n", link, v.Title) } d.FeedsMu.RUnlock() rawPage += TranslateString("\n\n## %s\n\n", "files.subscriptions_pages_title", nil) rawPage += TranslateString("%s\n\n\n", "files.subscriptions_pages_subtitle", nil) d.PagesMu.RLock() for _, v := range d.Pages { rawPage += fmt.Sprintf("=> %v", v.Link) if v.Title != "" { rawPage += fmt.Sprintf(" %v", v.Title) } rawPage += "\n" } d.PagesMu.RUnlock() rawPage += agplCompilance() err := ioutil.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 } func (d *FullData) WriteFeed(dataPath string) error { path := filepath.Join(dataPath, "feed.gmi.new") rawPage := Header d.RLock() pe := d.getPageEntries() rawPage += TranslateString("\n=> subscriptions.gmi %s\n\n", "files.feed_subscriptions_link", &localizations.Replacements{"num": len(d.Feeds) + len(d.Pages)}) d.RUnlock() rawPage += genDay() 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\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) } } } rawPage += agplCompilance() err := ioutil.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, "feed.gmi")) return err }