Added the new theme, Shadow. It still isn't complete yet.

Revamped the configuration system.
If you have trouble installing this, try installing my fork of gopsutil with `go get` and delete the users_penalties table from the schema folder. That stuff will be cleaned up in the next commit.

Fixed an issue with the links for the Uncategorised forum being broken.
Swapped out NOW() for UTC_TIMESTAMP() in MySQL queries.
We now get an error message when the server goes down for whatever reason.
The template compiler now supports pointers.
Swapped out shirou/gopsutil for a fork locked on an older and more stable commit of the same library.
Fixed a bug where the preprocessor didn't play nice with empty CSS files.

Added the site name to the navbar.
Added more things to .gitignore
Laid the foundations for the next commit.
This commit is contained in:
Azareal 2017-07-17 11:23:42 +01:00
parent e30707bc17
commit d976a192fb
60 changed files with 1190 additions and 666 deletions

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
tmp/* tmp/*
tmp2/* tmp2/*
uploads/avatar_* uploads/avatar_*
uploads/socialgroup_*
bin/* bin/*
*.exe *.exe
*.exe~
*.prof *.prof
.DS_Store .DS_Store

View File

@ -1,50 +1,52 @@
package main package main
func init() {
// Site Info // Site Info
var site_name = "Test Install" // Should be a setting in the database site.Name = "Test Site" // Should be a setting in the database
var site_url = "localhost:8080" site.Email = "" // Should be a setting in the database
var server_port = "8080" site.Url = "localhost"
var enable_ssl = false site.Port = "8080"
var ssl_privkey = "" site.EnableSsl = false
var ssl_fullchain = "" site.EnableEmails = false
config.SslPrivkey = ""
config.SslFullchain = ""
// Database details // Database details
var dbhost = "localhost" db_config.Host = "localhost"
var dbuser = "root" db_config.Username = "root"
var dbpassword = "password" db_config.Password = "password"
var dbname = "gosora" db_config.Dbname = "gosora"
var dbport = "3306" // You probably won't need to change this db_config.Port = "3306" // You probably won't need to change this
// Limiters // Limiters
var max_request_size = 5 * megabyte config.MaxRequestSize = 5 * megabyte
// Caching // Caching
var cache_topicuser = CACHE_STATIC config.CacheTopicUser = CACHE_STATIC
var user_cache_capacity = 100 // The max number of users held in memory config.UserCacheCapacity = 100 // The max number of users held in memory
var topic_cache_capacity = 100 // The max number of topics held in memory config.TopicCacheCapacity = 100 // The max number of topics held in memory
// Email // Email
var site_email = "" // Should be a setting in the database config.SmtpServer = ""
var smtp_server = "" config.SmtpUsername = ""
var smtp_username = "" config.SmtpPassword = ""
var smtp_password = "" config.SmtpPort = "25"
var smtp_port = "25"
var enable_emails = false
// Misc // Misc
var default_route = route_topics config.DefaultRoute = route_topics
var default_group = 3 // Should be a setting in the database config.DefaultGroup = 3 // Should be a setting in the database
var activation_group = 5 // Should be a setting in the database config.ActivationGroup = 5 // Should be a setting in the database
var staff_css = " background-color: #ffeaff;" config.StaffCss = "staff_post"
var uncategorised_forum_visible = true config.UncategorisedForumVisible = true
var minify_templates = false config.MinifyTemplates = false
var multi_server = false // Experimental: Enable Cross-Server Synchronisation and several other features config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features
//var noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png" //config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"
var noavatar = "https://api.adorable.io/avatars/285/{id}@" + site_url + ".png" config.Noavatar = "https://api.adorable.io/avatars/285/{id}@{site_url}.png"
var items_per_page = 25 config.ItemsPerPage = 25
// Developer flags // Developer flag
var debug_mode = false dev.DebugMode = true
var super_debug = false //dev.SuperDebug = true
var profiling = false //dev.Profiling = true
}

View File

@ -44,7 +44,7 @@ func init_database() (err error) {
if err != nil { if err != nil {
return err return err
} }
if debug_mode { if dev.DebugMode {
log.Print(group.Name + ": ") log.Print(group.Name + ": ")
fmt.Printf("%+v\n", group.Perms) fmt.Printf("%+v\n", group.Perms)
} }
@ -53,7 +53,7 @@ func init_database() (err error) {
if err != nil { if err != nil {
return err return err
} }
if debug_mode { if dev.DebugMode {
log.Print(group.Name + ": ") log.Print(group.Name + ": ")
fmt.Printf("%+v\n", group.PluginPerms) fmt.Printf("%+v\n", group.PluginPerms)
} }

View File

@ -1,23 +1,35 @@
{ {
"dbhost": "127.0.0.1", "config.DefaultGroup": 3,
"dbuser": "root", "config.ActivationGroup": 5,
"dbpassword": "password",
"dbname": "gosora",
"dbport": "3306",
"default_group": 3,
"activation_group": 5,
"staff_css": " background-color: #ffeaff;", "staff_css": " background-color: #ffeaff;",
"uncategorised_forum_visible": true, "uncategorised_forum_visible": true,
"enable_emails": false, "site.EnableEmails": false,
"smtp_server": "", "config.SmtpServer": "",
"items_per_page": 40, "config.ItemsPerPage": 40,
"site_url": "localhost:8080", "db": {
"server_port": "8080", "Host": "127.0.0.1",
"enable_ssl": false, "Username": "root",
"ssl_privkey": "", "Password": "password",
"ssl_fullchain": "", "Dbname": "gosora",
"Port": "3306"
},
"site":
{
"Url": "localhost:8080",
"Port": "8080",
"EnableSsl": false
},
"config":
{
"SslPrivkey": "",
"SslFullchain": ""
},
"dev":
{
"debug": false "debug": false
},
} }

View File

@ -19,7 +19,7 @@ func init_sendmail() {
// Sendmail is only available on Linux // Sendmail is only available on Linux
func activate_sendmail() error { func activate_sendmail() error {
if !enable_emails { if !site.EnableEmails {
return errors.New("You have emails disabled in your configuration file") return errors.New("You have emails disabled in your configuration file")
} }
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
@ -37,7 +37,7 @@ func send_sendmail(data ...interface{}) interface{} {
subject := data[1].(string) subject := data[1].(string)
body := data[2].(string) body := data[2].(string)
msg := "From: " + site_email + "\n" msg := "From: " + site.Email + "\n"
msg += "To: " + to + "\n" msg += "To: " + to + "\n"
msg += "Subject: " + subject + "\n\n" msg += "Subject: " + subject + "\n\n"
msg += body + "\n" msg += body + "\n"

View File

@ -49,7 +49,7 @@ func init_static_files() {
static_files["/static/" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)} static_files["/static/" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)}
if debug_mode { if dev.DebugMode {
log.Print("Added the '" + path + "' static file.") log.Print("Added the '" + path + "' static file.")
} }
return nil return nil
@ -79,7 +79,7 @@ func add_static_file(path string, prefix string) error {
static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)} static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)}
if debug_mode { if dev.DebugMode {
log.Print("Added the '" + path + "' static file") log.Print("Added the '" + path + "' static file")
} }
return nil return nil

View File

@ -65,7 +65,7 @@ func NewStaticForumStore() *StaticForumStore {
func (sfs *StaticForumStore) LoadForums() error { func (sfs *StaticForumStore) LoadForums() error {
log.Print("Adding the uncategorised forum") log.Print("Adding the uncategorised forum")
var forums []*Forum = []*Forum{ var forums []*Forum = []*Forum{
&Forum{0,"uncategorised","Uncategorised","",uncategorised_forum_visible,"all",0,"",0,"","",0,"",0,""}, &Forum{0,build_forum_url(name_to_slug("Uncategorised"),0),"Uncategorised","",config.UncategorisedForumVisible,"all",0,"",0,"","",0,"",0,""},
} }
rows, err := get_forums_stmt.Query() rows, err := get_forums_stmt.Query()
@ -89,7 +89,7 @@ func (sfs *StaticForumStore) LoadForums() error {
} }
if forum.Name == "" { if forum.Name == "" {
if debug_mode { if dev.DebugMode {
log.Print("Adding a placeholder forum") log.Print("Adding a placeholder forum")
} }
} else { } else {

View File

@ -114,7 +114,7 @@ var add_forum_perms_to_forum_members_stmt *sql.Stmt
var notify_watchers_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt
func _gen_mysql() (err error) { func _gen_mysql() (err error) {
if debug_mode { if dev.DebugMode {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
@ -365,19 +365,19 @@ func _gen_mysql() (err error) {
} }
log.Print("Preparing create_topic statement.") log.Print("Preparing create_topic statement.")
create_topic_stmt, err = db.Prepare("INSERT INTO `topics`(`parentID`,`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,?,NOW(),NOW(),?,?,?)") create_topic_stmt, err = db.Prepare("INSERT INTO `topics`(`parentID`,`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?)")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing create_report statement.") log.Print("Preparing create_report statement.")
create_report_stmt, err = db.Prepare("INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`createdBy`,`data`,`parentID`,`css_class`) VALUES (?,?,?,NOW(),NOW(),?,?,1,'report')") create_report_stmt, err = db.Prepare("INSERT INTO `topics`(`title`,`content`,`parsed_content`,`createdAt`,`lastReplyAt`,`createdBy`,`data`,`parentID`,`css_class`) VALUES (?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report')")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing create_reply statement.") log.Print("Preparing create_reply statement.")
create_reply_stmt, err = db.Prepare("INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,NOW(),?,?,?)") create_reply_stmt, err = db.Prepare("INSERT INTO `replies`(`tid`,`content`,`parsed_content`,`createdAt`,`ipaddress`,`words`,`createdBy`) VALUES (?,?,?,UTC_TIMESTAMP(),?,?,?)")
if err != nil { if err != nil {
return err return err
} }
@ -413,7 +413,7 @@ func _gen_mysql() (err error) {
} }
log.Print("Preparing create_profile_reply statement.") log.Print("Preparing create_profile_reply statement.")
create_profile_reply_stmt, err = db.Prepare("INSERT INTO `users_replies`(`uid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`ipaddress`) VALUES (?,?,?,NOW(),?,?)") create_profile_reply_stmt, err = db.Prepare("INSERT INTO `users_replies`(`uid`,`content`,`parsed_content`,`createdAt`,`createdBy`,`ipaddress`) VALUES (?,?,?,UTC_TIMESTAMP(),?,?)")
if err != nil { if err != nil {
return err return err
} }
@ -455,13 +455,13 @@ func _gen_mysql() (err error) {
} }
log.Print("Preparing add_modlog_entry statement.") log.Print("Preparing add_modlog_entry statement.")
add_modlog_entry_stmt, err = db.Prepare("INSERT INTO `moderation_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,NOW())") add_modlog_entry_stmt, err = db.Prepare("INSERT INTO `moderation_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,UTC_TIMESTAMP())")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing add_adminlog_entry statement.") log.Print("Preparing add_adminlog_entry statement.")
add_adminlog_entry_stmt, err = db.Prepare("INSERT INTO `administration_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,NOW())") add_adminlog_entry_stmt, err = db.Prepare("INSERT INTO `administration_logs`(`action`,`elementID`,`elementType`,`ipaddress`,`actorID`,`doneAt`) VALUES (?,?,?,?,?,UTC_TIMESTAMP())")
if err != nil { if err != nil {
return err return err
} }
@ -473,7 +473,7 @@ func _gen_mysql() (err error) {
} }
log.Print("Preparing add_replies_to_topic statement.") log.Print("Preparing add_replies_to_topic statement.")
add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyAt` = NOW() WHERE `tid` = ?") add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyAt` = UTC_TIMESTAMP() WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
@ -497,7 +497,7 @@ func _gen_mysql() (err error) {
} }
log.Print("Preparing update_forum_cache statement.") log.Print("Preparing update_forum_cache statement.")
update_forum_cache_stmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = NOW() WHERE `fid` = ?") update_forum_cache_stmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = UTC_TIMESTAMP() WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }

View File

@ -45,12 +45,12 @@ var update_email_stmt *sql.Stmt
var verify_email_stmt *sql.Stmt var verify_email_stmt *sql.Stmt
func _gen_pgsql() (err error) { func _gen_pgsql() (err error) {
if debug_mode { if dev.DebugMode {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
log.Print("Preparing add_replies_to_topic statement.") log.Print("Preparing add_replies_to_topic statement.")
add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyAt` = NOW() WHERE `tid` = ?") add_replies_to_topic_stmt, err = db.Prepare("UPDATE `topics` SET `postCount` = `postCount` + ?,`lastReplyAt` = UTC_TIMESTAMP() WHERE `tid` = ?")
if err != nil { if err != nil {
return err return err
} }
@ -74,7 +74,7 @@ func _gen_pgsql() (err error) {
} }
log.Print("Preparing update_forum_cache statement.") log.Print("Preparing update_forum_cache statement.")
update_forum_cache_stmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = NOW() WHERE `fid` = ?") update_forum_cache_stmt, err = db.Prepare("UPDATE `forums` SET `lastTopic` = ?,`lastTopicID` = ?,`lastReplyer` = ?,`lastReplyerID` = ?,`lastTopicTime` = UTC_TIMESTAMP() WHERE `fid` = ?")
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,7 +2,7 @@
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
package main package main
//import "fmt" import "fmt"
import "strings" import "strings"
import "sync" import "sync"
import "errors" import "errors"
@ -72,12 +72,20 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if dev.SuperDebug {
fmt.Println("before PreRoute")
}
// Deal with the session stuff, etc. // Deal with the session stuff, etc.
user, ok := PreRoute(w,req) user, ok := PreRoute(w,req)
if !ok { if !ok {
return return
} }
if dev.SuperDebug {
fmt.Println("after PreRoute")
}
switch(prefix) { switch(prefix) {
case "/api": case "/api":
route_api(w,req,user) route_api(w,req,user)
@ -199,7 +207,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
router.UploadHandler(w,req) router.UploadHandler(w,req)
return return
case "": case "":
default_route(w,req,user) config.DefaultRoute(w,req,user)
return return
//default: NotFound(w,req) //default: NotFound(w,req)
} }

View File

@ -26,7 +26,7 @@ var db_prod *sql.DB
var gloinited bool var gloinited bool
func gloinit() { func gloinit() {
debug_mode = false dev.DebugMode = false
//nogrouplog = true //nogrouplog = true
// init_database is a little noisy for a benchmark // init_database is a little noisy for a benchmark
@ -34,7 +34,8 @@ func gloinit() {
//log.SetOutput(discard) //log.SetOutput(discard)
startTime = time.Now() startTime = time.Now()
timeLocation = startTime.Location() //timeLocation = startTime.Location()
process_config()
init_themes() init_themes()
err := init_database() err := init_database()
@ -55,7 +56,7 @@ func gloinit() {
log.Fatal(err) log.Fatal(err)
} }
if cache_topicuser == CACHE_STATIC { if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(user_cache_capacity) users = NewMemoryUserStore(user_cache_capacity)
topics = NewMemoryTopicStore(topic_cache_capacity) topics = NewMemoryTopicStore(topic_cache_capacity)
} else { } else {
@ -84,16 +85,16 @@ func BenchmarkTopicTemplateSerial(b *testing.B) {
topic := TopicUser{Title: "Lol",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"} topic := TopicUser{Title: "Lol",Content: "Hey everyone!",CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58, IpAddress: "127.0.0.1"}
var replyList []Reply var replyList []Reply
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry","Jerry",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry","Jerry",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry2","Jerry2",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry2","Jerry2",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry3","Jerry3",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry3","Jerry3",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry4","Jerry4",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry4","Jerry4",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry5","Jerry5",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry5","Jerry5",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry6","Jerry6",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry6","Jerry6",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry7","Jerry7",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry7","Jerry7",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry8","Jerry8",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry8","Jerry8",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry9","Jerry9",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry9","Jerry9",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry10","Jerry10",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Hey everyone!","Hey everyone!",0,"jerry10","Jerry10",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
headerVars := HeaderVars{ headerVars := HeaderVars{
NoticeList:[]string{"test"}, NoticeList:[]string{"test"},

View File

@ -100,7 +100,7 @@ func main() {
} }
// Build the admin user query // Build the admin user query
admin_user_stmt, err := qgen.Builder.SimpleInsert("users","name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip","'Admin',?,?,'admin@localhost',1,1,1,NOW(),NOW(),'','127.0.0.1'") admin_user_stmt, err := qgen.Builder.SimpleInsert("users","name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip","'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'")
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
fmt.Println("Aborting installation...") fmt.Println("Aborting installation...")
@ -137,54 +137,56 @@ func main() {
configContents := []byte(`package main configContents := []byte(`package main
func init() {
// Site Info // Site Info
var site_name = "` + site_name + `" // Should be a setting in the database site.Name = "` + site_name + `" // Should be a setting in the database
var site_url = "` + site_url + `" site.Email = "" // Should be a setting in the database
var server_port = "` + server_port + `" site.Url = "` + site_url + `"
var enable_ssl = false site.Port = "` + server_port + `"
var ssl_privkey = "" site.EnableSsl = false
var ssl_fullchain = "" site.EnableEmails = false
config.SslPrivkey = ""
config.SslFullchain = ""
// Database details // Database details
var dbhost = "` + db_host + `" db_config.Host = "` + db_host + `"
var dbuser = "` + db_username + `" db_config.Username = "` + db_username + `"
var dbpassword = "` + db_password + `" db_config.Password = "` + db_password + `"
var dbname = "` + db_name + `" db_config.Dbname = "` + db_name + `"
var dbport = "` + db_port + `" // You probably won't need to change this db_config.Port = "` + db_port + `" // You probably won't need to change this
// Limiters // Limiters
var max_request_size = 5 * megabyte config.MaxRequestSize = 5 * megabyte
// Caching // Caching
var cache_topicuser = CACHE_STATIC config.CacheTopicUser = CACHE_STATIC
var user_cache_capacity = 100 // The max number of users held in memory config.UserCacheCapacity = 100 // The max number of users held in memory
var topic_cache_capacity = 100 // The max number of topics held in memory config.TopicCacheCapacity = 100 // The max number of topics held in memory
// Email // Email
var site_email = "" // Should be a setting in the database config.SmtpServer = ""
var smtp_server = "" config.SmtpUsername = ""
var smtp_username = "" config.SmtpPassword = ""
var smtp_password = "" config.SmtpPort = "25"
var smtp_port = "25"
var enable_emails = false
// Misc // Misc
var default_route = route_topics config.DefaultRoute = route_topics
var default_group = 3 // Should be a setting in the database config.DefaultGroup = 3 // Should be a setting in the database
var activation_group = 5 // Should be a setting in the database config.ActivationGroup = 5 // Should be a setting in the database
var staff_css = " background-color: #ffeaff;" config.StaffCss = "staff_post"
var uncategorised_forum_visible = true config.UncategorisedForumVisible = true
var minify_templates = true config.MinifyTemplates = true
var multi_server = false // Experimental: Enable Cross-Server Synchronisation and several other features config.MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features
//var noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png" //config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"
var noavatar = "https://api.adorable.io/avatars/285/{id}@" + site_url + ".png" config.Noavatar = "https://api.adorable.io/avatars/285/{id}@{site_url}.png"
var items_per_page = 25 config.ItemsPerPage = 25
// Developer flag // Developer flag
var debug_mode = true dev.DebugMode = true
var super_debug = false //dev.SuperDebug = true
var profiling = false //dev.Profiling = true
}
`) `)
fmt.Println("Opening the configuration file") fmt.Println("Opening the configuration file")

View File

@ -11,7 +11,7 @@ import _ "github.com/go-sql-driver/mysql"
var db_sslmode = "disable" var db_sslmode = "disable"
func _set_pgsql_adapter() { func _set_pgsql_adapter() {
db_port = "3306" db_port = "5432"
init_database = _init_pgsql init_database = _init_pgsql
} }

57
main.go
View File

@ -5,6 +5,7 @@ import (
"net/http" "net/http"
"fmt" "fmt"
"log" "log"
"strings"
"time" "time"
"io" "io"
"html/template" "html/template"
@ -27,10 +28,9 @@ var enable_websockets bool = false // Don't change this, the value is overwritte
var router *GenRouter var router *GenRouter
var startTime time.Time var startTime time.Time
var timeLocation *time.Location //var timeLocation *time.Location
var templates = template.New("") var templates = template.New("")
var no_css_tmpl template.CSS = template.CSS("") //var no_css_tmpl template.CSS = template.CSS("")
var staff_css_tmpl template.CSS = template.CSS(staff_css)
var settings map[string]interface{} = make(map[string]interface{}) var settings map[string]interface{} = make(map[string]interface{})
var external_sites map[string]string = make(map[string]string) var external_sites map[string]string = make(map[string]string)
var groups []Group var groups []Group
@ -49,6 +49,7 @@ func compile_templates() error {
var c CTemplateSet var c CTemplateSet
user := User{62,"fake-user","Fake User","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"0.0.0.0.0"} user := User{62,"fake-user","Fake User","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,make(map[string]bool),"",false,"","","","","",0,0,"0.0.0.0.0"}
headerVars := HeaderVars{ headerVars := HeaderVars{
Site:site,
NoticeList:[]string{"test"}, NoticeList:[]string{"test"},
Stylesheets:[]string{"panel"}, Stylesheets:[]string{"panel"},
Scripts:[]string{"whatever"}, Scripts:[]string{"whatever"},
@ -59,9 +60,9 @@ func compile_templates() error {
log.Print("Compiling the templates") log.Print("Compiling the templates")
topic := TopicUser{1,"blah","Blah","Hey there!",0,false,false,"Date","Date",0,"","127.0.0.1",0,1,"classname","weird-data","fake-user","Fake User",default_group,"",no_css_tmpl,0,"","","","",58,false} topic := TopicUser{1,"blah","Blah","Hey there!",0,false,false,"Date","Date",0,"","127.0.0.1",0,1,"classname","weird-data","fake-user","Fake User",config.DefaultGroup,"",0,"","","","",58,false}
var replyList []Reply var replyList []Reply
replyList = append(replyList, Reply{0,0,"Yo!","Yo!",0,"alice","Alice",default_group,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""}) replyList = append(replyList, Reply{0,0,"Yo!","Yo!",0,"alice","Alice",config.DefaultGroup,"",0,0,"","",0,"","","","",0,"127.0.0.1",false,1,"",""})
var varList map[string]VarItem = make(map[string]VarItem) var varList map[string]VarItem = make(map[string]VarItem)
tpage := TopicPage{"Title",user,headerVars,replyList,topic,1,1,extData} tpage := TopicPage{"Title",user,headerVars,replyList,topic,1,1,extData}
@ -93,7 +94,7 @@ func compile_templates() error {
topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage",topics_page,varList) topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage",topics_page,varList)
var topicList []TopicUser var topicList []TopicUser
topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",default_group,"","",0,"","","","",58,false}) topicList = append(topicList,TopicUser{1,"topic-title","Topic Title","The topic content.",1,false,false,"Date","Date",1,"","127.0.0.1",0,1,"classname","","admin-fred","Admin Fred",config.DefaultGroup,"",0,"","","","",58,false})
forum_item := Forum{1,"general","General Forum","Where the general stuff happens",true,"all",0,"",0,"","",0,"",0,""} forum_item := Forum{1,"general","General Forum","Where the general stuff happens",true,"all",0,"",0,"","",0,"",0,""}
forum_page := ForumPage{"General Forum",user,headerVars,topicList,forum_item,1,1,extData} forum_page := ForumPage{"General Forum",user,headerVars,topicList,forum_item,1,1,extData}
forum_tmpl := c.compile_template("forum.html","templates/","ForumPage",forum_page,varList) forum_tmpl := c.compile_template("forum.html","templates/","ForumPage",forum_page,varList)
@ -118,7 +119,7 @@ func write_template(name string, content string) {
} }
func init_templates() { func init_templates() {
if debug_mode { if dev.DebugMode {
log.Print("Initialising the template system") log.Print("Initialising the template system")
} }
compile_templates() compile_templates()
@ -134,7 +135,7 @@ func init_templates() {
fmap["divide"] = filler_func fmap["divide"] = filler_func
// The interpreted templates... // The interpreted templates...
if debug_mode { if dev.DebugMode {
log.Print("Loading the template files...") log.Print("Loading the template files...")
} }
templates.Funcs(fmap) templates.Funcs(fmap)
@ -142,6 +143,16 @@ func init_templates() {
template.Must(templates.ParseGlob("pages/*")) template.Must(templates.ParseGlob("pages/*"))
} }
func process_config() {
config.Noavatar = strings.Replace(config.Noavatar,"{site_url}",site.Url,-1)
if site.Port != "80" && site.Port != "443" {
site.Url = strings.TrimSuffix(site.Url,"/")
site.Url = strings.TrimSuffix(site.Url,"\\")
site.Url = strings.TrimSuffix(site.Url,":")
site.Url = site.Url + ":" + site.Port
}
}
func main(){ func main(){
//if profiling { //if profiling {
// f, err := os.Create("startup_cpu.prof") // f, err := os.Create("startup_cpu.prof")
@ -154,7 +165,10 @@ func main(){
log.Print("Running Gosora v" + version.String()) log.Print("Running Gosora v" + version.String())
fmt.Println("") fmt.Println("")
startTime = time.Now() startTime = time.Now()
timeLocation = startTime.Location() //timeLocation = startTime.Location()
fmt.Println("Processing configuration data")
process_config()
init_themes() init_themes()
err := init_database() err := init_database()
@ -168,9 +182,9 @@ func main(){
log.Fatal(err) log.Fatal(err)
} }
if cache_topicuser == CACHE_STATIC { if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(user_cache_capacity) users = NewMemoryUserStore(config.UserCacheCapacity)
topics = NewMemoryTopicStore(topic_cache_capacity) topics = NewMemoryTopicStore(config.TopicCacheCapacity)
} else { } else {
users = NewSqlUserStore() users = NewSqlUserStore()
topics = NewSqlTopicStore() topics = NewSqlTopicStore()
@ -285,15 +299,20 @@ func main(){
//} //}
log.Print("Initialising the HTTP server") log.Print("Initialising the HTTP server")
if !enable_ssl { if !site.EnableSsl {
if server_port == "" { if site.Port == "" {
server_port = "80" site.Port = "80"
} }
http.ListenAndServe(":" + server_port, router) err = http.ListenAndServe(":" + site.Port, router)
} else { } else {
if server_port == "" { if site.Port == "" {
server_port = "443" site.Port = "443"
} }
http.ListenAndServeTLS(":" + server_port, ssl_fullchain, ssl_privkey, router) err = http.ListenAndServeTLS(":" + site.Port, config.SslFullchain, config.SslPrivkey, router)
}
// Why did the server stop?
if err != nil {
log.Fatal(err)
} }
} }

View File

@ -659,7 +659,7 @@ func route_unban(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = change_group_stmt.Exec(default_group, uid) _, err = change_group_stmt.Exec(config.DefaultGroup, uid)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -724,7 +724,7 @@ func route_activate(w http.ResponseWriter, r *http.Request, user User) {
return return
} }
_, err = change_group_stmt.Exec(default_group, uid) _, err = change_group_stmt.Exec(config.DefaultGroup, uid)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return

View File

@ -18,12 +18,12 @@ var todays_newuser_count_stmt *sql.Stmt
func _init_database() (err error) { func _init_database() (err error) {
var _dbpassword string var _dbpassword string
if(dbpassword != ""){ if(db_config.Password != ""){
_dbpassword = ":" + dbpassword _dbpassword = ":" + db_config.Password
} }
// Open the database connection // Open the database connection
db, err = sql.Open("mysql",dbuser + _dbpassword + "@tcp(" + dbhost + ":" + dbport + ")/" + dbname + "?collation=" + db_collation) db, err = sql.Open("mysql", db_config.Username + _dbpassword + "@tcp(" + db_config.Host + ":" + db_config.Port + ")/" + db_config.Dbname + "?collation=" + db_collation)
if err != nil { if err != nil {
return err return err
} }
@ -66,25 +66,25 @@ func _init_database() (err error) {
} }
log.Print("Preparing todays_post_count statement.") log.Print("Preparing todays_post_count statement.")
todays_post_count_stmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (now() - interval 1 day) and now()") todays_post_count_stmt, err = db.Prepare("select count(*) from replies where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_topic_count statement.") log.Print("Preparing todays_topic_count statement.")
todays_topic_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now()") todays_topic_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_report_count statement.") log.Print("Preparing todays_report_count statement.")
todays_report_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (now() - interval 1 day) and now() and parentID = 1") todays_report_count_stmt, err = db.Prepare("select count(*) from topics where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp() and parentID = 1")
if err != nil { if err != nil {
return err return err
} }
log.Print("Preparing todays_newuser_count statement.") log.Print("Preparing todays_newuser_count statement.")
todays_newuser_count_stmt, err = db.Prepare("select count(*) from users where createdAt BETWEEN (now() - interval 1 day) and now()") todays_newuser_count_stmt, err = db.Prepare("select count(*) from users where createdAt BETWEEN (utc_timestamp() - interval 1 day) and utc_timestamp()")
if err != nil { if err != nil {
return err return err
} }

View File

@ -234,7 +234,7 @@ INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`) VALUES ('Awaiting
INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest'); INSERT INTO users_groups(`name`,`permissions`,`plugin_perms`,`tag`) VALUES ('Not Loggedin','{"ViewTopic":true}','{}','Guest');
INSERT INTO forums(`name`,`active`) VALUES ('Reports',0); INSERT INTO forums(`name`,`active`) VALUES ('Reports',0);
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW()); INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',UTC_TIMESTAMP());
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}'); INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (1,1,'{"ViewTopic":true,"CreateReply":true,"CreateTopic":true,"PinTopic":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}'); INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,1,'{}'); INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (3,1,'{}');
@ -242,7 +242,7 @@ INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (4,1,'{}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (5,1,'{}'); INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (5,1,'{}');
INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (6,1,'{}'); INSERT INTO forums_permissions(`gid`,`fid`,`permissions`) VALUES (6,1,'{}');
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`) INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
VALUES ('Test Topic','A topic automatically generated by the software.',NOW(),NOW(),1,2); VALUES ('Test Topic','A topic automatically generated by the software.',UTC_TIMESTAMP(),UTC_TIMESTAMP(),1,2);
INSERT INTO replies(`tid`,`content`,`createdAt`,`createdBy`,`lastEdit`,`lastEditBy`) INSERT INTO replies(`tid`,`content`,`createdAt`,`createdBy`,`lastEdit`,`lastEditBy`)
VALUES (1,'Reply 1',NOW(),1,0,0); VALUES (1,'Reply 1',UTC_TIMESTAMP(),1,0,0);

View File

@ -14,6 +14,7 @@ type HeaderVars struct
Scripts []string Scripts []string
Stylesheets []string Stylesheets []string
Widgets PageWidgets Widgets PageWidgets
Site *Site
ExtData ExtData ExtData ExtData
} }

View File

@ -7,14 +7,11 @@ import (
"strings" "strings"
"strconv" "strconv"
"html" "html"
"time"
"runtime"
"encoding/json" "encoding/json"
"net/http" "net/http"
"html/template" "html/template"
"github.com/shirou/gopsutil/cpu" "github.com/Azareal/gopsutil/mem"
"github.com/shirou/gopsutil/mem"
) )
func route_panel(w http.ResponseWriter, r *http.Request, user User){ func route_panel(w http.ResponseWriter, r *http.Request, user User){
@ -23,22 +20,14 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){
return return
} }
var cpustr, cpuColour string if dev.SuperDebug {
perc2, err := cpu.Percent(time.Duration(time.Second),true) fmt.Println("past PanelSessionCheck")
if err != nil {
cpustr = "Unknown"
} else {
calcperc := int(perc2[0]) / runtime.NumCPU()
cpustr = strconv.Itoa(calcperc)
if calcperc < 30 {
cpuColour = "stat_green"
} else if calcperc < 75 {
cpuColour = "stat_orange"
} else {
cpuColour = "stat_red"
}
} }
// We won't calculate this on the spot anymore, as the system doesn't seem to like it if we do multiple fetches simultaneously. Should we constantly calculate this on a background thread? Perhaps, the watchdog to scale back heavy features under load? One plus side is that we'd get immediate CPU percentages here instead of waiting it to kick in with WebSockets
var cpustr string = "Unknown"
var cpuColour string
var ramstr, ramColour string var ramstr, ramColour string
memres, err := mem.VirtualMemory() memres, err := mem.VirtualMemory()
if err != nil { if err != nil {
@ -126,7 +115,7 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){
var gridElements []GridElement = []GridElement{ var gridElements []GridElement = []GridElement{
GridElement{"dash-version","v" + version.String(),0,"grid_istat stat_green","","","Gosora is up-to-date :)"}, GridElement{"dash-version","v" + version.String(),0,"grid_istat stat_green","","","Gosora is up-to-date :)"},
GridElement{"dash-cpu","CPU: " + cpustr + "%",1,"grid_istat " + cpuColour,"","","The global CPU usage of this server"}, GridElement{"dash-cpu","CPU: " + cpustr,1,"grid_istat " + cpuColour,"","","The global CPU usage of this server"},
GridElement{"dash-ram","RAM: " + ramstr,2,"grid_istat " + ramColour,"","","The global RAM usage of this server"}, GridElement{"dash-ram","RAM: " + ramstr,2,"grid_istat " + ramColour,"","","The global RAM usage of this server"},
} }
@ -189,7 +178,10 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){
return return
} }
} }
templates.ExecuteTemplate(w,"panel-dashboard.html",pi) err = templates.ExecuteTemplate(w,"panel-dashboard.html",pi)
if err != nil {
InternalError(err,w,r)
}
} }
func route_panel_forums(w http.ResponseWriter, r *http.Request, user User){ func route_panel_forums(w http.ResponseWriter, r *http.Request, user User){
@ -987,7 +979,7 @@ func route_panel_users(w http.ResponseWriter, r *http.Request, user User){
puser.Avatar = "/uploads/avatar_" + strconv.Itoa(puser.ID) + puser.Avatar puser.Avatar = "/uploads/avatar_" + strconv.Itoa(puser.ID) + puser.Avatar
} }
} else { } else {
puser.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(puser.ID),1) puser.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(puser.ID),1)
} }
if groups[puser.Group].Tag != "" { if groups[puser.Group].Tag != "" {

View File

@ -205,7 +205,7 @@ func init() {
guest_user.Perms = GuestPerms guest_user.Perms = GuestPerms
if debug_mode { if dev.DebugMode {
fmt.Printf("Guest Perms: ") fmt.Printf("Guest Perms: ")
fmt.Printf("%+v\n", GuestPerms) fmt.Printf("%+v\n", GuestPerms)
fmt.Printf("All Perms: ") fmt.Printf("All Perms: ")
@ -304,7 +304,7 @@ func permmap_to_query(permmap map[string]ForumPerms, fid int) error {
} }
func rebuild_forum_permissions(fid int) error { func rebuild_forum_permissions(fid int) error {
if debug_mode { if dev.DebugMode {
log.Print("Loading the forum permissions") log.Print("Loading the forum permissions")
} }
forums, err := fstore.GetAll() forums, err := fstore.GetAll()
@ -318,7 +318,7 @@ func rebuild_forum_permissions(fid int) error {
} }
defer rows.Close() defer rows.Close()
if debug_mode { if dev.DebugMode {
log.Print("Updating the forum permissions") log.Print("Updating the forum permissions")
} }
for rows.Next() { for rows.Next() {
@ -342,7 +342,7 @@ func rebuild_forum_permissions(fid int) error {
forum_perms[gid][fid] = pperms forum_perms[gid][fid] = pperms
} }
for gid, _ := range groups { for gid, _ := range groups {
if debug_mode { if dev.DebugMode {
log.Print("Updating the forum permissions for Group #" + strconv.Itoa(gid)) log.Print("Updating the forum permissions for Group #" + strconv.Itoa(gid))
} }
var blank_list []ForumPerms var blank_list []ForumPerms
@ -369,7 +369,7 @@ func rebuild_forum_permissions(fid int) error {
groups[gid].CanSee = append(groups[gid].CanSee, ffid) groups[gid].CanSee = append(groups[gid].CanSee, ffid)
} }
} }
if super_debug { if dev.SuperDebug {
fmt.Printf("groups[gid].CanSee %+v\n", groups[gid].CanSee) fmt.Printf("groups[gid].CanSee %+v\n", groups[gid].CanSee)
fmt.Printf("groups[gid].Forums %+v\n", groups[gid].Forums) fmt.Printf("groups[gid].Forums %+v\n", groups[gid].Forums)
fmt.Println("len(groups[gid].Forums)",len(groups[gid].Forums)) fmt.Println("len(groups[gid].Forums)",len(groups[gid].Forums))
@ -390,7 +390,7 @@ func build_forum_permissions() error {
} }
defer rows.Close() defer rows.Close()
if debug_mode { if dev.DebugMode {
log.Print("Adding the forum permissions") log.Print("Adding the forum permissions")
} }
// Temporarily store the forum perms in a map before transferring it to a much faster and thread-safe slice // Temporarily store the forum perms in a map before transferring it to a much faster and thread-safe slice
@ -416,7 +416,7 @@ func build_forum_permissions() error {
forum_perms[gid][fid] = pperms forum_perms[gid][fid] = pperms
} }
for gid, _ := range groups { for gid, _ := range groups {
if debug_mode { if dev.DebugMode {
log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid) + " - " + groups[gid].Name) log.Print("Adding the forum permissions for Group #" + strconv.Itoa(gid) + " - " + groups[gid].Name)
} }
//groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. No longer needed now that Uncategorised occupies that slot //groups[gid].Forums = append(groups[gid].Forums,BlankForumPerms) // GID 0. No longer needed now that Uncategorised occupies that slot
@ -441,7 +441,7 @@ func build_forum_permissions() error {
groups[gid].CanSee = append(groups[gid].CanSee, fid) groups[gid].CanSee = append(groups[gid].CanSee, fid)
} }
} }
if super_debug { if dev.SuperDebug {
//fmt.Printf("groups[gid].CanSee %+v\n", groups[gid].CanSee) //fmt.Printf("groups[gid].CanSee %+v\n", groups[gid].CanSee)
//fmt.Printf("groups[gid].Forums %+v\n", groups[gid].Forums) //fmt.Printf("groups[gid].Forums %+v\n", groups[gid].Forums)
//fmt.Println("len(groups[gid].CanSee)",len(groups[gid].CanSee)) //fmt.Println("len(groups[gid].CanSee)",len(groups[gid].CanSee))

View File

@ -17,15 +17,14 @@ var todays_post_count_stmt *sql.Stmt
var todays_topic_count_stmt *sql.Stmt var todays_topic_count_stmt *sql.Stmt
var todays_report_count_stmt *sql.Stmt var todays_report_count_stmt *sql.Stmt
var todays_newuser_count_stmt *sql.Stmt var todays_newuser_count_stmt *sql.Stmt
// Note to self: PostgreSQL listens on a different port than MySQL does
func _init_database() (err error) { func _init_database() (err error) {
// TO-DO: Investigate connect_timeout to see what it does exactly and whether it's relevant to us // TO-DO: Investigate connect_timeout to see what it does exactly and whether it's relevant to us
var _dbpassword string var _dbpassword string
if(dbpassword != ""){ if(dbpassword != ""){
_dbpassword = " password='" + _escape_bit(dbpassword) + "'" _dbpassword = " password='" + _escape_bit(db_config.Password) + "'"
} }
db, err = sql.Open("postgres", "host='" + _escape_bit(dbhost) + "' port='" + _escape_bit(dbport) + "' user='" + _escape_bit(dbuser) + "' dbname='" + _escape_bit(dbname) + "'" + _dbpassword + " sslmode='" + db_sslmode + "'") db, err = sql.Open("postgres", "host='" + _escape_bit(db_config.Host) + "' port='" + _escape_bit(db_config.Port) + "' user='" + _escape_bit(db_config.Username) + "' dbname='" + _escape_bit(config.Dbname) + "'" + _dbpassword + " sslmode='" + db_sslmode + "'")
if err != nil { if err != nil {
return err return err
} }

View File

@ -34,6 +34,10 @@ type SocialGroup struct
Desc string Desc string
Active bool Active bool
Privacy int /* 0: Public, 1: Protected, 2: Private */ Privacy int /* 0: Public, 1: Protected, 2: Private */
// Who should be able to accept applications and create invites? Mods+ or just admins? Mods is a good start, we can ponder over whether we should make this more flexible in the future.
Joinable int /* 0: Private, 1: Anyone can join, 2: Applications, 3: Invite-only */
MemberCount int MemberCount int
Owner int Owner int
Backdrop string Backdrop string
@ -111,11 +115,11 @@ func init_socialgroups() (err error) {
router.HandleFunc("/group/create/submit/", socialgroups_create_group_submit) router.HandleFunc("/group/create/submit/", socialgroups_create_group_submit)
router.HandleFunc("/group/members/", socialgroups_member_list) router.HandleFunc("/group/members/", socialgroups_member_list)
socialgroups_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups","sgid, name, desc, active, privacy, owner, memberCount, createdAt, lastUpdateTime","","","") socialgroups_list_stmt, err = qgen.Builder.SimpleSelect("socialgroups","sgid, name, desc, active, privacy, joinable, owner, memberCount, createdAt, lastUpdateTime","","","")
if err != nil { if err != nil {
return err return err
} }
socialgroups_get_group_stmt, err = qgen.Builder.SimpleSelect("socialgroups","name, desc, active, privacy, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","sgid = ?","","") socialgroups_get_group_stmt, err = qgen.Builder.SimpleSelect("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","sgid = ?","","")
if err != nil { if err != nil {
return err return err
} }
@ -131,7 +135,7 @@ func init_socialgroups() (err error) {
if err != nil { if err != nil {
return err return err
} }
socialgroups_create_group_stmt, err = qgen.Builder.SimpleInsert("socialgroups","name, desc, active, privacy, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","?,?,?,?,?,1,?,'',NOW(),NOW()") socialgroups_create_group_stmt, err = qgen.Builder.SimpleInsert("socialgroups","name, desc, active, privacy, joinable, owner, memberCount, mainForum, backdrop, createdAt, lastUpdateTime","?,?,?,?,1,?,1,?,'',UTC_TIMESTAMP(),UTC_TIMESTAMP()")
if err != nil { if err != nil {
return err return err
} }
@ -143,7 +147,7 @@ func init_socialgroups() (err error) {
if err != nil { if err != nil {
return err return err
} }
socialgroups_add_member_stmt, err = qgen.Builder.SimpleInsert("socialgroups_members","sgid, uid, rank, posts, joinedAt","?,?,?,0,NOW()") socialgroups_add_member_stmt, err = qgen.Builder.SimpleInsert("socialgroups_members","sgid, uid, rank, posts, joinedAt","?,?,?,0,UTC_TIMESTAMP()")
if err != nil { if err != nil {
return err return err
} }
@ -181,12 +185,13 @@ func install_socialgroups() error {
qgen.DB_Table_Column{"sgid","int",0,false,true,""}, qgen.DB_Table_Column{"sgid","int",0,false,true,""},
qgen.DB_Table_Column{"name","varchar",100,false,false,""}, qgen.DB_Table_Column{"name","varchar",100,false,false,""},
qgen.DB_Table_Column{"desc","varchar",200,false,false,""}, qgen.DB_Table_Column{"desc","varchar",200,false,false,""},
qgen.DB_Table_Column{"active","tinyint",1,false,false,""}, qgen.DB_Table_Column{"active","boolean",1,false,false,""},
qgen.DB_Table_Column{"privacy","tinyint",1,false,false,""}, qgen.DB_Table_Column{"privacy","smallint",0,false,false,""},
qgen.DB_Table_Column{"joinable","smallint",0,false,false,"0"},
qgen.DB_Table_Column{"owner","int",0,false,false,""}, qgen.DB_Table_Column{"owner","int",0,false,false,""},
qgen.DB_Table_Column{"memberCount","int",0,false,false,""}, qgen.DB_Table_Column{"memberCount","int",0,false,false,""},
qgen.DB_Table_Column{"mainForum","int",0,false,false,"0"}, // The board the user lands on when they click ona group, we'll make it possible for group admins to change what users land on qgen.DB_Table_Column{"mainForum","int",0,false,false,"0"}, // The board the user lands on when they click ona group, we'll make it possible for group admins to change what users land on
//qgen.DB_Table_Column{"boards","varchar",200,false,false,""}, // Cap the max number of boards at 8 to avoid overflowing the confines of a 64-bit integer? //qgen.DB_Table_Column{"boards","varchar",255,false,false,""}, // Cap the max number of boards at 8 to avoid overflowing the confines of a 64-bit integer?
qgen.DB_Table_Column{"backdrop","varchar",200,false,false,""}, // File extension for the uploaded file, or an external link qgen.DB_Table_Column{"backdrop","varchar",200,false,false,""}, // File extension for the uploaded file, or an external link
qgen.DB_Table_Column{"createdAt","createdAt",0,false,false,""}, qgen.DB_Table_Column{"createdAt","createdAt",0,false,false,""},
qgen.DB_Table_Column{"lastUpdateTime","datetime",0,false,false,""}, qgen.DB_Table_Column{"lastUpdateTime","datetime",0,false,false,""},
@ -295,7 +300,7 @@ func socialgroups_group_list(w http.ResponseWriter, r *http.Request, user User)
var sgList []SocialGroup var sgList []SocialGroup
for rows.Next() { for rows.Next() {
sgItem := SocialGroup{ID:0} sgItem := SocialGroup{ID:0}
err := rows.Scan(&sgItem.ID, &sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Owner, &sgItem.MemberCount, &sgItem.CreatedAt, &sgItem.LastUpdateTime) err := rows.Scan(&sgItem.ID, &sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -319,7 +324,7 @@ func socialgroups_group_list(w http.ResponseWriter, r *http.Request, user User)
func socialgroups_get_group(sgid int) (sgItem SocialGroup, err error) { func socialgroups_get_group(sgid int) (sgItem SocialGroup, err error) {
sgItem = SocialGroup{ID:sgid} sgItem = SocialGroup{ID:sgid}
err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Owner, &sgItem.MemberCount, &sgItem.MainForumID, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &sgItem.MainForumID, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
return sgItem, err return sgItem, err
} }
@ -441,7 +446,7 @@ func socialgroups_member_list(w http.ResponseWriter, r *http.Request, user User)
var sgItem SocialGroup = SocialGroup{ID:sgid} var sgItem SocialGroup = SocialGroup{ID:sgid}
var mainForum int // Unused var mainForum int // Unused
err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Owner, &sgItem.MemberCount, &mainForum, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime) err = socialgroups_get_group_stmt.QueryRow(sgid).Scan(&sgItem.Name, &sgItem.Desc, &sgItem.Active, &sgItem.Privacy, &sgItem.Joinable, &sgItem.Owner, &sgItem.MemberCount, &mainForum, &sgItem.Backdrop, &sgItem.CreatedAt, &sgItem.LastUpdateTime)
if err != nil { if err != nil {
LocalError("Bad group",w,r,user) LocalError("Bad group",w,r,user)
return return
@ -470,7 +475,7 @@ func socialgroups_member_list(w http.ResponseWriter, r *http.Request, user User)
sgMember.User.Avatar = "/uploads/avatar_" + strconv.Itoa(sgMember.User.ID) + sgMember.User.Avatar sgMember.User.Avatar = "/uploads/avatar_" + strconv.Itoa(sgMember.User.ID) + sgMember.User.Avatar
} }
} else { } else {
sgMember.User.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(sgMember.User.ID),1) sgMember.User.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(sgMember.User.ID),1)
} }
sgMember.JoinedAt, _ = relative_time(sgMember.JoinedAt) sgMember.JoinedAt, _ = relative_time(sgMember.JoinedAt)
if sgItem.Owner == sgMember.User.ID { if sgItem.Owner == sgMember.User.ID {

View File

@ -839,7 +839,7 @@ import "database/sql"
` + stmts + ` ` + stmts + `
func _gen_mysql() (err error) { func _gen_mysql() (err error) {
if debug_mode { if dev.DebugMode {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
` + body + ` ` + body + `

View File

@ -164,7 +164,14 @@ func (adapter *Pgsql_Adapter) SimpleUpdate(name string, table string, set string
for _, loc := range _process_where(where) { for _, loc := range _process_where(where) {
for _, token := range loc.Expr { for _, token := range loc.Expr {
switch(token.Type) { switch(token.Type) {
case "function","operator","number","substitute": case "function":
// TO-DO: Write a more sophisticated function parser on the utils side. What's the situation in regards to case sensitivity?
// TO-DO: Change things on the MySQL and Gosora side to timestamps
if token.Contents == "UTC_TIMESTAMP()" {
token.Contents = "LOCALTIMESTAMP()"
}
querystr += " " + token.Contents + ""
case "operator","number","substitute":
querystr += " " + token.Contents + "" querystr += " " + token.Contents + ""
case "column": case "column":
querystr += " `" + token.Contents + "`" querystr += " `" + token.Contents + "`"
@ -316,7 +323,7 @@ import "database/sql"
` + stmts + ` ` + stmts + `
func _gen_pgsql() (err error) { func _gen_pgsql() (err error) {
if debug_mode { if dev.DebugMode {
log.Print("Building the generated statements") log.Print("Building the generated statements")
} }
` + body + ` ` + body + `

View File

@ -109,6 +109,7 @@ func create_tables(adapter qgen.DB_Adapter) error {
qgen.DB_Table_Column{"bigposts","int",0,false,false,"0"}, qgen.DB_Table_Column{"bigposts","int",0,false,false,"0"},
qgen.DB_Table_Column{"megaposts","int",0,false,false,"0"}, qgen.DB_Table_Column{"megaposts","int",0,false,false,"0"},
qgen.DB_Table_Column{"topics","int",0,false,false,"0"}, qgen.DB_Table_Column{"topics","int",0,false,false,"0"},
//qgen.DB_Table_Column{"penalty_count","int",0,false,false,"0"},
}, },
[]qgen.DB_Table_Key{ []qgen.DB_Table_Key{
qgen.DB_Table_Key{"uid","primary"}, qgen.DB_Table_Key{"uid","primary"},
@ -116,6 +117,34 @@ func create_tables(adapter qgen.DB_Adapter) error {
}, },
) )
// What should we do about global penalties? Put them on the users table for speed? Or keep them here?
// Should we add IP Penalties?
qgen.Install.CreateTable("users_penalties","","",
[]qgen.DB_Table_Column{
qgen.DB_Table_Column{"uid","int",0,false,false,""},
qgen.DB_Table_Column{"element_id","int",0,false,false,""},
qgen.DB_Table_Column{"element_type","varchar",50,false,false,""}, //global,forum,profile?,social_group
qgen.DB_Table_Column{"overrides","text",0,false,false,"{}"}, // Perm overrides. Coming Soon
qgen.DB_Table_Column{"mod_queue","boolean",0,false,false,"0"}, // All of this user's posts will go through the mod_queue. Coming Soon
// TO-DO: Add a mod-queue and other basic auto-mod features. This is needed for awaiting activation and the mod_queue penalty flag
// TO-DO: Add a penalty type where a user is stopped from creating plugin_socialgroups social groups
qgen.DB_Table_Column{"shadow_ban","boolean",0,false,false,"0"}, // Coming Soon. CanShadowBan permission.
qgen.DB_Table_Column{"no_avatar","boolean",0,false,false,"0"}, // Coming Soon. Should this be a perm override instead?
//qgen.DB_Table_Column{"posts_per_hour","int",0,false,false,"0"}, // Rate-limit penalty type. Coming soon
//qgen.DB_Table_Column{"topics_per_hour","int",0,false,false,"0"}, // Coming Soon
//qgen.DB_Table_Column{"posts_count","int",0,false,false,"0"}, // Coming soon
//qgen.DB_Table_Column{"topic_count","int",0,false,false,"0"}, // Coming Soon
//qgen.DB_Table_Column{"last_hour","int",0,false,false,"0"}, // UNIX Time, as we don't need to do anything too fancy here. When an hour has elapsed since that time, reset the hourly penalty counters.
qgen.DB_Table_Column{"issued_by","int",0,false,false,""},
qgen.DB_Table_Column{"issued_at","createdAt",0,false,false,""},
qgen.DB_Table_Column{"expiry","duration",0,false,false,""}, // TO-DO: Implement the duration parsing code on the adapter side
},
[]qgen.DB_Table_Key{},
)
return nil return nil
} }
@ -224,11 +253,11 @@ func write_inner_joins(adapter qgen.DB_Adapter) error {
} }
func write_inserts(adapter qgen.DB_Adapter) error { func write_inserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,NOW(),NOW(),?,?,?") adapter.SimpleInsert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,?")
adapter.SimpleInsert("create_report","topics","title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class","?,?,?,NOW(),NOW(),?,?,1,'report'") adapter.SimpleInsert("create_report","topics","title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class","?,?,?,UTC_TIMESTAMP(),UTC_TIMESTAMP(),?,?,1,'report'")
adapter.SimpleInsert("create_reply","replies","tid,content,parsed_content,createdAt,ipaddress,words,createdBy","?,?,?,NOW(),?,?,?") adapter.SimpleInsert("create_reply","replies","tid,content,parsed_content,createdAt,ipaddress,words,createdBy","?,?,?,UTC_TIMESTAMP(),?,?,?")
adapter.SimpleInsert("create_action_reply","replies","tid,actionType,ipaddress,createdBy","?,?,?,?") adapter.SimpleInsert("create_action_reply","replies","tid,actionType,ipaddress,createdBy","?,?,?,?")
@ -240,7 +269,7 @@ func write_inserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("add_email","emails","email, uid, validated, token","?,?,?,?") adapter.SimpleInsert("add_email","emails","email, uid, validated, token","?,?,?,?")
adapter.SimpleInsert("create_profile_reply","users_replies","uid, content, parsed_content, createdAt, createdBy, ipaddress","?,?,?,NOW(),?,?") adapter.SimpleInsert("create_profile_reply","users_replies","uid, content, parsed_content, createdAt, createdBy, ipaddress","?,?,?,UTC_TIMESTAMP(),?,?")
adapter.SimpleInsert("add_subscription","activity_subscriptions","user,targetID,targetType,level","?,?,?,2") adapter.SimpleInsert("add_subscription","activity_subscriptions","user,targetID,targetType,level","?,?,?,2")
@ -255,9 +284,9 @@ func write_inserts(adapter qgen.DB_Adapter) error {
adapter.SimpleInsert("create_group","users_groups","name, tag, is_admin, is_mod, is_banned, permissions","?,?,?,?,?,?") adapter.SimpleInsert("create_group","users_groups","name, tag, is_admin, is_mod, is_banned, permissions","?,?,?,?,?,?")
adapter.SimpleInsert("add_modlog_entry","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,NOW()") adapter.SimpleInsert("add_modlog_entry","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,UTC_TIMESTAMP()")
adapter.SimpleInsert("add_adminlog_entry","administration_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,NOW()") adapter.SimpleInsert("add_adminlog_entry","administration_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,UTC_TIMESTAMP()")
return nil return nil
} }
@ -269,7 +298,7 @@ func write_replaces(adapter qgen.DB_Adapter) error {
} }
func write_updates(adapter qgen.DB_Adapter) error { func write_updates(adapter qgen.DB_Adapter) error {
adapter.SimpleUpdate("add_replies_to_topic","topics","postCount = postCount + ?, lastReplyAt = NOW()","tid = ?") adapter.SimpleUpdate("add_replies_to_topic","topics","postCount = postCount + ?, lastReplyAt = UTC_TIMESTAMP()","tid = ?")
adapter.SimpleUpdate("remove_replies_from_topic","topics","postCount = postCount - ?","tid = ?") adapter.SimpleUpdate("remove_replies_from_topic","topics","postCount = postCount - ?","tid = ?")
@ -277,7 +306,7 @@ func write_updates(adapter qgen.DB_Adapter) error {
adapter.SimpleUpdate("remove_topics_from_forum","forums","topicCount = topicCount - ?","fid = ?") adapter.SimpleUpdate("remove_topics_from_forum","forums","topicCount = topicCount - ?","fid = ?")
adapter.SimpleUpdate("update_forum_cache","forums","lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = NOW()","fid = ?") adapter.SimpleUpdate("update_forum_cache","forums","lastTopic = ?, lastTopicID = ?, lastReplyer = ?, lastReplyerID = ?, lastTopicTime = UTC_TIMESTAMP()","fid = ?")
adapter.SimpleUpdate("add_likes_to_topic","topics","likeCount = likeCount + ?","tid = ?") adapter.SimpleUpdate("add_likes_to_topic","topics","likeCount = likeCount + ?","tid = ?")

View File

@ -1,6 +1,5 @@
/* Copyright Azareal 2016 - 2017 */ /* Copyright Azareal 2016 - 2017 */
package main package main
import "html/template"
// Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be seperate? // Should we add a reply store to centralise all the reply logic? Would this cover profile replies too or would that be seperate?
@ -18,7 +17,7 @@ type Reply struct /* Should probably rename this to ReplyUser and rename ReplySh
LastEdit int LastEdit int
LastEditBy int LastEditBy int
Avatar string Avatar string
Css template.CSS ClassName string
ContentLines int ContentLines int
Tag string Tag string
URL string URL string

View File

@ -80,7 +80,7 @@ func main() {
fdata += `package main fdata += `package main
//import "fmt" import "fmt"
import "strings" import "strings"
import "sync" import "sync"
import "errors" import "errors"
@ -150,12 +150,20 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return return
} }
if dev.SuperDebug {
fmt.Println("before PreRoute")
}
// Deal with the session stuff, etc. // Deal with the session stuff, etc.
user, ok := PreRoute(w,req) user, ok := PreRoute(w,req)
if !ok { if !ok {
return return
} }
if dev.SuperDebug {
fmt.Println("after PreRoute")
}
switch(prefix) {` + out + ` switch(prefix) {` + out + `
case "/uploads": case "/uploads":
if extra_data == "" { if extra_data == "" {
@ -166,7 +174,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
router.UploadHandler(w,req) router.UploadHandler(w,req)
return return
case "": case "":
default_route(w,req,user) config.DefaultRoute(w,req,user)
return return
//default: NotFound(w,req) //default: NotFound(w,req)
} }

View File

@ -14,7 +14,6 @@ import (
"net" "net"
"net/http" "net/http"
"html" "html"
"html/template"
"./query_gen/lib" "./query_gen/lib"
) )
@ -26,6 +25,10 @@ var hvars HeaderVars
var extData ExtData var extData ExtData
var success_json_bytes []byte = []byte(`{"success":"1"}`) var success_json_bytes []byte = []byte(`{"success":"1"}`)
func init() {
hvars.Site = site
}
// GET functions // GET functions
func route_static(w http.ResponseWriter, r *http.Request){ func route_static(w http.ResponseWriter, r *http.Request){
//log.Print("Outputting static file '" + r.URL.Path + "'") //log.Print("Outputting static file '" + r.URL.Path + "'")
@ -160,7 +163,7 @@ func route_topics(w http.ResponseWriter, r *http.Request, user User){
topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
} }
} else { } else {
topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1) topicItem.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
} }
forum := fstore.DirtyGet(topicItem.ParentID) forum := fstore.DirtyGet(topicItem.ParentID)
@ -251,16 +254,16 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string)
// Calculate the offset // Calculate the offset
var offset int var offset int
last_page := int(forum.TopicCount / items_per_page) + 1 last_page := int(forum.TopicCount / config.ItemsPerPage) + 1
if page > 1 { if page > 1 {
offset = (items_per_page * page) - items_per_page offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else if page == -1 { } else if page == -1 {
page = last_page page = last_page
offset = (items_per_page * page) - items_per_page offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else { } else {
page = 1 page = 1
} }
rows, err := get_forum_topics_offset_stmt.Query(fid,offset,items_per_page) rows, err := get_forum_topics_offset_stmt.Query(fid,offset,config.ItemsPerPage)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)
return return
@ -283,7 +286,7 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string)
topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
} }
} else { } else {
topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1) topicItem.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
} }
topicItem.LastReplyAt, err = relative_time(topicItem.LastReplyAt) topicItem.LastReplyAt, err = relative_time(topicItem.LastReplyAt)
@ -416,7 +419,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
InternalError(err,w,r) InternalError(err,w,r)
return return
} }
topic.Css = no_css_tmpl topic.ClassName = ""
headerVars, ok := ForumSessionCheck(w,r,&user,topic.ParentID) headerVars, ok := ForumSessionCheck(w,r,&user,topic.ParentID)
if !ok { if !ok {
@ -440,7 +443,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
topic.Tag = groups[topic.Group].Tag topic.Tag = groups[topic.Group].Tag
if groups[topic.Group].Is_Mod || groups[topic.Group].Is_Admin { if groups[topic.Group].Is_Mod || groups[topic.Group].Is_Admin {
topic.Css = staff_css_tmpl topic.ClassName = config.StaffCss
} }
/*if settings["url_tags"] == false { /*if settings["url_tags"] == false {
@ -460,18 +463,18 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
} }
// Calculate the offset // Calculate the offset
last_page := int(topic.PostCount / items_per_page) + 1 last_page := int(topic.PostCount / config.ItemsPerPage) + 1
if page > 1 { if page > 1 {
offset = (items_per_page * page) - items_per_page offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else if page == -1 { } else if page == -1 {
page = last_page page = last_page
offset = (items_per_page * page) - items_per_page offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else { } else {
page = 1 page = 1
} }
// Get the replies.. // Get the replies..
rows, err := get_topic_replies_offset_stmt.Query(topic.ID, offset, items_per_page) rows, err := get_topic_replies_offset_stmt.Query(topic.ID, offset, config.ItemsPerPage)
if err == ErrNoRows { if err == ErrNoRows {
LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.",w,r,user) LocalError("Bad Page. Some of the posts may have been deleted or you got here by directly typing in the page number.",w,r,user)
return return
@ -480,7 +483,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
return return
} }
replyItem := Reply{Css: no_css_tmpl} replyItem := Reply{ClassName:""}
for rows.Next() { for rows.Next() {
err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &replyItem.Group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress, &replyItem.LikeCount, &replyItem.ActionType) err := rows.Scan(&replyItem.ID, &replyItem.Content, &replyItem.CreatedBy, &replyItem.CreatedAt, &replyItem.LastEdit, &replyItem.LastEditBy, &replyItem.Avatar, &replyItem.CreatedByName, &replyItem.Group, &replyItem.URLPrefix, &replyItem.URLName, &replyItem.Level, &replyItem.IpAddress, &replyItem.LikeCount, &replyItem.ActionType)
if err != nil { if err != nil {
@ -494,9 +497,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
replyItem.ContentLines = strings.Count(replyItem.Content,"\n") replyItem.ContentLines = strings.Count(replyItem.Content,"\n")
if groups[replyItem.Group].Is_Mod || groups[replyItem.Group].Is_Admin { if groups[replyItem.Group].Is_Mod || groups[replyItem.Group].Is_Admin {
replyItem.Css = staff_css_tmpl replyItem.ClassName = config.StaffCss
} else { } else {
replyItem.Css = no_css_tmpl replyItem.ClassName = ""
} }
if replyItem.Avatar != "" { if replyItem.Avatar != "" {
@ -504,7 +507,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar replyItem.Avatar = "/uploads/avatar_" + strconv.Itoa(replyItem.CreatedBy) + replyItem.Avatar
} }
} else { } else {
replyItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyItem.CreatedBy),1) replyItem.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(replyItem.CreatedBy),1)
} }
replyItem.Tag = groups[replyItem.Group].Tag replyItem.Tag = groups[replyItem.Group].Tag
@ -588,9 +591,8 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){
} }
var err error var err error
var replyContent, replyCreatedByName, replyCreatedAt, replyAvatar, replyTag string var replyContent, replyCreatedByName, replyCreatedAt, replyAvatar, replyTag, replyClassName string
var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int var rid, replyCreatedBy, replyLastEdit, replyLastEditBy, replyLines, replyGroup int
var replyCss template.CSS
var replyList []Reply var replyList []Reply
// SEO URLs... // SEO URLs...
@ -638,16 +640,16 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){
replyLines = strings.Count(replyContent,"\n") replyLines = strings.Count(replyContent,"\n")
if groups[replyGroup].Is_Mod || groups[replyGroup].Is_Admin { if groups[replyGroup].Is_Mod || groups[replyGroup].Is_Admin {
replyCss = staff_css_tmpl replyClassName = config.StaffCss
} else { } else {
replyCss = no_css_tmpl replyClassName = ""
} }
if replyAvatar != "" { if replyAvatar != "" {
if replyAvatar[0] == '.' { if replyAvatar[0] == '.' {
replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar
} }
} else { } else {
replyAvatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyCreatedBy),1) replyAvatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(replyCreatedBy),1)
} }
if groups[replyGroup].Tag != "" { if groups[replyGroup].Tag != "" {
@ -663,7 +665,7 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){
// TO-DO: Add a hook here // TO-DO: Add a hook here
replyList = append(replyList, Reply{rid,puser.ID,replyContent,parse_message(replyContent),replyCreatedBy,name_to_slug(replyCreatedByName),replyCreatedByName,replyGroup,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","","",0,"",replyLiked,replyLikeCount,"",""}) replyList = append(replyList, Reply{rid,puser.ID,replyContent,parse_message(replyContent),replyCreatedBy,name_to_slug(replyCreatedByName),replyCreatedByName,replyGroup,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyClassName,replyLines,replyTag,"","","",0,"",replyLiked,replyLikeCount,"",""})
} }
err = rows.Err() err = rows.Err()
if err != nil { if err != nil {
@ -1405,11 +1407,11 @@ func route_account_own_edit_avatar(w http.ResponseWriter, r *http.Request, user
} }
func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request, user User) { func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request, user User) {
if r.ContentLength > int64(max_request_size) { if r.ContentLength > int64(config.MaxRequestSize) {
http.Error(w,"Request too large",http.StatusExpectationFailed) http.Error(w,"Request too large",http.StatusExpectationFailed)
return return
} }
r.Body = http.MaxBytesReader(w, r.Body, int64(max_request_size)) r.Body = http.MaxBytesReader(w, r.Body, int64(config.MaxRequestSize))
headerVars, ok := SessionCheck(w,r,&user) headerVars, ok := SessionCheck(w,r,&user)
if !ok { if !ok {
@ -1420,7 +1422,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request
return return
} }
err := r.ParseMultipartForm(int64(max_request_size)) err := r.ParseMultipartForm(int64(config.MaxRequestSize))
if err != nil { if err != nil {
LocalError("Upload failed",w,r,user) LocalError("Upload failed",w,r,user)
return return
@ -1594,7 +1596,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request, user U
} }
// Was this site migrated from another forum software? Most of them don't have multiple emails for a single user. // Was this site migrated from another forum software? Most of them don't have multiple emails for a single user.
// This also applies when the admin switches enable_emails on after having it off for a while. // This also applies when the admin switches site.EnableEmails on after having it off for a while.
if len(emailList) == 0 { if len(emailList) == 0 {
email.Email = user.Email email.Email = user.Email
email.Validated = false email.Validated = false
@ -1602,7 +1604,7 @@ func route_account_own_edit_email(w http.ResponseWriter, r *http.Request, user U
emailList = append(emailList, email) emailList = append(emailList, email)
} }
if !enable_emails { if !site.EnableEmails {
headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.") headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.")
} }
pi := Page{"Email Manager",user,headerVars,emailList,nil} pi := Page{"Email Manager",user,headerVars,emailList,nil}
@ -1680,7 +1682,7 @@ func route_account_own_edit_email_token_submit(w http.ResponseWriter, r *http.Re
} }
} }
if !enable_emails { if !site.EnableEmails {
headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.") headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.")
} }
headerVars.NoticeList = append(headerVars.NoticeList,"Your email was successfully verified") headerVars.NoticeList = append(headerVars.NoticeList,"Your email was successfully verified")
@ -1823,9 +1825,9 @@ func route_register_submit(w http.ResponseWriter, r *http.Request, user User) {
switch settings["activation_type"] { switch settings["activation_type"] {
case 1: // Activate All case 1: // Activate All
active = 1 active = 1
group = default_group group = config.DefaultGroup
default: // Anything else. E.g. Admin Activation or Email Activation. default: // Anything else. E.g. Admin Activation or Email Activation.
group = activation_group group = config.ActivationGroup
} }
uid, err := users.CreateUser(username, password, email, group, active) uid, err := users.CreateUser(username, password, email, group, active)
@ -1838,7 +1840,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request, user User) {
} }
// Check if this user actually owns this email, if email activation is on, automatically flip their account to active when the email is validated. Validation is also useful for determining whether this user should receive any alerts, etc. via email // Check if this user actually owns this email, if email activation is on, automatically flip their account to active when the email is validated. Validation is also useful for determining whether this user should receive any alerts, etc. via email
if enable_emails { if site.EnableEmails {
token, err := GenerateSafeString(80) token, err := GenerateSafeString(80)
if err != nil { if err != nil {
InternalError(err,w,r) InternalError(err,w,r)

View File

@ -0,0 +1,12 @@
CREATE TABLE `users_penalties` (
`uid` int not null,
`element_id` int not null,
`element_type` varchar(50) not null,
`overrides` text not null,
`mod_queue` boolean DEFAULT 0 not null,
`shadow_ban` boolean DEFAULT 0 not null,
`no_avatar` boolean DEFAULT 0 not null,
`issued_by` int not null,
`issued_at` datetime not null,
`expiry` duration not null
);

View File

@ -0,0 +1,12 @@
CREATE TABLE `users_penalties` (
`uid` int not null,
`element_id` int not null,
`element_type` varchar (50) not null,
`overrides` text DEFAULT '{}' not null,
`mod_queue` boolean DEFAULT 0 not null,
`shadow_ban` boolean DEFAULT 0 not null,
`no_avatar` boolean DEFAULT 0 not null,
`issued_by` int not null,
`issued_at` timestamp not null,
`expiry` duration not null
);

61
site.go Normal file
View File

@ -0,0 +1,61 @@
package main
import "net/http"
var site *Site = &Site{Name:"Magical Fairy Land"}
var db_config DB_Config = DB_Config{Host:"localhost"}
var config Config
var dev DevConfig
type Site struct
{
Name string
Email string
Url string
Port string
EnableSsl bool
EnableEmails bool
}
type DB_Config struct
{
Host string
Username string
Password string
Dbname string
Port string
}
type Config struct
{
SslPrivkey string
SslFullchain string
MaxRequestSize int
CacheTopicUser int
UserCacheCapacity int
TopicCacheCapacity int
SmtpServer string
SmtpUsername string
SmtpPassword string
SmtpPort string
DefaultRoute func(http.ResponseWriter, *http.Request, User)
DefaultGroup int
ActivationGroup int
StaffCss string
UncategorisedForumVisible bool
MinifyTemplates bool
MultiServer bool
Noavatar string
ItemsPerPage int
}
type DevConfig struct
{
DebugMode bool
SuperDebug bool
Profiling bool
}

View File

@ -2,8 +2,8 @@
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
// +build !no_templategen // +build !no_templategen
package main package main
import "strconv"
import "io" import "io"
import "strconv"
func init() { func init() {
template_forum_handle = template_forum template_forum_handle = template_forum
@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session)) w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_forum_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_forum_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_forum_vars.CurrentUser.Slug)) if tmpl_forum_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.CurrentUser.ID))) w.Write([]byte(tmpl_forum_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_forum_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_forum_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_forum_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_forum_vars.Header.Widgets.RightSidebar != "" { if tmpl_forum_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)
@ -92,13 +94,13 @@ w.Write(forum_11)
if tmpl_forum_vars.CurrentUser.ID != 0 { if tmpl_forum_vars.CurrentUser.ID != 0 {
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic { if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
w.Write(forum_12) w.Write(forum_12)
} else { w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
w.Write(forum_13) w.Write(forum_13)
} } else {
w.Write(forum_14) w.Write(forum_14)
} }
w.Write(forum_15) w.Write(forum_15)
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID))) }
w.Write(forum_16) w.Write(forum_16)
if len(tmpl_forum_vars.ItemList) != 0 { if len(tmpl_forum_vars.ItemList) != 0 {
for _, item := range tmpl_forum_vars.ItemList { for _, item := range tmpl_forum_vars.ItemList {

View File

@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_forums_vars.CurrentUser.Session)) w.Write([]byte(tmpl_forums_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_forums_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_forums_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_forums_vars.CurrentUser.Slug)) if tmpl_forums_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_forums_vars.CurrentUser.ID))) w.Write([]byte(tmpl_forums_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_forums_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_forums_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_forums_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_forums_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_forums_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)
@ -81,36 +83,28 @@ w.Write(forums_6)
w.Write([]byte(item.Desc)) w.Write([]byte(item.Desc))
w.Write(forums_7) w.Write(forums_7)
} else { } else {
if item.LastTopicTime != "" {
w.Write(forums_8) w.Write(forums_8)
w.Write([]byte(item.Link)) w.Write([]byte(item.Link))
w.Write(forums_9) w.Write(forums_9)
w.Write([]byte(item.Name)) w.Write([]byte(item.Name))
w.Write(forums_10) w.Write(forums_10)
} else { }
w.Write(forums_11) w.Write(forums_11)
w.Write([]byte(item.Link))
w.Write(forums_12)
w.Write([]byte(item.Name))
w.Write(forums_13)
}
}
w.Write(forums_14)
w.Write([]byte(item.LastTopicSlug)) w.Write([]byte(item.LastTopicSlug))
w.Write(forums_15) w.Write(forums_12)
w.Write([]byte(item.LastTopic)) w.Write([]byte(item.LastTopic))
w.Write(forums_16) w.Write(forums_13)
if item.LastTopicTime != "" { if item.LastTopicTime != "" {
w.Write(forums_17) w.Write(forums_14)
w.Write([]byte(item.LastTopicTime)) w.Write([]byte(item.LastTopicTime))
w.Write(forums_18) w.Write(forums_15)
} }
w.Write(forums_19) w.Write(forums_16)
} }
} else { } else {
w.Write(forums_20) w.Write(forums_17)
} }
w.Write(forums_21) w.Write(forums_18)
w.Write(footer_0) w.Write(footer_0)
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" { if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
w.Write(footer_1) w.Write(footer_1)

View File

@ -32,30 +32,32 @@ var menu_0 []byte = []byte(`<div class="nav">
<div class="move_left"> <div class="move_left">
<div class="move_right"> <div class="move_right">
<ul> <ul>
<li class="menu_left menu_overview"><a href="/">Overview</a></li> <li class="menu_left menu_overview"><a href="/">`)
var menu_1 []byte = []byte(`</a></li>
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li> <li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
<li class="menu_left menu_topics"><a href="/">Topics</a></li> <li class="menu_left menu_topics"><a href="/">Topics</a></li>
<li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li> <li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li>
`) `)
var menu_1 []byte = []byte(` var menu_2 []byte = []byte(`
<li class="menu_left menu_account"><a href="/user/edit/critical/">Account</a></li> <li class="menu_left menu_account"><a href="/user/edit/critical/">Account</a></li>
<li class="menu_left menu_profile"><a href="/user/`) <li class="menu_left menu_profile"><a href="/user/`)
var menu_2 []byte = []byte(`.`) var menu_3 []byte = []byte(`.`)
var menu_3 []byte = []byte(`">Profile</a></li> var menu_4 []byte = []byte(`">Profile</a></li>
`) `)
var menu_4 []byte = []byte(`<li class="menu_left menu_account"><a href="/panel/">Panel</a></li>`) var menu_5 []byte = []byte(`<li class="menu_left menu_account"><a href="/panel/">Panel</a></li>`)
var menu_5 []byte = []byte(` var menu_6 []byte = []byte(`
<li class="menu_left menu_logout"><a href="/accounts/logout/?session=`) <li class="menu_left menu_logout"><a href="/accounts/logout/?session=`)
var menu_6 []byte = []byte(`">Logout</a></li> var menu_7 []byte = []byte(`">Logout</a></li>
`) `)
var menu_7 []byte = []byte(` var menu_8 []byte = []byte(`
<li class="menu_left menu_register"><a href="/accounts/create/">Register</a></li> <li class="menu_left menu_register"><a href="/accounts/create/">Register</a></li>
<li class="menu_left menu_login"><a href="/accounts/login/">Login</a></li> <li class="menu_left menu_login"><a href="/accounts/login/">Login</a></li>
`) `)
var menu_8 []byte = []byte(` var menu_9 []byte = []byte(`
<li id="general_alerts" class="menu_right menu_alerts"> <li id="general_alerts" class="menu_right menu_alerts">
<div class="alert_bell">🔔</div> <div class="alert_bell"></div>
<div class="alert_counter"></div> <div class="alert_counter"></div>
<div class="alert_aftercounter"></div>
<div class="alertList"></div> <div class="alertList"></div>
</li> </li>
</ul> </ul>
@ -87,10 +89,10 @@ var topic_8 []byte = []byte(`
<div class="rowblock rowhead topic_block"> <div class="rowblock rowhead topic_block">
<form action='/topic/edit/submit/`) <form action='/topic/edit/submit/`)
var topic_9 []byte = []byte(`' method="post"> var topic_9 []byte = []byte(`' method="post">
<div class="rowitem topic_item"`) <div class="rowitem topic_item`)
var topic_10 []byte = []byte(` style="background-color:#FFFFEA;"`) var topic_10 []byte = []byte(` topic_sticky_head`)
var topic_11 []byte = []byte(` style="background-color:#eaeaea;"`) var topic_11 []byte = []byte(` topic_closed_head`)
var topic_12 []byte = []byte(`> var topic_12 []byte = []byte(`">
<a class='topic_name hide_on_edit'>`) <a class='topic_name hide_on_edit'>`)
var topic_13 []byte = []byte(`</a> var topic_13 []byte = []byte(`</a>
`) `)
@ -111,114 +113,116 @@ var topic_19 []byte = []byte(`
</form> </form>
</div> </div>
<div class="rowblock post_container top_post"> <div class="rowblock post_container top_post">
<div class="rowitem passive editable_parent post_item" style="border-bottom: none;`) <div class="rowitem passive editable_parent post_item `)
var topic_20 []byte = []byte(`background-image:url(`) var topic_20 []byte = []byte(`" style="`)
var topic_21 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `) var topic_21 []byte = []byte(`background-image:url(`)
var topic_22 []byte = []byte(`-1`) var topic_22 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_23 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;`) var topic_23 []byte = []byte(`-1`)
var topic_24 []byte = []byte(`"> var topic_24 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;`)
var topic_25 []byte = []byte(`">
<p class="hide_on_edit topic_content user_content" style="margin:0;padding:0;">`) <p class="hide_on_edit topic_content user_content" style="margin:0;padding:0;">`)
var topic_25 []byte = []byte(`</p> var topic_26 []byte = []byte(`</p>
<textarea name="topic_content" class="show_on_edit topic_content_input">`) <textarea name="topic_content" class="show_on_edit topic_content_input">`)
var topic_26 []byte = []byte(`</textarea> var topic_27 []byte = []byte(`</textarea>
<span class="controls"> <span class="controls">
<a href="/user/`) <a href="/user/`)
var topic_27 []byte = []byte(`.`) var topic_28 []byte = []byte(`.`)
var topic_28 []byte = []byte(`" class="username real_username">`) var topic_29 []byte = []byte(`" class="username real_username">`)
var topic_29 []byte = []byte(`</a>&nbsp;&nbsp; var topic_30 []byte = []byte(`</a>&nbsp;&nbsp;
`) `)
var topic_30 []byte = []byte(`<a href="/topic/like/submit/`) var topic_31 []byte = []byte(`<a href="/topic/like/submit/`)
var topic_31 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;"> var topic_32 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;">
<button class="username like_label" style="`) <button class="username like_label" style="`)
var topic_32 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`) var topic_33 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_33 []byte = []byte(`"></button></a>`) var topic_34 []byte = []byte(`"></button></a>`)
var topic_34 []byte = []byte(`<a href='/topic/edit/`) var topic_35 []byte = []byte(`<a href='/topic/edit/`)
var topic_35 []byte = []byte(`' class="mod_button open_edit" style="font-weight:normal;" title="Edit Topic"><button class="username edit_label"></button></a>`) var topic_36 []byte = []byte(`' class="mod_button open_edit" style="font-weight:normal;" title="Edit Topic"><button class="username edit_label"></button></a>`)
var topic_36 []byte = []byte(`<a href='/topic/delete/submit/`) var topic_37 []byte = []byte(`<a href='/topic/delete/submit/`)
var topic_37 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Delete Topic"><button class="username trash_label"></button></a>`) var topic_38 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Delete Topic"><button class="username trash_label"></button></a>`)
var topic_38 []byte = []byte(`<a class="mod_button" href='/topic/unstick/submit/`) var topic_39 []byte = []byte(`<a class="mod_button" href='/topic/unstick/submit/`)
var topic_39 []byte = []byte(`' style="font-weight:normal;" title="Unpin Topic"><button class="username unpin_label"></button></a>`) var topic_40 []byte = []byte(`' style="font-weight:normal;" title="Unpin Topic"><button class="username unpin_label"></button></a>`)
var topic_40 []byte = []byte(`<a href='/topic/stick/submit/`) var topic_41 []byte = []byte(`<a href='/topic/stick/submit/`)
var topic_41 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Pin Topic"><button class="username pin_label"></button></a>`) var topic_42 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Pin Topic"><button class="username pin_label"></button></a>`)
var topic_42 []byte = []byte(` var topic_43 []byte = []byte(`
<a class="mod_button" href="/report/submit/`) <a class="mod_button" href="/report/submit/`)
var topic_43 []byte = []byte(`?session=`) var topic_44 []byte = []byte(`?session=`)
var topic_44 []byte = []byte(`&type=topic" class="mod_button report_item" style="font-weight:normal;" title="Flag Topic"><button class="username flag_label"></button></a> var topic_45 []byte = []byte(`&type=topic" class="mod_button report_item" style="font-weight:normal;" title="Flag Topic"><button class="username flag_label"></button></a>
`) `)
var topic_45 []byte = []byte(`<a class="username hide_on_micro like_count">`) var topic_46 []byte = []byte(`<a class="username hide_on_micro like_count">`)
var topic_46 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`) var topic_47 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`)
var topic_47 []byte = []byte(`<a class="username hide_on_micro" style="float:right;color:#505050;font-size:16px;">`) var topic_48 []byte = []byte(`<a class="username hide_on_micro user_tag">`)
var topic_48 []byte = []byte(`</a>`) var topic_49 []byte = []byte(`</a>`)
var topic_49 []byte = []byte(`<a class="username hide_on_micro level">`) var topic_50 []byte = []byte(`<a class="username hide_on_micro level">`)
var topic_50 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="color:#505050;float:right;opacity:0.85;" title="Level"></a>`) var topic_51 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="float:right;" title="Level"></a>`)
var topic_51 []byte = []byte(` var topic_52 []byte = []byte(`
</span> </span>
</div> </div>
</div> </div>
<div class="rowblock post_container" style="overflow: hidden;">`) <div class="rowblock post_container" style="overflow: hidden;">`)
var topic_52 []byte = []byte(` var topic_53 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent post_item action_item"> <div class="rowitem passive deletable_block editable_parent post_item action_item">
<span class="action_icon" style="font-size: 18px;padding-right: 5px;">`) <span class="action_icon" style="font-size: 18px;padding-right: 5px;">`)
var topic_53 []byte = []byte(`</span>
<span>`)
var topic_54 []byte = []byte(`</span> var topic_54 []byte = []byte(`</span>
<span>`)
var topic_55 []byte = []byte(`</span>
</div> </div>
`) `)
var topic_55 []byte = []byte(` var topic_56 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent post_item" style="`) <div class="rowitem passive deletable_block editable_parent post_item `)
var topic_56 []byte = []byte(`background-image:url(`) var topic_57 []byte = []byte(`" style="`)
var topic_57 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `) var topic_58 []byte = []byte(`background-image:url(`)
var topic_58 []byte = []byte(`-1`) var topic_59 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_59 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;`) var topic_60 []byte = []byte(`-1`)
var topic_60 []byte = []byte(`"> var topic_61 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;`)
var topic_62 []byte = []byte(`">
<p class="editable_block user_content" style="margin:0;padding:0;">`) <p class="editable_block user_content" style="margin:0;padding:0;">`)
var topic_61 []byte = []byte(`</p> var topic_63 []byte = []byte(`</p>
<span class="controls"> <span class="controls">
<a href="/user/`) <a href="/user/`)
var topic_62 []byte = []byte(`.`) var topic_64 []byte = []byte(`.`)
var topic_63 []byte = []byte(`" class="username real_username">`) var topic_65 []byte = []byte(`" class="username real_username">`)
var topic_64 []byte = []byte(`</a>&nbsp;&nbsp; var topic_66 []byte = []byte(`</a>&nbsp;&nbsp;
`) `)
var topic_65 []byte = []byte(`<a href="/reply/like/submit/`) var topic_67 []byte = []byte(`<a href="/reply/like/submit/`)
var topic_66 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;"><button class="username like_label" style="`) var topic_68 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;"><button class="username like_label" style="`)
var topic_67 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`) var topic_69 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_68 []byte = []byte(`"></button></a>`) var topic_70 []byte = []byte(`"></button></a>`)
var topic_69 []byte = []byte(`<a href="/reply/edit/submit/`) var topic_71 []byte = []byte(`<a href="/reply/edit/submit/`)
var topic_70 []byte = []byte(`" class="mod_button" title="Edit Reply"><button class="username edit_item edit_label"></button></a>`) var topic_72 []byte = []byte(`" class="mod_button" title="Edit Reply"><button class="username edit_item edit_label"></button></a>`)
var topic_71 []byte = []byte(`<a href="/reply/delete/submit/`) var topic_73 []byte = []byte(`<a href="/reply/delete/submit/`)
var topic_72 []byte = []byte(`" class="mod_button" title="Delete Reply"><button class="username delete_item trash_label"></button></a>`) var topic_74 []byte = []byte(`" class="mod_button" title="Delete Reply"><button class="username delete_item trash_label"></button></a>`)
var topic_73 []byte = []byte(` var topic_75 []byte = []byte(`
<a class="mod_button" href="/report/submit/`) <a class="mod_button" href="/report/submit/`)
var topic_74 []byte = []byte(`?session=`) var topic_76 []byte = []byte(`?session=`)
var topic_75 []byte = []byte(`&type=reply" class="mod_button report_item" title="Flag Reply"><button class="username report_item flag_label"></button></a> var topic_77 []byte = []byte(`&type=reply" class="mod_button report_item" title="Flag Reply"><button class="username report_item flag_label"></button></a>
`) `)
var topic_76 []byte = []byte(`<a class="username hide_on_micro like_count">`) var topic_78 []byte = []byte(`<a class="username hide_on_micro like_count">`)
var topic_77 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`) var topic_79 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`)
var topic_78 []byte = []byte(`<a class="username hide_on_micro" style="float: right;color:#505050;font-size:16px;">`) var topic_80 []byte = []byte(`<a class="username hide_on_micro user_tag">`)
var topic_79 []byte = []byte(`</a>`) var topic_81 []byte = []byte(`</a>`)
var topic_80 []byte = []byte(`<a class="username hide_on_micro level">`) var topic_82 []byte = []byte(`<a class="username hide_on_micro level">`)
var topic_81 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="color:#505050;float:right;opacity:0.85;" title="Level">`) var topic_83 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="float:right;" title="Level">`)
var topic_82 []byte = []byte(`</a> var topic_84 []byte = []byte(`</a>
</span> </span>
</div> </div>
`) `)
var topic_83 []byte = []byte(`</div> var topic_85 []byte = []byte(`</div>
`) `)
var topic_84 []byte = []byte(` var topic_86 []byte = []byte(`
<div class="rowblock"> <div class="rowblock topic_reply_form">
<form action="/reply/create/" method="post"> <form action="/reply/create/" method="post">
<input name="tid" value='`) <input name="tid" value='`)
var topic_85 []byte = []byte(`' type="hidden" /> var topic_87 []byte = []byte(`' type="hidden" />
<div class="formrow"> <div class="formrow real_first_child">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div> <div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
</div> </div>
<div class="formrow"> <div class="formrow">
@ -278,7 +282,7 @@ var topic_alt_19 []byte = []byte(`
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style> <style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
<div class="rowblock post_container" style="border-top: none;"> <div class="rowblock post_container" style="border-top: none;">
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;"> <div class="rowitem passive deletable_block editable_parent post_item top_post" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
<div class="userinfo"> <div class="userinfo">
<div class="avatar_item" style="background-image: url(`) <div class="avatar_item" style="background-image: url(`)
var topic_alt_20 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;">&nbsp;</div> var topic_alt_20 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px -10px;">&nbsp;</div>
@ -391,7 +395,7 @@ var topic_alt_86 []byte = []byte(`
var topic_alt_87 []byte = []byte(`</div> var topic_alt_87 []byte = []byte(`</div>
`) `)
var topic_alt_88 []byte = []byte(` var topic_alt_88 []byte = []byte(`
<div class="rowblock" style="border-top: none;"> <div class="rowblock topic_reply_form" style="border-top: none;">
<form action="/reply/create/" method="post"> <form action="/reply/create/" method="post">
<input name="tid" value='`) <input name="tid" value='`)
var topic_alt_89 []byte = []byte(`' type="hidden" /> var topic_alt_89 []byte = []byte(`' type="hidden" />
@ -446,45 +450,46 @@ var profile_16 []byte = []byte(`&type=user" class="profile_menu_item report_item
</div> </div>
<div id="profile_comments" class="colblock_right" style="overflow: hidden;border-top: none;width:calc(95% - 210px);">`) <div id="profile_comments" class="colblock_right" style="overflow: hidden;border-top: none;width:calc(95% - 210px);">`)
var profile_17 []byte = []byte(` var profile_17 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent simple" style="`) <div class="rowitem passive deletable_block editable_parent simple `)
var profile_18 []byte = []byte(`background-image: url(`) var profile_18 []byte = []byte(`" style="`)
var profile_19 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `) var profile_19 []byte = []byte(`background-image: url(`)
var profile_20 []byte = []byte(`-1`) var profile_20 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var profile_21 []byte = []byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;`) var profile_21 []byte = []byte(`-1`)
var profile_22 []byte = []byte(`"> var profile_22 []byte = []byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;`)
var profile_23 []byte = []byte(`">
<span class="editable_block user_content simple">`) <span class="editable_block user_content simple">`)
var profile_23 []byte = []byte(`</span><br /><br /> var profile_24 []byte = []byte(`</span><br /><br />
<a href="/user/`) <a href="/user/`)
var profile_24 []byte = []byte(`.`) var profile_25 []byte = []byte(`.`)
var profile_25 []byte = []byte(`" class="real_username username">`) var profile_26 []byte = []byte(`" class="real_username username">`)
var profile_26 []byte = []byte(`</a>&nbsp;&nbsp; var profile_27 []byte = []byte(`</a>&nbsp;&nbsp;
`) `)
var profile_27 []byte = []byte(`<a href="/profile/reply/edit/submit/`) var profile_28 []byte = []byte(`<a href="/profile/reply/edit/submit/`)
var profile_28 []byte = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a> var profile_29 []byte = []byte(`" class="mod_button" title="Edit Item"><button class="username edit_item edit_label"></button></a>
<a href="/profile/reply/delete/submit/`) <a href="/profile/reply/delete/submit/`)
var profile_29 []byte = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`) var profile_30 []byte = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`)
var profile_30 []byte = []byte(` var profile_31 []byte = []byte(`
<a class="mod_button" href="/report/submit/`) <a class="mod_button" href="/report/submit/`)
var profile_31 []byte = []byte(`?session=`) var profile_32 []byte = []byte(`?session=`)
var profile_32 []byte = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a> var profile_33 []byte = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a>
`) `)
var profile_33 []byte = []byte(`<a class="username hide_on_mobile" style="float: right;">`) var profile_34 []byte = []byte(`<a class="username hide_on_mobile" style="float: right;">`)
var profile_34 []byte = []byte(`</a>`) var profile_35 []byte = []byte(`</a>`)
var profile_35 []byte = []byte(` var profile_36 []byte = []byte(`
</div> </div>
`) `)
var profile_36 []byte = []byte(`</div> var profile_37 []byte = []byte(`</div>
<div class="colblock_right" style="border-top: none;width: calc(95% - 210px);"> <div class="colblock_right" style="border-top: none;width: calc(95% - 210px);">
`) `)
var profile_37 []byte = []byte(` var profile_38 []byte = []byte(`
<form action="/profile/reply/create/" method="post"> <form action="/profile/reply/create/" method="post">
<input name="uid" value='`) <input name="uid" value='`)
var profile_38 []byte = []byte(`' type="hidden" /> var profile_39 []byte = []byte(`' type="hidden" />
<div class="formrow"> <div class="formrow">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div> <div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
</div> </div>
@ -493,7 +498,7 @@ var profile_38 []byte = []byte(`' type="hidden" />
</div> </div>
</form> </form>
`) `)
var profile_39 []byte = []byte(` var profile_40 []byte = []byte(`
</div> </div>
`) `)
@ -514,32 +519,28 @@ var forums_6 []byte = []byte(`</a>
<br /><span class="rowsmall">`) <br /><span class="rowsmall">`)
var forums_7 []byte = []byte(`</span> var forums_7 []byte = []byte(`</span>
</span>`) </span>`)
var forums_8 []byte = []byte(`<span style="float: left;padding-top: 8px;font-size: 18px;"> var forums_8 []byte = []byte(`<span style="float: left;">
<a href="`) <a href="`)
var forums_9 []byte = []byte(`">`) var forums_9 []byte = []byte(`">`)
var forums_10 []byte = []byte(`</a> var forums_10 []byte = []byte(`</a>
<br /><span class="rowsmall" style="font-style: italic;">No description</span>
</span>`) </span>`)
var forums_11 []byte = []byte(`<span style="float: left;"> var forums_11 []byte = []byte(`
<a href="`)
var forums_12 []byte = []byte(`">`)
var forums_13 []byte = []byte(`</a>
</span>`)
var forums_14 []byte = []byte(`
<span style="float: right;"> <span style="float: right;">
<a href="/topic/`) <a href="/topic/`)
var forums_15 []byte = []byte(`" style="float: right;font-size: 14px;">`) var forums_12 []byte = []byte(`" style="float: right;font-size: 14px;">`)
var forums_16 []byte = []byte(`</a> var forums_13 []byte = []byte(`</a>
`) `)
var forums_17 []byte = []byte(`<br /><span class="rowsmall">`) var forums_14 []byte = []byte(`<br /><span class="rowsmall">`)
var forums_18 []byte = []byte(`</span>`) var forums_15 []byte = []byte(`</span>`)
var forums_19 []byte = []byte(` var forums_16 []byte = []byte(`
</span> </span>
<div style="clear: both;"></div> <div style="clear: both;"></div>
</div> </div>
`) `)
var forums_20 []byte = []byte(`<div class="rowitem passive">You don't have access to any forums.</div>`) var forums_17 []byte = []byte(`<div class="rowitem passive">You don't have access to any forums.</div>`)
var forums_21 []byte = []byte(` var forums_18 []byte = []byte(`
</div> </div>
`) `)
var topics_0 []byte = []byte(` var topics_0 []byte = []byte(`
@ -605,15 +606,14 @@ var forum_11 []byte = []byte(`</a>
</div> </div>
`) `)
var forum_12 []byte = []byte(` var forum_12 []byte = []byte(`
<div class="opt create_topic_opt" title="Create Topic">&#x1F58A;&#xFE0E</div> <div class="opt create_topic_opt" title="Create Topic"><a href="/topics/create/`)
var forum_13 []byte = []byte(`">&#x1F58A;&#xFE0E</a></div>
`) `)
var forum_13 []byte = []byte(`<div class="opt locked_opt" title="You don't have the permissions needed to create a topic">&#x1F512;&#xFE0E</div>`) var forum_14 []byte = []byte(`<div class="opt locked_opt" title="You don't have the permissions needed to create a topic">&#x1F512;&#xFE0E</div>`)
var forum_14 []byte = []byte(` var forum_15 []byte = []byte(`
<div style="clear: both;"></div> <div style="clear: both;"></div>
`) `)
var forum_15 []byte = []byte(` var forum_16 []byte = []byte(`
<!--href="/topics/create/`)
var forum_16 []byte = []byte(`"-->
</div> </div>
<div id="forum_topic_list" class="rowblock topic_list"> <div id="forum_topic_list" class="rowblock topic_list">
`) `)

View File

@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session)) w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_profile_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_profile_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Slug)) if tmpl_profile_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.CurrentUser.ID))) w.Write([]byte(tmpl_profile_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_profile_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_profile_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_profile_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" { if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)
@ -100,52 +102,53 @@ w.Write(profile_16)
if len(tmpl_profile_vars.ItemList) != 0 { if len(tmpl_profile_vars.ItemList) != 0 {
for _, item := range tmpl_profile_vars.ItemList { for _, item := range tmpl_profile_vars.ItemList {
w.Write(profile_17) w.Write(profile_17)
if item.Avatar != "" { w.Write([]byte(item.ClassName))
w.Write(profile_18) w.Write(profile_18)
w.Write([]byte(item.Avatar)) if item.Avatar != "" {
w.Write(profile_19) w.Write(profile_19)
if item.ContentLines <= 5 { w.Write([]byte(item.Avatar))
w.Write(profile_20) w.Write(profile_20)
} if item.ContentLines <= 5 {
w.Write(profile_21) w.Write(profile_21)
w.Write([]byte(string(item.Css)))
} }
w.Write(profile_22) w.Write(profile_22)
w.Write([]byte(item.ContentHtml)) }
w.Write(profile_23) w.Write(profile_23)
w.Write([]byte(item.UserSlug)) w.Write([]byte(item.ContentHtml))
w.Write(profile_24) w.Write(profile_24)
w.Write([]byte(strconv.Itoa(item.CreatedBy))) w.Write([]byte(item.UserSlug))
w.Write(profile_25) w.Write(profile_25)
w.Write([]byte(item.CreatedByName)) w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write(profile_26) w.Write(profile_26)
if tmpl_profile_vars.CurrentUser.Is_Mod { w.Write([]byte(item.CreatedByName))
w.Write(profile_27) w.Write(profile_27)
w.Write([]byte(strconv.Itoa(item.ID))) if tmpl_profile_vars.CurrentUser.Is_Mod {
w.Write(profile_28) w.Write(profile_28)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_29) w.Write(profile_29)
}
w.Write(profile_30)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_31) w.Write(profile_30)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_32)
if item.Tag != "" {
w.Write(profile_33)
w.Write([]byte(item.Tag))
w.Write(profile_34)
} }
w.Write(profile_31)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_32)
w.Write([]byte(tmpl_profile_vars.CurrentUser.Session))
w.Write(profile_33)
if item.Tag != "" {
w.Write(profile_34)
w.Write([]byte(item.Tag))
w.Write(profile_35) w.Write(profile_35)
} }
}
w.Write(profile_36) w.Write(profile_36)
if !tmpl_profile_vars.CurrentUser.Is_Banned {
w.Write(profile_37)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_38)
} }
}
w.Write(profile_37)
if !tmpl_profile_vars.CurrentUser.Is_Banned {
w.Write(profile_38)
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.ProfileOwner.ID)))
w.Write(profile_39) w.Write(profile_39)
}
w.Write(profile_40)
w.Write(footer_0) w.Write(footer_0)
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" { if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
w.Write(footer_1) w.Write(footer_1)

View File

@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_topic_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_topic_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Slug)) if tmpl_topic_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.CurrentUser.ID))) w.Write([]byte(tmpl_topic_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_topic_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_topic_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_topic_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_topic_vars.Header.Widgets.RightSidebar != "" { if tmpl_topic_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)
@ -108,153 +110,155 @@ w.Write(topic_17)
w.Write(topic_18) w.Write(topic_18)
} }
w.Write(topic_19) w.Write(topic_19)
if tmpl_topic_vars.Topic.Avatar != "" { w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
w.Write(topic_20) w.Write(topic_20)
w.Write([]byte(tmpl_topic_vars.Topic.Avatar)) if tmpl_topic_vars.Topic.Avatar != "" {
w.Write(topic_21) w.Write(topic_21)
if tmpl_topic_vars.Topic.ContentLines <= 5 { w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
w.Write(topic_22) w.Write(topic_22)
} if tmpl_topic_vars.Topic.ContentLines <= 5 {
w.Write(topic_23) w.Write(topic_23)
w.Write([]byte(string(tmpl_topic_vars.Topic.Css)))
} }
w.Write(topic_24) w.Write(topic_24)
w.Write([]byte(tmpl_topic_vars.Topic.Content)) }
w.Write(topic_25) w.Write(topic_25)
w.Write([]byte(tmpl_topic_vars.Topic.Content)) w.Write([]byte(tmpl_topic_vars.Topic.Content))
w.Write(topic_26) w.Write(topic_26)
w.Write([]byte(tmpl_topic_vars.Topic.UserSlug)) w.Write([]byte(tmpl_topic_vars.Topic.Content))
w.Write(topic_27) w.Write(topic_27)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.CreatedBy))) w.Write([]byte(tmpl_topic_vars.Topic.UserSlug))
w.Write(topic_28) w.Write(topic_28)
w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName)) w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.CreatedBy)))
w.Write(topic_29) w.Write(topic_29)
if tmpl_topic_vars.CurrentUser.Perms.LikeItem { w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName))
w.Write(topic_30) w.Write(topic_30)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
w.Write(topic_31) w.Write(topic_31)
if tmpl_topic_vars.Topic.Liked { w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_32) w.Write(topic_32)
} if tmpl_topic_vars.Topic.Liked {
w.Write(topic_33) w.Write(topic_33)
} }
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
w.Write(topic_34) w.Write(topic_34)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) }
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
w.Write(topic_35) w.Write(topic_35)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_36)
} }
if tmpl_topic_vars.CurrentUser.Perms.DeleteTopic { if tmpl_topic_vars.CurrentUser.Perms.DeleteTopic {
w.Write(topic_36)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_37) w.Write(topic_37)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_38)
} }
if tmpl_topic_vars.CurrentUser.Perms.PinTopic { if tmpl_topic_vars.CurrentUser.Perms.PinTopic {
if tmpl_topic_vars.Topic.Sticky { if tmpl_topic_vars.Topic.Sticky {
w.Write(topic_38)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_39) w.Write(topic_39)
} else { w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_40) w.Write(topic_40)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) } else {
w.Write(topic_41) w.Write(topic_41)
}
}
w.Write(topic_42)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_42)
}
}
w.Write(topic_43) w.Write(topic_43)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_44) w.Write(topic_44)
if tmpl_topic_vars.Topic.LikeCount > 0 { w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(topic_45) w.Write(topic_45)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount))) if tmpl_topic_vars.Topic.LikeCount > 0 {
w.Write(topic_46) w.Write(topic_46)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount)))
w.Write(topic_47)
} }
if tmpl_topic_vars.Topic.Tag != "" { if tmpl_topic_vars.Topic.Tag != "" {
w.Write(topic_47)
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
w.Write(topic_48) w.Write(topic_48)
} else { w.Write([]byte(tmpl_topic_vars.Topic.Tag))
w.Write(topic_49) w.Write(topic_49)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level))) } else {
w.Write(topic_50) w.Write(topic_50)
} w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
w.Write(topic_51) w.Write(topic_51)
}
w.Write(topic_52)
if len(tmpl_topic_vars.ItemList) != 0 { if len(tmpl_topic_vars.ItemList) != 0 {
for _, item := range tmpl_topic_vars.ItemList { for _, item := range tmpl_topic_vars.ItemList {
if item.ActionType != "" { if item.ActionType != "" {
w.Write(topic_52)
w.Write([]byte(item.ActionIcon))
w.Write(topic_53) w.Write(topic_53)
w.Write([]byte(item.ActionType)) w.Write([]byte(item.ActionIcon))
w.Write(topic_54) w.Write(topic_54)
} else { w.Write([]byte(item.ActionType))
w.Write(topic_55) w.Write(topic_55)
if item.Avatar != "" { } else {
w.Write(topic_56) w.Write(topic_56)
w.Write([]byte(item.Avatar)) w.Write([]byte(item.ClassName))
w.Write(topic_57) w.Write(topic_57)
if item.ContentLines <= 5 { if item.Avatar != "" {
w.Write(topic_58) w.Write(topic_58)
} w.Write([]byte(item.Avatar))
w.Write(topic_59) w.Write(topic_59)
w.Write([]byte(string(item.Css))) if item.ContentLines <= 5 {
}
w.Write(topic_60) w.Write(topic_60)
w.Write([]byte(item.ContentHtml)) }
w.Write(topic_61) w.Write(topic_61)
w.Write([]byte(item.UserSlug)) }
w.Write(topic_62) w.Write(topic_62)
w.Write([]byte(strconv.Itoa(item.CreatedBy))) w.Write([]byte(item.ContentHtml))
w.Write(topic_63) w.Write(topic_63)
w.Write([]byte(item.CreatedByName)) w.Write([]byte(item.UserSlug))
w.Write(topic_64) w.Write(topic_64)
if tmpl_topic_vars.CurrentUser.Perms.LikeItem { w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write(topic_65) w.Write(topic_65)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(item.CreatedByName))
w.Write(topic_66) w.Write(topic_66)
if item.Liked { if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
w.Write(topic_67) w.Write(topic_67)
}
w.Write(topic_68)
}
if tmpl_topic_vars.CurrentUser.Perms.EditReply {
w.Write(topic_69)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_68)
if item.Liked {
w.Write(topic_69)
}
w.Write(topic_70) w.Write(topic_70)
} }
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply { if tmpl_topic_vars.CurrentUser.Perms.EditReply {
w.Write(topic_71) w.Write(topic_71)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_72) w.Write(topic_72)
} }
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
w.Write(topic_73) w.Write(topic_73)
w.Write([]byte(strconv.Itoa(item.ID))) w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_74) w.Write(topic_74)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session)) }
w.Write(topic_75) w.Write(topic_75)
if item.LikeCount > 0 { w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_76) w.Write(topic_76)
w.Write([]byte(strconv.Itoa(item.LikeCount))) w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(topic_77) w.Write(topic_77)
if item.LikeCount > 0 {
w.Write(topic_78)
w.Write([]byte(strconv.Itoa(item.LikeCount)))
w.Write(topic_79)
} }
if item.Tag != "" { if item.Tag != "" {
w.Write(topic_78)
w.Write([]byte(item.Tag))
w.Write(topic_79)
} else {
w.Write(topic_80) w.Write(topic_80)
w.Write([]byte(strconv.Itoa(item.Level))) w.Write([]byte(item.Tag))
w.Write(topic_81) w.Write(topic_81)
} } else {
w.Write(topic_82) w.Write(topic_82)
} w.Write([]byte(strconv.Itoa(item.Level)))
}
}
w.Write(topic_83) w.Write(topic_83)
if tmpl_topic_vars.CurrentUser.Perms.CreateReply { }
w.Write(topic_84) w.Write(topic_84)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID))) }
}
}
w.Write(topic_85) w.Write(topic_85)
if tmpl_topic_vars.CurrentUser.Perms.CreateReply {
w.Write(topic_86)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_87)
} }
w.Write(footer_0) w.Write(footer_0)
if tmpl_topic_vars.Header.Widgets.RightSidebar != "" { if tmpl_topic_vars.Header.Widgets.RightSidebar != "" {

View File

@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session)) w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_topic_alt_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_topic_alt_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Slug)) if tmpl_topic_alt_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.ID))) w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_topic_alt_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_topic_alt_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_topic_alt_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" { if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)

View File

@ -2,8 +2,8 @@
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */ /* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
// +build !no_templategen // +build !no_templategen
package main package main
import "io"
import "strconv" import "strconv"
import "io"
func init() { func init() {
template_topics_handle = template_topics template_topics_handle = template_topics
@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session)) w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
w.Write(header_8) w.Write(header_8)
w.Write(menu_0) w.Write(menu_0)
if tmpl_topics_vars.CurrentUser.Loggedin { w.Write([]byte(tmpl_topics_vars.Header.Site.Name))
w.Write(menu_1) w.Write(menu_1)
w.Write([]byte(tmpl_topics_vars.CurrentUser.Slug)) if tmpl_topics_vars.CurrentUser.Loggedin {
w.Write(menu_2) w.Write(menu_2)
w.Write([]byte(strconv.Itoa(tmpl_topics_vars.CurrentUser.ID))) w.Write([]byte(tmpl_topics_vars.CurrentUser.Slug))
w.Write(menu_3) w.Write(menu_3)
if tmpl_topics_vars.CurrentUser.Is_Super_Mod { w.Write([]byte(strconv.Itoa(tmpl_topics_vars.CurrentUser.ID)))
w.Write(menu_4) w.Write(menu_4)
} if tmpl_topics_vars.CurrentUser.Is_Super_Mod {
w.Write(menu_5) w.Write(menu_5)
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
w.Write(menu_6)
} else {
w.Write(menu_7)
} }
w.Write(menu_6)
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
w.Write(menu_7)
} else {
w.Write(menu_8) w.Write(menu_8)
}
w.Write(menu_9)
w.Write(header_9) w.Write(header_9)
if tmpl_topics_vars.Header.Widgets.RightSidebar != "" { if tmpl_topics_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10) w.Write(header_10)

View File

@ -93,7 +93,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
} }
content := string(res) content := string(res)
if minify_templates { if config.MinifyTemplates {
content = minify(content) content = minify(content)
} }
@ -103,7 +103,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
if super_debug { if dev.SuperDebug {
fmt.Println(name) fmt.Println(name)
} }
@ -113,7 +113,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
c.tlist[fname] = tree c.tlist[fname] = tree
varholder := "tmpl_" + fname + "_vars" varholder := "tmpl_" + fname + "_vars"
if super_debug { if dev.SuperDebug {
fmt.Println(c.tlist) fmt.Println(c.tlist)
} }
c.localVars = make(map[string]map[string]VarItemReflect) c.localVars = make(map[string]map[string]VarItemReflect)
@ -126,13 +126,13 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
c.FragmentCursor[fname] = 0 c.FragmentCursor[fname] = 0
subtree := c.tlist[fname] subtree := c.tlist[fname]
if super_debug { if dev.SuperDebug {
fmt.Println(subtree.Root) fmt.Println(subtree.Root)
} }
treeLength := len(subtree.Root.Nodes) treeLength := len(subtree.Root.Nodes)
for index, node := range subtree.Root.Nodes { for index, node := range subtree.Root.Nodes {
if super_debug { if dev.SuperDebug {
fmt.Println("Node: " + node.String()) fmt.Println("Node: " + node.String())
} }
@ -168,14 +168,14 @@ w.Write([]byte(`," + ",-1)
//whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`) //whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
//fout = whitespace_writes.ReplaceAllString(fout,"") //fout = whitespace_writes.ReplaceAllString(fout,"")
if debug_mode { if dev.DebugMode {
for index, count := range c.stats { for index, count := range c.stats {
fmt.Println(index + ": " + strconv.Itoa(count)) fmt.Println(index + ": " + strconv.Itoa(count))
} }
fmt.Println(" ") fmt.Println(" ")
} }
if super_debug { if dev.SuperDebug {
fmt.Println("Output!") fmt.Println("Output!")
fmt.Println(fout) fmt.Println(fout)
} }
@ -183,12 +183,12 @@ w.Write([]byte(`," + ",-1)
} }
func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) { func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_switch") fmt.Println("in compile_switch")
} }
switch node := node.(type) { switch node := node.(type) {
case *parse.ActionNode: case *parse.ActionNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Action Node") fmt.Println("Action Node")
} }
if node.Pipe == nil { if node.Pipe == nil {
@ -199,24 +199,24 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
} }
return out return out
case *parse.IfNode: case *parse.IfNode:
if super_debug { if dev.SuperDebug {
fmt.Println("If Node:") fmt.Println("If Node:")
fmt.Println("node.Pipe",node.Pipe) fmt.Println("node.Pipe",node.Pipe)
} }
var expr string var expr string
for _, cmd := range node.Pipe.Cmds { for _, cmd := range node.Pipe.Cmds {
if super_debug { if dev.SuperDebug {
fmt.Println("If Node Bit:",cmd) fmt.Println("If Node Bit:",cmd)
fmt.Println("If Node Bit Type:",reflect.ValueOf(cmd).Type().Name()) fmt.Println("If Node Bit Type:",reflect.ValueOf(cmd).Type().Name())
} }
expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd) expr += c.compile_varswitch(varholder, holdreflect, template_name, cmd)
if super_debug { if dev.SuperDebug {
fmt.Println("If Node Expression Step:",c.compile_varswitch(varholder, holdreflect, template_name, cmd)) fmt.Println("If Node Expression Step:",c.compile_varswitch(varholder, holdreflect, template_name, cmd))
} }
} }
if super_debug { if dev.SuperDebug {
fmt.Println("If Node Expression:",expr) fmt.Println("If Node Expression:",expr)
} }
@ -224,18 +224,18 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
c.currentNode = parse.NodeList c.currentNode = parse.NodeList
c.nextNode = -1 c.nextNode = -1
if node.ElseList == nil { if node.ElseList == nil {
if super_debug { if dev.SuperDebug {
fmt.Println("Selected Branch 1") fmt.Println("Selected Branch 1")
} }
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n" return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n"
} else { } else {
if super_debug { if dev.SuperDebug {
fmt.Println("Selected Branch 2") fmt.Println("Selected Branch 2")
} }
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n" return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "} else {\n" + c.compile_switch(varholder, holdreflect, template_name, node.ElseList) + "}\n"
} }
case *parse.ListNode: case *parse.ListNode:
if super_debug { if dev.SuperDebug {
fmt.Println("List Node") fmt.Println("List Node")
} }
for _, subnode := range node.Nodes { for _, subnode := range node.Nodes {
@ -243,20 +243,20 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
} }
return out return out
case *parse.RangeNode: case *parse.RangeNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Range Node!") fmt.Println("Range Node!")
fmt.Println(node.Pipe) fmt.Println(node.Pipe)
} }
var outVal reflect.Value var outVal reflect.Value
for _, cmd := range node.Pipe.Cmds { for _, cmd := range node.Pipe.Cmds {
if super_debug { if dev.SuperDebug {
fmt.Println("Range Bit:",cmd) fmt.Println("Range Bit:",cmd)
} }
out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd) out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd)
} }
if super_debug { if dev.SuperDebug {
fmt.Println("Returned:",out) fmt.Println("Returned:",out)
fmt.Println("Range Kind Switch!") fmt.Println("Range Kind Switch!")
} }
@ -316,13 +316,13 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
} }
func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_subswitch") fmt.Println("in compile_subswitch")
} }
firstWord := node.Args[0] firstWord := node.Args[0]
switch n := firstWord.(type) { switch n := firstWord.(type) {
case *parse.FieldNode: case *parse.FieldNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Field Node:",n.Ident) fmt.Println("Field Node:",n.Ident)
} }
@ -336,11 +336,25 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
} }
for _, id := range n.Ident { for _, id := range n.Ident {
if super_debug { if dev.SuperDebug {
fmt.Println("Data Kind:",cur.Kind().String()) fmt.Println("Data Kind:",cur.Kind().String())
fmt.Println("Field Bit:",id) fmt.Println("Field Bit:",id)
} }
if cur.Kind() == reflect.Ptr {
if dev.SuperDebug {
fmt.Println("Looping over pointer")
}
for cur.Kind() == reflect.Ptr {
cur = cur.Elem()
}
if dev.SuperDebug {
fmt.Println("Data Kind:",cur.Kind().String())
fmt.Println("Field Bit:",id)
}
}
cur = cur.FieldByName(id) cur = cur.FieldByName(id)
if cur.Kind() == reflect.Interface { if cur.Kind() == reflect.Interface {
cur = cur.Elem() cur = cur.Elem()
@ -356,7 +370,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
} else { } else {
varbit += "." + id varbit += "." + id
} }
if super_debug { if dev.SuperDebug {
fmt.Println("End Cycle") fmt.Println("End Cycle")
} }
} }
@ -369,14 +383,14 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
} }
return out return out
case *parse.DotNode: case *parse.DotNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Dot Node:",node.String()) fmt.Println("Dot Node:",node.String())
} }
return c.compile_varsub(varholder, holdreflect) return c.compile_varsub(varholder, holdreflect)
case *parse.NilNode: case *parse.NilNode:
panic("Nil is not a command x.x") panic("Nil is not a command x.x")
case *parse.VariableNode: case *parse.VariableNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Variable Node:",n.String()) fmt.Println("Variable Node:",n.String())
fmt.Println(n.Ident) fmt.Println(n.Ident)
} }
@ -385,7 +399,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
case *parse.StringNode: case *parse.StringNode:
return n.Quoted return n.Quoted
case *parse.IdentifierNode: case *parse.IdentifierNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Identifier Node:",node) fmt.Println("Identifier Node:",node)
fmt.Println("Identifier Node Args:",node.Args) fmt.Println("Identifier Node Args:",node.Args)
} }
@ -399,13 +413,13 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
} }
func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_varswitch") fmt.Println("in compile_varswitch")
} }
firstWord := node.Args[0] firstWord := node.Args[0]
switch n := firstWord.(type) { switch n := firstWord.(type) {
case *parse.FieldNode: case *parse.FieldNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Field Node:",n.Ident) fmt.Println("Field Node:",n.Ident)
for _, id := range n.Ident { for _, id := range n.Ident {
fmt.Println("Field Bit:",id) fmt.Println("Field Bit:",id)
@ -415,13 +429,13 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
return c.compile_boolsub(n.String(), varholder, template_name, holdreflect) return c.compile_boolsub(n.String(), varholder, template_name, holdreflect)
case *parse.ChainNode: case *parse.ChainNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Chain Node:",n.Node) fmt.Println("Chain Node:",n.Node)
fmt.Println("Chain Node Args:",node.Args) fmt.Println("Chain Node Args:",node.Args)
} }
break break
case *parse.IdentifierNode: case *parse.IdentifierNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Identifier Node:",node) fmt.Println("Identifier Node:",node)
fmt.Println("Identifier Node Args:",node.Args) fmt.Println("Identifier Node Args:",node.Args)
} }
@ -429,7 +443,7 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
case *parse.DotNode: case *parse.DotNode:
return varholder return varholder
case *parse.VariableNode: case *parse.VariableNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Variable Node:",n.String()) fmt.Println("Variable Node:",n.String())
fmt.Println("Variable Node Identifier:",n.Ident) fmt.Println("Variable Node Identifier:",n.Ident)
} }
@ -438,14 +452,14 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
case *parse.NilNode: case *parse.NilNode:
panic("Nil is not a command x.x") panic("Nil is not a command x.x")
case *parse.PipeNode: case *parse.PipeNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Pipe Node!") fmt.Println("Pipe Node!")
fmt.Println(n) fmt.Println(n)
fmt.Println("Args:",node.Args) fmt.Println("Args:",node.Args)
} }
out += c.compile_identswitch_n(varholder, holdreflect, template_name, node) out += c.compile_identswitch_n(varholder, holdreflect, template_name, node)
if super_debug { if dev.SuperDebug {
fmt.Println("Out:",out) fmt.Println("Out:",out)
} }
return out return out
@ -458,7 +472,7 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
} }
func (c *CTemplateSet) compile_identswitch_n(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) { func (c *CTemplateSet) compile_identswitch_n(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_identswitch_n") fmt.Println("in compile_identswitch_n")
} }
out, _ = c.compile_identswitch(varholder, holdreflect, template_name, node) out, _ = c.compile_identswitch(varholder, holdreflect, template_name, node)
@ -466,7 +480,7 @@ func (c *CTemplateSet) compile_identswitch_n(varholder string, holdreflect refle
} }
func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, val reflect.Value) { func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, val reflect.Value) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_identswitch") fmt.Println("in compile_identswitch")
} }
@ -474,7 +488,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
ArgLoop: ArgLoop:
for pos := 0; pos < len(node.Args); pos++ { for pos := 0; pos < len(node.Args); pos++ {
id := node.Args[pos] id := node.Args[pos]
if super_debug { if dev.SuperDebug {
fmt.Println("pos:",pos) fmt.Println("pos:",pos)
fmt.Println("ID:",id) fmt.Println("ID:",id)
} }
@ -482,7 +496,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
case "not": case "not":
out += "!" out += "!"
case "or": case "or":
if super_debug { if dev.SuperDebug {
fmt.Println("Building or function") fmt.Println("Building or function")
} }
if pos == 0 { if pos == 0 {
@ -507,7 +521,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
out += left + " || " + right out += left + " || " + right
if super_debug { if dev.SuperDebug {
fmt.Println("Left operand:",node.Args[pos - 1]) fmt.Println("Left operand:",node.Args[pos - 1])
fmt.Println("Right operand:",node.Args[pos + 1]) fmt.Println("Right operand:",node.Args[pos + 1])
} }
@ -516,12 +530,12 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
pos++ pos++
} }
if super_debug { if dev.SuperDebug {
fmt.Println("pos:",pos) fmt.Println("pos:",pos)
fmt.Println("len(node.Args):",len(node.Args)) fmt.Println("len(node.Args):",len(node.Args))
} }
case "and": case "and":
if super_debug { if dev.SuperDebug {
fmt.Println("Building and function") fmt.Println("Building and function")
} }
if pos == 0 { if pos == 0 {
@ -546,7 +560,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
out += left + " && " + right out += left + " && " + right
if super_debug { if dev.SuperDebug {
fmt.Println("Left operand:",node.Args[pos - 1]) fmt.Println("Left operand:",node.Args[pos - 1])
fmt.Println("Right operand:",node.Args[pos + 1]) fmt.Println("Right operand:",node.Args[pos + 1])
} }
@ -555,48 +569,48 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
pos++ pos++
} }
if super_debug { if dev.SuperDebug {
fmt.Println("pos:",pos) fmt.Println("pos:",pos)
fmt.Println("len(node.Args):",len(node.Args)) fmt.Println("len(node.Args):",len(node.Args))
} }
case "le": case "le":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " <= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
case "lt": case "lt":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " < " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " < " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
case "gt": case "gt":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " > " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " > " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
case "ge": case "ge":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " >= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " >= " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
case "eq": case "eq":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " == " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " == " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
case "ne": case "ne":
out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " != " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect) out += c.compile_if_varsub_n(node.Args[pos + 1].String(), varholder, template_name, holdreflect) + " != " + c.compile_if_varsub_n(node.Args[pos + 2].String(), varholder, template_name, holdreflect)
if super_debug { if dev.SuperDebug {
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
@ -615,7 +629,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
} }
out += param1 + " + " + param2 out += param1 + " + " + param2
if super_debug { if dev.SuperDebug {
fmt.Println("add") fmt.Println("add")
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
@ -635,7 +649,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
} }
out += param1 + " - " + param2 out += param1 + " - " + param2
if super_debug { if dev.SuperDebug {
fmt.Println("subtract") fmt.Println("subtract")
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
@ -655,7 +669,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
} }
out += param1 + " / " + param2 out += param1 + " / " + param2
if super_debug { if dev.SuperDebug {
fmt.Println("divide") fmt.Println("divide")
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
@ -675,14 +689,14 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
} }
out += param1 + " * " + param2 out += param1 + " * " + param2
if super_debug { if dev.SuperDebug {
fmt.Println("multiply") fmt.Println("multiply")
fmt.Println(node.Args[pos + 1]) fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2]) fmt.Println(node.Args[pos + 2])
} }
break ArgLoop break ArgLoop
default: default:
if super_debug { if dev.SuperDebug {
fmt.Println("Variable!") fmt.Println("Variable!")
} }
if len(node.Args) > (pos + 1) { if len(node.Args) > (pos + 1) {
@ -702,13 +716,13 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
} }
func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) { func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect reflect.Value, template_name string, node *parse.CommandNode) (out string, outVal reflect.Value) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_reflectswitch") fmt.Println("in compile_reflectswitch")
} }
firstWord := node.Args[0] firstWord := node.Args[0]
switch n := firstWord.(type) { switch n := firstWord.(type) {
case *parse.FieldNode: case *parse.FieldNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Field Node:",n.Ident) fmt.Println("Field Node:",n.Ident)
for _, id := range n.Ident { for _, id := range n.Ident {
fmt.Println("Field Bit:",id) fmt.Println("Field Bit:",id)
@ -717,7 +731,7 @@ func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect refle
/* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */ /* Use reflect to determine if the field is for a method, otherwise assume it's a variable. Coming Soon. */
return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
case *parse.ChainNode: case *parse.ChainNode:
if super_debug { if dev.SuperDebug {
fmt.Println("Chain Node: ") fmt.Println("Chain Node: ")
fmt.Println(n.Node) fmt.Println(n.Node)
fmt.Println(node.Args) fmt.Println(node.Args)
@ -734,7 +748,7 @@ func (c *CTemplateSet) compile_reflectswitch(varholder string, holdreflect refle
} }
func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) { func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, template_name string, cur reflect.Value) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_if_varsub_n") fmt.Println("in compile_if_varsub_n")
} }
out, _ = c.compile_if_varsub(varname, varholder, template_name, cur) out, _ = c.compile_if_varsub(varname, varholder, template_name, cur)
@ -742,7 +756,7 @@ func (c *CTemplateSet) compile_if_varsub_n(varname string, varholder string, tem
} }
func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) { func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, template_name string, cur reflect.Value) (out string, val reflect.Value) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_if_varsub") fmt.Println("in compile_if_varsub")
} }
if varname[0] != '.' && varname[0] != '$' { if varname[0] != '.' && varname[0] != '$' {
@ -773,13 +787,13 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
} }
bits[0] = strings.TrimPrefix(bits[0],"$") bits[0] = strings.TrimPrefix(bits[0],"$")
if super_debug { if dev.SuperDebug {
fmt.Println("Cur Kind:",cur.Kind()) fmt.Println("Cur Kind:",cur.Kind())
fmt.Println("Cur Type:",cur.Type().Name()) fmt.Println("Cur Type:",cur.Type().Name())
} }
for _, bit := range bits { for _, bit := range bits {
if super_debug { if dev.SuperDebug {
fmt.Println("Variable Field!") fmt.Println("Variable Field!")
fmt.Println(bit) fmt.Println(bit)
} }
@ -799,13 +813,13 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
panic(out + "^\n" + "Invalid value. Maybe, it doesn't exist?") panic(out + "^\n" + "Invalid value. Maybe, it doesn't exist?")
} }
if super_debug { if dev.SuperDebug {
fmt.Println("Data Kind:",cur.Kind()) fmt.Println("Data Kind:",cur.Kind())
fmt.Println("Data Type:",cur.Type().Name()) fmt.Println("Data Type:",cur.Type().Name())
} }
} }
if super_debug { if dev.SuperDebug {
fmt.Println("Out Value:",out) fmt.Println("Out Value:",out)
fmt.Println("Out Kind:",cur.Kind()) fmt.Println("Out Kind:",cur.Kind())
fmt.Println("Out Type:",cur.Type().Name()) fmt.Println("Out Type:",cur.Type().Name())
@ -817,7 +831,7 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
} }
} }
if super_debug { if dev.SuperDebug {
fmt.Println("Out Value:",out) fmt.Println("Out Value:",out)
fmt.Println("Out Kind:",cur.Kind()) fmt.Println("Out Kind:",cur.Kind())
fmt.Println("Out Type:",cur.Type().Name()) fmt.Println("Out Type:",cur.Type().Name())
@ -834,7 +848,7 @@ func (c *CTemplateSet) compile_if_varsub(varname string, varholder string, templ
} }
func (c *CTemplateSet) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string { func (c *CTemplateSet) compile_boolsub(varname string, varholder string, template_name string, val reflect.Value) string {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_boolsub") fmt.Println("in compile_boolsub")
} }
out, val := c.compile_if_varsub(varname, varholder, template_name, val) out, val := c.compile_if_varsub(varname, varholder, template_name, val)
@ -853,7 +867,7 @@ func (c *CTemplateSet) compile_boolsub(varname string, varholder string, templat
} }
func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string { func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_varsub") fmt.Println("in compile_varsub")
} }
for _, varItem := range c.varList { for _, varItem := range c.varList {
@ -898,7 +912,7 @@ func (c *CTemplateSet) compile_varsub(varname string, val reflect.Value) string
} }
func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) { func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect reflect.Value, node *parse.TemplateNode) (out string) {
if super_debug { if dev.SuperDebug {
fmt.Println("in compile_subtemplate") fmt.Println("in compile_subtemplate")
fmt.Println("Template Node: " + node.Name) fmt.Println("Template Node: " + node.Name)
} }
@ -929,7 +943,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
} }
content := string(res) content := string(res)
if minify_templates { if config.MinifyTemplates {
content = minify(content) content = minify(content)
} }
@ -942,7 +956,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
c.tlist[fname] = tree c.tlist[fname] = tree
subtree := c.tlist[fname] subtree := c.tlist[fname]
if super_debug { if dev.SuperDebug {
fmt.Println(subtree.Root) fmt.Println(subtree.Root)
} }
@ -952,7 +966,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
treeLength := len(subtree.Root.Nodes) treeLength := len(subtree.Root.Nodes)
for index, node := range subtree.Root.Nodes { for index, node := range subtree.Root.Nodes {
if super_debug { if dev.SuperDebug {
fmt.Println("Node:",node.String()) fmt.Println("Node:",node.String())
} }

View File

@ -9,11 +9,10 @@
</div> </div>
{{if ne .CurrentUser.ID 0}} {{if ne .CurrentUser.ID 0}}
{{if .CurrentUser.Perms.CreateTopic}} {{if .CurrentUser.Perms.CreateTopic}}
<div class="opt create_topic_opt" title="Create Topic">&#x1F58A;&#xFE0E</div> <div class="opt create_topic_opt" title="Create Topic"><a href="/topics/create/{{.Forum.ID}}">&#x1F58A;&#xFE0E</a></div>
{{else}}<div class="opt locked_opt" title="You don't have the permissions needed to create a topic">&#x1F512;&#xFE0E</div>{{end}} {{else}}<div class="opt locked_opt" title="You don't have the permissions needed to create a topic">&#x1F512;&#xFE0E</div>{{end}}
<div style="clear: both;"></div> <div style="clear: both;"></div>
{{end}} {{end}}
<!--href="/topics/create/{{.Forum.ID}}"-->
</div> </div>
<div id="forum_topic_list" class="rowblock topic_list"> <div id="forum_topic_list" class="rowblock topic_list">
{{range .ItemList}}<div class="rowitem passive datarow {{if .Sticky}}topic_sticky{{else if .Is_Closed}}topic_closed{{end}}" style="{{if .Avatar}}background-image: url({{.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}"> {{range .ItemList}}<div class="rowitem passive datarow {{if .Sticky}}topic_sticky{{else if .Is_Closed}}topic_closed{{end}}" style="{{if .Avatar}}background-image: url({{.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}">

View File

@ -7,10 +7,9 @@
{{if .Desc}}<span style="float: left;"> {{if .Desc}}<span style="float: left;">
<a href="{{.Link}}" style="">{{.Name}}</a> <a href="{{.Link}}" style="">{{.Name}}</a>
<br /><span class="rowsmall">{{.Desc}}</span> <br /><span class="rowsmall">{{.Desc}}</span>
</span>{{else if .LastTopicTime}}<span style="float: left;padding-top: 8px;font-size: 18px;">
<a href="{{.Link}}">{{.Name}}</a>
</span>{{else}}<span style="float: left;"> </span>{{else}}<span style="float: left;">
<a href="{{.Link}}">{{.Name}}</a> <a href="{{.Link}}">{{.Name}}</a>
<br /><span class="rowsmall" style="font-style: italic;">No description</span>
</span>{{end}} </span>{{end}}
<span style="float: right;"> <span style="float: right;">

View File

@ -2,7 +2,7 @@
<div class="move_left"> <div class="move_left">
<div class="move_right"> <div class="move_right">
<ul> <ul>
<li class="menu_left menu_overview"><a href="/">Overview</a></li> <li class="menu_left menu_overview"><a href="/">{{.Header.Site.Name}}</a></li>
<li class="menu_left menu_forums"><a href="/forums/">Forums</a></li> <li class="menu_left menu_forums"><a href="/forums/">Forums</a></li>
<li class="menu_left menu_topics"><a href="/">Topics</a></li> <li class="menu_left menu_topics"><a href="/">Topics</a></li>
<li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li> <li class="menu_left menu_create_topic"><a href="/topics/create/">Create Topic</a></li>
@ -16,8 +16,9 @@
<li class="menu_left menu_login"><a href="/accounts/login/">Login</a></li> <li class="menu_left menu_login"><a href="/accounts/login/">Login</a></li>
{{end}} {{end}}
<li id="general_alerts" class="menu_right menu_alerts"> <li id="general_alerts" class="menu_right menu_alerts">
<div class="alert_bell">🔔︎</div> <div class="alert_bell"></div>
<div class="alert_counter"></div> <div class="alert_counter"></div>
<div class="alert_aftercounter"></div>
<div class="alertList"></div> <div class="alertList"></div>
</li> </li>
</ul> </ul>

View File

@ -23,7 +23,7 @@
<div class="rowitem"><a>Comments</a></div> <div class="rowitem"><a>Comments</a></div>
</div> </div>
<div id="profile_comments" class="colblock_right" style="overflow: hidden;border-top: none;width:calc(95% - 210px);">{{range .ItemList}} <div id="profile_comments" class="colblock_right" style="overflow: hidden;border-top: none;width:calc(95% - 210px);">{{range .ItemList}}
<div class="rowitem passive deletable_block editable_parent simple" style="{{if .Avatar}}background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;{{.Css}}{{end}}"> <div class="rowitem passive deletable_block editable_parent simple {{.ClassName}}" style="{{if .Avatar}}background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;{{end}}">
<span class="editable_block user_content simple">{{.ContentHtml}}</span><br /><br /> <span class="editable_block user_content simple">{{.ContentHtml}}</span><br /><br />
<a href="/user/{{.UserSlug}}.{{.CreatedBy}}" class="real_username username">{{.CreatedByName}}</a>&nbsp;&nbsp; <a href="/user/{{.UserSlug}}.{{.CreatedBy}}" class="real_username username">{{.CreatedByName}}</a>&nbsp;&nbsp;

View File

@ -9,7 +9,7 @@
<div class="rowblock rowhead topic_block"> <div class="rowblock rowhead topic_block">
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post"> <form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
<div class="rowitem topic_item"{{if .Topic.Sticky}} style="background-color:#FFFFEA;"{{else if .Topic.Is_Closed}} style="background-color:#eaeaea;"{{end}}> <div class="rowitem topic_item{{if .Topic.Sticky}} topic_sticky_head{{else if .Topic.Is_Closed}} topic_closed_head{{end}}">
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a> <a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
{{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">&#x1F512;&#xFE0E</span>{{end}} {{if .Topic.Is_Closed}}<span class='username hide_on_micro topic_status_e topic_status_closed hide_on_edit' title='Status: Closed' style="font-weight:normal;float: right;position:relative;top:-5px;">&#x1F512;&#xFE0E</span>{{end}}
{{if .CurrentUser.Perms.EditTopic}} {{if .CurrentUser.Perms.EditTopic}}
@ -24,7 +24,7 @@
</form> </form>
</div> </div>
<div class="rowblock post_container top_post"> <div class="rowblock post_container top_post">
<div class="rowitem passive editable_parent post_item" style="border-bottom: none;{{if .Topic.Avatar}}background-image:url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;{{.Topic.Css}}{{end}}"> <div class="rowitem passive editable_parent post_item {{.Topic.ClassName}}" style="{{if .Topic.Avatar}}background-image:url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .Topic.ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;{{end}}">
<p class="hide_on_edit topic_content user_content" style="margin:0;padding:0;">{{.Topic.Content}}</p> <p class="hide_on_edit topic_content user_content" style="margin:0;padding:0;">{{.Topic.Content}}</p>
<textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea> <textarea name="topic_content" class="show_on_edit topic_content_input">{{.Topic.Content}}</textarea>
@ -43,7 +43,7 @@
{{if .Topic.LikeCount}}<a class="username hide_on_micro like_count">{{.Topic.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>{{end}} {{if .Topic.LikeCount}}<a class="username hide_on_micro like_count">{{.Topic.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>{{end}}
{{if .Topic.Tag}}<a class="username hide_on_micro" style="float:right;color:#505050;font-size:16px;">{{.Topic.Tag}}</a>{{else}}<a class="username hide_on_micro level">{{.Topic.Level}}</a><a class="username hide_on_micro level_label" style="color:#505050;float:right;opacity:0.85;" title="Level"></a>{{end}} {{if .Topic.Tag}}<a class="username hide_on_micro user_tag">{{.Topic.Tag}}</a>{{else}}<a class="username hide_on_micro level">{{.Topic.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="Level"></a>{{end}}
</span> </span>
</div> </div>
@ -54,7 +54,7 @@
<span>{{.ActionType}}</span> <span>{{.ActionType}}</span>
</div> </div>
{{else}} {{else}}
<div class="rowitem passive deletable_block editable_parent post_item" style="{{if .Avatar}}background-image:url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;{{.Css}}{{end}}"> <div class="rowitem passive deletable_block editable_parent post_item {{.ClassName}}" style="{{if .Avatar}}background-image:url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px {{if le .ContentLines 5}}-1{{end}}0px;background-repeat:no-repeat, repeat-y;{{end}}">
<p class="editable_block user_content" style="margin:0;padding:0;">{{.ContentHtml}}</p> <p class="editable_block user_content" style="margin:0;padding:0;">{{.ContentHtml}}</p>
<span class="controls"> <span class="controls">
@ -69,17 +69,17 @@
{{if .LikeCount}}<a class="username hide_on_micro like_count">{{.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>{{end}} {{if .LikeCount}}<a class="username hide_on_micro like_count">{{.LikeCount}}</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>{{end}}
{{if .Tag}}<a class="username hide_on_micro" style="float: right;color:#505050;font-size:16px;">{{.Tag}}</a>{{else}}<a class="username hide_on_micro level">{{.Level}}</a><a class="username hide_on_micro level_label" style="color:#505050;float:right;opacity:0.85;" title="Level">{{end}}</a> {{if .Tag}}<a class="username hide_on_micro user_tag">{{.Tag}}</a>{{else}}<a class="username hide_on_micro level">{{.Level}}</a><a class="username hide_on_micro level_label" style="float:right;" title="Level">{{end}}</a>
</span> </span>
</div> </div>
{{end}}{{end}}</div> {{end}}{{end}}</div>
{{if .CurrentUser.Perms.CreateReply}} {{if .CurrentUser.Perms.CreateReply}}
<div class="rowblock"> <div class="rowblock topic_reply_form">
<form action="/reply/create/" method="post"> <form action="/reply/create/" method="post">
<input name="tid" value='{{.Topic.ID}}' type="hidden" /> <input name="tid" value='{{.Topic.ID}}' type="hidden" />
<div class="formrow"> <div class="formrow real_first_child">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div> <div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
</div> </div>
<div class="formrow"> <div class="formrow">

View File

@ -22,7 +22,7 @@
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style> <style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
<div class="rowblock post_container" style="border-top: none;"> <div class="rowblock post_container" style="border-top: none;">
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;"> <div class="rowitem passive deletable_block editable_parent post_item top_post" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
<div class="userinfo"> <div class="userinfo">
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;">&nbsp;</div> <div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;">&nbsp;</div>
<a href="/user/{{.Topic.UserSlug}}.{{.Topic.CreatedBy}}" class="the_name">{{.Topic.CreatedByName}}</a> <a href="/user/{{.Topic.UserSlug}}.{{.Topic.CreatedBy}}" class="the_name">{{.Topic.CreatedByName}}</a>
@ -76,7 +76,7 @@
</div> </div>
{{end}}</div> {{end}}</div>
{{if .CurrentUser.Perms.CreateReply}} {{if .CurrentUser.Perms.CreateReply}}
<div class="rowblock" style="border-top: none;"> <div class="rowblock topic_reply_form" style="border-top: none;">
<form action="/reply/create/" method="post"> <form action="/reply/create/" method="post">
<input name="tid" value='{{.Topic.ID}}' type="hidden" /> <input name="tid" value='{{.Topic.ID}}' type="hidden" />
<div class="formrow"> <div class="formrow">

View File

@ -140,7 +140,7 @@ func init_themes() {
theme.Active = false // Set this to false, just in case someone explicitly overrode this value in the JSON file theme.Active = false // Set this to false, just in case someone explicitly overrode this value in the JSON file
if theme.FullImage != "" { if theme.FullImage != "" {
if debug_mode { if dev.DebugMode {
log.Print("Adding theme image") log.Print("Adding theme image")
} }
err = add_static_file("./themes/" + themeName + "/" + theme.FullImage, "./themes/" + themeName) err = add_static_file("./themes/" + themeName + "/" + theme.FullImage, "./themes/" + themeName)
@ -155,7 +155,7 @@ func init_themes() {
func add_theme_static_files(theme Theme) { func add_theme_static_files(theme Theme) {
err := filepath.Walk("./themes/" + theme.Name + "/public", func(path string, f os.FileInfo, err error) error { err := filepath.Walk("./themes/" + theme.Name + "/public", func(path string, f os.FileInfo, err error) error {
if debug_mode { if dev.DebugMode {
log.Print("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'") log.Print("Attempting to add static file '" + path + "' for default theme '" + theme.Name + "'")
} }
if err != nil { if err != nil {
@ -174,7 +174,7 @@ func add_theme_static_files(theme Theme) {
var ext string = filepath.Ext(path) var ext string = filepath.Ext(path)
//log.Print("path ",path) //log.Print("path ",path)
//log.Print("ext ",ext) //log.Print("ext ",ext)
if ext == ".css" { if ext == ".css" && len(data) != 0 {
var b bytes.Buffer var b bytes.Buffer
var pieces []string = strings.Split(path,"/") var pieces []string = strings.Split(path,"/")
var filename string = pieces[len(pieces) - 1] var filename string = pieces[len(pieces) - 1]
@ -190,7 +190,7 @@ func add_theme_static_files(theme Theme) {
gzip_data := compress_bytes_gzip(data) gzip_data := compress_bytes_gzip(data)
static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)} static_files["/static" + path] = SFile{data,gzip_data,0,int64(len(data)),int64(len(gzip_data)),mime.TypeByExtension(ext),f,f.ModTime().UTC().Format(http.TimeFormat)}
if debug_mode { if dev.DebugMode {
log.Print("Added the '" + path + "' static file for default theme " + theme.Name + ".") log.Print("Added the '" + path + "' static file for default theme " + theme.Name + ".")
} }
return nil return nil

View File

@ -76,6 +76,10 @@ li:hover {
border-left: 1px solid #7a7a7a; border-left: 1px solid #7a7a7a;
} }
.alert_bell:before {
content: '🔔︎';
}
.menu_alerts .alert_counter { .menu_alerts .alert_counter {
position: relative; position: relative;
font-size: 9px; font-size: 9px;

View File

@ -71,6 +71,10 @@ li:hover {
border-left: 1px solid #7a7a7a; border-left: 1px solid #7a7a7a;
} }
.alert_bell:before {
content: '🔔︎';
}
.menu_alerts .alert_counter { .menu_alerts .alert_counter {
position: relative; position: relative;
font-size: 9px; font-size: 9px;

View File

@ -0,0 +1,266 @@
/* Patch for Edge, until they fix emojis in arial x.x */
@supports (-ms-ime-align:auto) { .user_content { font-family: Segoe UI Emoji, arial; } }
body {
font-family: arial;
color: white;
background-color: #222222;
margin: 0;
}
#back {
margin-left: auto;
margin-right: auto;
width: 70%;
background-color: #333333;
position: relative;
top: -2px;
}
ul {
list-style-type: none;
background-color: rgb(61,61,61);
border-bottom: 1px solid #222222;
padding-left: 15%;
padding-right: 15%;
margin: 0;
height: 45px;
}
li {
float: left;
height: 35px;
padding-top: 12px;
margin: 0;
}
.menu_left {
margin-right: 10px;
}
.menu_right {
float: right;
}
.menu_overview {
margin-right: 13px;
margin-left: 10px;
}
.menu_left:not(.menu_overview) {
font-size: 15px;
padding-top: 13px;
}
.alert_bell {
float: right;
}
.menu_alerts {
float: none;
padding-top: 14px;
}
.alert_counter {
background-color: rgb(200,0,0);
border-radius: 2px;
font-size: 12px;
padding: 3px;
float: right;
position: relative;
top: -1px;
}
.alert_aftercounter {
float: right;
margin-right: 4px;
font-size: 15px;
}
.alert_aftercounter:before {
content: "Alerts";
}
.menu_alerts .alertList {
display: none;
}
.selectedAlert .alertList {
/* Coming Soon. Hidden so it doesn't distract me while I design this theme */
display: none;
}
a {
text-decoration: none;
color: white;
}
.rowblock {
margin-left: 8px;
margin-right: 8px;
}
.opthead, .rowhead, .colstack_head {
padding-bottom: 0px;
padding-top: 3px !important;
}
.rowblock:not(.opthead):not(.colstack_head):not(.rowhead) .rowitem {
font-size: 15px;
}
.rowblock:last-child {
padding-bottom: 10px;
}
.rowitem, .formitem {
padding-bottom: 12px;
background-color: rgb(61,61,61);
margin-top: 8px;
padding: 12px;
}
.rowsmall {
font-size: 12px;
}
.colstack_left, .colstack_right {
margin-left: 8px;
}
.colstack_left {
float: left;
width: 30%;
}
.colstack_right {
float: left;
width: calc(70% - 24px);
}
.colstack_left:empty, .colstack_right:empty {
display: none;
}
.show_on_edit {
display: none;
}
.topic_sticky_head {
}
.topic_closed_head {
}
.post_item {
background-size: 128px;
padding-left: calc(128px + 12px);
}
.controls {
width: 100%;
display: inline-block;
margin-top: 20px;
}
.staff_post {
border: 1px solid rgb(101, 71, 101)
}
.user_tag {
float: right;
color: rgb(205,205,205);
}
.real_username {
float: left;
margin-right: 7px;
}
.mod_button {
margin-right: 5px;
display: block;
float: left;
}
.mod_button button {
border: none;
background: none;
color: white;
font-size: 12px;
padding: 0;
}
.like_label:before {
content: "+1";
}
.edit_label:before { content: "Edit"; }
.trash_label:before { content: "Delete"; }
.pin_label:before { content: "Pin"; }
.unpin_label:before { content: "Unpin"; }
.flag_label:before { content: "Flag"; }
.level_label:before { content: "Level"; }
.like_count_label:before {
content: "likes";
}
.like_count_label {
font-size: 12px;
display: block;
float: left;
line-height: 19px;
}
.like_count {
font-size: 12px;
display: block;
float: left;
line-height: 19px;
margin-right: 2px;
}
.like_count:before {
content: "|";
margin-right: 5px;
}
.level_label, .level {
color: rgb(205,205,205);
float: right;
}
.level {
margin-left: 3px;
}
.topic_reply_form {
margin-top: 8px;
}
.formitem {
margin-top: 0px;
padding-bottom: 2px;
padding-top: 3px;
}
.formrow.real_first_child .formitem {
padding-top: 12px;
}
.formrow:last-child .formitem {
padding-bottom: 12px;
}
textarea {
background-color: #444444;
border-color: #555555;
}
.topic_reply_form textarea {
width: calc(100% - 5px);
min-height: 80px;
}
.formitem button {
background-color: #444444;
border: 1px solid #555555;
color: #999999;
padding: 7px;
padding-bottom: 6px;
font-size: 13px;
}

View File

View File

@ -3,7 +3,6 @@
"FriendlyName": "Shadow", "FriendlyName": "Shadow",
"Version": "0.0.1", "Version": "0.0.1",
"Creator": "Azareal", "Creator": "Azareal",
"Disabled": true, "URL": "github.com/Azareal/Gosora",
"HideFromThemes": true, "Tag": "WIP"
"URL": "github.com/Azareal/Gosora"
} }

View File

@ -47,6 +47,9 @@ li a {
padding-right: 10px; padding-right: 10px;
} }
.alert_bell:before {
content: '🔔︎';
}
.menu_bell { .menu_bell {
cursor: default; cursor: default;
} }

View File

@ -49,6 +49,9 @@ li a {
padding-right: 10px; padding-right: 10px;
} }
.alert_bell:before {
content: '🔔︎';
}
.menu_bell { .menu_bell {
cursor: default; cursor: default;
} }
@ -348,6 +351,23 @@ button.username {
display: inline-block; display: inline-block;
} }
.user_tag {
float: right;
color: #505050;
font-size: 16px;
}
.post_item {
background-size: 128px;
padding-left: calc(128px + 12px);
}
.controls {
width: 100%;
display: inline-block;
/*margin-top: 20px;*/
}
.controls > .username { .controls > .username {
display: inline-block; display: inline-block;
padding-bottom: 0px; padding-bottom: 0px;
@ -399,8 +419,8 @@ button.username {
.pin_label:before { content: "Pin"; } .pin_label:before { content: "Pin"; }
.unpin_label:before { content: "Unpin"; } .unpin_label:before { content: "Unpin"; }
.flag_label:before { content: "Flag"; } .flag_label:before { content: "Flag"; }
.level_label { margin-right: 1px; } .level_label { margin-right: 1px; color: #505050; }
.level_label:before { content: "Level"; } .level_label:before { content: "Level"; opacity:0.85; }
.controls { .controls {
margin-top: 23px; margin-top: 23px;

View File

@ -18,7 +18,7 @@ ul {
height: 36px; height: 36px;
list-style-type: none; list-style-type: none;
border: 1px solid #ccc; border: 1px solid #ccc;
background-color: rgb(248,248,248); background-color: rgb(252,252,252);
margin-bottom: 12px; margin-bottom: 12px;
} }
li { li {
@ -29,7 +29,7 @@ li {
background: white; background: white;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
} }
li:hover { background: rgb(250,250,250); } li:hover { background: rgb(252,252,252); }
li a { li a {
text-decoration: none; text-decoration: none;
/*color: #515151;*/ /*color: #515151;*/
@ -46,8 +46,20 @@ li a {
border-left: 1px solid #ccc; border-left: 1px solid #ccc;
padding-right: 10px; padding-right: 10px;
} }
.menu_overview {
background: none;
padding-right: 13px;
}
.menu_overview a {
padding-left: 3px;
}
.menu_bell { cursor: default; } .alert_bell:before {
content: '🔔︎';
}
.menu_bell {
cursor: default;
}
.menu_alerts { .menu_alerts {
/*padding-left: 7px;*/ /*padding-left: 7px;*/
font-size: 20px; font-size: 20px;
@ -222,7 +234,7 @@ li a {
.stat_red { background-color: #ffb2b2; border-color: #ffb2b2; } .stat_red { background-color: #ffb2b2; border-color: #ffb2b2; }
.stat_disabled { background-color: lightgray; border-color: lightgray; } .stat_disabled { background-color: lightgray; border-color: lightgray; }
.rowhead { .rowhead, .colstack_head {
border-bottom: none; border-bottom: none;
} }
.rowhead .rowitem, .colstack_head .rowitem { .rowhead .rowitem, .colstack_head .rowitem {
@ -265,8 +277,9 @@ li a {
width: 50px; width: 50px;
text-align: center; text-align: center;
} }
.create_topic_opt { .create_topic_opt, .create_topic_opt a {
color: rgb(120,120,120); color: rgb(120,120,120);
text-decoration: none;
} }
.locked_opt { .locked_opt {
color: rgb(80,80,80); color: rgb(80,80,80);
@ -339,6 +352,12 @@ button {
.topic_closed { .topic_closed {
background-color: rgb(248,248,248); background-color: rgb(248,248,248);
} }
.topic_sticky_head {
background-color:#FFFFEA;
}
.topic_closed_head {
background-color:#eaeaea;
}
.topic_status { .topic_status {
text-transform: none; text-transform: none;
@ -397,6 +416,19 @@ button.username {
} }
.post_item > .mod_button > button:hover { opacity: 0.9; } .post_item > .mod_button > button:hover { opacity: 0.9; }
.user_tag {
float: right;
color: #505050;
font-size: 16px;
}
.post_item {
background-size: 128px;
padding-left: 136px;
}
.staff_post {
background-color: #ffeaff;
}
.mod_button { margin-right: 4px; } .mod_button { margin-right: 4px; }
.like_label:before, .like_count_label:before { content: "😀"; } .like_label:before, .like_count_label:before { content: "😀"; }
.like_count_label { .like_count_label {
@ -421,6 +453,7 @@ button.username {
.unpin_label { background-color: #D6FFD6; } .unpin_label { background-color: #D6FFD6; }
.flag_label:before { content: "🚩"; } .flag_label:before { content: "🚩"; }
.level_label:before { content: "👑"; } .level_label:before { content: "👑"; }
.level_label { color: #505050; opacity:0.85; }
.controls { .controls {
margin-top: 23px; margin-top: 23px;

View File

@ -48,7 +48,6 @@ type TopicUser struct
CreatedByName string CreatedByName string
Group int Group int
Avatar string Avatar string
Css template.CSS
ContentLines int ContentLines int
Tag string Tag string
URL string URL string
@ -93,7 +92,7 @@ type TopicsRow struct
} }
func get_topicuser(tid int) (TopicUser,error) { func get_topicuser(tid int) (TopicUser,error) {
if cache_topicuser != CACHE_SQL { if config.CacheTopicUser != CACHE_SQL {
topic, err := topics.Get(tid) topic, err := topics.Get(tid)
if err == nil { if err == nil {
user, err := users.CascadeGet(topic.CreatedBy) user, err := users.CascadeGet(topic.CreatedBy)

View File

@ -100,12 +100,12 @@ func SetPassword(uid int, password string) error {
func SendValidationEmail(username string, email string, token string) bool { func SendValidationEmail(username string, email string, token string) bool {
var schema string = "http" var schema string = "http"
if enable_ssl { if site.EnableSsl {
schema += "s" schema += "s"
} }
subject := "Validate Your Email @ " + site_name subject := "Validate Your Email @ " + site.Name
msg := "Dear " + username + ", following your registration on our forums, we ask you to validate your email, so that we can confirm that this email actually belongs to you.\n\nClick on the following link to do so. " + schema + "://" + site_url + "/user/edit/token/" + token + "\n\nIf you haven't created an account here, then please feel free to ignore this email.\nWe're sorry for the inconvenience this may have caused." msg := "Dear " + username + ", following your registration on our forums, we ask you to validate your email, so that we can confirm that this email actually belongs to you.\n\nClick on the following link to do so. " + schema + "://" + site.Url + "/user/edit/token/" + token + "\n\nIf you haven't created an account here, then please feel free to ignore this email.\nWe're sorry for the inconvenience this may have caused."
return SendEmail(email, subject, msg) return SendEmail(email, subject, msg)
} }
@ -209,6 +209,7 @@ func _forum_session_check(w http.ResponseWriter, r *http.Request, user *User, fi
// Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with // Even if they have the right permissions, the control panel is only open to supermods+. There are many areas without subpermissions which assume that the current user is a supermod+ and admins are extremely unlikely to give these permissions to someone who isn't at-least a supermod to begin with
func _panel_session_check(w http.ResponseWriter, r *http.Request, user *User) (headerVars HeaderVars, success bool) { func _panel_session_check(w http.ResponseWriter, r *http.Request, user *User) (headerVars HeaderVars, success bool) {
headerVars.Site = site
if !user.Is_Super_Mod { if !user.Is_Super_Mod {
NoPermissions(w,r,*user) NoPermissions(w,r,*user)
return headerVars, false return headerVars, false
@ -243,6 +244,7 @@ func _simple_panel_session_check(w http.ResponseWriter, r *http.Request, user *U
} }
func _session_check(w http.ResponseWriter, r *http.Request, user *User) (headerVars HeaderVars, success bool) { func _session_check(w http.ResponseWriter, r *http.Request, user *User) (headerVars HeaderVars, success bool) {
headerVars.Site = site
if user.Is_Banned { if user.Is_Banned {
headerVars.NoticeList = append(headerVars.NoticeList,"Your account has been suspended. Some of your permissions may have been revoked.") headerVars.NoticeList = append(headerVars.NoticeList,"Your account has been suspended. Some of your permissions may have been revoked.")
} }

View File

@ -101,7 +101,7 @@ func (sus *MemoryUserStore) CascadeGet(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -121,7 +121,7 @@ func (sus *MemoryUserStore) BypassGet(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -142,7 +142,7 @@ func (sus *MemoryUserStore) Load(id int) error {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -280,7 +280,7 @@ func (sus *SqlUserStore) Get(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -297,7 +297,7 @@ func (sus *SqlUserStore) GetUnsafe(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -314,7 +314,7 @@ func (sus *SqlUserStore) CascadeGet(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag
@ -331,7 +331,7 @@ func (sus *SqlUserStore) BypassGet(id int) (*User, error) {
user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar user.Avatar = "/uploads/avatar_" + strconv.Itoa(user.ID) + user.Avatar
} }
} else { } else {
user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) user.Avatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(user.ID),1)
} }
user.Slug = name_to_slug(user.Name) user.Slug = name_to_slug(user.Name)
user.Tag = groups[user.Group].Tag user.Tag = groups[user.Group].Tag

View File

@ -49,7 +49,8 @@ func relative_time(in string) (string, error) {
return "", nil return "", nil
} }
layout := "2006-01-02 15:04:05" layout := "2006-01-02 15:04:05"
t, err := time.ParseInLocation(layout, in, timeLocation) t, err := time.Parse(layout, in)
//t, err := time.ParseInLocation(layout, in, timeLocation)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -150,20 +151,20 @@ func SendEmail(email string, subject string, msg string) (res bool) {
} }
body := "Subject: " + subject + "\n\n" + msg + "\n" body := "Subject: " + subject + "\n\n" + msg + "\n"
con, err := smtp.Dial(smtp_server + ":" + smtp_port) con, err := smtp.Dial(config.SmtpServer + ":" + config.SmtpPort)
if err != nil { if err != nil {
return return
} }
if smtp_username != "" { if config.SmtpUsername != "" {
auth := smtp.PlainAuth("",smtp_username,smtp_password,smtp_server) auth := smtp.PlainAuth("",config.SmtpUsername,config.SmtpPassword,config.SmtpServer)
err = con.Auth(auth) err = con.Auth(auth)
if err != nil { if err != nil {
return return
} }
} }
err = con.Mail(site_email) err = con.Mail(site.Email)
if err != nil { if err != nil {
return return
} }

View File

@ -13,8 +13,8 @@ import(
"net/http" "net/http"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/shirou/gopsutil/cpu" "github.com/Azareal/gopsutil/cpu"
"github.com/shirou/gopsutil/mem" "github.com/Azareal/gopsutil/mem"
) )
type WS_User struct type WS_User struct

View File

@ -99,7 +99,7 @@ func init_widgets() error {
docks.RightSidebar = rightWidgets docks.RightSidebar = rightWidgets
widget_update_mutex.Unlock() widget_update_mutex.Unlock()
if super_debug { if dev.SuperDebug {
fmt.Println("docks.LeftSidebar",docks.LeftSidebar) fmt.Println("docks.LeftSidebar",docks.LeftSidebar)
fmt.Println("docks.RightSidebar",docks.RightSidebar) fmt.Println("docks.RightSidebar",docks.RightSidebar)
} }