diff --git a/README.md b/README.md index 88638e59..5b3911b1 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A super fast forum software written in Go. The initial code-base was forked from one of my side projects, but has now gone far beyond that. -Discord Server: https://discord.gg/eyYvtTf +Azareal's Discord Chat: https://discord.gg/eyYvtTf If you like this software, please give it a star and give us some feedback :) diff --git a/build.bat b/build.bat index 16148879..3964dded 100644 --- a/build.bat +++ b/build.bat @@ -1,3 +1,13 @@ +@echo off go build +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) go build ./install +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) +echo Gosora was successfully built pause \ No newline at end of file diff --git a/data.sql b/data.sql index 48757118..59d8fbb0 100644 --- a/data.sql +++ b/data.sql @@ -2,19 +2,25 @@ CREATE TABLE `users`( `uid` int not null AUTO_INCREMENT, `name` varchar(100) not null, `password` varchar(100) not null, - `salt` varchar(80) DEFAULT '' not null, + `salt` varchar(80) default '' not null, `group` int not null, - `active` tinyint DEFAULT 0 not null, + `active` tinyint default 0 not null, `is_super_admin` tinyint(1) not null, `createdAt` datetime not null, `lastActiveAt` datetime not null, - `session` varchar(200) DEFAULT '' not null, - `last_ip` varchar(200) DEFAULT '0.0.0.0.0' not null, - `email` varchar(200) DEFAULT '' not null, - `avatar` varchar(20) DEFAULT '' not null, + `session` varchar(200) default '' not null, + `last_ip` varchar(200) default '0.0.0.0.0' not null, + `email` varchar(200) default '' not null, + `avatar` varchar(20) default '' not null, `message` text not null, - `url_prefix` varchar(20) DEFAULT '' not null, - `url_name` varchar(100) DEFAULT '' not null, + `url_prefix` varchar(20) default '' not null, + `url_name` varchar(100) default '' not null, + `level` tinyint default 0 not null, + `score` int default 0 not null, + `posts` int default 0 not null, + `bigposts` int default 0 not null, + `megaposts` int default 0 not null, + `topics` int default 0 not null, primary key(`uid`), unique(`name`) ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; @@ -91,8 +97,8 @@ CREATE TABLE `users_replies`( ) CHARSET=utf8mb4 COLLATE utf8mb4_general_ci; CREATE TABLE `likes`( - `weight` int DEFAULT 1 not null, - `type` int not null, /* Regular Post = 1, Big Post = 2, Mega Post = 3, etc.*/ + `weight` tinyint DEFAULT 1 not null, + `type` tinyint not null, /* Regular Post = 1, Big Post = 2, Mega Post = 3, etc.*/ `targetItem` int not null, `sentBy` int not null, `recalc` tinyint DEFAULT 0 not null @@ -120,6 +126,8 @@ CREATE TABLE `themes`( INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool'); INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3'); +INSERT INTO settings(`name`,`content`,`type`) VALUES ('bigpost_min_chars','250','int'); +INSERT INTO settings(`name`,`content`,`type`) VALUES ('megapost_min_chars','1000','int'); INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1); INSERT INTO users(`name`,`password`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`) diff --git a/general_test.go b/general_test.go index e4f752ee..239812f3 100644 --- a/general_test.go +++ b/general_test.go @@ -1,6 +1,7 @@ package main import "log" import "bytes" +import "strconv" import "math/rand" import "testing" import "net/http" @@ -12,24 +13,24 @@ import "html/template" func BenchmarkTopicTemplate(b *testing.B) { b.ReportAllocs() - user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""} - admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","",""} + user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} + admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58} var noticeList map[int]string = make(map[int]string) noticeList[0] = "test" - topic := TopicUser{0,"Lol",template.HTML("Hey everyone!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} + topic := TopicUser{Title: "Lol",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58} var replyList []Reply - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) - replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) + replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) tpage := TopicPage{"Topic Blah",user,noticeList,replyList,topic,false} tpage2 := TopicPage{"Topic Blah",admin,noticeList,replyList,topic,false} @@ -60,22 +61,22 @@ func BenchmarkTopicTemplate(b *testing.B) { func BenchmarkTopicsTemplate(b *testing.B) { b.ReportAllocs() - user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""} - admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","",""} + user := User{0,"Bob","bob@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} + admin := User{1,"Admin","admin@localhost",0,true,true,true,true,true,false,AllPerms,"",false,"","","","","",-1,58} var noticeList map[int]string = make(map[int]string) noticeList[0] = "test" var topicList []TopicUser - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) - topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) + topicList = append(topicList, TopicUser{Title: "Hey everyone!",Content: template.HTML("Hey everyone!"),CreatedBy: 1,CreatedAt: "0000-00-00 00:00:00",ParentID: 1,CreatedByName:"Admin",Css: no_css_tmpl,Tag: "Admin", Level: 58}) tpage := TopicsPage{"Topic Blah",user,noticeList,topicList,0} tpage2 := TopicsPage{"Topic Blah",admin,noticeList,topicList,0} @@ -895,6 +896,14 @@ func BenchmarkBBCodePluginWithFullParser(b *testing.B) { }) } +func TestLevels(t *testing.T) { + levels := getLevels(40) + for level, score := range levels { + sscore := strconv.FormatFloat(score, 'f', -1, 64) + log.Print("Level: " + strconv.Itoa(level) + " Score: " + sscore) + } +} + /*func TestRoute(t *testing.T) { }*/ \ No newline at end of file diff --git a/images/level_algorithm.PNG b/images/level_algorithm.PNG new file mode 100644 index 00000000..a992a8bc Binary files /dev/null and b/images/level_algorithm.PNG differ diff --git a/images/levels.PNG b/images/levels.PNG new file mode 100644 index 00000000..c88a4380 Binary files /dev/null and b/images/levels.PNG differ diff --git a/install.bat b/install.bat index e19d2904..ccd38783 100644 --- a/install.bat +++ b/install.bat @@ -1,5 +1,25 @@ +@echo off +echo Installing the dependencies go get -u github.com/go-sql-driver/mysql +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) go get -u golang.org/x/crypto/bcrypt +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) + +echo Preparing the installer go build +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) go build ./install +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) install.exe \ No newline at end of file diff --git a/install/install.go b/install/install.go index 29ee7755..32bd80e8 100644 --- a/install/install.go +++ b/install/install.go @@ -273,6 +273,11 @@ func get_site_details() bool { if server_port == "" { server_port = default_server_port } + _, err := strconv.Atoi(server_port) + if err != nil { + fmt.Println("That's not a valid number!") + return false + } fmt.Println("Set the server port to " + server_port) return true } diff --git a/main.go b/main.go index 106b80e6..dda9cc3d 100644 --- a/main.go +++ b/main.go @@ -41,15 +41,15 @@ var template_profile_handle func(ProfilePage,io.Writer) = nil func compile_templates() { var c CTemplateSet - user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""} + user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","","",0,0} var noticeList map[int]string = make(map[int]string) noticeList[0] = "test" log.Print("Compiling the templates") - topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} + topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","","",58} var replyList []Reply - replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""}) + replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","","",0}) var varList map[string]VarItem = make(map[string]VarItem) tpage := TopicPage{"Title",user,noticeList,replyList,topic,false} @@ -71,7 +71,7 @@ func compile_templates() { forums_tmpl := c.compile_template("forums.html","templates/","ForumsPage", forums_page, varList) var topicList []TopicUser - topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","",""}) + topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","","",58}) topics_page := TopicsPage{"Topic List",user,noticeList,topicList,""} topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage", topics_page, varList) diff --git a/mod_routes.go b/mod_routes.go index 1d114945..740acf00 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -38,11 +38,7 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) { topic_name := r.PostFormValue("topic_name") topic_status := r.PostFormValue("topic_status") - - var is_closed bool - if topic_status == "closed" { - is_closed = true - } + is_closed := (topic_status == "closed") topic_content := html.EscapeString(r.PostFormValue("topic_content")) _, err = edit_topic_stmt.Exec(topic_name, preparse_message(topic_content), parse_message(html.EscapeString(preparse_message(topic_content))), is_closed, tid) @@ -74,7 +70,9 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { return } - err = db.QueryRow("SELECT tid from topics where tid = ?", tid).Scan(&tid) + var content string + var createdBy int + err = db.QueryRow("select tid, content, createdBy from topics where tid = ?", tid).Scan(&tid, &content, &createdBy) if err == sql.ErrNoRows { LocalError("The topic you tried to delete doesn't exist.",w,r,user) return @@ -88,9 +86,15 @@ func route_delete_topic(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r,user) return } - log.Print("The topic '" + strconv.Itoa(tid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") - http.Redirect(w, r, "/", http.StatusSeeOther) + http.Redirect(w,r,"/",http.StatusSeeOther) + + wcount := word_count(content) + err = decrease_post_user_stats(wcount, createdBy, true, user) + if err != nil { + InternalError(err,w,r,user) + return + } } func route_stick_topic(w http.ResponseWriter, r *http.Request) { @@ -152,7 +156,6 @@ func route_reply_edit_submit(w http.ResponseWriter, r *http.Request) { LocalError("Bad Form", w, r, user) return } - is_js := r.PostFormValue("js") if is_js == "" { is_js = "0" @@ -218,7 +221,9 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { } var tid int - err = db.QueryRow("SELECT tid from replies where rid = ?", rid).Scan(&tid) + var content string + var createdBy int + err = db.QueryRow("SELECT tid, content, createdBy from replies where rid = ?", rid).Scan(&tid, &content, &createdBy) if err == sql.ErrNoRows { LocalErrorJSQ("The reply you tried to delete doesn't exist.",w,r,user,is_js) return @@ -233,12 +238,18 @@ func route_reply_delete_submit(w http.ResponseWriter, r *http.Request) { return } log.Print("The reply '" + strconv.Itoa(rid) + "' was deleted by User ID #" + strconv.Itoa(user.ID) + ".") - if is_js == "0" { //http.Redirect(w,r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) } else { fmt.Fprintf(w,"{'success': '1'}") } + + wcount := word_count(content) + err = decrease_post_user_stats(wcount, createdBy, false, user) + if err != nil { + InternalError(err,w,r,user) + return + } } func route_profile_reply_edit_submit(w http.ResponseWriter, r *http.Request) { diff --git a/mysql.go b/mysql.go index e9337b69..58913bc0 100644 --- a/mysql.go +++ b/mysql.go @@ -34,6 +34,12 @@ var register_stmt *sql.Stmt var username_exists_stmt *sql.Stmt var change_group_stmt *sql.Stmt var activate_user_stmt *sql.Stmt +var update_user_level_stmt *sql.Stmt +var increment_user_score_stmt *sql.Stmt +var increment_user_posts_stmt *sql.Stmt +var increment_user_bigposts_stmt *sql.Stmt +var increment_user_megaposts_stmt *sql.Stmt +var increment_user_topics_stmt *sql.Stmt var create_profile_reply_stmt *sql.Stmt var edit_profile_reply_stmt *sql.Stmt var delete_profile_reply_stmt *sql.Stmt @@ -64,7 +70,7 @@ func init_database(err error) { } log.Print("Preparing get_session statement.") - get_session_stmt, err = db.Prepare("select `uid`, `name`, `group`, `is_super_admin`, `session`, `email`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ? AND `session` = ? AND `session` <> ''") + get_session_stmt, err = db.Prepare("select `uid`, `name`, `group`, `is_super_admin`, `session`, `email`, `avatar`, `message`, `url_prefix`, `url_name`, `level`, `score` FROM `users` where `uid` = ? AND `session` = ? AND `session` <> ''") if err != nil { log.Fatal(err) } @@ -222,6 +228,42 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing update_user_level statement.") + update_user_level_stmt, err = db.Prepare("UPDATE users SET level = ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing increment_user_score statement.") + increment_user_score_stmt, err = db.Prepare("UPDATE users SET score = score + ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing increment_user_posts statement.") + increment_user_posts_stmt, err = db.Prepare("UPDATE users SET posts = posts + ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing increment_user_bigposts statement.") + increment_user_bigposts_stmt, err = db.Prepare("UPDATE users SET posts = posts + ?, bigposts = bigposts + ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing increment_user_megaposts statement.") + increment_user_megaposts_stmt, err = db.Prepare("UPDATE users SET posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + + log.Print("Preparing increment_user_topics statement.") + increment_user_topics_stmt, err = db.Prepare("UPDATE users SET topics = topics + ? WHERE uid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing create_profile_reply statement.") create_profile_reply_stmt, err = db.Prepare("INSERT INTO users_replies(uid,content,parsed_content,createdAt,createdBy) VALUES(?,?,?,NOW(),?)") if err != nil { diff --git a/reply.go b/reply.go index f7c5c806..47c9bfa3 100644 --- a/reply.go +++ b/reply.go @@ -20,4 +20,5 @@ type Reply struct URL string URLPrefix string URLName string + Level int } diff --git a/routes.go b/routes.go index ff1dd8a3..e5b167ac 100644 --- a/routes.go +++ b/routes.go @@ -236,7 +236,6 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ if !ok { return } - var( err error rid int @@ -254,13 +253,14 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ replyURL string replyURLPrefix string replyURLName string + replyLevel int is_super_admin bool group int replyList []Reply ) - topic := TopicUser{0,"","",0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""} + topic := TopicUser{Css: no_css_tmpl} topic.ID, err = strconv.Atoi(r.URL.Path[len("/topic/"):]) if err != nil { LocalError("The provided TopicID is not a valid number.",w,r,user) @@ -274,7 +274,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } // Get the topic.. - err = db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name from topics left join users ON topics.createdBy = users.uid where tid = ?", topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName) + err = db.QueryRow("select topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, users.name, users.avatar, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level from topics left join users ON topics.createdBy = users.uid where tid = ?", topic.ID).Scan(&topic.Title, &content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.CreatedByName, &topic.Avatar, &is_super_admin, &group, &topic.URLPrefix, &topic.URLName, &topic.Level) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -300,12 +300,13 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } if is_super_admin || groups[group].Is_Mod || groups[group].Is_Admin { topic.Css = staff_css_tmpl + topic.Level = -1 } - if groups[group].Tag != "" { + //if groups[group].Tag != "" { topic.Tag = groups[group].Tag - } else { - topic.Tag = "" - } + //} else { + // topic.Tag = "" + //} if settings["url_tags"] == false { topic.URLName = "" } else { @@ -318,7 +319,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } // Get the replies.. - rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID) + rows, err := db.Query("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.is_super_admin, users.group, users.url_prefix, users.url_name, users.level from replies left join users ON replies.createdBy = users.uid where tid = ?", topic.ID) if err != nil { InternalError(err,w,r,user) return @@ -326,7 +327,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ defer rows.Close() for rows.Next() { - err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group, &replyURLPrefix, &replyURLName) + err := rows.Scan(&rid, &replyContent, &replyCreatedBy, &replyCreatedAt, &replyLastEdit, &replyLastEditBy, &replyAvatar, &replyCreatedByName, &is_super_admin, &group, &replyURLPrefix, &replyURLName, &replyLevel) if err != nil { InternalError(err,w,r,user) return @@ -335,6 +336,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ replyLines = strings.Count(replyContent,"\n") if is_super_admin || groups[group].Is_Mod || groups[group].Is_Admin { replyCss = staff_css_tmpl + replyLevel = -1 } else { replyCss = no_css_tmpl } @@ -345,11 +347,11 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } else { replyAvatar = strings.Replace(noavatar,"{id}",strconv.Itoa(replyCreatedBy),1) } - if groups[group].Tag != "" { + //if groups[group].Tag != "" { replyTag = groups[group].Tag - } else { - replyTag = "" - } + //} else { + // replyTag = "" + //} if settings["url_tags"] == false { replyURLName = "" } else { @@ -361,7 +363,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){ } } - replyItem := Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName} + replyItem := Reply{rid,topic.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,replyURL,replyURLPrefix,replyURLName,replyLevel} if hooks["rrow_assign"] != nil { replyItem = run_hook("rrow_assign", replyItem).(Reply) @@ -422,7 +424,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ puser = user } else { // Fetch the user data - err = db.QueryRow("SELECT `name`, `group`, `is_super_admin`, `avatar`, `message`, `url_prefix`, `url_name` FROM `users` WHERE `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar, &puser.Message, &puser.URLPrefix, &puser.URLName) + err = db.QueryRow("SELECT `name`, `group`, `is_super_admin`, `avatar`, `message`, `url_prefix`, `url_name`, `level` FROM `users` WHERE `uid` = ?", puser.ID).Scan(&puser.Name, &puser.Group, &puser.Is_Super_Admin, &puser.Avatar, &puser.Message, &puser.URLPrefix, &puser.URLName, &puser.Level) if err == sql.ErrNoRows { NotFound(w,r,user) return @@ -440,11 +442,11 @@ func route_profile(w http.ResponseWriter, r *http.Request){ } } - if groups[puser.Group].Tag != "" { + //if groups[puser.Group].Tag != "" { puser.Tag = groups[puser.Group].Tag - } else { - puser.Tag = "" - } + //} else { + // puser.Tag = "" + //} if puser.Avatar != "" { if puser.Avatar[0] == '.' { @@ -490,7 +492,7 @@ func route_profile(w http.ResponseWriter, r *http.Request){ replyTag = "" } - replyList = append(replyList, Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","",""}) + replyList = append(replyList, Reply{rid,puser.ID,replyContent,template.HTML(parse_message(replyContent)),replyCreatedBy,replyCreatedByName,replyCreatedAt,replyLastEdit,replyLastEditBy,replyAvatar,replyCss,replyLines,replyTag,"","","",0}) } err = rows.Err() if err != nil { @@ -518,7 +520,6 @@ func route_topic_create(w http.ResponseWriter, r *http.Request){ NoPermissions(w,r,user) return } - pi := Page{"Create Topic","create-topic",user,noticeList,tList,0} templates.ExecuteTemplate(w,"create-topic.html", pi) } @@ -539,38 +540,32 @@ func route_create_topic(w http.ResponseWriter, r *http.Request) { LocalError("Bad Form", w, r, user) return } - success := 1 topic_name := html.EscapeString(r.PostFormValue("topic-name")) + content := html.EscapeString(preparse_message(r.PostFormValue("topic-content"))) - res, err := create_topic_stmt.Exec(topic_name,html.EscapeString(preparse_message(r.PostFormValue("topic-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("topic-content")))),user.ID) + res, err := create_topic_stmt.Exec(topic_name,content,parse_message(content),user.ID) if err != nil { - log.Print(err) - success = 0 + InternalError(err,w,r,user) + return } lastId, err := res.LastInsertId() if err != nil { - log.Print(err) - success = 0 + InternalError(err,w,r,user) + return } - _, err = update_forum_cache_stmt.Exec(topic_name, lastId, user.Name, user.ID, 1) if err != nil { InternalError(err,w,r,user) return } - if success != 1 { - errmsg := "Unable to create the topic" - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) - } else { - http.Redirect(w, r, "/topic/" + strconv.FormatInt(lastId, 10), http.StatusSeeOther) + http.Redirect(w, r, "/topic/" + strconv.FormatInt(lastId,10), http.StatusSeeOther) + wcount := word_count(content) + err = increase_post_user_stats(wcount, user.ID, true, user) + if err != nil { + InternalError(err,w,r,user) + return } } @@ -589,7 +584,6 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { LocalError("Bad Form", w, r, user) return } - tid, err := strconv.Atoi(r.PostFormValue("tid")) if err != nil { LocalError("Failed to convert the TopicID", w, r, user) @@ -597,7 +591,7 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } content := preparse_message(html.EscapeString(r.PostFormValue("reply-content"))) - log.Print(content) + //log.Print(content) _, err = create_reply_stmt.Exec(tid,content,parse_message(content),user.ID) if err != nil { InternalError(err,w,r,user) @@ -621,6 +615,12 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { } http.Redirect(w, r, "/topic/" + strconv.Itoa(tid), http.StatusSeeOther) + wcount := word_count(content) + err = increase_post_user_stats(wcount, user.ID, false, user) + if err != nil { + InternalError(err,w,r,user) + return + } } func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { @@ -638,52 +638,29 @@ func route_profile_reply_create(w http.ResponseWriter, r *http.Request) { LocalError("Bad Form", w, r, user) return } - - success := 1 uid, err := strconv.Atoi(r.PostFormValue("uid")) if err != nil { - log.Print(err) - success = 0 - - errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("Invalid UID",w,r,user) return } _, err = create_profile_reply_stmt.Exec(uid,html.EscapeString(preparse_message(r.PostFormValue("reply-content"))),parse_message(html.EscapeString(preparse_message(r.PostFormValue("reply-content")))),user.ID) if err != nil { - log.Print(err) - success = 0 + InternalError(err,w,r,user) + return } var user_name string err = db.QueryRow("select name from users where uid = ?", uid).Scan(&user_name) if err == sql.ErrNoRows { - log.Print(err) - success = 0 + LocalError("The profile you're trying to post on doesn't exist.",w,r,user) + return } else if err != nil { InternalError(err,w,r,user) return } - if success != 1 { - errmsg := "Unable to create the reply" - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) - } else { - http.Redirect(w, r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) - } + http.Redirect(w, r, "/user/" + strconv.Itoa(uid), http.StatusSeeOther) } func route_report_submit(w http.ResponseWriter, r *http.Request) { @@ -691,7 +668,6 @@ func route_report_submit(w http.ResponseWriter, r *http.Request) { if !ok { return } - if !user.Loggedin { LoginRequired(w,r,user) return @@ -872,13 +848,7 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque err = get_password_stmt.QueryRow(user.ID).Scan(&real_password, &salt) if err == sql.ErrNoRows { - pi := Page{"Error","error",user,nList,tList,"Your account doesn't exist."} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("Your account no longer exists.",w,r,user) return } else if err != nil { InternalError(err,w,r,user) @@ -888,26 +858,14 @@ func route_account_own_edit_critical_submit(w http.ResponseWriter, r *http.Reque current_password = current_password + salt err = bcrypt.CompareHashAndPassword([]byte(real_password), []byte(current_password)) if err == bcrypt.ErrMismatchedHashAndPassword { - pi := Page{"Error","error",user,nList,tList,"That's not the correct password."} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("That's not the correct password.",w,r,user) return } else if err != nil { InternalError(err,w,r,user) return } if new_password != confirm_password { - pi := Page{"Error","error",user,nList,tList,"The two passwords don't match."} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("The two passwords don't match.",w,r,user) return } SetPassword(user.ID, new_password) @@ -1192,16 +1150,8 @@ func route_logout(w http.ResponseWriter, r *http.Request) { if !ok { return } - if !user.Loggedin { - errmsg := "You can't logout without logging in first." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("You can't logout without logging in first.",w,r,user) return } @@ -1218,19 +1168,10 @@ func route_login(w http.ResponseWriter, r *http.Request) { if !ok { return } - if user.Loggedin { - errmsg := "You're already logged in." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("You're already logged in.",w,r,user) return } - pi := Page{"Login","login",user,noticeList,tList,0} templates.ExecuteTemplate(w,"login.html", pi) } @@ -1240,16 +1181,8 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { if !ok { return } - if user.Loggedin { - errmsg := "You're already logged in." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("You're already logged in.",w,r,user) return } @@ -1268,14 +1201,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { err = login_stmt.QueryRow(username).Scan(&uid, &username, &real_password, &salt) if err == sql.ErrNoRows { - errmsg := "That username doesn't exist." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("That username doesn't exist.",w,r,user) return } else if err != nil { InternalError(err,w,r,user) @@ -1285,14 +1211,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { // Emergency password reset mechanism.. if salt == "" { if password != real_password { - errmsg := "That's not the correct password." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("That's not the correct password.",w,r,user) return } @@ -1307,14 +1226,7 @@ func route_login_submit(w http.ResponseWriter, r *http.Request) { err := bcrypt.CompareHashAndPassword([]byte(real_password), []byte(password)) if err == bcrypt.ErrMismatchedHashAndPassword { - errmsg := "That's not the correct password." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("That's not the correct password.",w,r,user) return } else if err != nil { InternalError(err,w,r,user) @@ -1347,17 +1259,9 @@ func route_register(w http.ResponseWriter, r *http.Request) { return } if user.Loggedin { - errmsg := "You're already logged in." - pi := Page{"Error","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("You're already logged in.",w,r,user) return } - pi := Page{"Registration","register",user,noticeList,tList,0} templates.ExecuteTemplate(w,"register.html", pi) } @@ -1367,7 +1271,6 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { if !ok { return } - err := r.ParseForm() if err != nil { LocalError("Bad Form", w, r, user) @@ -1400,14 +1303,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { // Do the two inputted passwords match..? if password != confirm_password { - errmsg := "The two passwords don't match." - pi := Page{"Password Mismatch","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("The two passwords don't match.",w,r,user) return } @@ -1417,14 +1313,7 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r,user) return } else if err != sql.ErrNoRows { - errmsg := "This username isn't available. Try another." - pi := Page{"Username Taken","error",user,nList,tList,errmsg} - - var b bytes.Buffer - templates.ExecuteTemplate(&b,"error.html", pi) - errpage := b.String() - w.WriteHeader(500) - fmt.Fprintln(w,errpage) + LocalError("This username isn't available. Try another.",w,r,user) return } @@ -1433,7 +1322,6 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { InternalError(err,w,r,user) return } - session, err := GenerateSafeString(sessionLength) if err != nil { InternalError(err,w,r,user) diff --git a/run.bat b/run.bat index d939fc2a..359bc72d 100644 --- a/run.bat +++ b/run.bat @@ -1,3 +1,8 @@ +@echo off go build +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) gosora.exe pause \ No newline at end of file diff --git a/template_profile.go b/template_profile.go index 5c02a28d..c32f708a 100644 --- a/template_profile.go +++ b/template_profile.go @@ -1,7 +1,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 "io" import "strconv" +import "io" func init() { template_profile_handle = template_profile diff --git a/template_topic.go b/template_topic.go index 3d5c520a..3c0fde3e 100644 --- a/template_topic.go +++ b/template_topic.go @@ -120,10 +120,14 @@ w.Write([]byte(`0px;background-repeat: no-repeat, repeat-y;background-size: 128p } w.Write([]byte(`">

