package database import ( "time" log "github.com/cihub/seelog" ) type Visit struct { ID int `pg:"type:serial"` Downloads int `pg:"type:integer,notnull"` Views int `pg:"type:integer,notnull"` BookID string `pg:"type:varchar(16),unique"` Book *Book `pg:"rel:has-one"` } func (db *pgDB) IncViews(ID string) error { visit := &Visit{ Downloads: 0, Views: 1, BookID: ID, } _, err := db.sql.Model(visit). OnConflict("(book_id) DO UPDATE"). Set("views = Visit.views + 1"). Insert() return err } func (db *pgDB) IncDownloads(ID string) error { visit := &Visit{ Downloads: 1, Views: 0, BookID: ID, } _, err := db.sql.Model(visit). OnConflict("(book_id) DO UPDATE"). Set("downloads = Visit.downloads + 1"). Insert() return err } func (db *pgDB) GetDownloadCounter(ID string) (int, error) { var num int err := db.sql.Model(&Visit{}). Column("downloads"). Where("book_id = ?", ID). Select(&num) return num, err } func (db *pgDB) GetFrontPage() FrontPage { return db.frontPage } func (db *pgDB) frontPageUpdater() { periodicity := 5 * time.Minute for true { tags, err := db.getTags(tagsDisplay) if err != nil { log.Error("Error updating tags: ", err) } else { db.frontPage.Tags = tags } count, err := db.getCount() if err != nil { log.Error("Error updating count: ", err) } else { db.frontPage.Count = count } last, _, err := db.GetBooks("", booksFrontPage, 0) if err != nil { log.Error("Error updating last books: ", err) } else { db.frontPage.Last = last } visited, err := db.getVisitedBooks(booksFrontPage) if err != nil { log.Error("Error updating visited books: ", err) } else { db.frontPage.Visited = visited } download, err := db.getDownloadedBooks(booksFrontPage) if err != nil { log.Error("Error updating download books: ", err) } else { db.frontPage.Download = download } time.Sleep(periodicity) } } func (db *pgDB) GetTags() ([]string, error) { return db.frontPage.Tags, nil } func (db *pgDB) getVisitedBooks(num int) (books []Book, err error) { err = db.sql.Model(&books). Column("book.*"). Join("INNER JOIN visits ON book.id = visits.book_id "). Where("visits.views > 0 AND book.active"). Order("views DESC NULLS LAST"). Limit(num). Select() return } func (db *pgDB) getDownloadedBooks(num int) (books []Book, err error) { err = db.sql.Model(&books). Column("book.*"). Join("INNER JOIN visits ON book.id = visits.book_id "). Where("visits.downloads > 0 AND book.active"). Order("downloads DESC NULLS LAST"). Limit(num). Select() return } func (db *pgDB) getTags(num int) (tags []string, err error) { err = db.sql.Model(&Book{}). ColumnExpr("unnest(tags) as tag"). Where("active = true"). Group("tag"). OrderExpr("count(*) DESC"). Limit(num). Select(&tags) return tags, err } func (db *pgDB) getCount() (count int, err error) { err = db.sql.Model(&Book{}). ColumnExpr("count(*)"). Where("active = true"). Select(&count) return count, err }