func (f Feed) DeleteExcludes() { el := f.Excludes() for _, e := range el { e = Escape_guid(e) if len(e) < 1 { continue } var query = "delete from ttrss_entries where feed_id=" + u.Tostr(f.ID) + " and title like '%" + e + "%'" var stmt, err = u.Sth(db, query) if err != nil { glog.Errorf("u.Sth(db,%s): %s", query, err) return } if _, err := stmt.Exec(); err != nil { glog.Errorf("DeleteExcludes.stmt.Exec: %s", err) } } ed := f.ExcludesData() for _, e := range ed { e = Escape_guid(e) if len(e) < 1 { continue } var query = "delete from ttrss_entries where feed_id=" + u.Tostr(f.ID) + " and content like '%" + e + "%'" var stmt, err = u.Sth(db, query) if err != nil { glog.Errorf("u.Sth(db,%s): %s", query, err) return } if _, err := stmt.Exec(); err != nil { glog.Errorf("stmt.Exec: %s", err) } } f.ClearCache() }
func GetAllCategories() []Category { var allCats []Category var catids []int err := mc.Get("CategoryList", &catids) if err != nil { rows, err := stmtGetAllCats.Query() if err != nil { glog.Errorf("stmtGetAllCats: %s", err) return allCats } for rows.Next() { var cat Category rows.Scan(&cat.Name, &cat.UserName, &cat.Description, &cat.ID, &cat.Exclude) allCats = append(allCats, cat) catids = append(catids, cat.ID) go mc.Set("Category"+u.Tostr(cat.ID)+"_", cat) } go mc.Set("CategoryList", allCats) } else { for _, i := range catids { cat := GetCat(u.Tostr(i)) allCats = append(allCats, cat) } } return allCats }
func (f Feed) UnreadEntries() (el []Entry) { mc.GetOr("Feed"+u.Tostr(f.ID)+"_unreadentries", &el, func() { el = f.GetEntriesByParam("unread = 1") }) err := mc.Set("Feed"+u.Tostr(f.ID)+"_UnreadCount", len(el)) if err != nil { glog.Errorf("mc.Set(Feed %v _UnreadCount, %v): %s", f.ID, len(el), err) } return el }
func (c Category) UnreadEntries() (el []Entry) { mc.GetOr("Category"+u.Tostr(c.ID)+"_unreadentries", &el, func() { for _, f := range c.Feeds() { el = append(el, f.UnreadEntries()...) } sort.Sort(EntryList(el)) }) mc.SetTime("Category"+u.Tostr(c.ID)+"_UnreadCount", len(el), 60) return el }
func (c Category) ClearCache() { mc.DeleteLike("Category" + u.Tostr(c.ID) + "_") cl := mc.Find("Category" + u.Tostr(c.ID)) mc.Delete(cl...) mcl := []string{"Category" + u.Tostr(c.ID) + "_", "Category" + u.Tostr(c.ID) + "_UnreadCount", "Category" + u.Tostr(c.ID) + "_Feeds"} for _, k := range mcl { mc.Delete(k) } mc.Delete(mcl...) }
func CacheAllCats() { for _, c := range GetAllCategories() { err := mc.Set("Category"+u.Tostr(c.ID)+"_", c) if err != nil { glog.Errorf("mc.Set(Category %v _: %s", c.ID, err) } err = mc.Set("Category"+u.Tostr(c.ID)+"_UnreadCount", c.Unread()) if err != nil { glog.Errorf("mc.Set(Category %v _UnreadCount): %s", c.ID, err) } } }
func CacheAllFeeds() { for _, f := range GetAllFeeds() { err := mc.Set("Feed"+u.Tostr(f.ID)+"_", f) if err != nil { glog.Errorf("mc.Set(Feed%v): %s", f.ID, err) } err = mc.Set("Feed"+u.Tostr(f.ID)+"_UnreadCount", f.Unread()) if err != nil { glog.Errorf("mc.Set(Feed %v _UnreadCount): %s", f.ID, err) } } return }
func (f Feed) ClearEntries() { var err error err = mc.Delete("Category" + u.Tostr(f.CategoryID) + "_unreadentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(Category"+u.Tostr(f.CategoryID)+"_unreadentries: %s", err) } } err = mc.Delete("Feed" + u.Tostr(f.ID) + "_unreadentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(Feed"+u.Tostr(f.CategoryID)+"_unreadentries: %s", err) } } err = mc.Delete("Category" + u.Tostr(f.CategoryID) + "_readentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(Category"+u.Tostr(f.CategoryID)+"_readentries: %s", err) } } err = mc.Delete("Feed" + u.Tostr(f.ID) + "_readentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(Feed"+u.Tostr(f.CategoryID)+"_readentries: %s", err) } } }
func (f Feed) ClearMarked() { err := mc.Delete("Feed" + u.Tostr(f.ID) + "_markedentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(feed%v_markedentries): %s", f.ID, err) } } err = mc.Delete("Category" + u.Tostr(f.CategoryID) + "_markedentries") if err != nil { if err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(Category%v_markedentries): %s", f.ID, err) } } f.ClearEntries() }
func (c Category) Print() { print("Category: " + u.Tostr(c.ID) + "\n" + "\tName:\t" + c.Name + "\n" + "\tDesc:\t" + c.Description + "\n" + "\tUser:\t" + c.UserName + "\n" + "\tExclude:\t" + c.Exclude + "\n") }
func (c Category) FeedsStr() []string { f := c.Feeds() var feedstr []string for _, i := range f { feedstr = append(feedstr, u.Tostr(i.ID)) } return feedstr }
func (f Feed) MarkEntriesRead(ids []string) (err error) { if len(ids) == 0 { err = fmt.Errorf("Ids is null") return err } else { // make sure they're all integers var id_list []string for _, i := range ids { if _, err := strconv.Atoi(i); err == nil { id_list = append(id_list, i) } } if len(id_list) < 1 { return fmt.Errorf("Not enough valid ids passed") } j := strings.Join(id_list, ",") sql := "update ttrss_entries set unread='0' where feed_id=" + u.Tostr(f.ID) + " and id in (" + j + ")" stmtUpdateMarkEntries, err := u.Sth(db, sql) if err != nil { glog.Errorf("u.Sth(db,%s): %s", sql, err) return err } if _, err = stmtUpdateMarkEntries.Exec(); err != nil { glog.Errorf("stmtUpdateMarkEntries.Exec(%s): %s", sql, err) } mc.Decrement("Category"+u.Tostr(f.CategoryID)+"_UnreadCount", uint64(len(ids))) mc.Decrement("Feed"+u.Tostr(f.ID)+"_UnreadCount", uint64(len(ids))) mc.Delete("Category" + u.Tostr(f.CategoryID) + "_unreadentries") mc.Delete("Feed" + u.Tostr(f.ID) + "_unreadentries") mc.Delete("Category" + u.Tostr(f.CategoryID) + "_readentries") mc.Delete("Feed" + u.Tostr(f.ID) + "_readentries") } return err }
func (f Feed) Unread() (count int) { mc.GetOr("Feed"+u.Tostr(f.ID)+"_UnreadCount", &count, func() { err := stmtFeedUnread.QueryRow(f.ID).Scan(&count) if err != nil { glog.Errorf("stmtFeedUnread.QueryRow(%s): %s", f.ID, err) } }) return count }
func (c Category) ReadEntries() (el []Entry) { mc.GetOr("Category"+u.Tostr(c.ID)+"_readentries", &el, func() { for _, f := range c.Feeds() { el = append(el, f.ReadEntries()...) } sort.Sort(EntryList(el)) }) return el }
func (c Category) MarkedEntries() (el []Entry) { mc.GetOr("Category"+u.Tostr(c.ID)+"_markedentries", &el, func() { for _, f := range c.Feeds() { el = append(el, f.MarkedEntries()...) } sort.Sort(EntryList(el)) el = c.GetEntriesByParam("marked = 1") }) return el }
func (e Entry) Save(userName string) (err error) { if e.ID > 0 { if e.Title == "" { e.Title = " " } if e.Link == "" { e.Link = "" } if e.Date == "" { e.Date = "" } if e.FeedID == 0 { e.FeedID = 0 } if e.Marked == "" { e.Marked = "0" } if u.Tostr(e.Content) == "" { e.Content = template.HTML("") } var unread string = "1" if e.Unread == false { unread = "0" } _, err = stmtSaveEntry.Exec(e.Title, e.Link, e.Date, e.FeedID, e.Marked, unread, u.Tostr(e.Content), e.ID) if err != nil { glog.Errorf("stmtSaveEntry.Exec(%s,%s,%s,%s,%s,%s,%s,%s): %s", e.Title, e.Link, e.Date, e.FeedID, e.Marked, unread, u.Tostr(e.Content), e.ID, err) return err } } else { _, err := stmtAddEntry.Exec(e.Title, e.Link, e.FeedID, e.Marked, u.Tostr(e.Content), u.Tostr(e.ContentHash), e.GUID, userName) if err != nil { glog.Errorf("stmtAddEntry: %s", err) return err } } return err }
func (c Category) Unread() (count int) { mcf := "Category" + u.Tostr(c.ID) + "_UnreadCount" err := mc.Get(mcf, &count) switch { case err != nil && err.Error() == "memcache: cache miss": for _, f := range c.Feeds() { count = count + f.Unread() } go mc.Set(mcf, count) case err != nil: glog.Errorf("mc.Get(%s): %s", mcf, err) return 0 } return count }
func GetFeedsWithoutCats(userName string) (allFeeds []Feed) { mc.GetOr("FeedsWithoutCats"+userName, &allFeeds, func() { print("-") rows, err := stmtGetFeedsWithoutCats.Query(userName) if err != nil { glog.Errorf("stmtGetFeedsWithoutCats.Query(%s): %s", userName, err) } for rows.Next() { var feed Feed rows.Scan(&feed.ID, &feed.Title, &feed.Url, &feed.LastUpdated, &feed.UserName, &feed.Public, &feed.CategoryID, &feed.ViewMode, &feed.AutoscrollPX, &feed.Exclude, &feed.ExcludeData, &feed.ErrorString, &feed.Expirey) if feed.Title == "" { feed.Title = "--untitled--" } feed.Title = html.UnescapeString(feed.Title) allFeeds = append(allFeeds, feed) mc.Set("Feed"+u.Tostr(feed.ID)+"_", feed) //cache the feed, because why not } }) return allFeeds }
func GetCategories(userName string) []Category { var allCats []Category var catids []int //Try getting a category list from cache rows, err := stmtGetCats.Query(userName) if err != nil { err.Error() return allCats } for rows.Next() { var cat Category rows.Scan(&cat.Name, &cat.UserName, &cat.Description, &cat.ID, &cat.Exclude) allCats = append(allCats, cat) catids = append(catids, cat.ID) go mc.Set("Category"+u.Tostr(cat.ID)+"_", cat) } go mc.Set("CategoryList_"+userName, catids) return allCats }
func GetFeed(id int) (feed Feed, err error) { if id < 1 { glog.Errorf("Non valid id passed to GetFeed %s", id) return feed, errors.New("feed Invalid ID") } var fcn = "Feed" + u.Tostr(id) + "_" mc.GetOr(fcn, &feed, func() { err = stmtGetFeed.QueryRow(id).Scan(&feed.ID, &feed.Title, &feed.Url, &feed.LastUpdated, &feed.UserName, &feed.Public, &feed.CategoryID, &feed.ViewMode, &feed.AutoscrollPX, &feed.Exclude, &feed.ExcludeData, &feed.ErrorString, &feed.Expirey) if err != nil { glog.Errorf("stmtGetFeed.QueryRow(%s).Scan(...): %s", id, err) } if feed.Title == "" { feed.Title = "--untitled--" } feed.Title = html.UnescapeString(feed.Title) err := mc.Set(fcn, feed) if err != nil { glog.Errorf("mc.Set(feed%v): %s", feed.ID, err) } }) return feed, err }
func GetAllFeeds() []Feed { var allFeeds []Feed var feedids []int err := mc.Get("FeedList", &feedids) rows, err := stmtGetAllFeeds.Query() if err != nil { glog.Errorf("stmtGetAllFeeds.Query(): %s", err) return allFeeds } for rows.Next() { var feed Feed rows.Scan(&feed.ID, &feed.Title, &feed.Url, &feed.LastUpdated, &feed.UserName, &feed.Public, &feed.CategoryID, &feed.ViewMode, &feed.AutoscrollPX, &feed.Exclude, &feed.ExcludeData, &feed.ErrorString, &feed.Expirey) if feed.Title == "" { feed.Title = "--untitled--" } feed.Title = html.UnescapeString(feed.Title) allFeeds = append(allFeeds, feed) feedids = append(feedids, feed.ID) go mc.Set("Feed"+u.Tostr(feed.ID)+"_", feed) } mc.Set("FeedList", feedids) return allFeeds }
func (f Feed) ClearCache() { mc.DeleteLike("Feed" + u.Tostr(f.ID) + "_") cl := []string{"Feed" + u.Tostr(f.ID) + "_", "FeedsWithoutCats" + f.UserName, "FeedList", "Feed" + u.Tostr(f.ID) + "_UnreadCount", "Feed" + u.Tostr(f.ID) + "_readentries", "Feed" + u.Tostr(f.ID) + "_unreadentries", "Feed" + u.Tostr(f.ID) + "_markedentries", } for _, i := range cl { err := mc.Delete(i) if err != nil && err.Error() != "memcache: cache miss" { glog.Errorf("mc.Delete(%s): %s", i, err) return } } f.Category().ClearCache() }
func (c Category) MarkEntriesRead(ids []string) (err error) { if len(ids) == 0 { err = fmt.Errorf("Ids is null") } else { // make sure they're all integers var id_list []string for _, i := range ids { _, err := strconv.Atoi(i) if err != nil { glog.Errorf("Non int passed to markEntriesRead: %s", err) } else { id_list = append(id_list, i) } } if len(id_list) < 1 { err = fmt.Errorf("Not enough valid ids passed") return err } j := strings.Join(id_list, ",") sql := "update ttrss_entries set unread='0' where id in (" + j + ")" stmtUpdateMarkEntries, err := u.Sth(db, sql) if err != nil { glog.Errorf("Sth(db, %s): %s", sql, err) return err } _, err = stmtUpdateMarkEntries.Exec() if err != nil { glog.Errorf("stmtUpdateMarkEntries.Exec: %s\n%s\n", err, sql) return err } mc.Decrement("Category"+u.Tostr(c.ID)+"_UnreadCount", uint64(len(ids))) mc.Delete("Category" + u.Tostr(c.ID) + "_unreadentries") mc.Delete("Category" + u.Tostr(c.ID) + "_readentries") for _, f := range c.Feeds() { mc.Delete("Feed" + u.Tostr(f.ID) + "_readentries") mc.Delete("Feed" + u.Tostr(f.ID) + "_UnreadCount") mc.Delete("Feed" + u.Tostr(f.ID) + "_unreadentries") } } return err }
func (f Feed) ReadEntries() (el []Entry) { mc.GetOr("Feed"+u.Tostr(f.ID)+"_readentries", &el, func() { el = f.GetEntriesByParam("unread = '0'") }) return el }
func (f Feed) DecrementUnread() { mc.Decrement("Category"+u.Tostr(f.CategoryID)+"_UnreadCount", 1) mc.Decrement("Feed"+u.Tostr(f.ID)+"_UnreadCount", 1) f.ClearEntries() return }
func (f Feed) MarkedEntries() (el []Entry) { mc.GetOr("Feed"+u.Tostr(f.ID)+"_markedentries", &el, func() { el = f.GetEntriesByParam("marked = 1") }) return el }
func handleAdd(w http.ResponseWriter, r *http.Request) { t0 := time.Now() loggedin, user := auth.LoggedIn(w, r) if !loggedin { http.Redirect(w, r, "/", http.StatusFound) return } if !user.Admin { glog.Errorf("user %s attempting to add, not an admin", user) return } var cg string u.PathVars(r, "/add/", &cg) type Meta struct { User auth.User Message template.HTML Consoles []game.Console Search string } var meta Meta meta.User = user cl, err := game.GetConsoles(user) meta.Consoles = cl sort.Sort(game.ConsoleName(cl)) if err != nil { glog.Errorf("game.GetConsoles(%s): %s", user, err) } switch cg { case "console": var c game.Console c.Name = r.PostFormValue("name") c.Manufacturer = r.PostFormValue("manufacturer") c.Year = u.Toint(r.PostFormValue("year")) c.User = user c.Picture = r.PostFormValue("picture") err := c.Save() if err != nil { glog.Errorf("Saving console (%s): %s", c, err) meta.Message = template.HTML(err.Error()) } else { meta.Message = template.HTML("Saved") } case "game": var g game.Game g.Name = r.PostFormValue("name") g.Publisher = r.PostFormValue("publisher") g.Year = u.Toint(r.PostFormValue("year")) g.ConsoleName = r.PostFormValue("console") g.User = user g, err := game.InsertGame(g) if err != nil { glog.Errorf("Saving game (%s): %s", g, err) meta.Message = "Error saving" } else { meta.Message = template.HTML("Saved: <a href='/game/" + u.Tostr(g.ID) + "'>Game</a>") } } if err := tmpl.ExecuteTemplate(w, "add", meta); err != nil { glog.Errorf("ExecuteTemplate(w,add,meta): %s", err) } fmt.Printf("handleAdd %v\n", time.Now().Sub(t0)) }
func (f Feed) Category() (c Category) { c = GetCat(u.Tostr(f.CategoryID)) return c }
func handleEdit(w http.ResponseWriter, r *http.Request) { t0 := time.Now() loggedin, user := auth.LoggedIn(w, r) if !loggedin { http.Redirect(w, r, "/", http.StatusFound) return } if !user.Admin { glog.Errorf("user %s attempting to add, not an admin", user) return } var cg string u.PathVars(r, "/edit/", &cg) switch cg { case "console": c, err := game.GetConsole(r.FormValue("name"), user) if err != nil { glog.Errorf("GetConsole(%s,user): %s", r.PostFormValue("name"), err) } type Meta struct { User auth.User Message template.HTML Console game.Console CheapestGame game.Game Search string } var meta Meta meta.User = user meta.Console = c wl, err := game.UserWantedGames(user) if err != nil { glog.Errorf("game.UserWantedGames(user): %s", err) return } meta.CheapestGame = game.Filter(wl).Cheapest() switch r.PostFormValue("action") { case "submit": c.Name = r.PostFormValue("name") c.Manufacturer = r.PostFormValue("manufacturer") c.Year = u.Toint(r.PostFormValue("year")) c.Picture = r.PostFormValue("picture") if err := c.Save(); err != nil { glog.Errorf("Saving console (%s): %s", c, err) meta.Message = template.HTML(err.Error()) } else { meta.Message = template.HTML("Saved") } meta.Console = c if err := tmpl.ExecuteTemplate(w, "edit_console", meta); err != nil { glog.Errorf("ExecuteTemplate(w,edit_console,meta): %s", err) } case "delete": if err := tmpl.ExecuteTemplate(w, "really_delete_console", meta); err != nil { glog.Errorf("ExecuteTemplate(w,really_delete_console,meta): %s", err) return } case "reallydelete": err := c.Delete() if err != nil { glog.Errorf("c.Delete(): %s", err) } http.Redirect(w, r, "/", http.StatusFound) default: if err := tmpl.ExecuteTemplate(w, "edit_console", meta); err != nil { glog.Errorf("ExecuteTemplate(w,edit_console,meta): %s", err) } } case "game": id := u.Toint(r.FormValue("id")) g, err := game.GetGame(id, user) if err != nil { glog.Errorf("game.GetGame(%v,user): %s", id, err) return } type Meta struct { User auth.User CheapestGame game.Game Game game.Game Message template.HTML Search string } var meta Meta meta.User = user meta.Game = g wl, err := game.UserWantedGames(user) if err != nil { glog.Errorf("game.UserWantedGames(user): %s", err) return } meta.CheapestGame = game.Filter(wl).Cheapest() switch r.PostFormValue("action") { case "submit": g.Name = r.PostFormValue("name") g.Publisher = r.PostFormValue("publisher") g.Year = u.Toint(r.PostFormValue("year")) g.ConsoleName = r.PostFormValue("console") if err := g.Save(); err != nil { glog.Errorf("Saving game (%s): %s", g, err) meta.Message = "Error saving" } else { fmt.Printf("Saved game: %s", g) meta.Message = template.HTML("Saved: <a href='/game/" + u.Tostr(g.ID) + "'>Game</a>") } meta.Game = g case "delete": if err := tmpl.ExecuteTemplate(w, "really_delete_game", meta); err != nil { glog.Errorf("ExecuteTemplate(w,really_delete_game,meta): %s", err) return } case "reallydelete": err := g.Delete() if err != nil { glog.Errorf("g.Delete(): %s", err) } http.Redirect(w, r, "/", http.StatusFound) default: meta.Message = template.HTML("in default") } if err := tmpl.ExecuteTemplate(w, "edit_game", meta); err != nil { glog.Errorf("ExecuteTemplate(w,edit_game, meta): %s", err) return } } fmt.Printf("handleEdit %v\n", time.Now().Sub(t0)) }
func (f Feed) GetEntriesByParam(p string) []Entry { var query = "select " + entrySelectString + " from ttrss_entries e where e.feed_id = " + u.Tostr(f.ID) + " and " + p + " order by e.id ASC;" el := getEntriesFromSql(query) mc.Set("FeedCurrent"+f.UserName, el) return el }