Merge branch 'master' into user

This commit is contained in:
Las Zenow 2014-02-19 01:23:12 +01:00
commit 4695977bd8
8 changed files with 302 additions and 435 deletions

4
README
View file

@ -13,11 +13,9 @@ https://gitorious.org/trantor/
In order to run Trantor, you need to install the following packages:
* Go language
* Epub development library
* Mongodb
* Bazaar
* Mercurial
* Git (necessary only if you want to deal with the repository)
* Git
Under Debian Wheezy you can simply run:

View file

@ -34,6 +34,7 @@ const (
MINUTES_UPDATE_MONTHLY_D = 60*24 + 17
MINUTES_UPDATE_LOGGER = 5
TAGS_DISPLAY = 50
BOOKS_FRONT_PAGE = 6
SEARCH_ITEMS_PAGE = 20
NEW_ITEMS_PAGE = 50
NUM_NEWS = 10

View file

@ -4,6 +4,7 @@ import log "github.com/cihub/seelog"
import (
"crypto/md5"
"errors"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"os"
@ -182,14 +183,14 @@ func (d *DB) GetBooks(query bson.M, r ...int) (books []Book, num int, err error)
/* Get the most visited books
*/
func (d *DB) GetVisitedBooks(num int) (books []Book, err error) {
func (d *DB) GetVisitedBooks() (books []Book, err error) {
visitedColl := d.session.DB(DB_NAME).C(VISITED_COLL)
bookId, err := GetBooksVisited(num, visitedColl)
bookId, err := GetBooksVisited(visitedColl)
if err != nil {
return nil, err
}
books = make([]Book, num)
books = make([]Book, len(bookId))
for i, id := range bookId {
booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL)
booksColl.Find(bson.M{"_id": id}).One(&books[i])
@ -199,21 +200,22 @@ func (d *DB) GetVisitedBooks(num int) (books []Book, err error) {
}
func (d *DB) UpdateMostVisited() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateMostVisited(statsColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(VISITED_COLL)
return u.UpdateMostBooks("book")
}
/* Get the most downloaded books
*/
func (d *DB) GetDownloadedBooks(num int) (books []Book, err error) {
func (d *DB) GetDownloadedBooks() (books []Book, err error) {
downloadedColl := d.session.DB(DB_NAME).C(DOWNLOADED_COLL)
bookId, err := GetBooksVisited(num, downloadedColl)
bookId, err := GetBooksVisited(downloadedColl)
if err != nil {
return nil, err
}
books = make([]Book, num)
books = make([]Book, len(bookId))
for i, id := range bookId {
booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL)
booksColl.Find(bson.M{"_id": id}).One(&books[i])
@ -223,9 +225,10 @@ func (d *DB) GetDownloadedBooks(num int) (books []Book, err error) {
}
func (d *DB) UpdateDownloadedBooks() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateMostDownloaded(statsColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(DOWNLOADED_COLL)
return u.UpdateMostBooks("download")
}
/* optional parameters: length and start index
@ -250,84 +253,93 @@ func (d *DB) GetFS(prefix string) *mgo.GridFS {
return d.session.DB(DB_NAME).GridFS(prefix)
}
func (d *DB) GetTags(numTags int) ([]string, error) {
func (d *DB) GetTags() ([]string, error) {
tagsColl := d.session.DB(DB_NAME).C(TAGS_COLL)
return GetTags(numTags, tagsColl)
return GetTags(tagsColl)
}
func (d *DB) UpdateTags() error {
booksColl := d.session.DB(DB_NAME).C(BOOKS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateTags(booksColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(BOOKS_COLL)
u.dst = d.session.DB(DB_NAME).C(TAGS_COLL)
return u.UpdateTags()
}
type VisitType int
const (
hourly_visits = iota
daily_visits
monthly_visits
hourly_downloads
daily_downloads
monthly_downloads
)
type Visits struct {
Date int64 "_id"
Count int "value"
Date time.Time "date"
Count int "count"
}
func (d *DB) GetHourVisits() ([]Visits, error) {
hourlyColl := d.session.DB(DB_NAME).C(HOURLY_VISITS_COLL)
return GetVisits(hourlyColl)
func (d *DB) GetVisits(visitType VisitType) ([]Visits, error) {
var coll *mgo.Collection
switch visitType {
case hourly_visits:
coll = d.session.DB(DB_NAME).C(HOURLY_VISITS_COLL)
case daily_visits:
coll = d.session.DB(DB_NAME).C(DAILY_VISITS_COLL)
case monthly_visits:
coll = d.session.DB(DB_NAME).C(MONTHLY_VISITS_COLL)
case hourly_downloads:
coll = d.session.DB(DB_NAME).C(HOURLY_DOWNLOADS_COLL)
case daily_downloads:
coll = d.session.DB(DB_NAME).C(DAILY_DOWNLOADS_COLL)
case monthly_downloads:
coll = d.session.DB(DB_NAME).C(MONTHLY_DOWNLOADS_COLL)
default:
return nil, errors.New("Not valid VisitType")
}
return GetVisits(coll)
}
func (d *DB) UpdateHourVisits() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateHourVisits(statsColl)
}
func (d *DB) GetDayVisits() ([]Visits, error) {
dailyColl := d.session.DB(DB_NAME).C(DAILY_VISITS_COLL)
return GetVisits(dailyColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(HOURLY_VISITS_COLL)
return u.UpdateHourVisits(false)
}
func (d *DB) UpdateDayVisits() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateDayVisits(statsColl)
}
func (d *DB) GetMonthVisits() ([]Visits, error) {
monthlyColl := d.session.DB(DB_NAME).C(MONTHLY_VISITS_COLL)
return GetVisits(monthlyColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(DAILY_VISITS_COLL)
return u.UpdateDayVisits(false)
}
func (d *DB) UpdateMonthVisits() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateMonthVisits(statsColl)
}
func (d *DB) GetHourDownloads() ([]Visits, error) {
hourlyColl := d.session.DB(DB_NAME).C(HOURLY_DOWNLOADS_COLL)
return GetVisits(hourlyColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(MONTHLY_VISITS_COLL)
return u.UpdateMonthVisits(false)
}
func (d *DB) UpdateHourDownloads() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateHourDownloads(statsColl)
}
func (d *DB) GetDayDownloads() ([]Visits, error) {
dailyColl := d.session.DB(DB_NAME).C(DAILY_DOWNLOADS_COLL)
return GetVisits(dailyColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(HOURLY_DOWNLOADS_COLL)
return u.UpdateHourVisits(true)
}
func (d *DB) UpdateDayDownloads() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateDayDownloads(statsColl)
}
func (d *DB) GetMonthDownloads() ([]Visits, error) {
monthlyColl := d.session.DB(DB_NAME).C(MONTHLY_DOWNLOADS_COLL)
return GetVisits(monthlyColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(DAILY_DOWNLOADS_COLL)
return u.UpdateDayVisits(true)
}
func (d *DB) UpdateMonthDownloads() error {
statsColl := d.session.DB(DB_NAME).C(STATS_COLL)
mr := NewMR(d.session.DB(DB_NAME))
return mr.UpdateMonthDownloads(statsColl)
var u DBUpdate
u.src = d.session.DB(DB_NAME).C(STATS_COLL)
u.dst = d.session.DB(DB_NAME).C(MONTHLY_DOWNLOADS_COLL)
return u.UpdateMonthVisits(true)
}

200
db_stats.go Normal file
View file

@ -0,0 +1,200 @@
package main
import (
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"time"
)
type DBUpdate struct {
src *mgo.Collection
dst *mgo.Collection
}
func GetTags(tagsColl *mgo.Collection) ([]string, error) {
var result []struct {
Tag string "_id"
}
err := tagsColl.Find(nil).Sort("-count").All(&result)
if err != nil {
return nil, err
}
tags := make([]string, len(result))
for i, r := range result {
tags[i] = r.Tag
}
return tags, nil
}
func GetBooksVisited(visitedColl *mgo.Collection) ([]bson.ObjectId, error) {
var result []struct {
Book bson.ObjectId "_id"
}
err := visitedColl.Find(nil).Sort("-count").All(&result)
if err != nil {
return nil, err
}
books := make([]bson.ObjectId, len(result))
for i, r := range result {
books[i] = r.Book
}
return books, nil
}
func GetVisits(visitsColl *mgo.Collection) ([]Visits, error) {
var result []Visits
err := visitsColl.Find(nil).All(&result)
return result, err
}
func (u *DBUpdate) UpdateTags() error {
var tags []struct {
Tag string "_id"
Count int "count"
}
err := u.src.Pipe([]bson.M{
{"$project": bson.M{"subject": 1}},
{"$unwind": "$subject"},
{"$group": bson.M{"_id": "$subject", "count": bson.M{"$sum": 1}}},
{"$sort": bson.M{"count": -1}},
{"$limit": TAGS_DISPLAY},
}).All(&tags)
if err != nil {
return err
}
u.dst.DropCollection()
for _, tag := range tags {
err = u.dst.Insert(tag)
if err != nil {
return err
}
}
return nil
}
func (u *DBUpdate) UpdateMostBooks(section string) error {
const numDays = 30
start := time.Now().UTC().Add(-numDays * 24 * time.Hour)
var books []struct {
Book string "_id"
Count int "count"
}
err := u.src.Pipe([]bson.M{
{"$match": bson.M{"date": bson.M{"$gt": start}, "section": section}},
{"$project": bson.M{"id": 1}},
{"$group": bson.M{"_id": "$id", "count": bson.M{"$sum": 1}}},
{"$sort": bson.M{"count": -1}},
{"$limit": BOOKS_FRONT_PAGE},
}).All(&books)
if err != nil {
return err
}
u.dst.DropCollection()
for _, book := range books {
err = u.dst.Insert(book)
if err != nil {
return err
}
}
return nil
}
func (u *DBUpdate) UpdateHourVisits(isDownloads bool) error {
const numDays = 2
spanStore := numDays * 24 * time.Hour
return u.updateVisits(hourInc, spanStore, isDownloads)
}
func (u *DBUpdate) UpdateDayVisits(isDownloads bool) error {
const numDays = 30
spanStore := numDays * 24 * time.Hour
return u.updateVisits(dayInc, spanStore, isDownloads)
}
func (u *DBUpdate) UpdateMonthVisits(isDownloads bool) error {
const numDays = 365
spanStore := numDays * 24 * time.Hour
return u.updateVisits(monthInc, spanStore, isDownloads)
}
func hourInc(date time.Time) time.Time {
const span = time.Hour
return date.Add(span).Truncate(span)
}
func dayInc(date time.Time) time.Time {
const span = 24 * time.Hour
return date.Add(span).Truncate(span)
}
func monthInc(date time.Time) time.Time {
const span = 24 * time.Hour
return date.AddDate(0, 1, 1-date.Day()).Truncate(span)
}
func (u *DBUpdate) updateVisits(incTime func(time.Time) time.Time, spanStore time.Duration, isDownloads bool) error {
start := u.calculateStart(spanStore)
for start.Before(time.Now().UTC()) {
stop := incTime(start)
var count int
var err error
if isDownloads {
count, err = u.countDownloads(start, stop)
} else {
count = u.countVisits(start, stop)
}
if err != nil {
return err
}
err = u.dst.Insert(bson.M{"date": start, "count": count})
if err != nil {
return err
}
start = stop
}
_, err := u.dst.RemoveAll(bson.M{"date": bson.M{"$lt": time.Now().UTC().Add(-spanStore)}})
return err
}
func (u *DBUpdate) calculateStart(spanStore time.Duration) time.Time {
var date struct {
Id bson.ObjectId `bson:"_id"`
Date time.Time `bson:"date"`
}
err := u.dst.Find(bson.M{}).Sort("-date").One(&date)
if err == nil {
u.dst.RemoveId(date.Id)
return date.Date
}
return time.Now().UTC().Add(-spanStore).Truncate(time.Hour)
}
func (u *DBUpdate) countVisits(start time.Time, stop time.Time) int {
var result struct {
Count int "count"
}
err := u.src.Pipe([]bson.M{
{"$match": bson.M{"date": bson.M{"$gte": start, "$lt": stop}}},
{"$group": bson.M{"_id": "$session"}},
{"$group": bson.M{"_id": 1, "count": bson.M{"$sum": 1}}},
}).One(&result)
if err != nil {
return 0
}
return result.Count
}
func (u *DBUpdate) countDownloads(start time.Time, stop time.Time) (int, error) {
query := bson.M{"date": bson.M{"$gte": start, "$lt": stop}, "section": "download"}
return u.src.Find(query).Count()
}

View file

@ -1,283 +0,0 @@
package main
import (
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson"
"time"
)
func GetTags(numTags int, tagsColl *mgo.Collection) ([]string, error) {
var result []struct {
Tag string "_id"
}
err := tagsColl.Find(nil).Sort("-value").Limit(numTags).All(&result)
if err != nil {
return nil, err
}
tags := make([]string, len(result))
for i, r := range result {
tags[i] = r.Tag
}
return tags, nil
}
func GetBooksVisited(num int, visitedColl *mgo.Collection) ([]bson.ObjectId, error) {
var result []struct {
Book bson.ObjectId "_id"
}
err := visitedColl.Find(nil).Sort("-value").Limit(num).All(&result)
if err != nil {
return nil, err
}
books := make([]bson.ObjectId, len(result))
for i, r := range result {
books[i] = r.Book
}
return books, nil
}
func GetVisits(visitsColl *mgo.Collection) ([]Visits, error) {
var result []Visits
err := visitsColl.Find(nil).All(&result)
return result, err
}
type MR struct {
database *mgo.Database
}
func NewMR(database *mgo.Database) *MR {
m := new(MR)
m.database = database
return m
}
func (m *MR) UpdateTags(booksColl *mgo.Collection) error {
var mr mgo.MapReduce
mr.Map = `function() {
if (this.subject) {
this.subject.forEach(function(s) { emit(s, 1); });
}
}`
mr.Reduce = `function(tag, vals) {
var count = 0;
vals.forEach(function() { count += 1; });
return count;
}`
return m.update(&mr, bson.M{"active": true}, booksColl, TAGS_COLL)
}
func (m *MR) UpdateMostVisited(statsColl *mgo.Collection) error {
var mr mgo.MapReduce
mr.Map = `function() {
if (this.id) {
emit(this.id, 1);
}
}`
mr.Reduce = `function(tag, vals) {
var count = 0;
vals.forEach(function() { count += 1; });
return count;
}`
return m.update(&mr, bson.M{"section": "book"}, statsColl, VISITED_COLL)
}
func (m *MR) UpdateMostDownloaded(statsColl *mgo.Collection) error {
var mr mgo.MapReduce
mr.Map = `function() {
emit(this.id, 1);
}`
mr.Reduce = `function(tag, vals) {
var count = 0;
vals.forEach(function() { count += 1; });
return count;
}`
return m.update(&mr, bson.M{"section": "download"}, statsColl, DOWNLOADED_COLL)
}
func (m *MR) UpdateHourVisits(statsColl *mgo.Collection) error {
const numDays = 2
start := time.Now().UTC().Add(-numDays * 24 * time.Hour)
const reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
var mr mgo.MapReduce
mr.Map = `function() {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth(),
this.date.getUTCDate(),
this.date.getUTCHours());
emit({date: date, session: this.session}, 1);
}`
mr.Reduce = reduce
err := m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, HOURLY_VISITS_COLL+"_raw")
if err != nil {
return err
}
var mr2 mgo.MapReduce
mr2.Map = `function() {
emit(this['_id']['date'], 1);
}`
mr2.Reduce = reduce
hourly_raw := m.database.C(HOURLY_VISITS_COLL + "_raw")
return m.update(&mr2, bson.M{}, hourly_raw, HOURLY_VISITS_COLL)
}
func (m *MR) UpdateDayVisits(statsColl *mgo.Collection) error {
const numDays = 30
start := time.Now().UTC().Add(-numDays * 24 * time.Hour).Truncate(24 * time.Hour)
const reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
var mr mgo.MapReduce
mr.Map = `function() {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth(),
this.date.getUTCDate());
emit({date: date, session: this.session}, 1);
}`
mr.Reduce = reduce
err := m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, DAILY_VISITS_COLL+"_raw")
if err != nil {
return err
}
var mr2 mgo.MapReduce
mr2.Map = `function() {
emit(this['_id']['date'], 1);
}`
mr2.Reduce = reduce
daily_raw := m.database.C(DAILY_VISITS_COLL + "_raw")
return m.update(&mr2, bson.M{}, daily_raw, DAILY_VISITS_COLL)
}
func (m *MR) UpdateMonthVisits(statsColl *mgo.Collection) error {
const numDays = 365
start := time.Now().UTC().Add(-numDays * 24 * time.Hour).Truncate(24 * time.Hour)
const reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
var mr mgo.MapReduce
mr.Map = `function() {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth());
emit({date: date, session: this.session}, 1);
}`
mr.Reduce = reduce
err := m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, MONTHLY_VISITS_COLL+"_raw")
if err != nil {
return err
}
var mr2 mgo.MapReduce
mr2.Map = `function() {
emit(this['_id']['date'], 1);
}`
mr2.Reduce = reduce
monthly_raw := m.database.C(MONTHLY_VISITS_COLL + "_raw")
return m.update(&mr2, bson.M{}, monthly_raw, MONTHLY_VISITS_COLL)
}
func (m *MR) UpdateHourDownloads(statsColl *mgo.Collection) error {
const numDays = 2
start := time.Now().UTC().Add(-numDays * 24 * time.Hour)
var mr mgo.MapReduce
mr.Map = `function() {
if (this.section == "download") {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth(),
this.date.getUTCDate(),
this.date.getUTCHours());
emit(date, 1);
}
}`
mr.Reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
return m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, HOURLY_DOWNLOADS_COLL)
}
func (m *MR) UpdateDayDownloads(statsColl *mgo.Collection) error {
const numDays = 30
start := time.Now().UTC().Add(-numDays * 24 * time.Hour).Truncate(24 * time.Hour)
var mr mgo.MapReduce
mr.Map = `function() {
if (this.section == "download") {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth(),
this.date.getUTCDate());
emit(date, 1);
}
}`
mr.Reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
return m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, DAILY_DOWNLOADS_COLL)
}
func (m *MR) UpdateMonthDownloads(statsColl *mgo.Collection) error {
const numDays = 365
start := time.Now().UTC().Add(-numDays * 24 * time.Hour).Truncate(24 * time.Hour)
var mr mgo.MapReduce
mr.Map = `function() {
if (this.section == "download") {
var date = Date.UTC(this.date.getUTCFullYear(),
this.date.getUTCMonth());
emit(date, 1);
}
}`
mr.Reduce = `function(date, vals) {
var count = 0;
vals.forEach(function(v) { count += v; });
return count;
}`
return m.update(&mr, bson.M{"date": bson.M{"$gte": start}}, statsColl, MONTHLY_DOWNLOADS_COLL)
}
func (m *MR) update(mr *mgo.MapReduce, query bson.M, queryColl *mgo.Collection, storeColl string) error {
metaColl := m.database.C(META_COLL)
_, err := metaColl.RemoveAll(bson.M{"type": storeColl})
if err != nil {
return err
}
mr.Out = bson.M{"replace": storeColl}
_, err = queryColl.Find(query).MapReduce(mr, nil)
if err != nil {
return err
}
return metaColl.Insert(bson.M{"type": storeColl})
}
func (m *MR) isOutdated(coll string, minutes float64) bool {
var result struct {
Id bson.ObjectId `bson:"_id"`
}
metaColl := m.database.C(META_COLL)
err := metaColl.Find(bson.M{"type": coll}).One(&result)
if err != nil {
return true
}
lastUpdate := result.Id.Time()
return time.Since(lastUpdate).Minutes() > minutes
}

View file

@ -69,12 +69,12 @@ func statsHandler(h handler) {
var data statsData
data.S = GetStatus(h)
data.S.Stats = true
data.HVisits = getHourlyVisits(h.db)
data.DVisits = getDailyVisits(h.db)
data.MVisits = getMonthlyVisits(h.db)
data.HDownloads = getHourlyDownloads(h.db)
data.DDownloads = getDailyDownloads(h.db)
data.MDownloads = getMonthlyDownloads(h.db)
data.HVisits = getVisits(hourlyLabel, h.db, hourly_visits)
data.DVisits = getVisits(dailyLabel, h.db, daily_visits)
data.MVisits = getVisits(monthlyLabel, h.db, monthly_visits)
data.HDownloads = getVisits(hourlyLabel, h.db, hourly_downloads)
data.DDownloads = getVisits(dailyLabel, h.db, daily_downloads)
data.MDownloads = getVisits(monthlyLabel, h.db, monthly_downloads)
loadTemplate(h.w, "stats", data)
}
@ -94,89 +94,28 @@ type visitData struct {
Count int
}
func getHourlyVisits(db *DB) []visitData {
var visits []visitData
visit, _ := db.GetHourVisits()
for _, v := range visit {
var elem visitData
hour := time.Unix(v.Date/1000, 0).UTC().Hour()
elem.Label = strconv.Itoa(hour + 1)
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
func hourlyLabel(date time.Time) string {
return strconv.Itoa(date.Hour() + 1)
}
func getDailyVisits(db *DB) []visitData {
var visits []visitData
visit, _ := db.GetDayVisits()
for _, v := range visit {
var elem visitData
day := time.Unix(v.Date/1000, 0).UTC().Day()
elem.Label = strconv.Itoa(day)
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
func dailyLabel(date time.Time) string {
return strconv.Itoa(date.Day())
}
func getMonthlyVisits(db *DB) []visitData {
var visits []visitData
visit, _ := db.GetMonthVisits()
for _, v := range visit {
var elem visitData
month := time.Unix(v.Date/1000, 0).UTC().Month()
elem.Label = month.String()
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
func monthlyLabel(date time.Time) string {
return date.Month().String()
}
func getHourlyDownloads(db *DB) []visitData {
func getVisits(funcLabel func(time.Time) string, db *DB, visitType VisitType) []visitData {
var visits []visitData
visit, _ := db.GetHourDownloads()
for _, v := range visit {
var elem visitData
hour := time.Unix(v.Date/1000, 0).UTC().Hour()
elem.Label = strconv.Itoa(hour + 1)
elem.Count = v.Count
visits = append(visits, elem)
visit, err := db.GetVisits(visitType)
if err != nil {
log.Warn("GetVisits error (", visitType, "): ", err)
}
return visits
}
func getDailyDownloads(db *DB) []visitData {
var visits []visitData
visit, _ := db.GetDayDownloads()
for _, v := range visit {
var elem visitData
day := time.Unix(v.Date/1000, 0).UTC().Day()
elem.Label = strconv.Itoa(day)
elem.Count = v.Count
visits = append(visits, elem)
}
return visits
}
func getMonthlyDownloads(db *DB) []visitData {
var visits []visitData
visit, _ := db.GetMonthDownloads()
for _, v := range visit {
var elem visitData
month := time.Unix(v.Date/1000, 0).UTC().Month()
elem.Label = month.String()
elem.Label = funcLabel(v.Date.UTC())
elem.Count = v.Count
visits = append(visits, elem)
}

View file

@ -40,8 +40,8 @@ func uploadEpub(filename string, db *DB) {
return
}
book["filename"] = id
book["filenamesize"] = size
book["file"] = id
book["filesize"] = size
err = db.InsertBook(book)
if err != nil {
log.Error("Error storing metadata (", title, "): ", err)

View file

@ -112,12 +112,12 @@ type indexData struct {
func indexHandler(h handler) {
var data indexData
data.Tags, _ = h.db.GetTags(TAGS_DISPLAY)
data.Tags, _ = h.db.GetTags()
data.S = GetStatus(h)
data.S.Home = true
data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, 6)
data.VisitedBooks, _ = h.db.GetVisitedBooks(6)
data.DownloadedBooks, _ = h.db.GetDownloadedBooks(6)
data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, BOOKS_FRONT_PAGE)
data.VisitedBooks, _ = h.db.GetVisitedBooks()
data.DownloadedBooks, _ = h.db.GetDownloadedBooks()
data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db)
loadTemplate(h.w, "index", data)
}