Compare commits
29 Commits
21170c9cc2
...
new_rss
Author | SHA1 | Date | |
---|---|---|---|
93bc38db67 | |||
b74036343f | |||
45036fe286 | |||
8f7ac979a3 | |||
2da17014e4 | |||
4e2cae74bb | |||
4b5929911e | |||
f59321b9c6 | |||
cba3c663c9 | |||
59029c86a9 | |||
8f5739fb68 | |||
49988edd82 | |||
36f7a92a06 | |||
f716e9f0b5 | |||
f3c8cd6fa5 | |||
280e88a526 | |||
8ef6b6472d | |||
2e08600814 | |||
068bf045a7 | |||
96fe38726c | |||
75a21eeb9f | |||
6020b24e44 | |||
ebfe01069c | |||
5d41543543 | |||
2ccc9c7397 | |||
c5623fe4fd | |||
ee04a2a351 | |||
aa034701df | |||
ad9bfb2439 |
@ -11,12 +11,12 @@ import (
|
||||
)
|
||||
|
||||
type Article struct {
|
||||
Tags *TagList
|
||||
Title string
|
||||
Author string
|
||||
Created time.Time
|
||||
Desc string
|
||||
Content string
|
||||
Tags []string
|
||||
UUID uuid.UUID
|
||||
AuthorID int64
|
||||
}
|
||||
@ -37,7 +37,7 @@ type TagList struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func initArticleList() *ArticleList {
|
||||
func minArticleList() *ArticleList {
|
||||
return &ArticleList{
|
||||
addCh: make(chan *Article),
|
||||
delCh: make(chan uuid.UUID),
|
||||
@ -46,7 +46,7 @@ func initArticleList() *ArticleList {
|
||||
}
|
||||
}
|
||||
|
||||
func initTagList() *TagList {
|
||||
func minTagList() *TagList {
|
||||
return &TagList{
|
||||
addCh: make(chan string),
|
||||
getCh: make(chan []string),
|
||||
@ -89,7 +89,7 @@ func (tl *TagList) start() {
|
||||
}
|
||||
|
||||
func NewArticleList() *ArticleList {
|
||||
list := initArticleList()
|
||||
list := minArticleList()
|
||||
list.articles = []*Article{}
|
||||
|
||||
list.wg.Add(1)
|
||||
@ -106,7 +106,6 @@ func (al *ArticleList) Add(a *Article) {
|
||||
func (al *ArticleList) Release(uuid uuid.UUID) (*Article, bool) {
|
||||
al.delCh <- uuid
|
||||
article := <-al.retCh
|
||||
|
||||
if article == nil {
|
||||
return nil, false
|
||||
}
|
||||
@ -124,8 +123,10 @@ func (al *ArticleList) Save(filename string) error {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
encoder := gob.NewEncoder(file)
|
||||
articles := al.Get()
|
||||
if err = gob.NewEncoder(file).Encode(articles); err != nil {
|
||||
err = encoder.Encode(articles)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error ecoding key: %v", err)
|
||||
}
|
||||
|
||||
@ -138,8 +139,10 @@ func LoadArticleList(filename string) (*ArticleList, error) {
|
||||
return nil, fmt.Errorf("error opening key file: %v", err)
|
||||
}
|
||||
|
||||
decoder := gob.NewDecoder(file)
|
||||
articleList := NewArticleList()
|
||||
if err = gob.NewDecoder(file).Decode(&articleList.articles); err != nil {
|
||||
err = decoder.Decode(&articleList.articles)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding key: %v", err)
|
||||
}
|
||||
|
||||
@ -147,7 +150,7 @@ func LoadArticleList(filename string) (*ArticleList, error) {
|
||||
}
|
||||
|
||||
func NewTagList() *TagList {
|
||||
list := initTagList()
|
||||
list := minTagList()
|
||||
list.tags = []string{}
|
||||
|
||||
list.wg.Add(1)
|
||||
@ -172,8 +175,10 @@ func (tl *TagList) Save(filename string) error {
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
encoder := gob.NewEncoder(file)
|
||||
tags := tl.Get()
|
||||
if err = gob.NewEncoder(file).Encode(tags); err != nil {
|
||||
err = encoder.Encode(tags)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error ecoding key: %v", err)
|
||||
}
|
||||
|
||||
@ -185,10 +190,11 @@ func LoadTagList(filename string) (*TagList, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening key file: %v", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
decoder := gob.NewDecoder(file)
|
||||
tagList := NewTagList()
|
||||
if err = gob.NewDecoder(file).Decode(&tagList.tags); err != nil {
|
||||
err = decoder.Decode(&tagList.tags)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding key: %v", err)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,8 @@ func (db *DB) AddUser(user *User, pass string) error {
|
||||
(username, password, first_name, last_name, role)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`
|
||||
if _, err = db.Exec(query, user.UserName, string(hashedPass), user.FirstName, user.LastName, user.Role); err != nil {
|
||||
_, err = db.Exec(query, user.UserName, string(hashedPass), user.FirstName, user.LastName, user.Role)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error inserting user into DB: %v", err)
|
||||
}
|
||||
|
||||
@ -103,7 +104,8 @@ func (db *DB) ChangePassword(id int64, oldPass, newPass string) error {
|
||||
SET password = ?
|
||||
WHERE id = ?
|
||||
`
|
||||
if _, err = db.Exec(query, string(newHashedPass), id); err != nil {
|
||||
_, err = db.Exec(query, string(newHashedPass), id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error updating password in DB: %v", err)
|
||||
}
|
||||
|
||||
@ -132,7 +134,8 @@ func (db *DB) GetUser(id int64) (*User, error) {
|
||||
`
|
||||
|
||||
row := db.QueryRow(query, id)
|
||||
if err := row.Scan(&user.ID, &user.UserName, &user.FirstName, &user.LastName, &user.Role); err != nil {
|
||||
if err := row.Scan(&user.ID, &user.UserName, &user.FirstName,
|
||||
&user.LastName, &user.Role); err != nil {
|
||||
return nil, fmt.Errorf("error reading user information: %v", err)
|
||||
}
|
||||
|
||||
|
101
cmd/data/rss.go
101
cmd/data/rss.go
@ -1,101 +0,0 @@
|
||||
package data
|
||||
|
||||
import (
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
addCh chan *feeds.Item
|
||||
setCh chan feeds.Feed
|
||||
getCh chan feeds.Feed
|
||||
feed feeds.Feed
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
func initFeed() *Feed {
|
||||
return &Feed{
|
||||
addCh: make(chan *feeds.Item),
|
||||
setCh: make(chan feeds.Feed),
|
||||
getCh: make(chan feeds.Feed),
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Feed) start() {
|
||||
f.wg.Done()
|
||||
for {
|
||||
select {
|
||||
case item := <-f.addCh:
|
||||
f.feed.Items = append(f.feed.Items, item)
|
||||
case f.getCh <- f.feed:
|
||||
case f.feed = <-f.setCh:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewFeed(title, link, desc string) *Feed {
|
||||
feed := initFeed()
|
||||
feed.feed = feeds.Feed{
|
||||
Title: title,
|
||||
Link: &feeds.Link{Href: link},
|
||||
Description: desc,
|
||||
}
|
||||
|
||||
feed.wg.Add(1)
|
||||
go feed.start()
|
||||
feed.wg.Wait()
|
||||
|
||||
return feed
|
||||
}
|
||||
|
||||
func (f *Feed) Get() feeds.Feed {
|
||||
return <-f.getCh
|
||||
}
|
||||
|
||||
func (f *Feed) Set(feed feeds.Feed) {
|
||||
f.setCh <- feed
|
||||
}
|
||||
|
||||
func OpenFeed(filename string) (*Feed, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error opening file %v: %v", filename, err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
feed := initFeed()
|
||||
feed.wg.Add(1)
|
||||
go feed.start()
|
||||
feed.wg.Wait()
|
||||
|
||||
tmpFeed := new(feeds.Feed)
|
||||
if err = gob.NewDecoder(file).Decode(tmpFeed); err != nil {
|
||||
return nil, fmt.Errorf("error decoding file %v: %v", filename, err)
|
||||
}
|
||||
|
||||
feed.Set(*tmpFeed)
|
||||
return feed, nil
|
||||
}
|
||||
|
||||
func (f *Feed) 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()
|
||||
|
||||
feed := f.Get()
|
||||
if err = gob.NewEncoder(file).Encode(feed); err != nil {
|
||||
return fmt.Errorf("error encoding file %v: %v", filename, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *Feed) Add(i *feeds.Item) {
|
||||
f.addCh <- i
|
||||
}
|
@ -17,7 +17,8 @@ type CookieStore struct {
|
||||
func NewKey() ([]byte, error) {
|
||||
key := make([]byte, 32)
|
||||
|
||||
if _, err := io.ReadFull(rand.Reader, key); err != nil {
|
||||
_, err := io.ReadFull(rand.Reader, key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating key: %v", err)
|
||||
}
|
||||
|
||||
@ -32,7 +33,9 @@ func SaveKey(key []byte, filename string) error {
|
||||
defer file.Close()
|
||||
file.Chmod(0600)
|
||||
|
||||
if err = gob.NewEncoder(file).Encode(key); err != nil {
|
||||
encoder := gob.NewEncoder(file)
|
||||
err = encoder.Encode(key)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error ecoding key: %v", err)
|
||||
}
|
||||
|
||||
@ -46,7 +49,9 @@ func LoadKey(filename string) ([]byte, error) {
|
||||
}
|
||||
|
||||
key := make([]byte, 32)
|
||||
if err = gob.NewDecoder(file).Decode(&key); err != nil {
|
||||
decoder := gob.NewDecoder(file)
|
||||
err = decoder.Decode(&key)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error decoding key: %v", err)
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,8 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.streifling.com/jason/rss"
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/feeds"
|
||||
"streifling.com/jason/cpolis/cmd/data"
|
||||
)
|
||||
|
||||
@ -116,7 +116,7 @@ func ReviewArticle(al *data.ArticleList, s *data.CookieStore) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func PublishArticle(f *data.Feed, al *data.ArticleList, s *data.CookieStore) http.HandlerFunc {
|
||||
func PublishArticle(f *rss.Feed, al *data.ArticleList, s *data.CookieStore) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
uuid, err := uuid.Parse(r.PostFormValue("uuid"))
|
||||
if err != nil {
|
||||
@ -141,13 +141,12 @@ func PublishArticle(f *data.Feed, al *data.ArticleList, s *data.CookieStore) htt
|
||||
template.Must(tmpl, err).ExecuteTemplate(w, "page-content", msg)
|
||||
}
|
||||
|
||||
f.Add(&feeds.Item{
|
||||
Title: article.Title,
|
||||
Author: &feeds.Author{Name: session.Values["name"].(string)},
|
||||
Created: article.Created,
|
||||
Description: article.Desc,
|
||||
Content: article.Content,
|
||||
})
|
||||
item := rss.NewItem()
|
||||
item.Title = article.Title
|
||||
item.Author = article.Author
|
||||
item.Description = article.Desc
|
||||
item.Content = &rss.Content{Value: article.Content}
|
||||
f.Channels[0].AddItem(item)
|
||||
f.Save("tmp/rss.gob")
|
||||
|
||||
tmpl, err := template.ParseFiles("web/templates/hub.html")
|
||||
|
@ -5,13 +5,12 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"streifling.com/jason/cpolis/cmd/data"
|
||||
"git.streifling.com/jason/rss"
|
||||
)
|
||||
|
||||
func ShowRSS(f *data.Feed) http.HandlerFunc {
|
||||
func ShowRSS(f *rss.Feed) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
feed := f.Get()
|
||||
rss, err := feed.ToRss()
|
||||
rss, err := f.ToXML()
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
2
go.mod
2
go.mod
@ -3,9 +3,9 @@ module streifling.com/jason/cpolis
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
git.streifling.com/jason/rss v0.0.0-20240305145359-7d49b2cb25fc
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/feeds v1.1.2
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/microcosm-cc/bluemonday v1.0.26
|
||||
github.com/yuin/goldmark v1.7.0
|
||||
|
12
go.sum
12
go.sum
@ -1,3 +1,7 @@
|
||||
git.streifling.com/jason/rss v0.0.0-20240305140009-a59d3f112892 h1:miU3U9H8zSoYprEaG7xaGLMb4CcGLjGt7McC8Wrf+Vs=
|
||||
git.streifling.com/jason/rss v0.0.0-20240305140009-a59d3f112892/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg=
|
||||
git.streifling.com/jason/rss v0.0.0-20240305145359-7d49b2cb25fc h1:vJ36ouI2wTK+jFktnqyAfFHoYnoznAgAo1nUzvMzCvQ=
|
||||
git.streifling.com/jason/rss v0.0.0-20240305145359-7d49b2cb25fc/go.mod h1:gpZF0nZbQSstMpyHD9DTAvlQEG7v4pjO5c7aIMWM4Jg=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
@ -8,20 +12,12 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/feeds v1.1.2 h1:pxzZ5PD3RJdhFH2FsJJ4x6PqMqbgFk1+Vez4XWBW8Iw=
|
||||
github.com/gorilla/feeds v1.1.2/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
|
||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/yuin/goldmark v1.7.0 h1:EfOIvIMZIzHdB/R/zVrikYLPPwJlfMcNczJFMs1m6sA=
|
||||
github.com/yuin/goldmark v1.7.0/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
|
Reference in New Issue
Block a user