all repos — flounder @ bae10cb7517fdbe207275c9c03e5a4245ee588de

A small site builder for the Gemini protocol

feed.go (view raw)

 1package main
 2
 3import (
 4	"bufio"
 5	"fmt"
 6	"github.com/mmcdole/gofeed"
 7	"log"
 8	"os"
 9	"path"
10	"sort"
11	"time"
12)
13
14const followingPath = "following.txt"
15const followingFile = "following.gmi"
16
17// TODO also get gemini, gemfeed
18
19func feedsWorker() {
20	log.Println("Starting feeds worker")
21	for {
22		users, err := getActiveUserNames()
23		if err != nil {
24			// Handle error somehow
25			fmt.Println(err)
26			continue
27		}
28		for _, user := range users {
29			writeAllFeeds(user)
30		}
31		time.Sleep(time.Hour * 24)
32	}
33}
34
35func writeAllFeeds(user string) error {
36	// Open file
37	file, err := os.Open(path.Join(getUserDirectory(user), followingPath))
38	if err != nil {
39		if os.IsNotExist(err) {
40			// TODO
41			return nil
42		}
43		return err
44	}
45	log.Println("Writing feeds for user " + user)
46	defer file.Close()
47
48	feedData := []*gofeed.Feed{}
49	scanner := bufio.NewScanner(file)
50	for scanner.Scan() {
51		feedURL := scanner.Text()
52		// TODO if scheme is gemini and filetype is gemini... gemtext
53		// TODO if scheme is gemini and filetype is xml/rss... fetch data  and parse
54		// TODO rate limit etc
55		fp := gofeed.NewParser()
56		feed, err := fp.ParseURL(feedURL)
57		if err != nil {
58			log.Println("Error getting feed " + feedURL)
59		} else {
60			log.Println("Got feed data from " + feedURL)
61			feedData = append(feedData, feed)
62		}
63	}
64	if err := scanner.Err(); err != nil {
65		return err
66	}
67	// Aggregate and sort by date
68	type feedPlusItem struct {
69		Feed     *gofeed.Feed
70		FeedItem *gofeed.Item
71	}
72	data := struct {
73		FeedItems []feedPlusItem
74	}{}
75	for _, feed := range feedData {
76		for _, item := range feed.Items {
77			if item.PublishedParsed != nil {
78				data.FeedItems = append(data.FeedItems, feedPlusItem{feed, item})
79			}
80		}
81	}
82	sort.Slice(data.FeedItems, func(i, j int) bool {
83		return data.FeedItems[i].FeedItem.PublishedParsed.After(*data.FeedItems[j].FeedItem.PublishedParsed)
84	})
85
86	outputf, err := os.OpenFile(path.Join(getUserDirectory(user), followingFile), os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
87	if err != nil {
88		return err
89	}
90	err = gt.ExecuteTemplate(outputf, "following.gmi", data)
91	if err != nil {
92		return err
93	}
94	defer outputf.Close()
95	// convert to gemini template
96	// write template to file
97	return nil
98}