mirror of
https://github.com/Eggbertx/gochan.git
synced 2025-08-02 23:26:23 -07:00
de-deprecate pkg/building
This commit is contained in:
parent
be14983186
commit
e789b08492
5 changed files with 272 additions and 201 deletions
|
@ -7,7 +7,6 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/config"
|
||||
"github.com/gochan-org/gochan/pkg/gcsql"
|
||||
|
@ -27,113 +26,111 @@ var (
|
|||
ErrNoBoardTitle = errors.New("board must have a title before it is built")
|
||||
)
|
||||
|
||||
// BuildBoardPages builds the pages for the board archive.
|
||||
// `board` is a Board object representing the board to build archive pages for.
|
||||
// The return value is a string of HTML with debug information from the build process.
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func boolToInt(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// BuildBoardPages builds the front pages for the given board, and returns any error it encountered.
|
||||
func BuildBoardPages(board *gcsql.Board) error {
|
||||
err := gctemplates.InitTemplates("boardpage")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var currentPageFile *os.File
|
||||
var threadPages [][]interface{}
|
||||
var stickiedThreads []interface{}
|
||||
var nonStickiedThreads []interface{}
|
||||
var opPosts []gcsql.Post
|
||||
var stickiedThreads []gcsql.Thread
|
||||
var nonStickiedThreads []gcsql.Thread
|
||||
var catalog boardCatalog
|
||||
var catalogThreads []catalogThreadData
|
||||
|
||||
threads, err := gcsql.GetThreadsWithBoardID(board.ID, true)
|
||||
threads, err := board.GetThreads(true)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Int("boardID", board.ID).
|
||||
Msg("Failed getting OP posts")
|
||||
Msg("Failed getting board threads")
|
||||
return fmt.Errorf("error getting OP posts for /%s/: %s", board.Dir, err.Error())
|
||||
}
|
||||
|
||||
// Get all top level posts for the board
|
||||
if opPosts, err = gcsql.GetTopPosts(board.ID); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Msg("Failed getting OP posts")
|
||||
return fmt.Errorf("error getting OP posts for /%s/: %s", board.Dir, err.Error())
|
||||
}
|
||||
|
||||
// For each top level post, start building a Thread struct
|
||||
for p := range opPosts {
|
||||
op := &opPosts[p]
|
||||
var thread gcsql.Thread
|
||||
var postsInThread []gcsql.Post
|
||||
|
||||
var replyCount, err = gcsql.GetReplyCount(op.ID)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Int("op", op.ID).
|
||||
Msg("Failed getting thread replies")
|
||||
return fmt.Errorf("Error getting replies to /%s/%d: %s", board.Dir, op.ID, err.Error())
|
||||
for _, thread := range threads {
|
||||
catalogThread := catalogThreadData{
|
||||
Locked: boolToInt(thread.Locked),
|
||||
Sticky: boolToInt(thread.Stickied),
|
||||
}
|
||||
thread.NumReplies = replyCount
|
||||
|
||||
fileCount, err := gcsql.GetReplyFileCount(op.ID)
|
||||
if err != nil {
|
||||
if catalogThread.Images, err = thread.GetReplyFileCount(); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Int("op", op.ID).
|
||||
Int("threadID", thread.ID).
|
||||
Msg("Failed getting file count")
|
||||
return fmt.Errorf("Error getting file count to /%s/%d: %s", board.Dir, op.ID, err.Error())
|
||||
return errors.New("Error getting file count")
|
||||
}
|
||||
thread.NumImages = fileCount
|
||||
|
||||
thread.OP = *op
|
||||
|
||||
var numRepliesOnBoardPage int
|
||||
postCfg := config.GetBoardConfig("").PostConfig
|
||||
if op.Stickied {
|
||||
var maxRepliesOnBoardPage int
|
||||
postCfg := config.GetBoardConfig(board.Dir).PostConfig
|
||||
if thread.Stickied {
|
||||
// If the thread is stickied, limit replies on the archive page to the
|
||||
// configured value for stickied threads.
|
||||
numRepliesOnBoardPage = postCfg.StickyRepliesOnBoardPage
|
||||
maxRepliesOnBoardPage = postCfg.StickyRepliesOnBoardPage
|
||||
} else {
|
||||
// Otherwise, limit the replies to the configured value for normal threads.
|
||||
numRepliesOnBoardPage = postCfg.RepliesOnBoardPage
|
||||
maxRepliesOnBoardPage = postCfg.RepliesOnBoardPage
|
||||
}
|
||||
|
||||
postsInThread, err = gcsql.GetExistingRepliesLimitedRev(op.ID, numRepliesOnBoardPage)
|
||||
catalogThread.Replies, err = thread.GetReplyCount()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Int("op", op.ID).
|
||||
Msg("Failed getting thread posts")
|
||||
return fmt.Errorf("Error getting posts in /%s/%d: %s", board.Dir, op.ID, err.Error())
|
||||
Int("threadID", thread.ID).
|
||||
Msg("Failed getting reply count")
|
||||
return errors.New("Error getting reply count: " + err.Error())
|
||||
}
|
||||
catalogThread.posts, err = thread.GetPosts(false, true, maxRepliesOnBoardPage)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Int("threadid", thread.ID).
|
||||
Str("boardDir", board.Dir).
|
||||
Msg("Failed getting replies")
|
||||
return errors.New("Failed getting replies: " + err.Error())
|
||||
}
|
||||
catalogThread.uploads, err = thread.GetUploads()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Int("threadid", thread.ID).
|
||||
Str("boardDir", board.Dir).
|
||||
Msg("Failed getting thread uploads")
|
||||
return errors.New("Failed getting thread uploads: " + err.Error())
|
||||
}
|
||||
|
||||
var reversedPosts []gcsql.Post
|
||||
for i := len(postsInThread); i > 0; i-- {
|
||||
reversedPosts = append(reversedPosts, postsInThread[i-1])
|
||||
}
|
||||
|
||||
if len(postsInThread) > 0 {
|
||||
// Store the posts to show on board page
|
||||
//thread.BoardReplies = postsInThread
|
||||
thread.BoardReplies = reversedPosts
|
||||
|
||||
// Count number of images on board page
|
||||
imageCount := 0
|
||||
for p := range postsInThread {
|
||||
reply := &postsInThread[p]
|
||||
if reply.Filesize != 0 {
|
||||
imageCount++
|
||||
var imagesOnBoardPage int
|
||||
for _, upload := range catalogThread.uploads {
|
||||
for _, post := range catalogThread.posts {
|
||||
if post.ID == upload.PostID {
|
||||
imagesOnBoardPage++
|
||||
}
|
||||
}
|
||||
// Then calculate number of omitted images.
|
||||
thread.OmittedImages = thread.NumImages - imageCount
|
||||
}
|
||||
if catalogThread.Replies > maxRepliesOnBoardPage {
|
||||
catalogThread.OmittedPosts = catalogThread.Replies - len(catalogThread.posts)
|
||||
catalogThread.OmittedImages = len(catalogThread.uploads) - imagesOnBoardPage
|
||||
}
|
||||
catalogThread.OmittedPosts = catalogThread.Replies - len(catalogThread.posts)
|
||||
|
||||
// Add thread struct to appropriate list
|
||||
if op.Stickied {
|
||||
if thread.Stickied {
|
||||
stickiedThreads = append(stickiedThreads, thread)
|
||||
} else {
|
||||
nonStickiedThreads = append(nonStickiedThreads, thread)
|
||||
}
|
||||
catalogThreads = append(catalogThreads, catalogThread)
|
||||
}
|
||||
|
||||
criticalCfg := config.GetSystemCriticalConfig()
|
||||
gcutil.DeleteMatchingFiles(path.Join(criticalCfg.DocumentRoot, board.Dir), "\\d.html$")
|
||||
// Order the threads, stickied threads first, then nonstickied threads.
|
||||
|
@ -142,10 +139,11 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
// If there are no posts on the board
|
||||
var boardPageFile *os.File
|
||||
if len(threads) == 0 {
|
||||
board.CurrentPage = 1
|
||||
catalog.currentPage = 1
|
||||
|
||||
// Open 1.html for writing to the first page.
|
||||
boardPageFile, err = os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "1.html"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
boardPageFile, err = os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "1.html"),
|
||||
os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
|
@ -175,11 +173,10 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
|
||||
// Create the archive pages.
|
||||
boardCfg := config.GetBoardConfig(board.Dir)
|
||||
threadPages = paginate(boardCfg.ThreadsPerPage, threads)
|
||||
board.NumPages = len(threadPages)
|
||||
catalog.fillPages(boardCfg.ThreadsPerPage, catalogThreads)
|
||||
|
||||
// Create array of page wrapper objects, and open the file.
|
||||
var pagesArr boardCatalog
|
||||
var catalogPages boardCatalog
|
||||
|
||||
catalogJSONFile, err := os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "catalog.json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
|
@ -191,11 +188,11 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
}
|
||||
defer catalogJSONFile.Close()
|
||||
|
||||
currentBoardPage := board.CurrentPage
|
||||
for _, pageThreads := range threadPages {
|
||||
board.CurrentPage++
|
||||
// currentBoardPage := catalog.currentPage
|
||||
for _, page := range catalog.pages {
|
||||
catalog.currentPage++
|
||||
var currentPageFilepath string
|
||||
pageFilename := strconv.Itoa(board.CurrentPage) + ".html"
|
||||
pageFilename := strconv.Itoa(catalog.currentPage) + ".html"
|
||||
currentPageFilepath = path.Join(criticalCfg.DocumentRoot, board.Dir, pageFilename)
|
||||
currentPageFile, err = os.OpenFile(currentPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
|
@ -212,11 +209,11 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
"webroot": criticalCfg.WebRoot,
|
||||
"boards": gcsql.AllBoards,
|
||||
"sections": gcsql.AllSections,
|
||||
"threads": pageThreads,
|
||||
"threads": page.Threads,
|
||||
"board": board,
|
||||
"board_config": config.GetBoardConfig(board.Dir),
|
||||
"board_config": boardCfg,
|
||||
"posts": []interface{}{
|
||||
gcsql.Post{BoardID: board.ID},
|
||||
gcsql.Post{},
|
||||
},
|
||||
}, currentPageFile, "text/html"); err != nil {
|
||||
gcutil.LogError(err).
|
||||
|
@ -226,15 +223,15 @@ func BuildBoardPages(board *gcsql.Board) error {
|
|||
}
|
||||
|
||||
// Collect up threads for this page.
|
||||
pageMap := make(map[string]interface{})
|
||||
pageMap["page"] = board.CurrentPage
|
||||
pageMap["threads"] = pageThreads
|
||||
pagesArr = append(pagesArr, pageMap)
|
||||
page := catalogPage{}
|
||||
page.PageNum = catalog.currentPage
|
||||
// page.Threads = page.Threads
|
||||
catalogPages.pages = append(catalogPages.pages, page)
|
||||
}
|
||||
board.CurrentPage = currentBoardPage
|
||||
// board.CurrentPage = currentBoardPage
|
||||
|
||||
var catalogJSON []byte
|
||||
if catalogJSON, err = json.Marshal(pagesArr); err != nil {
|
||||
if catalogJSON, err = json.Marshal(catalog.pages); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Msg("Failed to marshal to JSON")
|
||||
|
@ -258,23 +255,24 @@ func BuildBoards(verbose bool, which ...int) error {
|
|||
if which == nil {
|
||||
boards = gcsql.AllBoards
|
||||
} else {
|
||||
for b, id := range which {
|
||||
boards = append(boards, gcsql.Board{})
|
||||
if err = boards[b].PopulateData(id); err != nil {
|
||||
for _, boardID := range which {
|
||||
board, err := gcsql.GetBoardFromID(boardID)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Int("boardid", id).
|
||||
Int("boardid", boardID).
|
||||
Msg("Unable to get board information")
|
||||
return fmt.Errorf("Error getting board information (ID: %d): %s", id, err.Error())
|
||||
return fmt.Errorf("Error getting board information (ID: %d): %s", boardID, err.Error())
|
||||
}
|
||||
boards = append(boards, *board)
|
||||
}
|
||||
}
|
||||
if len(boards) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for b := range boards {
|
||||
board := &boards[b]
|
||||
if err = buildBoard(board, false, true); err != nil {
|
||||
for _, board := range boards {
|
||||
// board := &boards[b]
|
||||
if err = buildBoard(&board, true); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Msg("Failed building board")
|
||||
|
@ -294,8 +292,8 @@ func BuildCatalog(boardID int) string {
|
|||
return err.Error()
|
||||
}
|
||||
|
||||
var board gcsql.Board
|
||||
if err = board.PopulateData(boardID); err != nil {
|
||||
board, err := gcsql.GetBoardFromID(boardID)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Int("boardid", boardID).
|
||||
Msg("Unable to get board information")
|
||||
|
@ -311,12 +309,7 @@ func BuildCatalog(boardID int) string {
|
|||
return fmt.Sprintf("Failed opening /%s/catalog.html: %s<br/>", board.Dir, err.Error())
|
||||
}
|
||||
|
||||
threadOPs, err := gcsql.GetTopPosts(boardID)
|
||||
// threadOPs, err := getPostArr(map[string]interface{}{
|
||||
// "boardid": boardID,
|
||||
// "parentid": 0,
|
||||
// "deleted_timestamp": nilTimestamp,
|
||||
// }, "ORDER BY bumped ASC")
|
||||
threadOPs, err := gcsql.GetBoardTopPosts(boardID, true)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "catalog").
|
||||
|
@ -341,9 +334,8 @@ func BuildCatalog(boardID int) string {
|
|||
}
|
||||
|
||||
// Build builds the board and its thread files
|
||||
// if newBoard is true, it adds a row to DBPREFIXboards and fails if it exists
|
||||
// if force is true, it doesn't fail if the directories exist but does fail if it is a file
|
||||
func buildBoard(board *gcsql.Board, newBoard, force bool) error {
|
||||
func buildBoard(board *gcsql.Board, force bool) error {
|
||||
var err error
|
||||
if board.Dir == "" {
|
||||
return ErrNoBoardDir
|
||||
|
@ -352,16 +344,6 @@ func buildBoard(board *gcsql.Board, newBoard, force bool) error {
|
|||
return ErrNoBoardTitle
|
||||
}
|
||||
|
||||
if newBoard {
|
||||
board.CreatedOn = time.Now()
|
||||
err := gcsql.CreateBoard(board)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err = board.UpdateID(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dirPath := board.AbsolutePath()
|
||||
resPath := board.AbsolutePath("res")
|
||||
srcPath := board.AbsolutePath("src")
|
||||
|
|
|
@ -7,6 +7,8 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/gochan-org/gochan/pkg/config"
|
||||
"github.com/gochan-org/gochan/pkg/gcsql"
|
||||
|
@ -15,6 +17,64 @@ import (
|
|||
"github.com/gochan-org/gochan/pkg/serverutil"
|
||||
)
|
||||
|
||||
var (
|
||||
bbcodeTagRE = regexp.MustCompile(`\[/?[^\[\]\s]+\]`)
|
||||
)
|
||||
|
||||
type recentPost struct {
|
||||
Board string
|
||||
URL string
|
||||
ThumbURL string
|
||||
FileDeleted bool
|
||||
MessageSample string
|
||||
}
|
||||
|
||||
func getRecentPosts() ([]recentPost, error) {
|
||||
siteCfg := config.GetSiteConfig()
|
||||
query := `SELECT id, thread_id AS threadid, message_raw,
|
||||
(SELECT dir FROM DBPREFIXboards WHERE id = (
|
||||
SELECT board_id FROM DBPREFIXthreads WHERE id = threadid)
|
||||
) AS board,
|
||||
COALESCE(
|
||||
(SELECT filename FROM DBPREFIXfiles WHERE post_id = DBPREFIXposts.id LIMIT 1),
|
||||
"") AS filename,
|
||||
(SELECT id FROM DBPREFIXposts WHERE is_top_post = TRUE AND thread_id = threadid) AS top_post
|
||||
FROM DBPREFIXposts WHERE is_deleted = FALSE LIMIT ` + strconv.Itoa(siteCfg.MaxRecentPosts)
|
||||
rows, err := gcsql.QuerySQL(query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var recentPosts []recentPost
|
||||
|
||||
for rows.Next() {
|
||||
var post recentPost
|
||||
var id, threadID, topPostID string
|
||||
var message, boardDir, filename string
|
||||
err = rows.Scan(&id, &threadID, &message, &boardDir, &filename, &topPostID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if filename == "" && !siteCfg.RecentPostsWithNoFile {
|
||||
continue
|
||||
}
|
||||
message = bbcodeTagRE.ReplaceAllString(message, "")
|
||||
if len(message) > 40 {
|
||||
message = message[:37] + "..."
|
||||
}
|
||||
post = recentPost{
|
||||
Board: boardDir,
|
||||
URL: config.WebPath(boardDir, "res", topPostID+".html") + "#" + id,
|
||||
ThumbURL: config.WebPath(boardDir, "thumb", gcutil.GetThumbnailPath("post", filename)),
|
||||
FileDeleted: filename == "deleted",
|
||||
MessageSample: message,
|
||||
}
|
||||
|
||||
recentPosts = append(recentPosts, post)
|
||||
}
|
||||
return recentPosts, nil
|
||||
}
|
||||
|
||||
// BuildFrontPage builds the front page using templates/front.html
|
||||
func BuildFrontPage() error {
|
||||
err := gctemplates.InitTemplates("front")
|
||||
|
@ -25,8 +85,8 @@ func BuildFrontPage() error {
|
|||
}
|
||||
criticalCfg := config.GetSystemCriticalConfig()
|
||||
os.Remove(path.Join(criticalCfg.DocumentRoot, "index.html"))
|
||||
frontFile, err := os.OpenFile(path.Join(criticalCfg.DocumentRoot, "index.html"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
|
||||
frontFile, err := os.OpenFile(path.Join(criticalCfg.DocumentRoot, "index.html"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "front").Send()
|
||||
|
@ -34,21 +94,15 @@ func BuildFrontPage() error {
|
|||
}
|
||||
defer frontFile.Close()
|
||||
|
||||
var recentPostsArr []gcsql.RecentPost
|
||||
var recentPostsArr []recentPost
|
||||
siteCfg := config.GetSiteConfig()
|
||||
recentPostsArr, err = gcsql.GetRecentPostsGlobal(siteCfg.MaxRecentPosts, !siteCfg.RecentPostsWithNoFile)
|
||||
recentPostsArr, err = getRecentPosts()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "recent").Send()
|
||||
return errors.New("Failed loading recent posts: " + err.Error())
|
||||
}
|
||||
|
||||
for b := range gcsql.AllBoards {
|
||||
if gcsql.AllBoards[b].Section == 0 {
|
||||
gcsql.AllBoards[b].Section = 1
|
||||
}
|
||||
}
|
||||
|
||||
if err = serverutil.MinifyTemplate(gctemplates.FrontPage, map[string]interface{}{
|
||||
"webroot": criticalCfg.WebRoot,
|
||||
"site_config": siteCfg,
|
||||
|
@ -79,18 +133,8 @@ func BuildBoardListJSON() error {
|
|||
"boards": {},
|
||||
}
|
||||
|
||||
boardCfg := config.GetBoardConfig("")
|
||||
// Our cooldowns are site-wide currently.
|
||||
cooldowns := gcsql.BoardCooldowns{
|
||||
NewThread: boardCfg.NewThreadDelay,
|
||||
Reply: boardCfg.ReplyDelay,
|
||||
ImageReply: boardCfg.ReplyDelay}
|
||||
|
||||
for b := range gcsql.AllBoards {
|
||||
gcsql.AllBoards[b].Cooldowns = cooldowns
|
||||
boardsMap["boards"] = append(boardsMap["boards"], gcsql.AllBoards[b])
|
||||
}
|
||||
|
||||
// TODO: properly check if the board is in a hidden section
|
||||
boardsMap["boards"] = gcsql.AllBoards
|
||||
boardJSON, err := json.Marshal(boardsMap)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).Str("building", "boards.json").Send()
|
||||
|
@ -166,28 +210,3 @@ func BuildJS() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// paginate returns a 2d array of a specified interface from a 1d array passed in,
|
||||
// with a specified number of values per array in the 2d array.
|
||||
// interfaceLength is the number of interfaces per array in the 2d array (e.g, threads per page)
|
||||
// interf is the array of interfaces to be split up.
|
||||
func paginate(interfaceLength int, interf []interface{}) [][]interface{} {
|
||||
// paginatedInterfaces = the finished interface array
|
||||
// numArrays = the current number of arrays (before remainder overflow)
|
||||
// interfacesRemaining = if greater than 0, these are the remaining interfaces
|
||||
// that will be added to the super-interface
|
||||
|
||||
var paginatedInterfaces [][]interface{}
|
||||
numArrays := len(interf) / interfaceLength
|
||||
interfacesRemaining := len(interf) % interfaceLength
|
||||
currentInterface := 0
|
||||
for l := 0; l < numArrays; l++ {
|
||||
paginatedInterfaces = append(paginatedInterfaces,
|
||||
interf[currentInterface:currentInterface+interfaceLength])
|
||||
currentInterface += interfaceLength
|
||||
}
|
||||
if interfacesRemaining > 0 {
|
||||
paginatedInterfaces = append(paginatedInterfaces, interf[len(interf)-interfacesRemaining:])
|
||||
}
|
||||
return paginatedInterfaces
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package building
|
||||
|
||||
import "github.com/gochan-org/gochan/pkg/gcsql"
|
||||
|
||||
type catalogThreadData struct {
|
||||
Replies int `json:"replies"`
|
||||
Images int `json:"images"`
|
||||
OmittedPosts int `json:"omitted_posts"`
|
||||
OmittedImages int `json:"omitted_images"`
|
||||
OmittedPosts int `json:"omitted_posts"` // posts in the thread but not shown on the board page
|
||||
OmittedImages int `json:"omitted_images"` // uploads in the thread but not shown on the board page
|
||||
Sticky int `json:"sticky"`
|
||||
Locked int `json:"locked"`
|
||||
numPages int
|
||||
// numPages int
|
||||
posts []gcsql.Post
|
||||
uploads []gcsql.Upload
|
||||
}
|
||||
|
||||
type catalogPage struct {
|
||||
|
@ -15,4 +19,51 @@ type catalogPage struct {
|
|||
Threads []catalogThreadData `json:"threads"`
|
||||
}
|
||||
|
||||
type boardCatalog []catalogPage
|
||||
type boardCatalog struct {
|
||||
pages []catalogPage // this array gets marshalled, not the boardCatalog object
|
||||
numPages int
|
||||
currentPage int
|
||||
}
|
||||
|
||||
// fillPages fills the catalog's pages array with pages of the specified size, with the remainder
|
||||
// on the last page
|
||||
func (catalog *boardCatalog) fillPages(threadsPerPage int, threads []catalogThreadData) {
|
||||
catalog.pages = []catalogPage{} // clear the array if it isn't already
|
||||
catalog.numPages = len(threads) / threadsPerPage
|
||||
remainder := len(threads) % threadsPerPage
|
||||
currentThreadIndex := 0
|
||||
var i int
|
||||
for i = 0; i < catalog.numPages; i++ {
|
||||
catalog.pages = append(catalog.pages,
|
||||
catalogPage{
|
||||
PageNum: i + 1,
|
||||
Threads: threads[currentThreadIndex : currentThreadIndex+threadsPerPage],
|
||||
},
|
||||
)
|
||||
currentThreadIndex += threadsPerPage
|
||||
}
|
||||
if remainder > 0 {
|
||||
catalog.pages = append(catalog.pages,
|
||||
catalogPage{
|
||||
PageNum: i + 1,
|
||||
Threads: threads[len(threads)-remainder:],
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// func paginateBoards(threadsPerPage int, threads []catalogThreadData) [][]catalogThreadData {
|
||||
// var paginatedThreads [][]catalogThreadData
|
||||
// numArrays := len(threads) / threadsPerPage
|
||||
// remainder := len(threads) % threadsPerPage
|
||||
// currentIndex := 0
|
||||
// for l := 0; l < numArrays; l++ {
|
||||
// paginatedThreads = append(paginatedThreads,
|
||||
// threads[currentIndex:currentIndex+threadsPerPage])
|
||||
// currentIndex += threadsPerPage
|
||||
// }
|
||||
// if remainder > 0 {
|
||||
// paginatedThreads = append(paginatedThreads, threads[len(threads)-remainder:])
|
||||
// }
|
||||
// return paginatedThreads
|
||||
// }
|
||||
|
|
|
@ -2,6 +2,7 @@ package building
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
@ -21,11 +22,11 @@ func BuildThreads(all bool, boardid, threadid int) error {
|
|||
var threads []gcsql.Post
|
||||
var err error
|
||||
if all {
|
||||
threads, err = gcsql.GetTopPostsNoSort(boardid)
|
||||
threads, err = gcsql.GetBoardTopPosts(boardid, true)
|
||||
} else {
|
||||
var post gcsql.Post
|
||||
post, err = gcsql.GetSpecificTopPost(threadid)
|
||||
threads = []gcsql.Post{post}
|
||||
var post *gcsql.Post
|
||||
post, err = gcsql.GetThreadTopPost(threadid)
|
||||
threads = []gcsql.Post{*post}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -40,26 +41,41 @@ func BuildThreads(all bool, boardid, threadid int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// BuildThreadPages builds the pages for a thread given by a Post object.
|
||||
// BuildThreadPages builds the pages for a thread given the top post. It fails if op is not the top post
|
||||
func BuildThreadPages(op *gcsql.Post) error {
|
||||
if !op.IsTopPost {
|
||||
return gcsql.ErrNotTopPost
|
||||
}
|
||||
err := gctemplates.InitTemplates("threadpage")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var replies []gcsql.Post
|
||||
var threadPageFile *os.File
|
||||
var board gcsql.Board
|
||||
if err = board.PopulateData(op.BoardID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
replies, err = gcsql.GetExistingReplies(op.ID)
|
||||
board, err := op.GetBoard()
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "thread").
|
||||
Int("threadid", op.ID).Send()
|
||||
return fmt.Errorf("failed building thread %d: %s", op.ID, err.Error())
|
||||
Int("postid", op.ID).
|
||||
Int("threadid", op.ThreadID).
|
||||
Msg("failed building thread")
|
||||
return errors.New("failed building thread: " + err.Error())
|
||||
}
|
||||
|
||||
thread, err := gcsql.GetThread(op.ThreadID)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "thread").
|
||||
Int("threadid", op.ThreadID).
|
||||
Msg("Unable to get thread info")
|
||||
return errors.New("unable to get thread info: " + err.Error())
|
||||
}
|
||||
posts, err := thread.GetPosts(false, false, 0)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "thread").
|
||||
Int("threadid", thread.ID).Send()
|
||||
return errors.New("failed building thread: " + err.Error())
|
||||
}
|
||||
criticalCfg := config.GetSystemCriticalConfig()
|
||||
os.Remove(path.Join(criticalCfg.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+".html"))
|
||||
|
@ -82,45 +98,45 @@ func BuildThreadPages(op *gcsql.Post) error {
|
|||
"board": board,
|
||||
"board_config": config.GetBoardConfig(board.Dir),
|
||||
"sections": gcsql.AllSections,
|
||||
"posts": replies,
|
||||
"posts": posts[1:],
|
||||
"op": op,
|
||||
}, threadPageFile, "text/html"); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("building", "thread").
|
||||
Str("boardDir", board.Dir).
|
||||
Int("threadid", op.ID).
|
||||
Int("threadid", thread.ID).
|
||||
Msg("Failed building threadpage")
|
||||
return fmt.Errorf("failed building /%s/res/%d threadpage: %s", board.Dir, op.ID, err.Error())
|
||||
return fmt.Errorf("failed building /%s/res/%d threadpage: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
|
||||
// Put together the thread JSON
|
||||
threadJSONFile, err := os.OpenFile(path.Join(criticalCfg.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+".json"), os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
threadJSONFile, err := os.OpenFile(
|
||||
path.Join(criticalCfg.DocumentRoot, board.Dir, "res", strconv.Itoa(posts[0].ID)+".json"),
|
||||
os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Int("threadid", op.ID).Send()
|
||||
return fmt.Errorf("failed opening /%s/res/%d.json: %s", board.Dir, op.ID, err.Error())
|
||||
Int("threadid", thread.ID).
|
||||
Int("op", posts[0].ID).Send()
|
||||
return fmt.Errorf("failed opening /%s/res/%d.json: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
defer threadJSONFile.Close()
|
||||
|
||||
threadMap := make(map[string][]gcsql.Post)
|
||||
|
||||
// Handle the OP, of type *Post
|
||||
threadMap["posts"] = []gcsql.Post{*op}
|
||||
|
||||
// Iterate through each reply, which are of type Post
|
||||
threadMap["posts"] = append(threadMap["posts"], replies...)
|
||||
threadMap["posts"] = posts
|
||||
threadJSON, err := json.Marshal(threadMap)
|
||||
if err != nil {
|
||||
gcutil.LogError(err).Send()
|
||||
return fmt.Errorf("failed to marshal to JSON: %s", err.Error())
|
||||
return errors.New("failed to marshal to JSON: " + err.Error())
|
||||
}
|
||||
if _, err = threadJSONFile.Write(threadJSON); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("boardDir", board.Dir).
|
||||
Int("threadid", op.ID).Send()
|
||||
Int("threadid", thread.ID).
|
||||
Int("op", posts[0].ID).Send()
|
||||
|
||||
return fmt.Errorf("failed writing /%s/res/%d.json: %s", board.Dir, op.ID, err.Error())
|
||||
return fmt.Errorf("failed writing /%s/res/%d.json: %s", board.Dir, posts[0].ID, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,38 +18,41 @@ func tempCleaner() {
|
|||
case <-tempCleanerTicker.C:
|
||||
for p := range gcsql.TempPosts {
|
||||
post := &gcsql.TempPosts[p]
|
||||
if !time.Now().After(post.Timestamp.Add(time.Minute * 5)) {
|
||||
if !time.Now().After(post.CreatedOn.Add(time.Minute * 5)) {
|
||||
continue
|
||||
}
|
||||
// temporary post is >= 5 minutes, time to prune it
|
||||
gcsql.TempPosts[p] = gcsql.TempPosts[len(gcsql.TempPosts)-1]
|
||||
gcsql.TempPosts = gcsql.TempPosts[:len(gcsql.TempPosts)-1]
|
||||
if post.FilenameOriginal == "" {
|
||||
upload, err := post.GetUpload()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var board gcsql.Board
|
||||
err := board.PopulateData(post.BoardID)
|
||||
if upload.OriginalFilename == "" {
|
||||
continue
|
||||
}
|
||||
board, err := post.GetBoard()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
systemCritical := config.GetSystemCriticalConfig()
|
||||
fileSrc := path.Join(systemCritical.DocumentRoot, board.Dir, "src", post.FilenameOriginal)
|
||||
fileSrc := path.Join(systemCritical.DocumentRoot, board.Dir, "src", upload.OriginalFilename)
|
||||
if err = os.Remove(fileSrc); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("subject", "tempUpload").
|
||||
Str("filePath", fileSrc).Send()
|
||||
}
|
||||
|
||||
thumbSrc := gcutil.GetThumbnailPath("thread", fileSrc)
|
||||
thumbSrc := upload.ThumbnailPath("thread")
|
||||
if err = os.Remove(thumbSrc); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("subject", "tempUpload").
|
||||
Str("filePath", thumbSrc).Send()
|
||||
}
|
||||
|
||||
if post.ParentID == 0 {
|
||||
catalogSrc := gcutil.GetThumbnailPath("catalog", fileSrc)
|
||||
if post.IsTopPost {
|
||||
catalogSrc := upload.ThumbnailPath("catalog")
|
||||
if err = os.Remove(catalogSrc); err != nil {
|
||||
gcutil.LogError(err).
|
||||
Str("subject", "tempUpload").
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue