1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-09 12:06:24 -07:00
gochan/pkg/gcsql/postsretrievalqueries.go
Eggbertx 8e706a313c Make template for recent posts page
Also make manage page h1 headers automatic
2022-01-29 23:47:13 -08:00

316 lines
11 KiB
Go

package gcsql
import (
"database/sql"
"errors"
"html/template"
"strconv"
)
var abstractSelectPosts = `
/*
Left join singlefiles on recentposts where recentposts.selfid = singlefiles.post_id
Coalesce filenames to "" (if filename = null -> "" else filename)
*/
Select
recentposts.selfid AS id,
recentposts.toppostid AS parentid,
recentposts.boardid,
recentposts.name,
recentposts.tripcode,
recentposts.email,
recentposts.subject,
recentposts.message,
recentposts.message_raw,
recentposts.password,
COALESCE(singlefiles.filename, '') as filename,
COALESCE(singlefiles.original_filename, '') as original_filename,
COALESCE(singlefiles.checksum, ''),
COALESCE(singlefiles.file_size, 0),
COALESCE(singlefiles.width, 0),
COALESCE(singlefiles.height, 0),
COALESCE(singlefiles.thumbnail_width, 0),
COALESCE(singlefiles.thumbnail_height, 0),
recentposts.ip,
recentposts.created_on,
recentposts.anchored,
recentposts.last_bump,
recentposts.stickied,
recentposts.locked
FROM
(SELECT
posts.id AS selfid,
COALESCE(NULLIF(topposts.id, posts.id), 0) AS toppostid,
boards.id AS boardid,
posts.name,
posts.ip,
posts.tripcode,
posts.message,
posts.email,
posts.subject,
posts.message_raw,
posts.password,
posts.created_on,
posts.is_top_post,
threads.anchored,
threads.last_bump,
threads.stickied,
threads.locked
FROM
DBPREFIXposts AS posts
JOIN DBPREFIXthreads AS threads
ON threads.id = posts.thread_id
JOIN DBPREFIXposts AS topposts
ON threads.id = topposts.thread_id
JOIN DBPREFIXboards AS boards
ON threads.board_id = boards.id
WHERE
topposts.is_top_post = TRUE AND posts.is_deleted = FALSE
) as recentposts
LEFT JOIN
(SELECT files.*
FROM DBPREFIXfiles as files
JOIN
(SELECT post_id, min(file_order) as file_order
FROM DBPREFIXfiles
GROUP BY post_id) as topfiles
ON files.post_id = topfiles.post_id AND files.file_order = topfiles.file_order
) AS singlefiles
ON recentposts.selfid = singlefiles.post_id`
// getPostsExcecution excecutes a given variation on abstractSelectPosts with parameters and loads the result into an array of posts
func getPostsExcecution(sql string, arguments ...interface{}) ([]Post, error) {
rows, err := QuerySQL(sql, arguments...)
if err != nil {
return nil, err
}
var posts []Post
for rows.Next() {
post := new(Post)
var messageHTML string
if err = rows.Scan(&post.ID, &post.ParentID, &post.BoardID, &post.Name, &post.Tripcode, &post.Email,
&post.Subject, &messageHTML, &post.MessageText, &post.Password, &post.Filename,
&post.FilenameOriginal, &post.FileChecksum, &post.Filesize, &post.ImageW, &post.ImageH,
&post.ThumbW, &post.ThumbH, &post.IP, &post.Timestamp, &post.Autosage, &post.Bumped, &post.Stickied, &post.Locked,
); err != nil {
return nil, err
}
post.MessageHTML = template.HTML(messageHTML)
post.FileExt = "placeholder"
posts = append(posts, *post)
}
return posts, nil
}
var onlyTopPosts = abstractSelectPosts + "\nWHERE recentposts.is_top_post AND recentposts.boardid = ?"
var sortedTopPosts = onlyTopPosts + "\nORDER BY recentposts.last_bump DESC"
// GetTopPostsNoSort gets the thread ops for a given board.
// Results are unsorted
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetTopPostsNoSort(boardID int) (posts []Post, err error) {
return getPostsExcecution(onlyTopPosts, boardID)
}
// GetTopPosts gets the thread ops for a given board.
// newestFirst sorts the ops by the newest first if true, by newest last if false
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetTopPosts(boardID int) (posts []Post, err error) {
return getPostsExcecution(sortedTopPosts, boardID)
}
var repliesToX = abstractSelectPosts + "\nWHERE recentposts.toppostid = ?"
var oldestRepliesFirst = repliesToX + "\nORDER BY recentposts.created_on ASC"
var newestFirstLimited = repliesToX + "\nORDER BY recentposts.created_on DESC\nLIMIT ?"
// GetExistingReplies gets all the reply posts to a given thread, ordered by oldest first.
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetExistingReplies(topPost int) (posts []Post, err error) {
return getPostsExcecution(oldestRepliesFirst, topPost)
}
// GetExistingRepliesLimitedRev gets N amount of reply posts to a given thread, ordered by newest first.
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetExistingRepliesLimitedRev(topPost, limit int) (posts []Post, err error) {
return getPostsExcecution(newestFirstLimited, topPost, limit)
}
//Toppost: where a post with a given id has this as their top post
// GetSpecificTopPost gets the information for the top post for a given id.
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetSpecificTopPost(ID int) (Post, error) {
const topPostIDQuery = `SELECT posts.id from DBPREFIXposts as posts
JOIN (
SELECT threads.id from DBPREFIXthreads as threads
JOIN DBPREFIXposts as posts
ON posts.thread_id = threads.id
WHERE posts.id = ?
) as thread
ON posts.thread_id = thread.id
WHERE posts.is_top_post`
//get top post of item with given id
var FoundID int
err := QueryRowSQL(topPostIDQuery, interfaceSlice(ID), interfaceSlice(&FoundID))
if err != nil {
return Post{}, err
}
return GetSpecificPost(FoundID, false)
}
// GetSpecificPostByString gets a specific post for a given string id.
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetSpecificPostByString(ID string) (Post, error) {
return getSpecificPostStringDecorated(ID, false)
}
// GetSpecificPost gets a specific post for a given id.
// returns SQL.ErrNoRows if no post could be found
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetSpecificPost(ID int, onlyNotDeleted bool) (Post, error) {
return getSpecificPostStringDecorated(strconv.Itoa(ID), onlyNotDeleted)
}
var specificPostSQL = abstractSelectPosts + "\nWHERE recentposts.selfid = ?"
var specificPostSQLNotDeleted = specificPostSQL + "\nWHERE recentposts.is_deleted = FALSE"
func getSpecificPostStringDecorated(ID string, onlyNotDeleted bool) (Post, error) {
var sql string
if onlyNotDeleted {
sql = specificPostSQL
} else {
sql = specificPostSQLNotDeleted
}
posts, err := getPostsExcecution(sql, ID)
if err != nil {
return Post{}, err
}
if len(posts) == 0 {
return Post{}, errors.New("Could not find a post with the ID: " + ID)
}
return posts[0], nil
}
// getRecentPostsInternal returns the most recent N posts, on a specific board if specified, only with files if specified
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
// TODO: rework so it uses all features/better sql
// get recent posts
func getRecentPostsInternal(amount int, onlyWithFile bool, boardID int, onSpecificBoard bool) ([]RecentPost, error) {
// recentposts = join all non-deleted posts with the post id of their thread and the board it belongs on, sort by date and grab top x posts
// singlefiles = the top file per post id
// Left join singlefiles on recentposts where recentposts.selfid = singlefiles.post_id
// Coalesce filenames to "" (if filename = null -> "" else filename)
// Query might benefit from [filter on posts with at least one file -> ] filter N most recent -> manually loop N results for file/board/parentthreadid
recentQueryStr := `SELECT
recentposts.selfid AS id,
recentposts.toppostid AS parentid,
recentposts.boardname,
recentposts.boardid,
recentposts.ip,
recentposts.name,
recentposts.tripcode,
recentposts.message,
COALESCE(singlefiles.filename, '') as filename,
COALESCE(singlefiles.thumbnail_width, 0) as thumb_w,
COALESCE(singlefiles.thumbnail_height, 0) as thumb_h
FROM
(SELECT
posts.id AS selfid,
topposts.id AS toppostid,
boards.dir AS boardname,
boards.id AS boardid,
posts.ip,
posts.name,
posts.tripcode,
posts.message,
posts.email,
posts.created_on
FROM
DBPREFIXposts AS posts
JOIN DBPREFIXthreads AS threads
ON threads.id = posts.thread_id
JOIN DBPREFIXposts AS topposts
ON threads.id = topposts.thread_id
JOIN DBPREFIXboards AS boards
ON threads.board_id = boards.id
WHERE
topposts.is_top_post = TRUE AND posts.is_deleted = FALSE
) as recentposts
LEFT JOIN
(SELECT files.post_id, filename, files.thumbnail_width, files.thumbnail_height
FROM DBPREFIXfiles as files
JOIN
(SELECT post_id, min(file_order) as file_order
FROM DBPREFIXfiles
GROUP BY post_id) as topfiles
ON files.post_id = topfiles.post_id AND files.file_order = topfiles.file_order
) AS singlefiles
ON recentposts.selfid = singlefiles.post_id`
var rows *sql.Rows
var err error
if onlyWithFile && onSpecificBoard {
recentQueryStr += "\n" + `WHERE singlefiles.filename IS NOT NULL AND recentposts.boardid = ?
ORDER BY recentposts.created_on DESC LIMIT ?`
rows, err = QuerySQL(recentQueryStr, boardID, amount)
}
if onlyWithFile && !onSpecificBoard {
recentQueryStr += "\n" + `WHERE singlefiles.filename IS NOT NULL
ORDER BY recentposts.created_on DESC LIMIT ?`
rows, err = QuerySQL(recentQueryStr, amount)
}
if !onlyWithFile && onSpecificBoard {
recentQueryStr += "\n" + `WHERE recentposts.boardid = ?
ORDER BY recentposts.created_on DESC LIMIT ?`
rows, err = QuerySQL(recentQueryStr, boardID, amount)
}
if !onlyWithFile && !onSpecificBoard {
recentQueryStr += "\nORDER BY recentposts.created_on DESC LIMIT ?"
rows, err = QuerySQL(recentQueryStr, amount)
}
if err != nil {
return nil, err
}
defer rows.Close()
var recentPostsArr []RecentPost
for rows.Next() {
recentPost := new(RecentPost)
var formattedHTML template.HTML
if err = rows.Scan(
&recentPost.PostID, &recentPost.ParentID, &recentPost.BoardName, &recentPost.BoardID,
&recentPost.IP, &recentPost.Name, &recentPost.Tripcode, &formattedHTML, &recentPost.Filename,
&recentPost.ThumbW, &recentPost.ThumbH,
); err != nil {
return nil, err
}
recentPost.Message = formattedHTML
recentPostsArr = append(recentPostsArr, *recentPost)
}
return recentPostsArr, nil
}
// GetRecentPostsGlobal returns the global N most recent posts from the database.
// Deprecated: This method was created to support old functionality during the database refactor of april 2020
// The code should be changed to reflect the new database design
func GetRecentPostsGlobal(amount int, onlyWithFile bool) ([]RecentPost, error) {
return getRecentPostsInternal(amount, onlyWithFile, 0, false)
}