Moved the phrase logic to the phrases package.

Removed some initialisation boilerplate from the test code.
De-duplicated some of the common portions of the benchmarks.
Added miscinit to reduce the amount of initialisation boilerplate in the tests and to better catch initialisation errors.
Added a profile benchmark.
This commit is contained in:
Azareal 2018-11-01 16:43:56 +10:00
parent f5a0e3386b
commit 76cfcb509b
28 changed files with 296 additions and 384 deletions

View File

@ -13,6 +13,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/Gosora/common/phrases"
) )
type AlertStmts struct { type AlertStmts struct {
@ -54,7 +55,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
actor, err := Users.Get(actorID) actor, err := Users.Get(actorID)
if err != nil { if err != nil {
return "", errors.New(GetErrorPhrase("alerts_no_actor")) return "", errors.New(phrases.GetErrorPhrase("alerts_no_actor"))
} }
/*if elementType != "forum" { /*if elementType != "forum" {
@ -66,7 +67,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
}*/ }*/
if event == "friend_invite" { if event == "friend_invite" {
return buildAlertString(GetTmplPhrase("alerts.new_friend_invite"), []string{actor.Name}, actor.Link, actor.Avatar, asid), nil return buildAlertString(phrases.GetTmplPhrase("alerts.new_friend_invite"), []string{actor.Name}, actor.Link, actor.Avatar, asid), nil
} }
// Not that many events for us to handle in a forum // Not that many events for us to handle in a forum
@ -75,13 +76,13 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
topic, err := Topics.Get(elementID) topic, err := Topics.Get(elementID)
if err != nil { if err != nil {
DebugLogf("Unable to find linked topic %d", elementID) DebugLogf("Unable to find linked topic %d", elementID)
return "", errors.New(GetErrorPhrase("alerts_no_linked_topic")) return "", errors.New(phrases.GetErrorPhrase("alerts_no_linked_topic"))
} }
// Store the forum ID in the targetUser column instead of making a new one? o.O // Store the forum ID in the targetUser column instead of making a new one? o.O
// Add an additional column for extra information later on when we add the ability to link directly to posts. We don't need the forum data for now... // Add an additional column for extra information later on when we add the ability to link directly to posts. We don't need the forum data for now...
return buildAlertString(GetTmplPhrase("alerts.forum_new_topic"), []string{actor.Name, topic.Title}, topic.Link, actor.Avatar, asid), nil return buildAlertString(phrases.GetTmplPhrase("alerts.forum_new_topic"), []string{actor.Name, topic.Title}, topic.Link, actor.Avatar, asid), nil
} }
return buildAlertString(GetTmplPhrase("alerts.forum_unknown_action"), []string{actor.Name}, "", actor.Avatar, asid), nil return buildAlertString(phrases.GetTmplPhrase("alerts.forum_unknown_action"), []string{actor.Name}, "", actor.Avatar, asid), nil
} }
var url, area string var url, area string
@ -91,7 +92,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
topic, err := Topics.Get(elementID) topic, err := Topics.Get(elementID)
if err != nil { if err != nil {
DebugLogf("Unable to find linked topic %d", elementID) DebugLogf("Unable to find linked topic %d", elementID)
return "", errors.New(GetErrorPhrase("alerts_no_linked_topic")) return "", errors.New(phrases.GetErrorPhrase("alerts_no_linked_topic"))
} }
url = topic.Link url = topic.Link
area = topic.Title area = topic.Title
@ -102,7 +103,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
targetUser, err = Users.Get(elementID) targetUser, err = Users.Get(elementID)
if err != nil { if err != nil {
DebugLogf("Unable to find target user %d", elementID) DebugLogf("Unable to find target user %d", elementID)
return "", errors.New(GetErrorPhrase("alerts_no_target_user")) return "", errors.New(phrases.GetErrorPhrase("alerts_no_target_user"))
} }
area = targetUser.Name area = targetUser.Name
url = targetUser.Link url = targetUser.Link
@ -112,7 +113,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
case "post": case "post":
topic, err := TopicByReplyID(elementID) topic, err := TopicByReplyID(elementID)
if err != nil { if err != nil {
return "", errors.New(GetErrorPhrase("alerts_no_linked_topic_by_reply")) return "", errors.New(phrases.GetErrorPhrase("alerts_no_linked_topic_by_reply"))
} }
url = topic.Link url = topic.Link
area = topic.Title area = topic.Title
@ -120,7 +121,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
phraseName += "_own" phraseName += "_own"
} }
default: default:
return "", errors.New(GetErrorPhrase("alerts_invalid_elementtype")) return "", errors.New(phrases.GetErrorPhrase("alerts_invalid_elementtype"))
} }
switch event { switch event {
@ -132,7 +133,7 @@ func BuildAlert(asid int, event string, elementType string, actorID int, targetU
phraseName += "_reply" phraseName += "_reply"
} }
return buildAlertString(GetTmplPhrase(phraseName), []string{actor.Name, area}, url, actor.Avatar, asid), nil return buildAlertString(phrases.GetTmplPhrase(phraseName), []string{actor.Name, area}, url, actor.Avatar, asid), nil
} }
func buildAlertString(msg string, sub []string, path string, avatar string, asid int) string { func buildAlertString(msg string, sub []string, path string, avatar string, asid int) string {

View File

@ -6,6 +6,8 @@ import (
"runtime/debug" "runtime/debug"
"strings" "strings"
"sync" "sync"
"github.com/Azareal/Gosora/common/phrases"
) )
type ErrorItem struct { type ErrorItem struct {
@ -101,7 +103,7 @@ func errorHeader(w http.ResponseWriter, user User, title string) *Header {
// ? - Add a user parameter? // ? - Add a user parameter?
func InternalError(err error, w http.ResponseWriter, r *http.Request) RouteError { func InternalError(err error, w http.ResponseWriter, r *http.Request) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
pi := ErrorPage{errorHeader(w, GuestUser, GetErrorPhrase("internal_error_title")), GetErrorPhrase("internal_error_body")} pi := ErrorPage{errorHeader(w, GuestUser, phrases.GetErrorPhrase("internal_error_title")), phrases.GetErrorPhrase("internal_error_body")}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
LogError(err) LogError(err)
return HandledRouteError() return HandledRouteError()
@ -120,7 +122,7 @@ func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, isJs bo
// ? - Add a user parameter? // ? - Add a user parameter?
func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteError { func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
writeJsonError(GetErrorPhrase("internal_error_body"), w) writeJsonError(phrases.GetErrorPhrase("internal_error_body"), w)
LogError(err) LogError(err)
return HandledRouteError() return HandledRouteError()
} }
@ -128,7 +130,7 @@ func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) RouteErr
// When the task system detects if the database is down, some database errors might lip by this // When the task system detects if the database is down, some database errors might lip by this
func DatabaseError(w http.ResponseWriter, r *http.Request) RouteError { func DatabaseError(w http.ResponseWriter, r *http.Request) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
pi := ErrorPage{errorHeader(w, GuestUser, GetErrorPhrase("internal_error_title")), GetErrorPhrase("internal_error_body")} pi := ErrorPage{errorHeader(w, GuestUser, phrases.GetErrorPhrase("internal_error_title")), phrases.GetErrorPhrase("internal_error_body")}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -137,7 +139,7 @@ func InternalErrorXML(err error, w http.ResponseWriter, r *http.Request) RouteEr
w.Header().Set("Content-Type", "application/xml") w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?> w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<error>` + GetErrorPhrase("internal_error_body") + `</error>`)) <error>` + phrases.GetErrorPhrase("internal_error_body") + `</error>`))
LogError(err) LogError(err)
return HandledRouteError() return HandledRouteError()
} }
@ -147,14 +149,14 @@ func SilentInternalErrorXML(err error, w http.ResponseWriter, r *http.Request) R
w.Header().Set("Content-Type", "application/xml") w.Header().Set("Content-Type", "application/xml")
w.WriteHeader(500) w.WriteHeader(500)
w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?> w.Write([]byte(`<?xml version="1.0" encoding="UTF-8"?>
<error>` + GetErrorPhrase("internal_error_body") + `</error>`)) <error>` + phrases.GetErrorPhrase("internal_error_body") + `</error>`))
log.Print("InternalError: ", err) log.Print("InternalError: ", err)
return HandledRouteError() return HandledRouteError()
} }
func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError { func PreError(errmsg string, w http.ResponseWriter, r *http.Request) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
pi := ErrorPage{errorHeader(w, GuestUser, GetErrorPhrase("error_title")), errmsg} pi := ErrorPage{errorHeader(w, GuestUser, phrases.GetErrorPhrase("error_title")), errmsg}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -176,7 +178,7 @@ func PreErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, isJs boo
// TODO: Pass header in for this and similar errors instead of having to pass in both user and w? Would also allow for more stateful things, although this could be a problem // TODO: Pass header in for this and similar errors instead of having to pass in both user and w? Would also allow for more stateful things, although this could be a problem
func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) RouteError { func LocalError(errmsg string, w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(500) w.WriteHeader(500)
pi := ErrorPage{errorHeader(w, user, GetErrorPhrase("local_error_title")), errmsg} pi := ErrorPage{errorHeader(w, user, phrases.GetErrorPhrase("local_error_title")), errmsg}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -198,7 +200,7 @@ func LocalErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) RouteEr
// NoPermissions is an error shown to the end-user when they try to access an area which they aren't authorised to access // NoPermissions is an error shown to the end-user when they try to access an area which they aren't authorised to access
func NoPermissions(w http.ResponseWriter, r *http.Request, user User) RouteError { func NoPermissions(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(403) w.WriteHeader(403)
pi := ErrorPage{errorHeader(w, user, GetErrorPhrase("no_permissions_title")), GetErrorPhrase("no_permissions_body")} pi := ErrorPage{errorHeader(w, user, phrases.GetErrorPhrase("no_permissions_title")), phrases.GetErrorPhrase("no_permissions_body")}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -212,14 +214,14 @@ func NoPermissionsJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bo
func NoPermissionsJS(w http.ResponseWriter, r *http.Request, user User) RouteError { func NoPermissionsJS(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(403) w.WriteHeader(403)
writeJsonError(GetErrorPhrase("no_permissions_body"), w) writeJsonError(phrases.GetErrorPhrase("no_permissions_body"), w)
return HandledRouteError() return HandledRouteError()
} }
// ? - Is this actually used? Should it be used? A ban in Gosora should be more of a permission revocation to stop them posting rather than something which spits up an error page, right? // ? - Is this actually used? Should it be used? A ban in Gosora should be more of a permission revocation to stop them posting rather than something which spits up an error page, right?
func Banned(w http.ResponseWriter, r *http.Request, user User) RouteError { func Banned(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(403) w.WriteHeader(403)
pi := ErrorPage{errorHeader(w, user, GetErrorPhrase("banned_title")), GetErrorPhrase("banned_body")} pi := ErrorPage{errorHeader(w, user, phrases.GetErrorPhrase("banned_title")), phrases.GetErrorPhrase("banned_body")}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -235,7 +237,7 @@ func BannedJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bool) Rou
func BannedJS(w http.ResponseWriter, r *http.Request, user User) RouteError { func BannedJS(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(403) w.WriteHeader(403)
writeJsonError(GetErrorPhrase("banned_body"), w) writeJsonError(phrases.GetErrorPhrase("banned_body"), w)
return HandledRouteError() return HandledRouteError()
} }
@ -251,7 +253,7 @@ func LoginRequiredJSQ(w http.ResponseWriter, r *http.Request, user User, isJs bo
// LoginRequired is an error shown to the end-user when they try to access an area which requires them to login // LoginRequired is an error shown to the end-user when they try to access an area which requires them to login
func LoginRequired(w http.ResponseWriter, r *http.Request, user User) RouteError { func LoginRequired(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(401) w.WriteHeader(401)
pi := ErrorPage{errorHeader(w, user, GetErrorPhrase("no_permissions_title")), GetErrorPhrase("login_required_body")} pi := ErrorPage{errorHeader(w, user, phrases.GetErrorPhrase("no_permissions_title")), phrases.GetErrorPhrase("login_required_body")}
handleErrorTemplate(w, r, pi) handleErrorTemplate(w, r, pi)
return HandledRouteError() return HandledRouteError()
} }
@ -259,7 +261,7 @@ func LoginRequired(w http.ResponseWriter, r *http.Request, user User) RouteError
// nolint // nolint
func LoginRequiredJS(w http.ResponseWriter, r *http.Request, user User) RouteError { func LoginRequiredJS(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(401) w.WriteHeader(401)
writeJsonError(GetErrorPhrase("login_required_body"), w) writeJsonError(phrases.GetErrorPhrase("login_required_body"), w)
return HandledRouteError() return HandledRouteError()
} }
@ -267,7 +269,7 @@ func LoginRequiredJS(w http.ResponseWriter, r *http.Request, user User) RouteErr
// ? - Should we add JS and JSQ versions of this? // ? - Should we add JS and JSQ versions of this?
func SecurityError(w http.ResponseWriter, r *http.Request, user User) RouteError { func SecurityError(w http.ResponseWriter, r *http.Request, user User) RouteError {
w.WriteHeader(403) w.WriteHeader(403)
pi := ErrorPage{errorHeader(w, user, GetErrorPhrase("security_error_title")), GetErrorPhrase("security_error_body")} pi := ErrorPage{errorHeader(w, user, phrases.GetErrorPhrase("security_error_title")), phrases.GetErrorPhrase("security_error_body")}
if RunPreRenderHook("pre_render_security_error", w, r, &user, &pi) { if RunPreRenderHook("pre_render_security_error", w, r, &user, &pi) {
return nil return nil
} }
@ -282,7 +284,7 @@ func SecurityError(w http.ResponseWriter, r *http.Request, user User) RouteError
// ? - Add a JSQ and JS version of this? // ? - Add a JSQ and JS version of this?
// ? - Add a user parameter? // ? - Add a user parameter?
func NotFound(w http.ResponseWriter, r *http.Request, header *Header) RouteError { func NotFound(w http.ResponseWriter, r *http.Request, header *Header) RouteError {
return CustomError(GetErrorPhrase("not_found_body"), 404, GetErrorPhrase("not_found_title"), w, r, header, GuestUser) return CustomError(phrases.GetErrorPhrase("not_found_body"), 404, phrases.GetErrorPhrase("not_found_title"), w, r, header, GuestUser)
} }
// CustomError lets us make custom error types which aren't covered by the generic functions above // CustomError lets us make custom error types which aren't covered by the generic functions above

View File

@ -10,6 +10,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/Gosora/common/phrases"
) )
type MenuItemList []MenuItem type MenuItemList []MenuItem
@ -346,7 +347,7 @@ func (hold *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuIt
} }
if bytes.Equal(variable[:dotAt], []byte("lang")) { if bytes.Equal(variable[:dotAt], []byte("lang")) {
renderBuffer = append(renderBuffer, []byte(GetTmplPhrase(string(bytes.TrimPrefix(variable[dotAt:], []byte(".")))))) renderBuffer = append(renderBuffer, []byte(phrases.GetTmplPhrase(string(bytes.TrimPrefix(variable[dotAt:], []byte("."))))))
continue continue
} }
@ -385,7 +386,7 @@ func (hold *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuIt
if bytes.Equal(renderItem[1:dotAt], []byte("lang")) { if bytes.Equal(renderItem[1:dotAt], []byte("lang")) {
//fmt.Println("lang var: ", string(renderItem[dotAt+1:endFence])) //fmt.Println("lang var: ", string(renderItem[dotAt+1:endFence]))
renderBuffer = append(renderBuffer, []byte(GetTmplPhrase(string(renderItem[dotAt+1:endFence])))) renderBuffer = append(renderBuffer, []byte(phrases.GetTmplPhrase(string(renderItem[dotAt+1:endFence]))))
} else { } else {
fmt.Println("other var: ", string(variable[:dotAt])) fmt.Println("other var: ", string(variable[:dotAt]))
if len(renderItem) > 0 { if len(renderItem) > 0 {

View File

@ -6,6 +6,8 @@ import (
"runtime" "runtime"
"sync" "sync"
"time" "time"
"github.com/Azareal/Gosora/common/phrases"
) )
// TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs) // TODO: Allow resources in spots other than /static/ and possibly even external domains (e.g. CDNs)
@ -44,7 +46,7 @@ func (header *Header) AddSheet(name string) {
} }
func (header *Header) AddNotice(name string) { func (header *Header) AddNotice(name string) {
header.NoticeList = append(header.NoticeList, GetNoticePhrase(name)) header.NoticeList = append(header.NoticeList, phrases.GetNoticePhrase(name))
} }
// TODO: Add this to routes which don't use templates. E.g. Json APIs. // TODO: Add this to routes which don't use templates. E.g. Json APIs.

View File

@ -5,6 +5,7 @@ import (
"log" "log"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/Gosora/common/phrases"
) )
// TODO: Refactor the perms system // TODO: Refactor the perms system
@ -158,7 +159,7 @@ func StripInvalidPreset(preset string) string {
// TODO: Move this into the phrase system? // TODO: Move this into the phrase system?
func PresetToLang(preset string) string { func PresetToLang(preset string) string {
phrases := GetAllPermPresets() phrases := phrases.GetAllPermPresets()
phrase, ok := phrases[preset] phrase, ok := phrases[preset]
if !ok { if !ok {
phrase = phrases["unknown"] phrase = phrases["unknown"]

View File

@ -4,7 +4,7 @@
* Copyright Azareal 2017 - 2019 * Copyright Azareal 2017 - 2019
* *
*/ */
package common package phrases
import ( import (
"encoding/json" "encoding/json"
@ -61,7 +61,7 @@ type LanguagePack struct {
var langPacks sync.Map // nolint it is used var langPacks sync.Map // nolint it is used
var langTmplIndicesToNames [][]string // [tmplID][index]phraseName var langTmplIndicesToNames [][]string // [tmplID][index]phraseName
func InitPhrases() error { func InitPhrases(lang string) error {
log.Print("Loading the language packs") log.Print("Loading the language packs")
err := filepath.Walk("./langs", func(path string, f os.FileInfo, err error) error { err := filepath.Walk("./langs", func(path string, f os.FileInfo, err error) error {
if f.IsDir() { if f.IsDir() {
@ -122,9 +122,9 @@ func InitPhrases() error {
return errors.New("You don't have any language packs") return errors.New("You don't have any language packs")
} }
langPack, ok := langPacks.Load(Site.Language) langPack, ok := langPacks.Load(lang)
if !ok { if !ok {
return errors.New("Couldn't find the " + Site.Language + " language pack") return errors.New("Couldn't find the " + lang + " language pack")
} }
currentLangPack.Store(langPack) currentLangPack.Store(langPack)
return nil return nil
@ -154,14 +154,14 @@ func GetLevelPhrase(level int) string {
func GetGlobalPermPhrase(name string) string { func GetGlobalPermPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).GlobalPerms[name] res, ok := currentLangPack.Load().(*LanguagePack).GlobalPerms[name]
if !ok { if !ok {
return getPhrasePlaceholder("perms", name) return getPlaceholder("perms", name)
} }
return res return res
} }
func GetLocalPermPhrase(name string) string { func GetLocalPermPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).LocalPerms[name] res, ok := currentLangPack.Load().(*LanguagePack).LocalPerms[name]
if !ok { if !ok {
return getPhrasePlaceholder("perms", name) return getPlaceholder("perms", name)
} }
return res return res
} }
@ -169,7 +169,7 @@ func GetLocalPermPhrase(name string) string {
func GetSettingPhrase(name string) string { func GetSettingPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).SettingPhrases[name] res, ok := currentLangPack.Load().(*LanguagePack).SettingPhrases[name]
if !ok { if !ok {
return getPhrasePlaceholder("settings", name) return getPlaceholder("settings", name)
} }
return res return res
} }
@ -185,7 +185,7 @@ func GetAllPermPresets() map[string]string {
func GetAccountPhrase(name string) string { func GetAccountPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).Accounts[name] res, ok := currentLangPack.Load().(*LanguagePack).Accounts[name]
if !ok { if !ok {
return getPhrasePlaceholder("account", name) return getPlaceholder("account", name)
} }
return res return res
} }
@ -209,7 +209,7 @@ func GetOSPhrase(name string) (string, bool) {
func GetHumanLangPhrase(name string) (string, bool) { func GetHumanLangPhrase(name string) (string, bool) {
res, ok := currentLangPack.Load().(*LanguagePack).HumanLanguages[name] res, ok := currentLangPack.Load().(*LanguagePack).HumanLanguages[name]
if !ok { if !ok {
return getPhrasePlaceholder("humanlang", name), false return getPlaceholder("humanlang", name), false
} }
return res, true return res, true
} }
@ -218,7 +218,7 @@ func GetHumanLangPhrase(name string) (string, bool) {
func GetErrorPhrase(name string) string { func GetErrorPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).Errors[name] res, ok := currentLangPack.Load().(*LanguagePack).Errors[name]
if !ok { if !ok {
return getPhrasePlaceholder("error", name) return getPlaceholder("error", name)
} }
return res return res
} }
@ -226,7 +226,7 @@ func GetErrorPhrase(name string) string {
func GetNoticePhrase(name string) string { func GetNoticePhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).NoticePhrases[name] res, ok := currentLangPack.Load().(*LanguagePack).NoticePhrases[name]
if !ok { if !ok {
return getPhrasePlaceholder("notices", name) return getPlaceholder("notices", name)
} }
return res return res
} }
@ -234,7 +234,7 @@ func GetNoticePhrase(name string) string {
func GetTitlePhrase(name string) string { func GetTitlePhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name] res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name]
if !ok { if !ok {
return getPhrasePlaceholder("title", name) return getPlaceholder("title", name)
} }
return res return res
} }
@ -242,7 +242,7 @@ func GetTitlePhrase(name string) string {
func GetTitlePhrasef(name string, params ...interface{}) string { func GetTitlePhrasef(name string, params ...interface{}) string {
res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name] res, ok := currentLangPack.Load().(*LanguagePack).PageTitles[name]
if !ok { if !ok {
return getPhrasePlaceholder("title", name) return getPlaceholder("title", name)
} }
return fmt.Sprintf(res, params...) return fmt.Sprintf(res, params...)
} }
@ -250,7 +250,7 @@ func GetTitlePhrasef(name string, params ...interface{}) string {
func GetTmplPhrase(name string) string { func GetTmplPhrase(name string) string {
res, ok := currentLangPack.Load().(*LanguagePack).TmplPhrases[name] res, ok := currentLangPack.Load().(*LanguagePack).TmplPhrases[name]
if !ok { if !ok {
return getPhrasePlaceholder("tmpl", name) return getPlaceholder("tmpl", name)
} }
return res return res
} }
@ -258,7 +258,7 @@ func GetTmplPhrase(name string) string {
func GetTmplPhrasef(name string, params ...interface{}) string { func GetTmplPhrasef(name string, params ...interface{}) string {
res, ok := currentLangPack.Load().(*LanguagePack).TmplPhrases[name] res, ok := currentLangPack.Load().(*LanguagePack).TmplPhrases[name]
if !ok { if !ok {
return getPhrasePlaceholder("tmpl", name) return getPlaceholder("tmpl", name)
} }
return fmt.Sprintf(res, params...) return fmt.Sprintf(res, params...)
} }
@ -272,7 +272,7 @@ func GetTmplPhrasesByPrefix(prefix string) (phrases map[string]string, ok bool)
return res, ok return res, ok
} }
func getPhrasePlaceholder(prefix string, suffix string) string { func getPlaceholder(prefix string, suffix string) string {
return "{lang." + prefix + "[" + suffix + "]}" return "{lang." + prefix + "[" + suffix + "]}"
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/Azareal/Gosora/common/alerts" "github.com/Azareal/Gosora/common/alerts"
"github.com/Azareal/Gosora/common/templates" "github.com/Azareal/Gosora/common/templates"
"github.com/Azareal/Gosora/common/phrases"
) )
var Ctemplates []string var Ctemplates []string
@ -532,7 +533,7 @@ func InitTemplates() error {
panic("phraseNameInt is not a string") panic("phraseNameInt is not a string")
} }
// TODO: Log non-existent phrases? // TODO: Log non-existent phrases?
return template.HTML(GetTmplPhrase(phraseName)) return template.HTML(phrases.GetTmplPhrase(phraseName))
} }
fmap["level"] = func(levelInt interface{}) interface{} { fmap["level"] = func(levelInt interface{}) interface{} {
@ -540,7 +541,7 @@ func InitTemplates() error {
if !ok { if !ok {
panic("levelInt is not an integer") panic("levelInt is not an integer")
} }
return template.HTML(GetLevelPhrase(level)) return template.HTML(phrases.GetLevelPhrase(level))
} }
fmap["scope"] = func(name interface{}) interface{} { fmap["scope"] = func(name interface{}) interface{} {

View File

@ -14,6 +14,8 @@ import (
// TODO: Turn this file into a library // TODO: Turn this file into a library
var textOverlapList = make(map[string]int) var textOverlapList = make(map[string]int)
// TODO: Stop hard-coding this here
var langPkg = "github.com/Azareal/Gosora/common/phrases"
type VarItem struct { type VarItem struct {
Name string Name string
@ -177,6 +179,10 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
out += c.rootIterate(c.templateList[fname], varholder, holdreflect, fname) out += c.rootIterate(c.templateList[fname], varholder, holdreflect, fname)
c.TemplateFragmentCount[fname] = c.fragmentCursor[fname] + 1 c.TemplateFragmentCount[fname] = c.fragmentCursor[fname] + 1
if len(c.langIndexToName) > 0 {
c.importMap[langPkg] = langPkg
}
var importList string var importList string
for _, item := range c.importMap { for _, item := range c.importMap {
importList += "import \"" + item + "\"\n" importList += "import \"" + item + "\"\n"
@ -211,7 +217,7 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
fout += "\tcommon.TmplPtrMap[\"o_" + fname + "\"] = Template_" + fname + "\n" fout += "\tcommon.TmplPtrMap[\"o_" + fname + "\"] = Template_" + fname + "\n"
} }
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {
fout += "\t" + fname + "_tmpl_phrase_id = common.RegisterTmplPhraseNames([]string{\n" fout += "\t" + fname + "_tmpl_phrase_id = phrases.RegisterTmplPhraseNames([]string{\n"
for _, name := range c.langIndexToName { for _, name := range c.langIndexToName {
fout += "\t\t" + `"` + name + `"` + ",\n" fout += "\t\t" + `"` + name + `"` + ",\n"
} }
@ -222,7 +228,7 @@ func (c *CTemplateSet) Compile(name string, fileDir string, expects string, expe
fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w io.Writer) error {\n" fout += "// nolint\nfunc Template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w io.Writer) error {\n"
if len(c.langIndexToName) > 0 { if len(c.langIndexToName) > 0 {
fout += "var phrases = common.GetTmplPhrasesBytes(" + fname + "_tmpl_phrase_id)\n" fout += "var plist = phrases.GetTmplPhrasesBytes(" + fname + "_tmpl_phrase_id)\n"
} }
fout += varString + out + "return nil\n}\n" fout += varString + out + "return nil\n}\n"
@ -714,7 +720,7 @@ ArgLoop:
} }
c.langIndexToName = append(c.langIndexToName, leftParam) c.langIndexToName = append(c.langIndexToName, leftParam)
out = "w.Write(phrases[" + strconv.Itoa(len(c.langIndexToName)-1) + "])\n" out = "w.Write(plist[" + strconv.Itoa(len(c.langIndexToName)-1) + "])\n"
literal = true literal = true
break ArgLoop break ArgLoop
case "level": case "level":
@ -727,8 +733,9 @@ ArgLoop:
leftParam, _ = c.compileIfVarsub(leftOperand, varholder, templateName, holdreflect) leftParam, _ = c.compileIfVarsub(leftOperand, varholder, templateName, holdreflect)
// TODO: Refactor this // TODO: Refactor this
out = "w.Write([]byte(common.GetLevelPhrase(" + leftParam + ")))\n" out = "w.Write([]byte(phrases.GetLevelPhrase(" + leftParam + ")))\n"
literal = true literal = true
c.importMap[langPkg] = langPkg
break ArgLoop break ArgLoop
case "scope": case "scope":
literal = true literal = true

View File

@ -14,6 +14,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"text/template" "text/template"
"github.com/Azareal/Gosora/common/phrases"
) )
var ErrNoDefaultTheme = errors.New("The default theme isn't registered in the system") var ErrNoDefaultTheme = errors.New("The default theme isn't registered in the system")
@ -82,7 +84,7 @@ func (theme *Theme) LoadStaticFiles() error {
} }
func (theme *Theme) AddThemeStaticFiles() error { func (theme *Theme) AddThemeStaticFiles() error {
phraseMap := GetTmplPhrases() phraseMap := phrases.GetTmplPhrases()
// TODO: Use a function instead of a closure to make this more testable? What about a function call inside the closure to take the theme variable into account? // TODO: Use a function instead of a closure to make this more testable? What about a function call inside the closure to take the theme variable into account?
return filepath.Walk("./themes/"+theme.Name+"/public", func(path string, f os.FileInfo, err error) error { return filepath.Walk("./themes/"+theme.Name+"/public", func(path string, f os.FileInfo, err error) error {
DebugLog("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'") DebugLog("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'")

View File

@ -21,6 +21,7 @@ import (
"github.com/Azareal/gopsutil/cpu" "github.com/Azareal/gopsutil/cpu"
"github.com/Azareal/gopsutil/mem" "github.com/Azareal/gopsutil/mem"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/Azareal/Gosora/common/phrases"
) )
// TODO: Disable WebSockets on high load? Add a Control Panel interface for disabling it? // TODO: Disable WebSockets on high load? Add a Control Panel interface for disabling it?
@ -288,9 +289,9 @@ AdminStatLoop:
// nolint // nolint
// TODO: Use JSON for this to make things more portable and easier to convert to MessagePack, if need be? // TODO: Use JSON for this to make things more portable and easier to convert to MessagePack, if need be?
if !noStatUpdates { if !noStatUpdates {
w.Write([]byte("set #dash-totonline <span>" + GetTmplPhrasef("panel_dashboard_online", totonline, totunit) + "</span>\r")) w.Write([]byte("set #dash-totonline <span>" + phrases.GetTmplPhrasef("panel_dashboard_online", totonline, totunit) + "</span>\r"))
w.Write([]byte("set #dash-gonline <span>" + GetTmplPhrasef("panel_dashboard_guests_online", gonline, gunit) + "</span>\r")) w.Write([]byte("set #dash-gonline <span>" + phrases.GetTmplPhrasef("panel_dashboard_guests_online", gonline, gunit) + "</span>\r"))
w.Write([]byte("set #dash-uonline <span>" + GetTmplPhrasef("panel_dashboard_users_online", uonline, uunit) + "</span>\r")) w.Write([]byte("set #dash-uonline <span>" + phrases.GetTmplPhrasef("panel_dashboard_users_online", uonline, uunit) + "</span>\r"))
w.Write([]byte("set #dash-reqs <span>" + strconv.Itoa(reqCount) + " reqs / second</span>\r")) w.Write([]byte("set #dash-reqs <span>" + strconv.Itoa(reqCount) + " reqs / second</span>\r"))
w.Write([]byte("set-class #dash-totonline grid_item grid_stat " + onlineColour + "\r")) w.Write([]byte("set-class #dash-totonline grid_item grid_stat " + onlineColour + "\r"))

View File

@ -17,7 +17,6 @@ import (
"github.com/Azareal/Gosora/install" "github.com/Azareal/Gosora/install"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/Gosora/routes" "github.com/Azareal/Gosora/routes"
//"github.com/husobee/vestigo"
) )
//var dbTest *sql.DB //var dbTest *sql.DB
@ -111,12 +110,7 @@ func init() {
// TODO: Swap out LocalError for a panic for this? // TODO: Swap out LocalError for a panic for this?
func BenchmarkTopicAdminRouteParallel(b *testing.B) { func BenchmarkTopicAdminRouteParallel(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit()
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -158,13 +152,8 @@ func BenchmarkTopicAdminRouteParallel(b *testing.B) {
} }
func BenchmarkTopicAdminRouteParallelWithRouter(b *testing.B) { func BenchmarkTopicAdminRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit() router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -218,12 +207,7 @@ func BenchmarkTopicAdminRouteParallelAltAlt(b *testing.B) {
} }
func BenchmarkTopicGuestRouteParallel(b *testing.B) { func BenchmarkTopicGuestRouteParallel(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit()
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
@ -247,12 +231,7 @@ func BenchmarkTopicGuestRouteParallel(b *testing.B) {
} }
func BenchmarkTopicGuestRouteParallelDebugMode(b *testing.B) { func BenchmarkTopicGuestRouteParallelDebugMode(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit()
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = true common.Dev.DebugMode = true
@ -276,13 +255,8 @@ func BenchmarkTopicGuestRouteParallelDebugMode(b *testing.B) {
} }
func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit() router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -319,13 +293,8 @@ func BenchmarkTopicGuestRouteParallelWithRouter(b *testing.B) {
} }
func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() binit(b)
err := gloinit() router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
@ -349,96 +318,60 @@ func BenchmarkBadRouteGuestRouteParallelWithRouter(b *testing.B) {
common.Dev.SuperDebug = prev2 common.Dev.SuperDebug = prev2
} }
func BenchmarkTopicsGuestRouteParallelWithRouter(b *testing.B) { func obRoute(b *testing.B,path string) {
b.ReportAllocs() binit(b)
err := gloinit() cfg := NewStashConfig()
if err != nil {
b.Fatal(err)
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false common.Dev.DebugMode = false
common.Dev.SuperDebug = false common.Dev.SuperDebug = false
b.RunParallel(benchRoute(b,path))
cfg.Restore()
}
b.RunParallel(func(pb *testing.PB) { func BenchmarkTopicsGuestRouteParallelWithRouter(b *testing.B) {
for pb.Next() { obRoute(b,"/topics/")
listW := httptest.NewRecorder()
listReq := httptest.NewRequest("GET", "/topics/", bytes.NewReader(nil))
listReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
listReq.Header.Set("Host", "localhost")
listReq.Host = "localhost"
router.ServeHTTP(listW, listReq)
if listW.Code != 200 {
b.Log(listW.Body)
b.Fatal("HTTP Error!")
}
}
})
common.Dev.DebugMode = prev
common.Dev.SuperDebug = prev2
} }
func BenchmarkForumsGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkForumsGuestRouteParallelWithRouter(b *testing.B) {
b.ReportAllocs() obRoute(b,"/forums/")
err := gloinit()
if err != nil {
b.Fatal(err)
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil {
b.Fatal(err)
}
prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false
common.Dev.SuperDebug = false
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
listW := httptest.NewRecorder()
listReq := httptest.NewRequest("GET", "/forums/", bytes.NewReader(nil))
listReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
listReq.Header.Set("Host", "localhost")
listReq.Host = "localhost"
router.ServeHTTP(listW, listReq)
if listW.Code != 200 {
b.Log(listW.Body)
b.Fatal("HTTP Error!")
}
}
})
common.Dev.DebugMode = prev
common.Dev.SuperDebug = prev2
} }
func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) { func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) {
obRoute(b,"/forum/general.2")
}
func binit(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
err := gloinit() err := gloinit()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
}
router, err = NewGenRouter(http.FileServer(http.Dir("./uploads"))) type StashConfig struct {
prev bool
prev2 bool
}
func NewStashConfig() *StashConfig {
prev := common.Dev.DebugMode
prev2 := common.Dev.SuperDebug
return &StashConfig{prev,prev2}
}
func (cfg *StashConfig) Restore() {
common.Dev.DebugMode = cfg.prev
common.Dev.SuperDebug = cfg.prev2
}
func benchRoute(b *testing.B, path string) func(*testing.PB) {
router, err := NewGenRouter(http.FileServer(http.Dir("./uploads")))
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
} }
prev := common.Dev.DebugMode return func(pb *testing.PB) {
prev2 := common.Dev.SuperDebug
common.Dev.DebugMode = false
common.Dev.SuperDebug = false
b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
listW := httptest.NewRecorder() listW := httptest.NewRecorder()
listReq := httptest.NewRequest("GET", "/forum/general.2", bytes.NewReader(nil)) listReq := httptest.NewRequest("GET", path, bytes.NewReader(nil))
listReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36") listReq.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36")
listReq.Header.Set("Host", "localhost") listReq.Header.Set("Host", "localhost")
listReq.Host = "localhost" listReq.Host = "localhost"
@ -448,10 +381,11 @@ func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) {
b.Fatal("HTTP Error!") b.Fatal("HTTP Error!")
} }
} }
}) }
}
common.Dev.DebugMode = prev func BenchmarkProfileGuestRouteParallelWithRouter(b *testing.B) {
common.Dev.SuperDebug = prev2 obRoute(b,"/profile/admin.1")
} }
// TODO: Make these routes compatible with the changes to the router // TODO: Make these routes compatible with the changes to the router
@ -459,7 +393,6 @@ func BenchmarkForumGuestRouteParallelWithRouter(b *testing.B) {
func BenchmarkForumsAdminRouteParallel(b *testing.B) { func BenchmarkForumsAdminRouteParallel(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
gloinit() gloinit()
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
admin, err := users.Get(1) admin, err := users.Get(1)
if err != nil { if err != nil {
@ -473,9 +406,9 @@ func BenchmarkForumsAdminRouteParallel(b *testing.B) {
forumsW := httptest.NewRecorder() forumsW := httptest.NewRecorder()
forumsReq := httptest.NewRequest("get","/forums/",bytes.NewReader(nil)) forumsReq := httptest.NewRequest("get","/forums/",bytes.NewReader(nil))
forumsReq_admin := forums_req forumsReqAdmin := forums_req
forumsReq_admin.AddCookie(&adminUidCookie) forumsReqAdmin.AddCookie(&adminUidCookie)
forumsReq_admin.AddCookie(&adminSessionCookie) forumsReqAdmin.AddCookie(&adminSessionCookie)
forumsHandler := http.HandlerFunc(route_forums) forumsHandler := http.HandlerFunc(route_forums)
for pb.Next() { for pb.Next() {

13
main.go
View File

@ -23,6 +23,7 @@ import (
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/counters" "github.com/Azareal/Gosora/common/counters"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/routes" "github.com/Azareal/Gosora/routes"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
@ -56,7 +57,7 @@ func afterDBInit() (err error) {
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
err = common.InitPhrases() err = phrases.InitPhrases(common.Site.Language)
if err != nil { if err != nil {
return errors.WithStack(err) return errors.WithStack(err)
} }
@ -229,7 +230,7 @@ func main() {
// TODO: Add a flag for enabling the profiler // TODO: Add a flag for enabling the profiler
if false { if false {
f, err := os.Create("./logs/cpuprof.prof") f, err := os.Create("./logs/cpu.prof")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -421,6 +422,14 @@ func main() {
// Start up the WebSocket ticks // Start up the WebSocket ticks
common.WsHub.Start() common.WsHub.Start()
if false {
f, err := os.Create("./logs/cpu.prof")
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
}
//if profiling { //if profiling {
// pprof.StopCPUProfile() // pprof.StopCPUProfile()
//} //}

View File

@ -10,8 +10,16 @@ import (
"time" "time"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func miscinit(t *testing.T) {
err := gloinit()
if err != nil {
t.Fatal(err)
}
}
func recordMustExist(t *testing.T, err error, errmsg string, args ...interface{}) { func recordMustExist(t *testing.T, err error, errmsg string, args ...interface{}) {
if err == ErrNoRows { if err == ErrNoRows {
debug.PrintStack() debug.PrintStack()
@ -33,12 +41,7 @@ func recordMustNotExist(t *testing.T, err error, errmsg string, args ...interfac
} }
func TestUserStore(t *testing.T) { func TestUserStore(t *testing.T) {
if !gloinited { miscinit(t)
err := gloinit()
if err != nil {
t.Fatal(err)
}
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -344,12 +347,7 @@ func expect(t *testing.T, item bool, errmsg string) {
} }
func TestPermsMiddleware(t *testing.T) { func TestPermsMiddleware(t *testing.T) {
if !gloinited { miscinit(t)
err := gloinit()
if err != nil {
t.Fatal(err)
}
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -410,12 +408,7 @@ func TestPermsMiddleware(t *testing.T) {
} }
func TestTopicStore(t *testing.T) { func TestTopicStore(t *testing.T) {
if !gloinited { miscinit(t)
err := gloinit()
if err != nil {
t.Fatal(err)
}
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -531,9 +524,7 @@ func topicStoreTest(t *testing.T, newID int) {
} }
func TestForumStore(t *testing.T) { func TestForumStore(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -593,9 +584,7 @@ func TestForumStore(t *testing.T) {
// TODO: Implement this // TODO: Implement this
func TestForumPermsStore(t *testing.T) { func TestForumPermsStore(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -603,9 +592,7 @@ func TestForumPermsStore(t *testing.T) {
// TODO: Test the group permissions // TODO: Test the group permissions
func TestGroupStore(t *testing.T) { func TestGroupStore(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -704,9 +691,7 @@ func TestGroupStore(t *testing.T) {
} }
func TestReplyStore(t *testing.T) { func TestReplyStore(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -759,9 +744,7 @@ func TestReplyStore(t *testing.T) {
} }
func TestProfileReplyStore(t *testing.T) { func TestProfileReplyStore(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -800,10 +783,7 @@ func TestProfileReplyStore(t *testing.T) {
} }
func TestLogs(t *testing.T) { func TestLogs(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
gTests := func(store common.LogStore, phrase string) { gTests := func(store common.LogStore, phrase string) {
expect(t, store.GlobalCount() == 0, "There shouldn't be any "+phrase) expect(t, store.GlobalCount() == 0, "There shouldn't be any "+phrase)
logs, err := store.GetOffset(0, 25) logs, err := store.GetOffset(0, 25)
@ -837,9 +817,7 @@ func TestLogs(t *testing.T) {
// TODO: Add tests for registration logs // TODO: Add tests for registration logs
func TestPluginManager(t *testing.T) { func TestPluginManager(t *testing.T) {
if !gloinited { miscinit(t)
gloinit()
}
if !common.PluginsInited { if !common.PluginsInited {
common.InitPlugins() common.InitPlugins()
} }
@ -989,10 +967,10 @@ func TestPluginManager(t *testing.T) {
} }
func TestPhrases(t *testing.T) { func TestPhrases(t *testing.T) {
expect(t, common.GetGlobalPermPhrase("BanUsers") == "Can ban users", "Not the expected phrase") expect(t, phrases.GetGlobalPermPhrase("BanUsers") == "Can ban users", "Not the expected phrase")
expect(t, common.GetGlobalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase") expect(t, phrases.GetGlobalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase")
expect(t, common.GetLocalPermPhrase("ViewTopic") == "Can view topics", "Not the expected phrase") expect(t, phrases.GetLocalPermPhrase("ViewTopic") == "Can view topics", "Not the expected phrase")
expect(t, common.GetLocalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase") expect(t, phrases.GetLocalPermPhrase("NoSuchPerm") == "{lang.perms[NoSuchPerm]}", "Not the expected phrase")
// TODO: Cover the other phrase types, also try switching between languages to see if anything strange happens // TODO: Cover the other phrase types, also try switching between languages to see if anything strange happens
} }

View File

@ -16,6 +16,7 @@ import (
"unicode" "unicode"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
// A blank list to fill out that parameter in Page for routes which don't use it // A blank list to fill out that parameter in Page for routes which don't use it
@ -157,21 +158,21 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user common.User) c
return common.PreErrorJS("You haven't requested any phrases", w, r) return common.PreErrorJS("You haven't requested any phrases", w, r)
} }
var phrases map[string]string var plist map[string]string
// A little optimisation to avoid copying entries from one map to the other, if we don't have to mutate it // A little optimisation to avoid copying entries from one map to the other, if we don't have to mutate it
if len(positives) > 1 { if len(positives) > 1 {
phrases = make(map[string]string) plist = make(map[string]string)
for _, positive := range positives { for _, positive := range positives {
// ! Constrain it to topic and status phrases for now // ! Constrain it to topic and status phrases for now
if !strings.HasPrefix(positive, "topic") && !strings.HasPrefix(positive, "status") && !strings.HasPrefix(positive, "alerts") { if !strings.HasPrefix(positive, "topic") && !strings.HasPrefix(positive, "status") && !strings.HasPrefix(positive, "alerts") {
return common.PreErrorJS("Not implemented!", w, r) return common.PreErrorJS("Not implemented!", w, r)
} }
pPhrases, ok := common.GetTmplPhrasesByPrefix(positive) pPhrases, ok := phrases.GetTmplPhrasesByPrefix(positive)
if !ok { if !ok {
return common.PreErrorJS("No such prefix", w, r) return common.PreErrorJS("No such prefix", w, r)
} }
for name, phrase := range pPhrases { for name, phrase := range pPhrases {
phrases[name] = phrase plist[name] = phrase
} }
} }
} else { } else {
@ -179,23 +180,23 @@ func routeAPIPhrases(w http.ResponseWriter, r *http.Request, user common.User) c
if !strings.HasPrefix(positives[0], "topic") && !strings.HasPrefix(positives[0], "status") && !strings.HasPrefix(positives[0], "alerts") { if !strings.HasPrefix(positives[0], "topic") && !strings.HasPrefix(positives[0], "status") && !strings.HasPrefix(positives[0], "alerts") {
return common.PreErrorJS("Not implemented!", w, r) return common.PreErrorJS("Not implemented!", w, r)
} }
pPhrases, ok := common.GetTmplPhrasesByPrefix(positives[0]) pPhrases, ok := phrases.GetTmplPhrasesByPrefix(positives[0])
if !ok { if !ok {
return common.PreErrorJS("No such prefix", w, r) return common.PreErrorJS("No such prefix", w, r)
} }
phrases = pPhrases plist = pPhrases
} }
for _, negation := range negations { for _, negation := range negations {
for name, _ := range phrases { for name, _ := range plist {
if strings.HasPrefix(name, negation) { if strings.HasPrefix(name, negation) {
delete(phrases, name) delete(plist, name)
} }
} }
} }
// TODO: Cache the output of this, especially for things like topic, so we don't have to waste more time than we need on this // TODO: Cache the output of this, especially for things like topic, so we don't have to waste more time than we need on this
jsonBytes, err := json.Marshal(phrases) jsonBytes, err := json.Marshal(plist)
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }

View File

@ -16,6 +16,7 @@ import (
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/Gosora/common/phrases"
) )
// A blank list to fill out that parameter in Page for routes which don't use it // A blank list to fill out that parameter in Page for routes which don't use it
@ -29,7 +30,7 @@ func AccountLogin(w http.ResponseWriter, r *http.Request, user common.User) comm
if user.Loggedin { if user.Loggedin {
return common.LocalError("You're already logged in.", w, r, user) return common.LocalError("You're already logged in.", w, r, user)
} }
header.Title = common.GetTitlePhrase("login") header.Title = phrases.GetTitlePhrase("login")
pi := common.Page{header, tList, nil} pi := common.Page{header, tList, nil}
return renderTemplate("login", w, r, header, pi) return renderTemplate("login", w, r, header, pi)
} }
@ -140,7 +141,7 @@ func AccountLoginMFAVerify(w http.ResponseWriter, r *http.Request, user common.U
if user.Loggedin { if user.Loggedin {
return common.LocalError("You're already logged in.", w, r, user) return common.LocalError("You're already logged in.", w, r, user)
} }
header.Title = common.GetTitlePhrase("login_mfa_verify") header.Title = phrases.GetTitlePhrase("login_mfa_verify")
uid, provSession, signedSession, err := mfaGetCookies(r) uid, provSession, signedSession, err := mfaGetCookies(r)
if err != nil { if err != nil {
@ -193,7 +194,7 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, user common.User) c
if user.Loggedin { if user.Loggedin {
return common.LocalError("You're already logged in.", w, r, user) return common.LocalError("You're already logged in.", w, r, user)
} }
header.Title = common.GetTitlePhrase("register") header.Title = phrases.GetTitlePhrase("register")
pi := common.Page{header, tList, nil} pi := common.Page{header, tList, nil}
return renderTemplate("register", w, r, header, pi) return renderTemplate("register", w, r, header, pi)
@ -224,14 +225,14 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
} }
if r.PostFormValue("tos") != "0" { if r.PostFormValue("tos") != "0" {
regError(common.GetErrorPhrase("register_might_be_machine"), "trap-question") regError(phrases.GetErrorPhrase("register_might_be_machine"), "trap-question")
} }
if !common.Config.DisableJSAntispam { if !common.Config.DisableJSAntispam {
h := sha256.New() h := sha256.New()
h.Write([]byte(common.JSTokenBox.Load().(string))) h.Write([]byte(common.JSTokenBox.Load().(string)))
h.Write([]byte(user.LastIP)) h.Write([]byte(user.LastIP))
if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) { if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) {
regError(common.GetErrorPhrase("register_might_be_machine"), "js-antispam") regError(phrases.GetErrorPhrase("register_might_be_machine"), "js-antispam")
} }
} }
@ -239,21 +240,21 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
// TODO: Add a dedicated function for validating emails // TODO: Add a dedicated function for validating emails
email := common.SanitiseSingleLine(r.PostFormValue("email")) email := common.SanitiseSingleLine(r.PostFormValue("email"))
if username == "" { if username == "" {
regError(common.GetErrorPhrase("register_need_username"), "no-username") regError(phrases.GetErrorPhrase("register_need_username"), "no-username")
} }
if email == "" { if email == "" {
regError(common.GetErrorPhrase("register_need_email"), "no-email") regError(phrases.GetErrorPhrase("register_need_email"), "no-email")
} }
// This is so a numeric name won't interfere with mentioning a user by ID, there might be a better way of doing this like perhaps !@ to mean IDs and @ to mean usernames in the pre-parser // This is so a numeric name won't interfere with mentioning a user by ID, there might be a better way of doing this like perhaps !@ to mean IDs and @ to mean usernames in the pre-parser
usernameBits := strings.Split(username, " ") usernameBits := strings.Split(username, " ")
if isNumeric(usernameBits[0]) { if isNumeric(usernameBits[0]) {
regError(common.GetErrorPhrase("register_first_word_numeric"), "numeric-name") regError(phrases.GetErrorPhrase("register_first_word_numeric"), "numeric-name")
} }
ok := common.HasSuspiciousEmail(email) ok := common.HasSuspiciousEmail(email)
if ok { if ok {
regError(common.GetErrorPhrase("register_suspicious_email"), "suspicious-email") regError(phrases.GetErrorPhrase("register_suspicious_email"), "suspicious-email")
} }
password := r.PostFormValue("password") password := r.PostFormValue("password")
@ -265,7 +266,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
// Do the two inputted passwords match..? // Do the two inputted passwords match..?
confirmPassword := r.PostFormValue("confirm_password") confirmPassword := r.PostFormValue("confirm_password")
if password != confirmPassword { if password != confirmPassword {
regError(common.GetErrorPhrase("register_password_mismatch"), "password-mismatch") regError(phrases.GetErrorPhrase("register_password_mismatch"), "password-mismatch")
} }
} }
@ -298,14 +299,14 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
return common.LocalError(common.GetErrorPhrase("register_username_unavailable"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("register_username_unavailable"), w, r, user)
} else if err == common.ErrLongUsername { } else if err == common.ErrLongUsername {
regLog.FailureReason += "username-too-long" regLog.FailureReason += "username-too-long"
err = regLog.Commit() err = regLog.Commit()
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
return common.LocalError(common.GetErrorPhrase("register_username_too_long_prefix")+strconv.Itoa(common.Config.MaxUsernameLength), w, r, user) return common.LocalError(phrases.GetErrorPhrase("register_username_too_long_prefix")+strconv.Itoa(common.Config.MaxUsernameLength), w, r, user)
} }
regLog.FailureReason += "internal-error" regLog.FailureReason += "internal-error"
err2 := regLog.Commit() err2 := regLog.Commit()
@ -329,7 +330,7 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user common.U
} }
if !common.SendValidationEmail(username, email, token) { if !common.SendValidationEmail(username, email, token) {
return common.LocalError(common.GetErrorPhrase("register_email_fail"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("register_email_fail"), w, r, user)
} }
} }
@ -349,7 +350,7 @@ func accountEditHead(titlePhrase string, w http.ResponseWriter, r *http.Request,
if ferr != nil { if ferr != nil {
return nil, ferr return nil, ferr
} }
header.Title = common.GetTitlePhrase(titlePhrase) header.Title = phrases.GetTitlePhrase(titlePhrase)
header.Path = "/user/edit/" header.Path = "/user/edit/"
header.AddSheet(header.Theme.Name + "/account.css") header.AddSheet(header.Theme.Name + "/account.css")
header.AddScript("account.js") header.AddScript("account.js")
@ -389,6 +390,7 @@ func AccountEdit(w http.ResponseWriter, r *http.Request, user common.User) commo
return renderTemplate("account", w, r, header, pi) return renderTemplate("account", w, r, header, pi)
} }
//edit_password
func AccountEditPassword(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func AccountEditPassword(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
header, ferr := accountEditHead("account_password", w, r, &user) header, ferr := accountEditHead("account_password", w, r, &user)
if ferr != nil { if ferr != nil {
@ -736,7 +738,7 @@ func LevelList(w http.ResponseWriter, r *http.Request, user common.User) common.
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("account_level_list") header.Title = phrases.GetTitlePhrase("account_level_list")
var fScores = common.GetLevels(20) var fScores = common.GetLevels(20)
var levels = make([]common.LevelListItem, len(fScores)) var levels = make([]common.LevelListItem, len(fScores))

View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func ForumList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func ForumList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -12,7 +13,7 @@ func ForumList(w http.ResponseWriter, r *http.Request, user common.User) common.
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("forums") header.Title = phrases.GetTitlePhrase("forums")
header.Zone = "forums" header.Zone = "forums"
header.Path = "/forums/" header.Path = "/forums/"
header.MetaDesc = header.Settings["meta_desc"].(string) header.MetaDesc = header.Settings["meta_desc"].(string)

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
) )
@ -53,7 +54,7 @@ func Overview(w http.ResponseWriter, r *http.Request, user common.User) common.R
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("overview") header.Title = phrases.GetTitlePhrase("overview")
header.Zone = "overview" header.Zone = "overview"
pi := common.Page{header, tList, nil} pi := common.Page{header, tList, nil}
@ -72,7 +73,7 @@ func CustomPage(w http.ResponseWriter, r *http.Request, user common.User, name s
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("page") header.Title = phrases.GetTitlePhrase("page")
header.Zone = "custom_page" header.Zone = "custom_page"
name = common.SanitiseSingleLine(name) name = common.SanitiseSingleLine(name)

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func IPSearch(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func IPSearch(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -11,7 +12,7 @@ func IPSearch(w http.ResponseWriter, r *http.Request, user common.User) common.R
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("ip_search") header.Title = phrases.GetTitlePhrase("ip_search")
// TODO: How should we handle the permissions if we extend this into an alt detector of sorts? // TODO: How should we handle the permissions if we extend this into an alt detector of sorts?
if !user.Perms.ViewIPs { if !user.Perms.ViewIPs {

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
) )
@ -227,7 +228,7 @@ func AnalyticsAgentViews(w http.ResponseWriter, r *http.Request, user common.Use
graph := common.PanelTimeGraph{Series: viewList, Labels: labelList} graph := common.PanelTimeGraph{Series: viewList, Labels: labelList}
common.DebugLogf("graph: %+v\n", graph) common.DebugLogf("graph: %+v\n", graph)
friendlyAgent, ok := common.GetUserAgentPhrase(agent) friendlyAgent, ok := phrases.GetUserAgentPhrase(agent)
if !ok { if !ok {
friendlyAgent = agent friendlyAgent = agent
} }
@ -312,7 +313,7 @@ func AnalyticsSystemViews(w http.ResponseWriter, r *http.Request, user common.Us
graph := common.PanelTimeGraph{Series: viewList, Labels: labelList} graph := common.PanelTimeGraph{Series: viewList, Labels: labelList}
common.DebugLogf("graph: %+v\n", graph) common.DebugLogf("graph: %+v\n", graph)
friendlySystem, ok := common.GetOSPhrase(system) friendlySystem, ok := phrases.GetOSPhrase(system)
if !ok { if !ok {
friendlySystem = system friendlySystem = system
} }
@ -352,7 +353,7 @@ func AnalyticsLanguageViews(w http.ResponseWriter, r *http.Request, user common.
graph := common.PanelTimeGraph{Series: viewList, Labels: labelList} graph := common.PanelTimeGraph{Series: viewList, Labels: labelList}
common.DebugLogf("graph: %+v\n", graph) common.DebugLogf("graph: %+v\n", graph)
friendlyLang, ok := common.GetHumanLangPhrase(lang) friendlyLang, ok := phrases.GetHumanLangPhrase(lang)
if !ok { if !ok {
friendlyLang = lang friendlyLang = lang
} }
@ -584,7 +585,7 @@ func AnalyticsAgents(w http.ResponseWriter, r *http.Request, user common.User) c
// TODO: Sort this slice // TODO: Sort this slice
var agentItems []common.PanelAnalyticsAgentsItem var agentItems []common.PanelAnalyticsAgentsItem
for agent, count := range agentMap { for agent, count := range agentMap {
aAgent, ok := common.GetUserAgentPhrase(agent) aAgent, ok := phrases.GetUserAgentPhrase(agent)
if !ok { if !ok {
aAgent = agent aAgent = agent
} }
@ -622,7 +623,7 @@ func AnalyticsSystems(w http.ResponseWriter, r *http.Request, user common.User)
// TODO: Sort this slice // TODO: Sort this slice
var systemItems []common.PanelAnalyticsAgentsItem var systemItems []common.PanelAnalyticsAgentsItem
for system, count := range osMap { for system, count := range osMap {
sSystem, ok := common.GetOSPhrase(system) sSystem, ok := phrases.GetOSPhrase(system)
if !ok { if !ok {
sSystem = system sSystem = system
} }
@ -661,7 +662,7 @@ func AnalyticsLanguages(w http.ResponseWriter, r *http.Request, user common.User
// TODO: Sort this slice // TODO: Sort this slice
var langItems []common.PanelAnalyticsAgentsItem var langItems []common.PanelAnalyticsAgentsItem
for lang, count := range langMap { for lang, count := range langMap {
lLang, ok := common.GetHumanLangPhrase(lang) lLang, ok := phrases.GetHumanLangPhrase(lang)
if !ok { if !ok {
lLang = lang lLang = lang
} }

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
// A blank list to fill out that parameter in Page for routes which don't use it // A blank list to fill out that parameter in Page for routes which don't use it
@ -37,7 +38,7 @@ func buildBasePage(w http.ResponseWriter, r *http.Request, user *common.User, ti
if ferr != nil { if ferr != nil {
return nil, ferr return nil, ferr
} }
header.Title = common.GetTitlePhrase("panel_" + titlePhrase) header.Title = phrases.GetTitlePhrase("panel_" + titlePhrase)
return &common.BasePanelPage{header, stats, zone, common.ReportForumID}, nil return &common.BasePanelPage{header, stats, zone, common.ReportForumID}, nil
} }

View File

@ -7,6 +7,7 @@ import (
"strconv" "strconv"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
"github.com/Azareal/gopsutil/mem" "github.com/Azareal/gopsutil/mem"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -142,18 +143,18 @@ func Dashboard(w http.ResponseWriter, r *http.Request, user common.User) common.
// TODO: Allow for more complex phrase structures than just suffixes // TODO: Allow for more complex phrase structures than just suffixes
var postCount = extractStat(stmts.todaysPostCount) var postCount = extractStat(stmts.todaysPostCount)
var postInterval = common.GetTmplPhrase("panel_dashboard_day_suffix") var postInterval = phrases.GetTmplPhrase("panel_dashboard_day_suffix")
var postColour = greaterThanSwitch(postCount, 5, 25) var postColour = greaterThanSwitch(postCount, 5, 25)
var topicCount = extractStat(stmts.todaysTopicCount) var topicCount = extractStat(stmts.todaysTopicCount)
var topicInterval = common.GetTmplPhrase("panel_dashboard_day_suffix") var topicInterval = phrases.GetTmplPhrase("panel_dashboard_day_suffix")
var topicColour = greaterThanSwitch(topicCount, 0, 8) var topicColour = greaterThanSwitch(topicCount, 0, 8)
var reportCount = extractStat(stmts.todaysTopicCountByForum, common.ReportForumID) var reportCount = extractStat(stmts.todaysTopicCountByForum, common.ReportForumID)
var reportInterval = common.GetTmplPhrase("panel_dashboard_week_suffix") var reportInterval = phrases.GetTmplPhrase("panel_dashboard_week_suffix")
var newUserCount = extractStat(stmts.todaysNewUserCount) var newUserCount = extractStat(stmts.todaysNewUserCount)
var newUserInterval = common.GetTmplPhrase("panel_dashboard_week_suffix") var newUserInterval = phrases.GetTmplPhrase("panel_dashboard_week_suffix")
// Did any of the extractStats fail? // Did any of the extractStats fail?
if intErr != nil { if intErr != nil {
@ -187,9 +188,9 @@ func Dashboard(w http.ResponseWriter, r *http.Request, user common.User) common.
uonline, uunit := common.ConvertFriendlyUnit(uonline) uonline, uunit := common.ConvertFriendlyUnit(uonline)
gonline, gunit := common.ConvertFriendlyUnit(gonline) gonline, gunit := common.ConvertFriendlyUnit(gonline)
addElement(common.GridElement{"dash-totonline", common.GetTmplPhrasef("panel_dashboard_online", totonline, totunit), 3, "grid_stat " + onlineColour, "", "", "The number of people who are currently online"}) addElement(common.GridElement{"dash-totonline", phrases.GetTmplPhrasef("panel_dashboard_online", totonline, totunit), 3, "grid_stat " + onlineColour, "", "", "The number of people who are currently online"})
addElement(common.GridElement{"dash-gonline", common.GetTmplPhrasef("panel_dashboard_guests_online", gonline, gunit), 4, "grid_stat " + onlineGuestsColour, "", "", "The number of guests who are currently online"}) addElement(common.GridElement{"dash-gonline", phrases.GetTmplPhrasef("panel_dashboard_guests_online", gonline, gunit), 4, "grid_stat " + onlineGuestsColour, "", "", "The number of guests who are currently online"})
addElement(common.GridElement{"dash-uonline", common.GetTmplPhrasef("panel_dashboard_users_online", uonline, uunit), 5, "grid_stat " + onlineUsersColour, "", "", "The number of logged-in users who are currently online"}) addElement(common.GridElement{"dash-uonline", phrases.GetTmplPhrasef("panel_dashboard_users_online", uonline, uunit), 5, "grid_stat " + onlineUsersColour, "", "", "The number of logged-in users who are currently online"})
addElement(common.GridElement{"dash-reqs", strconv.Itoa(reqCount) + " reqs / second", 7, "grid_stat grid_end_group " + topicColour, "", "", "The number of requests over the last 24 hours"}) addElement(common.GridElement{"dash-reqs", strconv.Itoa(reqCount) + " reqs / second", 7, "grid_stat grid_end_group " + topicColour, "", "", "The number of requests over the last 24 hours"})
} }

View File

@ -8,6 +8,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func Forums(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func Forums(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -329,7 +330,7 @@ func ForumsEditPermsAdvance(w http.ResponseWriter, r *http.Request, user common.
// TODO: Load the phrases in bulk for efficiency? // TODO: Load the phrases in bulk for efficiency?
// TODO: Reduce the amount of code duplication between this and the group editor. Also, can we grind this down into one line or use a code generator to stay current more easily? // TODO: Reduce the amount of code duplication between this and the group editor. Also, can we grind this down into one line or use a code generator to stay current more easily?
var addNameLangToggle = func(permStr string, perm bool) { var addNameLangToggle = func(permStr string, perm bool) {
formattedPermList = append(formattedPermList, common.NameLangToggle{permStr, common.GetLocalPermPhrase(permStr), perm}) formattedPermList = append(formattedPermList, common.NameLangToggle{permStr, phrases.GetLocalPermPhrase(permStr), perm})
} }
addNameLangToggle("ViewTopic", forumPerms.ViewTopic) addNameLangToggle("ViewTopic", forumPerms.ViewTopic)
addNameLangToggle("LikeItem", forumPerms.LikeItem) addNameLangToggle("LikeItem", forumPerms.LikeItem)

View File

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func Groups(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func Groups(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -72,7 +73,7 @@ func GroupsEdit(w http.ResponseWriter, r *http.Request, user common.User, sgid s
gid, err := strconv.Atoi(sgid) gid, err := strconv.Atoi(sgid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("url_id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, user)
} }
group, err := common.Groups.Get(gid) group, err := common.Groups.Get(gid)
@ -84,10 +85,10 @@ func GroupsEdit(w http.ResponseWriter, r *http.Request, user common.User, sgid s
} }
if group.IsAdmin && !user.Perms.EditGroupAdmin { if group.IsAdmin && !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user)
} }
if group.IsMod && !user.Perms.EditGroupSuperMod { if group.IsMod && !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user)
} }
var rank string var rank string
@ -120,7 +121,7 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user common.User, s
gid, err := strconv.Atoi(sgid) gid, err := strconv.Atoi(sgid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("url_id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, user)
} }
group, err := common.Groups.Get(gid) group, err := common.Groups.Get(gid)
@ -132,17 +133,17 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user common.User, s
} }
if group.IsAdmin && !user.Perms.EditGroupAdmin { if group.IsAdmin && !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user)
} }
if group.IsMod && !user.Perms.EditGroupSuperMod { if group.IsMod && !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user)
} }
// TODO: Load the phrases in bulk for efficiency? // TODO: Load the phrases in bulk for efficiency?
var localPerms []common.NameLangToggle var localPerms []common.NameLangToggle
var addLocalPerm = func(permStr string, perm bool) { var addLocalPerm = func(permStr string, perm bool) {
localPerms = append(localPerms, common.NameLangToggle{permStr, common.GetLocalPermPhrase(permStr), perm}) localPerms = append(localPerms, common.NameLangToggle{permStr, phrases.GetLocalPermPhrase(permStr), perm})
} }
addLocalPerm("ViewTopic", group.Perms.ViewTopic) addLocalPerm("ViewTopic", group.Perms.ViewTopic)
@ -160,7 +161,7 @@ func GroupsEditPerms(w http.ResponseWriter, r *http.Request, user common.User, s
var globalPerms []common.NameLangToggle var globalPerms []common.NameLangToggle
var addGlobalPerm = func(permStr string, perm bool) { var addGlobalPerm = func(permStr string, perm bool) {
globalPerms = append(globalPerms, common.NameLangToggle{permStr, common.GetGlobalPermPhrase(permStr), perm}) globalPerms = append(globalPerms, common.NameLangToggle{permStr, phrases.GetGlobalPermPhrase(permStr), perm})
} }
addGlobalPerm("BanUsers", group.Perms.BanUsers) addGlobalPerm("BanUsers", group.Perms.BanUsers)
@ -199,7 +200,7 @@ func GroupsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User,
gid, err := strconv.Atoi(sgid) gid, err := strconv.Atoi(sgid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
} }
group, err := common.Groups.Get(gid) group, err := common.Groups.Get(gid)
@ -211,15 +212,15 @@ func GroupsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User,
} }
if group.IsAdmin && !user.Perms.EditGroupAdmin { if group.IsAdmin && !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user)
} }
if group.IsMod && !user.Perms.EditGroupSuperMod { if group.IsMod && !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user)
} }
gname := r.FormValue("group-name") gname := r.FormValue("group-name")
if gname == "" { if gname == "" {
return common.LocalError(common.GetErrorPhrase("panel_groups_need_name"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_need_name"), w, r, user)
} }
gtag := r.FormValue("group-tag") gtag := r.FormValue("group-tag")
rank := r.FormValue("group-type") rank := r.FormValue("group-type")
@ -240,28 +241,28 @@ func GroupsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User,
if rank != originalRank && originalRank != "Guest" { if rank != originalRank && originalRank != "Guest" {
if !user.Perms.EditGroupGlobalPerms { if !user.Perms.EditGroupGlobalPerms {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_group_type"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_group_type"), w, r, user)
} }
switch rank { switch rank {
case "Admin": case "Admin":
if !user.Perms.EditGroupAdmin { if !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_edit_cannot_designate_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_edit_cannot_designate_admin"), w, r, user)
} }
err = group.ChangeRank(true, true, false) err = group.ChangeRank(true, true, false)
case "Mod": case "Mod":
if !user.Perms.EditGroupSuperMod { if !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_edit_cannot_designate_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_edit_cannot_designate_supermod"), w, r, user)
} }
err = group.ChangeRank(false, true, false) err = group.ChangeRank(false, true, false)
case "Banned": case "Banned":
err = group.ChangeRank(false, false, true) err = group.ChangeRank(false, false, true)
case "Guest": case "Guest":
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_be_guest"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_be_guest"), w, r, user)
case "Member": case "Member":
err = group.ChangeRank(false, false, false) err = group.ChangeRank(false, false, false)
default: default:
return common.LocalError(common.GetErrorPhrase("panel_groups_invalid_group_type"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_invalid_group_type"), w, r, user)
} }
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
@ -288,7 +289,7 @@ func GroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user common.U
gid, err := strconv.Atoi(sgid) gid, err := strconv.Atoi(sgid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user)
} }
group, err := common.Groups.Get(gid) group, err := common.Groups.Get(gid)
@ -300,10 +301,10 @@ func GroupsEditPermsSubmit(w http.ResponseWriter, r *http.Request, user common.U
} }
if group.IsAdmin && !user.Perms.EditGroupAdmin { if group.IsAdmin && !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_admin"), w, r, user)
} }
if group.IsMod && !user.Perms.EditGroupSuperMod { if group.IsMod && !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_cannot_edit_supermod"), w, r, user)
} }
var pmap = make(map[string]bool) var pmap = make(map[string]bool)
@ -342,7 +343,7 @@ func GroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User
groupName := r.PostFormValue("group-name") groupName := r.PostFormValue("group-name")
if groupName == "" { if groupName == "" {
return common.LocalError(common.GetErrorPhrase("panel_groups_need_name"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_need_name"), w, r, user)
} }
groupTag := r.PostFormValue("group-tag") groupTag := r.PostFormValue("group-tag")
@ -351,13 +352,13 @@ func GroupsCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User
groupType := r.PostFormValue("group-type") groupType := r.PostFormValue("group-type")
if groupType == "Admin" { if groupType == "Admin" {
if !user.Perms.EditGroupAdmin { if !user.Perms.EditGroupAdmin {
return common.LocalError(common.GetErrorPhrase("panel_groups_create_cannot_designate_admin"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_create_cannot_designate_admin"), w, r, user)
} }
isAdmin = true isAdmin = true
isMod = true isMod = true
} else if groupType == "Mod" { } else if groupType == "Mod" {
if !user.Perms.EditGroupSuperMod { if !user.Perms.EditGroupSuperMod {
return common.LocalError(common.GetErrorPhrase("panel_groups_create_cannot_designate_supermod"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("panel_groups_create_cannot_designate_supermod"), w, r, user)
} }
isMod = true isMod = true
} else if groupType == "Banned" { } else if groupType == "Banned" {

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func Settings(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func Settings(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -22,7 +23,7 @@ func Settings(w http.ResponseWriter, r *http.Request, user common.User) common.R
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
settingPhrases := common.GetAllSettingPhrases() settingPhrases := phrases.GetAllSettingPhrases()
var settingList []*common.PanelSetting var settingList []*common.PanelSetting
for _, settingPtr := range settings { for _, settingPtr := range settings {
@ -44,7 +45,7 @@ func Settings(w http.ResponseWriter, r *http.Request, user common.User) common.R
} else if setting.Type == "html-attribute" { } else if setting.Type == "html-attribute" {
setting.Type = "textarea" setting.Type = "textarea"
} }
settingList = append(settingList, &common.PanelSetting{setting, common.GetSettingPhrase(setting.Name)}) settingList = append(settingList, &common.PanelSetting{setting, phrases.GetSettingPhrase(setting.Name)})
} }
pi := common.PanelPage{basePage, tList, settingList} pi := common.PanelPage{basePage, tList, settingList}
@ -69,12 +70,11 @@ func SettingEdit(w http.ResponseWriter, r *http.Request, user common.User, sname
var itemList []common.OptionLabel var itemList []common.OptionLabel
if setting.Type == "list" { if setting.Type == "list" {
llist := common.GetSettingPhrase(setting.Name + "_label") llist := phrases.GetSettingPhrase(setting.Name + "_label")
conv, err := strconv.Atoi(setting.Content) conv, err := strconv.Atoi(setting.Content)
if err != nil { if err != nil {
return common.LocalError("The value of this setting couldn't be converted to an integer", w, r, user) return common.LocalError("The value of this setting couldn't be converted to an integer", w, r, user)
} }
//fmt.Println("llist: ", llist)
for index, label := range strings.Split(llist, ",") { for index, label := range strings.Split(llist, ",") {
itemList = append(itemList, common.OptionLabel{ itemList = append(itemList, common.OptionLabel{
@ -87,7 +87,7 @@ func SettingEdit(w http.ResponseWriter, r *http.Request, user common.User, sname
setting.Type = "textarea" setting.Type = "textarea"
} }
pSetting := &common.PanelSetting{setting, common.GetSettingPhrase(setting.Name)} pSetting := &common.PanelSetting{setting, phrases.GetSettingPhrase(setting.Name)}
pi := common.PanelSettingPage{basePage, itemList, pSetting} pi := common.PanelSettingPage{basePage, itemList, pSetting}
return renderTemplate("panel_setting", w, r, user, &pi) return renderTemplate("panel_setting", w, r, user, &pi)
} }

View File

@ -7,6 +7,7 @@ import (
"strings" "strings"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func Themes(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func Themes(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -73,7 +74,7 @@ func ThemesMenus(w http.ResponseWriter, r *http.Request, user common.User) commo
for mid, list := range common.Menus.GetAllMap() { for mid, list := range common.Menus.GetAllMap() {
var name = "" var name = ""
if mid == 1 { if mid == 1 {
name = common.GetTmplPhrase("panel_themes_menus_main") name = phrases.GetTmplPhrase("panel_themes_menus_main")
} }
menuList = append(menuList, common.PanelMenuListItem{ menuList = append(menuList, common.PanelMenuListItem{
Name: name, Name: name,
@ -99,7 +100,7 @@ func ThemesMenusEdit(w http.ResponseWriter, r *http.Request, user common.User, s
mid, err := strconv.Atoi(smid) mid, err := strconv.Atoi(smid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("url_id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, user)
} }
menuHold, err := common.Menus.Get(mid) menuHold, err := common.Menus.Get(mid)
@ -145,7 +146,7 @@ func ThemesMenuItemEdit(w http.ResponseWriter, r *http.Request, user common.User
itemID, err := strconv.Atoi(sitemID) itemID, err := strconv.Atoi(sitemID)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("url_id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, user)
} }
menuItem, err := common.Menus.ItemStore().Get(itemID) menuItem, err := common.Menus.ItemStore().Get(itemID)
@ -217,7 +218,7 @@ func ThemesMenuItemEditSubmit(w http.ResponseWriter, r *http.Request, user commo
itemID, err := strconv.Atoi(sitemID) itemID, err := strconv.Atoi(sitemID)
if err != nil { if err != nil {
return common.LocalErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs) return common.LocalErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs)
} }
menuItem, err := common.Menus.ItemStore().Get(itemID) menuItem, err := common.Menus.ItemStore().Get(itemID)
@ -252,7 +253,7 @@ func ThemesMenuItemCreateSubmit(w http.ResponseWriter, r *http.Request, user com
} }
menuID, err := strconv.Atoi(smenuID) menuID, err := strconv.Atoi(smenuID)
if err != nil { if err != nil {
return common.LocalErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs) return common.LocalErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs)
} }
menuItem := common.MenuItem{MenuID: menuID} menuItem := common.MenuItem{MenuID: menuID}
@ -276,7 +277,7 @@ func ThemesMenuItemDeleteSubmit(w http.ResponseWriter, r *http.Request, user com
itemID, err := strconv.Atoi(sitemID) itemID, err := strconv.Atoi(sitemID)
if err != nil { if err != nil {
return common.LocalErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs) return common.LocalErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs)
} }
menuItem, err := common.Menus.ItemStore().Get(itemID) menuItem, err := common.Menus.ItemStore().Get(itemID)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
@ -305,7 +306,7 @@ func ThemesMenuItemOrderSubmit(w http.ResponseWriter, r *http.Request, user comm
mid, err := strconv.Atoi(smid) mid, err := strconv.Atoi(smid)
if err != nil { if err != nil {
return common.LocalErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs) return common.LocalErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, user, isJs)
} }
menuHold, err := common.Menus.Get(mid) menuHold, err := common.Menus.Get(mid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {

View File

@ -8,6 +8,7 @@ import (
"time" "time"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
) )
@ -68,7 +69,7 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user common.User) commo
} }
puser.Init() puser.Init()
} }
header.Title = common.GetTitlePhrasef("profile", puser.Name) header.Title = phrases.GetTitlePhrasef("profile", puser.Name)
header.Path = common.BuildProfileURL(common.NameToSlug(puser.Name), puser.ID) header.Path = common.BuildProfileURL(common.NameToSlug(puser.Name), puser.ID)
// Get the replies.. // Get the replies..
@ -100,7 +101,7 @@ func ViewProfile(w http.ResponseWriter, r *http.Request, user common.User) commo
if group.Tag != "" { if group.Tag != "" {
replyTag = group.Tag replyTag = group.Tag
} else if puser.ID == replyCreatedBy { } else if puser.ID == replyCreatedBy {
replyTag = common.GetTmplPhrase("profile_owner_tag") replyTag = phrases.GetTmplPhrase("profile_owner_tag")
} else { } else {
replyTag = "" replyTag = ""
} }

View File

@ -15,6 +15,7 @@ import (
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/counters" "github.com/Azareal/Gosora/common/counters"
"github.com/Azareal/Gosora/common/phrases"
"github.com/Azareal/Gosora/query_gen" "github.com/Azareal/Gosora/query_gen"
) )
@ -48,7 +49,7 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
tid, err := strconv.Atoi(halves[1]) tid, err := strconv.Atoi(halves[1])
if err != nil { if err != nil {
return common.PreError(common.GetErrorPhrase("url_id_must_be_integer"), w, r) return common.PreError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r)
} }
// Get the topic... // Get the topic...
@ -162,22 +163,22 @@ func ViewTopic(w http.ResponseWriter, r *http.Request, user common.User, urlBit
if replyItem.ActionType != "" { if replyItem.ActionType != "" {
switch replyItem.ActionType { switch replyItem.ActionType {
case "lock": case "lock":
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_lock",replyItem.UserLink,replyItem.CreatedByName) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_lock",replyItem.UserLink,replyItem.CreatedByName)
replyItem.ActionIcon = "&#x1F512;&#xFE0E" replyItem.ActionIcon = "&#x1F512;&#xFE0E"
case "unlock": case "unlock":
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_unlock",replyItem.UserLink,replyItem.CreatedByName) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_unlock",replyItem.UserLink,replyItem.CreatedByName)
replyItem.ActionIcon = "&#x1F513;&#xFE0E" replyItem.ActionIcon = "&#x1F513;&#xFE0E"
case "stick": case "stick":
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_stick",replyItem.UserLink,replyItem.CreatedByName) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_stick",replyItem.UserLink,replyItem.CreatedByName)
replyItem.ActionIcon = "&#x1F4CC;&#xFE0E" replyItem.ActionIcon = "&#x1F4CC;&#xFE0E"
case "unstick": case "unstick":
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_unstick",replyItem.UserLink,replyItem.CreatedByName) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_unstick",replyItem.UserLink,replyItem.CreatedByName)
replyItem.ActionIcon = "&#x1F4CC;&#xFE0E" replyItem.ActionIcon = "&#x1F4CC;&#xFE0E"
case "move": case "move":
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_move",replyItem.UserLink,replyItem.CreatedByName) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_move",replyItem.UserLink,replyItem.CreatedByName)
// TODO: Only fire this off if a corresponding phrase for the ActionType doesn't exist? Or maybe have some sort of action registry? // TODO: Only fire this off if a corresponding phrase for the ActionType doesn't exist? Or maybe have some sort of action registry?
default: default:
replyItem.ActionType = common.GetTmplPhrasef("topic.action_topic_default",replyItem.ActionType) replyItem.ActionType = phrases.GetTmplPhrasef("topic.action_topic_default",replyItem.ActionType)
replyItem.ActionIcon = "" replyItem.ActionIcon = ""
} }
} }
@ -237,7 +238,7 @@ func CreateTopic(w http.ResponseWriter, r *http.Request, user common.User, sfid
if sfid != "" { if sfid != "" {
fid, err = strconv.Atoi(sfid) fid, err = strconv.Atoi(sfid)
if err != nil { if err != nil {
return common.LocalError(common.GetErrorPhrase("url_id_must_be_integer"), w, r, user) return common.LocalError(phrases.GetErrorPhrase("url_id_must_be_integer"), w, r, user)
} }
} }
if fid == 0 { if fid == 0 {
@ -252,7 +253,7 @@ func CreateTopic(w http.ResponseWriter, r *http.Request, user common.User, sfid
return common.NoPermissions(w, r, user) return common.NoPermissions(w, r, user)
} }
// TODO: Add a phrase for this // TODO: Add a phrase for this
header.Title = common.GetTitlePhrase("create_topic") header.Title = phrases.GetTitlePhrase("create_topic")
header.Zone = "create_topic" header.Zone = "create_topic"
// Lock this to the forum being linked? // Lock this to the forum being linked?
@ -343,8 +344,8 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
var maxPollOptions = 10 var maxPollOptions = 10
var pollInputItems = make(map[int]string) var pollInputItems = make(map[int]string)
for key, values := range r.Form { for key, values := range r.Form {
common.DebugDetail("key: ", key) //common.DebugDetail("key: ", key)
common.DebugDetailf("values: %+v\n", values) //common.DebugDetailf("values: %+v\n", values)
for _, value := range values { for _, value := range values {
if strings.HasPrefix(key, "pollinputitem[") { if strings.HasPrefix(key, "pollinputitem[") {
halves := strings.Split(key, "[") halves := strings.Split(key, "[")
@ -474,10 +475,9 @@ func CreateTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
// TODO: Disable stat updates in posts handled by plugin_guilds // TODO: Disable stat updates in posts handled by plugin_guilds
func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError { func EditTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
isJs := (r.PostFormValue("js") == "1") isJs := (r.PostFormValue("js") == "1")
tid, err := strconv.Atoi(stid) tid, err := strconv.Atoi(stid)
if err != nil { if err != nil {
return common.PreErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, isJs) return common.PreErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, isJs)
} }
topic, err := common.Topics.Get(tid) topic, err := common.Topics.Get(tid)
@ -593,74 +593,59 @@ func DeleteTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User)
} }
func StickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError { func StickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
topic,rerr := topicActionPre(stid,"pin",w,r,user)
if rerr != nil {
return rerr
}
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
return common.NoPermissions(w, r, user)
}
return topicActionPost(topic.Stick(),"stick",w,r,topic,user)
}
func topicActionPre(stid string, action string, w http.ResponseWriter, r *http.Request, user common.User) (*common.Topic, common.RouteError) {
tid, err := strconv.Atoi(stid) tid, err := strconv.Atoi(stid)
if err != nil { if err != nil {
return common.PreError(common.GetErrorPhrase("id_must_be_integer"), w, r) return nil,common.PreError(phrases.GetErrorPhrase("id_must_be_integer"), w, r)
} }
topic, err := common.Topics.Get(tid) topic, err := common.Topics.Get(tid)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return common.PreError("The topic you tried to pin doesn't exist.", w, r) return nil, common.PreError("The topic you tried to "+action+" doesn't exist.", w, r)
} else if err != nil { } else if err != nil {
return common.InternalError(err, w, r) return nil, common.InternalError(err, w, r)
} }
// TODO: Add hooks to make use of headerLite // TODO: Add hooks to make use of headerLite
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID) _, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
if ferr != nil { if ferr != nil {
return ferr return nil, ferr
}
if !user.Perms.ViewTopic || !user.Perms.PinTopic {
return common.NoPermissions(w, r, user)
} }
err = topic.Stick() return topic, nil
}
func topicActionPost(err error, action string,w http.ResponseWriter, r *http.Request, topic *common.Topic, user common.User) common.RouteError {
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
err = addTopicAction(action, topic, user)
err = addTopicAction("stick", topic, user)
if err != nil { if err != nil {
return common.InternalError(err, w, r) return common.InternalError(err, w, r)
} }
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther) http.Redirect(w, r, "/topic/"+strconv.Itoa(topic.ID), http.StatusSeeOther)
return nil return nil
} }
func UnstickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError { func UnstickTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
tid, err := strconv.Atoi(stid) topic,rerr := topicActionPre(stid,"unpin",w,r,user)
if err != nil { if rerr != nil {
return common.PreError(common.GetErrorPhrase("id_must_be_integer"), w, r) return rerr
}
topic, err := common.Topics.Get(tid)
if err == sql.ErrNoRows {
return common.PreError("The topic you tried to unpin doesn't exist.", w, r)
} else if err != nil {
return common.InternalError(err, w, r)
}
// TODO: Add hooks to make use of headerLite
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
if ferr != nil {
return ferr
} }
if !user.Perms.ViewTopic || !user.Perms.PinTopic { if !user.Perms.ViewTopic || !user.Perms.PinTopic {
return common.NoPermissions(w, r, user) return common.NoPermissions(w, r, user)
} }
return topicActionPost(topic.Unstick(),"unstick",w,r,topic,user)
err = topic.Unstick()
if err != nil {
return common.InternalError(err, w, r)
}
err = addTopicAction("unstick", topic, user)
if err != nil {
return common.InternalError(err, w, r)
}
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
return nil
} }
func LockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func LockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -722,39 +707,14 @@ func LockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User) c
} }
func UnlockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError { func UnlockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, stid string) common.RouteError {
tid, err := strconv.Atoi(stid) topic,rerr := topicActionPre(stid,"unlock",w,r,user)
if err != nil { if rerr != nil {
return common.PreError(common.GetErrorPhrase("id_must_be_integer"), w, r) return rerr
}
topic, err := common.Topics.Get(tid)
if err == sql.ErrNoRows {
return common.PreError("The topic you tried to unlock doesn't exist.", w, r)
} else if err != nil {
return common.InternalError(err, w, r)
}
// TODO: Add hooks to make use of headerLite
_, ferr := common.SimpleForumUserCheck(w, r, &user, topic.ParentID)
if ferr != nil {
return ferr
} }
if !user.Perms.ViewTopic || !user.Perms.CloseTopic { if !user.Perms.ViewTopic || !user.Perms.CloseTopic {
return common.NoPermissions(w, r, user) return common.NoPermissions(w, r, user)
} }
return topicActionPost(topic.Unlock(),"unlock",w,r,topic,user)
err = topic.Unlock()
if err != nil {
return common.InternalError(err, w, r)
}
err = addTopicAction("unlock", topic, user)
if err != nil {
return common.InternalError(err, w, r)
}
http.Redirect(w, r, "/topic/"+strconv.Itoa(tid), http.StatusSeeOther)
return nil
} }
// ! JS only route // ! JS only route
@ -762,7 +722,7 @@ func UnlockTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User,
func MoveTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, sfid string) common.RouteError { func MoveTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, sfid string) common.RouteError {
fid, err := strconv.Atoi(sfid) fid, err := strconv.Atoi(sfid)
if err != nil { if err != nil {
return common.PreErrorJS(common.GetErrorPhrase("id_must_be_integer"), w, r) return common.PreErrorJS(phrases.GetErrorPhrase("id_must_be_integer"), w, r)
} }
// TODO: Move this to some sort of middleware // TODO: Move this to some sort of middleware
@ -833,7 +793,7 @@ func LikeTopicSubmit(w http.ResponseWriter, r *http.Request, user common.User, s
isJs := (r.PostFormValue("isJs") == "1") isJs := (r.PostFormValue("isJs") == "1")
tid, err := strconv.Atoi(stid) tid, err := strconv.Atoi(stid)
if err != nil { if err != nil {
return common.PreErrorJSQ(common.GetErrorPhrase("id_must_be_integer"), w, r, isJs) return common.PreErrorJSQ(phrases.GetErrorPhrase("id_must_be_integer"), w, r, isJs)
} }
topic, err := common.Topics.Get(tid) topic, err := common.Topics.Get(tid)

View File

@ -6,6 +6,7 @@ import (
"strconv" "strconv"
"github.com/Azareal/Gosora/common" "github.com/Azareal/Gosora/common"
"github.com/Azareal/Gosora/common/phrases"
) )
func TopicList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError { func TopicList(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
@ -13,7 +14,7 @@ func TopicList(w http.ResponseWriter, r *http.Request, user common.User) common.
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("topics") header.Title = phrases.GetTitlePhrase("topics")
header.Zone = "topics" header.Zone = "topics"
header.Path = "/topics/" header.Path = "/topics/"
header.MetaDesc = header.Settings["meta_desc"].(string) header.MetaDesc = header.Settings["meta_desc"].(string)
@ -61,7 +62,7 @@ func TopicListMostViewed(w http.ResponseWriter, r *http.Request, user common.Use
if ferr != nil { if ferr != nil {
return ferr return ferr
} }
header.Title = common.GetTitlePhrase("topics") header.Title = phrases.GetTitlePhrase("topics")
header.Zone = "topics" header.Zone = "topics"
header.Path = "/topics/" header.Path = "/topics/"
header.MetaDesc = header.Settings["meta_desc"].(string) header.MetaDesc = header.Settings["meta_desc"].(string)