Recently Written · git

recentlywritten

my writings (done recently)

git clone https://github.com/equwal/recentlywritten

Log | Files | Refs


accounts/feed.go (2460 bytes)

1 package main
2 
3 import (
4 	"encoding/xml"
5 	"io"
6 	"time"
7 )
8 
9 // The rss types give the RSS 2.0 shape. encoding/xml does the escaping.
10 type rss struct {
11 	XMLName xml.Name `xml:"rss"`
12 	Version string   `xml:"version,attr"`
13 	Channel channel  `xml:"channel"`
14 }
15 
16 type channel struct {
17 	Title       string `xml:"title"`
18 	Link        string `xml:"link"`
19 	Description string `xml:"description"`
20 	Language    string `xml:"language"`
21 	Items       []item `xml:"item"`
22 }
23 
24 type item struct {
25 	Title       string   `xml:"title"`
26 	Link        string   `xml:"link"`
27 	GUID        guid     `xml:"guid"`
28 	PubDate     string   `xml:"pubDate,omitempty"`
29 	Categories  []string `xml:"category"`
30 	Description string   `xml:"description"`
31 }
32 
33 type guid struct {
34 	IsPermaLink string `xml:"isPermaLink,attr"`
35 	Value       string `xml:",chardata"`
36 }
37 
38 // feedSize is the number of items in a private feed.
39 const feedSize = 20
40 
41 // buildFeed makes the private feed for a user who muted the tags in muted.
42 // body returns the HTML body of a post.
43 func buildFeed(baseURL string, posts []Post, muted map[string]bool, body func(slug string) string) channel {
44 	ch := channel{
45 		Title:       "Recently Written",
46 		Link:        baseURL + "/",
47 		Description: "A site full of things which I have recently written.",
48 		Language:    "en-us",
49 	}
50 	for _, p := range posts {
51 		if len(ch.Items) == feedSize {
52 			break
53 		}
54 		if !wanted(p, muted) {
55 			continue
56 		}
57 		url := baseURL + "/" + p.Slug + ".html"
58 		ch.Items = append(ch.Items, item{
59 			Title:       p.Title,
60 			Link:        url,
61 			GUID:        guid{IsPermaLink: "true", Value: url},
62 			PubDate:     feedDate(p.Date),
63 			Categories:  p.Tags,
64 			Description: body(p.Slug),
65 		})
66 	}
67 	return ch
68 }
69 
70 // feedDate gives the RFC 822 date that RSS requires, in the format that
71 // build.sh uses. A date that does not parse gives an empty string, and the
72 // item then has no pubDate.
73 func feedDate(d string) string {
74 	t, err := time.Parse("2006-01-02", d)
75 	if err != nil {
76 		return ""
77 	}
78 	return t.Format(time.RFC1123Z)
79 }
80 
81 // writeFeed writes ch as an RSS 2.0 document. encoding/xml escapes the
82 // text and replaces each character that XML 1.0 does not permit.
83 func writeFeed(w io.Writer, ch channel) error {
84 	if _, err := io.WriteString(w, xml.Header); err != nil {
85 		return err
86 	}
87 	enc := xml.NewEncoder(w)
88 	enc.Indent("", "  ")
89 	if err := enc.Encode(rss{Version: "2.0", Channel: ch}); err != nil {
90 		return err
91 	}
92 	_, err := io.WriteString(w, "\n")
93 	return err
94 }