From 93d6d36eb697cd9452eb4aab446151a1a33ed245 Mon Sep 17 00:00:00 2001 From: Adam Mathes Date: Mon, 23 Jan 2017 20:04:03 -0800 Subject: neko v2 initial commit --- models/db.go | 24 +++++++++++ models/feed/feed.go | 103 +++++++++++++++++++++++++++++++++++++++++++++ models/item/item.go | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 models/db.go create mode 100644 models/feed/feed.go create mode 100644 models/item/item.go (limited to 'models') diff --git a/models/db.go b/models/db.go new file mode 100644 index 0000000..b8bc655 --- /dev/null +++ b/models/db.go @@ -0,0 +1,24 @@ +/* +Package neko/models implements behavior for the entities necessary for the subscription services and handles persistence via a mysql/maridb database +*/ +package models + +import ( + "database/sql" + _ "github.com/go-sql-driver/mysql" + "log" +) + +var DB *sql.DB + +func InitDB(dataSourceName string) { + var err error + DB, err = sql.Open("mysql", dataSourceName) + if err != nil { + log.Panic(err) + } + + if err = DB.Ping(); err != nil { + log.Panic(err) + } +} diff --git a/models/feed/feed.go b/models/feed/feed.go new file mode 100644 index 0000000..4abebb4 --- /dev/null +++ b/models/feed/feed.go @@ -0,0 +1,103 @@ +package feed + +import ( + "log" + "neko/models" +) + +type Feed struct { + Id int64 `json:"_id"` + Url string `json:"url"` + Title string `json:"title"` + // TODO: last_updated scan +} + +func NewFeed(url string) error { + stmt, err := models.DB.Prepare("INSERT INTO feed(url) VALUES(?)") + if err != nil { + return err + } + _, err = stmt.Exec(url) + if err != nil { + return err + } + return nil +} + +func All() ([]*Feed, error) { + return filter("") +} + +func filter(where string) ([]*Feed, error) { + // todo: add back in title + rows, err := models.DB.Query(`SELECT id, url, title + FROM feed ` + where) + if err != nil { + return nil, err + } + defer rows.Close() + + feeds := make([]*Feed, 0) + for rows.Next() { + f := new(Feed) + err := rows.Scan(&f.Id, &f.Url, &f.Title) + if err != nil { + return nil, err + } + feeds = append(feeds, f) + } + if err = rows.Err(); err != nil { + return nil, err + } + return feeds, nil +} + +func (f *Feed) Update() { + if len(f.Title) == 0 { + return + } + + if f.Id == 0 { + return + } + + if len(f.Url) == 0 { + return + } + + models.DB.Query(`UPDATE feed + SET title=?, url=? + WHERE id=?`, f.Title, f.Url, f.Id) +} + +func (f *Feed) Delete() { + log.Println("lets delete some shiteeee") + _, err := models.DB.Exec(`DELETE FROM feed + WHERE id=?`, f.Id) + if err != nil { + log.Println(err) + } +} + +func (f *Feed) ByUrl(url string) error { + err := models.DB.QueryRow(`SELECT id, url, title + FROM feed + WHERE url = ?`, url).Scan(&f.Id, &f.Url, &f.Title) + if err != nil { + return err + } + return nil +} + +func (f *Feed) Create() error { + res, err := models.DB.Exec(`INSERT INTO feed(url, title) + VALUES(?, ?)`, f.Url, f.Title) + if err != nil { + return err + } + + id, _ := res.LastInsertId() + f.Id = id + + return nil +} diff --git a/models/item/item.go b/models/item/item.go new file mode 100644 index 0000000..51166c4 --- /dev/null +++ b/models/item/item.go @@ -0,0 +1,118 @@ +package item + +import ( + "fmt" + "log" + "neko/models" + // "database/sql" + "github.com/microcosm-cc/bluemonday" +) + +type Item struct { + Id int64 `json:"_id,string,omitempty"` + Title string `json:"title"` + Url string `json:"url"` + Description string `json:"description"` + ReadState bool `json:"read"` + FeedId int64 + PublishDate string `json:"publish_date"` + FeedTitle string `json:"feed_title"` + FeedUrl string `json:"feed_url"` +} + +func (i *Item) Print() { + fmt.Printf("id: %d\n", i.Id) + fmt.Printf("title: %s\n", i.Title) + fmt.Printf("ReadState: %d\n", i.ReadState) +} + +func (i *Item) Create() error { + res, err := models.DB.Exec(`INSERT INTO + item(title, url, description, feed_id) + VALUES(?, ?, ?, ?)`, i.Title, i.Url, i.Description, i.FeedId) + if err != nil { + return err + } + + id, _ := res.LastInsertId() + i.Id = id + + return nil +} + +func (i *Item) Save() { + _, err := models.DB.Exec(`UPDATE item + SET read_state=? + WHERE id=?`, i.ReadState, i.Id) + if err != nil { + log.Println(err) + } +} + +func (i *Item) FullSave() { + _, err := models.DB.Exec(`UPDATE item + SET title=?, url=?, description=?, feed_id=? + WHERE id=?`, i.Title, i.Url, i.Description, i.FeedId, i.Id) + if err != nil { + log.Println(err) + } +} + +func Filter(max_id int64, feed_id int64, unread_only bool) ([]*Item, error) { + + var args []interface{} + + query := `SELECT item.id, item.title, item.url, item.description, + item.read_state, item.publish_date, + feed.url, feed.title + FROM item,feed + WHERE item.feed_id=feed.id ` + + if max_id != 0 { + query = query + "AND item.id < ? " + args = append(args, max_id) + } + + if feed_id != 0 { + query = query + " AND feed.id=? " + args = append(args, feed_id) + } + + if unread_only { + query = query + " AND item.read_state=0 " + } + + query = query + "ORDER BY item.id DESC LIMIT 15" + // log.Println(query) + // log.Println(args...) + + rows, err := models.DB.Query(query, args...) + if err != nil { + log.Println(err) + return nil, err + } + defer rows.Close() + + p := bluemonday.NewPolicy() + p.AllowElements("blockquote", "a", "img", "p", "h1", "h2", "h3", "h4", "b", "i", "em", "strong") + p.AllowAttrs("href").OnElements("a") + p.AllowAttrs("src", "alt").OnElements("img") + + + items := make([]*Item, 0) + for rows.Next() { + i := new(Item) + err := rows.Scan(&i.Id, &i.Title, &i.Url, &i.Description, &i.ReadState, &i.PublishDate, &i.FeedUrl, &i.FeedTitle) + if err != nil { + log.Println(err) + return nil, err + } + i.Description = p.Sanitize(i.Description) + // TODO: sanitize other fields + items = append(items, i) + } + if err = rows.Err(); err != nil { + return nil, err + } + return items, nil +} -- cgit v1.2.3