1
0
Fork 0
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:
Eggbertx 2022-10-31 12:41:17 -07:00
parent be14983186
commit e789b08492
5 changed files with 272 additions and 201 deletions

View file

@ -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")

View file

@ -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
}

View file

@ -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
// }

View file

@ -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
}

View file

@ -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").