diff --git a/assets.go b/assets.go
index d28486d..1879a8b 100644
--- a/assets.go
+++ b/assets.go
@@ -222,6 +222,94 @@ nC1WAvxNMB27f2/7AjTg5s54BOwNTttvIBe0ubuEzo83ocq/bONcqwz1BCL/BAAA///ACu/RdBMAAA==
`,
},
+ "/assets/img/favicon.png": {
+ local: "assets/img/favicon.png",
+ size: 4752,
+ modtime: 1547232209,
+ compressed: `
+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
+`,
+ },
+
"/assets/vendor/css/grids-responsive-min.css": {
local: "assets/vendor/css/grids-responsive-min.css",
size: 8032,
@@ -389,10 +477,38 @@ ZfY39XJelrPeb2dTP1e8O5VLPwIAAP//0xnP9ywDAAA=
"/templates/user_dashboard.html": {
local: "templates/user_dashboard.html",
- size: 0,
- modtime: 1547138339,
+ size: 45,
+ modtime: 1547160534,
compressed: `
-H4sIAAAAAAAC/wEAAP//AAAAAAAAAAA=
+H4sIAAAAAAAC/7JJVMgoSk2zVdIvLU4t0k9LTU0pVrJzTcksUQguTSpOLsosKMnMzyu20U+04wIEAAD/
+/2HSavctAAAA
+`,
+ },
+
+ "/templates/user_feeds.html": {
+ local: "templates/user_feeds.html",
+ size: 3588,
+ modtime: 1547234296,
+ compressed: `
+H4sIAAAAAAAC/5xXXY/aOBe+z6+wrLkIGia0t4UgtdP3lSpVu9JC92aEkIkPiTXGjmwHZjTiv69sJ9ih
+IWL3ApT4POf7wycLyo6I0RwTzrdaNqoAvS2kMIQJUHi5mFF2XCaLvVQHJMgBcrwHoFvd7HShWG2YFBoj
+UtiHHM8aDWrW1JQY6EOWCUILJurGOHUWt7WSNEbmvYYcV4xSELhVEtOPhDeQY4xmTsiuMUaKlks3uwMz
+eLkiR1jMPGmZLGbW3mWy8AYskyNRKIhEOXpJPj6QIqIE9MCm6OGIvuQoW8Oh5sTAd2JI9kuDylbNbsWb
+UqPzOUEIf3w8HM9nPLXcIKg93cwTJ94G8F9I/z8AXfl4e9mB4+hY9pbn4eiALQShD/ePELZRwl+8Qfvs
+D3IAZ1ZLJY2ppAr0r+49RmjelIFuXexRnWER3b3HCAq6CPTvoIuYyok2W18FAfSTaPPLnZ3P2CHPU+93
+G8l+TPeNcEWFmGAmnTjXbZzbIn3uahTliMqiOYAwWQnmfxzs47f3HzS9UdSTeV+UTdjGnu2lSu05Qzn6
+NEcMLUJWMw6iNNUcscfHSZsHtk9bERkTFN7+3KcX/AvbZJ44QQv0aXJJXcdRN7oahPvQJP43YFInYMCg
+69hkpK5B0OeKcZoWCoiBUHdrsuPQOfDCNhMXl3NyjmI/xnOdksGMeAFtUlJM2fE6/GtmOIywVJ89R4TO
+mBCg1vBmUN6eB8Sw8xH3Rb+xzoxodnSv3D1mBSda/2TaZITSFNeNgicPmkYvTzupKCigeIoLEAbUE+E8
+uG0qIHRMraXHcDMWUaNi6HP1Oio5xoo7kKYSvWBjO2lwkEHukkH6Mvw0iqTwu6TwvhQ7TpCfJ9gDTD/l
+YxIn/7HdB/oV5V0Nhh735TLcfK6F/pKnnixvUGj7sVJ2wh1egWmUuAbPb3TwRbFV+sPAITSwkqc7S6yo
+Xp+BjyaM9tDf5NsI2C0EHu+xmQbz1RjFdo2BFNtLHk8RLiooXnfybQRKiSFP7lqbos7Dl+4m2zziOX6M
+ji1uEwuTouCssN3ThS7t8mlkWXJYRetMaiqm7W0zqL8bpK5iwtZxuSPutQ4t83BxtGa6QIAdH0Y10Olp
+s9KWSeqxvkTkKTq1oEty7ApxZy47aK8Dg71uGdlcqet4LvrsUnKnvg56Q1+73lxr7LguGpua3qmwRd7Q
+F68z10pbzrgflTz1e3CggGyKfWoLKbTkkHFZpnhtkUyUCD86xM0a8vxxgUQgXXNWwE22KfrsKxQB1/A7
+u9tMHLKrL+977MDfdidPJ30/SzCrZmdHTHCvjcnNFU3J09Y7mymoOSkgxXM8xVvXRucg/Hcb/DLi1QzM
+8sijgWEexl6wOnDYkTzvhr6SpzDabeqDD/rb+5qU9lK8zLKXT5uBLu1Gexyum1F1ym5GLPo0mmTu2wjl
+kbMuJX5nnic3gzZPFrPu4+ifAAAA//9hEtQ2BA4AAA==
`,
},
@@ -411,6 +527,11 @@ H4sIAAAAAAAC/wEAAP//AAAAAAAAAAA=
local: "assets/css",
},
+ "/assets/img": {
+ isDir: true,
+ local: "assets/img",
+ },
+
"/assets/vendor": {
isDir: true,
local: "assets/vendor",
diff --git a/assets/img/favicon.png b/assets/img/favicon.png
new file mode 100644
index 0000000..6c2bd38
Binary files /dev/null and b/assets/img/favicon.png differ
diff --git a/endpoints_public.go b/endpoints_public.go
index 8b0bf6d..28b98cf 100644
--- a/endpoints_public.go
+++ b/endpoints_public.go
@@ -36,3 +36,7 @@ func handleRssFeed(w http.ResponseWriter, req *http.Request) {
}
fmt.Fprint(w, v)
}
+
+func buildRssFeed(uid string) (string, error) {
+ return "", nil
+}
diff --git a/endpoints_user.go b/endpoints_user.go
index 5e3f249..3e89756 100644
--- a/endpoints_user.go
+++ b/endpoints_user.go
@@ -21,16 +21,22 @@ func handleUserRequest(w http.ResponseWriter, req *http.Request) {
if !page.LoggedIn {
page.SubTitle = "ribbit login"
- page.show("login.html", w)
+ page.show("login.html")
return
}
- page.SubTitle = "dashboard"
- page.show("user_dashboard.html", w)
+ switch f {
+ case "feeds":
+ handleUserFeeds(page)
+ case "updatesubscriptions":
+ handleUpdateUserSubs(page)
+ default:
+ handleUserDashboard(page)
+ }
}
func handleUserLoginForm(page *pageData) {
page.SubTitle = "ribbit login"
- page.show("login.html", page.session.w)
+ page.show("login.html")
}
func handleUserLogin(page *pageData) {
@@ -61,9 +67,59 @@ func handleUserLogin(page *pageData) {
// doLogin attempts to log in with the given email/password
// If it can't, it returns an error
func doLogin(uid, password string) error {
- fmt.Println("Doing Login", uid, password)
if strings.TrimSpace(uid) != "" && strings.TrimSpace(password) != "" {
return m.checkCredentials(uid, password)
}
return errors.New("Invalid Credentials")
}
+
+func handleUserDashboard(page *pageData) {
+ page.SubTitle = "dashboard"
+ page.show("user_dashboard.html")
+}
+
+func handleUserFeeds(page *pageData) {
+ page.SubTitle = "feeds"
+ type feedsPageData struct {
+ User *User
+ FeedSources []FeedSource
+ }
+ fpd := new(feedsPageData)
+ fpd.FeedSources = m.FeedSources
+ id, err := page.session.getStringValue("id")
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ fpd.User, err = m.GetUser(id)
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ page.TemplateData = fpd
+ page.show("user_feeds.html")
+}
+
+func handleUpdateUserSubs(page *pageData) {
+ subs := page.session.req.FormValue("user_feeds")
+ fmt.Println(subs)
+ subPts := strings.Split(subs, ",")
+ var userSubs []string
+ for i := range subPts {
+ subPts[i] = strings.TrimSpace(subPts[i])
+ if subPts[i] != "" {
+ userSubs = append(userSubs, subPts[i])
+ }
+ }
+ id, err := page.session.getStringValue("id")
+ if err != nil {
+ userError(page.session.w)
+ return
+ }
+ var u *User
+ u, err = m.GetUser(id)
+ u.SubSlugs = userSubs
+ m.SaveUser(u)
+
+ redirect("/user/dashboard", page.session.w, page.session.req)
+}
diff --git a/main.go b/main.go
index 9098cf1..efd0147 100644
--- a/main.go
+++ b/main.go
@@ -6,10 +6,12 @@ import (
"bufio"
"fmt"
"html/template"
+ "io/ioutil"
"log"
"net/http"
"os"
"os/signal"
+ "plugin"
"strconv"
"strings"
"syscall"
@@ -24,25 +26,6 @@ import (
const AppName = "ribbit"
const DbName = AppName + ".db"
-// pageData is stuff that changes per request
-type pageData struct {
- Site *SiteData
- Title string
- SubTitle string
- Stylesheets []string
- HeaderScripts []string
- Scripts []string
- FlashMessage string
- FlashClass string
- LoggedIn bool
- IsAdmin bool
- Menu []menuItem
- BottomMenu []menuItem
- session *pageSession
-
- TemplateData interface{}
-}
-
type menuItem struct {
Label string
Location string
@@ -130,10 +113,6 @@ func main() {
log.Fatal(http.ListenAndServe("127.0.0.1:"+strconv.Itoa(m.Site.Port), chain))
}
-func buildRssFeed(uid string) (string, error) {
- return uid, nil
-}
-
func loggingHandler(h http.Handler) http.Handler {
return handlers.LoggingHandler(os.Stdout, h)
}
@@ -193,22 +172,6 @@ func initPageData(w http.ResponseWriter, req *http.Request) *pageData {
return p
}
-func (p *pageData) show(tmplName string, w http.ResponseWriter) error {
- for _, tmpl := range []string{
- "htmlheader.html",
- "header.html",
- tmplName,
- "footer.html",
- "htmlfooter.html",
- } {
- if err := outputTemplate(tmpl, p, w); err != nil {
- fmt.Printf("%s\n", err)
- return err
- }
- }
- return nil
-}
-
func outputTemplate(tmplName string, tmplData interface{}, w http.ResponseWriter) error {
n := "/templates/" + tmplName
l := template.Must(template.New("layout").Parse(FSMustString(m.Site.DevMode, n)))
@@ -272,4 +235,24 @@ func initialize() {
m.Site.sessionSecret = sessSc
assertError(m.Site.SaveToDB())
}
+
+ // Load Feed Sources from Plugins
+ files, err := ioutil.ReadDir("./plugins/")
+ if err != nil {
+ log.Fatal(err)
+ }
+ for _, f := range files {
+ fmt.Print("Loading plugin ", f.Name(), "...")
+ p, err := plugin.Open("./plugins/" + f.Name())
+ if err != nil {
+ panic(err)
+ }
+ var feedSource *FeedSource
+ if feedSource, err = LoadFeedPlugin(p); err != nil {
+ fmt.Println(" ", err.Error())
+ continue
+ }
+ m.FeedSources = append(m.FeedSources, *feedSource)
+ fmt.Printf("Done. (%d feeds)\n", len(feedSource.Feeds))
+ }
}
diff --git a/model.go b/model.go
index acce94a..e032645 100644
--- a/model.go
+++ b/model.go
@@ -13,8 +13,9 @@ type model struct {
bolt *boltease.DB
dbFileName string
- Users []User
- Feeds []Feed
+ Users []User
+ FeedSources []FeedSource
+ Feeds []Feed
Site *SiteData
}
diff --git a/model_feeds.go b/model_feeds.go
index 862c472..99b1e35 100644
--- a/model_feeds.go
+++ b/model_feeds.go
@@ -1,9 +1,77 @@
package main
import (
+ "plugin"
"time"
)
+type FeedSource struct {
+ Feeds []*Feed
+
+ // Plugin Functions
+ getSourceName func() string
+ refreshFeedList func() []map[string]string
+ getFeedUrl func(string, time.Time) (string, error)
+ getFeedDesc func(string, time.Time) (string, error)
+}
+
+func LoadFeedPlugin(p *plugin.Plugin) (*FeedSource, error) {
+ ret := new(FeedSource)
+ feedSourceSymbol, err := p.Lookup("GetSourceName")
+ if err != nil {
+ return nil, err
+ }
+ ret.getSourceName = feedSourceSymbol.(func() string)
+
+ feedListSymbol, err := p.Lookup("GetFeedList")
+ if err != nil {
+ return nil, err
+ }
+ ret.refreshFeedList = feedListSymbol.(func() []map[string]string)
+ feeds := ret.refreshFeedList()
+ // `feeds` is a []map, each map should contain keys: `slug`, `name`, `author`, `source`
+ for _, f := range feeds {
+ var slug, name, author, source string
+ var ok bool
+ if slug, ok = f["slug"]; !ok {
+ continue
+ }
+ if name, ok = f["name"]; !ok {
+ continue
+ }
+ if author, ok = f["author"]; !ok {
+ continue
+ }
+ if source, ok = f["source"]; !ok {
+ continue
+ }
+ ret.Feeds = append(ret.Feeds, NewFeed(slug, name, author, source))
+ }
+
+ feedUrlSymbol, err := p.Lookup("GetFeedUrl")
+ if err != nil {
+ return nil, err
+ }
+ ret.getFeedUrl = feedUrlSymbol.(func(string, time.Time) (string, error))
+
+ feedDescSymbol, err := p.Lookup("GetFeedDesc")
+ if err != nil {
+ return nil, err
+ }
+ ret.getFeedDesc = feedDescSymbol.(func(string, time.Time) (string, error))
+
+ return ret, nil
+}
+
+func (f *FeedSource) getFeed(slug string) *Feed {
+ for i := range f.Feeds {
+ if f.Feeds[i].Slug == slug {
+ return f.Feeds[i]
+ }
+ }
+ return nil
+}
+
type Feed struct {
Name string
Author string
diff --git a/page_data.go b/page_data.go
new file mode 100644
index 0000000..41a9e02
--- /dev/null
+++ b/page_data.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "fmt"
+)
+
+// pageData is stuff that changes per request
+type pageData struct {
+ Site *SiteData
+ Title string
+ SubTitle string
+ Stylesheets []string
+ HeaderScripts []string
+ Scripts []string
+ FlashMessage string
+ FlashClass string
+ LoggedIn bool
+ IsAdmin bool
+ Menu []menuItem
+ BottomMenu []menuItem
+ session *pageSession
+
+ TemplateData interface{}
+}
+
+func (p *pageData) show(tmplName string) error {
+ for _, tmpl := range []string{
+ "htmlheader.html",
+ "header.html",
+ tmplName,
+ "footer.html",
+ "htmlfooter.html",
+ } {
+ if err := outputTemplate(tmpl, p, p.session.w); err != nil {
+ fmt.Printf("%s\n", err)
+ return err
+ }
+ }
+ return nil
+}
diff --git a/plugin_src/plugin_dilbert.go b/plugin_src/plugin_dilbert.go
index 1aba78d..82921eb 100644
--- a/plugin_src/plugin_dilbert.go
+++ b/plugin_src/plugin_dilbert.go
@@ -2,8 +2,6 @@ package main
import (
"C"
-)
-import (
"errors"
"fmt"
"net/http"
@@ -12,43 +10,36 @@ import (
"github.com/PuerkitoBio/goquery"
)
-func getFeedList() []Feed {
- var ret []Feed
- ret = append(ret, *NewFeed("dilbert", "Dilbert", "Scott Adams", "dilbert"))
+func GetSourceName() string {
+ return "dilbert"
+}
+
+func GetFeedList() []map[string]string {
+ var ret []map[string]string
+ feedMap := make(map[string]string)
+ feedMap["slug"] = "dilbert"
+ feedMap["name"] = "Dilbert"
+ feedMap["author"] = "Scott Adams"
+ feedMap["source"] = GetSourceName()
+ ret = append(ret, feedMap)
return ret
}
-func getRssItem(slug string) (string, error) {
- desc, err := getFeedDesc(time.Now())
- if err != nil {
- return "", err
- }
- feed, err := m.GetFeed(SRC_DILBERT, slug)
- if err != nil {
- return "", err
- }
- desc = ""
- ret := "