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/*
tmp2/*
uploads/avatar_*
uploads/socialgroup_*
bin/*
*.exe
*.exe~
*.prof
.DS_Store

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@ func init_sendmail() {
// Sendmail is only available on Linux
func activate_sendmail() error {
if !enable_emails {
if !site.EnableEmails {
return errors.New("You have emails disabled in your configuration file")
}
if runtime.GOOS != "linux" {
@ -37,7 +37,7 @@ func send_sendmail(data ...interface{}) interface{} {
subject := data[1].(string)
body := data[2].(string)
msg := "From: " + site_email + "\n"
msg := "From: " + site.Email + "\n"
msg += "To: " + to + "\n"
msg += "Subject: " + subject + "\n\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)}
if debug_mode {
if dev.DebugMode {
log.Print("Added the '" + path + "' static file.")
}
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)}
if debug_mode {
if dev.DebugMode {
log.Print("Added the '" + path + "' static file")
}
return nil

View File

@ -65,7 +65,7 @@ func NewStaticForumStore() *StaticForumStore {
func (sfs *StaticForumStore) LoadForums() error {
log.Print("Adding the uncategorised 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()
@ -89,7 +89,7 @@ func (sfs *StaticForumStore) LoadForums() error {
}
if forum.Name == "" {
if debug_mode {
if dev.DebugMode {
log.Print("Adding a placeholder forum")
}
} else {
@ -111,14 +111,14 @@ func (sfs *StaticForumStore) LoadForums() error {
}
func (sfs *StaticForumStore) DirtyGet(id int) *Forum {
if !((id <= sfs.forumCapCount) && (id >= 0) && sfs.forums[id].Name!="") {
if !((id <= sfs.forumCapCount) && (id >= 0) && sfs.forums[id].Name != "") {
return &Forum{ID:-1,Name:""}
}
return sfs.forums[id]
}
func (sfs *StaticForumStore) Get(id int) (*Forum, error) {
if !((id <= sfs.forumCapCount) && (id >= 0) && sfs.forums[id].Name!="") {
if !((id <= sfs.forumCapCount) && (id >= 0) && sfs.forums[id].Name != "") {
return nil, ErrNoRows
}
return sfs.forums[id], nil

View File

@ -114,7 +114,7 @@ var add_forum_perms_to_forum_members_stmt *sql.Stmt
var notify_watchers_stmt *sql.Stmt
func _gen_mysql() (err error) {
if debug_mode {
if dev.DebugMode {
log.Print("Building the generated statements")
}
@ -365,19 +365,19 @@ func _gen_mysql() (err error) {
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
@ -413,7 +413,7 @@ func _gen_mysql() (err error) {
}
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 {
return err
}
@ -455,13 +455,13 @@ func _gen_mysql() (err error) {
}
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 {
return err
}
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 {
return err
}
@ -473,7 +473,7 @@ func _gen_mysql() (err error) {
}
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 {
return err
}
@ -497,7 +497,7 @@ func _gen_mysql() (err error) {
}
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 {
return err
}

View File

@ -45,12 +45,12 @@ var update_email_stmt *sql.Stmt
var verify_email_stmt *sql.Stmt
func _gen_pgsql() (err error) {
if debug_mode {
if dev.DebugMode {
log.Print("Building the generated statements")
}
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 {
return err
}
@ -74,7 +74,7 @@ func _gen_pgsql() (err error) {
}
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 {
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. */
package main
//import "fmt"
import "fmt"
import "strings"
import "sync"
import "errors"
@ -72,12 +72,20 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
return
}
if dev.SuperDebug {
fmt.Println("before PreRoute")
}
// Deal with the session stuff, etc.
user, ok := PreRoute(w,req)
if !ok {
return
}
if dev.SuperDebug {
fmt.Println("after PreRoute")
}
switch(prefix) {
case "/api":
route_api(w,req,user)
@ -199,7 +207,7 @@ func (router *GenRouter) ServeHTTP(w http.ResponseWriter, req *http.Request) {
router.UploadHandler(w,req)
return
case "":
default_route(w,req,user)
config.DefaultRoute(w,req,user)
return
//default: NotFound(w,req)
}

View File

@ -26,7 +26,7 @@ var db_prod *sql.DB
var gloinited bool
func gloinit() {
debug_mode = false
dev.DebugMode = false
//nogrouplog = true
// init_database is a little noisy for a benchmark
@ -34,8 +34,9 @@ func gloinit() {
//log.SetOutput(discard)
startTime = time.Now()
timeLocation = startTime.Location()
//timeLocation = startTime.Location()
process_config()
init_themes()
err := init_database()
if err != nil {
@ -55,7 +56,7 @@ func gloinit() {
log.Fatal(err)
}
if cache_topicuser == CACHE_STATIC {
if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(user_cache_capacity)
topics = NewMemoryTopicStore(topic_cache_capacity)
} 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"}
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,"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,"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,"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,"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,"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,"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,"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,"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,"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,"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",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",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",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",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",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",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",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",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",config.DefaultGroup,"",0,0,"",no_css_tmpl,0,"","","","",0,"127.0.0.1",false,1,"",""})
headerVars := HeaderVars{
NoticeList:[]string{"test"},

View File

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

View File

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

57
main.go
View File

@ -5,6 +5,7 @@ import (
"net/http"
"fmt"
"log"
"strings"
"time"
"io"
"html/template"
@ -27,10 +28,9 @@ var enable_websockets bool = false // Don't change this, the value is overwritte
var router *GenRouter
var startTime time.Time
var timeLocation *time.Location
//var timeLocation *time.Location
var templates = template.New("")
var no_css_tmpl template.CSS = template.CSS("")
var staff_css_tmpl template.CSS = template.CSS(staff_css)
//var no_css_tmpl template.CSS = template.CSS("")
var settings map[string]interface{} = make(map[string]interface{})
var external_sites map[string]string = make(map[string]string)
var groups []Group
@ -49,6 +49,7 @@ func compile_templates() error {
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"}
headerVars := HeaderVars{
Site:site,
NoticeList:[]string{"test"},
Stylesheets:[]string{"panel"},
Scripts:[]string{"whatever"},
@ -59,9 +60,9 @@ func compile_templates() error {
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
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)
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)
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_page := ForumPage{"General Forum",user,headerVars,topicList,forum_item,1,1,extData}
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() {
if debug_mode {
if dev.DebugMode {
log.Print("Initialising the template system")
}
compile_templates()
@ -134,7 +135,7 @@ func init_templates() {
fmap["divide"] = filler_func
// The interpreted templates...
if debug_mode {
if dev.DebugMode {
log.Print("Loading the template files...")
}
templates.Funcs(fmap)
@ -142,6 +143,16 @@ func init_templates() {
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(){
//if profiling {
// f, err := os.Create("startup_cpu.prof")
@ -154,7 +165,10 @@ func main(){
log.Print("Running Gosora v" + version.String())
fmt.Println("")
startTime = time.Now()
timeLocation = startTime.Location()
//timeLocation = startTime.Location()
fmt.Println("Processing configuration data")
process_config()
init_themes()
err := init_database()
@ -168,9 +182,9 @@ func main(){
log.Fatal(err)
}
if cache_topicuser == CACHE_STATIC {
users = NewMemoryUserStore(user_cache_capacity)
topics = NewMemoryTopicStore(topic_cache_capacity)
if config.CacheTopicUser == CACHE_STATIC {
users = NewMemoryUserStore(config.UserCacheCapacity)
topics = NewMemoryTopicStore(config.TopicCacheCapacity)
} else {
users = NewSqlUserStore()
topics = NewSqlTopicStore()
@ -285,15 +299,20 @@ func main(){
//}
log.Print("Initialising the HTTP server")
if !enable_ssl {
if server_port == "" {
server_port = "80"
if !site.EnableSsl {
if site.Port == "" {
site.Port = "80"
}
http.ListenAndServe(":" + server_port, router)
err = http.ListenAndServe(":" + site.Port, router)
} else {
if server_port == "" {
server_port = "443"
if site.Port == "" {
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
}
_, err = change_group_stmt.Exec(default_group, uid)
_, err = change_group_stmt.Exec(config.DefaultGroup, uid)
if err != nil {
InternalError(err,w,r)
return
@ -724,7 +724,7 @@ func route_activate(w http.ResponseWriter, r *http.Request, user User) {
return
}
_, err = change_group_stmt.Exec(default_group, uid)
_, err = change_group_stmt.Exec(config.DefaultGroup, uid)
if err != nil {
InternalError(err,w,r)
return

View File

@ -18,12 +18,12 @@ var todays_newuser_count_stmt *sql.Stmt
func _init_database() (err error) {
var _dbpassword string
if(dbpassword != ""){
_dbpassword = ":" + dbpassword
if(db_config.Password != ""){
_dbpassword = ":" + db_config.Password
}
// 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 {
return err
}
@ -66,25 +66,25 @@ func _init_database() (err error) {
}
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 {
return err
}
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 {
return err
}
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 {
return err
}
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 {
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 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 (2,1,'{"ViewTopic":true,"CreateReply":true,"CloseTopic":true}');
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 (6,1,'{}');
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`)
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
Stylesheets []string
Widgets PageWidgets
Site *Site
ExtData ExtData
}

View File

@ -7,14 +7,11 @@ import (
"strings"
"strconv"
"html"
"time"
"runtime"
"encoding/json"
"net/http"
"html/template"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/mem"
"github.com/Azareal/gopsutil/mem"
)
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
}
var cpustr, cpuColour string
perc2, err := cpu.Percent(time.Duration(time.Second),true)
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"
}
if dev.SuperDebug {
fmt.Println("past PanelSessionCheck")
}
// 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
memres, err := mem.VirtualMemory()
if err != nil {
@ -126,7 +115,7 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){
var gridElements []GridElement = []GridElement{
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"},
}
@ -189,7 +178,10 @@ func route_panel(w http.ResponseWriter, r *http.Request, user User){
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){
@ -334,7 +326,7 @@ func route_panel_forums_delete_submit(w http.ResponseWriter, r *http.Request, us
InternalError(err,w,r)
return
}
http.Redirect(w,r,"/panel/forums/",http.StatusSeeOther)
}
@ -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
}
} 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 != "" {

View File

@ -205,7 +205,7 @@ func init() {
guest_user.Perms = GuestPerms
if debug_mode {
if dev.DebugMode {
fmt.Printf("Guest Perms: ")
fmt.Printf("%+v\n", GuestPerms)
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 {
if debug_mode {
if dev.DebugMode {
log.Print("Loading the forum permissions")
}
forums, err := fstore.GetAll()
@ -318,7 +318,7 @@ func rebuild_forum_permissions(fid int) error {
}
defer rows.Close()
if debug_mode {
if dev.DebugMode {
log.Print("Updating the forum permissions")
}
for rows.Next() {
@ -342,7 +342,7 @@ func rebuild_forum_permissions(fid int) error {
forum_perms[gid][fid] = pperms
}
for gid, _ := range groups {
if debug_mode {
if dev.DebugMode {
log.Print("Updating the forum permissions for Group #" + strconv.Itoa(gid))
}
var blank_list []ForumPerms
@ -369,7 +369,7 @@ func rebuild_forum_permissions(fid int) error {
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].Forums %+v\n", 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()
if debug_mode {
if dev.DebugMode {
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
@ -416,7 +416,7 @@ func build_forum_permissions() error {
forum_perms[gid][fid] = pperms
}
for gid, _ := range groups {
if debug_mode {
if dev.DebugMode {
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
@ -441,7 +441,7 @@ func build_forum_permissions() error {
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].Forums %+v\n", groups[gid].Forums)
//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_report_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) {
// TO-DO: Investigate connect_timeout to see what it does exactly and whether it's relevant to us
var _dbpassword string
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 {
return err
}

View File

@ -34,6 +34,10 @@ type SocialGroup struct
Desc string
Active bool
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
Owner int
Backdrop string
@ -97,7 +101,7 @@ func init() {
}
func init_socialgroups() (err error) {
plugins["socialgroups"].AddHook("intercept_build_widgets", socialgroups_widgets)
plugins["socialgroups"].AddHook("intercept_build_widgets", socialgroups_widgets)
plugins["socialgroups"].AddHook("trow_assign", socialgroups_trow_assign)
plugins["socialgroups"].AddHook("topic_create_pre_loop", socialgroups_topic_create_pre_loop)
plugins["socialgroups"].AddHook("pre_render_view_forum", socialgroups_pre_render_view_forum)
@ -111,11 +115,11 @@ func init_socialgroups() (err error) {
router.HandleFunc("/group/create/submit/", socialgroups_create_group_submit)
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 {
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 {
return err
}
@ -131,7 +135,7 @@ func init_socialgroups() (err error) {
if err != nil {
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 {
return err
}
@ -143,7 +147,7 @@ func init_socialgroups() (err error) {
if err != nil {
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 {
return err
}
@ -181,12 +185,13 @@ func install_socialgroups() error {
qgen.DB_Table_Column{"sgid","int",0,false,true,""},
qgen.DB_Table_Column{"name","varchar",100,false,false,""},
qgen.DB_Table_Column{"desc","varchar",200,false,false,""},
qgen.DB_Table_Column{"active","tinyint",1,false,false,""},
qgen.DB_Table_Column{"privacy","tinyint",1,false,false,""},
qgen.DB_Table_Column{"active","boolean",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{"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{"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{"createdAt","createdAt",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
for rows.Next() {
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 {
InternalError(err,w,r)
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) {
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
}
@ -441,7 +446,7 @@ func socialgroups_member_list(w http.ResponseWriter, r *http.Request, user User)
var sgItem SocialGroup = SocialGroup{ID:sgid}
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 {
LocalError("Bad group",w,r,user)
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
}
} 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)
if sgItem.Owner == sgMember.User.ID {

View File

@ -839,7 +839,7 @@ import "database/sql"
` + stmts + `
func _gen_mysql() (err error) {
if debug_mode {
if dev.DebugMode {
log.Print("Building the generated statements")
}
` + 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 _, token := range loc.Expr {
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 + ""
case "column":
querystr += " `" + token.Contents + "`"
@ -316,7 +323,7 @@ import "database/sql"
` + stmts + `
func _gen_pgsql() (err error) {
if debug_mode {
if dev.DebugMode {
log.Print("Building the generated statements")
}
` + 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{"megaposts","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{"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
}
@ -224,11 +253,11 @@ func write_inner_joins(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","?,?,?,?")
@ -240,7 +269,7 @@ func write_inserts(adapter qgen.DB_Adapter) error {
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")
@ -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("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
}
@ -269,7 +298,7 @@ func write_replaces(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 = ?")
@ -277,7 +306,7 @@ func write_updates(adapter qgen.DB_Adapter) error {
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 = ?")

View File

@ -1,6 +1,5 @@
/* Copyright Azareal 2016 - 2017 */
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?
@ -18,7 +17,7 @@ type Reply struct /* Should probably rename this to ReplyUser and rename ReplySh
LastEdit int
LastEditBy int
Avatar string
Css template.CSS
ClassName string
ContentLines int
Tag string
URL string

View File

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

View File

@ -14,7 +14,6 @@ import (
"net"
"net/http"
"html"
"html/template"
"./query_gen/lib"
)
@ -26,6 +25,10 @@ var hvars HeaderVars
var extData ExtData
var success_json_bytes []byte = []byte(`{"success":"1"}`)
func init() {
hvars.Site = site
}
// GET functions
func route_static(w http.ResponseWriter, r *http.Request){
//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
}
} 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)
@ -251,16 +254,16 @@ func route_forum(w http.ResponseWriter, r *http.Request, user User, sfid string)
// Calculate the offset
var offset int
last_page := int(forum.TopicCount / items_per_page) + 1
last_page := int(forum.TopicCount / config.ItemsPerPage) + 1
if page > 1 {
offset = (items_per_page * page) - items_per_page
offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else if page == -1 {
page = last_page
offset = (items_per_page * page) - items_per_page
offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else {
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 {
InternalError(err,w,r)
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
}
} 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)
@ -416,7 +419,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
InternalError(err,w,r)
return
}
topic.Css = no_css_tmpl
topic.ClassName = ""
headerVars, ok := ForumSessionCheck(w,r,&user,topic.ParentID)
if !ok {
@ -440,7 +443,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
topic.Tag = groups[topic.Group].Tag
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 {
@ -460,18 +463,18 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
}
// Calculate the offset
last_page := int(topic.PostCount / items_per_page) + 1
last_page := int(topic.PostCount / config.ItemsPerPage) + 1
if page > 1 {
offset = (items_per_page * page) - items_per_page
offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else if page == -1 {
page = last_page
offset = (items_per_page * page) - items_per_page
offset = (config.ItemsPerPage * page) - config.ItemsPerPage
} else {
page = 1
}
// 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 {
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
@ -480,7 +483,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request, user User){
return
}
replyItem := Reply{Css: no_css_tmpl}
replyItem := Reply{ClassName:""}
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)
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")
if groups[replyItem.Group].Is_Mod || groups[replyItem.Group].Is_Admin {
replyItem.Css = staff_css_tmpl
replyItem.ClassName = config.StaffCss
} else {
replyItem.Css = no_css_tmpl
replyItem.ClassName = ""
}
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
}
} 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
@ -588,9 +591,8 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){
}
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 replyCss template.CSS
var replyList []Reply
// SEO URLs...
@ -638,16 +640,16 @@ func route_profile(w http.ResponseWriter, r *http.Request, user User){
replyLines = strings.Count(replyContent,"\n")
if groups[replyGroup].Is_Mod || groups[replyGroup].Is_Admin {
replyCss = staff_css_tmpl
replyClassName = config.StaffCss
} else {
replyCss = no_css_tmpl
replyClassName = ""
}
if replyAvatar != "" {
if replyAvatar[0] == '.' {
replyAvatar = "/uploads/avatar_" + strconv.Itoa(replyCreatedBy) + replyAvatar
}
} else {
replyAvatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyCreatedBy),1)
replyAvatar = strings.Replace(config.Noavatar,"{id}",strconv.Itoa(replyCreatedBy),1)
}
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
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()
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) {
if r.ContentLength > int64(max_request_size) {
if r.ContentLength > int64(config.MaxRequestSize) {
http.Error(w,"Request too large",http.StatusExpectationFailed)
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)
if !ok {
@ -1420,7 +1422,7 @@ func route_account_own_edit_avatar_submit(w http.ResponseWriter, r *http.Request
return
}
err := r.ParseMultipartForm(int64(max_request_size))
err := r.ParseMultipartForm(int64(config.MaxRequestSize))
if err != nil {
LocalError("Upload failed",w,r,user)
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.
// 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 {
email.Email = user.Email
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)
}
if !enable_emails {
if !site.EnableEmails {
headerVars.NoticeList = append(headerVars.NoticeList,"The mail system is currently disabled.")
}
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,"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"] {
case 1: // Activate All
active = 1
group = default_group
group = config.DefaultGroup
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)
@ -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
if enable_emails {
if site.EnableEmails {
token, err := GenerateSafeString(80)
if err != nil {
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. */
// +build !no_templategen
package main
import "strconv"
import "io"
import "strconv"
func init() {
template_forum_handle = template_forum
@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_forum_vars.CurrentUser.Session))
w.Write(header_8)
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([]byte(tmpl_forum_vars.CurrentUser.Slug))
if tmpl_forum_vars.CurrentUser.Loggedin {
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)
if tmpl_forum_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_forum_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_forum_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10)
@ -92,13 +94,13 @@ w.Write(forum_11)
if tmpl_forum_vars.CurrentUser.ID != 0 {
if tmpl_forum_vars.CurrentUser.Perms.CreateTopic {
w.Write(forum_12)
} else {
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
w.Write(forum_13)
}
} else {
w.Write(forum_14)
}
w.Write(forum_15)
w.Write([]byte(strconv.Itoa(tmpl_forum_vars.Forum.ID)))
}
w.Write(forum_16)
if len(tmpl_forum_vars.ItemList) != 0 {
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(header_8)
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([]byte(tmpl_forums_vars.CurrentUser.Slug))
if tmpl_forums_vars.CurrentUser.Loggedin {
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)
if tmpl_forums_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_forums_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_forums_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10)
@ -81,36 +83,28 @@ w.Write(forums_6)
w.Write([]byte(item.Desc))
w.Write(forums_7)
} else {
if item.LastTopicTime != "" {
w.Write(forums_8)
w.Write([]byte(item.Link))
w.Write(forums_9)
w.Write([]byte(item.Name))
w.Write(forums_10)
} else {
}
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(forums_15)
w.Write(forums_12)
w.Write([]byte(item.LastTopic))
w.Write(forums_16)
w.Write(forums_13)
if item.LastTopicTime != "" {
w.Write(forums_17)
w.Write(forums_14)
w.Write([]byte(item.LastTopicTime))
w.Write(forums_18)
w.Write(forums_15)
}
w.Write(forums_19)
w.Write(forums_16)
}
} else {
w.Write(forums_20)
w.Write(forums_17)
}
w.Write(forums_21)
w.Write(forums_18)
w.Write(footer_0)
if tmpl_forums_vars.Header.Widgets.RightSidebar != "" {
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_right">
<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_topics"><a href="/">Topics</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_profile"><a href="/user/`)
var menu_2 []byte = []byte(`.`)
var menu_3 []byte = []byte(`">Profile</a></li>
var menu_3 []byte = []byte(`.`)
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(`
var menu_5 []byte = []byte(`<li class="menu_left menu_account"><a href="/panel/">Panel</a></li>`)
var menu_6 []byte = []byte(`
<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_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">
<div class="alert_bell">🔔</div>
<div class="alert_bell"></div>
<div class="alert_counter"></div>
<div class="alert_aftercounter"></div>
<div class="alertList"></div>
</li>
</ul>
@ -87,10 +89,10 @@ var topic_8 []byte = []byte(`
<div class="rowblock rowhead topic_block">
<form action='/topic/edit/submit/`)
var topic_9 []byte = []byte(`' method="post">
<div class="rowitem topic_item"`)
var topic_10 []byte = []byte(` style="background-color:#FFFFEA;"`)
var topic_11 []byte = []byte(` style="background-color:#eaeaea;"`)
var topic_12 []byte = []byte(`>
<div class="rowitem topic_item`)
var topic_10 []byte = []byte(` topic_sticky_head`)
var topic_11 []byte = []byte(` topic_closed_head`)
var topic_12 []byte = []byte(`">
<a class='topic_name hide_on_edit'>`)
var topic_13 []byte = []byte(`</a>
`)
@ -111,114 +113,116 @@ var topic_19 []byte = []byte(`
</form>
</div>
<div class="rowblock post_container top_post">
<div class="rowitem passive editable_parent post_item" style="border-bottom: none;`)
var topic_20 []byte = []byte(`background-image:url(`)
var topic_21 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_22 []byte = []byte(`-1`)
var topic_23 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;`)
var topic_24 []byte = []byte(`">
<div class="rowitem passive editable_parent post_item `)
var topic_20 []byte = []byte(`" style="`)
var topic_21 []byte = []byte(`background-image:url(`)
var topic_22 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_23 []byte = []byte(`-1`)
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;">`)
var topic_25 []byte = []byte(`</p>
var topic_26 []byte = []byte(`</p>
<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">
<a href="/user/`)
var topic_27 []byte = []byte(`.`)
var topic_28 []byte = []byte(`" class="username real_username">`)
var topic_29 []byte = []byte(`</a>&nbsp;&nbsp;
var topic_28 []byte = []byte(`.`)
var topic_29 []byte = []byte(`" class="username real_username">`)
var topic_30 []byte = []byte(`</a>&nbsp;&nbsp;
`)
var topic_30 []byte = []byte(`<a href="/topic/like/submit/`)
var topic_31 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;">
var topic_31 []byte = []byte(`<a href="/topic/like/submit/`)
var topic_32 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;">
<button class="username like_label" style="`)
var topic_32 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_33 []byte = []byte(`"></button></a>`)
var topic_34 []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(`<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(`<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(`<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(`
var topic_33 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_34 []byte = []byte(`"></button></a>`)
var topic_35 []byte = []byte(`<a href='/topic/edit/`)
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_37 []byte = []byte(`<a href='/topic/delete/submit/`)
var topic_38 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Delete Topic"><button class="username trash_label"></button></a>`)
var topic_39 []byte = []byte(`<a class="mod_button" href='/topic/unstick/submit/`)
var topic_40 []byte = []byte(`' style="font-weight:normal;" title="Unpin Topic"><button class="username unpin_label"></button></a>`)
var topic_41 []byte = []byte(`<a href='/topic/stick/submit/`)
var topic_42 []byte = []byte(`' class="mod_button" style="font-weight:normal;" title="Pin Topic"><button class="username pin_label"></button></a>`)
var topic_43 []byte = []byte(`
<a class="mod_button" href="/report/submit/`)
var topic_43 []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_44 []byte = []byte(`?session=`)
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><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>`)
var topic_49 []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(`
var topic_46 []byte = []byte(`<a class="username hide_on_micro like_count">`)
var topic_47 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`)
var topic_48 []byte = []byte(`<a class="username hide_on_micro user_tag">`)
var topic_49 []byte = []byte(`</a>`)
var topic_50 []byte = []byte(`<a class="username hide_on_micro level">`)
var topic_51 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="float:right;" title="Level"></a>`)
var topic_52 []byte = []byte(`
</span>
</div>
</div>
<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">
<span class="action_icon" style="font-size: 18px;padding-right: 5px;">`)
var topic_53 []byte = []byte(`</span>
<span>`)
var topic_54 []byte = []byte(`</span>
<span>`)
var topic_55 []byte = []byte(`</span>
</div>
`)
var topic_55 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent post_item" style="`)
var topic_56 []byte = []byte(`background-image:url(`)
var topic_57 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_58 []byte = []byte(`-1`)
var topic_59 []byte = []byte(`0px;background-repeat:no-repeat, repeat-y;background-size:128px;padding-left:136px;`)
var topic_60 []byte = []byte(`">
var topic_56 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent post_item `)
var topic_57 []byte = []byte(`" style="`)
var topic_58 []byte = []byte(`background-image:url(`)
var topic_59 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var topic_60 []byte = []byte(`-1`)
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;">`)
var topic_61 []byte = []byte(`</p>
var topic_63 []byte = []byte(`</p>
<span class="controls">
<a href="/user/`)
var topic_62 []byte = []byte(`.`)
var topic_63 []byte = []byte(`" class="username real_username">`)
var topic_64 []byte = []byte(`</a>&nbsp;&nbsp;
var topic_64 []byte = []byte(`.`)
var topic_65 []byte = []byte(`" class="username real_username">`)
var topic_66 []byte = []byte(`</a>&nbsp;&nbsp;
`)
var topic_65 []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_67 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_68 []byte = []byte(`"></button></a>`)
var topic_69 []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_71 []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_73 []byte = []byte(`
var topic_67 []byte = []byte(`<a href="/reply/like/submit/`)
var topic_68 []byte = []byte(`" class="mod_button" title="Love it" style="color:#202020;"><button class="username like_label" style="`)
var topic_69 []byte = []byte(`background-color:/*#eaffea*/#D6FFD6;`)
var topic_70 []byte = []byte(`"></button></a>`)
var topic_71 []byte = []byte(`<a href="/reply/edit/submit/`)
var topic_72 []byte = []byte(`" class="mod_button" title="Edit Reply"><button class="username edit_item edit_label"></button></a>`)
var topic_73 []byte = []byte(`<a href="/reply/delete/submit/`)
var topic_74 []byte = []byte(`" class="mod_button" title="Delete Reply"><button class="username delete_item trash_label"></button></a>`)
var topic_75 []byte = []byte(`
<a class="mod_button" href="/report/submit/`)
var topic_74 []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_76 []byte = []byte(`?session=`)
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_77 []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_79 []byte = []byte(`</a>`)
var topic_80 []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_82 []byte = []byte(`</a>
var topic_78 []byte = []byte(`<a class="username hide_on_micro like_count">`)
var topic_79 []byte = []byte(`</a><a class="username hide_on_micro like_count_label" title="Like Count"></a>`)
var topic_80 []byte = []byte(`<a class="username hide_on_micro user_tag">`)
var topic_81 []byte = []byte(`</a>`)
var topic_82 []byte = []byte(`<a class="username hide_on_micro level">`)
var topic_83 []byte = []byte(`</a><a class="username hide_on_micro level_label" style="float:right;" title="Level">`)
var topic_84 []byte = []byte(`</a>
</span>
</div>
`)
var topic_83 []byte = []byte(`</div>
var topic_85 []byte = []byte(`</div>
`)
var topic_84 []byte = []byte(`
<div class="rowblock">
var topic_86 []byte = []byte(`
<div class="rowblock topic_reply_form">
<form action="/reply/create/" method="post">
<input name="tid" value='`)
var topic_85 []byte = []byte(`' type="hidden" />
<div class="formrow">
var topic_87 []byte = []byte(`' type="hidden" />
<div class="formrow real_first_child">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
</div>
<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>
<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="avatar_item" style="background-image: url(`)
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_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">
<input name="tid" value='`)
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 id="profile_comments" class="colblock_right" style="overflow: hidden;border-top: none;width:calc(95% - 210px);">`)
var profile_17 []byte = []byte(`
<div class="rowitem passive deletable_block editable_parent simple" style="`)
var profile_18 []byte = []byte(`background-image: url(`)
var profile_19 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var profile_20 []byte = []byte(`-1`)
var profile_21 []byte = []byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128px;padding-left: 136px;`)
var profile_22 []byte = []byte(`">
<div class="rowitem passive deletable_block editable_parent simple `)
var profile_18 []byte = []byte(`" style="`)
var profile_19 []byte = []byte(`background-image: url(`)
var profile_20 []byte = []byte(`), url(/static/white-dot.jpg);background-position: 0px `)
var profile_21 []byte = []byte(`-1`)
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">`)
var profile_23 []byte = []byte(`</span><br /><br />
var profile_24 []byte = []byte(`</span><br /><br />
<a href="/user/`)
var profile_24 []byte = []byte(`.`)
var profile_25 []byte = []byte(`" class="real_username username">`)
var profile_26 []byte = []byte(`</a>&nbsp;&nbsp;
var profile_25 []byte = []byte(`.`)
var profile_26 []byte = []byte(`" class="real_username username">`)
var profile_27 []byte = []byte(`</a>&nbsp;&nbsp;
`)
var profile_27 []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_28 []byte = []byte(`<a href="/profile/reply/edit/submit/`)
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/`)
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(`
var profile_30 []byte = []byte(`" class="mod_button" title="Delete Item"><button class="username delete_item trash_label"></button></a>`)
var profile_31 []byte = []byte(`
<a class="mod_button" href="/report/submit/`)
var profile_31 []byte = []byte(`?session=`)
var profile_32 []byte = []byte(`&type=user-reply"><button class="username report_item flag_label"></button></a>
var profile_32 []byte = []byte(`?session=`)
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>`)
var profile_35 []byte = []byte(`
var profile_34 []byte = []byte(`<a class="username hide_on_mobile" style="float: right;">`)
var profile_35 []byte = []byte(`</a>`)
var profile_36 []byte = []byte(`
</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);">
`)
var profile_37 []byte = []byte(`
var profile_38 []byte = []byte(`
<form action="/profile/reply/create/" method="post">
<input name="uid" value='`)
var profile_38 []byte = []byte(`' type="hidden" />
var profile_39 []byte = []byte(`' type="hidden" />
<div class="formrow">
<div class="formitem"><textarea name="reply-content" placeholder="Insert reply here"></textarea></div>
</div>
@ -493,7 +498,7 @@ var profile_38 []byte = []byte(`' type="hidden" />
</div>
</form>
`)
var profile_39 []byte = []byte(`
var profile_40 []byte = []byte(`
</div>
`)
@ -514,32 +519,28 @@ var forums_6 []byte = []byte(`</a>
<br /><span class="rowsmall">`)
var forums_7 []byte = []byte(`</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="`)
var forums_9 []byte = []byte(`">`)
var forums_10 []byte = []byte(`</a>
<br /><span class="rowsmall" style="font-style: italic;">No description</span>
</span>`)
var forums_11 []byte = []byte(`<span style="float: left;">
<a href="`)
var forums_12 []byte = []byte(`">`)
var forums_13 []byte = []byte(`</a>
</span>`)
var forums_14 []byte = []byte(`
var forums_11 []byte = []byte(`
<span style="float: right;">
<a href="/topic/`)
var forums_15 []byte = []byte(`" style="float: right;font-size: 14px;">`)
var forums_16 []byte = []byte(`</a>
var forums_12 []byte = []byte(`" style="float: right;font-size: 14px;">`)
var forums_13 []byte = []byte(`</a>
`)
var forums_17 []byte = []byte(`<br /><span class="rowsmall">`)
var forums_18 []byte = []byte(`</span>`)
var forums_19 []byte = []byte(`
var forums_14 []byte = []byte(`<br /><span class="rowsmall">`)
var forums_15 []byte = []byte(`</span>`)
var forums_16 []byte = []byte(`
</span>
<div style="clear: both;"></div>
</div>
`)
var forums_20 []byte = []byte(`<div class="rowitem passive">You don't have access to any forums.</div>`)
var forums_21 []byte = []byte(`
var forums_17 []byte = []byte(`<div class="rowitem passive">You don't have access to any forums.</div>`)
var forums_18 []byte = []byte(`
</div>
`)
var topics_0 []byte = []byte(`
@ -605,15 +606,14 @@ var forum_11 []byte = []byte(`</a>
</div>
`)
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(`
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_15 []byte = []byte(`
<div style="clear: both;"></div>
`)
var forum_15 []byte = []byte(`
<!--href="/topics/create/`)
var forum_16 []byte = []byte(`"-->
var forum_16 []byte = []byte(`
</div>
<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(header_8)
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([]byte(tmpl_profile_vars.CurrentUser.Slug))
if tmpl_profile_vars.CurrentUser.Loggedin {
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)
if tmpl_profile_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_profile_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_profile_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10)
@ -100,52 +102,53 @@ w.Write(profile_16)
if len(tmpl_profile_vars.ItemList) != 0 {
for _, item := range tmpl_profile_vars.ItemList {
w.Write(profile_17)
if item.Avatar != "" {
w.Write([]byte(item.ClassName))
w.Write(profile_18)
w.Write([]byte(item.Avatar))
if item.Avatar != "" {
w.Write(profile_19)
if item.ContentLines <= 5 {
w.Write([]byte(item.Avatar))
w.Write(profile_20)
}
if item.ContentLines <= 5 {
w.Write(profile_21)
w.Write([]byte(string(item.Css)))
}
w.Write(profile_22)
w.Write([]byte(item.ContentHtml))
}
w.Write(profile_23)
w.Write([]byte(item.UserSlug))
w.Write([]byte(item.ContentHtml))
w.Write(profile_24)
w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write([]byte(item.UserSlug))
w.Write(profile_25)
w.Write([]byte(item.CreatedByName))
w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write(profile_26)
if tmpl_profile_vars.CurrentUser.Is_Mod {
w.Write([]byte(item.CreatedByName))
w.Write(profile_27)
w.Write([]byte(strconv.Itoa(item.ID)))
if tmpl_profile_vars.CurrentUser.Is_Mod {
w.Write(profile_28)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_29)
}
w.Write(profile_30)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(profile_31)
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_30)
}
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_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_40)
w.Write(footer_0)
if tmpl_profile_vars.Header.Widgets.RightSidebar != "" {
w.Write(footer_1)

View File

@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
w.Write(header_8)
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([]byte(tmpl_topic_vars.CurrentUser.Slug))
if tmpl_topic_vars.CurrentUser.Loggedin {
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)
if tmpl_topic_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_topic_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_topic_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10)
@ -108,153 +110,155 @@ w.Write(topic_17)
w.Write(topic_18)
}
w.Write(topic_19)
if tmpl_topic_vars.Topic.Avatar != "" {
w.Write([]byte(tmpl_topic_vars.Topic.ClassName))
w.Write(topic_20)
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
if tmpl_topic_vars.Topic.Avatar != "" {
w.Write(topic_21)
if tmpl_topic_vars.Topic.ContentLines <= 5 {
w.Write([]byte(tmpl_topic_vars.Topic.Avatar))
w.Write(topic_22)
}
if tmpl_topic_vars.Topic.ContentLines <= 5 {
w.Write(topic_23)
w.Write([]byte(string(tmpl_topic_vars.Topic.Css)))
}
w.Write(topic_24)
w.Write([]byte(tmpl_topic_vars.Topic.Content))
}
w.Write(topic_25)
w.Write([]byte(tmpl_topic_vars.Topic.Content))
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([]byte(strconv.Itoa(tmpl_topic_vars.Topic.CreatedBy)))
w.Write([]byte(tmpl_topic_vars.Topic.UserSlug))
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)
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
w.Write([]byte(tmpl_topic_vars.Topic.CreatedByName))
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)
if tmpl_topic_vars.Topic.Liked {
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_32)
}
if tmpl_topic_vars.Topic.Liked {
w.Write(topic_33)
}
if tmpl_topic_vars.CurrentUser.Perms.EditTopic {
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([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_36)
}
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([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_38)
}
if tmpl_topic_vars.CurrentUser.Perms.PinTopic {
if tmpl_topic_vars.Topic.Sticky {
w.Write(topic_38)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_39)
} else {
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_40)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
} else {
w.Write(topic_41)
}
}
w.Write(topic_42)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
w.Write(topic_42)
}
}
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)
if tmpl_topic_vars.Topic.LikeCount > 0 {
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
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([]byte(strconv.Itoa(tmpl_topic_vars.Topic.LikeCount)))
w.Write(topic_47)
}
if tmpl_topic_vars.Topic.Tag != "" {
w.Write(topic_47)
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
w.Write(topic_48)
} else {
w.Write([]byte(tmpl_topic_vars.Topic.Tag))
w.Write(topic_49)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
} else {
w.Write(topic_50)
}
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.Level)))
w.Write(topic_51)
}
w.Write(topic_52)
if len(tmpl_topic_vars.ItemList) != 0 {
for _, item := range tmpl_topic_vars.ItemList {
if item.ActionType != "" {
w.Write(topic_52)
w.Write([]byte(item.ActionIcon))
w.Write(topic_53)
w.Write([]byte(item.ActionType))
w.Write([]byte(item.ActionIcon))
w.Write(topic_54)
} else {
w.Write([]byte(item.ActionType))
w.Write(topic_55)
if item.Avatar != "" {
} else {
w.Write(topic_56)
w.Write([]byte(item.Avatar))
w.Write([]byte(item.ClassName))
w.Write(topic_57)
if item.ContentLines <= 5 {
if item.Avatar != "" {
w.Write(topic_58)
}
w.Write([]byte(item.Avatar))
w.Write(topic_59)
w.Write([]byte(string(item.Css)))
}
if item.ContentLines <= 5 {
w.Write(topic_60)
w.Write([]byte(item.ContentHtml))
}
w.Write(topic_61)
w.Write([]byte(item.UserSlug))
}
w.Write(topic_62)
w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write([]byte(item.ContentHtml))
w.Write(topic_63)
w.Write([]byte(item.CreatedByName))
w.Write([]byte(item.UserSlug))
w.Write(topic_64)
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
w.Write([]byte(strconv.Itoa(item.CreatedBy)))
w.Write(topic_65)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write([]byte(item.CreatedByName))
w.Write(topic_66)
if item.Liked {
if tmpl_topic_vars.CurrentUser.Perms.LikeItem {
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(topic_68)
if item.Liked {
w.Write(topic_69)
}
w.Write(topic_70)
}
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
if tmpl_topic_vars.CurrentUser.Perms.EditReply {
w.Write(topic_71)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_72)
}
if tmpl_topic_vars.CurrentUser.Perms.DeleteReply {
w.Write(topic_73)
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_74)
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
}
w.Write(topic_75)
if item.LikeCount > 0 {
w.Write([]byte(strconv.Itoa(item.ID)))
w.Write(topic_76)
w.Write([]byte(strconv.Itoa(item.LikeCount)))
w.Write([]byte(tmpl_topic_vars.CurrentUser.Session))
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 != "" {
w.Write(topic_78)
w.Write([]byte(item.Tag))
w.Write(topic_79)
} else {
w.Write(topic_80)
w.Write([]byte(strconv.Itoa(item.Level)))
w.Write([]byte(item.Tag))
w.Write(topic_81)
}
} else {
w.Write(topic_82)
}
}
}
w.Write([]byte(strconv.Itoa(item.Level)))
w.Write(topic_83)
if tmpl_topic_vars.CurrentUser.Perms.CreateReply {
}
w.Write(topic_84)
w.Write([]byte(strconv.Itoa(tmpl_topic_vars.Topic.ID)))
}
}
}
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)
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(header_8)
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([]byte(tmpl_topic_alt_vars.CurrentUser.Slug))
if tmpl_topic_alt_vars.CurrentUser.Loggedin {
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)
if tmpl_topic_alt_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_topic_alt_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_topic_alt_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_topic_alt_vars.Header.Widgets.RightSidebar != "" {
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. */
// +build !no_templategen
package main
import "io"
import "strconv"
import "io"
func init() {
template_topics_handle = template_topics
@ -36,22 +36,24 @@ w.Write(header_7)
w.Write([]byte(tmpl_topics_vars.CurrentUser.Session))
w.Write(header_8)
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([]byte(tmpl_topics_vars.CurrentUser.Slug))
if tmpl_topics_vars.CurrentUser.Loggedin {
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)
if tmpl_topics_vars.CurrentUser.Is_Super_Mod {
w.Write([]byte(strconv.Itoa(tmpl_topics_vars.CurrentUser.ID)))
w.Write(menu_4)
}
if tmpl_topics_vars.CurrentUser.Is_Super_Mod {
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_9)
w.Write(header_9)
if tmpl_topics_vars.Header.Widgets.RightSidebar != "" {
w.Write(header_10)

View File

@ -93,7 +93,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
}
content := string(res)
if minify_templates {
if config.MinifyTemplates {
content = minify(content)
}
@ -103,7 +103,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
if err != nil {
log.Fatal(err)
}
if super_debug {
if dev.SuperDebug {
fmt.Println(name)
}
@ -113,7 +113,7 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
c.tlist[fname] = tree
varholder := "tmpl_" + fname + "_vars"
if super_debug {
if dev.SuperDebug {
fmt.Println(c.tlist)
}
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
subtree := c.tlist[fname]
if super_debug {
if dev.SuperDebug {
fmt.Println(subtree.Root)
}
treeLength := len(subtree.Root.Nodes)
for index, node := range subtree.Root.Nodes {
if super_debug {
if dev.SuperDebug {
fmt.Println("Node: " + node.String())
}
@ -168,14 +168,14 @@ w.Write([]byte(`," + ",-1)
//whitespace_writes := regexp.MustCompile(`(?s)w.Write\(\[\]byte\(`+spstr+`\)\)`)
//fout = whitespace_writes.ReplaceAllString(fout,"")
if debug_mode {
if dev.DebugMode {
for index, count := range c.stats {
fmt.Println(index + ": " + strconv.Itoa(count))
}
fmt.Println(" ")
}
if super_debug {
if dev.SuperDebug {
fmt.Println("Output!")
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_switch")
}
switch node := node.(type) {
case *parse.ActionNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Action Node")
}
if node.Pipe == nil {
@ -199,24 +199,24 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
}
return out
case *parse.IfNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("If Node:")
fmt.Println("node.Pipe",node.Pipe)
}
var expr string
for _, cmd := range node.Pipe.Cmds {
if super_debug {
if dev.SuperDebug {
fmt.Println("If Node Bit:",cmd)
fmt.Println("If Node Bit Type:",reflect.ValueOf(cmd).Type().Name())
}
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))
}
}
if super_debug {
if dev.SuperDebug {
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.nextNode = -1
if node.ElseList == nil {
if super_debug {
if dev.SuperDebug {
fmt.Println("Selected Branch 1")
}
return "if " + expr + " {\n" + c.compile_switch(varholder, holdreflect, template_name, node.List) + "}\n"
} else {
if super_debug {
if dev.SuperDebug {
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"
}
case *parse.ListNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("List Node")
}
for _, subnode := range node.Nodes {
@ -243,20 +243,20 @@ func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Valu
}
return out
case *parse.RangeNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Range Node!")
fmt.Println(node.Pipe)
}
var outVal reflect.Value
for _, cmd := range node.Pipe.Cmds {
if super_debug {
if dev.SuperDebug {
fmt.Println("Range Bit:",cmd)
}
out, outVal = c.compile_reflectswitch(varholder, holdreflect, template_name, cmd)
}
if super_debug {
if dev.SuperDebug {
fmt.Println("Returned:",out)
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_subswitch")
}
firstWord := node.Args[0]
switch n := firstWord.(type) {
case *parse.FieldNode:
if super_debug {
if dev.SuperDebug {
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 {
if super_debug {
if dev.SuperDebug {
fmt.Println("Data Kind:",cur.Kind().String())
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)
if cur.Kind() == reflect.Interface {
cur = cur.Elem()
@ -356,7 +370,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
} else {
varbit += "." + id
}
if super_debug {
if dev.SuperDebug {
fmt.Println("End Cycle")
}
}
@ -369,14 +383,14 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
}
return out
case *parse.DotNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Dot Node:",node.String())
}
return c.compile_varsub(varholder, holdreflect)
case *parse.NilNode:
panic("Nil is not a command x.x")
case *parse.VariableNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Variable Node:",n.String())
fmt.Println(n.Ident)
}
@ -385,7 +399,7 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V
case *parse.StringNode:
return n.Quoted
case *parse.IdentifierNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Identifier Node:",node)
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_varswitch")
}
firstWord := node.Args[0]
switch n := firstWord.(type) {
case *parse.FieldNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Field Node:",n.Ident)
for _, id := range n.Ident {
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. */
return c.compile_boolsub(n.String(), varholder, template_name, holdreflect)
case *parse.ChainNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Chain Node:",n.Node)
fmt.Println("Chain Node Args:",node.Args)
}
break
case *parse.IdentifierNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Identifier Node:",node)
fmt.Println("Identifier Node Args:",node.Args)
}
@ -429,7 +443,7 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
case *parse.DotNode:
return varholder
case *parse.VariableNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Variable Node:",n.String())
fmt.Println("Variable Node Identifier:",n.Ident)
}
@ -438,14 +452,14 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
case *parse.NilNode:
panic("Nil is not a command x.x")
case *parse.PipeNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Pipe Node!")
fmt.Println(n)
fmt.Println("Args:",node.Args)
}
out += c.compile_identswitch_n(varholder, holdreflect, template_name, node)
if super_debug {
if dev.SuperDebug {
fmt.Println("Out:",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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_identswitch_n")
}
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_identswitch")
}
@ -474,7 +488,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
ArgLoop:
for pos := 0; pos < len(node.Args); pos++ {
id := node.Args[pos]
if super_debug {
if dev.SuperDebug {
fmt.Println("pos:",pos)
fmt.Println("ID:",id)
}
@ -482,7 +496,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
case "not":
out += "!"
case "or":
if super_debug {
if dev.SuperDebug {
fmt.Println("Building or function")
}
if pos == 0 {
@ -507,7 +521,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
out += left + " || " + right
if super_debug {
if dev.SuperDebug {
fmt.Println("Left 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++
}
if super_debug {
if dev.SuperDebug {
fmt.Println("pos:",pos)
fmt.Println("len(node.Args):",len(node.Args))
}
case "and":
if super_debug {
if dev.SuperDebug {
fmt.Println("Building and function")
}
if pos == 0 {
@ -546,7 +560,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
out += left + " && " + right
if super_debug {
if dev.SuperDebug {
fmt.Println("Left 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++
}
if super_debug {
if dev.SuperDebug {
fmt.Println("pos:",pos)
fmt.Println("len(node.Args):",len(node.Args))
}
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
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)
if super_debug {
if dev.SuperDebug {
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
@ -615,7 +629,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
}
out += param1 + " + " + param2
if super_debug {
if dev.SuperDebug {
fmt.Println("add")
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
@ -635,7 +649,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
}
out += param1 + " - " + param2
if super_debug {
if dev.SuperDebug {
fmt.Println("subtract")
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
@ -655,7 +669,7 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
}
out += param1 + " / " + param2
if super_debug {
if dev.SuperDebug {
fmt.Println("divide")
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
@ -675,14 +689,14 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect
}
out += param1 + " * " + param2
if super_debug {
if dev.SuperDebug {
fmt.Println("multiply")
fmt.Println(node.Args[pos + 1])
fmt.Println(node.Args[pos + 2])
}
break ArgLoop
default:
if super_debug {
if dev.SuperDebug {
fmt.Println("Variable!")
}
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_reflectswitch")
}
firstWord := node.Args[0]
switch n := firstWord.(type) {
case *parse.FieldNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Field Node:",n.Ident)
for _, id := range n.Ident {
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. */
return c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
case *parse.ChainNode:
if super_debug {
if dev.SuperDebug {
fmt.Println("Chain Node: ")
fmt.Println(n.Node)
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_if_varsub_n")
}
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_if_varsub")
}
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],"$")
if super_debug {
if dev.SuperDebug {
fmt.Println("Cur Kind:",cur.Kind())
fmt.Println("Cur Type:",cur.Type().Name())
}
for _, bit := range bits {
if super_debug {
if dev.SuperDebug {
fmt.Println("Variable Field!")
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?")
}
if super_debug {
if dev.SuperDebug {
fmt.Println("Data Kind:",cur.Kind())
fmt.Println("Data Type:",cur.Type().Name())
}
}
if super_debug {
if dev.SuperDebug {
fmt.Println("Out Value:",out)
fmt.Println("Out Kind:",cur.Kind())
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 Kind:",cur.Kind())
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 {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_boolsub")
}
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 {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_varsub")
}
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) {
if super_debug {
if dev.SuperDebug {
fmt.Println("in compile_subtemplate")
fmt.Println("Template Node: " + node.Name)
}
@ -929,7 +943,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
}
content := string(res)
if minify_templates {
if config.MinifyTemplates {
content = minify(content)
}
@ -942,7 +956,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
c.tlist[fname] = tree
subtree := c.tlist[fname]
if super_debug {
if dev.SuperDebug {
fmt.Println(subtree.Root)
}
@ -952,7 +966,7 @@ func (c *CTemplateSet) compile_subtemplate(pvarholder string, pholdreflect refle
treeLength := len(subtree.Root.Nodes)
for index, node := range subtree.Root.Nodes {
if super_debug {
if dev.SuperDebug {
fmt.Println("Node:",node.String())
}

View File

@ -9,11 +9,10 @@
</div>
{{if ne .CurrentUser.ID 0}}
{{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}}
<div style="clear: both;"></div>
{{end}}
<!--href="/topics/create/{{.Forum.ID}}"-->
</div>
<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}}">

View File

@ -7,10 +7,9 @@
{{if .Desc}}<span style="float: left;">
<a href="{{.Link}}" style="">{{.Name}}</a>
<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;">
<a href="{{.Link}}">{{.Name}}</a>
<br /><span class="rowsmall" style="font-style: italic;">No description</span>
</span>{{end}}
<span style="float: right;">

View File

@ -2,7 +2,7 @@
<div class="move_left">
<div class="move_right">
<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_topics"><a href="/">Topics</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>
{{end}}
<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_aftercounter"></div>
<div class="alertList"></div>
</li>
</ul>

View File

@ -23,7 +23,7 @@
<div class="rowitem"><a>Comments</a></div>
</div>
<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 />
<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">
<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>
{{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}}
@ -24,7 +24,7 @@
</form>
</div>
<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>
<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.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>
</div>
@ -54,7 +54,7 @@
<span>{{.ActionType}}</span>
</div>
{{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>
<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 .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>
</div>
{{end}}{{end}}</div>
{{if .CurrentUser.Perms.CreateReply}}
<div class="rowblock">
<div class="rowblock topic_reply_form">
<form action="/reply/create/" method="post">
<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>
<div class="formrow">

View File

@ -22,7 +22,7 @@
<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="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="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>
@ -76,7 +76,7 @@
</div>
{{end}}</div>
{{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">
<input name="tid" value='{{.Topic.ID}}' type="hidden" />
<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
if theme.FullImage != "" {
if debug_mode {
if dev.DebugMode {
log.Print("Adding theme image")
}
err = add_static_file("./themes/" + themeName + "/" + theme.FullImage, "./themes/" + themeName)
@ -155,7 +155,7 @@ func init_themes() {
func add_theme_static_files(theme Theme) {
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 + "'")
}
if err != nil {
@ -174,7 +174,7 @@ func add_theme_static_files(theme Theme) {
var ext string = filepath.Ext(path)
//log.Print("path ",path)
//log.Print("ext ",ext)
if ext == ".css" {
if ext == ".css" && len(data) != 0 {
var b bytes.Buffer
var pieces []string = strings.Split(path,"/")
var filename string = pieces[len(pieces) - 1]
@ -190,7 +190,7 @@ func add_theme_static_files(theme Theme) {
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)}
if debug_mode {
if dev.DebugMode {
log.Print("Added the '" + path + "' static file for default theme " + theme.Name + ".")
}
return nil

View File

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

View File

@ -71,6 +71,10 @@ li:hover {
border-left: 1px solid #7a7a7a;
}
.alert_bell:before {
content: '🔔︎';
}
.menu_alerts .alert_counter {
position: relative;
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",
"Version": "0.0.1",
"Creator": "Azareal",
"Disabled": true,
"HideFromThemes": true,
"URL": "github.com/Azareal/Gosora"
"URL": "github.com/Azareal/Gosora",
"Tag": "WIP"
}

View File

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

View File

@ -49,6 +49,9 @@ li a {
padding-right: 10px;
}
.alert_bell:before {
content: '🔔︎';
}
.menu_bell {
cursor: default;
}
@ -348,6 +351,23 @@ button.username {
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 {
display: inline-block;
padding-bottom: 0px;
@ -399,8 +419,8 @@ button.username {
.pin_label:before { content: "Pin"; }
.unpin_label:before { content: "Unpin"; }
.flag_label:before { content: "Flag"; }
.level_label { margin-right: 1px; }
.level_label:before { content: "Level"; }
.level_label { margin-right: 1px; color: #505050; }
.level_label:before { content: "Level"; opacity:0.85; }
.controls {
margin-top: 23px;

View File

@ -18,7 +18,7 @@ ul {
height: 36px;
list-style-type: none;
border: 1px solid #ccc;
background-color: rgb(248,248,248);
background-color: rgb(252,252,252);
margin-bottom: 12px;
}
li {
@ -29,7 +29,7 @@ li {
background: white;
border-bottom: 1px solid #ccc;
}
li:hover { background: rgb(250,250,250); }
li:hover { background: rgb(252,252,252); }
li a {
text-decoration: none;
/*color: #515151;*/
@ -46,8 +46,20 @@ li a {
border-left: 1px solid #ccc;
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 {
/*padding-left: 7px;*/
font-size: 20px;
@ -222,7 +234,7 @@ li a {
.stat_red { background-color: #ffb2b2; border-color: #ffb2b2; }
.stat_disabled { background-color: lightgray; border-color: lightgray; }
.rowhead {
.rowhead, .colstack_head {
border-bottom: none;
}
.rowhead .rowitem, .colstack_head .rowitem {
@ -265,8 +277,9 @@ li a {
width: 50px;
text-align: center;
}
.create_topic_opt {
.create_topic_opt, .create_topic_opt a {
color: rgb(120,120,120);
text-decoration: none;
}
.locked_opt {
color: rgb(80,80,80);
@ -339,6 +352,12 @@ button {
.topic_closed {
background-color: rgb(248,248,248);
}
.topic_sticky_head {
background-color:#FFFFEA;
}
.topic_closed_head {
background-color:#eaeaea;
}
.topic_status {
text-transform: none;
@ -397,6 +416,19 @@ button.username {
}
.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; }
.like_label:before, .like_count_label:before { content: "😀"; }
.like_count_label {
@ -421,6 +453,7 @@ button.username {
.unpin_label { background-color: #D6FFD6; }
.flag_label:before { content: "🚩"; }
.level_label:before { content: "👑"; }
.level_label { color: #505050; opacity:0.85; }
.controls {
margin-top: 23px;

View File

@ -48,7 +48,6 @@ type TopicUser struct
CreatedByName string
Group int
Avatar string
Css template.CSS
ContentLines int
Tag string
URL string
@ -93,7 +92,7 @@ type TopicsRow struct
}
func get_topicuser(tid int) (TopicUser,error) {
if cache_topicuser != CACHE_SQL {
if config.CacheTopicUser != CACHE_SQL {
topic, err := topics.Get(tid)
if err == nil {
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 {
var schema string = "http"
if enable_ssl {
if site.EnableSsl {
schema += "s"
}
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."
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."
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
func _panel_session_check(w http.ResponseWriter, r *http.Request, user *User) (headerVars HeaderVars, success bool) {
headerVars.Site = site
if !user.Is_Super_Mod {
NoPermissions(w,r,*user)
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) {
headerVars.Site = site
if user.Is_Banned {
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
}
} 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.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
}
} 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.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
}
} 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.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
}
} 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.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
}
} 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.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
}
} 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.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
}
} 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.Tag = groups[user.Group].Tag

View File

@ -49,7 +49,8 @@ func relative_time(in string) (string, error) {
return "", nil
}
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 {
return "", err
}
@ -150,20 +151,20 @@ func SendEmail(email string, subject string, msg string) (res bool) {
}
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 {
return
}
if smtp_username != "" {
auth := smtp.PlainAuth("",smtp_username,smtp_password,smtp_server)
if config.SmtpUsername != "" {
auth := smtp.PlainAuth("",config.SmtpUsername,config.SmtpPassword,config.SmtpServer)
err = con.Auth(auth)
if err != nil {
return
}
}
err = con.Mail(site_email)
err = con.Mail(site.Email)
if err != nil {
return
}

View File

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

View File

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