diff --git a/assets.go b/assets.go
index 1879a8b..64bfe34 100644
--- a/assets.go
+++ b/assets.go
@@ -475,40 +475,57 @@ ZfY39XJelrPeb2dTP1e8O5VLPwIAAP//0xnP9ywDAAA=
`,
},
+ "/templates/rss_feed.xml": {
+ local: "templates/rss_feed.xml",
+ size: 700,
+ modtime: 1547486966,
+ compressed: `
+H4sIAAAAAAAC/2xSTY+bMBC951dMEbdt7bTqaev1alvUU9VDlZyiHAyeEivGIH/QShb/fQUG8qGcsGfe
+e543D/b6v9HQo3WqNS/ZZ7LNXvmGWecuxS9km/ENAKtOwhjU4xmAeeU18j+qLJWHn4iS0VRKba3MmZ+8
+754ptROIlEFrtFUr8V9rz45UbUNRKk9jJDtsOi08FsILsndoyT4oOQyMTkJJU6KrrOq8ag0fX4S/rYXH
+ZIfWiAZHgWvWPJswdRA1cjSfgmN0vS9t578HpWUhPPJ7/bUzDXcDnRfjNf+6ZXT8TpUYwQpTI+TqI+Q9
+PL/AreToxcEwJP6Hw4/ibfd2yOAJ8p4Ul/HhCbLjkWcJpzw26YE1jRjznvyefV+lAcC6UM528p78Es7v
+OzmbWFoLtA5KJpxrg61wGL6lmw71cr5VmBgLfQrsOre75Cb+6OpxOPTiK0ZAI9NiGF1/P0atc3zzHgAA
+//+UZXAKvAIAAA==
+`,
+ },
+
"/templates/user_dashboard.html": {
local: "templates/user_dashboard.html",
- size: 45,
- modtime: 1547160534,
+ size: 97,
+ modtime: 1547486320,
compressed: `
-H4sIAAAAAAAC/7JJVMgoSk2zVdIvLU4t0k9LTU0pVrJzTcksUQguTSpOLsosKMnMzyu20U+04wIEAAD/
-/2HSavctAAAA
+H4sIAAAAAAAC/7JJVMgoSk2zVdIvLU4t0k9LTU0pVrJzTcksUQguTSpOLsosKMnMzyu20U+04+JCqC4q
+LtavrtYLSc0tyEksSXVJLEnUCy3NTKmtVbILCg5WcEtNTQHrAQQAAP//EcPbEmEAAAA=
`,
},
"/templates/user_feeds.html": {
local: "templates/user_feeds.html",
- size: 3588,
- modtime: 1547234296,
+ size: 4065,
+ modtime: 1547235825,
compressed: `
-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
+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
+UuK/debJVdLmyWLWftT+EwAA///sH8RP4Q8AAA==
`,
},
diff --git a/endpoints_public.go b/endpoints_public.go
index 28b98cf..5f45e6d 100644
--- a/endpoints_public.go
+++ b/endpoints_public.go
@@ -1,10 +1,7 @@
package main
import (
- "fmt"
"net/http"
-
- "github.com/gorilla/mux"
)
func handleRequest(w http.ResponseWriter, req *http.Request) {
@@ -19,24 +16,3 @@ func handleRequest(w http.ResponseWriter, req *http.Request) {
handleUserLoginForm(page)
}
}
-
-func handleRssFeed(w http.ResponseWriter, req *http.Request) {
- vars := mux.Vars(req)
- var uid string
- var uidOk bool
- if uid, uidOk = vars["uid"]; !uidOk {
- userError(w)
- return
- }
- w.Header().Set("Content-Type", "application/xml")
- v, err := buildRssFeed(uid)
- if err != nil {
- userError(w)
- return
- }
- fmt.Fprint(w, v)
-}
-
-func buildRssFeed(uid string) (string, error) {
- return "", nil
-}
diff --git a/endpoints_rss.go b/endpoints_rss.go
new file mode 100644
index 0000000..d955b19
--- /dev/null
+++ b/endpoints_rss.go
@@ -0,0 +1,73 @@
+package main
+
+import (
+ "net/http"
+ "strings"
+ "time"
+
+ "github.com/gorilla/mux"
+)
+
+func handleRssFeed(w http.ResponseWriter, req *http.Request) {
+ page := initPageData(w, req)
+
+ vars := mux.Vars(req)
+ var uid string
+ var uidOk bool
+ if uid, uidOk = vars["uid"]; !uidOk {
+ userError(w)
+ return
+ }
+ w.Header().Set("Content-Type", "application/xml")
+ var slug string
+ var slugOk bool
+ slug, slugOk = vars["slug"]
+ if !slugOk {
+ // Print the user's entire feed
+ buildUserRssFeed(page, uid)
+ } else {
+ // Print the feed for a specific slug
+ buildSlugRssFeed(page, uid, slug)
+ }
+}
+
+type rssPageData struct {
+ User *User
+ Feeds []Feed
+ BuildDate time.Time
+}
+
+func buildUserRssFeed(page *pageData, uid string) {
+ var err error
+ rpd := new(rssPageData)
+ rpd.BuildDate = time.Now()
+ rpd.User, err = m.GetUser(uid)
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ for _, v := range rpd.User.SubSlugs {
+ pts := strings.Split(v, ";")
+ fd, err := m.GetFeed(pts[0], pts[1])
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ rpd.Feeds = append(rpd.Feeds, *fd)
+ }
+ page.TemplateData = rpd
+ page.showRss()
+}
+
+func buildSlugRssFeed(page *pageData, uid, slug string) {
+ var err error
+ rpd := new(rssPageData)
+ rpd.BuildDate = time.Now()
+ rpd.User, err = m.GetUser(uid)
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ page.TemplateData = rpd
+ page.showRss()
+}
diff --git a/endpoints_user.go b/endpoints_user.go
index 3e89756..36ecbf4 100644
--- a/endpoints_user.go
+++ b/endpoints_user.go
@@ -75,6 +75,17 @@ func doLogin(uid, password string) error {
func handleUserDashboard(page *pageData) {
page.SubTitle = "dashboard"
+ var err error
+ id, err := page.session.getStringValue("id")
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ page.TemplateData, err = m.GetUser(id)
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
page.show("user_dashboard.html")
}
@@ -120,6 +131,11 @@ func handleUpdateUserSubs(page *pageData) {
u, err = m.GetUser(id)
u.SubSlugs = userSubs
m.SaveUser(u)
+ for k := range m.Users {
+ if m.Users[k].Uuid == id {
+ m.Users[k].SubSlugs = userSubs
+ }
+ }
redirect("/user/dashboard", page.session.w, page.session.req)
}
diff --git a/main.go b/main.go
index efd0147..98acb6f 100644
--- a/main.go
+++ b/main.go
@@ -72,6 +72,7 @@ func main() {
pub.HandleFunc("/api/comics/{cid}/{function}", handleApiComicsCall)
*/
pub.HandleFunc("/rss/{uid}", handleRssFeed)
+ pub.HandleFunc("/rss/{uid}/{slug}", handleRssFeed)
pub.HandleFunc("/user/{function}", handleUserRequest)
http.Handle("/", r)
diff --git a/model.go b/model.go
index e032645..31e0d16 100644
--- a/model.go
+++ b/model.go
@@ -10,8 +10,10 @@ import (
)
type model struct {
+ dbOpen int
bolt *boltease.DB
dbFileName string
+ dbChanged bool
Users []User
FeedSources []FeedSource
@@ -48,10 +50,10 @@ func NewModel() (*model, error) {
func (m *model) initDB() error {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
if err = m.bolt.MkBucketPath([]string{"site"}); err != nil {
return err
@@ -65,9 +67,31 @@ func (m *model) initDB() error {
return nil
}
+func (m *model) openDB() error {
+ m.dbOpen = m.dbOpen + 1
+ if m.dbOpen > 1 {
+ return nil
+ }
+ var err error
+ if err = m.openDB(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (m *model) closeDB() {
+ m.dbOpen = m.dbOpen - 1
+ if m.dbOpen == 0 {
+ m.closeDB()
+ }
+}
+
func (m *model) saveChanges() {
+ fmt.Println("Saving Site to DB")
m.Site.SaveToDB()
- //m.SaveAllFeeds(m.Feeds)
+ //fmt.Println("Saving Feeds to DB")
+ //m.SaveAllFeeds(m.FeedSources)
+ fmt.Println("Saving Users to DB")
m.SaveAllUsers(m.Users)
}
diff --git a/model_feeds.go b/model_feeds.go
index 99b1e35..b111531 100644
--- a/model_feeds.go
+++ b/model_feeds.go
@@ -1,6 +1,7 @@
package main
import (
+ "fmt"
"plugin"
"time"
)
@@ -91,7 +92,7 @@ func NewFeed(s, n, a, source string) *Feed {
}
func (f *Feed) GetBucket() []string {
- return []string{"feed", f.Source, f.Slug}
+ return []string{"feeds", f.Source, f.Slug}
}
func (f *Feed) Update() error {
@@ -146,10 +147,10 @@ func (f *Feed) GetRssItem() string {
// DB Function to save a feed
func (m *model) SaveFeed(f *Feed) error {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
bkt := f.GetBucket()
if err = m.bolt.MkBucketPath(bkt); err != nil {
return err
@@ -180,10 +181,10 @@ func (m *model) SaveFeed(f *Feed) error {
// DB Function to get a feed
func (m *model) GetFeed(source, slug string) (*Feed, error) {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return nil, err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
ret := new(Feed)
ret.Source = source
ret.Slug = slug
@@ -210,14 +211,17 @@ func (m *model) LoadFeeds() error {
}
// Save all feeds to the DB
-func (m *model) SaveAllFeeds(feeds []Feed) {
+func (m *model) SaveAllFeeds(feedSources []FeedSource) {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return
}
- defer m.bolt.CloseDB()
- for i := range feeds {
- m.SaveFeed(&feeds[i])
+ defer m.closeDB()
+ for _, v := range feedSources {
+ for j := range v.Feeds {
+ fmt.Printf("Saving Feed to DB (%s;%s)\n", v.Feeds[j].Source, v.Feeds[j].Slug)
+ m.SaveFeed(v.Feeds[j])
+ }
}
}
@@ -225,10 +229,10 @@ func (m *model) SaveAllFeeds(feeds []Feed) {
func (m *model) GetAllFeeds() []Feed {
var ret []Feed
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return ret
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
var srcs []string
bkt := []string{"feeds"}
if srcs, err = m.bolt.GetBucketList(bkt); err != nil {
@@ -253,10 +257,10 @@ func (m *model) GetAllFeeds() []Feed {
// Delete a feed from the DB
func (m *model) DeleteFeed(slug string) error {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
return m.bolt.DeleteBucket([]string{"feeds"}, slug)
}
diff --git a/model_sitedata.go b/model_sitedata.go
index 0a8a6b1..d012518 100644
--- a/model_sitedata.go
+++ b/model_sitedata.go
@@ -42,10 +42,10 @@ func NewSiteData(m *model) *SiteData {
// load the site data out of the database
// If fields don't exist in the DB, don't clobber what is already in s
func (s *SiteData) LoadFromDB() error {
- if err := s.m.bolt.OpenDB(); err != nil {
+ if err := s.m.openDB(); err != nil {
return err
}
- defer s.m.bolt.CloseDB()
+ defer s.m.closeDB()
if title, _ := s.m.bolt.GetValue(s.mPath, "title"); strings.TrimSpace(title) != "" {
s.Title = title
@@ -78,10 +78,10 @@ func (s *SiteData) NeedsSave() bool {
func (s *SiteData) SaveToDB() error {
s.lastSave = time.Now()
var err error
- if err = s.m.bolt.OpenDB(); err != nil {
+ if err = s.m.openDB(); err != nil {
return err
}
- defer s.m.bolt.CloseDB()
+ defer s.m.closeDB()
if err = s.m.bolt.SetValue(s.mPath, "title", s.Title); err != nil {
return err
diff --git a/model_user.go b/model_user.go
index eb7d7a5..e256401 100644
--- a/model_user.go
+++ b/model_user.go
@@ -40,10 +40,10 @@ func (u *User) UpdateFeed() error {
func (m *model) SaveUser(u *User) error {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
bkt := []string{"users", u.Uuid}
if err = m.bolt.MkBucketPath(bkt); err != nil {
return err
@@ -73,10 +73,10 @@ func (m *model) SaveUser(u *User) error {
func (m *model) isValidUser(uid string) bool {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return false
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
ret := new(User)
bkt := []string{"users", uid}
ret.Uuid = uid
@@ -105,10 +105,10 @@ func (m *model) GetUser(uid string) (*User, error) {
return nil, errors.New("No user id given")
}
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return nil, err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
ret := new(User)
bkt := []string{"users", uid}
ret.Uuid = uid
@@ -128,10 +128,10 @@ func (m *model) GetUser(uid string) (*User, error) {
func (m *model) SaveAllUsers(users []User) {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
for i := range users {
m.SaveUser(&users[i])
}
@@ -145,10 +145,10 @@ func (m *model) LoadUsers() error {
func (m *model) GetAllUsers() []User {
var err error
var ret []User
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return ret
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
uids := m.GetUserIdList()
for _, uid := range uids {
@@ -161,10 +161,10 @@ func (m *model) GetAllUsers() []User {
func (m *model) GetUserByName(nm string) (*User, error) {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return nil, err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
usrids := m.GetUserIdList()
for i := range usrids {
bkt := []string{"users", usrids[i]}
@@ -180,10 +180,10 @@ func (m *model) GetUserByName(nm string) (*User, error) {
func (m *model) GetUserIdList() []string {
var ret []string
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return ret
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
bkt := []string{"users"}
ret, _ = m.bolt.GetBucketList(bkt)
return ret
@@ -201,10 +201,10 @@ func (m *model) updateUserPassword(uid, password string) error {
return err
}
- if err := m.bolt.OpenDB(); err != nil {
+ if err := m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
usrPath := []string{"users", uid}
return m.bolt.SetValue(usrPath, "password", string(cryptPw))
@@ -213,10 +213,10 @@ func (m *model) updateUserPassword(uid, password string) error {
// Is the uid and pw given valid?
func (m *model) checkCredentials(uid, pw string) error {
var err error
- if err = m.bolt.OpenDB(); err != nil {
+ if err = m.openDB(); err != nil {
return err
}
- defer m.bolt.CloseDB()
+ defer m.closeDB()
var uPw string
usrPath := []string{"users", uid}
diff --git a/page_data.go b/page_data.go
index 41a9e02..0347ae9 100644
--- a/page_data.go
+++ b/page_data.go
@@ -38,3 +38,11 @@ func (p *pageData) show(tmplName string) error {
}
return nil
}
+
+func (p *pageData) showRss() error {
+ if err := outputTemplate("rss_feed.xml", p, p.session.w); err != nil {
+ fmt.Printf("%s\n", err)
+ return err
+ }
+ return nil
+}
diff --git a/templates/rss_feed.xml b/templates/rss_feed.xml
new file mode 100644
index 0000000..e1d3708
--- /dev/null
+++ b/templates/rss_feed.xml
@@ -0,0 +1,20 @@
+
+
+
+ Ribbit Feed
+ http://ribbit.bullercodeworks.com/edit/{{.TemplateData.User.Uuid}}
+ Feed for {{.TemplateData.User.Username}}
+ en-us
+ {{.TemplateData.BuildDate}}
+ 40
+ {{ range $i, $v := .TemplateData.Feeds }}
+ -
+ {{$v.Name}}
+ {{$v.LastUpdate}}
+ {{$v.Source}};{{$v.Slug}};{{$v.LastUpdate}}
+
+
+
+ {{ end }}
+
+
diff --git a/templates/user_dashboard.html b/templates/user_dashboard.html
index c1cb451..921e256 100644
--- a/templates/user_dashboard.html
+++ b/templates/user_dashboard.html
@@ -1 +1,3 @@
Edit Subscriptions
+
+RSS Feed