func ProcessIndexHandler(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, _ := session.Values["user"] rows := model.GetAllUserQueues() defer rows.Close() var list []userQueue for rows.Next() { var entry userQueue rows.Scan(&entry.Id, &entry.Latest, &entry.Count) list = append(list, entry) } templates := loadTemplates( "header.html", "footer.html", "nav.html", "admin/processIndex.html", ) templates.ExecuteTemplate(w, "processIndex", struct { User int List []userQueue }{ User: userid.(int), List: list, }) }
func requireAdmin(fn func(http.ResponseWriter, *http.Request)) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] if !ok || userid.(int) != 1 { http.Error(w, "Not found", http.StatusNotFound) return } fn(w, r) } }
func ProcessQueueHandler(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, _ := session.Values["user"] owner := mux.Vars(r)["owner"] ownerInt, _ := strconv.Atoi(owner) faulty := mux.Vars(r)["faulty"] faultyInt, _ := strconv.Atoi(faulty) row := model.GetQueueWithProfileById(faultyInt) defer row.Close() row.Next() faultyProfile := rowToQueueProfile(row) previous := mux.Vars(r)["previous"] previousInt, _ := strconv.Atoi(previous) row = model.GetQueueWithProfileById(previousInt) defer row.Close() row.Next() previousProfile := rowToQueueProfile(row) o := ocr.New(faultyProfile.File, 0) o.Split() o.Process() o.CleanUp() templates := loadTemplates( "header.html", "footer.html", "nav.html", "admin/processQueue.html", ) templates.ExecuteTemplate(w, "processQueue", struct { User int Owner int File string Faulty userQueueEntry Previous userQueueEntry Dry profile.Profile }{ User: userid.(int), Owner: ownerInt, Faulty: faultyProfile, Previous: previousProfile, Dry: o.Profile, }) }
func UploadViewHandler(w http.ResponseWriter, r *http.Request) { templates := loadTemplates( "header.html", "footer.html", "nav.html", "upload.html", ) session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] if !ok { http.Redirect(w, r, "/", 302) return } templates.ExecuteTemplate(w, "upload", UploadPage{ User: userid.(int), }) }
func ProcessListHandler(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, _ := session.Values["user"] owner := mux.Vars(r)["owner"] ownerInt, _ := strconv.Atoi(owner) rows := model.GetAllQueuesWithProfileByUser(ownerInt) defer rows.Close() var list []userQueueEntry for rows.Next() { e := rowToQueueProfile(rows) list = append(list, e) } // First entry is always seen as good. list[0].HasProblem = false for i := 1; i < len(list)-1; i++ { list[i].Previous = list[i-1].Id list[i].HasProblem = comparePrevious(list[i-1].Profile, list[i].Profile) } templates := loadTemplates( "header.html", "footer.html", "nav.html", "admin/processList.html", ) templates.ExecuteTemplate(w, "processList", struct { User int Owner int List []userQueueEntry }{ User: userid.(int), Owner: ownerInt, List: list, }) }
func LogoutHandle(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] if !ok { http.Redirect(w, r, "/", 302) return } u, _ := model.GetUserById(userid.(int)) if u.GPlusId != "" { // Execute HTTP GET request to revoke current token url := "https://accounts.google.com/o/oauth2/revoke?token=" + u.AccessToken resp, _ := http.Get(url) defer resp.Body.Close() } delete(session.Values, "user") session.Save(r, w) http.Redirect(w, r, "/", 302) }
func ProfileHandler(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] templates := loadTemplates( "header.html", "footer.html", "nav.html", "index-unauthed.html", "profile.html", ) if ok { var profiles []profile.Profile period := mux.Vars(r)["period"] var p profile.Profile var diff profile.Profile queue := model.GetNumQueuedProfiles(userid.(int)) switch period { case "daily": period = "Daily" p1 := model.GetNewestProfile(userid.(int)) p2 := model.GetProfileByTimestamp(userid.(int), time.Now().AddDate(0, 0, -1).Unix()) profiles = append(profiles, p1, p2) case "weekly": period = "Weekly" p1 := model.GetNewestProfile(userid.(int)) p2 := model.GetProfileByTimestamp(userid.(int), time.Now().AddDate(0, 0, -7).Unix()) profiles = append(profiles, p1, p2) case "monthly": period = "Monthly" p1 := model.GetNewestProfile(userid.(int)) p2 := model.GetProfileByTimestamp(userid.(int), time.Now().AddDate(0, -1, 0).Unix()) profiles = append(profiles, p1, p2) default: period = "Previous" profiles = model.GetNewestProfiles(userid.(int), 2) } switch len(profiles) { case 1: p = profiles[0] case 2: diff = profile.Diff(profiles[1], profiles[0]) p = profiles[0] } templates.ExecuteTemplate(w, "profile", ProfilePage{ User: userid.(int), Data: ProfilePageData{ Period: period, Profile: p, Diff: diff, Queue: queue, }, }) } else { templates.ExecuteTemplate(w, "index-unauthed", nil) } }
func ProgressHandler(w http.ResponseWriter, r *http.Request) { templates := loadTemplates( "header.html", "footer.html", "nav.html", "progress.html", ) session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] if !ok { http.Redirect(w, r, "/", 302) return } var view view view.User = userid.(int) limit := time.Now().Unix() - int64((time.Hour * 24 * 30).Seconds()) profiles := model.GetAllProfiles(view.User, limit) if len(profiles) == 0 { view.Warning = "Not enough data to generate page. :(" templates.ExecuteTemplate(w, "progress", &view) return } view.Queue = model.GetNumQueuedProfiles(userid.(int)) var x = map[string][]int64{} var y = map[string][]int64{} for k := range profiles { p := &profiles[k] profile.HandleProfile(p) x["AP"] = append(x["AP"], p.Timestamp) y["AP"] = append(y["AP"], p.AP) } newestProfile := profiles[len(profiles)-1] if newestProfile.AP < newestProfile.NextLevel.AP { var ts int64 if y["AP"][0] == y["AP"][len(y["AP"])-1] { ts = -1 } else { slope, intercept, _ := lineaRegression(x["AP"], y["AP"]) ts = int64(((float64(newestProfile.NextLevel.AP) - intercept) / slope)) + 1262304000 } perc := (float64(int(float64(newestProfile.AP)/float64(newestProfile.NextLevel.AP)*1000)) / 10) view.AP = progress{ Name: "AP", Tiers: []tier{ { Name: "info", Percentage: perc, }, }, Current: newestProfile.AP, Required: newestProfile.NextLevel.AP, Expected: ts, } } else { view.AP = progress{ Name: "AP", Tiers: []tier{ { Name: "info", Percentage: 100, }, }, Current: newestProfile.AP, Required: newestProfile.NextLevel.AP, Expected: -2, } } var badges []progress for badgeName := range profile.BadgeRanks { if badgeName == "Innovator" { continue } badges = append(badges, progress{ Name: badgeName, }) } for _, badge := range badges { for _, p := range profiles { s := reflect.ValueOf(&p.Badges).Elem() typeOf := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) name := typeOf.Field(i).Name current := f.FieldByName("Current").Int() if badge.Name == name && shouldIncludeBadge(badge.Name, p.Timestamp, current) { x[name] = append(x[name], p.Timestamp) y[name] = append(y[name], current) } } } if badge.Name == "Guardian" && len(x["Guardian"]) > 1 { var i int var n = len(x["Guardian"]) - 1 xValue := x["Guardian"][n] yValue := y["Guardian"][n] for i = n - 1; i > 0; i-- { var curX = x["Guardian"][i] var curY = y["Guardian"][i] diff := xValue - curX if curY != yValue { if diff <= 86400 { xValue = curX yValue = curY } } else if diff > 86400 { i++ break } } x["Guardian"] = x["Guardian"][i : n+1] y["Guardian"] = y["Guardian"][i : n+1] } s := reflect.ValueOf(&newestProfile.Badges).Elem() typeOf := s.Type() for i := 0; i < s.NumField(); i++ { f := s.Field(i) name := typeOf.Field(i).Name if badge.Name == name { badge.Rank = int(f.FieldByName("Rank").Int()) badge.Current = f.FieldByName("Current").Int() badge.Required = f.FieldByName("Next").Int() if len(y[name]) > 0 && y[name][0] == y[name][len(y[name])-1] { badge.Expected = -2 } else if badge.Current < badge.Required { slope, intercept, _ := lineaRegression(x[badge.Name], y[badge.Name]) ts := int64(((float64(badge.Required) - intercept) / slope)) + 1262304000 badge.Expected = ts } else { badge.Expected = -1 } var total float64 max := float64(badge.Required) for rank, value := range profile.BadgeRanks[name] { if rank <= badge.Rank { perc := (float64(int(float64(value)/max*1000)) / 10) - total badge.Tiers = append(badge.Tiers, tier{ Name: rankNames[rank], Percentage: perc, }) total += perc } } if badge.Rank != 4 { badge.Tiers = append(badge.Tiers, tier{ Name: rankNames[badge.Rank+1], Percentage: (float64(int(float64(badge.Current)/max*1000)) / 10) - total, }) } badge.Icon = fmt.Sprintf("images/badges/%s/%d.png", strings.ToLower(badge.Name), badge.Rank+1) } } view.NextLevel = newestProfile.NextLevel.Level view.Progress = append(view.Progress, badge) } var inprogress []progress var completed []progress for _, v := range view.Progress { switch v.Expected { case -1: completed = append(completed, v) default: inprogress = append(inprogress, v) } } sort.Sort(progressByExpected{inprogress}) sort.Sort(progressByName{completed}) view.Progress = inprogress view.Completed = completed templates.ExecuteTemplate(w, "progress", &view) }
func UploadHandler(w http.ResponseWriter, r *http.Request) { session, _ := session.Get(r, "tiers") userid, ok := session.Values["user"] if !ok { return } reader, err := r.MultipartReader() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // XXX: Handle errors. var db, _ = sql.Open("mysql", conf.Config.Database) defer db.Close() for { part, err := reader.NextPart() if err != nil { break } // if part.FileName() is empty, skip this iteration. if part.FileName() == "" { continue } var fileName string var t time.Time // profile_20140815_135412_0.png r := regexp.MustCompile("^(ingress|profile)_(\\d+)_(\\d+)_\\d+\\.png$") if r.MatchString(part.FileName()) { m := r.FindStringSubmatch(part.FileName()) t, _ = time.ParseInLocation("20060102150405", m[2]+m[3], time.Local) fileName = fmt.Sprintf("%d_%s", userid, part.FileName()) } else { t = time.Now() fileName = fmt.Sprintf("%d_%s.png", userid, t.Format("20060102_150405")) } dst, err := os.Create(conf.Config.Cache + fileName) defer dst.Close() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if _, err := io.Copy(dst, part); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } reader, err := os.Open(conf.Config.Cache + fileName) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer reader.Close() m, _, err := image.Decode(reader) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } width := m.Bounds().Dx() // XXX: Handle errors... db.Exec(` INSERT INTO tiers_queues(user_id, timestamp, file, ocr_profile) VALUES(?, ?, ?, ?) `, userid, t.Unix(), fileName, width) } var numQueue float32 db.QueryRow(`SELECT count(id) FROM tiers_queues WHERE processed = 0`).Scan(&numQueue) var processTime float32 db.QueryRow(` SELECT avg(processtime) AS processtime FROM ( SELECT processtime FROM tiers_queues WHERE processed = 1 ORDER BY id DESC LIMIT 10 ) T `).Scan(&processTime) queueText := fmt.Sprintf( "Your file has been added to the queue and should be processed within %.1f seconds.", numQueue*processTime/1000, ) if r.Header.Get("X-Requested-With") == "XMLHttpRequest" { data, _ := json.Marshal(map[string]interface{}{ "success": true, "message": queueText, }) fmt.Fprintf(w, "%s", data) } else { http.Redirect(w, r, "/", 302) } queue.Queue <- true }