From eb49dde0763a93e8caecd26e30b8f68a4714a270 Mon Sep 17 00:00:00 2001 From: Azareal Date: Mon, 28 Oct 2019 17:46:14 +1000 Subject: [PATCH] Experiment with eliminating allocations. Encode png images as pngs rather than turning them into jpgs. Shorten things to eliminate bytes and boilerplate. Remove some old code. --- common/attachments.go | 21 +++++----- common/audit_logs.go | 14 ++++--- common/extend.go | 26 ++++++------ common/forum_perms.go | 12 +++--- common/forum_store.go | 23 ++++++----- common/group.go | 7 ++-- common/menu_store.go | 2 +- common/menus.go | 91 +++++++++++++++++++++--------------------- common/report_store.go | 14 +++---- common/theme_list.go | 17 ++++---- common/thumbnailer.go | 12 +++++- common/topic.go | 23 ++++++----- common/topic_store.go | 19 +++++---- common/word_filters.go | 11 ++--- public/global.js | 4 -- 15 files changed, 153 insertions(+), 143 deletions(-) diff --git a/common/attachments.go b/common/attachments.go index 7feb5935..0ce563ce 100644 --- a/common/attachments.go +++ b/common/attachments.go @@ -48,16 +48,17 @@ type DefaultAttachmentStore struct { } func NewDefaultAttachmentStore(acc *qgen.Accumulator) (*DefaultAttachmentStore, error) { + a := "attachments" return &DefaultAttachmentStore{ - get: acc.Select("attachments").Columns("originID, sectionID, uploadedBy, path, extra").Where("attachID = ?").Prepare(), - getByObj: acc.Select("attachments").Columns("attachID, sectionID, uploadedBy, path, extra").Where("originTable = ? AND originID = ?").Prepare(), - add: acc.Insert("attachments").Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path, extra").Fields("?,?,?,?,?,?,?").Prepare(), - count: acc.Count("attachments").Prepare(), - countIn: acc.Count("attachments").Where("originTable = ? and originID = ?").Prepare(), - countInPath: acc.Count("attachments").Where("path = ?").Prepare(), - move: acc.Update("attachments").Set("sectionID = ?").Where("originID = ? AND originTable = ?").Prepare(), - moveByExtra: acc.Update("attachments").Set("sectionID = ?").Where("originTable = ? AND extra = ?").Prepare(), - delete: acc.Delete("attachments").Where("attachID = ?").Prepare(), + get: acc.Select(a).Columns("originID, sectionID, uploadedBy, path, extra").Where("attachID = ?").Prepare(), + getByObj: acc.Select(a).Columns("attachID, sectionID, uploadedBy, path, extra").Where("originTable = ? AND originID = ?").Prepare(), + add: acc.Insert(a).Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path, extra").Fields("?,?,?,?,?,?,?").Prepare(), + count: acc.Count(a).Prepare(), + countIn: acc.Count(a).Where("originTable = ? and originID = ?").Prepare(), + countInPath: acc.Count(a).Where("path = ?").Prepare(), + move: acc.Update(a).Set("sectionID = ?").Where("originID = ? AND originTable = ?").Prepare(), + moveByExtra: acc.Update(a).Set("sectionID = ?").Where("originTable = ? AND extra = ?").Prepare(), + delete: acc.Delete(a).Where("attachID = ?").Prepare(), }, acc.FirstError() } @@ -93,7 +94,7 @@ func (s *DefaultAttachmentStore) BulkMiniGetList(originTable string, ids []int) amap = make(map[int][]*MiniAttachment) var buffer []*MiniAttachment var currentID int - rows, err := qgen.NewAcc().Select("attachments").Columns("attachID,sectionID,originID,uploadedBy,path").Where("originTable = ?").In("originID", ids).Orderby("originID ASC").Query(originTable) + rows, err := qgen.NewAcc().Select("attachments").Columns("attachID,sectionID,originID,uploadedBy,path").Where("originTable=?").In("originID", ids).Orderby("originID ASC").Query(originTable) defer rows.Close() for rows.Next() { a := &MiniAttachment{} diff --git a/common/audit_logs.go b/common/audit_logs.go index ab60e531..a322129b 100644 --- a/common/audit_logs.go +++ b/common/audit_logs.go @@ -32,10 +32,11 @@ type SQLModLogStore struct { } func NewModLogStore(acc *qgen.Accumulator) (*SQLModLogStore, error) { + ml := "moderation_logs" return &SQLModLogStore{ - create: acc.Insert("moderation_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), - count: acc.Count("moderation_logs").Prepare(), - getOffset: acc.Select("moderation_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(), + create: acc.Insert(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), + count: acc.Count(ml).Prepare(), + getOffset: acc.Select(ml).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(), }, acc.FirstError() } @@ -83,10 +84,11 @@ type SQLAdminLogStore struct { } func NewAdminLogStore(acc *qgen.Accumulator) (*SQLAdminLogStore, error) { + al := "administration_logs" return &SQLAdminLogStore{ - create: acc.Insert("administration_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), - count: acc.Count("administration_logs").Prepare(), - getOffset: acc.Select("administration_logs").Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(), + create: acc.Insert(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Fields("?,?,?,?,?,UTC_TIMESTAMP()").Prepare(), + count: acc.Count(al).Prepare(), + getOffset: acc.Select(al).Columns("action, elementID, elementType, ipaddress, actorID, doneAt").Orderby("doneAt DESC").Limit("?,?").Prepare(), }, acc.FirstError() } diff --git a/common/extend.go b/common/extend.go index 4251d4db..246b5557 100644 --- a/common/extend.go +++ b/common/extend.go @@ -30,15 +30,15 @@ func (list PluginList) Add(plugin *Plugin) { list[plugin.UName] = plugin } -func buildPlugin(plugin *Plugin) { - plugin.Installable = (plugin.Install != nil) +func buildPlugin(pl *Plugin) { + pl.Installable = (pl.Install != nil) /* The Active field should never be altered by a plugin. It's used internally by the software to determine whether an admin has enabled a plugin or not and whether to run it. This will be overwritten by the user's preference. */ - plugin.Active = false - plugin.Installed = false - plugin.Hooks = make(map[string]int) - plugin.Data = nil + pl.Active = false + pl.Installed = false + pl.Hooks = make(map[string]int) + pl.Data = nil } var hookTableBox atomic.Value @@ -391,13 +391,14 @@ var extendStmts ExtendStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { + pl := "plugins" extendStmts = ExtendStmts{ - getPlugins: acc.Select("plugins").Columns("uname, active, installed").Prepare(), + getPlugins: acc.Select(pl).Columns("uname, active, installed").Prepare(), - isActive: acc.Select("plugins").Columns("active").Where("uname = ?").Prepare(), - setActive: acc.Update("plugins").Set("active = ?").Where("uname = ?").Prepare(), - setInstalled: acc.Update("plugins").Set("installed = ?").Where("uname = ?").Prepare(), - add: acc.Insert("plugins").Columns("uname, active, installed").Fields("?,?,?").Prepare(), + isActive: acc.Select(pl).Columns("active").Where("uname = ?").Prepare(), + setActive: acc.Update(pl).Set("active = ?").Where("uname = ?").Prepare(), + setInstalled: acc.Update(pl).Set("installed = ?").Where("uname = ?").Prepare(), + add: acc.Insert(pl).Columns("uname, active, installed").Fields("?,?,?").Prepare(), } return acc.FirstError() }) @@ -564,8 +565,7 @@ func InitPlugins() { // ? - Are the following functions racey? func RunTaskHook(name string) error { for _, hook := range taskHooks[name] { - err := hook() - if err != nil { + if err := hook(); err != nil { return err } } diff --git a/common/forum_perms.go b/common/forum_perms.go index b00d7ade..1360576d 100644 --- a/common/forum_perms.go +++ b/common/forum_perms.go @@ -110,8 +110,8 @@ func PermmapToQuery(permmap map[string]*ForumPerms, fid int) error { } addForumPermsToForumAdminsTx, err := qgen.Builder.SimpleInsertSelectTx(tx, - qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""}, - qgen.DBSelect{"users_groups", "gid, ?, '', ?", "is_admin = 1", "", ""}, + qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 1", "", ""}, ) if err != nil { return err @@ -127,8 +127,8 @@ func PermmapToQuery(permmap map[string]*ForumPerms, fid int) error { } addForumPermsToForumStaffTx, err := qgen.Builder.SimpleInsertSelectTx(tx, - qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""}, - qgen.DBSelect{"users_groups", "gid, ?, '', ?", "is_admin = 0 AND is_mod = 1", "", ""}, + qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 0 AND is_mod = 1", "", ""}, ) if err != nil { return err @@ -144,8 +144,8 @@ func PermmapToQuery(permmap map[string]*ForumPerms, fid int) error { } addForumPermsToForumMembersTx, err := qgen.Builder.SimpleInsertSelectTx(tx, - qgen.DBInsert{"forums_permissions", "gid, fid, preset, permissions", ""}, - qgen.DBSelect{"users_groups", "gid, ?, '', ?", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""}, + qgen.DBInsert{"forums_permissions", "gid,fid,preset,permissions", ""}, + qgen.DBSelect{"users_groups", "gid,?,'',?", "is_admin = 0 AND is_mod = 0 AND is_banned = 0", "", ""}, ) if err != nil { return err diff --git a/common/forum_store.go b/common/forum_store.go index b83ef3cb..95405928 100644 --- a/common/forum_store.go +++ b/common/forum_store.go @@ -76,17 +76,18 @@ type MemoryForumStore struct { // NewMemoryForumStore gives you a new instance of MemoryForumStore func NewMemoryForumStore() (*MemoryForumStore, error) { acc := qgen.NewAcc() + f := "forums" // TODO: Do a proper delete return &MemoryForumStore{ - get: acc.Select("forums").Columns("name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Where("fid = ?").Prepare(), - getAll: acc.Select("forums").Columns("fid, name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Orderby("order ASC, fid ASC").Prepare(), - delete: acc.Update("forums").Set("name= '', active = 0").Where("fid = ?").Prepare(), - create: acc.Insert("forums").Columns("name, desc, tmpl, active, preset").Fields("?,?,'',?,?").Prepare(), - count: acc.Count("forums").Where("name != ''").Prepare(), - updateCache: acc.Update("forums").Set("lastTopicID = ?, lastReplyerID = ?").Where("fid = ?").Prepare(), - addTopics: acc.Update("forums").Set("topicCount = topicCount + ?").Where("fid = ?").Prepare(), - removeTopics: acc.Update("forums").Set("topicCount = topicCount - ?").Where("fid = ?").Prepare(), - updateOrder: acc.Update("forums").Set("order = ?").Where("fid = ?").Prepare(), + get: acc.Select(f).Columns("name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Where("fid = ?").Prepare(), + getAll: acc.Select(f).Columns("fid, name, desc, tmpl, active, order, preset, parentID, parentType, topicCount, lastTopicID, lastReplyerID").Orderby("order ASC, fid ASC").Prepare(), + delete: acc.Update(f).Set("name= '', active = 0").Where("fid = ?").Prepare(), + create: acc.Insert(f).Columns("name, desc, tmpl, active, preset").Fields("?,?,'',?,?").Prepare(), + count: acc.Count(f).Where("name != ''").Prepare(), + updateCache: acc.Update(f).Set("lastTopicID = ?, lastReplyerID = ?").Where("fid = ?").Prepare(), + addTopics: acc.Update(f).Set("topicCount = topicCount + ?").Where("fid = ?").Prepare(), + removeTopics: acc.Update(f).Set("topicCount = topicCount - ?").Where("fid = ?").Prepare(), + updateOrder: acc.Update(f).Set("order = ?").Where("fid = ?").Prepare(), }, acc.FirstError() } @@ -107,7 +108,7 @@ func (s *MemoryForumStore) LoadForums() error { } defer rows.Close() - var i = 0 + i := 0 for ; rows.Next(); i++ { f := &Forum{ID: 0, Active: true, Preset: "all"} err = rows.Scan(&f.ID, &f.Name, &f.Desc, &f.Tmpl, &f.Active, &f.Order, &f.Preset, &f.ParentID, &f.ParentType, &f.TopicCount, &f.LastTopicID, &f.LastReplyerID) @@ -254,7 +255,7 @@ func (s *MemoryForumStore) GetAllVisible() (forumView []*Forum, err error) { func (s *MemoryForumStore) GetAllVisibleIDs() ([]int, error) { forumView := s.forumView.Load().([]*Forum) - var ids = make([]int, len(forumView)) + ids := make([]int, len(forumView)) for i := 0; i < len(forumView); i++ { ids[i] = forumView[i].ID } diff --git a/common/group.go b/common/group.go index a0405282..08a14b5e 100644 --- a/common/group.go +++ b/common/group.go @@ -44,10 +44,11 @@ var groupStmts GroupStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { + ug := "users_groups" groupStmts = GroupStmts{ - updateGroup: acc.Update("users_groups").Set("name = ?, tag = ?").Where("gid = ?").Prepare(), - updateGroupRank: acc.Update("users_groups").Set("is_admin = ?, is_mod = ?, is_banned = ?").Where("gid = ?").Prepare(), - updateGroupPerms: acc.Update("users_groups").Set("permissions = ?").Where("gid = ?").Prepare(), + updateGroup: acc.Update(ug).Set("name = ?, tag = ?").Where("gid = ?").Prepare(), + updateGroupRank: acc.Update(ug).Set("is_admin = ?, is_mod = ?, is_banned = ?").Where("gid = ?").Prepare(), + updateGroupPerms: acc.Update(ug).Set("permissions = ?").Where("gid = ?").Prepare(), } return acc.FirstError() }) diff --git a/common/menu_store.go b/common/menu_store.go index 57e72355..0462e496 100644 --- a/common/menu_store.go +++ b/common/menu_store.go @@ -40,7 +40,7 @@ func (s *DefaultMenuStore) Get(mid int) (*MenuListHolder, error) { } func (s *DefaultMenuStore) Items(mid int) (mlist MenuItemList, err error) { - err = qgen.NewAcc().Select("menu_items").Columns("miid, name, htmlID, cssClass, position, path, aria, tooltip, order, tmplName, guestOnly, memberOnly, staffOnly, adminOnly").Where("mid = " + strconv.Itoa(mid)).Orderby("order ASC").Each(func(rows *sql.Rows) error { + err = qgen.NewAcc().Select("menu_items").Columns("miid,name,htmlID,cssClass,position,path,aria,tooltip,order,tmplName,guestOnly,memberOnly,staffOnly,adminOnly").Where("mid = " + strconv.Itoa(mid)).Orderby("order ASC").Each(func(rows *sql.Rows) error { i := MenuItem{MenuID: mid} err := rows.Scan(&i.ID, &i.Name, &i.HTMLID, &i.CSSClass, &i.Position, &i.Path, &i.Aria, &i.Tooltip, &i.Order, &i.TmplName, &i.GuestOnly, &i.MemberOnly, &i.SuperModOnly, &i.AdminOnly) if err != nil { diff --git a/common/menus.go b/common/menus.go index 09735149..cd8366ac 100644 --- a/common/menus.go +++ b/common/menus.go @@ -64,63 +64,64 @@ var menuItemStmts MenuItemStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { + mi := "menu_items" menuItemStmts = MenuItemStmts{ - update: acc.Update("menu_items").Set("name = ?, htmlID = ?, cssClass = ?, position = ?, path = ?, aria = ?, tooltip = ?, tmplName = ?, guestOnly = ?, memberOnly = ?, staffOnly = ?, adminOnly = ?").Where("miid = ?").Prepare(), - insert: acc.Insert("menu_items").Columns("mid, name, htmlID, cssClass, position, path, aria, tooltip, tmplName, guestOnly, memberOnly, staffOnly, adminOnly").Fields("?,?,?,?,?,?,?,?,?,?,?,?,?").Prepare(), - delete: acc.Delete("menu_items").Where("miid = ?").Prepare(), - updateOrder: acc.Update("menu_items").Set("order = ?").Where("miid = ?").Prepare(), + update: acc.Update(mi).Set("name = ?, htmlID = ?, cssClass = ?, position = ?, path = ?, aria = ?, tooltip = ?, tmplName = ?, guestOnly = ?, memberOnly = ?, staffOnly = ?, adminOnly = ?").Where("miid = ?").Prepare(), + insert: acc.Insert(mi).Columns("mid, name, htmlID, cssClass, position, path, aria, tooltip, tmplName, guestOnly, memberOnly, staffOnly, adminOnly").Fields("?,?,?,?,?,?,?,?,?,?,?,?,?").Prepare(), + delete: acc.Delete(mi).Where("miid = ?").Prepare(), + updateOrder: acc.Update(mi).Set("order = ?").Where("miid = ?").Prepare(), } return acc.FirstError() }) } -func (item MenuItem) Commit() error { - _, err := menuItemStmts.update.Exec(item.Name, item.HTMLID, item.CSSClass, item.Position, item.Path, item.Aria, item.Tooltip, item.TmplName, item.GuestOnly, item.MemberOnly, item.SuperModOnly, item.AdminOnly, item.ID) - Menus.Load(item.MenuID) +func (i MenuItem) Commit() error { + _, err := menuItemStmts.update.Exec(i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly, i.ID) + Menus.Load(i.MenuID) return err } -func (item MenuItem) Create() (int, error) { - res, err := menuItemStmts.insert.Exec(item.MenuID, item.Name, item.HTMLID, item.CSSClass, item.Position, item.Path, item.Aria, item.Tooltip, item.TmplName, item.GuestOnly, item.MemberOnly, item.SuperModOnly, item.AdminOnly) +func (i MenuItem) Create() (int, error) { + res, err := menuItemStmts.insert.Exec(i.MenuID, i.Name, i.HTMLID, i.CSSClass, i.Position, i.Path, i.Aria, i.Tooltip, i.TmplName, i.GuestOnly, i.MemberOnly, i.SuperModOnly, i.AdminOnly) if err != nil { return 0, err } - Menus.Load(item.MenuID) + Menus.Load(i.MenuID) miid64, err := res.LastInsertId() return int(miid64), err } -func (item MenuItem) Delete() error { - _, err := menuItemStmts.delete.Exec(item.ID) - Menus.Load(item.MenuID) +func (i MenuItem) Delete() error { + _, err := menuItemStmts.delete.Exec(i.ID) + Menus.Load(i.MenuID) return err } -func (hold *MenuListHolder) LoadTmpl(name string) (menuTmpl MenuTmpl, err error) { +func (h *MenuListHolder) LoadTmpl(name string) (menuTmpl MenuTmpl, err error) { data, err := ioutil.ReadFile("./templates/" + name + ".html") if err != nil { return menuTmpl, err } - return hold.Parse(name, data), nil + return h.Parse(name, data), nil } // TODO: Make this atomic, maybe with a transaction or store the order on the menu itself? -func (hold *MenuListHolder) UpdateOrder(updateMap map[int]int) error { +func (h *MenuListHolder) UpdateOrder(updateMap map[int]int) error { for miid, order := range updateMap { _, err := menuItemStmts.updateOrder.Exec(order, miid) if err != nil { return err } } - Menus.Load(hold.MenuID) + Menus.Load(h.MenuID) return nil } -func (hold *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, err error) { +func (h *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, err error) { tmpls = make(map[string]MenuTmpl) - var loadTmpl = func(name string) error { - menuTmpl, err := hold.LoadTmpl(name) + loadTmpl := func(name string) error { + menuTmpl, err := h.LoadTmpl(name) if err != nil { return err } @@ -136,32 +137,32 @@ func (hold *MenuListHolder) LoadTmpls() (tmpls map[string]MenuTmpl, err error) { } // TODO: Run this in main, sync ticks, when the phrase file changes (need to implement the sync for that first), and when the settings are changed -func (hold *MenuListHolder) Preparse() error { - tmpls, err := hold.LoadTmpls() +func (h *MenuListHolder) Preparse() error { + tmpls, err := h.LoadTmpls() if err != nil { return err } - var addVariation = func(index int, callback func(mitem MenuItem) bool) { - renderBuffer, variableIndices, pathList := hold.Scan(tmpls, callback) - hold.Variations[index] = menuTmpl{renderBuffer, variableIndices, pathList} + addVariation := func(index int, callback func(i MenuItem) bool) { + renderBuffer, variableIndices, pathList := h.Scan(tmpls, callback) + h.Variations[index] = menuTmpl{renderBuffer, variableIndices, pathList} } // Guest Menu - addVariation(0, func(mitem MenuItem) bool { - return !mitem.MemberOnly + addVariation(0, func(i MenuItem) bool { + return !i.MemberOnly }) // Member Menu - addVariation(1, func(mitem MenuItem) bool { - return !mitem.SuperModOnly && !mitem.GuestOnly + addVariation(1, func(i MenuItem) bool { + return !i.SuperModOnly && !i.GuestOnly }) // Super Mod Menu - addVariation(2, func(mitem MenuItem) bool { - return !mitem.AdminOnly && !mitem.GuestOnly + addVariation(2, func(i MenuItem) bool { + return !i.AdminOnly && !i.GuestOnly }) // Admin Menu - addVariation(3, func(mitem MenuItem) bool { - return !mitem.GuestOnly + addVariation(3, func(i MenuItem) bool { + return !i.GuestOnly }) return nil } @@ -264,13 +265,13 @@ func menuDumpSlice(outerSlice [][]byte) { } } -func (hold *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTmpl) { +func (h *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTmpl) { var textBuffer, variableBuffer [][]byte var renderList []menuRenderItem var subBuffer []byte // ? We only support simple properties on MenuItem right now - var addVariable = func(name []byte) { + addVariable := func(name []byte) { // TODO: Check if the subBuffer has any items or is empty textBuffer = append(textBuffer, subBuffer) subBuffer = nil @@ -325,13 +326,13 @@ func (hold *MenuListHolder) Parse(name string, tmplData []byte) (menuTmpl MenuTm return MenuTmpl{name, textBuffer, variableBuffer, renderList} } -func (hold *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(mitem MenuItem) bool) (renderBuffer [][]byte, variableIndices []int, pathList []menuPath) { - for _, mitem := range hold.List { +func (h *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(i MenuItem) bool) (renderBuffer [][]byte, variableIndices []int, pathList []menuPath) { + for _, mitem := range h.List { // Do we want this item in this variation of the menu? if !showItem(mitem) { continue } - renderBuffer, variableIndices = hold.ScanItem(menuTmpls, mitem, renderBuffer, variableIndices) + renderBuffer, variableIndices = h.ScanItem(menuTmpls, mitem, renderBuffer, variableIndices) pathList = append(pathList, menuPath{mitem.Path, len(renderBuffer) - 1}) } @@ -340,7 +341,7 @@ func (hold *MenuListHolder) Scan(menuTmpls map[string]MenuTmpl, showItem func(mi } // Note: This doesn't do a visibility check like hold.Scan() does -func (hold *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuItem, renderBuffer [][]byte, variableIndices []int) ([][]byte, []int) { +func (h *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuItem, renderBuffer [][]byte, variableIndices []int) ([][]byte, []int) { menuTmpl, ok := menuTmpls[mitem.TmplName] if !ok { menuTmpl = menuTmpls["menu_item"] @@ -416,16 +417,16 @@ func (hold *MenuListHolder) ScanItem(menuTmpls map[string]MenuTmpl, mitem MenuIt } // TODO: Pre-render the lang stuff -func (hold *MenuListHolder) Build(w io.Writer, user *User, pathPrefix string) error { +func (h *MenuListHolder) Build(w io.Writer, user *User, pathPrefix string) error { var mTmpl menuTmpl if !user.Loggedin { - mTmpl = hold.Variations[0] + mTmpl = h.Variations[0] } else if user.IsAdmin { - mTmpl = hold.Variations[3] + mTmpl = h.Variations[3] } else if user.IsSuperMod { - mTmpl = hold.Variations[2] + mTmpl = h.Variations[2] } else { - mTmpl = hold.Variations[1] + mTmpl = h.Variations[1] } if pathPrefix == "" { pathPrefix = Config.DefaultPath @@ -438,7 +439,7 @@ func (hold *MenuListHolder) Build(w io.Writer, user *User, pathPrefix string) er return nil } - var nearIndex = 0 + nearIndex := 0 for index, renderItem := range mTmpl.RenderBuffer { if index != mTmpl.VariableIndices[nearIndex] { w.Write(renderItem) diff --git a/common/report_store.go b/common/report_store.go index ed17d73a..43bb765b 100644 --- a/common/report_store.go +++ b/common/report_store.go @@ -26,16 +26,17 @@ type DefaultReportStore struct { } func NewDefaultReportStore(acc *qgen.Accumulator) (*DefaultReportStore, error) { + t := "topics" return &DefaultReportStore{ - create: acc.Insert("topics").Columns("title, content, parsed_content, ipaddress, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?,'report'").Prepare(), - exists: acc.Count("topics").Where("data = ? AND data != '' AND parentID = ?").Prepare(), + create: acc.Insert(t).Columns("title, content, parsed_content, ipaddress, createdAt, lastReplyAt, createdBy, lastReplyBy, data, parentID, css_class").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?,'report'").Prepare(), + exists: acc.Count(t).Where("data = ? AND data != '' AND parentID = ?").Prepare(), }, acc.FirstError() } // ! There's a data race in this. If two users report one item at the exact same time, then both reports will go through -func (s *DefaultReportStore) Create(title string, content string, user *User, itemType string, itemID int) (int, error) { +func (s *DefaultReportStore) Create(title string, content string, user *User, itemType string, itemID int) (tid int, err error) { var count int - err := s.exists.QueryRow(itemType+"_"+strconv.Itoa(itemID), ReportForumID).Scan(&count) + err = s.exists.QueryRow(itemType+"_"+strconv.Itoa(itemID), ReportForumID).Scan(&count) if err != nil && err != sql.ErrNoRows { return 0, err } @@ -47,11 +48,10 @@ func (s *DefaultReportStore) Create(title string, content string, user *User, it if err != nil { return 0, err } - lastID, err := res.LastInsertId() if err != nil { return 0, err } - - return int(lastID), Forums.AddTopic(int(lastID), user.ID, ReportForumID) + tid = int(lastID) + return tid, Forums.AddTopic(tid, user.ID, ReportForumID) } diff --git a/common/theme_list.go b/common/theme_list.go index e9881b58..687e8c10 100644 --- a/common/theme_list.go +++ b/common/theme_list.go @@ -41,11 +41,12 @@ var themeStmts ThemeStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { + t := "themes" themeStmts = ThemeStmts{ - getAll: acc.Select("themes").Columns("uname, default").Prepare(), - isDefault: acc.Select("themes").Columns("default").Where("uname = ?").Prepare(), - update: acc.Update("themes").Set("default = ?").Where("uname = ?").Prepare(), - add: acc.Insert("themes").Columns("uname, default").Fields("?,?").Prepare(), + getAll: acc.Select(t).Columns("uname, default").Prepare(), + isDefault: acc.Select(t).Columns("default").Where("uname = ?").Prepare(), + update: acc.Update(t).Set("default = ?").Where("uname = ?").Prepare(), + add: acc.Insert(t).Columns("uname, default").Fields("?,?").Prepare(), } return acc.FirstError() }) @@ -144,7 +145,7 @@ func NewThemeList() (themes ThemeList, err error) { return themes, err } if len(overrides) > 0 { - var overCount = 0 + overCount := 0 theme.OverridenMap = make(map[string]bool) for _, override := range overrides { if override.IsDir() { @@ -180,7 +181,6 @@ func NewThemeList() (themes ThemeList, err error) { themes[theme.Name] = theme } - if defaultTheme == "" { defaultTheme = lastTheme } @@ -232,8 +232,7 @@ func (t ThemeList) LoadActiveStatus() error { func (t ThemeList) LoadStaticFiles() error { for _, theme := range t { - err := theme.LoadStaticFiles() - if err != nil { + if err := theme.LoadStaticFiles(); err != nil { return err } } @@ -244,7 +243,6 @@ func ResetTemplateOverrides() { log.Print("Resetting the template overrides") for name := range overridenTemplates { log.Print("Resetting '" + name + "' template override") - originPointer, ok := TmplPtrMap["o_"+name] if !ok { log.Print("The origin template doesn't exist!") @@ -269,7 +267,6 @@ func ResetTemplateOverrides() { LogError(errors.New("The source and destination templates are incompatible")) return } - *dPtr = oPtr log.Print("The template override was reset") } diff --git a/common/thumbnailer.go b/common/thumbnailer.go index 3f2f57e5..a6569afd 100644 --- a/common/thumbnailer.go +++ b/common/thumbnailer.go @@ -4,7 +4,7 @@ import ( "image" "image/gif" "image/jpeg" - _ "image/png" + "image/png" "os" "strconv" @@ -66,6 +66,14 @@ func ThumbTask(thumbChan chan bool) { if err != nil { LogError(err) } + + /* + err := acc.Select("attach_image_queue").Columns("attachID").Limit("0,5").EachInt(func(attachID int) error { + return nil + + _, err = acc.Delete("attach_image_queue").Where("attachID = ?").Run(uid) + } + */ if err = acc.FirstError(); err != nil { LogError(err) } @@ -119,6 +127,8 @@ func precodeImage(format string, inPath string, tmpPath string) error { // TODO: Make sure animated gifs work after being encoded if format == "gif" { return gif.Encode(outFile, img, nil) + } else if format == "png" { + return png.Encode(outFile, img) } return jpeg.Encode(outFile, img, nil) } diff --git a/common/topic.go b/common/topic.go index 988c5dae..b08d1d51 100644 --- a/common/topic.go +++ b/common/topic.go @@ -212,24 +212,25 @@ var topicStmts TopicStmts func init() { DbInits.Add(func(acc *qgen.Accumulator) error { + t := "topics" topicStmts = TopicStmts{ getRids: acc.Select("replies").Columns("rid").Where("tid = ?").Orderby("rid ASC").Limit("?,?").Prepare(), getReplies: acc.SimpleLeftJoin("replies AS r", "users AS u", "r.rid, r.content, r.createdBy, r.createdAt, r.lastEdit, r.lastEditBy, u.avatar, u.name, u.group, u.url_prefix, u.url_name, u.level, r.ipaddress, r.likeCount, r.attachCount, r.actionType", "r.createdBy = u.uid", "r.tid = ?", "r.rid ASC", "?,?"), - addReplies: acc.Update("topics").Set("postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()").Where("tid = ?").Prepare(), - updateLastReply: acc.Update("topics").Set("lastReplyID = ?").Where("lastReplyID > ? AND tid = ?").Prepare(), - lock: acc.Update("topics").Set("is_closed = 1").Where("tid = ?").Prepare(), - unlock: acc.Update("topics").Set("is_closed = 0").Where("tid = ?").Prepare(), - moveTo: acc.Update("topics").Set("parentID = ?").Where("tid = ?").Prepare(), - stick: acc.Update("topics").Set("sticky = 1").Where("tid = ?").Prepare(), - unstick: acc.Update("topics").Set("sticky = 0").Where("tid = ?").Prepare(), + addReplies: acc.Update(t).Set("postCount = postCount + ?, lastReplyBy = ?, lastReplyAt = UTC_TIMESTAMP()").Where("tid = ?").Prepare(), + updateLastReply: acc.Update(t).Set("lastReplyID = ?").Where("lastReplyID > ? AND tid = ?").Prepare(), + lock: acc.Update(t).Set("is_closed = 1").Where("tid = ?").Prepare(), + unlock: acc.Update(t).Set("is_closed = 0").Where("tid = ?").Prepare(), + moveTo: acc.Update(t).Set("parentID = ?").Where("tid = ?").Prepare(), + stick: acc.Update(t).Set("sticky = 1").Where("tid = ?").Prepare(), + unstick: acc.Update(t).Set("sticky = 0").Where("tid = ?").Prepare(), hasLikedTopic: acc.Select("likes").Columns("targetItem").Where("sentBy = ? and targetItem = ? and targetType = 'topics'").Prepare(), createLike: acc.Insert("likes").Columns("weight, targetItem, targetType, sentBy, createdAt").Fields("?,?,?,?,UTC_TIMESTAMP()").Prepare(), - addLikesToTopic: acc.Update("topics").Set("likeCount = likeCount + ?").Where("tid = ?").Prepare(), - delete: acc.Delete("topics").Where("tid = ?").Prepare(), + addLikesToTopic: acc.Update(t).Set("likeCount = likeCount + ?").Where("tid = ?").Prepare(), + delete: acc.Delete(t).Where("tid = ?").Prepare(), deleteActivity: acc.Delete("activity_stream").Where("elementID = ? AND elementType = 'topic'").Prepare(), deleteActivitySubs: acc.Delete("activity_subscriptions").Where("targetID = ? AND targetType = 'topic'").Prepare(), - edit: acc.Update("topics").Set("title = ?, content = ?, parsed_content = ?").Where("tid = ?").Prepare(), // TODO: Only run the content update bits on non-polls, does this matter? - setPoll: acc.Update("topics").Set("poll = ?").Where("tid = ? AND poll = 0").Prepare(), + edit: acc.Update(t).Set("title = ?, content = ?, parsed_content = ?").Where("tid = ?").Prepare(), // TODO: Only run the content update bits on non-polls, does this matter? + setPoll: acc.Update(t).Set("poll = ?").Where("tid = ? AND poll = 0").Prepare(), createAction: acc.Insert("replies").Columns("tid, actionType, ipaddress, createdBy, createdAt, lastUpdated, content, parsed_content").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'',''").Prepare(), getTopicUser: acc.SimpleLeftJoin("topics AS t", "users AS u", "t.title, t.content, t.createdBy, t.createdAt, t.lastReplyAt, t.lastReplyBy, t.lastReplyID, t.is_closed, t.sticky, t.parentID, t.ipaddress, t.views, t.postCount, t.likeCount, t.attachCount,t.poll, u.name, u.avatar, u.group, u.url_prefix, u.url_name, u.level", "t.createdBy = u.uid", "tid = ?", "", ""), diff --git a/common/topic_store.go b/common/topic_store.go index 1778d4bc..d687b158 100644 --- a/common/topic_store.go +++ b/common/topic_store.go @@ -56,12 +56,13 @@ func NewDefaultTopicStore(cache TopicCache) (*DefaultTopicStore, error) { if cache == nil { cache = NewNullTopicCache() } + t := "topics" return &DefaultTopicStore{ cache: cache, - get: acc.Select("topics").Columns("title, content, createdBy, createdAt, lastReplyBy, lastReplyAt, lastReplyID, is_closed, sticky, parentID, ipaddress, views, postCount, likeCount, attachCount, poll, data").Where("tid = ?").Prepare(), - exists: acc.Select("topics").Columns("tid").Where("tid = ?").Prepare(), - count: acc.Count("topics").Prepare(), - create: acc.Insert("topics").Columns("parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?").Prepare(), + get: acc.Select(t).Columns("title, content, createdBy, createdAt, lastReplyBy, lastReplyAt, lastReplyID, is_closed, sticky, parentID, ipaddress, views, postCount, likeCount, attachCount, poll, data").Where("tid = ?").Prepare(), + exists: acc.Exists(t,"tid").Prepare(), + count: acc.Count(t).Prepare(), + create: acc.Insert(t).Columns("parentID, title, content, parsed_content, createdAt, lastReplyAt, lastReplyBy, ipaddress, words, createdBy").Fields("?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?,?").Prepare(), }, acc.FirstError() } @@ -159,8 +160,7 @@ func (s *DefaultTopicStore) BulkGetMap(ids []int) (list map[int]*Topic, err erro s.cache.Set(t) list[t.ID] = t } - err = rows.Err() - if err != nil { + if err = rows.Err(); err != nil { return list, err } @@ -211,19 +211,18 @@ func (s *DefaultTopicStore) Create(fid int, topicName string, content string, ui return 0, ErrNoBody } - wcount := WordCount(content) // TODO: Move this statement into the topic store - res, err := s.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, wcount, uid) + res, err := s.create.Exec(fid, topicName, content, parsedContent, uid, ipaddress, WordCount(content), uid) if err != nil { return 0, err } - lastID, err := res.LastInsertId() if err != nil { return 0, err } + tid = int(lastID) - return int(lastID), Forums.AddTopic(int(lastID), uid, fid) + return tid, Forums.AddTopic(tid, uid, fid) } // ? - What is this? Do we need it? Should it be in the main store interface? diff --git a/common/word_filters.go b/common/word_filters.go index 5f766364..55b1deb7 100644 --- a/common/word_filters.go +++ b/common/word_filters.go @@ -38,12 +38,13 @@ type DefaultWordFilterStore struct { } func NewDefaultWordFilterStore(acc *qgen.Accumulator) (*DefaultWordFilterStore, error) { + wf := "word_filters" store := &DefaultWordFilterStore{ - getAll: acc.Select("word_filters").Columns("wfid, find, replacement").Prepare(), - create: acc.Insert("word_filters").Columns("find, replacement").Fields("?,?").Prepare(), - delete: acc.Delete("word_filters").Where("wfid = ?").Prepare(), - update: acc.Update("word_filters").Set("find = ?, replacement = ?").Where("wfid = ?").Prepare(), - count: acc.Count("word_filters").Prepare(), + getAll: acc.Select(wf).Columns("wfid,find,replacement").Prepare(), + create: acc.Insert(wf).Columns("find,replacement").Fields("?,?").Prepare(), + delete: acc.Delete(wf).Where("wfid = ?").Prepare(), + update: acc.Update(wf).Set("find = ?, replacement = ?").Where("wfid = ?").Prepare(), + count: acc.Count(wf).Prepare(), } // TODO: Should we initialise this elsewhere? if acc.FirstError() == nil { diff --git a/public/global.js b/public/global.js index cebecea5..375d7a39 100644 --- a/public/global.js +++ b/public/global.js @@ -869,10 +869,6 @@ function mainInit(){ }); // The time range selector for the time graphs in the Control Panel - /*$(".timeRangeSelector").change(function(){ - console.log("Changed the time range to " + this.options[this.selectedIndex].getAttribute("val")); - window.location = this.form.getAttribute("action")+"?timeRange=" + this.options[this.selectedIndex].getAttribute("val"); // Do a redirect as a form submission refuses to work properly - });*/ $(".autoSubmitRedirect").change(function(){ let elems = this.form.elements; let s = "";