atom/atom.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package atom import ( "bufio" "fmt" "log" "net/http" "os" "path/filepath" "sort" "strings" "time" ) const maxFeed = 10 var timeLayoutPost = "2006-01-02" var timeLayoutAtom = "2006-01-02T15:04:05.000Z" type post struct { title string updated string link string // starting with content disabled because a lot of my content is nonsensical // to any reasonable xml parser tbh // content string } func Handler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/atom+xml") posts, err := getPosts("thought/*") if err != nil { log.Println(err) } sort.Slice(posts, func(i, j int) bool { // we assume that timeLayoutAtom is correct here because // it was passed up correctly hopefully ti, _ := time.Parse(timeLayoutAtom, posts[i].updated) tj, _ := time.Parse(timeLayoutAtom, posts[j].updated) return ti.After(tj) }) if len(posts) > maxFeed { posts = posts[:maxFeed] } var updated string if len(posts) > 0 { updated = posts[0].updated } fmt.Fprintf(w, `<?xml version="1.0" encoding="utf-8"?> <feed xmlns="http://www.w3.org/2005/Atom"> <title>j3s.sh</title> <link rel="self" href="https://j3s.sh/feed.atom" /> <link href="https://j3s.sh/" /> <updated>%s</updated> <author> <name>Jes Olson</name> </author> <id>https://j3s.sh/</id> `, updated) for _, p := range posts { // add content in future? idk prob not fmt.Fprintf(w, ` <entry> <title>%s</title> <link href="%s"/> <id>%s</id> <updated>%s</updated> </entry> `, p.title, p.link, p.link, p.updated) } fmt.Fprint(w, ` </feed>`) } func getPosts(dir string) ([]post, error) { var posts []post files, err := filepath.Glob(dir) if err != nil { return nil, err } for _, f := range files { post, err := fileToPost(f) if err != nil { // this can be failed intentionally for drafts or posts too small for rss updoots // add a print statement here if blog posts mysteriously vanish from the atom feed // // lmao continue } posts = append(posts, post) } return posts, err } func fileToPost(file string) (post, error) { var p post f, err := os.Open(file) if err != nil { return p, err } defer f.Close() scanner := bufio.NewScanner(f) scanner.Scan() // this moves to the next token // strip spaces title := scanner.Text() p.title = strings.TrimSpace(title) scanner.Scan() timestr := strings.TrimSpace(scanner.Text()) updated, err := time.Parse(timeLayoutPost, timestr) if err != nil { return p, err } // for scanner.Scan() { // p.content = p.content + scanner.Text() // } p.updated = updated.Format(timeLayoutAtom) p.link = "https://j3s.sh/" + file return p, err }