170 lines
4.1 KiB
Go
170 lines
4.1 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 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, "forums.explicit = false")
|
|
}
|
|
|
|
// Circle membership.
|
|
if !user.IsInnerCircle() {
|
|
wheres = append(wheres, "forums.inner_circle is not true")
|
|
}
|
|
|
|
// 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!", rc.ThreadID)
|
|
}
|
|
|
|
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
|
|
}
|