` + string(tmpl_topic_vars.Topic.Content.(template.HTML)) + `

- -

+

` + tmpl_topic_vars.Topic.CreatedByName + ` `)) +if tmpl_topic_vars.Topic.Level != -1 { +w.Write([]byte(`L` + strconv.Itoa(tmpl_topic_vars.Topic.Level) + ``)) +} +w.Write([]byte(` + `)) if tmpl_topic_vars.Topic.Tag != "" { w.Write([]byte(`` + tmpl_topic_vars.Topic.Tag + ``)) } else { @@ -151,6 +155,11 @@ w.Write([]byte(`">

` + string(item.ContentHtml) + `



` + item.CreatedByName + ` `)) +if item.Level != -1 { +w.Write([]byte(`L` + strconv.Itoa(item.Level) + ``)) +} +w.Write([]byte(` + `)) if tmpl_topic_vars.CurrentUser.Perms.EditReply { w.Write([]byte(``)) } diff --git a/templates.go b/templates.go index 05419862..7903e8d2 100644 --- a/templates.go +++ b/templates.go @@ -304,7 +304,6 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V } else { varbit += "." + id } - if debug { fmt.Println("End Cycle") } @@ -331,9 +330,8 @@ func (c *CTemplateSet) compile_subswitch(varholder string, holdreflect reflect.V fmt.Println(n.String()) fmt.Println(n.Ident) } - - out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) - return "w.Write([]byte(" + out + "))\n" + varname, reflectVal := c.compile_if_varsub(n.String(), varholder, template_name, holdreflect) + return c.compile_varsub(varname, reflectVal) case *parse.StringNode: return n.Quoted default: @@ -429,6 +427,21 @@ func (c *CTemplateSet) compile_identswitch(varholder string, holdreflect reflect 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) 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) + 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) + 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) + 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) + 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) + break ArgLoop default: if debug { fmt.Println("Variable!") diff --git a/templates/topic.html b/templates/topic.html index 34df7b55..87cc0b41 100644 --- a/templates/topic.html +++ b/templates/topic.html @@ -23,9 +23,9 @@

{{.Topic.Content}}

- -

+

{{.Topic.CreatedByName}} + {{if ne .Topic.Level -1}}L{{.Topic.Level}}{{end}} {{if .Topic.Tag}}{{.Topic.Tag}}{{else if .Topic.URLName}}{{.Topic.URLName}} {{.Topic.URLPrefix}}{{end}}
@@ -34,6 +34,7 @@

{{.ContentHtml}}



{{.CreatedByName}} + {{if ne .Level -1}}L{{.Level}}{{end}} {{if $.CurrentUser.Perms.EditReply}}{{end}} {{if $.CurrentUser.Perms.DeleteReply}}{{end}} diff --git a/topic.go b/topic.go index 0c29dfb8..01ecf53d 100644 --- a/topic.go +++ b/topic.go @@ -34,4 +34,5 @@ type TopicUser struct URL string URLPrefix string URLName string + Level int } diff --git a/update-deps.bat b/update-deps.bat index 2c536081..2bc8b55a 100644 --- a/update-deps.bat +++ b/update-deps.bat @@ -1,3 +1,13 @@ +@echo off go get -u github.com/go-sql-driver/mysql +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) go get -u golang.org/x/crypto/bcrypt +if %errorlevel% neq 0 ( + pause + exit /b %errorlevel% +) +echo The dependencies were successfully updated pause \ No newline at end of file diff --git a/user.go b/user.go index aabf4c98..1f36ad5d 100644 --- a/user.go +++ b/user.go @@ -1,4 +1,5 @@ package main +import "fmt" import "strings" import "strconv" import "net/http" @@ -26,6 +27,8 @@ type User struct URLPrefix string URLName string Tag string + Level int + Score int } type Email struct @@ -92,7 +95,7 @@ func SessionCheck(w http.ResponseWriter, r *http.Request) (user User, noticeList user.Session = cookie.Value // Is this session valid..? - err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName) + err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score) if err == sql.ErrNoRows { user.ID = 0 user.Session = "" @@ -154,7 +157,7 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ user.Session = cookie.Value // Is this session valid..? - err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName) + err = get_session_stmt.QueryRow(user.ID,user.Session).Scan(&user.ID, &user.Name, &user.Group, &user.Is_Super_Admin, &user.Session, &user.Email, &user.Avatar, &user.Message, &user.URLPrefix, &user.URLName, &user.Level, &user.Score) if err == sql.ErrNoRows { user.ID = 0 user.Session = "" @@ -188,4 +191,80 @@ func SimpleSessionCheck(w http.ResponseWriter, r *http.Request) (user User, succ user.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(user.ID),1) } return user, true -} \ No newline at end of file +} + +func increase_post_user_stats(wcount int, uid int, topic bool, user User) error { + var mod int + base_score := 1 + if topic { + _, err := increment_user_topics_stmt.Exec(1, uid) + if err != nil { + return err + } + base_score = 2 + } + + if wcount > settings["megapost_min_chars"].(int) { + _, err := increment_user_megaposts_stmt.Exec(1,1,1,uid) + if err != nil { + return err + } + mod = 4 + } else if wcount > settings["bigpost_min_chars"].(int) { + _, err := increment_user_bigposts_stmt.Exec(1,1,uid) + if err != nil { + return err + } + mod = 1 + } else { + _, err := increment_user_posts_stmt.Exec(1,uid) + if err != nil { + return err + } + } + _, err := increment_user_score_stmt.Exec(base_score + mod, uid) + if err != nil { + return err + } + fmt.Println(user.Score + base_score + mod) + fmt.Println(getLevel(user.Score + base_score + mod)) + _, err = update_user_level_stmt.Exec(getLevel(user.Score + base_score + mod), uid) + return err +} + +func decrease_post_user_stats(wcount int, uid int, topic bool, user User) error { + var mod int + base_score := -1 + if topic { + _, err := increment_user_topics_stmt.Exec(-1, uid) + if err != nil { + return err + } + base_score = -2 + } + + if wcount > settings["megapost_min_chars"].(int) { + _, err := increment_user_megaposts_stmt.Exec(-1,-1,-1,uid) + if err != nil { + return err + } + mod = 4 + } else if wcount > settings["bigpost_min_chars"].(int) { + _, err := increment_user_bigposts_stmt.Exec(-1,-1,uid) + if err != nil { + return err + } + mod = 1 + } else { + _, err := increment_user_posts_stmt.Exec(-1,uid) + if err != nil { + return err + } + } + _, err := increment_user_score_stmt.Exec(base_score - mod, uid) + if err != nil { + return err + } + _, err = update_user_level_stmt.Exec(getLevel(user.Score - base_score - mod), uid) + return err +} diff --git a/utils.go b/utils.go index 9b3e8a12..71faa5bb 100644 --- a/utils.go +++ b/utils.go @@ -3,6 +3,9 @@ import "log" import "fmt" import "time" import "os" +import "math" +import "strings" +import "unicode" import "encoding/base64" import "crypto/rand" import "net/smtp" @@ -103,3 +106,84 @@ func write_file(name string, content string) { f.Sync() f.Close() } + +func word_count(input string) int { + input = strings.TrimSpace(input) + count := 0 + in_space := false + for _, value := range input { + if unicode.IsSpace(value) { + if !in_space { + in_space = true + } + } else if in_space { + count++ + in_space = false + } + } + return count +} + +func getLevel(score int) (level int) { + var base float64 = 25 + var current float64 + var prev float64 + exp_factor := 2.8 + + for i := 1;;i++ { + _, bit := math.Modf(float64(i) / 10) + if bit == 0 { + exp_factor += 0.1 + } + current = base + math.Pow(float64(i), exp_factor) + (prev / 3) + prev = current + if float64(score) < current { + break + } else { + level++ + } + } + return level +} + +func getLevelScore(getLevel int) (score int) { + var base float64 = 25 + var current float64 + var prev float64 + var level int + exp_factor := 2.8 + + for i := 1;;i++ { + _, bit := math.Modf(float64(i) / 10) + if bit == 0 { + exp_factor += 0.1 + } + current = base + math.Pow(float64(i), exp_factor) + (prev / 3) + prev = current + level++ + if level <= getLevel { + break + } + } + return int(math.Ceil(current)) +} + +func getLevels(maxLevel int) []float64 { + var base float64 = 25 + var current float64 = 0 + var prev float64 = 0 + exp_factor := 2.8 + var out []float64 + out = append(out, 0) + + for i := 1;i <= maxLevel;i++ { + _, bit := math.Modf(float64(i) / 10) + if bit == 0 { + exp_factor += 0.1 + } + current = base + math.Pow(float64(i), exp_factor) + (prev / 3) + prev = current + out = append(out, current) + } + return out +}