website/pkg/controller/account/search.go
2024-06-19 14:12:25 -07:00

164 lines
4.3 KiB
Go

package account
import (
"net/http"
"strconv"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/geoip"
"code.nonshy.com/nonshy/website/pkg/log"
"code.nonshy.com/nonshy/website/pkg/models"
"code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/templates"
"code.nonshy.com/nonshy/website/pkg/worker"
)
// Search controller.
func Search() http.HandlerFunc {
tmpl := templates.Must("account/search.html")
// Whitelist for ordering options.
var sortWhitelist = []string{
"last_login_at desc",
"created_at desc",
"username",
"username desc",
"lower(name)",
"lower(name) desc",
"distance",
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Search filters.
var (
isCertified = r.FormValue("certified")
username = r.FormValue("name") // username search
searchTerm = r.FormValue("search") // profile text search
gender = r.FormValue("gender")
orientation = r.FormValue("orientation")
maritalStatus = r.FormValue("marital_status")
hereFor = r.FormValue("here_for")
friendSearch = r.FormValue("friends") == "true"
sort = r.FormValue("sort")
sortOK bool
)
ageMin, err1 := strconv.Atoi(r.FormValue("age_min"))
ageMax, err2 := strconv.Atoi(r.FormValue("age_max"))
if ageMin > ageMax && err1 == nil && err2 == nil {
ageMin, ageMax = ageMax, ageMin
}
search := models.ParseSearchString(searchTerm)
// Get current user.
currentUser, err := session.CurrentUser(r)
if err != nil {
session.FlashError(w, r, "Couldn't get current user!")
templates.Redirect(w, "/")
return
}
// Geolocation/Who's Nearby: if the current user uses GeoIP, update
// their coordinates now.
myLocation, err := models.RefreshGeoIP(currentUser.ID, r)
if err != nil {
log.Error("RefreshGeoIP: %s", err)
}
// Sort options.
for _, v := range sortWhitelist {
if sort == v {
sortOK = true
break
}
}
if !sortOK {
sort = "last_login_at desc"
}
// Default
if isCertified == "" {
isCertified = "true"
}
pager := &models.Pagination{
PerPage: config.PageSizeMemberSearch,
Sort: sort,
}
pager.ParsePage(r)
users, err := models.SearchUsers(currentUser, &models.UserSearch{
Username: username,
Gender: gender,
Orientation: orientation,
MaritalStatus: maritalStatus,
HereFor: hereFor,
ProfileText: search,
Certified: isCertified == "true",
NotCertified: isCertified == "false",
InnerCircle: isCertified == "circle",
ShyAccounts: isCertified == "shy",
IsBanned: isCertified == "banned",
IsDisabled: isCertified == "disabled",
IsAdmin: isCertified == "admin",
Friends: friendSearch,
AgeMin: ageMin,
AgeMax: ageMax,
}, pager)
if err != nil {
session.FlashError(w, r, "An error has occurred: %s.", err)
}
// Who's Nearby feature, get some data.
insights, _ := geoip.GetRequestInsights(r)
// Collect usernames to map to chat online status.
var usernames = []string{}
for _, user := range users {
usernames = append(usernames, user.Username)
}
var vars = map[string]interface{}{
"Users": users,
"Pager": pager,
"Enum": config.ProfileEnums,
// Search filter values.
"Certified": isCertified,
"Gender": gender,
"Orientation": orientation,
"MaritalStatus": maritalStatus,
"HereFor": hereFor,
"EmailOrUsername": username,
"Search": searchTerm,
"AgeMin": ageMin,
"AgeMax": ageMax,
"FriendSearch": friendSearch,
"Sort": sort,
// Photo counts mapped to users
"PhotoCountMap": models.MapPhotoCounts(users),
// Map Shy Account badges for these results
"ShyMap": models.MapShyAccounts(users),
// Map friendships to these users.
"FriendMap": models.MapFriends(currentUser, users),
// Users on the chat room map.
"UserOnChatMap": worker.GetChatStatistics().MapUsersOnline(usernames),
// Current user's location setting.
"MyLocation": myLocation,
"GeoIPInsights": insights,
"DistanceMap": models.MapDistances(currentUser, users),
}
if err := tmpl.Execute(w, r, vars); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
})
}