2018-02-26 09:07:00 +00:00
|
|
|
package routes
|
|
|
|
|
|
|
|
import (
|
|
|
|
"database/sql"
|
2021-07-28 07:43:38 +00:00
|
|
|
"math"
|
2018-02-26 09:07:00 +00:00
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
2019-04-19 06:36:26 +00:00
|
|
|
c "github.com/Azareal/Gosora/common"
|
2018-11-01 06:43:56 +00:00
|
|
|
"github.com/Azareal/Gosora/common/phrases"
|
2019-10-18 00:35:13 +00:00
|
|
|
qgen "github.com/Azareal/Gosora/query_gen"
|
2018-02-26 09:07:00 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type ProfileStmts struct {
|
|
|
|
getReplies *sql.Stmt
|
|
|
|
}
|
|
|
|
|
|
|
|
var profileStmts ProfileStmts
|
|
|
|
|
|
|
|
// TODO: Move these DbInits into some sort of abstraction
|
|
|
|
func init() {
|
2019-04-19 06:36:26 +00:00
|
|
|
c.DbInits.Add(func(acc *qgen.Accumulator) error {
|
2018-02-26 09:07:00 +00:00
|
|
|
profileStmts = ProfileStmts{
|
2020-02-04 11:47:03 +00:00
|
|
|
getReplies: acc.SimpleLeftJoin("users_replies", "users", "users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group", "users_replies.createdBy=users.uid", "users_replies.uid=?", "", ""),
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
return acc.FirstError()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2018-10-14 05:08:44 +00:00
|
|
|
// TODO: Remove the View part of the name?
|
2020-04-27 12:41:55 +00:00
|
|
|
func ViewProfile(w http.ResponseWriter, r *http.Request, user *c.User, h *c.Header) c.RouteError {
|
2020-02-04 11:47:03 +00:00
|
|
|
var reCreatedAt time.Time
|
|
|
|
var reContent, reCreatedByName, reAvatar string
|
|
|
|
var rid, reCreatedBy, reLastEdit, reLastEditBy, reGroup int
|
|
|
|
var reList []*c.ReplyUser
|
2018-02-26 09:07:00 +00:00
|
|
|
|
|
|
|
// TODO: Do a 301 if it's the wrong username? Do a canonical too?
|
2018-11-12 09:23:36 +00:00
|
|
|
_, pid, err := ParseSEOURL(r.URL.Path[len("/user/"):])
|
2018-02-26 09:07:00 +00:00
|
|
|
if err != nil {
|
2020-04-27 12:41:55 +00:00
|
|
|
return c.SimpleError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, h)
|
2019-07-28 04:58:01 +00:00
|
|
|
}
|
2020-06-30 02:27:04 +00:00
|
|
|
if pid == 0 {
|
|
|
|
return c.NotFound(w, r, h)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
|
2019-04-19 06:36:26 +00:00
|
|
|
var puser *c.User
|
2018-02-26 09:07:00 +00:00
|
|
|
if pid == user.ID {
|
|
|
|
user.IsMod = true
|
2020-03-18 09:21:34 +00:00
|
|
|
puser = user
|
2018-02-26 09:07:00 +00:00
|
|
|
} else {
|
|
|
|
// Fetch the user data
|
|
|
|
// TODO: Add a shared function for checking for ErrNoRows and internal erroring if it's not that case?
|
2019-04-19 06:36:26 +00:00
|
|
|
puser, err = c.Users.Get(pid)
|
2018-02-26 09:07:00 +00:00
|
|
|
if err == sql.ErrNoRows {
|
2020-04-27 12:41:55 +00:00
|
|
|
return c.NotFound(w, r, h)
|
2018-02-26 09:07:00 +00:00
|
|
|
} else if err != nil {
|
2019-04-19 06:36:26 +00:00
|
|
|
return c.InternalError(err, w, r)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-27 12:41:55 +00:00
|
|
|
h.Title = phrases.GetTitlePhrasef("profile", puser.Name)
|
|
|
|
h.Path = c.BuildProfileURL(c.NameToSlug(puser.Name), puser.ID)
|
2020-06-30 02:27:04 +00:00
|
|
|
// TODO: Preload this?
|
|
|
|
h.AddSheet(h.Theme.Name + "/profile.css")
|
|
|
|
if user.Loggedin {
|
|
|
|
h.AddScriptAsync("profile_member.js")
|
|
|
|
}
|
2018-02-26 09:07:00 +00:00
|
|
|
|
|
|
|
// Get the replies..
|
|
|
|
rows, err := profileStmts.getReplies.Query(puser.ID)
|
|
|
|
if err != nil {
|
2019-04-19 06:36:26 +00:00
|
|
|
return c.InternalError(err, w, r)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
defer rows.Close()
|
|
|
|
|
|
|
|
for rows.Next() {
|
2020-02-04 11:47:03 +00:00
|
|
|
err := rows.Scan(&rid, &reContent, &reCreatedBy, &reCreatedAt, &reLastEdit, &reLastEditBy, &reAvatar, &reCreatedByName, &reGroup)
|
2018-02-26 09:07:00 +00:00
|
|
|
if err != nil {
|
2019-04-19 06:36:26 +00:00
|
|
|
return c.InternalError(err, w, r)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
|
2020-02-04 11:47:03 +00:00
|
|
|
reLiked := false
|
|
|
|
reLikeCount := 0
|
2020-04-27 12:41:55 +00:00
|
|
|
ru := &c.ReplyUser{Reply: c.Reply{rid, puser.ID, reContent, reCreatedBy /*, reGroup*/, reCreatedAt, reLastEdit, reLastEditBy, 0, "", reLiked, reLikeCount, 0, ""}, ContentHtml: c.ParseMessage(reContent, 0, "", user.ParseSettings, user), CreatedByName: reCreatedByName, Avatar: reAvatar, Group: reGroup, Level: 0}
|
|
|
|
_, err = ru.Init(user)
|
2018-02-26 09:07:00 +00:00
|
|
|
if err != nil {
|
2019-04-19 06:36:26 +00:00
|
|
|
return c.InternalError(err, w, r)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
2020-02-04 11:47:03 +00:00
|
|
|
if puser.ID == ru.CreatedBy {
|
2020-01-14 05:07:00 +00:00
|
|
|
ru.Tag = phrases.GetTmplPhrase("profile.owner_tag")
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Add a hook here
|
2020-02-04 11:47:03 +00:00
|
|
|
reList = append(reList, ru)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
2019-10-18 00:35:13 +00:00
|
|
|
if err := rows.Err(); err != nil {
|
2019-04-19 06:36:26 +00:00
|
|
|
return c.InternalError(err, w, r)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|
|
|
|
|
2018-10-08 05:34:25 +00:00
|
|
|
// Normalise the score so that the user sees their relative progress to the next level rather than showing them their total score
|
2019-04-19 06:36:26 +00:00
|
|
|
prevScore := c.GetLevelScore(puser.Level)
|
2021-07-28 07:43:38 +00:00
|
|
|
score := puser.Score
|
|
|
|
//score = 23
|
|
|
|
currentScore := score - prevScore
|
2019-04-19 06:36:26 +00:00
|
|
|
nextScore := c.GetLevelScore(puser.Level+1) - prevScore
|
2021-07-28 07:43:38 +00:00
|
|
|
perc := int(math.Floor((float64(currentScore) / float64(nextScore)) * 100))
|
2019-10-20 01:42:19 +00:00
|
|
|
var blocked, blockedInv bool
|
|
|
|
if user.Loggedin {
|
|
|
|
blocked, err = c.UserBlocks.IsBlockedBy(user.ID, puser.ID)
|
|
|
|
if err != nil {
|
|
|
|
return c.InternalError(err, w, r)
|
|
|
|
}
|
|
|
|
blockedInv, err = c.UserBlocks.IsBlockedBy(puser.ID, user.ID)
|
|
|
|
if err != nil {
|
|
|
|
return c.InternalError(err, w, r)
|
|
|
|
}
|
2019-10-19 10:33:59 +00:00
|
|
|
}
|
2020-07-14 21:50:29 +00:00
|
|
|
|
2020-02-11 03:13:38 +00:00
|
|
|
canMessage := (!blockedInv && user.Perms.UseConvos) || (!blockedInv && puser.IsSuperMod && user.Perms.UseConvosOnlyWithMod) || user.IsSuperMod
|
2020-02-04 11:47:03 +00:00
|
|
|
canComment := !blockedInv && user.Perms.CreateProfileReply
|
2020-07-15 06:59:47 +00:00
|
|
|
showComments := c.PrivacyCommentsShow(puser, user)
|
2020-07-14 21:50:29 +00:00
|
|
|
if !showComments {
|
|
|
|
canComment = false
|
|
|
|
}
|
2020-07-15 06:59:47 +00:00
|
|
|
if !c.PrivacyAllowMessage(puser, user) {
|
2020-07-14 21:50:29 +00:00
|
|
|
canMessage = false
|
|
|
|
}
|
2019-10-19 10:33:59 +00:00
|
|
|
|
2021-07-28 07:43:38 +00:00
|
|
|
ppage := c.ProfilePage{h, reList, *puser, currentScore, nextScore, perc, blocked, canMessage, canComment, showComments}
|
2020-04-27 12:41:55 +00:00
|
|
|
return renderTemplate("profile", w, r, h, ppage)
|
2018-02-26 09:07:00 +00:00
|
|
|
}
|