Converted RSS feed to be DB based

This commit is contained in:
Jason Streifling 2024-03-09 10:12:46 +01:00
parent fa5f189cda
commit 88e0d5086c
5 changed files with 88 additions and 136 deletions

View File

@ -258,13 +258,13 @@ func (db *DB) GetArticle(id int64) (*Article, error) {
return article, nil return article, nil
} }
func (db *DB) GetUnpublishedArticles() ([]*Article, error) { func (db *DB) GetCertainArticles(published bool) ([]*Article, error) {
query := ` query := `
SELECT id, title, created, description, content, author_id SELECT id, title, created, description, content, author_id
FROM articles FROM articles
WHERE published = ? WHERE published = ?
` `
rows, err := db.Query(query, false) rows, err := db.Query(query, published)
if err != nil { if err != nil {
return nil, fmt.Errorf("error querying articles: %v", err) return nil, fmt.Errorf("error querying articles: %v", err)
} }

View File

@ -1,104 +1,49 @@
package data package data
import ( import (
"encoding/gob"
"fmt" "fmt"
"os" "time"
"sync"
"git.streifling.com/jason/rss" "git.streifling.com/jason/rss"
) )
type Channel struct { func GetChannel(db *DB, title, link, desc string) (*rss.Channel, error) {
addCh chan *rss.Item channel := &rss.Channel{
setCh chan rss.Channel
getCh chan rss.Channel
channel rss.Channel
wg sync.WaitGroup
}
func initChannel() *Channel {
return &Channel{
addCh: make(chan *rss.Item),
setCh: make(chan rss.Channel),
getCh: make(chan rss.Channel),
channel: rss.Channel{
Items: make([]*rss.Item, 0),
},
}
}
func (c *Channel) start() {
c.wg.Done()
for {
select {
case item := <-c.addCh:
c.channel.Items = append(c.channel.Items, item)
case c.getCh <- c.channel:
case c.channel = <-c.setCh:
}
}
}
func NewChannel(title, link, desc string) *Channel {
channel := initChannel()
channel.channel = rss.Channel{
Title: title, Title: title,
Link: link, Link: link,
Description: desc, Description: desc,
Items: make([]*rss.Item, 0),
} }
channel.wg.Add(1) articles, err := db.GetCertainArticles(true)
go channel.start()
channel.wg.Wait()
return channel
}
func (c *Channel) Get() rss.Channel {
return <-c.getCh
}
func (f *Channel) Set(channel rss.Channel) {
f.setCh <- channel
}
func LoadChannel(filename string) (*Channel, error) {
file, err := os.Open(filename)
if err != nil { if err != nil {
return nil, fmt.Errorf("error opening file %v: %v", filename, err) return nil, fmt.Errorf("error fetching published articles: %v", err)
}
defer file.Close()
tmpChannel := new(rss.Channel)
if err = gob.NewDecoder(file).Decode(tmpChannel); err != nil {
return nil, fmt.Errorf("error decoding channel from file %v: %v", filename, err)
} }
channel := initChannel() for _, article := range articles {
channel.wg.Add(1) tags, err := db.GetArticleTags(article.ID)
go channel.start() if err != nil {
channel.wg.Wait() return nil, fmt.Errorf("error fetching tags for article %v: %v", article.Title, err)
channel.Set(*tmpChannel) }
tagNames := make([]string, 0)
for _, tag := range tags {
tagNames = append(tagNames, tag.Name)
}
user, err := db.GetUser(article.AuthorID)
if err != nil {
return nil, fmt.Errorf("error finding user %v: %v", article.AuthorID, err)
}
channel.Items = append(channel.Items, &rss.Item{
Title: article.Title,
Author: user.FirstName + user.LastName,
PubDate: article.Created.Format(time.RFC1123Z),
Description: article.Desc,
Content: &rss.Content{Value: article.Content},
Categories: tagNames,
})
}
return channel, nil return channel, nil
} }
func (c *Channel) Save(filename string) error {
file, err := os.Create(filename)
if err != nil {
return fmt.Errorf("error creating file %v: %v", filename, err)
}
defer file.Close()
channel := c.Get()
if err = gob.NewEncoder(file).Encode(channel); err != nil {
return fmt.Errorf("error encoding file %v: %v", filename, err)
}
return nil
}
func (c *Channel) Add(i *rss.Item) {
c.addCh <- i
}

View File

@ -29,14 +29,6 @@ func main() {
} }
defer db.Close() defer db.Close()
feed, err := data.LoadChannel("tmp/rss.gob")
if err != nil {
log.Println(err)
feed = data.NewChannel("Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt",
"https://distrikt-ni-st.de",
"Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität")
}
key, err := data.LoadKey("tmp/key.gob") key, err := data.LoadKey("tmp/key.gob")
if err != nil { if err != nil {
key, err = data.NewKey() key, err = data.NewKey()
@ -55,7 +47,12 @@ func main() {
mux.HandleFunc("GET /create-tag/", ui.CreateTag) mux.HandleFunc("GET /create-tag/", ui.CreateTag)
mux.HandleFunc("GET /create-user/", ui.CreateUser) mux.HandleFunc("GET /create-user/", ui.CreateUser)
mux.HandleFunc("GET /hub/", ui.ShowHub(store)) mux.HandleFunc("GET /hub/", ui.ShowHub(store))
mux.HandleFunc("GET /rss/", ui.ShowRSS(feed)) mux.HandleFunc("GET /rss/", ui.ShowRSS(
db,
"Freimaurer Distrikt Niedersachsen und Sachsen-Anhalt",
"https://distrikt-ni-st.de",
"Freiheit, Gleichheit, Brüderlichkeit, Toleranz und Humanität",
))
mux.HandleFunc("GET /unpublished-articles/", ui.ShowUnpublishedArticles(db)) mux.HandleFunc("GET /unpublished-articles/", ui.ShowUnpublishedArticles(db))
mux.HandleFunc("GET /write-article/", ui.WriteArticle(db)) mux.HandleFunc("GET /write-article/", ui.WriteArticle(db))
@ -64,7 +61,7 @@ func main() {
mux.HandleFunc("POST /finish-article/", ui.FinishArticle(db, store)) mux.HandleFunc("POST /finish-article/", ui.FinishArticle(db, store))
mux.HandleFunc("POST /login/", ui.Login(db, store)) mux.HandleFunc("POST /login/", ui.Login(db, store))
mux.HandleFunc("POST /review-article/", ui.ReviewArticle(db, store)) mux.HandleFunc("POST /review-article/", ui.ReviewArticle(db, store))
mux.HandleFunc("POST /publish-article/", ui.PublishArticle(db, feed, store)) mux.HandleFunc("POST /publish-article/", ui.PublishArticle(db, store))
log.Fatalln(http.ListenAndServe(":8080", mux)) log.Fatalln(http.ListenAndServe(":8080", mux))
} }

View File

@ -5,9 +5,7 @@ import (
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
"time"
"git.streifling.com/jason/rss"
"streifling.com/jason/cpolis/cmd/data" "streifling.com/jason/cpolis/cmd/data"
) )
@ -105,7 +103,7 @@ func FinishArticle(db *data.DB, s *data.CookieStore) http.HandlerFunc {
func ShowUnpublishedArticles(db *data.DB) http.HandlerFunc { func ShowUnpublishedArticles(db *data.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
articles, err := db.GetUnpublishedArticles() articles, err := db.GetCertainArticles(false)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
@ -145,7 +143,7 @@ func ReviewArticle(db *data.DB, s *data.CookieStore) http.HandlerFunc {
} }
} }
func PublishArticle(db *data.DB, c *data.Channel, s *data.CookieStore) http.HandlerFunc { func PublishArticle(db *data.DB, s *data.CookieStore) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(r.PostFormValue("id"), 10, 64) id, err := strconv.ParseInt(r.PostFormValue("id"), 10, 64)
if err != nil { if err != nil {
@ -154,18 +152,6 @@ func PublishArticle(db *data.DB, c *data.Channel, s *data.CookieStore) http.Hand
return return
} }
if err = db.UpdateAttribute("articles", id, "published", true); err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
article, err := db.GetArticle(id)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
session, err := s.Get(r, "cookie") session, err := s.Get(r, "cookie")
if err != nil { if err != nil {
tmpl, err := template.ParseFiles("web/templates/login.html") tmpl, err := template.ParseFiles("web/templates/login.html")
@ -173,26 +159,7 @@ func PublishArticle(db *data.DB, c *data.Channel, s *data.CookieStore) http.Hand
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg) template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
} }
tags, err := db.GetArticleTags(article.ID) db.UpdateAttribute("articles", id, "published", true)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tagNames := make([]string, 0)
for _, tag := range tags {
tagNames = append(tagNames, tag.Name)
}
c.Add(&rss.Item{
Title: article.Title,
Author: session.Values["name"].(string),
PubDate: article.Created.Format(time.RFC1123Z),
Description: article.Desc,
Content: &rss.Content{Value: article.Content},
Categories: tagNames,
})
c.Save("tmp/rss.gob")
tmpl, err := template.ParseFiles("web/templates/hub.html") tmpl, err := template.ParseFiles("web/templates/hub.html")
tmpl = template.Must(tmpl, err) tmpl = template.Must(tmpl, err)

View File

@ -4,16 +4,59 @@ import (
"html/template" "html/template"
"log" "log"
"net/http" "net/http"
"time"
"git.streifling.com/jason/rss" "git.streifling.com/jason/rss"
"streifling.com/jason/cpolis/cmd/data" "streifling.com/jason/cpolis/cmd/data"
) )
func ShowRSS(c *data.Channel) http.HandlerFunc { func ShowRSS(db *data.DB, title, link, desc string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
channel := c.Get() channel := &rss.Channel{
Title: title,
Link: link,
Description: desc,
Items: make([]*rss.Item, 0),
}
articles, err := db.GetCertainArticles(true)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
for _, article := range articles {
tags, err := db.GetArticleTags(article.ID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
tagNames := make([]string, 0)
for _, tag := range tags {
tagNames = append(tagNames, tag.Name)
}
user, err := db.GetUser(article.AuthorID)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
channel.Items = append(channel.Items, &rss.Item{
Title: article.Title,
Author: user.FirstName + user.LastName,
PubDate: article.Created.Format(time.RFC1123Z),
Description: article.Desc,
Content: &rss.Content{Value: article.Content},
Categories: tagNames,
})
}
feed := rss.NewFeed() feed := rss.NewFeed()
feed.Channels = append(feed.Channels, &channel) feed.Channels = append(feed.Channels, channel)
rss, err := feed.ToXML() rss, err := feed.ToXML()
if err != nil { if err != nil {
log.Println(err) log.Println(err)