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
165 lines
4.0 KiB
Go
165 lines
4.0 KiB
Go
package models
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"code.nonshy.com/nonshy/website/pkg/log"
|
|
)
|
|
|
|
// RecentPost drives the "Forums / Newest" page - carrying all forum comments
|
|
// on all threads sorted by date.
|
|
type RecentPost struct {
|
|
CommentID uint64
|
|
ThreadID uint64
|
|
ForumID uint64
|
|
UpdatedAt time.Time
|
|
Thread *Thread
|
|
Comment *Comment
|
|
Forum *Forum
|
|
}
|
|
|
|
// PaginateRecentPosts returns all of the comments on a forum paginated.
|
|
func PaginateRecentPosts(user *User, categories []string, pager *Pagination) ([]*RecentPost, error) {
|
|
var (
|
|
result = []*RecentPost{}
|
|
query = (&Comment{}).Preload()
|
|
wheres = []string{"table_name = 'threads'"}
|
|
placeholders = []interface{}{}
|
|
)
|
|
|
|
if categories != nil && len(categories) > 0 {
|
|
wheres = append(wheres, "forums.category IN ?")
|
|
placeholders = append(placeholders, categories)
|
|
}
|
|
|
|
// Hide explicit forum if user hasn't opted into it.
|
|
if !user.Explicit && !user.IsAdmin {
|
|
wheres = append(wheres, "explicit = false")
|
|
}
|
|
|
|
// Get the page of recent forum comment IDs of all time.
|
|
type scanner struct {
|
|
CommentID uint64
|
|
ThreadID *uint64
|
|
ForumID *uint64
|
|
}
|
|
var scan []scanner
|
|
query = DB.Table("comments").Select(
|
|
`comments.id AS comment_id,
|
|
threads.id AS thread_id,
|
|
forums.id AS forum_id`,
|
|
).Joins(
|
|
"LEFT OUTER JOIN threads ON (table_name = 'threads' AND table_id = threads.id)",
|
|
).Joins(
|
|
"LEFT OUTER JOIN forums ON (threads.forum_id = forums.id)",
|
|
).Where(
|
|
strings.Join(wheres, " AND "),
|
|
placeholders...,
|
|
).Order("comments.updated_at desc")
|
|
|
|
// Get the total for the pager and scan the page of ID sets.
|
|
query.Model(&Comment{}).Count(&pager.Total)
|
|
query = query.Offset(pager.GetOffset()).Limit(pager.PerPage).Find(&scan)
|
|
if query.Error != nil {
|
|
return nil, query.Error
|
|
}
|
|
|
|
// Ingest the results.
|
|
var (
|
|
commentIDs = []uint64{} // collect distinct IDs
|
|
threadIDs = []uint64{}
|
|
forumIDs = []uint64{}
|
|
seenComments = map[uint64]interface{}{} // deduplication
|
|
seenThreads = map[uint64]interface{}{}
|
|
seenForums = map[uint64]interface{}{}
|
|
mapCommentRC = map[uint64]*RecentPost{} // map commentID to result
|
|
)
|
|
for _, row := range scan {
|
|
// Upsert the result set.
|
|
var rp *RecentPost
|
|
if existing, ok := mapCommentRC[row.CommentID]; ok {
|
|
rp = existing
|
|
} else {
|
|
rp = &RecentPost{
|
|
CommentID: row.CommentID,
|
|
}
|
|
mapCommentRC[row.CommentID] = rp
|
|
result = append(result, rp)
|
|
}
|
|
|
|
// Got a thread ID?
|
|
if row.ThreadID != nil {
|
|
rp.ThreadID = *row.ThreadID
|
|
if _, ok := seenThreads[rp.ThreadID]; !ok {
|
|
seenThreads[rp.ThreadID] = nil
|
|
threadIDs = append(threadIDs, rp.ThreadID)
|
|
}
|
|
|
|
}
|
|
|
|
// Got a forum ID?
|
|
if row.ForumID != nil {
|
|
rp.ForumID = *row.ForumID
|
|
if _, ok := seenForums[rp.ForumID]; !ok {
|
|
seenForums[rp.ForumID] = nil
|
|
forumIDs = append(forumIDs, rp.ForumID)
|
|
}
|
|
}
|
|
|
|
// Collect distinct comment IDs.
|
|
if _, ok := seenComments[rp.CommentID]; !ok {
|
|
seenComments[rp.CommentID] = nil
|
|
commentIDs = append(commentIDs, rp.CommentID)
|
|
}
|
|
}
|
|
|
|
// Load all of the distinct comments, threads and forums.
|
|
var (
|
|
comments = map[uint64]*Comment{}
|
|
threads = map[uint64]*Thread{}
|
|
forums = map[uint64]*Forum{}
|
|
)
|
|
|
|
if len(commentIDs) > 0 {
|
|
comments, _ = GetComments(commentIDs)
|
|
}
|
|
if len(threadIDs) > 0 {
|
|
threads, _ = GetThreads(threadIDs)
|
|
}
|
|
if len(forumIDs) > 0 {
|
|
forums, _ = GetForums(forumIDs)
|
|
}
|
|
|
|
// Collect comments so we can inject UserRelationships in efficiently.
|
|
var (
|
|
coms = []*Comment{}
|
|
thrs = []*Thread{}
|
|
)
|
|
|
|
// Merge all the objects back in.
|
|
for _, rc := range result {
|
|
if com, ok := comments[rc.CommentID]; ok {
|
|
rc.Comment = com
|
|
coms = append(coms, com)
|
|
}
|
|
|
|
if thr, ok := threads[rc.ThreadID]; ok {
|
|
rc.Thread = thr
|
|
thrs = append(thrs, thr)
|
|
} else {
|
|
log.Error("RecentPosts: didn't find thread ID %d in map!")
|
|
}
|
|
|
|
if f, ok := forums[rc.ForumID]; ok {
|
|
rc.Forum = f
|
|
}
|
|
}
|
|
|
|
// Inject user relationships into all comment users now.
|
|
SetUserRelationshipsInComments(user, coms)
|
|
SetUserRelationshipsInThreads(user, thrs)
|
|
|
|
return result, nil
|
|
}
|