all repos — flounder @ bae10cb7517fdbe207275c9c03e5a4245ee588de

A small site builder for the Gemini protocol

Very early working prototype of feed getter
alex wennerberg alex@alexwennerberg.com
Wed, 27 Jan 2021 17:51:06 -0800
commit

bae10cb7517fdbe207275c9c03e5a4245ee588de

parent

adce4038a08103cb7a2c2c7a0f093b16fe16b647

4 files changed, 69 insertions(+), 15 deletions(-)

jump to
M admin.goadmin.go

@@ -108,6 +108,7 @@ os.Mkdir(path.Join(c.FilesDirectory, username), os.ModePerm)

ioutil.WriteFile(path.Join(c.FilesDirectory, username, "index.gmi"), []byte(baseIndex), 0644) os.Mkdir(path.Join(c.FilesDirectory, username), os.ModePerm) if c.SMTPUsername != "" { + // TODO move into work queue SendEmail(email, "Welcome to Flounder!", fmt.Sprintf(` Hi %s, Welcome to Flounder! You can now log into your account at https://flounder.online/login -- For more information about
M feed.gofeed.go

@@ -4,8 +4,11 @@ import (

"bufio" "fmt" "github.com/mmcdole/gofeed" + "log" "os" "path" + "sort" + "time" ) const followingPath = "following.txt"

@@ -13,33 +16,82 @@ const followingFile = "following.gmi"

// TODO also get gemini, gemfeed -func getAllFeeds(user string) error { +func feedsWorker() { + log.Println("Starting feeds worker") + for { + users, err := getActiveUserNames() + if err != nil { + // Handle error somehow + fmt.Println(err) + continue + } + for _, user := range users { + writeAllFeeds(user) + } + time.Sleep(time.Hour * 24) + } +} + +func writeAllFeeds(user string) error { // Open file file, err := os.Open(path.Join(getUserDirectory(user), followingPath)) if err != nil { + if os.IsNotExist(err) { + // TODO + return nil + } return err } + log.Println("Writing feeds for user " + user) defer file.Close() + feedData := []*gofeed.Feed{} scanner := bufio.NewScanner(file) for scanner.Scan() { feedURL := scanner.Text() - // if scheme is gemini and filetype is gemini... gemtext - // if scheme is gemini and filetype is xml/rss... fetch data and parse + // TODO if scheme is gemini and filetype is gemini... gemtext + // TODO if scheme is gemini and filetype is xml/rss... fetch data and parse + // TODO rate limit etc fp := gofeed.NewParser() - fp.ParseURL(feedURL) + feed, err := fp.ParseURL(feedURL) + if err != nil { + log.Println("Error getting feed " + feedURL) + } else { + log.Println("Got feed data from " + feedURL) + feedData = append(feedData, feed) + } } if err := scanner.Err(); err != nil { return err + } + // Aggregate and sort by date + type feedPlusItem struct { + Feed *gofeed.Feed + FeedItem *gofeed.Item } data := struct { - DayContent []struct { - date string - feed *gofeed.Feed - feedItems []gofeed.Item - } + FeedItems []feedPlusItem }{} - fmt.Println(data) + for _, feed := range feedData { + for _, item := range feed.Items { + if item.PublishedParsed != nil { + data.FeedItems = append(data.FeedItems, feedPlusItem{feed, item}) + } + } + } + sort.Slice(data.FeedItems, func(i, j int) bool { + return data.FeedItems[i].FeedItem.PublishedParsed.After(*data.FeedItems[j].FeedItem.PublishedParsed) + }) + + outputf, err := os.OpenFile(path.Join(getUserDirectory(user), followingFile), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755) + if err != nil { + return err + } + err = gt.ExecuteTemplate(outputf, "following.gmi", data) + if err != nil { + return err + } + defer outputf.Close() // convert to gemini template // write template to file return nil
M main.gomain.go

@@ -39,13 +39,14 @@ initializeDB()

cookie := generateCookieKeyIfDNE() SessionStore = sessions.NewCookieStore(cookie) + // load domains in memory + refreshDomainMap() + // Background workers if c.AnalyticsDBFile != "" { go dumpLogsWorker() } - - // load domains in memory - refreshDomainMap() + go feedsWorker() switch args[0] { case "serve":
M templates/following.gmitemplates/following.gmi

@@ -1,3 +1,3 @@

-# {{.User}} Following - +{{ range .FeedItems }} +=> {{.FeedItem.Link}} {{.FeedItem.Published}} {{.Feed.Title}} -- {{.FeedItem.Title}}{{ end }}