gosora/routes/profile.go
Azareal 0a628f7201 PNG and JPG avatars are now encoded as JPG images leading to a dramatic drop in the amount of bandwidth used.
Did some work on image thumbnailing, but our dependencies are acting up delaying this from being released.

Fixed the positions of the topic list bits for Nox on mobile.
Removed APNG as an accepted image format, as we don't currently have a good way of optimising these images.
Added a comment regarding the constant time compare for sessions.
Added a warning about putting Gosora in www folders.
Noavatars can now take a width parameters.
Added a bit of missing validation for the avatar uploader.
Refactored the multiple file detector for the avatar uploader.

Added a Run method to accDeleteBuilder.
Added an EachInt method to AccSelectBuilder.
Added a Run method to accInsertBuilder.

Added the users_avatar_queue table, you will need to run the patcher / update script.
You might also want to update the Noavatar field in your config.json file with the new one.
2018-07-28 22:52:23 +10:00

130 lines
3.8 KiB
Go

package routes
import (
"database/sql"
"net/http"
"strconv"
"strings"
"time"
"../common"
"../query_gen/lib"
)
type ProfileStmts struct {
getReplies *sql.Stmt
}
var profileStmts ProfileStmts
// TODO: Move these DbInits into some sort of abstraction
func init() {
common.DbInits.Add(func(acc *qgen.Accumulator) error {
profileStmts = ProfileStmts{
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 = ?", "", ""),
}
return acc.FirstError()
})
}
func ViewProfile(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
header, ferr := common.UserCheck(w, r, &user)
if ferr != nil {
return ferr
}
// TODO: Preload this?
header.AddSheet(header.Theme.Name + "/profile.css")
var err error
var replyCreatedAt time.Time
var replyContent, replyCreatedByName, replyRelativeCreatedAt, replyAvatar, replyMicroAvatar, replyTag, replyClassName string
var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int
var replyList []common.ReplyUser
// SEO URLs...
// TODO: Do a 301 if it's the wrong username? Do a canonical too?
halves := strings.Split(r.URL.Path[len("/user/"):], ".")
if len(halves) < 2 {
halves = append(halves, halves[0])
}
pid, err := strconv.Atoi(halves[1])
if err != nil {
return common.LocalError("The provided UserID is not a valid number.", w, r, user)
}
var puser *common.User
if pid == user.ID {
user.IsMod = true
puser = &user
} else {
// Fetch the user data
// TODO: Add a shared function for checking for ErrNoRows and internal erroring if it's not that case?
puser, err = common.Users.Get(pid)
if err == sql.ErrNoRows {
return common.NotFound(w, r, header)
} else if err != nil {
return common.InternalError(err, w, r)
}
}
// TODO: Add a phrase for this title
header.Title = puser.Name + "'s Profile"
// Get the replies..
rows, err := profileStmts.getReplies.Query(puser.ID)
if err != nil {
return common.InternalError(err, w, r)
}
defer rows.Close()
for rows.Next() {
err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &replyGroup)
if err != nil {
return common.InternalError(err, w, r)
}
group, err := common.Groups.Get(replyGroup)
if err != nil {
return common.InternalError(err, w, r)
}
replyLines = strings.Count(replyContent, "\n")
if group.IsMod {
replyClassName = common.Config.StaffCSS
} else {
replyClassName = ""
}
replyAvatar, replyMicroAvatar = common.BuildAvatar(replyCreatedBy, replyAvatar)
if group.Tag != "" {
replyTag = group.Tag
} else if puser.ID == replyCreatedBy {
replyTag = "Profile Owner"
} else {
replyTag = ""
}
replyLiked := false
replyLikeCount := 0
replyRelativeCreatedAt = common.RelativeTime(replyCreatedAt)
// TODO: Add a hook here
replyList = append(replyList, common.ReplyUser{rid, puser.ID, replyContent, common.ParseMessage(replyContent, 0, ""), replyCreatedBy, common.BuildProfileURL(common.NameToSlug(replyCreatedByName), replyCreatedBy), replyCreatedByName, replyGroup, replyCreatedAt, replyRelativeCreatedAt, replyLastEdit, replyLastEditBy, replyAvatar, replyMicroAvatar, replyClassName, replyLines, replyTag, "", "", "", 0, "", replyLiked, replyLikeCount, "", ""})
}
err = rows.Err()
if err != nil {
return common.InternalError(err, w, r)
}
ppage := common.ProfilePage{header, replyList, *puser}
if common.RunPreRenderHook("pre_render_profile", w, r, &user, &ppage) {
return nil
}
err = common.RunThemeTemplate(header.Theme.Name, "profile", ppage, w)
if err != nil {
return common.InternalError(err, w, r)
}
return nil
}