diff --git a/data.sql b/data.sql index 08fdbc44..0c9854a9 100644 --- a/data.sql +++ b/data.sql @@ -112,13 +112,35 @@ CREATE TABLE `users_replies`( CREATE TABLE `likes`( `weight` tinyint DEFAULT 1 not null, - /*`type` tinyint not null, /* Regular Post = 1, Big Post = 2, Mega Post = 3, etc.*/ + /*`type` tinyint not null, /* Regular Post: 1, Big Post: 2, Mega Post: 3, etc.*/ `targetItem` int not null, `targetType` varchar(50) DEFAULT 'replies' not null, `sentBy` int not null, `recalc` tinyint DEFAULT 0 not null ); +CREATE TABLE `activity_stream_matches`( + `watcher` int not null, + `asid` int not null +); + +CREATE TABLE `activity_stream`( + `asid` int not null AUTO_INCREMENT, + `actor` int not null, /* the one doing the act */ + `targetUser` int not null, /* the user who created the item the actor is acting on, some items like forums may lack a targetUser field */ + `event` varchar(50) not null, /* mention, like, reply (as in the act of replying to an item, not the reply item type, you can "reply" to a forum by making a topic in it), friend_invite */ + `elementType` varchar(50) not null, /* topic, post (calling it post here to differentiate it from the 'reply' event), forum, user */ + `elementID` int not null, /* the ID of the element being acted upon */ + primary key(`asid`) +); + +CREATE TABLE `activity_subscriptions`( + `user` int not null, + `targetID` int not null, + `targetType` varchar(50) not null, + `level` tinyint DEFAULT 0 not null /* 0: Mentions (aka the global default for any post), 1: Replies, 2: Everyone*/ +); + CREATE TABLE `settings`( `name` varchar(200) not null, `content` varchar(250) not null, diff --git a/errors.go b/errors.go index 5748b37e..3b3c79e6 100644 --- a/errors.go +++ b/errors.go @@ -41,6 +41,12 @@ func InternalErrorJSQ(err error, w http.ResponseWriter, r *http.Request, is_js s log.Fatal(err) } +func InternalErrorJS(err error, w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + w.Write([]byte(`{'errmsg': 'A problem has occured in the system.'}`)) + log.Fatal(err) +} + func PreError(errmsg string, w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) user := User{ID:0,Group:6,Perms:GuestPerms,} @@ -91,6 +97,11 @@ func LocalErrorJSQ(errmsg string, w http.ResponseWriter, r *http.Request, user U } } +func LocalErrorJS(errmsg string, w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + w.Write([]byte(`{'errmsg': '` + errmsg + `'}`)) +} + func NoPermissions(w http.ResponseWriter, r *http.Request, user User) { w.WriteHeader(403) pi := Page{"Local Error",user,nList,tList,"You don't have permission to do that."} diff --git a/general_test.go b/general_test.go index 40f8f04c..b2900fd3 100644 --- a/general_test.go +++ b/general_test.go @@ -10,12 +10,17 @@ import "net/http" import "net/http/httptest" import "io/ioutil" import "database/sql" -import _ "github.com/go-sql-driver/mysql" +//import _ "github.com/go-sql-driver/mysql" +//import "github.com/erikstmartin/go-testdb" //import "github.com/husobee/vestigo" import "runtime/pprof" +var db_test *sql.DB +var db_prod *sql.DB var gloinited bool = false + func gloinit() { + var err error debug = false nogrouplog = true @@ -24,10 +29,15 @@ func gloinit() { //log.SetOutput(discard) init_themes() - var err error init_database(err) + db_prod = db + //db_test, err = sql.Open("testdb","") + //if err != nil { + // log.Fatal(err) + //} + init_templates() - db.SetMaxOpenConns(64) + db_prod.SetMaxOpenConns(64) err = init_errors() if err != nil { log.Fatal(err) @@ -1368,6 +1378,35 @@ func TestForumGuestRoute(t *testing.T) { fmt.Println("No problems found in the forum-guest route!") } +/*func TestAlerts(t *testing.T) { + if !gloinited { + gloinit() + } + if !plugins_inited { + init_plugins() + } + db = db_test + alert_w := httptest.NewRecorder() + alert_req := httptest.NewRequest("get","/api/?action=get&module=alerts",bytes.NewReader(nil)) + alert_handler := http.HandlerFunc(route_api) + //testdb.StubQuery() + testdb.SetQueryFunc(func(query string) (result sql.Rows, err error) { + cols := []string{"asid","actor","targetUser","event","elementType","elementID"} + rows := `1,1,0,like,post,5 + 1,1,0,friend_invite,user,2` + return testdb.RowsFromCSVString(cols,rows), nil + }) + + alert_handler.ServeHTTP(alert_w,alert_req) + fmt.Println(alert_w.Body) + if alert_w.Code != 200 { + panic("HTTP Error!") + } + + fmt.Println("No problems found in the alert handler!") + db = db_prod +}*/ + /*func TestRoute(t *testing.T) { }*/ \ No newline at end of file diff --git a/main.go b/main.go index 871edc17..8bfb6cae 100644 --- a/main.go +++ b/main.go @@ -184,8 +184,7 @@ func main(){ init_plugins() router := NewRouter() - router.HandleFunc("/static/", route_static) // In a directory to stop it clashing with the other paths - + router.HandleFunc("/static/", route_static) fs_u := http.FileServer(http.Dir("./uploads")) router.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u)) @@ -260,6 +259,7 @@ func main(){ router.HandleFunc("/panel/users/edit/", route_panel_users_edit) router.HandleFunc("/panel/users/edit/submit/", route_panel_users_edit_submit) router.HandleFunc("/panel/groups/", route_panel_groups) + router.HandleFunc("/api/", route_api) //router.HandleFunc("/exit/", route_exit) router.HandleFunc("/", default_route) diff --git a/mod_routes.go b/mod_routes.go index 80a5db70..b1a74d99 100644 --- a/mod_routes.go +++ b/mod_routes.go @@ -1412,6 +1412,9 @@ func route_panel_themes(w http.ResponseWriter, r *http.Request){ var themeList []interface{} for _, theme := range themes { + if theme.HideFromThemes { + continue + } themeList = append(themeList,theme) } diff --git a/mysql.go b/mysql.go index a0ab9e60..922a8ef8 100644 --- a/mysql.go +++ b/mysql.go @@ -16,8 +16,10 @@ var get_full_user_stmt *sql.Stmt var get_topic_list_stmt *sql.Stmt var get_topic_user_stmt *sql.Stmt var get_topic_stmt *sql.Stmt +var get_topic_by_reply_stmt *sql.Stmt var get_topic_replies_stmt *sql.Stmt var get_topic_replies_offset_stmt *sql.Stmt +var get_post_stmt *sql.Stmt var get_forum_topics_stmt *sql.Stmt var get_forum_topics_offset_stmt *sql.Stmt var create_topic_stmt *sql.Stmt @@ -37,6 +39,7 @@ var delete_reply_stmt *sql.Stmt var delete_topic_stmt *sql.Stmt var stick_topic_stmt *sql.Stmt var unstick_topic_stmt *sql.Stmt +var get_activity_feed_by_watcher_stmt *sql.Stmt var update_last_ip_stmt *sql.Stmt var login_stmt *sql.Stmt var update_session_stmt *sql.Stmt @@ -133,6 +136,12 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing get_topic_by_reply statement.") + get_topic_by_reply_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount from replies left join topics on replies.tid = topics.tid where rid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing get_topic_replies statement.") get_topic_replies_stmt, err = db.Prepare("select replies.rid, replies.content, replies.createdBy, replies.createdAt, replies.lastEdit, replies.lastEditBy, users.avatar, users.name, users.group, users.url_prefix, users.url_name, users.level, replies.ipaddress from replies left join users ON replies.createdBy = users.uid where tid = ?") if err != nil { @@ -145,6 +154,12 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing get_post statement.") + get_post_stmt, err = db.Prepare("select content, createdBy, createdAt, lastEdit, lastEditBy, ipaddress, likeCount from replies where rid = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing get_forum_topics statement.") get_forum_topics_stmt, err = db.Prepare("select topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar from topics left join users ON topics.createdBy = users.uid where topics.parentID = ? order by topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc") if err != nil { @@ -259,6 +274,12 @@ func init_database(err error) { log.Fatal(err) } + log.Print("Preparing get_activity_feed_by_watcher statement.") + get_activity_feed_by_watcher_stmt, err = db.Prepare("SELECT activity_stream_matches.asid, activity_stream.actor, activity_stream.targetUser, activity_stream.event, activity_stream.elementType, activity_stream.elementID FROM `activity_stream_matches` LEFT JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid WHERE `watcher` = ?") + if err != nil { + log.Fatal(err) + } + log.Print("Preparing update_last_ip statement.") update_last_ip_stmt, err = db.Prepare("UPDATE users SET last_ip = ? WHERE uid = ?") if err != nil { @@ -266,7 +287,7 @@ func init_database(err error) { } log.Print("Preparing login statement.") - login_stmt, err = db.Prepare("SELECT `uid`, `name`, `password`, `salt` FROM `users` WHERE `name` = ?") + login_stmt, err = db.Prepare("SELECT `uid`,`name`,`password`,`salt` FROM `users` WHERE `name` = ?") if err != nil { log.Fatal(err) } @@ -290,7 +311,7 @@ func init_database(err error) { } log.Print("Preparing get_password statement.") - get_password_stmt, err = db.Prepare("SELECT `password`, `salt` FROM `users` WHERE `uid` = ?") + get_password_stmt, err = db.Prepare("SELECT `password`,`salt` FROM `users` WHERE `uid` = ?") if err != nil { log.Fatal(err) } @@ -444,19 +465,19 @@ func init_database(err error) { } log.Print("Preparing add_forum_perms_to_forum_admins statement.") - add_forum_perms_to_forum_admins_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset, ? AS permissions FROM users_groups WHERE is_admin = 1") + add_forum_perms_to_forum_admins_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset,? AS permissions FROM users_groups WHERE is_admin = 1") if err != nil { log.Fatal(err) } log.Print("Preparing add_forum_perms_to_forum_staff statement.") - add_forum_perms_to_forum_staff_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset, ? AS permissions FROM users_groups WHERE is_admin = 0 AND is_mod = 1") + add_forum_perms_to_forum_staff_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset,? AS permissions FROM users_groups WHERE is_admin = 0 AND is_mod = 1") if err != nil { log.Fatal(err) } log.Print("Preparing add_forum_perms_to_forum_members statement.") - add_forum_perms_to_forum_members_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset, ? AS permissions FROM users_groups WHERE is_admin = 0 AND is_mod = 0 AND is_banned = 0") + add_forum_perms_to_forum_members_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) SELECT `gid`,? AS fid,? AS preset,? AS permissions FROM users_groups WHERE is_admin = 0 AND is_mod = 0 AND is_banned = 0") if err != nil { log.Fatal(err) } diff --git a/plugin_bbcode.go b/plugin_bbcode.go index 4ab800a3..75ade75a 100644 --- a/plugin_bbcode.go +++ b/plugin_bbcode.go @@ -364,21 +364,20 @@ func bbcode_full_parse(data interface{}) interface{} { } } } - //fmt.Println(outbytes) //fmt.Println(string(outbytes)) if lastTag != i { - outbytes = append(outbytes, msgbytes[lastTag:len(msgbytes) - 10]...) + outbytes = append(outbytes, msgbytes[lastTag:]...) } if len(outbytes) != 0 { - return string(outbytes) + return string(outbytes[0:len(msgbytes) - 10]) } - msg = string(msgbytes) + msg = string(msgbytes[0:len(msgbytes) - 10]) //msg = bbcode_url.ReplaceAllString(msg,"$1$2//$3") msg = bbcode_url_label.ReplaceAllString(msg,"$4") // Convert [code] into class="codequotes" } else { - msg = string(msgbytes) + msg = string(msgbytes[0:len(msgbytes) - 10]) } return msg } diff --git a/reply.go b/reply.go index b0cfb088..b567f141 100644 --- a/reply.go +++ b/reply.go @@ -2,7 +2,7 @@ package main import "html/template" -type Reply struct +type Reply struct /* Should probably rename this to ReplyUser and rename ReplyShort to Reply */ { ID int ParentID int @@ -27,3 +27,24 @@ type Reply struct LikeCount int } +type ReplyShort struct +{ + ID int + ParentID int + Content string + CreatedBy int + Group int + CreatedAt string + LastEdit int + LastEditBy int + ContentLines int + IpAddress string + Liked bool + LikeCount int +} + +func get_reply(id int) (*ReplyShort, error) { + reply := ReplyShort{ID:id} + err := get_post_stmt.QueryRow(id).Scan(&reply.Content, &reply.CreatedBy, &reply.CreatedAt, &reply.LastEdit, &reply.LastEditBy, &reply.IpAddress, &reply.LikeCount) + return &reply, err +} diff --git a/routes.go b/routes.go index 3443d683..b00af8c3 100644 --- a/routes.go +++ b/routes.go @@ -1605,3 +1605,187 @@ func route_register_submit(w http.ResponseWriter, r *http.Request) { http.SetCookie(w,&cookie) http.Redirect(w,r, "/", http.StatusSeeOther) } + +func route_api(w http.ResponseWriter, r *http.Request) { + err := r.ParseForm() + is_js := r.PostFormValue("js") + if is_js == "" { + is_js = "0" + } + if err != nil { + PreErrorJSQ("Bad Form",w,r,is_js) + return + } + + user, ok := SimpleSessionCheck(w,r) + if !ok { + return + } + + action := r.FormValue("action") + if action != "get" && action != "set" { + PreErrorJSQ("Invalid Action",w,r,is_js) + return + } + + module := r.FormValue("module") + switch(module) { + case "alerts": // A feed of events tailored for a specific user + w.Header().Set("Content-Type","application/json") + if !user.Loggedin { + w.Write([]byte(`{"msgs":[{"msg":"Login to see your alerts","path":"/accounts/login"}]}`)) + return + } + + var msglist string + var asid int + var actor_id int + var targetUser_id int + var event string + var elementType string + var elementID int + //--- + var targetUser *User + + rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) + if err != nil { + InternalErrorJS(err,w,r) + return + } + + for rows.Next() { + err = rows.Scan(&asid,&actor_id,&targetUser_id,&event,&elementType,&elementID) + if err != nil { + InternalErrorJS(err,w,r) + return + } + + actor, err := users.CascadeGet(actor_id) + if err != nil { + LocalErrorJS("Unable to find the actor",w,r) + return + } + + /*if elementType != "forum" { + targetUser, err = users.CascadeGet(targetUser_id) + if err != nil { + LocalErrorJS("Unable to find the target user",w,r) + return + } + }*/ + + if event == "friend_invite" { + msglist += `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"/user/`+strconv.Itoa(actor.ID)+`"},` + continue + } + + /* + "You received a friend invite from {user}" + "{x}{mentioned you on}{user}{'s profile}" + "{x}{mentioned you in}{topic}" + "{x}{likes}{you}" + "{x}{liked}{your topic}{topic}" + "{x}{liked}{your post on}{user}{'s profile}" todo + "{x}{liked}{your post in}{topic}" + "{x}{replied to}{your post in}{topic}" todo + "{x}{created a new topic}{topic}" + */ + + var act string + var post_act string + var url string + var area string + var start_frag string + var end_frag string + switch(elementType) { + case "forum": + if event == "reply" { + act = "created a new topic" + topic, err := topics.CascadeGet(elementID) + if err != nil { + LocalErrorJS("Unable to find the linked topic",w,r) + return + } + url = build_topic_url(elementID) + area = topic.Title + // Store the forum ID in the targetUser column instead of making a new one? o.O + // Add an additional column for extra information later on when we add the ability to link directly to posts. We don't need the forum data for now.. + } else { + act = "did something in a forum" + } + case "topic": + topic, err := topics.CascadeGet(elementID) + if err != nil { + LocalErrorJS("Unable to find the linked topic",w,r) + return + } + url = build_topic_url(elementID) + area = topic.Title + if targetUser_id == user.ID { + post_act = " your topic" + } + case "user": + targetUser, err = users.CascadeGet(elementID) + if err != nil { + LocalErrorJS("Unable to find the target user",w,r) + return + } + area = targetUser.Name + end_frag = "'s profile" + url = build_profile_url(elementID) + case "post": + topic, err := get_topic_by_reply(elementID) + if err != nil { + LocalErrorJS("Unable to find the target reply or parent topic",w,r) + return + } + url = build_topic_url(elementID) + area = topic.Title + if targetUser_id == user.ID { + post_act = " your post in" + } + default: + LocalErrorJS("Invalid elementType",w,r) + } + + if event == "like" { + if elementType == "user" { + act = "likes" + end_frag = "" + if targetUser.ID == user.ID { + area = "you" + } + } else { + act = "liked" + } + } else if event == "mention" { + if elementType == "user" { + act = "mentioned you on" + } else { + act = "mentioned you in" + post_act = "" + } + } + + msglist += `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `"},` + } + + err = rows.Err() + if err != nil { + InternalErrorJS(err,w,r) + return + } + rows.Close() + + if len(msglist) != 0 { + msglist = msglist[0:len(msglist)-1] + } + w.Write([]byte(`{"msgs":[`+msglist+`]}`)) + //case "topics": + //case "forums": + //case "users": + //case "pages": + default: + PreErrorJSQ("Invalid Module",w,r,is_js) + } +} diff --git a/template_forum.go b/template_forum.go index 55a5e609..383046b6 100644 --- a/template_forum.go +++ b/template_forum.go @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_forum_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_forum_vars.NoticeList) != 0 { for _, item := range tmpl_forum_vars.NoticeList { diff --git a/template_forums.go b/template_forums.go index 4f0e2372..d8b4beb7 100644 --- a/template_forums.go +++ b/template_forums.go @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_forums_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_forums_vars.NoticeList) != 0 { for _, item := range tmpl_forums_vars.NoticeList { diff --git a/template_list.go b/template_list.go index 5a2955e4..92f35c9a 100644 --- a/template_list.go +++ b/template_list.go @@ -40,6 +40,9 @@ var menu_6 []byte = []byte(` `) var menu_7 []byte = []byte(` + diff --git a/template_profile.go b/template_profile.go index 71e1c103..76525d1c 100644 --- a/template_profile.go +++ b/template_profile.go @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_profile_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_profile_vars.NoticeList) != 0 { for _, item := range tmpl_profile_vars.NoticeList { diff --git a/template_topic.go b/template_topic.go index 80201881..1fb4187c 100644 --- a/template_topic.go +++ b/template_topic.go @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_topic_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_topic_vars.NoticeList) != 0 { for _, item := range tmpl_topic_vars.NoticeList { diff --git a/template_topic_alt.go b/template_topic_alt.go index c8518fc9..15ecdb3d 100644 --- a/template_topic_alt.go +++ b/template_topic_alt.go @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_topic_alt_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_topic_alt_vars.NoticeList) != 0 { for _, item := range tmpl_topic_alt_vars.NoticeList { diff --git a/template_topics.go b/template_topics.go index 25153d41..d44be385 100644 --- a/template_topics.go +++ b/template_topics.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 "strconv" import "io" +import "strconv" func init() { template_topics_handle = template_topics @@ -32,6 +32,10 @@ w.Write(menu_5) w.Write(menu_6) } w.Write(menu_7) +if !tmpl_topics_vars.CurrentUser.Loggedin { +w.Write(menu_8) +} +w.Write(menu_9) w.Write(header_3) if len(tmpl_topics_vars.NoticeList) != 0 { for _, item := range tmpl_topics_vars.NoticeList { diff --git a/templates/account-menu.html b/templates/account-menu.html index 81d8cf7a..0a8e88dc 100644 --- a/templates/account-menu.html +++ b/templates/account-menu.html @@ -1,5 +1,5 @@
-
My Account
+
My Account
Change Avatar
Change Username
Change Password
diff --git a/templates/account-own-edit-avatar.html b/templates/account-own-edit-avatar.html index 05bd896f..1975ca55 100644 --- a/templates/account-own-edit-avatar.html +++ b/templates/account-own-edit-avatar.html @@ -1,7 +1,7 @@ {{template "header.html" . }} {{template "account-menu.html" . }}
- +
{{ if .CurrentUser.Avatar }}
diff --git a/templates/account-own-edit-email.html b/templates/account-own-edit-email.html index f634be04..6d522d72 100644 --- a/templates/account-own-edit-email.html +++ b/templates/account-own-edit-email.html @@ -1,7 +1,7 @@ {{template "header.html" . }} {{template "account-menu.html" . }}
{{range .ItemList}} diff --git a/templates/account-own-edit-username.html b/templates/account-own-edit-username.html index 87a8f1ed..d362ec33 100644 --- a/templates/account-own-edit-username.html +++ b/templates/account-own-edit-username.html @@ -1,7 +1,7 @@ {{template "header.html" . }} {{template "account-menu.html" . }}
diff --git a/templates/account-own-edit.html b/templates/account-own-edit.html index b131f715..9225646e 100644 --- a/templates/account-own-edit.html +++ b/templates/account-own-edit.html @@ -1,7 +1,7 @@ {{template "header.html" . }} {{template "account-menu.html" . }}
diff --git a/templates/create-topic.html b/templates/create-topic.html index 36ffaeb2..e353fb5b 100644 --- a/templates/create-topic.html +++ b/templates/create-topic.html @@ -1,6 +1,6 @@ {{template "header.html" . }}
diff --git a/templates/login.html b/templates/login.html index d854784f..a413013c 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,6 +1,6 @@ {{template "header.html" . }}
- +
@@ -13,7 +13,8 @@
-
+
+
Don't have an account?
diff --git a/templates/menu.html b/templates/menu.html index 3161488c..4bda3987 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -9,12 +9,13 @@ {{if .CurrentUser.Loggedin}} - {{ if .CurrentUser.Is_Super_Mod}}{{end}} + {{if .CurrentUser.Is_Super_Mod}}{{end}} {{else}} {{end}} +
diff --git a/templates/register.html b/templates/register.html index 5e0bc8e6..8a67aa33 100644 --- a/templates/register.html +++ b/templates/register.html @@ -1,6 +1,6 @@ {{template "header.html" . }}
diff --git a/themes.go b/themes.go index 94a95e1b..a7217a96 100644 --- a/themes.go +++ b/themes.go @@ -26,6 +26,7 @@ type Theme struct FullImage string MobileFriendly bool Disabled bool + HideFromThemes bool Tag string Settings map[string]ThemeSetting Templates []TemplateMapping @@ -141,21 +142,7 @@ func map_theme_templates(theme Theme) { case *func(TopicPage,io.Writer): //overriden_templates[themeTmpl.Name] = d_tmpl_ptr overriden_templates[themeTmpl.Name] = true - //log.Print("Topic Handle") - //fmt.Println(template_topic_handle) - //log.Print("Before") - //fmt.Println(d_tmpl_ptr) - //fmt.Println(*d_tmpl_ptr) - //log.Print("Source") - //fmt.Println(s_tmpl_ptr) - //fmt.Println(*s_tmpl_ptr) *d_tmpl_ptr = *s_tmpl_ptr - //log.Print("After") - //fmt.Println(d_tmpl_ptr) - //fmt.Println(*d_tmpl_ptr) - //log.Print("Source") - //fmt.Println(s_tmpl_ptr) - //fmt.Println(*s_tmpl_ptr) default: log.Fatal("The source and destination templates are incompatible") } @@ -236,19 +223,7 @@ func reset_template_overrides() { case func(TopicPage,io.Writer): switch d_ptr := dest_tmpl_ptr.(type) { case *func(TopicPage,io.Writer): - //log.Print("Topic Handle") - //fmt.Println(template_topic_handle) - //log.Print("Before") - //fmt.Println(d_ptr) - //fmt.Println(*d_ptr) - //log.Print("Origin") - //fmt.Println(o_ptr) *d_ptr = o_ptr - //log.Print("After") - //fmt.Println(d_ptr) - //fmt.Println(*d_ptr) - //log.Print("Origin") - //fmt.Println(o_ptr) default: log.Fatal("The origin and destination templates are incompatible") } diff --git a/themes/cosmo-classic/theme.json b/themes/cosmo-classic/theme.json index 5247f229..1c8bdbe3 100644 --- a/themes/cosmo-classic/theme.json +++ b/themes/cosmo-classic/theme.json @@ -4,6 +4,7 @@ "Version": "Coming Soon", "Creator": "Azareal", "Disabled": true, + "HideFromThemes": true, "Tag": "WIP", "Templates": [ { diff --git a/themes/cosmo/public/main.css b/themes/cosmo/public/main.css index 8400a5e0..78dc2468 100644 --- a/themes/cosmo/public/main.css +++ b/themes/cosmo/public/main.css @@ -50,10 +50,7 @@ li padding-left: 1px; padding-right: 1px; - border: 1px solid #7a7a7a; - border-top: none; - border-bottom: none; - border-left: none; + border-right: 1px solid #7a7a7a; font-weight: normal; color: white; } @@ -63,16 +60,10 @@ li a color: white; text-decoration: none; } -li:hover a, li a:hover, li a:link, li a:visited -{ - color: white; - text-decoration: none; -} li:hover { background: rgba(10,10,10,0.5); font-weight: normal; - color: white; } .menu_right @@ -85,17 +76,28 @@ li:hover padding-right: 10px; height: 38px; text-align: center; + border-left: 1px solid #7a7a7a; } -.menu_right:hover -{ - border: #282828 1px solid; - background: #282828; - padding-left: 10px; - padding-right: 10px; - height: 38px; +.menu_alerts .alert_counter { + position: relative; + font-size: 9px; + top: -24px; + background-color: rgb(140,0,0); + color: white; + padding: 3px; + width: 14px; + left: 10px; + line-height: 8px; + border-radius: 20px; + padding-top: 2.5px; + height: 14px; + opacity: 0.8; text-align: center; } +.menu_alerts .alert_counter:empty { + display: none; +} #footer { diff --git a/themes/shadow/theme.json b/themes/shadow/theme.json new file mode 100644 index 00000000..fa861f80 --- /dev/null +++ b/themes/shadow/theme.json @@ -0,0 +1,8 @@ +{ + "Name": "shadow", + "FriendlyName": "Shadow", + "Version": "0.0.1", + "Creator": "Azareal", + "Disabled": true, + "HideFromThemes": true +} \ No newline at end of file diff --git a/themes/tempra-conflux/public/main.css b/themes/tempra-conflux/public/main.css index b51db5e4..359d3539 100644 --- a/themes/tempra-conflux/public/main.css +++ b/themes/tempra-conflux/public/main.css @@ -57,6 +57,31 @@ li a padding-right: 10px; } +.menu_alerts { + padding-left: 7px; + padding-top: 2px; + color: rgb(80,80,80); +} +.menu_alerts .alert_counter { + position:relative; + font-size: 9px; + top: -24px; + background-color: rgb(140,0,0); + color: white; + padding: 3px; + width: 14px; + left: 10px; + line-height: 8px; + border-radius: 20px; + padding-top: 2.5px; + height: 14px; + opacity: 0.8; + text-align: center; +} +.menu_alerts .alert_counter:empty { + display: none; +} + .container { width: 90%; diff --git a/themes/tempra-simple/public/main.css b/themes/tempra-simple/public/main.css index 794ef75f..05dc82be 100644 --- a/themes/tempra-simple/public/main.css +++ b/themes/tempra-simple/public/main.css @@ -55,6 +55,31 @@ li a padding-right: 10px; } +.menu_alerts { + padding-left: 7px; + padding-top: 2px; + color: rgb(80,80,80); +} +.menu_alerts .alert_counter { + position:relative; + font-size: 9px; + top: -24px; + background-color: rgb(140,0,0); + color: white; + padding: 3px; + width: 14px; + left: 10px; + line-height: 8px; + border-radius: 20px; + padding-top: 2.5px; + height: 14px; + opacity: 0.8; + text-align: center; +} +.menu_alerts .alert_counter:empty { + display: none; +} + .container { width: 90%; diff --git a/topic.go b/topic.go index 9372c410..361caa7b 100644 --- a/topic.go +++ b/topic.go @@ -1,6 +1,7 @@ package main //import "fmt" import "sync" +import "strconv" import "html/template" import "database/sql" @@ -341,4 +342,14 @@ func copy_topic_to_topicuser(topic *Topic, user *User) (tu TopicUser) { tu.PostCount = topic.PostCount tu.LikeCount = topic.LikeCount return tu -} \ No newline at end of file +} + +func get_topic_by_reply(rid int) (*Topic, error) { + topic := Topic{ID:0} + err := get_topic_by_reply_stmt.QueryRow(rid).Scan(&topic.ID, &topic.Title, &topic.Content, &topic.CreatedBy, &topic.CreatedAt, &topic.Is_Closed, &topic.Sticky, &topic.ParentID, &topic.IpAddress, &topic.PostCount, &topic.LikeCount) + return &topic, err +} + +func build_topic_url(tid int) string { + return "/topic/" + strconv.Itoa(tid) +} diff --git a/user.go b/user.go index b9a93c17..1780d0a1 100644 --- a/user.go +++ b/user.go @@ -525,4 +525,8 @@ func init_user_perms(user *User) { if user.Is_Banned && user.Is_Super_Mod { user.Is_Banned = false } -} \ No newline at end of file +} + +func build_profile_url(uid int) string { + return "/user/" + strconv.Itoa(uid) +}