aboutsummaryrefslogtreecommitdiff
path: root/cmd/web
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/web')
-rw-r--r--cmd/web/handlers/export.go109
-rw-r--r--cmd/web/handlers/routes.go7
-rw-r--r--cmd/web/main.go1
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,