Noah
6c91c67c97
* Users who set their Profile Picture to "friends only" or "private" can have their avatar be private all over the website to users who are not their friends or not granted access. * Users who are not your friends see a yellow placeholder avatar, and users not granted access to a private Profile Pic sees a purple avatar. * Admin users see these same placeholder avatars most places too (on search, forums, comments, etc.) if the user did not friend or grant the admin. But admins ALWAYS see it on their Profile Page directly, for ability to moderate. * Fix marking Notifications as read: clicking the link in an unread notification now will wait on the ajax request to finish before allowing the redirect. * Update the FAQ
141 lines
4.0 KiB
Go
141 lines
4.0 KiB
Go
package inbox
|
|
|
|
import (
|
|
"net/http"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/config"
|
|
"code.nonshy.com/nonshy/website/pkg/models"
|
|
"code.nonshy.com/nonshy/website/pkg/session"
|
|
"code.nonshy.com/nonshy/website/pkg/templates"
|
|
)
|
|
|
|
var ReadURLRegexp = regexp.MustCompile(`^/messages/read/(\d+)$`)
|
|
|
|
// Inbox is where users receive direct messages.
|
|
func Inbox() http.HandlerFunc {
|
|
tmpl := templates.Must("inbox/inbox.html")
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
currentUser, err := session.CurrentUser(r)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Unexpected error: could not get currentUser.")
|
|
templates.Redirect(w, "/")
|
|
return
|
|
}
|
|
|
|
// Default is inbox, what about sentbox?
|
|
var showSent = r.FormValue("box") == "sent"
|
|
|
|
// Are we reading a specific message?
|
|
var (
|
|
viewThread []*models.Message
|
|
threadPager *models.Pagination
|
|
composeToUsername string
|
|
msgId int
|
|
)
|
|
if uri := ReadURLRegexp.FindStringSubmatch(r.URL.Path); uri != nil {
|
|
msgId, _ = strconv.Atoi(uri[1])
|
|
if msg, err := models.GetMessage(uint64(msgId)); err != nil {
|
|
session.FlashError(w, r, "Message not found.")
|
|
templates.Redirect(w, "/messages")
|
|
return
|
|
} else {
|
|
// We must be a party to this thread.
|
|
if msg.SourceUserID != currentUser.ID && msg.TargetUserID != currentUser.ID {
|
|
templates.ForbiddenPage(w, r)
|
|
return
|
|
}
|
|
|
|
// Find the other party in this thread.
|
|
var senderUserID = msg.SourceUserID
|
|
if senderUserID == currentUser.ID {
|
|
senderUserID = msg.TargetUserID
|
|
}
|
|
|
|
// Look up the sender's username to compose a response to them.
|
|
sender, err := models.GetUser(senderUserID)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't get sender of that message: %s", err)
|
|
}
|
|
composeToUsername = sender.Username
|
|
|
|
// Get the full chat thread (paginated).
|
|
threadPager = &models.Pagination{
|
|
PerPage: config.PageSizeInboxThread,
|
|
Sort: "created_at desc",
|
|
}
|
|
threadPager.ParsePage(r)
|
|
thread, err := models.GetMessageThread(msg.SourceUserID, msg.TargetUserID, threadPager)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't get chat history: %s", err)
|
|
}
|
|
|
|
viewThread = thread
|
|
|
|
// Mark all these messages as read if the recipient sees them.
|
|
for _, m := range viewThread {
|
|
if m.TargetUserID == currentUser.ID && !m.Read {
|
|
m.Read = true
|
|
if err := m.Save(); err != nil {
|
|
session.FlashError(w, r, "Couldn't mark message as read: %s", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the inbox list of messages.
|
|
pager := &models.Pagination{
|
|
Page: 1,
|
|
PerPage: config.PageSizeInboxList,
|
|
Sort: "created_at desc",
|
|
}
|
|
if viewThread == nil {
|
|
// On the main inbox view, ?page= params page thru the message list, not a thread.
|
|
pager.ParsePage(r)
|
|
}
|
|
messages, err := models.GetMessages(currentUser.ID, showSent, pager)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't get your messages from DB: %s", err)
|
|
}
|
|
|
|
// How many unreads?
|
|
unread, err := models.CountUnreadMessages(currentUser.ID)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't get your unread message count from DB: %s", err)
|
|
}
|
|
|
|
// Map sender data on these messages.
|
|
var userIDs = []uint64{}
|
|
for _, m := range messages {
|
|
userIDs = append(userIDs, m.SourceUserID, m.TargetUserID)
|
|
}
|
|
if viewThread != nil {
|
|
for _, m := range viewThread {
|
|
userIDs = append(userIDs, m.SourceUserID, m.TargetUserID)
|
|
}
|
|
}
|
|
userMap, err := models.MapUsers(currentUser, userIDs)
|
|
if err != nil {
|
|
session.FlashError(w, r, "Couldn't map users: %s", err)
|
|
}
|
|
|
|
var vars = map[string]interface{}{
|
|
"Messages": messages,
|
|
"UserMap": userMap,
|
|
"Unread": unread,
|
|
"Pager": pager,
|
|
"IsSentBox": showSent,
|
|
"ViewThread": viewThread, // nil on inbox page
|
|
"ThreadPager": threadPager,
|
|
"ReplyTo": composeToUsername,
|
|
"MessageID": msgId,
|
|
}
|
|
if err := tmpl.Execute(w, r, vars); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
})
|
|
}
|