diff options
Diffstat (limited to 'cmd/web/handlers/export.go')
| -rw-r--r-- | cmd/web/handlers/export.go | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/cmd/web/handlers/export.go b/cmd/web/handlers/export.go new file mode 100644 index 0000000..becdae8 --- /dev/null +++ b/cmd/web/handlers/export.go @@ -0,0 +1,109 @@ +package handlers + +import ( + "database/sql" + "encoding/xml" + "log" + "net/http" + "strconv" + "strings" + "time" + + "golang.org/x/net/html" + + "paterissa.net/mblog/internal/models" +) + +type Item struct { + XMLName xml.Name `xml:"item"` + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + PubDate string `xml:"pubDate"` + Content string `xml:"content:encoded"` +} + +type Channel struct { + XMLName xml.Name `xml:"channel"` + Title string `xml:"title"` + Link string `xml:"link"` + Description string `xml:"description"` + Items []Item `xml:"item"` +} + +type rssExportContext struct { + err *log.Logger + db *sql.DB + + serv string +} + +func (ctx *rssExportContext) feed(w http.ResponseWriter, r *http.Request) { + feed := &Channel{ + Title: "Paterissa", + Link: ctx.serv, + Description: "Blog feed", + } + + rows, err := ctx.db.Query("SELECT p.id, u.name, p.time, p.brief, p.content FROM posts p INNER JOIN logins u ON p.user_id = u.id ORDER BY p.id DESC LIMIT 20;") + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal Error")) + ctx.err.Printf("Could not load posts from DB: %v\n", err) + return + } + defer rows.Close() + + for rows.Next() { + var p models.Post + + if err = rows.Scan(&p.Id, &p.Name, &p.Time, &p.Brief, &p.Content); err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal Error")) + ctx.err.Printf("Could not load posts from DB: %v\n", err) + return + } + + p.FormattedTime = p.Time.Format(time.ANSIC) + + title := "" + z := html.NewTokenizer(strings.NewReader(string(p.Brief))) + + for { + tt := z.Next() + + if tt == html.ErrorToken { + break + } else if tt == html.StartTagToken { + tag := z.Token() + + if tag.Data == "h1" { + if tt = z.Next(); tt == html.TextToken { + title = z.Token().Data + } + } + } + } + + brief := html.EscapeString(string(p.Brief)) + content := html.EscapeString(string(p.Content)) + + feed.Items = append(feed.Items, Item{ + Title: title, + Link: ctx.serv + "/post?id=" + strconv.Itoa(p.Id), + Description: brief, + PubDate: p.FormattedTime, + Content: content, + }) + } + + out, err := xml.MarshalIndent(feed, "", " ") + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal Error")) + ctx.err.Printf("Could not create RSS feed: %v\n", err) + return + } + + w.Write([]byte(xml.Header + `<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">` + string(out) + `</rss>`)) +} |
