1
0
Fork 0
mirror of https://github.com/Eggbertx/gochan.git synced 2025-08-29 08:56:23 -07:00

Remove thread pagination, make logger write to requested log

This commit is contained in:
Eggbertx 2020-03-26 12:09:10 -07:00
parent 598d5ba99a
commit 5986d572bb
12 changed files with 128 additions and 118 deletions

View file

@ -25,7 +25,7 @@ $VERSION = Get-Content version
$RELEASE_NAME = "$BIN-v${VERSION}_$GCOS_NAME"
$RELEASE_DIR = "releases/${RELEASE_NAME}"
$LDFLAGS = "-X main.versionStr=${VERSION} -w -s"
$LDFLAGS = "-X main.versionStr=${VERSION} -s"
$DOCUMENT_ROOT_FILES = @"
banned.jpg
notbanned.png

View file

@ -296,7 +296,7 @@ func buildBoardPages(board *Board) (html string) {
// Create the archive pages.
threadPages = paginate(config.ThreadsPerPage, threads)
board.NumPages = len(threadPages) - 1
board.NumPages = len(threadPages)
// Create array of page wrapper objects, and open the file.
pagesArr := make([]map[string]interface{}, board.NumPages)
@ -361,7 +361,7 @@ func buildBoardPages(board *Board) (html string) {
return html + gclog.Print(lErrorLog, "Failed to marshal to JSON: ", err.Error()) + "<br />"
}
if _, err = catalogJSONFile.Write(catalogJSON); err != nil {
return html + gclog.Print(lErrorLog,
return html + gclog.Printf(lErrorLog,
"Failed writing /%s/catalog.json: %s", board.Dir, err.Error()) + "<br />"
}
html += "/" + board.Dir + "/ built successfully."
@ -470,14 +470,12 @@ func buildCatalog(which int) string {
for _, thread := range threadOPs {
threadInterfaces = append(threadInterfaces, thread)
}
threadPages := paginate(config.PostsPerThreadPage, threadInterfaces)
if err = minifyTemplate(catalogTmpl, map[string]interface{}{
"boards": allBoards,
"config": config,
"board": board,
"sections": allSections,
"threadPages": threadPages,
"boards": allBoards,
"config": config,
"board": board,
"sections": allSections,
}, catalogFile, "text/html"); err != nil {
return gclog.Printf(lErrorLog,
"Error building catalog for /%s/: %s", board.Dir, err.Error()) + "<br />"
@ -493,7 +491,7 @@ func buildThreadPages(op *Post) error {
}
var replies []Post
var currentPageFile *os.File
var threadPageFile *os.File
var board Board
if err = board.PopulateData(op.BoardID, ""); err != nil {
return err
@ -514,18 +512,13 @@ func buildThreadPages(op *Post) error {
repliesInterface = append(repliesInterface, reply)
}
threadPages := paginate(config.PostsPerThreadPage, repliesInterface)
deleteMatchingFiles(path.Join(config.DocumentRoot, board.Dir, "res"), "^"+strconv.Itoa(op.ID)+"p")
op.NumPages = len(threadPages)
currentPageFilepath := path.Join(config.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+".html")
currentPageFile, err = os.OpenFile(currentPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
threadPageFilepath := path.Join(config.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+".html")
threadPageFile, err = os.OpenFile(threadPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
if err != nil {
return fmt.Errorf("Failed opening /%s/res/%d.html: %s", board.Dir, op.ID, err.Error())
}
// render main page
// render thread page
if err = minifyTemplate(threadpageTmpl, map[string]interface{}{
"config": config,
"boards": allBoards,
@ -533,7 +526,7 @@ func buildThreadPages(op *Post) error {
"sections": allSections,
"posts": replies,
"op": op,
}, currentPageFile, "text/html"); err != nil {
}, threadPageFile, "text/html"); err != nil {
return fmt.Errorf("Failed building /%s/res/%d threadpage: %s", board.Dir, op.ID, err.Error())
}
@ -560,25 +553,6 @@ func buildThreadPages(op *Post) error {
return fmt.Errorf("Failed writing /%s/res/%d.json: %s", board.Dir, op.ID, err.Error())
}
for pageNum, pagePosts := range threadPages {
op.CurrentPage = pageNum + 1
currentPageFilepath := path.Join(config.DocumentRoot, board.Dir, "res", strconv.Itoa(op.ID)+"p"+strconv.Itoa(op.CurrentPage)+".html")
currentPageFile, err = os.OpenFile(currentPageFilepath, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0777)
if err != nil {
return fmt.Errorf("Failed opening /%s/res/%dp%d.html: %s", board.Dir, op.ID, op.CurrentPage, err.Error())
}
if err = minifyTemplate(threadpageTmpl, map[string]interface{}{
"config": config,
"boards": allBoards,
"board": board,
"sections": allSections,
"posts": pagePosts,
"op": op,
}, currentPageFile, "text/html"); err != nil {
return fmt.Errorf("Failed building /%s/%d: %s", board.Dir, op.ID, err.Error())
}
}
return nil
}

View file

@ -70,13 +70,13 @@ func parseCommandLine() {
flag.Usage()
os.Exit(1)
}
gclog.Print(lStdLog, "Are you sure you want to delete the staff account %q?[y/N]: ", delstaff)
gclog.Printf(lStdLog, "Are you sure you want to delete the staff account %q? [y/N]: ", delstaff)
var answer string
fmt.Scanln(&answer)
answer = strings.ToLower(answer)
if answer == "y" || answer == "yes" {
if err = deleteStaff(delstaff); err != nil {
gclog.Print(lStdLog|lFatal, "Error deleting %q: %s", delstaff, err.Error())
gclog.Printf(lStdLog|lFatal, "Error deleting %q: %s", delstaff, err.Error())
}
} else {
gclog.Print(lStdLog|lFatal, "Not deleting.")

View file

@ -1,6 +1,7 @@
package main
import (
"errors"
"fmt"
"io"
"os"
@ -32,10 +33,10 @@ func (gcl *GcLogger) selectLogs(flags int) []*os.File {
logs = append(logs, gcl.accessFile)
}
if flags&lErrorLog > 0 {
logs = append(logs, gcl.accessFile)
logs = append(logs, gcl.errorFile)
}
if flags&lStaffLog > 0 {
logs = append(logs, gcl.accessFile)
logs = append(logs, gcl.staffFile)
}
if flags&lStdLog > 0 {
logs = append(logs, os.Stdout)
@ -60,9 +61,9 @@ func (gcl *GcLogger) Print(flags int, v ...interface{}) string {
} else {
io.WriteString(l, gcl.getPrefix()+str+"\n")
}
if flags&lFatal > 0 {
os.Exit(1)
}
}
if flags&lFatal > 0 {
os.Exit(1)
}
return str
}
@ -76,9 +77,9 @@ func (gcl *GcLogger) Printf(flags int, format string, v ...interface{}) string {
} else {
io.WriteString(l, gcl.getPrefix()+str+"\n")
}
if flags&lFatal > 0 {
os.Exit(1)
}
}
if flags&lFatal > 0 {
os.Exit(1)
}
return str
}
@ -92,9 +93,9 @@ func (gcl *GcLogger) Println(flags int, v ...interface{}) string {
} else {
io.WriteString(l, gcl.getPrefix()+str+"\n")
}
if flags&lFatal > 0 {
defer os.Exit(1)
}
}
if flags&lFatal > 0 {
os.Exit(1)
}
return str
}
@ -105,20 +106,18 @@ func (gcl *GcLogger) Close() {
gcl.staffFile.Close()
}
func initLogs(accessLogPath, errorLogPath, staffLogPath string) *GcLogger {
func initLogs(accessLogPath, errorLogPath, staffLogPath string) (*GcLogger, error) {
var gcl GcLogger
var err error
if gcl.accessFile, err = os.OpenFile(accessLogPath, logFileFlags, 0777); err != nil {
fmt.Println("Error loading " + accessLogPath + ": " + err.Error())
os.Exit(1)
return nil, errors.New("Error loading " + accessLogPath + ": " + err.Error())
}
if gcl.errorFile, err = os.OpenFile(errorLogPath, logFileFlags, 0777); err != nil {
fmt.Println("Error loading " + errorLogPath + ": " + err.Error())
os.Exit(1)
return nil, errors.New("Error loading " + errorLogPath + ": " + err.Error())
}
if gcl.staffFile, err = os.OpenFile(staffLogPath, logFileFlags, 0777); err != nil {
fmt.Println("Error loading " + staffLogPath + ": " + err.Error())
os.Exit(1)
return nil, errors.New("Error loading " + staffLogPath + ": " + err.Error())
}
return &gcl
return &gcl, nil
}

18
src/logging_test.go Normal file
View file

@ -0,0 +1,18 @@
package main
import "testing"
func TestGochanLog(t *testing.T) {
gcl, err := initLogs("../access.log", "../error.log", "../staff.log")
if err != nil {
t.Fatal(err.Error())
}
gcl.Print(lStdLog, "os.Stdout log")
gcl.Print(lStdLog|lAccessLog|lErrorLog|lStaffLog, "all logs")
gcl.Print(lAccessLog, "Access log")
gcl.Print(lErrorLog, "Error log")
gcl.Print(lStaffLog, "Staff log")
gcl.Print(lAccessLog|lErrorLog, "Access and error log")
gcl.Print(lAccessLog|lStaffLog|lFatal, "Fatal access and staff log")
gcl.Print(lAccessLog, "This shouldn't be here")
}

View file

@ -335,13 +335,6 @@ var manageFunctions = map[string]ManageFunction{
config.ThumbHeight_catalog = ThumbHeight_catalog
}
PostsPerThreadPage, err := strconv.Atoi(request.PostFormValue("PostsPerThreadPage"))
if err != nil {
status += err.Error() + "<br />\n"
} else {
config.PostsPerThreadPage = PostsPerThreadPage
}
RepliesOnBoardPage, err := strconv.Atoi(request.PostFormValue("RepliesOnBoardPage"))
if err != nil {
status += err.Error() + "<br />\n"
@ -958,7 +951,7 @@ var manageFunctions = map[string]ManageFunction{
err.Error())
}
html += fmt.Sprintf(
`<tr><td><b>Post:</b> <a href="%s/res/%d.html#%d">%s/%d</a><br /><b>IP:</b> %s</td><td>%s</td><td>%s</td></tr>`,
`<tr><td><b>Post:</b> <a href="%s">%s/%d</a><br /><b>IP:</b> %s</td><td>%s</td><td>%s</td></tr>`,
path.Join(config.SiteWebfolder, recentpost.BoardName, "/res/", strconv.Itoa(recentpost.ParentID)+".html#"+strconv.Itoa(recentpost.PostID)),
recentpost.BoardName, recentpost.PostID, recentpost.IP, recentpost.Message,
recentpost.Timestamp.Format("01/02/06, 15:04"),
@ -1033,8 +1026,8 @@ var manageFunctions = map[string]ManageFunction{
rankI, _ := strconv.Atoi(rank)
if do == "add" {
if err := newStaff(username, password, rankI); err != nil {
serveErrorPage(writer, gclog.Print(lErrorLog,
"Error creating new staff account %q: ", username, err.Error()))
serveErrorPage(writer, gclog.Printf(lErrorLog,
"Error creating new staff account %q: %s", username, err.Error()))
return
}
} else if do == "del" && username != "" {

View file

@ -514,7 +514,7 @@ func makePost(writer http.ResponseWriter, request *http.Request) {
post.ThumbW, post.ThumbH = getThumbnailSize(post.ImageW, post.ImageH, "reply")
}
gclog.Print(lAccessLog, "Receiving post with image: %q from %s, referrer: %s",
gclog.Printf(lAccessLog, "Receiving post with image: %q from %s, referrer: %s",
handler.Filename, post.IP, request.Referer())
if request.FormValue("spoiler") == "on" {

View file

@ -166,6 +166,46 @@ func (board *Board) AbsolutePath(subpath ...string) string {
return path.Join(config.DocumentRoot, board.Dir, path.Join(subpath...))
}
// WebPath returns a string that represents the file's path as accessible by a browser
// fileType should be "boardPage", "threadPage", "upload", or "thumb"
func (board *Board) WebPath(fileName string, fileType string) string {
var filePath string
switch fileType {
case "":
fallthrough
case "boardPage":
filePath = path.Join(config.SiteWebfolder, board.Dir, fileName)
case "threadPage":
filePath = path.Join(config.SiteWebfolder, board.Dir, "res", fileName)
case "upload":
filePath = path.Join(config.SiteWebfolder, board.Dir, "src", fileName)
case "thumb":
filePath = path.Join(config.SiteWebfolder, board.Dir, "thumb", fileName)
}
return filePath
}
func (board *Board) PagePath(pageNum interface{}) string {
var page string
pageNumStr := fmt.Sprintf("%v", pageNum)
if pageNumStr == "prev" {
if board.CurrentPage < 2 {
page = "1"
} else {
page = strconv.Itoa(board.CurrentPage - 1)
}
} else if pageNumStr == "next" {
if board.CurrentPage >= board.NumPages {
page = strconv.Itoa(board.NumPages)
} else {
page = strconv.Itoa(board.CurrentPage + 1)
}
} else {
page = pageNumStr
}
return board.WebPath(page+".html", "boardPage")
}
// 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
@ -348,7 +388,6 @@ type Post struct {
ID int `json:"no"`
ParentID int `json:"resto"`
CurrentPage int `json:"-"`
NumPages int `json:"-"`
BoardID int `json:"-"`
Name string `json:"name"`
Tripcode string `json:"trip"`
@ -504,7 +543,6 @@ type GochanConfig struct {
ThumbHeight_catalog int `description:"Same as ThumbWidth and ThumbHeight but for catalog images." default:"50"`
ThreadsPerPage int `default:"15"`
PostsPerThreadPage int `description:"Max number of replies to a thread to show on each thread page." default:"50"`
RepliesOnBoardPage int `description:"Number of replies to a thread to show on the board page." default:"3"`
StickyRepliesOnBoardPage int `description:"Same as above for stickied threads." default:"1"`
BanColors []string `description:"Colors to be used for public ban messages (e.g. USER WAS BANNED FOR THIS POST).<br />Each entry should be on its own line, and should look something like this:<br />username1:#FF0000<br />username2:#FAF00F<br />username3:blue<br />Invalid entries/nonexistent usernames will show a warning and use the default red."`
@ -533,6 +571,7 @@ type GochanConfig struct {
EnableAppeals bool `description:"If checked, allow banned users to appeal their bans.<br />This will likely be removed (permanently allowing appeals) or made board-specific in the future." default:"checked"`
MaxLogDays int `description:"The maximum number of days to keep messages in the moderation/staff log file."`
RandomSeed string `critical:"true"`
TimeZone int `json:"-"`
}
func (cfg *GochanConfig) CheckString(val, defaultVal string, critical bool, msg string) string {
@ -568,7 +607,7 @@ func initConfig() {
jfile, err := ioutil.ReadFile(cfgPath)
if err != nil {
fmt.Println("Error reading %s: %s gochan.json: %s\n", cfgPath, err.Error())
fmt.Printf("Error reading %s: %s\n", cfgPath, err.Error())
os.Exit(1)
}
@ -578,11 +617,14 @@ func initConfig() {
}
config.LogDir = findResource(config.LogDir, "log", "/var/log/gochan/")
gclog = initLogs(
if gclog, err = initLogs(
path.Join(config.LogDir, "access.log"),
path.Join(config.LogDir, "error.log"),
path.Join(config.LogDir, "staff.log"),
)
); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
config.CheckString(config.ListenIP, "", true, "ListenIP not set in gochan.json, halting.")
@ -652,7 +694,6 @@ func initConfig() {
config.ThumbHeight_catalog = config.CheckInt(config.ThumbHeight_catalog, 50, false, "")
config.ThreadsPerPage = config.CheckInt(config.ThreadsPerPage, 10, false, "")
config.PostsPerThreadPage = config.CheckInt(config.PostsPerThreadPage, 4, false, "")
config.RepliesOnBoardPage = config.CheckInt(config.RepliesOnBoardPage, 3, false, "")
config.StickyRepliesOnBoardPage = config.CheckInt(config.StickyRepliesOnBoardPage, 1, false, "")
@ -689,6 +730,10 @@ func initConfig() {
gclog.Printf(lErrorLog|lStdLog|lFatal, "Unable to write %s with randomly generated seed: %s", cfgPath, err.Error())
}
}
_, zoneOffset := time.Now().Zone()
config.TimeZone = zoneOffset / 60 / 60
bbcompiler = bbcode.NewCompiler(true, true)
bbcompiler.SetTag("center", nil)
bbcompiler.SetTag("code", nil)

View file

@ -505,3 +505,8 @@ func parseDurationString(str string) (time.Duration, error) {
}
return time.ParseDuration(strconv.Itoa(expire) + "s")
}
func timezone() int {
_, offset := time.Now().Zone()
return offset / 60 / 60
}

View file

@ -59,26 +59,28 @@
<div id="left-bottom-content">
<table id="pages">
<tr>
<td>{{if gt .board.CurrentPage 2}}
<form method="GET" action="{{.config.SiteWebfolder}}{{.board.Dir}}/{{subtract .board.CurrentPage 1}}.html">
<input type="submit" value="Previous" />
</form>
{{else if intEq .board.CurrentPage 2}}
<form method="GET" action="{{.config.SiteWebfolder}}{{.board.Dir}}/board.html">
<input type="submit" value="Previous" />
</form>
{{else}}Previous{{end}}</td>
<td>{{range $_,$i := makeLoop .board.NumPages 1}} [{{if eq $i $.board.CurrentPage}}<b>{{end}}<a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/{{if intEq $i 1}}board{{else}}{{$i}}{{end}}.html">{{$i}}</a>{{if eq $i $.board.CurrentPage}}</b>{{end}}]{{end}}</td>
<td>{{if gt .board.CurrentPage 1}}
<form method="GET" action='{{.board.PagePath "prev"}}'>
<input type="submit" value="Previous" />
</form>
{{else}}Previous{{end}}</td>
<td>{{range $_,$i := makeLoop .board.NumPages 1}}
{{if eq $.board.CurrentPage $i}}
[<b>{{$i}}</b>]
{{else}}
[<a href="{{$.board.PagePath $i }}">{{$i}}</a>]
{{end}}
{{end}}</td>
<td>{{if lt .board.CurrentPage .board.NumPages}}
<form method="GET" action="{{.config.SiteWebfolder}}{{.board.Dir}}/{{add .board.CurrentPage 1}}.html">
<form method="GET" action="{{.board.PagePath `next` }}">
<input type="submit" value="Next" />
</form>
{{else}}Next{{end}}
</td>
{{else}}Next{{end}}</td>
</tr>
</table>
<span id="boardmenu-bottom">
[{{range $i, $boardlink := $.boards}}{{if gt $i 0}}/{{end}} <a href="{{$.config.SiteWebfolder}}{{$boardlink.Dir}}/">{{$boardlink.Dir}}</a> {{end}}]
[{{range $i, $boardlink := $.boards}}{{if gt $i 0}}/{{end}} <a href="{{$boardlink.WebPath `` `boardPage`}}/">{{$boardlink.Dir}}</a> {{end}}]
</span>
</div>
</div>

View file

@ -10,3 +10,4 @@ var styles = [
];
var defaultStyle = "{{.DefaultStyle}}";
var webroot = "{{.SiteWebfolder}}";
var serverTZ = {{.TimeZone}};

View file

@ -5,13 +5,6 @@
</header><hr />
<div id="threadlinks-top">
<a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/board.html" >Return</a><br />
<select id="changepage" onchange="changePage(this)">
<option value="">Select page...</option>
<option value="1">Page 1</option>
<option value="2">Page 2</option>
<option value="3">Page 3</option>
<option value="4">Page 4</option>
</select>
</div>
<div id="right-sidelinks">
<a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/catalog.html">Board catalog</a><br />
@ -60,27 +53,7 @@
</div>
</form>
<div id="left-bottom-content">
<table id="pages">
<tr>
<td><a href="{{.config.SiteWebfolder}}{{.board.Dir}}/">Return</a></td>
<td>{{- if gt .op.CurrentPage 1 -}}
<form method="GET" action="{{.config.SiteWebfolder}}{{.board.Dir}}/res/{{.op.ID}}p{{subtract .op.CurrentPage 1}}.html">
<input type="submit" value="Previous" />
</form>
{{- else}}Previous{{end -}}
</td>
<td>[<a href="{{.config.SiteWebfolder}}{{.board.Dir}}/res/{{.op.ID}}.html">All</a>]
{{- range $i,$_ := makeLoop .op.NumPages 0 -}}
[{{if eq $i (subtract $.op.CurrentPage 1)}}<b>{{end}}
<a href="{{$.config.SiteWebfolder}}{{$.board.Dir}}/res/{{$.op.ID}}p{{add $i 1}}.html">{{add $i 1}}</a>
{{if eq $i (subtract $.op.CurrentPage 1)}}</b>{{end}}]
{{end}}</td>
<td>{{if lt .op.CurrentPage .op.NumPages}}
<form method="GET" action="{{.config.SiteWebfolder}}{{.board.Dir}}/res/{{.op.ID}}p{{add .op.CurrentPage 1}}.html">
<input type="submit" value="Next" />
</form>
{{else}}Next{{end}}</td></tr>
</table>
<a href="{{.config.SiteWebfolder}}{{.board.Dir}}/">Return</a><br /><br />
<span id="boardmenu-bottom">
[{{range $i, $boardlink := .boards -}}
{{if gt $i 0}}/{{end -}} <a href="/{{$boardlink.Dir}}/">{{$boardlink.Dir}}</a>