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.
This commit is contained in:
Azareal 2019-10-28 17:46:14 +10:00
parent d9cffb2c5f
commit eb49dde076
15 changed files with 153 additions and 143 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = ?", "", ""),

View File

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

View File

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

View File

@ -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 = "";