diff options
Diffstat (limited to 'cmd/web')
| -rw-r--r-- | cmd/web/handlers/export.go | 109 | ||||
| -rw-r--r-- | cmd/web/handlers/routes.go | 7 | ||||
| -rw-r--r-- | cmd/web/main.go | 1 |
3 files changed, 117 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>`)) +} diff --git a/cmd/web/handlers/routes.go b/cmd/web/handlers/routes.go index be48ae3..1c14705 100644 --- a/cmd/web/handlers/routes.go +++ b/cmd/web/handlers/routes.go @@ -27,6 +27,12 @@ func RegisterEndpoints(app types.Application, db *sql.DB) *http.ServeMux { err: app.Err, db: db, } + constructor := rssExportContext{ + err: app.Err, + db: db, + + serv: app.Env.Serv, + } audio := fsContext{ err: app.Err, path: app.AudioDir, @@ -48,6 +54,7 @@ func RegisterEndpoints(app types.Application, db *sql.DB) *http.ServeMux { blogRouter.HandleFunc("/feeds", auth.CheckAndInvalidate(feeds.index)) blogRouter.HandleFunc("/feeds/new", auth.Resolve(feeds.new)) blogRouter.HandleFunc("/feed", feeds.feed) + blogRouter.HandleFunc("/feed.rss", constructor.feed) blogRouter.HandleFunc("/audio", audio.readdir) blogRouter.HandleFunc("/audio/get", audio.get) diff --git a/cmd/web/main.go b/cmd/web/main.go index 00286b8..d4deaff 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -43,6 +43,7 @@ func main() { if err != nil { app.Env.AppPort = 5005 } + app.Env.Serv = os.Getenv("serv") connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", app.Env.Db.Host, |
