Converted RSS feed to be DB based
This commit is contained in:
parent
fa5f189cda
commit
88e0d5086c
@ -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)
|
||||||
}
|
}
|
||||||
|
115
cmd/data/rss.go
115
cmd/data/rss.go
@ -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
|
|
||||||
}
|
|
||||||
|
17
cmd/main.go
17
cmd/main.go
@ -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))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user