func Photos(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusNotFound) } var photos []*models.Photo if err := ctx.C(P).Find(bson.M{"user": bson.ObjectIdHex(id), "active": true}).All(&photos); err != nil { return perform_status(w, req, http.StatusNotFound) } user := new(models.User) if err := ctx.C("users").FindId(bson.ObjectIdHex(id)).One(user); err != nil { return perform_status(w, req, http.StatusNotFound) } // find the index of the photo photoId := req.URL.Query().Get(":photo") ctx.Data["index"] = 0 var pIds []bson.ObjectId for i, p := range photos { if p.Id.Hex() == photoId { ctx.Data["index"] = i } pIds = append(pIds, p.Id) } return AJAX("galleria.html").Execute(w, map[string]interface{}{ "photos": photos, "user": user, "hash": models.GenUUID(), "ctx": ctx, }) }
func report(w http.ResponseWriter, req *http.Request, ctx *models.Context, repType string) error { if ctx.User == nil { return perform_status(w, req, http.StatusForbidden) } if req.URL.Query().Get(":csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } photoId := req.URL.Query().Get(":photo") if !bson.IsObjectIdHex(photoId) { return perform_status(w, req, http.StatusForbidden) } query := bson.M{"_id": bson.ObjectIdHex(photoId), "active": true, repType + "reporters": bson.M{"$ne": ctx.User.Id}} update := bson.M{ "$push": bson.M{repType + "reporters": ctx.User.Id}, "$inc": bson.M{repType + "count": 1}, } if err := ctx.C(P).Update(query, update); err != nil { // toggle report // This query succeeds when the voter has already voted on the story. //query = {_id: ObjectId("4bcc9e697e020f2d44471d27"), voters: user_id}; // Update to remove the user from the array and decrement the number of votes. //update = {'$pull': {'voters': user_id}, '$inc': {vote_count: -1}} //db.stories.update(query, update); } return nil }
func CommentForm(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { //set up the collection and query id := req.URL.Query().Get(":id") kind := req.URL.Query().Get(":kind") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } var object models.Commenter switch kind { case "p": query := ctx.C(P).FindId(bson.ObjectIdHex(id)) //execute the query photo := &models.Photo{} if err := query.One(&photo); err != nil { return perform_status(w, req, http.StatusNotFound) } object = photo case "c": query := ctx.C(C).FindId(bson.ObjectIdHex(id)) //execute the query contest := &models.Contest{} if err := query.One(&contest); err != nil { return perform_status(w, req, http.StatusNotFound) } object = contest } //execute the template return AJAX("comments.html").Execute(w, map[string]interface{}{ "object": object, "kind": kind, "ctx": ctx, }) }
func SendMessage(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } to := req.URL.Query().Get(":to") if !bson.IsObjectIdHex(to) { return perform_status(w, req, http.StatusForbidden) } if to == ctx.User.Id.Hex() { return perform_status(w, req, http.StatusForbidden) } m := models.Message{ Id: bson.NewObjectId(), From: ctx.User.Id, To: bson.ObjectIdHex(to), UserName: ctx.User.FullName(), Avatar: ctx.User.Avatar, Subject: req.FormValue("subject"), Body: req.FormValue("body"), } if err := ctx.C(M).Insert(m); err != nil { models.Log("Error sending message: ", err.Error()) } return nil }
func GetPhotoVotes(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } match := bson.M{"photo": bson.ObjectIdHex(id)} if f, ok := ctx.Session.Values["filter"]; ok { f.(*models.Filter).AddQuery(match) } var result bson.M pipe := ctx.C(V).Pipe([]bson.M{ {"$match": match}, {"$group": bson.M{ "_id": "$photo", "avg": bson.M{"$avg": "$score"}, "count": bson.M{"$sum": 1}, "user": bson.M{"$addToSet": "$photouser"}, }}, {"$unwind": "$user"}, }) pipe.One(&result) if result["user"] != nil && result["user"].(bson.ObjectId) != ctx.User.Id { return perform_status(w, req, http.StatusForbidden) } w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"avg": %.1f, "count": %d}`, result["avg"], result["count"]) return nil }
func Messages(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } var messages []*models.Message ctx.C(M).Find(bson.M{"to": ctx.User.Id}).All(&messages) return T("messages.html").Execute(w, map[string]interface{}{ "ctx": ctx, "messages": messages, }) }
func ResetPassword(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { // should not be logged in if ctx.User != nil { ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Already logged in!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil } form := models.UserForm form.Fields = form.Fields[2:3] r := (&form).Load(req) ctx.Data["result"] = r if r.Err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem reseting password:"******"csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } if len(r.Errors) != 0 { return ResetPasswordForm(w, req, ctx) } email := r.Values["email"] u := &models.User{} err := ctx.C(U).Find(bson.M{"email": email}).One(&u) if err == nil { pt := &models.PasswordToken{ Uuid: models.GenUUID(), User: u.Id, CreatedOn: time.Now(), } // set new password to database if err := ctx.C(PT).Insert(pt); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem reseting password:"******"Subject: lov3ly.me password reset\r\n\r\nChange password link: http://%s\n\nIf you have NOT requested this, please ignore. Link available for 24 hours.\n\nHave fun,\nlov3ly.me Team", req.Host+reverse("change_token", "uuid", pt.Uuid)) go func() { err := models.SendEmail([]byte(body), email) if err != nil { models.Log("Error sending mail: ", err.Error()) } }() ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Email sent succesfully!", ctx))) } else { ctx.Session.AddFlash(models.F(models.NOTICE, trans("Email not in our database:", ctx), err.Error())) } http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil }
func Admin(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil || !ctx.User.Admin { return perform_status(w, req, http.StatusForbidden) } photoCount, _ := ctx.C(P).Find(nil).Count() pp := NewPagination(photoCount, req.URL.Query()) photoSkip := pp.PerPage * (pp.Current - 1) var photos []*models.Photo if err := ctx.C(P).Find(nil).Skip(photoSkip).Limit(pp.PerPage).All(&photos); err != nil { models.Log("error getting photos: ", err.Error()) return err } userCount, _ := ctx.C(U).Find(nil).Count() up := NewPagination(userCount, req.URL.Query()) userSkip := up.PerPage * (up.Current - 1) var users []*models.User if err := ctx.C(U).Find(nil).Skip(userSkip).Limit(up.PerPage).All(&users); err != nil { models.Log("error getting users: ", err.Error()) return err } return T("admin.html").Execute(w, map[string]interface{}{ "ctx": ctx, "pp": pp, "photos": photos, "up": up, "users": users, }) }
func Delete(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } if req.URL.Query().Get(":csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } if rc, _ := ctx.C(C).Find(bson.M{"registered.photo": bson.ObjectIdHex(id)}).Count(); rc != 0 { // the photo is registered in contests // only mark as deleted if err := ctx.C(P).UpdateId(bson.ObjectIdHex(id), bson.M{"$set": bson.M{"deleted": true, "active": false}}); err != nil { return perform_status(w, req, http.StatusNotFound) } // delete non contest votes // delete related votes if _, err := ctx.C(V).RemoveAll(bson.M{"photo": bson.ObjectIdHex(id), "contest": bson.M{"$exists": false}}); err != nil { models.Log("Error deleting votes on photo delete: ", err.Error()) } } else { // the photo is not registered in any contest if err := ctx.C(P).RemoveId(bson.ObjectIdHex(id)); err != nil { return perform_status(w, req, http.StatusNotFound) } // delete from disk err := os.Remove(path.Join(models.DATA_DIR, models.UPLOADS, fmt.Sprintf("%s.jpg", id))) if err != nil { models.Log("Error deleting image:", err.Error()) } err = os.Remove(path.Join(models.DATA_DIR, models.UPLOADS, fmt.Sprintf("%s_thumb.jpg", id))) if err != nil { models.Log("Error deleting image:", err.Error()) } // delete related votes if _, err := ctx.C(V).RemoveAll(bson.M{"photo": bson.ObjectIdHex(id)}); err != nil { models.Log("Error deleting votes on photo delete: ", err.Error()) } } http.Redirect(w, req, reverse("upload", "id", ""), http.StatusSeeOther) return nil }
func SetAvatar(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { return perform_status(w, req, http.StatusForbidden) } if req.URL.Query().Get(":csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } photoId := req.URL.Query().Get(":photo") if bson.IsObjectIdHex(photoId) { newAvatar := models.ImageUrl(photoId, "thumb") ctx.User.Avatar = newAvatar ctx.C(U).UpdateId(ctx.User.Id, bson.M{"$set": bson.M{"avatar": newAvatar}}) //ctx.C(P).Update(bson.M{"comments.user": ctx.User.Id}, bson.M{"comments.$.avatar": bson.M{"$set": ctx.User.Gravatar(80)}}) } return nil }
func typeAhead(field, q string, ctx *models.Context) string { var users []map[string]string query := bson.M{field: bson.RegEx{"^" + q, "i"}} ctx.C(U).Find(query).Select(bson.M{field: 1, "_id": 0}).All(&users) distinct := make(map[string]bool) for _, u := range users { if _, ok := distinct[u[field]]; !ok { distinct[u[field]] = true } } var result string for k, _ := range distinct { result += `"` + k + `",` } result = strings.TrimRight(result, ",") return `{"options":[` + result + `]}` }
func DelMessage(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } if err := ctx.C(M).Remove(bson.M{"_id": bson.ObjectIdHex(id), "to": ctx.User.Id}); err != nil { models.Log("error removing message: ", err.Error()) return err } fmt.Fprint(w, "ok") return nil }
func ChangePassword(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } if req.FormValue("csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } old_pass := req.FormValue("password") u := models.User{} if err := ctx.C(U).Find(bson.M{"email": ctx.User.Email}).One(&u); err != nil { return perform_status(w, req, http.StatusNotFound) } if len(u.Password) > 0 { // if the account was not created with social auth err := bcrypt.CompareHashAndPassword(u.Password, []byte(old_pass)) if err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Invalid Old Password", ctx))) return ChangePasswordForm(w, req, ctx) } } new_pass := req.FormValue("password1") if len(new_pass) < 5 { ctx.Session.AddFlash(models.F(models.ERROR, trans("Passwords too short (5 chars or more)", ctx))) return ChangePasswordForm(w, req, ctx) } vfy_pass := req.FormValue("password2") if new_pass != vfy_pass { ctx.Session.AddFlash(models.F(models.ERROR, trans("Password did not match", ctx))) return ChangePasswordForm(w, req, ctx) } hpass, err := models.EncryptPassword(new_pass) if err != nil { return internal_error(w, req, err.Error()) } // set new password to database if err := ctx.C(U).UpdateId(ctx.User.Id, bson.M{"$set": bson.M{"password": hpass}}); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem changing password:"******"Password changed succesfully!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil }
func DelUser(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil || !ctx.User.Admin { return perform_status(w, req, http.StatusForbidden) } id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } if err := ctx.C(U).RemoveId(bson.ObjectIdHex(id)); err != nil { models.Log("error deleting user: "******"Problem deleting user:"******"admin"), http.StatusSeeOther) return err } ctx.Session.AddFlash(models.F(models.SUCCESS, trans("User deleted!", ctx))) http.Redirect(w, req, reverse("admin"), http.StatusSeeOther) return nil }
func Profile(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } if req.FormValue("csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } ctx.Data["title"] = "Profile" form := models.UserForm form.Fields = form.Fields[2:] // remove passwords r := (&form).Load(req) ctx.Data["result"] = r if len(r.Errors) != 0 { return ProfileForm(w, req, ctx) } u := r.Value.(map[string]interface{}) gender := u["gender"].(string) if gender != "m" && gender != "f" { r.Errors["gender"] = errors.New("Please select Male or Female") } now := time.Now() oldest := time.Date(now.Year()-120, 1, 1, 0, 0, 0, 0, time.UTC) bDate := u["birthdate"].(time.Time) if bDate.Before(oldest) || bDate.After(now) { r.Errors["birthdate"] = errors.New("Invalid birth date") } if r.Err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem editing profile:", ctx), r.Err.Error())) return ProfileForm(w, req, ctx) } if len(r.Errors) != 0 { return ProfileForm(w, req, ctx) } if err := ctx.C(U).UpdateId(ctx.User.Id, bson.M{"$set": u}); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem editing profile:", ctx), err.Error())) models.Log(err.Error()) r.Err = err } ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Profile updated succesfully!", ctx))) return ProfileForm(w, req, ctx) }
func Rankings(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { var results models.WilsonSorter pipe := ctx.C(V).Pipe([]bson.M{ {"$match": bson.M{"active": true}}, {"$group": bson.M{ "_id": "$photo", "count": bson.M{"$sum": 1}, "avg": bson.M{"$avg": "$score"}, "scores": bson.M{"$push": "$score"}, "title": bson.M{"$addToSet": "$title"}, "description": bson.M{"$addToSet": "$description"}, "user": bson.M{"$addToSet": "$photouser"}, }}, {"$unwind": "$user"}, {"$unwind": "$title"}, {"$unwind": "$description"}, }) pipe.All(&results) // calculate wilson rating http://www.goproblems.com/test/wilson/wilson-new.php vc := make([]int, 5) for _, r := range results { scores := r["scores"].([]interface{}) for _, s := range scores { index := int(s.(float64) - 1) vc[index] += 1 } sum := 0.0 for i, c := range vc { w := float64(i) / 4.0 sum += float64(c) * w } r["wilson"] = models.Wilson(len(scores), sum) vc[0], vc[1], vc[2], vc[3], vc[4] = 0, 0, 0, 0, 0 } sort.Sort(results) return AJAX("rankings.html").Execute(w, map[string]interface{}{ "results": results, "ctx": ctx, }) }
func Random(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { page := 1 page, err := strconv.Atoi(req.URL.Query().Get(":page")) if err != nil && page == 0 { page = 1 } skip := ITEMS_PER_PAGE * (page - 1) query := bson.M{"active": true} if f, ok := ctx.Session.Values["filter"]; ok { f.(*models.Filter).AddQuery(query) } //execute the query var photos []*models.Photo if err := ctx.C("photos").Find(query).Skip(skip).Limit(ITEMS_PER_PAGE).Sort("-_id").All(&photos); err != nil { return internal_error(w, req, err.Error()) } data := "" var layer bytes.Buffer for _, i := range rand.Perm(len(photos)) { p := photos[i] err := layerTemplate.Execute(&layer, map[string]interface{}{"p": p, "ctx": ctx}) if err != nil { models.Log("layer template: ", err.Error()) } data += fmt.Sprintf(`{"image":"%s","thumb":"%s","title":"%s","description":"%s","layer":"%s"},`, models.ImageUrl(p.Id.Hex(), ""), models.ImageUrl(p.Id.Hex(), "thumb"), p.Title, p.Description, strings.Replace(layer.String(), "\n", "", -1), ) layer.Reset() } data = strings.TrimRight(data, ",") w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, "["+data+"]") return nil }
func Search(w http.ResponseWriter, req *http.Request, ctx *models.Context) (err error) { var users []*models.User q := req.FormValue("q") query := bson.M{"$or": []bson.M{ {"firstname": bson.RegEx{q, "i"}}, {"lastname": bson.RegEx{q, "i"}}, }, } if err := ctx.C(U).Find(query).Select(bson.M{"password": 0, "birthdate": 0}).Limit(10).All(&users); err != nil { return err } response := "" var text bytes.Buffer for _, u := range users { responseTemplate.Execute(&text, u) response += fmt.Sprintf(`{"id":"%s","text":"%s", "name":"%s"},`, u.Id.Hex(), text.String(), u.FullName()) text.Reset() } response = strings.TrimRight(response, ",") w.Header().Set("Content-Type", "application/json") fmt.Fprint(w, "["+response+"]") return nil }
func Comment(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } if req.FormValue("csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } form := models.CommentForm r := form.Load(req) ctx.Data["result"] = r if len(r.Errors) != 0 { return CommentForm(w, req, ctx) } id := req.URL.Query().Get(":id") if !bson.IsObjectIdHex(id) { return perform_status(w, req, http.StatusForbidden) } c := &models.Comment{ Id: bson.NewObjectId(), User: ctx.User.Id, UserName: ctx.User.FullName(), Avatar: ctx.User.Avatar, Body: r.Values["body"], } col := P if req.URL.Query().Get(":kind") == "c" { col = C } if err := ctx.C(col).UpdateId(bson.ObjectIdHex(id), bson.M{"$push": bson.M{"comments": c}}); err != nil { r.Errors["body"] = err return CommentForm(w, req, ctx) } return CommentForm(w, req, ctx) }
func GetVote(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { return perform_status(w, req, http.StatusForbidden) } photoId := req.URL.Query().Get(":photo") if !bson.IsObjectIdHex(photoId) { return perform_status(w, req, http.StatusForbidden) } contestId := req.URL.Query().Get(":contest") if contestId != "" && !bson.IsObjectIdHex(contestId) { return perform_status(w, req, http.StatusForbidden) } query := bson.M{"photo": bson.ObjectIdHex(photoId), "user": ctx.User.Id} if contestId != "" { query["contest"] = bson.ObjectIdHex(contestId) } vote := &models.Vote{} ctx.C(V).Find(query).One(vote) // on error we still want the stars hearts := "" for i := 0; i < 5; i++ { if float64(i) < vote.Score { hearts += `<s class="voted">` } else { hearts += "<s>" } } return AJAX("vote.html").Execute(w, map[string]interface{}{ "v": vote, "photoId": photoId, "contestId": contestId, "hearts": SafeHtml(hearts), "ctx": ctx, }) }
func ChangePasswordToken(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { go models.RemoveOldPasswordTokens() // should not be logged in if ctx.User != nil { ctx.Session.AddFlash(models.F(models.SUCCESS, trans("You can change password normally!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil } uuid := req.URL.Query().Get(":uuid") if uuid == "" { return perform_status(w, req, http.StatusForbidden) } pt := &models.PasswordToken{} if err := ctx.C(PT).FindId(uuid).One(&pt); err != nil { ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Password token expired!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil } if req.FormValue("csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } new_pass := req.FormValue("password1") if len(new_pass) < 5 { ctx.Session.AddFlash(models.F(models.ERROR, trans("Passwords too short (5 chars or more)", ctx))) return ChangePasswordForm(w, req, ctx) } vfy_pass := req.FormValue("password2") if new_pass != vfy_pass { ctx.Session.AddFlash(models.F(models.ERROR, trans("Password did not match", ctx))) return ChangePasswordForm(w, req, ctx) } hpass, err := models.EncryptPassword(new_pass) if err != nil { return internal_error(w, req, err.Error()) } // set new password to database if err := ctx.C(U).UpdateId(pt.User, bson.M{"$set": bson.M{"password": hpass}}); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem changing password:"******"user"] = pt.User // delete password token if err := ctx.C(PT).RemoveId(pt.Uuid); err != nil { models.Log("error deleting password token: ", err.Error()) } ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Password changed succesfully!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil }
func Vote(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { return perform_status(w, req, http.StatusForbidden) } if req.URL.Query().Get(":csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } photoId := req.URL.Query().Get(":photo") if !bson.IsObjectIdHex(photoId) { return perform_status(w, req, http.StatusForbidden) } photo := models.Photo{} if err := ctx.C(P).FindId(bson.ObjectIdHex(photoId)).One(&photo); err != nil { return perform_status(w, req, http.StatusNotFound) } // check photo is own photo and return forbidden if c, _ := ctx.C(P).Find(bson.M{"_id": bson.ObjectIdHex(photoId), "user": ctx.User.Id}).Limit(1).Count(); c != 0 { return perform_status(w, req, http.StatusForbidden) } contestId := req.URL.Query().Get(":contest") var contest bson.ObjectId if contestId != "" && bson.IsObjectIdHex(contestId) { contest = bson.ObjectIdHex(contestId) // check contest is in voting period now := time.Now() query := ctx.C(C).Find(bson.M{ "_id": contest, "admissiondeadline": bson.M{"$lt": now}, "votingdeadline": bson.M{"$gt": now}, }).Limit(1) if count, err := query.Count(); count != 1 || err != nil { return perform_status(w, req, http.StatusForbidden) } } hearts, err := strconv.ParseFloat(req.FormValue("v"), 64) if err != nil || hearts < 1 || hearts > 5 { return perform_status(w, req, http.StatusForbidden) } v := &models.Vote{ Photo: photo.Id, PhotoUser: photo.User, Title: photo.Title, Description: photo.Description, Country: photo.Country, Location: photo.Location, Age: photo.Age, Gender: photo.Gender, Active: photo.Active, Contest: contest, Score: hearts, UpdatedOn: time.Now(), User: ctx.User.Id, } query := bson.M{"photo": v.Photo, "user": v.User} if contestId != "" { query["contest"] = contest } else { query["contest"] = bson.M{"$exists": false} } if _, err := ctx.C(V).Upsert(query, v); err != nil { models.Log("vote err: ", err.Error()) } return nil }
func Register(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User != nil { http.Redirect(w, req, reverse("logout"), http.StatusSeeOther) return nil } if req.FormValue("csrf_token") != ctx.Session.Values["csrf_token"] { return perform_status(w, req, http.StatusForbidden) } ctx.Data["title"] = "Register" r := (&models.UserForm).Load(req) ctx.Data["result"] = r if len(r.Errors) != 0 { return RegisterForm(w, req, ctx) } u := r.Value.(map[string]interface{}) password1 := u["password1"].(string) if len(password1) < 5 { r.Errors["password1"] = errors.New("Passwords too short (5 chars or more)") } password2 := u["password2"].(string) if password2 != password1 { r.Errors["password2"] = errors.New("Passwords do not match") } gender := u["gender"].(string) if gender != "m" && gender != "f" { r.Errors["gender"] = errors.New("Please select Male or Female") } now := time.Now() oldest := time.Date(now.Year()-120, 1, 1, 0, 0, 0, 0, time.UTC) bDate := u["birthdate"].(time.Time) if bDate.Before(oldest) || bDate.After(now) { r.Errors["birthdate"] = errors.New("Invalid birth date") } if len(r.Errors) != 0 { return RegisterForm(w, req, ctx) } if r.Err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem registering user:"******"captchaId"), req.FormValue("captchaSolution")) { ctx.Session.AddFlash(models.F(models.ERROR, trans("The control numbers do not match!", ctx))) return RegisterForm(w, req, ctx) } pass, err := models.EncryptPassword(u["password1"].(string)) if err != nil { return internal_error(w, req, err.Error()) // bcrypt errors on invalid costs } u["password"] = pass delete(u, "password1") delete(u, "password2") u["_id"] = bson.NewObjectId() u["avatar"] = gravatar.UrlSize(u["email"].(string), 80) if err := ctx.C("users").Insert(u); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem registering user:"******"user"] = u["_id"] ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Welcome to lov3ly.me!", ctx))) http.Redirect(w, req, reverse("index"), http.StatusSeeOther) return nil }
func Upload(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } form := models.UploadForm r := (&form).Load(req) ctx.Data["result"] = r if len(r.Errors) != 0 { return UploadForm(w, req, ctx) } p := r.Value.(map[string]interface{}) rand, err := crand.Int(crand.Reader, big.NewInt(1000000)) if err != nil { models.Log("error generating random number:", err.Error()) } photo := &models.Photo{ Title: p["title"].(string), Description: p["description"].(string), Country: p["country"].(string), Location: p["location"].(string), Age: p["age"].(int), Gender: p["gender"].(string), Active: p["active"].(bool), Deleted: false, User: ctx.User.Id, UpdatedOn: time.Now(), Rand: rand.Int64(), } var objectToBeUpdated interface{} var nid bson.ObjectId id := "" if id = req.URL.Query().Get(":id"); bson.IsObjectIdHex(id) { //edit mode nid = bson.ObjectIdHex(id) if nid != ctx.User.Id { // doesn't belong to the registered user return perform_status(w, req, http.StatusForbidden) } objectToBeUpdated = p // update previous votes if _, err := ctx.C(V).UpdateAll(bson.M{"photo": nid}, bson.M{"$set": bson.M{ "title": photo.Title, "description": photo.Description, "country": photo.Country, "location": photo.Location, "age": photo.Age, "gender": photo.Gender, "active": photo.Active, }}); err != nil { models.Log("Error updating votes on photo edit: ", err.Error()) } } else { // upload mode objectToBeUpdated = photo x1, _ := strconv.Atoi(req.FormValue("x1")) y1, _ := strconv.Atoi(req.FormValue("y1")) x2, _ := strconv.Atoi(req.FormValue("x2")) y2, _ := strconv.Atoi(req.FormValue("y2")) ff, _, err := req.FormFile("photo") if err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem uploading photo:", ctx), err.Error())) models.Log(err.Error()) return UploadForm(w, req, ctx) } defer ff.Close() // decode jpeg into image.Image img, err := jpeg.Decode(ff) if err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem uploading photo:", ctx), err.Error())) models.Log(err.Error()) r.Err = err return UploadForm(w, req, ctx) } photo.Id = bson.NewObjectId() nid = photo.Id if err := photo.SaveImage(img, x1, y1, x2, y2); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem uploading photo:", ctx), err.Error())) models.Log(err.Error()) r.Err = err return UploadForm(w, req, ctx) } } photo.Id = "" if _, err := ctx.C(P).UpsertId(nid, bson.M{"$set": objectToBeUpdated}); err != nil { ctx.Session.AddFlash(models.F(models.ERROR, trans("Problem editing photo:", ctx), err.Error())) models.Log(err.Error()) r.Err = err return UploadForm(w, req, ctx) } ctx.Session.AddFlash(models.F(models.SUCCESS, trans("Photo updated succesfully!", ctx))) http.Redirect(w, req, reverse("upload", "id", id), http.StatusSeeOther) return nil }
func TopVoted(w http.ResponseWriter, req *http.Request, ctx *models.Context) error { page := 1 page, err := strconv.Atoi(req.URL.Query().Get(":page")) if err != nil && page == 0 { page = 1 } skip := ITEMS_PER_PAGE * (page - 1) match := bson.M{"active": true} if f, ok := ctx.Session.Values["filter"]; ok { f.(*models.Filter).AddQuery(match) } var results models.WilsonSorter pipe := ctx.C(V).Pipe([]bson.M{ {"$match": match}, {"$group": bson.M{ "_id": "$photo", "scores": bson.M{"$push": "$score"}, "title": bson.M{"$addToSet": "$title"}, "description": bson.M{"$addToSet": "$description"}, "user": bson.M{"$addToSet": "$photouser"}, }}, {"$skip": skip}, {"$limit": ITEMS_PER_PAGE}, {"$unwind": "$user"}, {"$unwind": "$title"}, {"$unwind": "$description"}, }) pipe.All(&results) // calculate wilson rating http://www.goproblems.com/test/wilson/wilson-new.php vc := make([]int, 5) for _, r := range results { scores := r["scores"].([]interface{}) for _, s := range scores { index := int(s.(float64) - 1) vc[index] += 1 } sum := 0.0 for i, c := range vc { w := float64(i) / 4.0 sum += float64(c) * w } r["wilson"] = models.Wilson(len(scores), sum) vc[0], vc[1], vc[2], vc[3], vc[4] = 0, 0, 0, 0, 0 } sort.Sort(results) data := "" var layer bytes.Buffer for _, r := range results { p := &models.Photo{ Id: r["_id"].(bson.ObjectId), User: r["user"].(bson.ObjectId), Title: r["title"].(string), Description: r["description"].(string), } err := layerTemplate.Execute(&layer, map[string]interface{}{"p": p, "ctx": ctx}) if err != nil { models.Log("layer template: ", err.Error()) } data += fmt.Sprintf(`{"image":"%s","thumb":"%s","title":"%s","description":"%s", "layer":"%s"},`, models.ImageUrl(p.Id.Hex(), ""), models.ImageUrl(p.Id.Hex(), "thumb"), p.Title, p.Description, strings.Replace(layer.String(), "\n", "", -1), ) layer.Reset() } data = strings.TrimRight(data, ",") w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, "["+data+"]") return nil }
func UploadForm(w http.ResponseWriter, req *http.Request, ctx *models.Context) (err error) { if ctx.User == nil { http.Redirect(w, req, reverse("login"), http.StatusSeeOther) return nil } //set up the collection and query query := ctx.C(P).Find(bson.M{"user": ctx.User.Id, "deleted": false}).Sort("-_id") var photos []*models.Photo if err = query.All(&photos); err != nil { return perform_status(w, req, http.StatusNotFound) } // get id for edit mode id := req.URL.Query().Get(":id") if bson.IsObjectIdHex(id) { p := &models.Photo{} if err := ctx.C(P).Find(bson.M{"_id": bson.ObjectIdHex(id), "user": ctx.User.Id, "deleted": false}).One(p); err != nil { return perform_status(w, req, http.StatusNotFound) } if p == nil { return perform_status(w, req, http.StatusNotFound) } r, ok := ctx.Data["result"] a := "" if p.Active { a = "yes" } if !ok { r = forms.Result{ Values: map[string]string{ "title": p.Title, "description": p.Description, "country": p.Country, "location": p.Location, "age": strconv.Itoa(p.Age), "gender": p.Gender, "active": a, }, } ctx.Data["result"] = r } } // default values r, ok := ctx.Data["result"] if !ok { r = forms.Result{Values: map[string]string{"active": "yes"}} ctx.Data["result"] = r r.(forms.Result).Values["country"] = ctx.User.Country r.(forms.Result).Values["location"] = ctx.User.Location r.(forms.Result).Values["gender"] = ctx.User.Gender r.(forms.Result).Values["age"] = strconv.Itoa(ctx.User.Age()) } // find the index of the photo ctx.Data["index"] = 0 for i, p := range photos { if p.Id.Hex() == id { ctx.Data["index"] = i break } } return T("upload.html").Execute(w, map[string]interface{}{ "photos": photos, "id": id, "ctx": ctx, }) }