diff --git a/cmd/query_gen/tables.go b/cmd/query_gen/tables.go
index f6918ae0..c2eb48c1 100644
--- a/cmd/query_gen/tables.go
+++ b/cmd/query_gen/tables.go
@@ -69,6 +69,22 @@ func createTables(adapter qgen.Adapter) error {
},
)
+ qgen.Install.CreateTable("users_groups_promotions", mysqlPre, mysqlCol,
+ []tC{
+ tC{"pid", "int", 0, false, true, ""},
+ tC{"from_gid", "int", 0, false, false, ""},
+ tC{"to_gid", "int", 0, false, false, ""},
+ tC{"two_way", "boolean",0,false,false,"0"}, // If a user no longer meets the requirements for this promotion then they will be demoted if this flag is set
+
+ // Requirements
+ tC{"level", "int", 0, false, false, ""},
+ tC{"minTime", "int", 0, false, false, ""}, // How long someone needs to have been in their current group before being promoted
+ },
+ []tblKey{
+ tblKey{"pid", "primary","",false},
+ },
+ )
+
qgen.Install.CreateTable("users_2fa_keys", mysqlPre, mysqlCol,
[]tC{
tC{"uid", "int", 0, false, false, ""},
diff --git a/common/activity_stream.go b/common/activity_stream.go
index dcf30f2f..60aff6e9 100644
--- a/common/activity_stream.go
+++ b/common/activity_stream.go
@@ -25,8 +25,8 @@ func NewDefaultActivityStream(acc *qgen.Accumulator) (*DefaultActivityStream, er
}, acc.FirstError()
}
-func (s *DefaultActivityStream) Add(alert Alert) (int, error) {
- res, err := s.add.Exec(alert.ActorID, alert.TargetUserID, alert.Event, alert.ElementType, alert.ElementID)
+func (s *DefaultActivityStream) Add(a Alert) (int, error) {
+ res, err := s.add.Exec(a.ActorID, a.TargetUserID, a.Event, a.ElementType, a.ElementID)
if err != nil {
return 0, err
}
@@ -36,7 +36,7 @@ func (s *DefaultActivityStream) Add(alert Alert) (int, error) {
}
func (s *DefaultActivityStream) Get(id int) (Alert, error) {
- var a = Alert{ASID: id}
+ a := Alert{ASID: id}
err := s.get.QueryRow(id).Scan(&a.ActorID, &a.TargetUserID, &a.Event, &a.ElementType, &a.ElementID, &a.CreatedAt)
return a, err
}
diff --git a/common/alerts.go b/common/alerts.go
index ab40b82e..0a7332de 100644
--- a/common/alerts.go
+++ b/common/alerts.go
@@ -96,7 +96,7 @@ func BuildAlert(alert Alert, user User /* The current user */) (out string, err
}
var url, area string
- var phraseName = "." + alert.ElementType
+ phraseName := "." + alert.ElementType
switch alert.ElementType {
case "topic":
topic, err := Topics.Get(alert.ElementID)
diff --git a/common/email.go b/common/email.go
index 3269ebb4..6cbb3869 100644
--- a/common/email.go
+++ b/common/email.go
@@ -16,7 +16,7 @@ type Email struct {
}
func SendValidationEmail(username string, email string, token string) error {
- var schema = "http"
+ schema := "http"
if Site.EnableSsl {
schema += "s"
}
diff --git a/common/email_store.go b/common/email_store.go
index 4d67178b..c1bc3f51 100644
--- a/common/email_store.go
+++ b/common/email_store.go
@@ -28,7 +28,7 @@ func NewDefaultEmailStore(acc *qgen.Accumulator) (*DefaultEmailStore, error) {
}
func (s *DefaultEmailStore) GetEmailsByUser(user *User) (emails []Email, err error) {
- email := Email{UserID: user.ID}
+ e := Email{UserID: user.ID}
rows, err := s.getEmailsByUser.Query(user.ID)
if err != nil {
return emails, err
@@ -36,15 +36,15 @@ func (s *DefaultEmailStore) GetEmailsByUser(user *User) (emails []Email, err err
defer rows.Close()
for rows.Next() {
- err := rows.Scan(&email.Email, &email.Validated, &email.Token)
+ err := rows.Scan(&e.Email, &e.Validated, &e.Token)
if err != nil {
return emails, err
}
- if email.Email == user.Email {
- email.Primary = true
+ if e.Email == user.Email {
+ e.Primary = true
}
- emails = append(emails, email)
+ emails = append(emails, e)
}
return emails, rows.Err()
}
diff --git a/common/files.go b/common/files.go
index 809297f2..4774f8ba 100644
--- a/common/files.go
+++ b/common/files.go
@@ -212,7 +212,7 @@ func (list SFileList) JSTmplInit() error {
fragset := tmpl.GetFrag(shortName)
if fragset != nil {
- var sfrags = []byte("let " + shortName + "_frags = [];\n")
+ sfrags := []byte("let " + shortName + "_frags = [];\n")
for _, frags := range fragset {
sfrags = append(sfrags, []byte(shortName+"_frags.push(`"+string(frags)+"`);\n")...)
}
@@ -229,7 +229,7 @@ func (list SFileList) JSTmplInit() error {
path = tmplName + ".js"
DebugLog("js path: ", path)
- var ext = filepath.Ext("/tmpl_client/" + path)
+ ext := filepath.Ext("/tmpl_client/" + path)
gzipData, err := CompressBytesGzip(data)
if err != nil {
return err
@@ -306,7 +306,7 @@ func (list SFileList) Add(path string, prefix string) error {
return err
}
- var ext = filepath.Ext(path)
+ ext := filepath.Ext(path)
path = strings.TrimPrefix(path, prefix)
gzipData, err := CompressBytesGzip(data)
if err != nil {
diff --git a/common/forum_perms.go b/common/forum_perms.go
index a2e09270..30d08305 100644
--- a/common/forum_perms.go
+++ b/common/forum_perms.go
@@ -229,8 +229,8 @@ func ForumPermsToGroupForumPreset(fperms *ForumPerms) string {
if !fperms.ViewTopic {
return "no_access"
}
- var canPost = (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply)
- var canModerate = (canPost && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic && fperms.MoveTopic)
+ canPost := (fperms.LikeItem && fperms.CreateTopic && fperms.CreateReply)
+ canModerate := (canPost && fperms.EditTopic && fperms.DeleteTopic && fperms.EditReply && fperms.DeleteReply && fperms.PinTopic && fperms.CloseTopic && fperms.MoveTopic)
if canModerate {
return "can_moderate"
}
diff --git a/common/forum_store.go b/common/forum_store.go
index 1cd469a5..b83ef3cb 100644
--- a/common/forum_store.go
+++ b/common/forum_store.go
@@ -329,14 +329,14 @@ func (s *MemoryForumStore) UpdateLastTopic(tid int, uid int, fid int) error {
return s.Reload(fid)
}
-func (s *MemoryForumStore) Create(forumName string, forumDesc string, active bool, preset string) (int, error) {
- if forumName == "" {
+func (s *MemoryForumStore) Create(name string, desc string, active bool, preset string) (int, error) {
+ if name == "" {
return 0, ErrBlankName
}
forumCreateMutex.Lock()
defer forumCreateMutex.Unlock()
- res, err := s.create.Exec(forumName, forumDesc, active, preset)
+ res, err := s.create.Exec(name, desc, active, preset)
if err != nil {
return 0, err
}
diff --git a/common/ip_search.go b/common/ip_search.go
index f411891d..4bb7d0ec 100644
--- a/common/ip_search.go
+++ b/common/ip_search.go
@@ -32,9 +32,8 @@ func NewDefaultIPSearcher() (*DefaultIPSearcher, error) {
func (searcher *DefaultIPSearcher) Lookup(ip string) (uids []int, err error) {
var uid int
- var reqUserList = make(map[int]bool)
-
- var runQuery = func(stmt *sql.Stmt) error {
+ reqUserList := make(map[int]bool)
+ runQuery := func(stmt *sql.Stmt) error {
rows, err := stmt.Query(ip)
if err != nil {
return err
diff --git a/common/pages.go b/common/pages.go
index 88cba86c..f5be8801 100644
--- a/common/pages.go
+++ b/common/pages.go
@@ -579,6 +579,20 @@ type PanelEditGroupPermsPage struct {
GlobalPerms []NameLangToggle
}
+type GroupPromotionExtend struct {
+ *GroupPromotion
+ FromGroup *Group
+ ToGroup *Group
+}
+
+type PanelEditGroupPromotionsPage struct {
+ *BasePanelPage
+ ID int
+ Name string
+ Promotions []*GroupPromotionExtend
+ Groups []*Group
+}
+
type BackupItem struct {
SQLURL string
diff --git a/common/password_reset.go b/common/password_reset.go
index fafb4121..7697cb01 100644
--- a/common/password_reset.go
+++ b/common/password_reset.go
@@ -42,7 +42,7 @@ func (r *DefaultPasswordResetter) ValidateToken(uid int, token string) error {
}
defer rows.Close()
- var success = false
+ success := false
for rows.Next() {
var rtoken string
err := rows.Scan(&rtoken)
diff --git a/common/pluginlangs.go b/common/pluginlangs.go
index f9915817..509d6eca 100644
--- a/common/pluginlangs.go
+++ b/common/pluginlangs.go
@@ -46,7 +46,6 @@ func InitPluginLangs() error {
for _, pluginLang := range pluginLangs {
pluginLang.Init()
}
-
pluginList, err := GetPluginFiles()
if err != nil {
return err
@@ -80,7 +79,7 @@ func InitPluginLangs() error {
return errors.New("Couldn't find a main file for plugin '" + pluginItem + "'")
}
- var ext = filepath.Ext(plugin.Main)
+ ext := filepath.Ext(plugin.Main)
pluginLang, err := ExtToPluginLang(ext)
if err != nil {
return err
diff --git a/common/promotions.go b/common/promotions.go
new file mode 100644
index 00000000..e91eb263
--- /dev/null
+++ b/common/promotions.go
@@ -0,0 +1,109 @@
+package common
+
+import (
+ "database/sql"
+
+ qgen "github.com/Azareal/Gosora/query_gen"
+)
+
+var GroupPromotions *DefaultGroupPromotionStore
+
+type GroupPromotion struct {
+ ID int
+ From int
+ To int
+ TwoWay bool
+
+ Level int
+ MinTime int
+}
+
+type GroupPromotionStore interface {
+ GetByGroup() ([]*GroupPromotion, error)
+ Get(id int) (*GroupPromotion, error)
+ PromoteIfEligible(u *User, level int) error
+ Delete(id int) error
+ Create(from int, to int, twoWay bool, level int) (int, error)
+}
+
+type DefaultGroupPromotionStore struct {
+ getByGroup *sql.Stmt
+ get *sql.Stmt
+ delete *sql.Stmt
+ create *sql.Stmt
+
+ getByUser *sql.Stmt
+ updateUser *sql.Stmt
+}
+
+func NewDefaultGroupPromotionStore(acc *qgen.Accumulator) (*DefaultGroupPromotionStore, error) {
+ ugp := "users_groups_promotions"
+ return &DefaultGroupPromotionStore{
+ getByGroup: acc.Select(ugp).Columns("pid, from_gid, to_gid, two_way, level, minTime").Where("from_gid=? OR to_gid=?").Prepare(),
+ get: acc.Select(ugp).Columns("from_gid, to_gid, two_way, level, minTime").Where("pid = ?").Prepare(),
+ delete: acc.Delete(ugp).Where("pid = ?").Prepare(),
+ create: acc.Insert(ugp).Columns("from_gid, to_gid, two_way, level, minTime").Fields("?,?,?,?,?").Prepare(),
+
+ getByUser: acc.Select(ugp).Columns("pid, to_gid, two_way, level, minTime").Where("from_gid=? AND level>=?").Orderby("level DESC").Limit("1").Prepare(),
+ updateUser: acc.Update("users").Set("group = ?").Where("level >= ?").Prepare(),
+ }, acc.FirstError()
+}
+
+func (s *DefaultGroupPromotionStore) GetByGroup(gid int) (gps []*GroupPromotion, err error) {
+ rows, err := s.getByGroup.Query(gid, gid)
+ if err != nil {
+ return nil, err
+ }
+ defer rows.Close()
+
+ for rows.Next() {
+ g := &GroupPromotion{}
+ err := rows.Scan(&g.ID, &g.From, &g.To, &g.TwoWay, &g.Level, &g.MinTime)
+ if err != nil {
+ return nil, err
+ }
+ gps = append(gps, g)
+ }
+ return gps, rows.Err()
+}
+
+// TODO: Cache the group promotions to avoid hitting the database as much
+func (s *DefaultGroupPromotionStore) Get(id int) (*GroupPromotion, error) {
+ /*g, err := s.cache.Get(id)
+ if err == nil {
+ return u, nil
+ }*/
+
+ g := &GroupPromotion{ID: id}
+ err := s.get.QueryRow(id).Scan(&g.From, &g.To, &g.TwoWay, &g.Level, &g.MinTime)
+ if err == nil {
+ //s.cache.Set(u)
+ }
+ return g, err
+}
+
+func (s *DefaultGroupPromotionStore) PromoteIfEligible(u *User, level int) error {
+ g := &GroupPromotion{From: u.Group}
+ err := s.getByUser.QueryRow(u.Group, level).Scan(&g.ID, &g.To, &g.TwoWay, &g.Level, &g.MinTime)
+ if err == sql.ErrNoRows {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ _, err = s.updateUser.Exec(g.To, g.Level)
+ return err
+}
+
+func (s *DefaultGroupPromotionStore) Delete(id int) error {
+ _, err := s.delete.Exec(id)
+ return err
+}
+
+func (s *DefaultGroupPromotionStore) Create(from int, to int, twoWay bool, level int) (int, error) {
+ res, err := s.create.Exec(from, to, twoWay, level, 0)
+ if err != nil {
+ return 0, err
+ }
+ lastID, err := res.LastInsertId()
+ return int(lastID), err
+}
diff --git a/common/statistics.go b/common/statistics.go
index 241b4b10..807741b6 100644
--- a/common/statistics.go
+++ b/common/statistics.go
@@ -18,15 +18,15 @@ func NewDefaultStatStore() *DefaultStatStore {
return &DefaultStatStore{}
}
-func (store *DefaultStatStore) LookupInt(name string, duration int, unit string) (int, error) {
+func (s *DefaultStatStore) LookupInt(name string, duration int, unit string) (int, error) {
switch name {
case "postCount":
- return store.countTable("replies", duration, unit)
+ return s.countTable("replies", duration, unit)
}
return 0, errors.New("The requested stat doesn't exist")
}
-func (store *DefaultStatStore) countTable(table string, duration int, unit string) (stat int, err error) {
+func (s *DefaultStatStore) countTable(table string, duration int, unit string) (stat int, err error) {
/*counter := qgen.NewAcc().Count("replies").DateCutoff("createdAt", 1, "day").Prepare()
if acc.FirstError() != nil {
return 0, acc.FirstError()
diff --git a/common/subscription.go b/common/subscription.go
index a15c03de..c48ebe31 100644
--- a/common/subscription.go
+++ b/common/subscription.go
@@ -1,7 +1,10 @@
package common
-import "database/sql"
-import "github.com/Azareal/Gosora/query_gen"
+import (
+ "database/sql"
+
+ qgen "github.com/Azareal/Gosora/query_gen"
+)
var Subscriptions SubscriptionStore
@@ -21,7 +24,7 @@ func NewDefaultSubscriptionStore() (*DefaultSubscriptionStore, error) {
}, acc.FirstError()
}
-func (store *DefaultSubscriptionStore) Add(uid int, elementID int, elementType string) error {
- _, err := store.add.Exec(uid, elementID, elementType)
+func (s *DefaultSubscriptionStore) Add(uid int, elementID int, elementType string) error {
+ _, err := s.add.Exec(uid, elementID, elementType)
return err
}
diff --git a/common/template_init.go b/common/template_init.go
index a7fac951..694b3440 100644
--- a/common/template_init.go
+++ b/common/template_init.go
@@ -289,14 +289,14 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
header.Title = name
return header
}
- tmpls := TItemHold(make(map[string]TItem))
- err = compileCommons(c, header, header2, forumList, tmpls)
+ t := TItemHold(make(map[string]TItem))
+ err = compileCommons(c, header, header2, forumList, t)
if err != nil {
return err
}
ppage := ProfilePage{htitle("User 526"), replyList, user, 0, 0} // TODO: Use the score from user to generate the currentScore and nextScore
- tmpls.Add("profile", "c.ProfilePage", ppage)
+ t.Add("profile", "c.ProfilePage", ppage)
var topicsList []*TopicsRow
topicsList = append(topicsList, &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 1, 0, "classname", 0, "", &user2, "", 0, &user3, "General", "/forum/general.2", nil})
@@ -331,38 +331,38 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
}
if typ == "1" {
- tmpls.Add(sp[0], sp[1], pi)
+ t.Add(sp[0], sp[1], pi)
} else {
- tmpls.AddStd(sp[0], sp[1], pi)
+ t.AddStd(sp[0], sp[1], pi)
}
}
- tmpls.AddStd("login", "c.Page", Page{htitle("Login Page"), tList, nil})
- tmpls.AddStd("register", "c.Page", Page{htitle("Registration Page"), tList, "nananana"})
- tmpls.AddStd("error", "c.ErrorPage", ErrorPage{htitle("Error"), "A problem has occurred in the system."})
+ t.AddStd("login", "c.Page", Page{htitle("Login Page"), tList, nil})
+ t.AddStd("register", "c.Page", Page{htitle("Registration Page"), tList, "nananana"})
+ t.AddStd("error", "c.ErrorPage", ErrorPage{htitle("Error"), "A problem has occurred in the system."})
ipSearchPage := IPSearchPage{htitle("IP Search"), map[int]*User{1: &user2}, "::1"}
- tmpls.AddStd("ip_search", "c.IPSearchPage", ipSearchPage)
+ t.AddStd("ip_search", "c.IPSearchPage", ipSearchPage)
var inter nobreak
accountPage := Account{header, "dashboard", "account_own_edit", inter}
- tmpls.AddStd("account", "c.Account", accountPage)
+ t.AddStd("account", "c.Account", accountPage)
parti := []*User{&user}
convo := &Conversation{1,user.ID,time.Now(),0,time.Now()}
convoItems := []ConvoViewRow{ConvoViewRow{&ConversationPost{1,1,"hey","",user.ID}, &user, "", 4, true}}
convoPage := ConvoViewPage{header, convo, convoItems, parti, Paginator{[]int{1}, 1, 1}}
- tmpls.AddStd("convo", "c.ConvoViewPage", convoPage)
+ t.AddStd("convo", "c.ConvoViewPage", convoPage)
convos := []*ConversationExtra{&ConversationExtra{&Conversation{},[]*User{&user}}}
convoListPage := ConvoListPage{header, convos, Paginator{[]int{1}, 1, 1}}
- tmpls.AddStd("convos", "c.ConvoListPage", convoListPage)
+ t.AddStd("convos", "c.ConvoListPage", convoListPage)
basePage := &BasePanelPage{header, PanelStats{}, "dashboard", ReportForumID}
- tmpls.AddStd("panel", "c.Panel", Panel{basePage, "panel_dashboard_right", "", "panel_dashboard", inter})
+ t.AddStd("panel", "c.Panel", Panel{basePage, "panel_dashboard_right", "", "panel_dashboard", inter})
ges := []GridElement{GridElement{"","", "", 1, "grid_istat", "", "", ""}}
- tmpls.AddStd("panel_dashboard", "c.DashGrids", DashGrids{ges,ges})
- //tmpls.AddStd("panel_analytics", "c.PanelAnalytics", Panel{basePage, "panel_dashboard_right","panel_dashboard", inter})
+ t.AddStd("panel_dashboard", "c.DashGrids", DashGrids{ges,ges})
+ //t.AddStd("panel_analytics", "c.PanelAnalytics", Panel{basePage, "panel_dashboard_right","panel_dashboard", inter})
writeTemplate := func(name string, content interface{}) {
log.Print("Writing template '" + name + "'")
@@ -409,7 +409,7 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
}
log.Print("Writing the templates")
- for name, titem := range tmpls {
+ for name, titem := range t {
log.Print("Writing " + name)
varList := make(map[string]tmpl.VarItem)
if titem.LoggedIn {
@@ -444,15 +444,15 @@ func CompileJSTemplates() error {
}
log.Printf("overriden: %+v\n", overriden)
- var config tmpl.CTemplateConfig
- config.Minify = Config.MinifyTemplates
- config.Debug = Dev.DebugMode
- config.SuperDebug = Dev.TemplateDebug
- config.SkipHandles = true
- config.SkipTmplPtrMap = true
- config.SkipInitBlock = false
- config.PackageName = "tmpl"
-
+ config := tmpl.CTemplateConfig{
+ Minify: Config.MinifyTemplates,
+ Debug: Dev.DebugMode,
+ SuperDebug: Dev.TemplateDebug,
+ SkipHandles: true,
+ SkipTmplPtrMap: true,
+ SkipInitBlock: false,
+ PackageName: "tmpl",
+ }
c := tmpl.NewCTemplateSet("js")
c.SetConfig(config)
c.SetBuildTags("!no_templategen")
@@ -509,10 +509,10 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
// TODO: Fix the import loop so we don't have to use this hack anymore
c.SetBuildTags("!no_templategen,tmplgentopic")
- tmpls := TItemHold(make(map[string]TItem))
+ t := TItemHold(make(map[string]TItem))
topicsRow := &TopicsRow{1, "topic-title", "Topic Title", "The topic content.", 1, false, false, now, now, user3.ID, 1, 1, "", "127.0.0.1", 1, 0, 1, 0, 1, "classname", 0, "", &user2, "", 0, &user3, "General", "/forum/general.2", nil}
- tmpls.AddStd("topics_topic", "c.TopicsRow", topicsRow)
+ t.AddStd("topics_topic", "c.TopicsRow", topicsRow)
poll := Poll{ID: 1, Type: 0, Options: map[int]string{0: "Nothing", 1: "Something"}, Results: map[int]int{0: 5, 1: 2}, QuickOptions: []PollOption{
PollOption{0, "Nothing"},
@@ -533,19 +533,25 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
header.Title = "Topic Name"
tpage := TopicPage{header, replyList, topic, &Forum{ID: 1, Name: "Hahaha"}, poll, Paginator{[]int{1}, 1, 1}}
tpage.Forum.Link = BuildForumURL(NameToSlug(tpage.Forum.Name), tpage.Forum.ID)
- tmpls.AddStd("topic_posts", "c.TopicPage", tpage)
- tmpls.AddStd("topic_alt_posts", "c.TopicPage", tpage)
+ t.AddStd("topic_posts", "c.TopicPage", tpage)
+ t.AddStd("topic_alt_posts", "c.TopicPage", tpage)
itemsPerPage := 25
_, page, lastPage := PageOffset(20, 1, itemsPerPage)
pageList := Paginate(page, lastPage, 5)
- tmpls.AddStd("paginator", "c.Paginator", Paginator{pageList, page, lastPage})
+ t.AddStd("paginator", "c.Paginator", Paginator{pageList, page, lastPage})
- tmpls.AddStd("topic_c_edit_post", "c.TopicCEditPost", TopicCEditPost{ID: 0, Source: "", Ref: ""})
- tmpls.AddStd("topic_c_attach_item", "c.TopicCAttachItem", TopicCAttachItem{ID: 1, ImgSrc: "", Path: "", FullPath: ""})
- tmpls.AddStd("topic_c_poll_input", "c.TopicCPollInput", TopicCPollInput{Index:0})
+ t.AddStd("topic_c_edit_post", "c.TopicCEditPost", TopicCEditPost{ID: 0, Source: "", Ref: ""})
+ t.AddStd("topic_c_attach_item", "c.TopicCAttachItem", TopicCAttachItem{ID: 1, ImgSrc: "", Path: "", FullPath: ""})
+ t.AddStd("topic_c_poll_input", "c.TopicCPollInput", TopicCPollInput{Index:0})
- tmpls.AddStd("notice", "string", "nonono")
+ parti := []*User{&user}
+ convo := &Conversation{1,user.ID,time.Now(),0,time.Now()}
+ convoItems := []ConvoViewRow{ConvoViewRow{&ConversationPost{1,1,"hey","",user.ID}, &user, "", 4, true}}
+ convoPage := ConvoViewPage{header, convo, convoItems, parti, Paginator{[]int{1}, 1, 1}}
+ t.AddStd("convo", "c.ConvoViewPage", convoPage)
+
+ t.AddStd("notice", "string", "nonono")
dirPrefix := "./tmpl_client/"
writeTemplate := func(name string, content string) {
@@ -568,7 +574,7 @@ func compileJSTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName stri
}
log.Print("Writing the templates")
- for name, titem := range tmpls {
+ for name, titem := range t {
log.Print("Writing " + name)
varList := make(map[string]tmpl.VarItem)
tmpl, err := c.Compile(name+".html", "templates/", titem.Expects, titem.ExpectsInt, varList)
@@ -802,22 +808,22 @@ func initDefaultTmplFuncMap() {
DefaultTemplateFuncMap = fmap
}
-func loadTemplates(tmpls *template.Template, themeName string) error {
- tmpls.Funcs(DefaultTemplateFuncMap)
- templateFiles, err := filepath.Glob("templates/*.html")
+func loadTemplates(t *template.Template, themeName string) error {
+ t.Funcs(DefaultTemplateFuncMap)
+ tFiles, err := filepath.Glob("templates/*.html")
if err != nil {
return err
}
- templateFileMap := make(map[string]int)
- for index, path := range templateFiles {
+ tFileMap := make(map[string]int)
+ for index, path := range tFiles {
path = strings.Replace(path, "\\", "/", -1)
log.Print("templateFile: ", path)
if skipCTmpl(path) {
log.Print("skipping")
continue
}
- templateFileMap[path] = index
+ tFileMap[path] = index
}
overrideFiles, err := filepath.Glob("templates/overrides/*.html")
@@ -831,13 +837,13 @@ func loadTemplates(tmpls *template.Template, themeName string) error {
log.Print("skipping")
continue
}
- index, ok := templateFileMap["templates/"+strings.TrimPrefix(path, "templates/overrides/")]
+ index, ok := tFileMap["templates/"+strings.TrimPrefix(path, "templates/overrides/")]
if !ok {
log.Print("not ok: templates/" + strings.TrimPrefix(path, "templates/overrides/"))
- templateFiles = append(templateFiles, path)
+ tFiles = append(tFiles, path)
continue
}
- templateFiles[index] = path
+ tFiles[index] = path
}
if themeName != "" {
@@ -852,18 +858,18 @@ func loadTemplates(tmpls *template.Template, themeName string) error {
log.Print("skipping")
continue
}
- index, ok := templateFileMap["templates/"+strings.TrimPrefix(path, "themes/"+themeName+"/overrides/")]
+ index, ok := tFileMap["templates/"+strings.TrimPrefix(path, "themes/"+themeName+"/overrides/")]
if !ok {
log.Print("not ok: templates/" + strings.TrimPrefix(path, "themes/"+themeName+"/overrides/"))
- templateFiles = append(templateFiles, path)
+ tFiles = append(tFiles, path)
continue
}
- templateFiles[index] = path
+ tFiles[index] = path
}
}
- template.Must(tmpls.ParseFiles(templateFiles...))
- template.Must(tmpls.ParseGlob("pages/*"))
+ template.Must(t.ParseFiles(tFiles...))
+ template.Must(t.ParseGlob("pages/*"))
return nil
}
diff --git a/common/thaw.go b/common/thaw.go
index 635c8d5e..503f80a0 100644
--- a/common/thaw.go
+++ b/common/thaw.go
@@ -18,23 +18,23 @@ type SingleServerThaw struct {
}
func NewSingleServerThaw() *SingleServerThaw {
- thaw := &SingleServerThaw{}
+ t := &SingleServerThaw{}
if Config.ServerCount == 1 {
- AddScheduledSecondTask(thaw.Tick)
+ AddScheduledSecondTask(t.Tick)
}
- return thaw
+ return t
}
-func (thaw *SingleServerThaw) Thawed() bool {
+func (t *SingleServerThaw) Thawed() bool {
if Config.ServerCount == 1 {
- return thaw.DefaultThaw.Thawed()
+ return t.DefaultThaw.Thawed()
}
return true
}
-func (thaw *SingleServerThaw) Thaw() {
+func (t *SingleServerThaw) Thaw() {
if Config.ServerCount == 1 {
- thaw.DefaultThaw.Thaw()
+ t.DefaultThaw.Thaw()
}
}
@@ -43,24 +43,24 @@ type DefaultThaw struct {
}
func NewDefaultThaw() *DefaultThaw {
- thaw := &DefaultThaw{}
- AddScheduledSecondTask(thaw.Tick)
- return thaw
+ t := &DefaultThaw{}
+ AddScheduledSecondTask(t.Tick)
+ return t
}
// Decrement the thawed counter once a second until it goes cold
-func (thaw *DefaultThaw) Tick() error {
- prior := thaw.thawed
+func (t *DefaultThaw) Tick() error {
+ prior := t.thawed
if prior > 0 {
- atomic.StoreInt64(&thaw.thawed, prior-1)
+ atomic.StoreInt64(&t.thawed, prior-1)
}
return nil
}
-func (thaw *DefaultThaw) Thawed() bool {
- return thaw.thawed > 0
+func (t *DefaultThaw) Thawed() bool {
+ return t.thawed > 0
}
-func (thaw *DefaultThaw) Thaw() {
- atomic.StoreInt64(&thaw.thawed, 5)
+func (t *DefaultThaw) Thaw() {
+ atomic.StoreInt64(&t.thawed, 5)
}
diff --git a/common/theme.go b/common/theme.go
index a2c11b34..ccc0a4a0 100644
--- a/common/theme.go
+++ b/common/theme.go
@@ -145,8 +145,8 @@ func (theme *Theme) AddThemeStaticFiles() error {
var ext = filepath.Ext(path)
if ext == ".css" && len(data) != 0 {
var b bytes.Buffer
- var pieces = strings.Split(path, "/")
- var filename = pieces[len(pieces)-1]
+ pieces := strings.Split(path, "/")
+ filename := pieces[len(pieces)-1]
// TODO: Prepare resource templates for each loaded langpack?
err = theme.ResourceTemplates.ExecuteTemplate(&b, filename, CSSData{Phrases: phraseMap})
if err != nil {
diff --git a/common/user.go b/common/user.go
index 3ab504e4..d5262e57 100644
--- a/common/user.go
+++ b/common/user.go
@@ -376,9 +376,15 @@ func (u *User) IncreasePostStats(wcount int, topic bool) (err error) {
return err
}
//log.Print(u.Score + baseScore + mod)
- //log.Print(getLevel(u.Score + baseScore + mod))
// TODO: Use a transaction to prevent level desyncs?
- _, err = userStmts.updateLevel.Exec(GetLevel(u.Score+baseScore+mod), u.ID)
+ level := GetLevel(u.Score+baseScore+mod)
+ //log.Print(level)
+ _, err = userStmts.updateLevel.Exec(level, u.ID)
+ if err != nil {
+ return err
+ }
+ err = GroupPromotions.PromoteIfEligible(u,level)
+ u.CacheRemove()
return err
}
@@ -413,6 +419,7 @@ func (u *User) DecreasePostStats(wcount int, topic bool) (err error) {
}
// TODO: Use a transaction to prevent level desyncs?
_, err = userStmts.updateLevel.Exec(GetLevel(u.Score-baseScore-mod), u.ID)
+ u.CacheRemove()
return err
}
diff --git a/common/ws_hub.go b/common/ws_hub.go
index 6385867b..b403795e 100644
--- a/common/ws_hub.go
+++ b/common/ws_hub.go
@@ -47,7 +47,7 @@ func (hub *WsHubImpl) Start() {
go func() {
for {
- var item = func(lock *sync.RWMutex, userMap map[int]*WSUser) {
+ item := func(lock *sync.RWMutex, userMap map[int]*WSUser) {
lock.RLock()
defer lock.RUnlock()
// TODO: Copy to temporary slice for less contention?
diff --git a/extend/guilds/lib/guilds.go b/extend/guilds/lib/guilds.go
index 95747cec..770477aa 100644
--- a/extend/guilds/lib/guilds.go
+++ b/extend/guilds/lib/guilds.go
@@ -408,7 +408,7 @@ func TopicCreatePreLoop(args ...interface{}) interface{} {
// TODO: Add privacy options
// TODO: Add support for multiple boards and add per-board simplified permissions
-// TODO: Take isJs into account for routes which expect JSON responses
+// TODO: Take js into account for routes which expect JSON responses
func ForumCheck(args ...interface{}) (skip bool, rerr c.RouteError) {
var r = args[1].(*http.Request)
var fid = args[3].(*int)
@@ -416,7 +416,7 @@ func ForumCheck(args ...interface{}) (skip bool, rerr c.RouteError) {
if forum.ParentType == "guild" {
var err error
- var w = args[0].(http.ResponseWriter)
+ w := args[0].(http.ResponseWriter)
guildItem, ok := r.Context().Value("guilds_current_group").(*Guild)
if !ok {
guildItem, err = Gstore.Get(forum.ParentID)
@@ -429,7 +429,7 @@ func ForumCheck(args ...interface{}) (skip bool, rerr c.RouteError) {
r = r.WithContext(context.WithValue(r.Context(), "guilds_current_group", guildItem))
}
- var user = args[2].(*c.User)
+ user := args[2].(*c.User)
var rank int
var posts int
var joinedAt string
@@ -474,15 +474,14 @@ func ForumCheck(args ...interface{}) (skip bool, rerr c.RouteError) {
// TODO: Override redirects? I don't think this is needed quite yet
func Widgets(args ...interface{}) interface{} {
- var zone = args[0].(string)
- var header = args[2].(*c.Header)
- var request = args[3].(*http.Request)
-
+ zone := args[0].(string)
+ header := args[2].(*c.Header)
+ request := args[3].(*http.Request)
if zone != "view_forum" {
return false
}
- var forum = args[1].(*c.Forum)
+ forum := args[1].(*c.Forum)
if forum.ParentType == "guild" {
// This is why I hate using contexts, all the daisy chains and interface casts x.x
guildItem, ok := request.Context().Value("guilds_current_group").(*Guild)
diff --git a/gen_router.go b/gen_router.go
index ce9d104f..bbc84904 100644
--- a/gen_router.go
+++ b/gen_router.go
@@ -102,6 +102,9 @@ var RouteMap = map[string]interface{}{
"panel.AnalyticsForums": panel.AnalyticsForums,
"panel.Groups": panel.Groups,
"panel.GroupsEdit": panel.GroupsEdit,
+ "panel.GroupsEditPromotions": panel.GroupsEditPromotions,
+ "panel.GroupsPromotionsCreateSubmit": panel.GroupsPromotionsCreateSubmit,
+ "panel.GroupsPromotionsDeleteSubmit": panel.GroupsPromotionsDeleteSubmit,
"panel.GroupsEditPerms": panel.GroupsEditPerms,
"panel.GroupsEditSubmit": panel.GroupsEditSubmit,
"panel.GroupsEditPermsSubmit": panel.GroupsEditPermsSubmit,
@@ -262,83 +265,86 @@ var routeMapEnum = map[string]int{
"panel.AnalyticsForums": 76,
"panel.Groups": 77,
"panel.GroupsEdit": 78,
- "panel.GroupsEditPerms": 79,
- "panel.GroupsEditSubmit": 80,
- "panel.GroupsEditPermsSubmit": 81,
- "panel.GroupsCreateSubmit": 82,
- "panel.Backups": 83,
- "panel.LogsRegs": 84,
- "panel.LogsMod": 85,
- "panel.Debug": 86,
- "panel.Dashboard": 87,
- "routes.AccountEdit": 88,
- "routes.AccountEditPassword": 89,
- "routes.AccountEditPasswordSubmit": 90,
- "routes.AccountEditAvatarSubmit": 91,
- "routes.AccountEditRevokeAvatarSubmit": 92,
- "routes.AccountEditUsernameSubmit": 93,
- "routes.AccountEditMFA": 94,
- "routes.AccountEditMFASetup": 95,
- "routes.AccountEditMFASetupSubmit": 96,
- "routes.AccountEditMFADisableSubmit": 97,
- "routes.AccountEditEmail": 98,
- "routes.AccountEditEmailTokenSubmit": 99,
- "routes.AccountLogins": 100,
- "routes.LevelList": 101,
- "routes.Convos": 102,
- "routes.ConvosCreate": 103,
- "routes.Convo": 104,
- "routes.ConvosCreateSubmit": 105,
- "routes.ConvosCreateReplySubmit": 106,
- "routes.ConvosDeleteReplySubmit": 107,
- "routes.ConvosEditReplySubmit": 108,
- "routes.ViewProfile": 109,
- "routes.BanUserSubmit": 110,
- "routes.UnbanUser": 111,
- "routes.ActivateUser": 112,
- "routes.IPSearch": 113,
- "routes.CreateTopicSubmit": 114,
- "routes.EditTopicSubmit": 115,
- "routes.DeleteTopicSubmit": 116,
- "routes.StickTopicSubmit": 117,
- "routes.UnstickTopicSubmit": 118,
- "routes.LockTopicSubmit": 119,
- "routes.UnlockTopicSubmit": 120,
- "routes.MoveTopicSubmit": 121,
- "routes.LikeTopicSubmit": 122,
- "routes.AddAttachToTopicSubmit": 123,
- "routes.RemoveAttachFromTopicSubmit": 124,
- "routes.ViewTopic": 125,
- "routes.CreateReplySubmit": 126,
- "routes.ReplyEditSubmit": 127,
- "routes.ReplyDeleteSubmit": 128,
- "routes.ReplyLikeSubmit": 129,
- "routes.AddAttachToReplySubmit": 130,
- "routes.RemoveAttachFromReplySubmit": 131,
- "routes.ProfileReplyCreateSubmit": 132,
- "routes.ProfileReplyEditSubmit": 133,
- "routes.ProfileReplyDeleteSubmit": 134,
- "routes.PollVote": 135,
- "routes.PollResults": 136,
- "routes.AccountLogin": 137,
- "routes.AccountRegister": 138,
- "routes.AccountLogout": 139,
- "routes.AccountLoginSubmit": 140,
- "routes.AccountLoginMFAVerify": 141,
- "routes.AccountLoginMFAVerifySubmit": 142,
- "routes.AccountRegisterSubmit": 143,
- "routes.AccountPasswordReset": 144,
- "routes.AccountPasswordResetSubmit": 145,
- "routes.AccountPasswordResetToken": 146,
- "routes.AccountPasswordResetTokenSubmit": 147,
- "routes.DynamicRoute": 148,
- "routes.UploadedFile": 149,
- "routes.StaticFile": 150,
- "routes.RobotsTxt": 151,
- "routes.SitemapXml": 152,
- "routes.OpenSearchXml": 153,
- "routes.BadRoute": 154,
- "routes.HTTPSRedirect": 155,
+ "panel.GroupsEditPromotions": 79,
+ "panel.GroupsPromotionsCreateSubmit": 80,
+ "panel.GroupsPromotionsDeleteSubmit": 81,
+ "panel.GroupsEditPerms": 82,
+ "panel.GroupsEditSubmit": 83,
+ "panel.GroupsEditPermsSubmit": 84,
+ "panel.GroupsCreateSubmit": 85,
+ "panel.Backups": 86,
+ "panel.LogsRegs": 87,
+ "panel.LogsMod": 88,
+ "panel.Debug": 89,
+ "panel.Dashboard": 90,
+ "routes.AccountEdit": 91,
+ "routes.AccountEditPassword": 92,
+ "routes.AccountEditPasswordSubmit": 93,
+ "routes.AccountEditAvatarSubmit": 94,
+ "routes.AccountEditRevokeAvatarSubmit": 95,
+ "routes.AccountEditUsernameSubmit": 96,
+ "routes.AccountEditMFA": 97,
+ "routes.AccountEditMFASetup": 98,
+ "routes.AccountEditMFASetupSubmit": 99,
+ "routes.AccountEditMFADisableSubmit": 100,
+ "routes.AccountEditEmail": 101,
+ "routes.AccountEditEmailTokenSubmit": 102,
+ "routes.AccountLogins": 103,
+ "routes.LevelList": 104,
+ "routes.Convos": 105,
+ "routes.ConvosCreate": 106,
+ "routes.Convo": 107,
+ "routes.ConvosCreateSubmit": 108,
+ "routes.ConvosCreateReplySubmit": 109,
+ "routes.ConvosDeleteReplySubmit": 110,
+ "routes.ConvosEditReplySubmit": 111,
+ "routes.ViewProfile": 112,
+ "routes.BanUserSubmit": 113,
+ "routes.UnbanUser": 114,
+ "routes.ActivateUser": 115,
+ "routes.IPSearch": 116,
+ "routes.CreateTopicSubmit": 117,
+ "routes.EditTopicSubmit": 118,
+ "routes.DeleteTopicSubmit": 119,
+ "routes.StickTopicSubmit": 120,
+ "routes.UnstickTopicSubmit": 121,
+ "routes.LockTopicSubmit": 122,
+ "routes.UnlockTopicSubmit": 123,
+ "routes.MoveTopicSubmit": 124,
+ "routes.LikeTopicSubmit": 125,
+ "routes.AddAttachToTopicSubmit": 126,
+ "routes.RemoveAttachFromTopicSubmit": 127,
+ "routes.ViewTopic": 128,
+ "routes.CreateReplySubmit": 129,
+ "routes.ReplyEditSubmit": 130,
+ "routes.ReplyDeleteSubmit": 131,
+ "routes.ReplyLikeSubmit": 132,
+ "routes.AddAttachToReplySubmit": 133,
+ "routes.RemoveAttachFromReplySubmit": 134,
+ "routes.ProfileReplyCreateSubmit": 135,
+ "routes.ProfileReplyEditSubmit": 136,
+ "routes.ProfileReplyDeleteSubmit": 137,
+ "routes.PollVote": 138,
+ "routes.PollResults": 139,
+ "routes.AccountLogin": 140,
+ "routes.AccountRegister": 141,
+ "routes.AccountLogout": 142,
+ "routes.AccountLoginSubmit": 143,
+ "routes.AccountLoginMFAVerify": 144,
+ "routes.AccountLoginMFAVerifySubmit": 145,
+ "routes.AccountRegisterSubmit": 146,
+ "routes.AccountPasswordReset": 147,
+ "routes.AccountPasswordResetSubmit": 148,
+ "routes.AccountPasswordResetToken": 149,
+ "routes.AccountPasswordResetTokenSubmit": 150,
+ "routes.DynamicRoute": 151,
+ "routes.UploadedFile": 152,
+ "routes.StaticFile": 153,
+ "routes.RobotsTxt": 154,
+ "routes.SitemapXml": 155,
+ "routes.OpenSearchXml": 156,
+ "routes.BadRoute": 157,
+ "routes.HTTPSRedirect": 158,
}
var reverseRouteMapEnum = map[int]string{
0: "routes.Overview",
@@ -420,83 +426,86 @@ var reverseRouteMapEnum = map[int]string{
76: "panel.AnalyticsForums",
77: "panel.Groups",
78: "panel.GroupsEdit",
- 79: "panel.GroupsEditPerms",
- 80: "panel.GroupsEditSubmit",
- 81: "panel.GroupsEditPermsSubmit",
- 82: "panel.GroupsCreateSubmit",
- 83: "panel.Backups",
- 84: "panel.LogsRegs",
- 85: "panel.LogsMod",
- 86: "panel.Debug",
- 87: "panel.Dashboard",
- 88: "routes.AccountEdit",
- 89: "routes.AccountEditPassword",
- 90: "routes.AccountEditPasswordSubmit",
- 91: "routes.AccountEditAvatarSubmit",
- 92: "routes.AccountEditRevokeAvatarSubmit",
- 93: "routes.AccountEditUsernameSubmit",
- 94: "routes.AccountEditMFA",
- 95: "routes.AccountEditMFASetup",
- 96: "routes.AccountEditMFASetupSubmit",
- 97: "routes.AccountEditMFADisableSubmit",
- 98: "routes.AccountEditEmail",
- 99: "routes.AccountEditEmailTokenSubmit",
- 100: "routes.AccountLogins",
- 101: "routes.LevelList",
- 102: "routes.Convos",
- 103: "routes.ConvosCreate",
- 104: "routes.Convo",
- 105: "routes.ConvosCreateSubmit",
- 106: "routes.ConvosCreateReplySubmit",
- 107: "routes.ConvosDeleteReplySubmit",
- 108: "routes.ConvosEditReplySubmit",
- 109: "routes.ViewProfile",
- 110: "routes.BanUserSubmit",
- 111: "routes.UnbanUser",
- 112: "routes.ActivateUser",
- 113: "routes.IPSearch",
- 114: "routes.CreateTopicSubmit",
- 115: "routes.EditTopicSubmit",
- 116: "routes.DeleteTopicSubmit",
- 117: "routes.StickTopicSubmit",
- 118: "routes.UnstickTopicSubmit",
- 119: "routes.LockTopicSubmit",
- 120: "routes.UnlockTopicSubmit",
- 121: "routes.MoveTopicSubmit",
- 122: "routes.LikeTopicSubmit",
- 123: "routes.AddAttachToTopicSubmit",
- 124: "routes.RemoveAttachFromTopicSubmit",
- 125: "routes.ViewTopic",
- 126: "routes.CreateReplySubmit",
- 127: "routes.ReplyEditSubmit",
- 128: "routes.ReplyDeleteSubmit",
- 129: "routes.ReplyLikeSubmit",
- 130: "routes.AddAttachToReplySubmit",
- 131: "routes.RemoveAttachFromReplySubmit",
- 132: "routes.ProfileReplyCreateSubmit",
- 133: "routes.ProfileReplyEditSubmit",
- 134: "routes.ProfileReplyDeleteSubmit",
- 135: "routes.PollVote",
- 136: "routes.PollResults",
- 137: "routes.AccountLogin",
- 138: "routes.AccountRegister",
- 139: "routes.AccountLogout",
- 140: "routes.AccountLoginSubmit",
- 141: "routes.AccountLoginMFAVerify",
- 142: "routes.AccountLoginMFAVerifySubmit",
- 143: "routes.AccountRegisterSubmit",
- 144: "routes.AccountPasswordReset",
- 145: "routes.AccountPasswordResetSubmit",
- 146: "routes.AccountPasswordResetToken",
- 147: "routes.AccountPasswordResetTokenSubmit",
- 148: "routes.DynamicRoute",
- 149: "routes.UploadedFile",
- 150: "routes.StaticFile",
- 151: "routes.RobotsTxt",
- 152: "routes.SitemapXml",
- 153: "routes.OpenSearchXml",
- 154: "routes.BadRoute",
- 155: "routes.HTTPSRedirect",
+ 79: "panel.GroupsEditPromotions",
+ 80: "panel.GroupsPromotionsCreateSubmit",
+ 81: "panel.GroupsPromotionsDeleteSubmit",
+ 82: "panel.GroupsEditPerms",
+ 83: "panel.GroupsEditSubmit",
+ 84: "panel.GroupsEditPermsSubmit",
+ 85: "panel.GroupsCreateSubmit",
+ 86: "panel.Backups",
+ 87: "panel.LogsRegs",
+ 88: "panel.LogsMod",
+ 89: "panel.Debug",
+ 90: "panel.Dashboard",
+ 91: "routes.AccountEdit",
+ 92: "routes.AccountEditPassword",
+ 93: "routes.AccountEditPasswordSubmit",
+ 94: "routes.AccountEditAvatarSubmit",
+ 95: "routes.AccountEditRevokeAvatarSubmit",
+ 96: "routes.AccountEditUsernameSubmit",
+ 97: "routes.AccountEditMFA",
+ 98: "routes.AccountEditMFASetup",
+ 99: "routes.AccountEditMFASetupSubmit",
+ 100: "routes.AccountEditMFADisableSubmit",
+ 101: "routes.AccountEditEmail",
+ 102: "routes.AccountEditEmailTokenSubmit",
+ 103: "routes.AccountLogins",
+ 104: "routes.LevelList",
+ 105: "routes.Convos",
+ 106: "routes.ConvosCreate",
+ 107: "routes.Convo",
+ 108: "routes.ConvosCreateSubmit",
+ 109: "routes.ConvosCreateReplySubmit",
+ 110: "routes.ConvosDeleteReplySubmit",
+ 111: "routes.ConvosEditReplySubmit",
+ 112: "routes.ViewProfile",
+ 113: "routes.BanUserSubmit",
+ 114: "routes.UnbanUser",
+ 115: "routes.ActivateUser",
+ 116: "routes.IPSearch",
+ 117: "routes.CreateTopicSubmit",
+ 118: "routes.EditTopicSubmit",
+ 119: "routes.DeleteTopicSubmit",
+ 120: "routes.StickTopicSubmit",
+ 121: "routes.UnstickTopicSubmit",
+ 122: "routes.LockTopicSubmit",
+ 123: "routes.UnlockTopicSubmit",
+ 124: "routes.MoveTopicSubmit",
+ 125: "routes.LikeTopicSubmit",
+ 126: "routes.AddAttachToTopicSubmit",
+ 127: "routes.RemoveAttachFromTopicSubmit",
+ 128: "routes.ViewTopic",
+ 129: "routes.CreateReplySubmit",
+ 130: "routes.ReplyEditSubmit",
+ 131: "routes.ReplyDeleteSubmit",
+ 132: "routes.ReplyLikeSubmit",
+ 133: "routes.AddAttachToReplySubmit",
+ 134: "routes.RemoveAttachFromReplySubmit",
+ 135: "routes.ProfileReplyCreateSubmit",
+ 136: "routes.ProfileReplyEditSubmit",
+ 137: "routes.ProfileReplyDeleteSubmit",
+ 138: "routes.PollVote",
+ 139: "routes.PollResults",
+ 140: "routes.AccountLogin",
+ 141: "routes.AccountRegister",
+ 142: "routes.AccountLogout",
+ 143: "routes.AccountLoginSubmit",
+ 144: "routes.AccountLoginMFAVerify",
+ 145: "routes.AccountLoginMFAVerifySubmit",
+ 146: "routes.AccountRegisterSubmit",
+ 147: "routes.AccountPasswordReset",
+ 148: "routes.AccountPasswordResetSubmit",
+ 149: "routes.AccountPasswordResetToken",
+ 150: "routes.AccountPasswordResetTokenSubmit",
+ 151: "routes.DynamicRoute",
+ 152: "routes.UploadedFile",
+ 153: "routes.StaticFile",
+ 154: "routes.RobotsTxt",
+ 155: "routes.SitemapXml",
+ 156: "routes.OpenSearchXml",
+ 157: "routes.BadRoute",
+ 158: "routes.HTTPSRedirect",
}
var osMapEnum = map[string]int{
"unknown": 0,
@@ -654,7 +663,7 @@ type HTTPSRedirect struct {}
func (red *HTTPSRedirect) ServeHTTP(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Connection", "close")
- counters.RouteViewCounter.Bump(155)
+ counters.RouteViewCounter.Bump(158)
dest := "https://" + req.Host + req.URL.String()
http.Redirect(w, req, dest, http.StatusTemporaryRedirect)
}
@@ -863,7 +872,7 @@ func (r *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
counters.GlobalViewCounter.Bump()
if prefix == "/s" { //old prefix: /static
- counters.RouteViewCounter.Bump(150)
+ counters.RouteViewCounter.Bump(153)
req.URL.Path += extraData
routes.StaticFile(w, req)
return
@@ -1611,8 +1620,27 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
case "/panel/groups/edit/":
counters.RouteViewCounter.Bump(78)
err = panel.GroupsEdit(w,req,user,extraData)
- case "/panel/groups/edit/perms/":
+ case "/panel/groups/edit/promotions/":
counters.RouteViewCounter.Bump(79)
+ err = panel.GroupsEditPromotions(w,req,user,extraData)
+ case "/panel/groups/promotions/create/submit/":
+ err = c.NoSessionMismatch(w,req,user)
+ if err != nil {
+ return err
+ }
+
+ counters.RouteViewCounter.Bump(80)
+ err = panel.GroupsPromotionsCreateSubmit(w,req,user,extraData)
+ case "/panel/groups/promotions/delete/submit/":
+ err = c.NoSessionMismatch(w,req,user)
+ if err != nil {
+ return err
+ }
+
+ counters.RouteViewCounter.Bump(81)
+ err = panel.GroupsPromotionsDeleteSubmit(w,req,user,extraData)
+ case "/panel/groups/edit/perms/":
+ counters.RouteViewCounter.Bump(82)
err = panel.GroupsEditPerms(w,req,user,extraData)
case "/panel/groups/edit/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1620,7 +1648,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(80)
+ counters.RouteViewCounter.Bump(83)
err = panel.GroupsEditSubmit(w,req,user,extraData)
case "/panel/groups/edit/perms/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1628,7 +1656,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(81)
+ counters.RouteViewCounter.Bump(84)
err = panel.GroupsEditPermsSubmit(w,req,user,extraData)
case "/panel/groups/create/":
err = c.NoSessionMismatch(w,req,user)
@@ -1636,7 +1664,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(82)
+ counters.RouteViewCounter.Bump(85)
err = panel.GroupsCreateSubmit(w,req,user)
case "/panel/backups/":
err = c.SuperAdminOnly(w,req,user)
@@ -1650,13 +1678,13 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
w.Header().Del("Content-Type")
w.Header().Del("Content-Encoding")
}
- counters.RouteViewCounter.Bump(83)
+ counters.RouteViewCounter.Bump(86)
err = panel.Backups(w,req,user,extraData)
case "/panel/logs/regs/":
- counters.RouteViewCounter.Bump(84)
+ counters.RouteViewCounter.Bump(87)
err = panel.LogsRegs(w,req,user)
case "/panel/logs/mod/":
- counters.RouteViewCounter.Bump(85)
+ counters.RouteViewCounter.Bump(88)
err = panel.LogsMod(w,req,user)
case "/panel/debug/":
err = c.AdminOnly(w,req,user)
@@ -1664,10 +1692,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(86)
+ counters.RouteViewCounter.Bump(89)
err = panel.Debug(w,req,user)
default:
- counters.RouteViewCounter.Bump(87)
+ counters.RouteViewCounter.Bump(90)
err = panel.Dashboard(w,req,user)
}
case "/user":
@@ -1678,7 +1706,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(88)
+ counters.RouteViewCounter.Bump(91)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1690,7 +1718,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(89)
+ counters.RouteViewCounter.Bump(92)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1707,7 +1735,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(90)
+ counters.RouteViewCounter.Bump(93)
err = routes.AccountEditPasswordSubmit(w,req,user)
case "/user/edit/avatar/submit/":
err = c.MemberOnly(w,req,user)
@@ -1724,7 +1752,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(91)
+ counters.RouteViewCounter.Bump(94)
err = routes.AccountEditAvatarSubmit(w,req,user)
case "/user/edit/avatar/revoke/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1737,7 +1765,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(92)
+ counters.RouteViewCounter.Bump(95)
err = routes.AccountEditRevokeAvatarSubmit(w,req,user)
case "/user/edit/username/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1750,7 +1778,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(93)
+ counters.RouteViewCounter.Bump(96)
err = routes.AccountEditUsernameSubmit(w,req,user)
case "/user/edit/mfa/":
err = c.MemberOnly(w,req,user)
@@ -1758,7 +1786,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(94)
+ counters.RouteViewCounter.Bump(97)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1770,7 +1798,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(95)
+ counters.RouteViewCounter.Bump(98)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1787,7 +1815,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(96)
+ counters.RouteViewCounter.Bump(99)
err = routes.AccountEditMFASetupSubmit(w,req,user)
case "/user/edit/mfa/disable/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1800,7 +1828,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(97)
+ counters.RouteViewCounter.Bump(100)
err = routes.AccountEditMFADisableSubmit(w,req,user)
case "/user/edit/email/":
err = c.MemberOnly(w,req,user)
@@ -1808,14 +1836,14 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(98)
+ counters.RouteViewCounter.Bump(101)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
}
err = routes.AccountEditEmail(w,req,user,head)
case "/user/edit/token/":
- counters.RouteViewCounter.Bump(99)
+ counters.RouteViewCounter.Bump(102)
err = routes.AccountEditEmailTokenSubmit(w,req,user,extraData)
case "/user/edit/logins/":
err = c.MemberOnly(w,req,user)
@@ -1823,7 +1851,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(100)
+ counters.RouteViewCounter.Bump(103)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1835,7 +1863,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(101)
+ counters.RouteViewCounter.Bump(104)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1847,7 +1875,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(102)
+ counters.RouteViewCounter.Bump(105)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1859,7 +1887,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(103)
+ counters.RouteViewCounter.Bump(106)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1871,7 +1899,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(104)
+ counters.RouteViewCounter.Bump(107)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1888,7 +1916,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(105)
+ counters.RouteViewCounter.Bump(108)
err = routes.ConvosCreateSubmit(w,req,user)
case "/user/convo/create/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1901,7 +1929,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(106)
+ counters.RouteViewCounter.Bump(109)
err = routes.ConvosCreateReplySubmit(w,req,user,extraData)
case "/user/convo/delete/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1914,7 +1942,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(107)
+ counters.RouteViewCounter.Bump(110)
err = routes.ConvosDeleteReplySubmit(w,req,user,extraData)
case "/user/convo/edit/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -1927,11 +1955,11 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(108)
+ counters.RouteViewCounter.Bump(111)
err = routes.ConvosEditReplySubmit(w,req,user,extraData)
default:
req.URL.Path += extraData
- counters.RouteViewCounter.Bump(109)
+ counters.RouteViewCounter.Bump(112)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -1951,7 +1979,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(110)
+ counters.RouteViewCounter.Bump(113)
err = routes.BanUserSubmit(w,req,user,extraData)
case "/users/unban/":
err = c.NoSessionMismatch(w,req,user)
@@ -1964,7 +1992,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(111)
+ counters.RouteViewCounter.Bump(114)
err = routes.UnbanUser(w,req,user,extraData)
case "/users/activate/":
err = c.NoSessionMismatch(w,req,user)
@@ -1977,7 +2005,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(112)
+ counters.RouteViewCounter.Bump(115)
err = routes.ActivateUser(w,req,user,extraData)
case "/users/ips/":
err = c.MemberOnly(w,req,user)
@@ -1985,7 +2013,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(113)
+ counters.RouteViewCounter.Bump(116)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2009,7 +2037,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(114)
+ counters.RouteViewCounter.Bump(117)
err = routes.CreateTopicSubmit(w,req,user)
case "/topic/edit/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2022,7 +2050,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(115)
+ counters.RouteViewCounter.Bump(118)
err = routes.EditTopicSubmit(w,req,user,extraData)
case "/topic/delete/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2036,7 +2064,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
}
req.URL.Path += extraData
- counters.RouteViewCounter.Bump(116)
+ counters.RouteViewCounter.Bump(119)
err = routes.DeleteTopicSubmit(w,req,user)
case "/topic/stick/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2049,7 +2077,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(117)
+ counters.RouteViewCounter.Bump(120)
err = routes.StickTopicSubmit(w,req,user,extraData)
case "/topic/unstick/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2062,7 +2090,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(118)
+ counters.RouteViewCounter.Bump(121)
err = routes.UnstickTopicSubmit(w,req,user,extraData)
case "/topic/lock/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2076,7 +2104,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
}
req.URL.Path += extraData
- counters.RouteViewCounter.Bump(119)
+ counters.RouteViewCounter.Bump(122)
err = routes.LockTopicSubmit(w,req,user)
case "/topic/unlock/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2089,7 +2117,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(120)
+ counters.RouteViewCounter.Bump(123)
err = routes.UnlockTopicSubmit(w,req,user,extraData)
case "/topic/move/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2102,7 +2130,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(121)
+ counters.RouteViewCounter.Bump(124)
err = routes.MoveTopicSubmit(w,req,user,extraData)
case "/topic/like/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2115,7 +2143,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(122)
+ counters.RouteViewCounter.Bump(125)
err = routes.LikeTopicSubmit(w,req,user,extraData)
case "/topic/attach/add/submit/":
err = c.MemberOnly(w,req,user)
@@ -2132,7 +2160,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(123)
+ counters.RouteViewCounter.Bump(126)
err = routes.AddAttachToTopicSubmit(w,req,user,extraData)
case "/topic/attach/remove/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2145,10 +2173,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(124)
+ counters.RouteViewCounter.Bump(127)
err = routes.RemoveAttachFromTopicSubmit(w,req,user,extraData)
default:
- counters.RouteViewCounter.Bump(125)
+ counters.RouteViewCounter.Bump(128)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2172,7 +2200,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(126)
+ counters.RouteViewCounter.Bump(129)
err = routes.CreateReplySubmit(w,req,user)
case "/reply/edit/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2185,7 +2213,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(127)
+ counters.RouteViewCounter.Bump(130)
err = routes.ReplyEditSubmit(w,req,user,extraData)
case "/reply/delete/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2198,7 +2226,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(128)
+ counters.RouteViewCounter.Bump(131)
err = routes.ReplyDeleteSubmit(w,req,user,extraData)
case "/reply/like/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2211,7 +2239,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(129)
+ counters.RouteViewCounter.Bump(132)
err = routes.ReplyLikeSubmit(w,req,user,extraData)
case "/reply/attach/add/submit/":
err = c.MemberOnly(w,req,user)
@@ -2228,7 +2256,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(130)
+ counters.RouteViewCounter.Bump(133)
err = routes.AddAttachToReplySubmit(w,req,user,extraData)
case "/reply/attach/remove/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2241,7 +2269,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(131)
+ counters.RouteViewCounter.Bump(134)
err = routes.RemoveAttachFromReplySubmit(w,req,user,extraData)
}
case "/profile":
@@ -2257,7 +2285,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(132)
+ counters.RouteViewCounter.Bump(135)
err = routes.ProfileReplyCreateSubmit(w,req,user)
case "/profile/reply/edit/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2270,7 +2298,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(133)
+ counters.RouteViewCounter.Bump(136)
err = routes.ProfileReplyEditSubmit(w,req,user,extraData)
case "/profile/reply/delete/submit/":
err = c.NoSessionMismatch(w,req,user)
@@ -2283,7 +2311,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(134)
+ counters.RouteViewCounter.Bump(137)
err = routes.ProfileReplyDeleteSubmit(w,req,user,extraData)
}
case "/poll":
@@ -2299,23 +2327,23 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(135)
+ counters.RouteViewCounter.Bump(138)
err = routes.PollVote(w,req,user,extraData)
case "/poll/results/":
- counters.RouteViewCounter.Bump(136)
+ counters.RouteViewCounter.Bump(139)
err = routes.PollResults(w,req,user,extraData)
}
case "/accounts":
switch(req.URL.Path) {
case "/accounts/login/":
- counters.RouteViewCounter.Bump(137)
+ counters.RouteViewCounter.Bump(140)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
}
err = routes.AccountLogin(w,req,user,head)
case "/accounts/create/":
- counters.RouteViewCounter.Bump(138)
+ counters.RouteViewCounter.Bump(141)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2332,7 +2360,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(139)
+ counters.RouteViewCounter.Bump(142)
err = routes.AccountLogout(w,req,user)
case "/accounts/login/submit/":
err = c.ParseForm(w,req,user)
@@ -2340,10 +2368,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(140)
+ counters.RouteViewCounter.Bump(143)
err = routes.AccountLoginSubmit(w,req,user)
case "/accounts/mfa_verify/":
- counters.RouteViewCounter.Bump(141)
+ counters.RouteViewCounter.Bump(144)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2355,7 +2383,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(142)
+ counters.RouteViewCounter.Bump(145)
err = routes.AccountLoginMFAVerifySubmit(w,req,user)
case "/accounts/create/submit/":
err = c.ParseForm(w,req,user)
@@ -2363,10 +2391,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(143)
+ counters.RouteViewCounter.Bump(146)
err = routes.AccountRegisterSubmit(w,req,user)
case "/accounts/password-reset/":
- counters.RouteViewCounter.Bump(144)
+ counters.RouteViewCounter.Bump(147)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2378,10 +2406,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(145)
+ counters.RouteViewCounter.Bump(148)
err = routes.AccountPasswordResetSubmit(w,req,user)
case "/accounts/password-reset/token/":
- counters.RouteViewCounter.Bump(146)
+ counters.RouteViewCounter.Bump(149)
head, err := c.UserCheck(w,req,&user)
if err != nil {
return err
@@ -2393,7 +2421,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
return err
}
- counters.RouteViewCounter.Bump(147)
+ counters.RouteViewCounter.Bump(150)
err = routes.AccountPasswordResetTokenSubmit(w,req,user)
}
/*case "/sitemaps": // TODO: Count these views
@@ -2410,7 +2438,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
h.Del("Content-Type")
h.Del("Content-Encoding")
}
- counters.RouteViewCounter.Bump(149)
+ counters.RouteViewCounter.Bump(152)
req.URL.Path += extraData
// TODO: Find a way to propagate errors up from this?
r.UploadHandler(w,req) // TODO: Count these views
@@ -2420,7 +2448,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
// TODO: Add support for favicons and robots.txt files
switch(extraData) {
case "robots.txt":
- counters.RouteViewCounter.Bump(151)
+ counters.RouteViewCounter.Bump(154)
return routes.RobotsTxt(w,req)
case "favicon.ico":
gzw, ok := w.(c.GzipResponseWriter)
@@ -2434,10 +2462,10 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
routes.StaticFile(w,req)
return nil
case "opensearch.xml":
- counters.RouteViewCounter.Bump(153)
+ counters.RouteViewCounter.Bump(156)
return routes.OpenSearchXml(w,req)
/*case "sitemap.xml":
- counters.RouteViewCounter.Bump(152)
+ counters.RouteViewCounter.Bump(155)
return routes.SitemapXml(w,req)*/
}
return c.NotFound(w,req,nil)
@@ -2448,7 +2476,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
r.RUnlock()
if ok {
- counters.RouteViewCounter.Bump(148) // TODO: Be more specific about *which* dynamic route it is
+ counters.RouteViewCounter.Bump(151) // TODO: Be more specific about *which* dynamic route it is
req.URL.Path += extraData
return handle(w,req,user)
}
@@ -2459,7 +2487,7 @@ func (r *GenRouter) routeSwitch(w http.ResponseWriter, req *http.Request, user c
} else {
r.DumpRequest(req,"Bad Route")
}
- counters.RouteViewCounter.Bump(154)
+ counters.RouteViewCounter.Bump(157)
return c.NotFound(w,req,nil)
}
return err
diff --git a/gen_tables.go b/gen_tables.go
index 44475f3c..e6ea0b27 100644
--- a/gen_tables.go
+++ b/gen_tables.go
@@ -2,24 +2,27 @@
package main
var dbTablePrimaryKeys = map[string]string{
- "users_groups":"gid",
- "users_avatar_queue":"uid",
+ "polls":"pollID",
+ "widgets":"wid",
+ "users_groups_promotions":"pid",
+ "topics":"tid",
+ "attachments":"attachID",
"word_filters":"wfid",
+ "menu_items":"miid",
+ "users_groups":"gid",
+ "users_2fa_keys":"uid",
+ "activity_stream":"asid",
+ "conversations_posts":"pid",
"menus":"mid",
"login_logs":"lid",
- "polls":"pollID",
- "activity_stream":"asid",
- "pages":"pid",
"forums":"fid",
- "topics":"tid",
+ "users_replies":"rid",
+ "conversations":"cid",
"replies":"rid",
- "attachments":"attachID",
"revisions":"reviseID",
- "users_2fa_keys":"uid",
- "users_groups_scheduler":"uid",
- "menu_items":"miid",
+ "pages":"pid",
"registration_logs":"rlid",
"users":"uid",
- "users_replies":"rid",
- "widgets":"wid",
+ "users_groups_scheduler":"uid",
+ "users_avatar_queue":"uid",
}
diff --git a/main.go b/main.go
index 121a3aa6..4bb31425 100644
--- a/main.go
+++ b/main.go
@@ -138,6 +138,10 @@ func storeInit() (err error) {
if err != nil {
return errors.WithStack(err)
}
+ c.GroupPromotions, err = c.NewDefaultGroupPromotionStore(acc)
+ if err != nil {
+ return errors.WithStack(err)
+ }
err = phrases.InitPhrases(c.Site.Language)
if err != nil {
diff --git a/patcher/patches.go b/patcher/patches.go
index 1c81b4df..e6b14758 100644
--- a/patcher/patches.go
+++ b/patcher/patches.go
@@ -37,6 +37,7 @@ func init() {
addPatch(21, patch21)
addPatch(22, patch22)
addPatch(23, patch23)
+ addPatch(24, patch24)
}
func patch0(scanner *bufio.Scanner) (err error) {
@@ -711,4 +712,26 @@ func patch23(scanner *bufio.Scanner) error {
tC{"cid", "int", 0, false, false, ""},
}, nil,
))
+}
+
+func patch24(scanner *bufio.Scanner) error {
+ err := execStmt(qgen.Builder.DropTable("users_groups_promotions"))
+ if err != nil {
+ return err
+ }
+ return execStmt(qgen.Builder.CreateTable("users_groups_promotions", "", "",
+ []tC{
+ tC{"pid", "int", 0, false, true, ""},
+ tC{"from_gid", "int", 0, false, false, ""},
+ tC{"to_gid", "int", 0, false, false, ""},
+ tC{"two_way", "boolean",0,false,false,"0"}, // If a user no longer meets the requirements for this promotion then they will be demoted if this flag is set
+
+ // Requirements
+ tC{"level", "int", 0, false, false, ""},
+ tC{"minTime", "int", 0, false, false, ""}, // How long someone needs to have been in their current group before being promoted
+ },
+ []tblKey{
+ tblKey{"pid", "primary","",false},
+ },
+ ))
}
\ No newline at end of file
diff --git a/router_gen/routes.go b/router_gen/routes.go
index 813608b7..5b2a79d0 100644
--- a/router_gen/routes.go
+++ b/router_gen/routes.go
@@ -248,6 +248,9 @@ func panelRoutes() *RouteGroup {
View("panel.Groups", "/panel/groups/"),
View("panel.GroupsEdit", "/panel/groups/edit/", "extraData"),
+ View("panel.GroupsEditPromotions", "/panel/groups/edit/promotions/", "extraData"),
+ Action("panel.GroupsPromotionsCreateSubmit", "/panel/groups/promotions/create/submit/","extraData"),
+ Action("panel.GroupsPromotionsDeleteSubmit", "/panel/groups/promotions/delete/submit/","extraData"),
View("panel.GroupsEditPerms", "/panel/groups/edit/perms/", "extraData"),
Action("panel.GroupsEditSubmit", "/panel/groups/edit/submit/", "extraData"),
Action("panel.GroupsEditPermsSubmit", "/panel/groups/edit/perms/submit/", "extraData"),
diff --git a/routes/convos.go b/routes/convos.go
index 2f108b69..42428f8c 100644
--- a/routes/convos.go
+++ b/routes/convos.go
@@ -263,7 +263,7 @@ func ConvosEditReplySubmit(w http.ResponseWriter, r *http.Request, user c.User,
if err != nil {
return c.LocalError(p.GetErrorPhrase("id_must_be_integer"), w, r, user)
}
- isJs := (r.PostFormValue("js") == "1")
+ js := (r.PostFormValue("js") == "1")
post := &c.ConversationPost{ID: cpid}
err = post.Fetch()
@@ -296,7 +296,7 @@ func ConvosEditReplySubmit(w http.ResponseWriter, r *http.Request, user c.User,
return c.InternalError(err, w, r)
}
- if !isJs {
+ if !js {
http.Redirect(w, r, "/user/convo/"+strconv.Itoa(post.CID), http.StatusSeeOther)
} else {
w.Write(successJSONBytes)
diff --git a/routes/panel/dashboard.go b/routes/panel/dashboard.go
index fa5730d4..b7c4a141 100644
--- a/routes/panel/dashboard.go
+++ b/routes/panel/dashboard.go
@@ -29,8 +29,7 @@ type dashStmts struct {
// TODO: Stop hard-coding these queries
func dashMySQLStmts() (stmts dashStmts, err error) {
db := qgen.Builder.GetConn()
-
- var prepareStmt = func(table string, ext string, dur string) *sql.Stmt {
+ prepareStmt := func(table string, ext string, dur string) *sql.Stmt {
if err != nil {
return nil
}
@@ -51,8 +50,7 @@ func dashMySQLStmts() (stmts dashStmts, err error) {
// TODO: Stop hard-coding these queries
func dashMSSQLStmts() (stmts dashStmts, err error) {
db := qgen.Builder.GetConn()
-
- var prepareStmt = func(table string, ext string, dur string) *sql.Stmt {
+ prepareStmt := func(table string, ext string, dur string) *sql.Stmt {
if err != nil {
return nil
}
@@ -134,7 +132,7 @@ func Dashboard(w http.ResponseWriter, r *http.Request, user c.User) c.RouteError
// TODO: Add a stat store for this?
var intErr error
- var extractStat = func(stmt *sql.Stmt, args ...interface{}) (stat int) {
+ extractStat := func(stmt *sql.Stmt, args ...interface{}) (stat int) {
err := stmt.QueryRow(args...).Scan(&stat)
if err != nil && err != sql.ErrNoRows {
intErr = err
diff --git a/schema/mssql/query_users_groups_promotions.sql b/schema/mssql/query_users_groups_promotions.sql
new file mode 100644
index 00000000..7cfc8f44
--- /dev/null
+++ b/schema/mssql/query_users_groups_promotions.sql
@@ -0,0 +1,9 @@
+CREATE TABLE [users_groups_promotions] (
+ [pid] int not null IDENTITY,
+ [from_gid] int not null,
+ [to_gid] int not null,
+ [two_way] bit DEFAULT 0 not null,
+ [level] int not null,
+ [minTime] int not null,
+ primary key([pid])
+);
\ No newline at end of file
diff --git a/schema/mysql/query_users_groups_promotions.sql b/schema/mysql/query_users_groups_promotions.sql
new file mode 100644
index 00000000..cf534c5a
--- /dev/null
+++ b/schema/mysql/query_users_groups_promotions.sql
@@ -0,0 +1,9 @@
+CREATE TABLE `users_groups_promotions` (
+ `pid` int not null AUTO_INCREMENT,
+ `from_gid` int not null,
+ `to_gid` int not null,
+ `two_way` boolean DEFAULT 0 not null,
+ `level` int not null,
+ `minTime` int not null,
+ primary key(`pid`)
+) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci;
\ No newline at end of file
diff --git a/schema/pgsql/query_users_groups_promotions.sql b/schema/pgsql/query_users_groups_promotions.sql
new file mode 100644
index 00000000..5f1fc701
--- /dev/null
+++ b/schema/pgsql/query_users_groups_promotions.sql
@@ -0,0 +1,9 @@
+CREATE TABLE "users_groups_promotions" (
+ `pid` serial not null,
+ `from_gid` int not null,
+ `to_gid` int not null,
+ `two_way` boolean DEFAULT 0 not null,
+ `level` int not null,
+ `minTime` int not null,
+ primary key(`pid`)
+);
\ No newline at end of file
diff --git a/templates/convos.html b/templates/convos.html
index 932e6f5b..7e140fa9 100644
--- a/templates/convos.html
+++ b/templates/convos.html
@@ -30,7 +30,7 @@
{{range .Users}}{{.Name}} {{end}}
{{reltime .LastReplyAt}}
+
{{end}}
-
{{template "paginator.html" . }}
\ No newline at end of file
diff --git a/templates/panel_group_edit_promotions.html b/templates/panel_group_edit_promotions.html
new file mode 100644
index 00000000..2c5ada0b
--- /dev/null
+++ b/templates/panel_group_edit_promotions.html
@@ -0,0 +1,69 @@
+{{template "header.html" . }}
+
+{{template "panel_group_menu.html" . }}
+
+{{template "panel_before_head.html" . }}
+
+
{{.Name}}{{lang "panel_group_head_suffix"}}
+
+
+
+{{if .CurrentUser.Perms.EditGroup}}
+
+
+{{end}}
+
+
+
+{{template "footer.html" . }}
\ No newline at end of file
diff --git a/templates/panel_group_menu.html b/templates/panel_group_menu.html
index 6794ebd4..51f9503f 100644
--- a/templates/panel_group_menu.html
+++ b/templates/panel_group_menu.html
@@ -4,7 +4,7 @@
{{template "panel_inner_menu.html" . }}
diff --git a/templates/topic.html b/templates/topic.html
index c8da2f69..fd5cdefd 100644
--- a/templates/topic.html
+++ b/templates/topic.html
@@ -31,7 +31,7 @@
{{end}}
-
+
{{.Topic.ContentHTML}}
{{if .CurrentUser.Loggedin}}
{{end}}
@@ -41,7 +41,7 @@
{{if .CurrentUser.Loggedin}}
{{if .CurrentUser.Perms.LikeItem}}
- {{end}}
+
{{end}}
diff --git a/templates/topic_posts.html b/templates/topic_posts.html
index 5dca6e21..5edf370b 100644
--- a/templates/topic_posts.html
+++ b/templates/topic_posts.html
@@ -1,11 +1,11 @@
-
{{range .ItemList}}
+
{{range .ItemList}}
{{if .ActionType}}
{{.ActionIcon}}
{{.ActionType}}
{{else}}
-
+
{{/** TODO: We might end up with s in the inline editor, fix this **/}}
{{.ContentHtml}}
{{if $.CurrentUser.Loggedin}}{{.Content}}
{{end}}
diff --git a/templates/topics_quick_topic.html b/templates/topics_quick_topic.html
index c6e86b47..7f9fb92a 100644
--- a/templates/topics_quick_topic.html
+++ b/templates/topics_quick_topic.html
@@ -1,4 +1,4 @@
-
+
diff --git a/themes/nox/overrides/panel_group_menu.html b/themes/nox/overrides/panel_group_menu.html
index 491bad4e..0341da19 100644
--- a/themes/nox/overrides/panel_group_menu.html
+++ b/themes/nox/overrides/panel_group_menu.html
@@ -7,7 +7,7 @@
{{template "panel_inner_menu.html" . }}
diff --git a/themes/nox/public/panel.css b/themes/nox/public/panel.css
index 43128432..669216c8 100644
--- a/themes/nox/public/panel.css
+++ b/themes/nox/public/panel.css
@@ -50,7 +50,7 @@
background-color: rgb(72, 72, 72);
padding-top: 12px;
padding-bottom: 12px;
- padding-right: 20px;
+ padding-right: 22px;
padding-left: 20px;
}
.above_right img {
@@ -275,6 +275,9 @@ select + .timeRangeSelector {
margin-top: 8px;
margin-right: auto;
}
+.panel_group_promotions .formitem {
+ display: flex;
+}
.perm_preset_no_access:before {
content: "{{lang "panel_perms_no_access" . }}";
diff --git a/themes/shadow/public/convo.css b/themes/shadow/public/convo.css
index a50090b4..0e615767 100644
--- a/themes/shadow/public/convo.css
+++ b/themes/shadow/public/convo.css
@@ -1,3 +1,19 @@
.convos_item_user:not(:last-child):after {
content: ",";
+}
+
+.parti {
+ margin-bottom: 8px;
+}
+.parti .rowitem {
+ display: flex;
+}
+.parti_user:not(:last-child):after {
+ content: ",";
+}
+
+.convo_row_box .rowitem {
+ background-repeat: no-repeat, repeat-y;
+ background-size: 128px;
+ padding-left: 136px;
}
\ No newline at end of file
diff --git a/themes/tempra_simple/public/convo.css b/themes/tempra_simple/public/convo.css
index a50090b4..25f13e86 100644
--- a/themes/tempra_simple/public/convo.css
+++ b/themes/tempra_simple/public/convo.css
@@ -1,3 +1,22 @@
.convos_item_user:not(:last-child):after {
content: ",";
+}
+.to_left:after {
+ clear: both;
+}
+
+/*.parti {
+ margin-bottom: 8px;
+}*/
+.parti .rowitem {
+ display: flex;
+}
+.parti_user:not(:last-child):after {
+ content: ",";
+}
+
+.convo_row_box .rowitem {
+ background-repeat: no-repeat, repeat-y;
+ background-size: 128px;
+ padding-left: 136px;
}
\ No newline at end of file