From 81af085c7ab57ddfde3d44240e0d139659831427 Mon Sep 17 00:00:00 2001 From: Azareal Date: Sat, 10 Jun 2017 08:58:15 +0100 Subject: [PATCH] Added support for Live Likes, the first step towards Live Alerts. Moved 26 queries into the query generator. Added support for sime replace queries in the query generator. The alert list can only have eight entries now. Users can no longer like their own posts. Renamed the bigpost_min_chars setting to bigpost_min_words. Renamed the megapost_min_chars setting to megapost_min_words. Moved the alert building logic into it's own file. Fixed a bug in the megapost and bigpost algorithms where only posts larger than the minimum would be considered. Renamed the GuestCount and UserCount methods for WebSockets to guest_count and user_count. Added the broadcast_message, push_message, and push_alert methods to the WebSockets Hub. --- alerts.go | 113 ++++++++++++++++++++++++++ gen_mysql.go | 182 +++++++++++++++++++++++++++++++++++++++++ general_test.go | 118 ++++++++++++++------------- mysql.go | 193 ++------------------------------------------ mysql.sql | 4 +- no_websockets.go | 18 ++++- panel_routes.go | 5 +- public/global.js | 60 ++++++++++---- query_gen/main.go | 97 +++++++++++++++++++++- query_gen/mysql.go | 38 +++++++++ routes.go | 165 +++++++++---------------------------- setting.go | 8 +- template_list.go | 2 +- templates/menu.html | 2 +- user.go | 12 +-- websockets.go | 165 +++++++++++++++++++++++++------------ 16 files changed, 728 insertions(+), 454 deletions(-) create mode 100644 alerts.go diff --git a/alerts.go b/alerts.go new file mode 100644 index 00000000..4e72774f --- /dev/null +++ b/alerts.go @@ -0,0 +1,113 @@ +package main + +import "strings" +import "strconv" +import "errors" + +/* +"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}{replied to}{topic}" +"{x}{replied to}{your topic}{topic}" +"{x}{created a new topic}{topic}" +*/ + +func build_alert(event string, elementType string, actor_id int, targetUser_id int, elementID int, user User /* The current user */) (string, error) { + var targetUser *User + + actor, err := users.CascadeGet(actor_id) + if err != nil { + return "", errors.New("Unable to find the actor") + } + + /*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" { + return `{"msg":"You received a friend invite from {0}","sub":["` + actor.Name + `"],"path":"\/user\/`+strconv.Itoa(actor.ID)+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`"}`, nil + } + + var act, post_act, url, area string + var start_frag, end_frag string + switch(elementType) { + case "forum": + if event == "reply" { + act = "created a new topic" + topic, err := topics.CascadeGet(elementID) + if err != nil { + return "", errors.New("Unable to find the linked topic") + } + 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 { + return "", errors.New("Unable to find the linked topic") + } + 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 { + return "", errors.New("Unable to find the target user") + } + area = targetUser.Name + end_frag = "'s profile" + url = build_profile_url(elementID) + case "post": + topic, err := get_topic_by_reply(elementID) + if err != nil { + return "", errors.New("Unable to find the linked reply or parent topic") + } + url = build_topic_url(topic.ID) + area = topic.Title + if targetUser_id == user.ID { + post_act = " your post in" + } + default: + return "", errors.New("Invalid elementType") + } + + switch(event) { + case "like": + if elementType == "user" { + act = "likes" + end_frag = "" + if targetUser.ID == user.ID { + area = "you" + } + } else { + act = "liked" + } + case "mention": + if elementType == "user" { + act = "mentioned you on" + } else { + act = "mentioned you in" + post_act = "" + } + case "reply": act = "replied to" + } + + return `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `"}`, nil +} diff --git a/gen_mysql.go b/gen_mysql.go index 45a283c9..0675c54f 100644 --- a/gen_mysql.go +++ b/gen_mysql.go @@ -40,7 +40,17 @@ var create_reply_stmt *sql.Stmt var create_action_reply_stmt *sql.Stmt var create_like_stmt *sql.Stmt var add_activity_stmt *sql.Stmt +var notify_one_stmt *sql.Stmt var register_stmt *sql.Stmt +var create_profile_reply_stmt *sql.Stmt +var create_forum_stmt *sql.Stmt +var add_forum_perms_to_forum_stmt *sql.Stmt +var add_plugin_stmt *sql.Stmt +var add_theme_stmt *sql.Stmt +var create_group_stmt *sql.Stmt +var add_modlog_entry_stmt *sql.Stmt +var add_adminlog_entry_stmt *sql.Stmt +var add_forum_perms_to_group_stmt *sql.Stmt var add_replies_to_topic_stmt *sql.Stmt var remove_replies_from_topic_stmt *sql.Stmt var add_topics_to_forum_stmt *sql.Stmt @@ -60,6 +70,22 @@ var set_avatar_stmt *sql.Stmt var set_username_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 edit_profile_reply_stmt *sql.Stmt +var delete_forum_stmt *sql.Stmt +var update_forum_stmt *sql.Stmt +var update_setting_stmt *sql.Stmt +var update_plugin_stmt *sql.Stmt +var update_theme_stmt *sql.Stmt +var update_user_stmt *sql.Stmt +var update_group_perms_stmt *sql.Stmt +var update_group_rank_stmt *sql.Stmt +var update_group_stmt *sql.Stmt func gen_mysql() (err error) { if debug { @@ -270,12 +296,72 @@ func gen_mysql() (err error) { return err } + log.Print("Preparing notify_one statement.") + notify_one_stmt, err = db.Prepare("INSERT INTO `activity_stream_matches`(`watcher`,`asid`) VALUES (?,?)") + if err != nil { + return err + } + log.Print("Preparing register statement.") register_stmt, err = db.Prepare("INSERT INTO `users`(`name`,`email`,`password`,`salt`,`group`,`is_super_admin`,`session`,`active`,`message`) VALUES (?,?,?,?,?,0,?,?,'')") if err != nil { return 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 { + return err + } + + log.Print("Preparing create_forum statement.") + create_forum_stmt, err = db.Prepare("INSERT INTO `forums`(`name`,`desc`,`active`,`preset`) VALUES (?,?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing add_forum_perms_to_forum statement.") + add_forum_perms_to_forum_stmt, err = db.Prepare("INSERT INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)") + if err != nil { + return err + } + + log.Print("Preparing add_plugin statement.") + add_plugin_stmt, err = db.Prepare("INSERT INTO `plugins`(`uname`,`active`) VALUES (?,?)") + if err != nil { + return err + } + + log.Print("Preparing add_theme statement.") + add_theme_stmt, err = db.Prepare("INSERT INTO `themes`(`uname`,`default`) VALUES (?,?)") + if err != nil { + return err + } + + log.Print("Preparing create_group statement.") + create_group_stmt, err = db.Prepare("INSERT INTO `users_groups`(`name`,`tag`,`is_admin`,`is_mod`,`is_banned`,`permissions`) VALUES (?,?,?,?,?,?)") + if err != nil { + return err + } + + 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())") + 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())") + if err != nil { + return err + } + + log.Print("Preparing add_forum_perms_to_group statement.") + add_forum_perms_to_group_stmt, err = db.Prepare("REPLACE INTO `forums_permissions`(`gid`,`fid`,`preset`,`permissions`) VALUES (?,?,?,?)") + if err != nil { + return err + } + 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` = ? ") if err != nil { @@ -389,6 +475,102 @@ func gen_mysql() (err error) { if err != nil { return err } + + log.Print("Preparing update_user_level statement.") + update_user_level_stmt, err = db.Prepare("UPDATE `users` SET `level` = ? WHERE `uid` = ? ") + if err != nil { + return 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 { + return 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 { + return 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 { + return 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 { + return 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 { + return err + } + + log.Print("Preparing edit_profile_reply statement.") + edit_profile_reply_stmt, err = db.Prepare("UPDATE `users_replies` SET `content` = ?,`parsed_content` = ? WHERE `rid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing delete_forum statement.") + delete_forum_stmt, err = db.Prepare("UPDATE `forums` SET `name` = '',`active` = 0 WHERE `fid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_forum statement.") + update_forum_stmt, err = db.Prepare("UPDATE `forums` SET `name` = ?,`desc` = ?,`active` = ?,`preset` = ? WHERE `fid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_setting statement.") + update_setting_stmt, err = db.Prepare("UPDATE `settings` SET `content` = ? WHERE `name` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_plugin statement.") + update_plugin_stmt, err = db.Prepare("UPDATE `plugins` SET `active` = ? WHERE `uname` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_theme statement.") + update_theme_stmt, err = db.Prepare("UPDATE `themes` SET `default` = ? WHERE `uname` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_user statement.") + update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?,`email` = ?,`group` = ? WHERE `uid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_group_perms statement.") + update_group_perms_stmt, err = db.Prepare("UPDATE `users_groups` SET `permissions` = ? WHERE `gid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_group_rank statement.") + update_group_rank_stmt, err = db.Prepare("UPDATE `users_groups` SET `is_admin` = ?,`is_mod` = ?,`is_banned` = ? WHERE `gid` = ? ") + if err != nil { + return err + } + + log.Print("Preparing update_group statement.") + update_group_stmt, err = db.Prepare("UPDATE `users_groups` SET `name` = ?,`tag` = ? WHERE `gid` = ? ") + if err != nil { + return err + } return nil } diff --git a/general_test.go b/general_test.go index 29c92ebd..d92dd6b4 100644 --- a/general_test.go +++ b/general_test.go @@ -1,34 +1,40 @@ package main -import "os" -import "fmt" -import "log" -import "bytes" -import "strings" -import "strconv" -import "math/rand" -import "testing" -import "net/http" -import "net/http/httptest" -import "io/ioutil" -import "database/sql" -import "runtime/pprof" -//import _ "github.com/go-sql-driver/mysql" -//import "github.com/erikstmartin/go-testdb" -//import "github.com/husobee/vestigo" +import ( + "os" + "fmt" + "log" + "bytes" + "strings" + "strconv" + //"math/rand" + "testing" + "time" + "net/http" + "net/http/httptest" + "io/ioutil" + "database/sql" + "runtime/pprof" + + //_ "github.com/go-sql-driver/mysql" + //"github.com/erikstmartin/go-testdb" + //"github.com/husobee/vestigo" +) -var db_test *sql.DB -var db_prod *sql.DB +var db_test, db_prod *sql.DB var gloinited bool = false func gloinit() { debug = false - nogrouplog = true + //nogrouplog = true // init_database is a little noisy for a benchmark //discard := ioutil.Discard //log.SetOutput(discard) + startTime = time.Now() + timeLocation = startTime.Location() + init_themes() err := init_database() if err != nil { @@ -352,7 +358,7 @@ func BenchmarkForumsGuestRouteParallel(b *testing.B) { } -func BenchmarkRoutesSerial(b *testing.B) { +/*func BenchmarkRoutesSerial(b *testing.B) { b.ReportAllocs() admin, err := users.CascadeGet(1) if err != nil { @@ -404,13 +410,13 @@ func BenchmarkRoutesSerial(b *testing.B) { gloinit() } - /*f, err := os.Create("routes_bench_cpu.prof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f)*/ - //defer pprof.StopCPUProfile() - //pprof.StopCPUProfile() + //f, err := os.Create("routes_bench_cpu.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) + ///defer pprof.StopCPUProfile() + ///pprof.StopCPUProfile() b.Run("static_recorder", func(b *testing.B) { for i := 0; i < b.N; i++ { @@ -490,11 +496,11 @@ func BenchmarkRoutesSerial(b *testing.B) { } }) b.Run("forums_guest_recorder", func(b *testing.B) { - /*f, err := os.Create("routes_bench_forums_cpu_2.prof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f)*/ + //f, err := os.Create("routes_bench_forums_cpu_2.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //forums_w.Code = 200 forums_w.Body.Reset() @@ -508,11 +514,11 @@ func BenchmarkRoutesSerial(b *testing.B) { } b.Run("topic_admin_recorder_with_plugins", func(b *testing.B) { - /*f, err := os.Create("routes_bench_topic_cpu.prof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f)*/ + //f, err := os.Create("routes_bench_topic_cpu.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //topic_w.Code = 200 topic_w.Body.Reset() @@ -525,11 +531,11 @@ func BenchmarkRoutesSerial(b *testing.B) { //pprof.StopCPUProfile() }) b.Run("topic_guest_recorder_with_plugins", func(b *testing.B) { - /*f, err := os.Create("routes_bench_topic_cpu_2.prof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f)*/ + //f, err := os.Create("routes_bench_topic_cpu_2.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //topic_w.Code = 200 topic_w.Body.Reset() @@ -573,11 +579,11 @@ func BenchmarkRoutesSerial(b *testing.B) { } }) b.Run("forums_guest_recorder_with_plugins", func(b *testing.B) { - /*f, err := os.Create("routes_bench_forums_cpu_2.prof") - if err != nil { - log.Fatal(err) - } - pprof.StartCPUProfile(f)*/ + //f, err := os.Create("routes_bench_forums_cpu_2.prof") + //if err != nil { + // log.Fatal(err) + //} + //pprof.StartCPUProfile(f) for i := 0; i < b.N; i++ { //forums_w.Code = 200 forums_w.Body.Reset() @@ -585,7 +591,7 @@ func BenchmarkRoutesSerial(b *testing.B) { } //pprof.StopCPUProfile() }) -} +}*/ func BenchmarkQueryTopicParallel(b *testing.B) { b.ReportAllocs() @@ -1224,7 +1230,7 @@ func TestStaticRoute(t *testing.T) { fmt.Println("No problems found in the static route!") } -func TestTopicAdminRoute(t *testing.T) { +/*func TestTopicAdminRoute(t *testing.T) { if !gloinited { gloinit() } @@ -1256,9 +1262,9 @@ func TestTopicAdminRoute(t *testing.T) { panic("HTTP Error!") } fmt.Println("No problems found in the topic-admin route!") -} +}*/ -func TestTopicGuestRoute(t *testing.T) { +/*func TestTopicGuestRoute(t *testing.T) { if !gloinited { gloinit() } @@ -1276,7 +1282,7 @@ func TestTopicGuestRoute(t *testing.T) { panic("HTTP Error!") } fmt.Println("No problems found in the topic-guest route!") -} +}*/ func TestForumsAdminRoute(t *testing.T) { if !gloinited { @@ -1331,7 +1337,7 @@ func TestForumsGuestRoute(t *testing.T) { fmt.Println("No problems found in the forums-guest route!") } -func TestForumAdminRoute(t *testing.T) { +/*func TestForumAdminRoute(t *testing.T) { if !gloinited { gloinit() } @@ -1362,9 +1368,9 @@ func TestForumAdminRoute(t *testing.T) { panic("HTTP Error!") } fmt.Println("No problems found in the forum-admin route!") -} +}*/ -func TestForumGuestRoute(t *testing.T) { +/*func TestForumGuestRoute(t *testing.T) { if !gloinited { gloinit() } @@ -1382,7 +1388,7 @@ func TestForumGuestRoute(t *testing.T) { panic("HTTP Error!") } fmt.Println("No problems found in the forum-guest route!") -} +}*/ /*func TestAlerts(t *testing.T) { if !gloinited { diff --git a/mysql.go b/mysql.go index df2aaef8..b66a9829 100644 --- a/mysql.go +++ b/mysql.go @@ -16,49 +16,23 @@ var db_collation string = "utf8mb4_general_ci" var get_topic_replies_offset_stmt *sql.Stmt // I'll need to rewrite this one to stop it hard-coding the per page setting before moving it to the query generator var get_forum_topics_offset_stmt *sql.Stmt var notify_watchers_stmt *sql.Stmt -var notify_one_stmt *sql.Stmt var add_subscription_stmt *sql.Stmt var delete_reply_stmt *sql.Stmt var delete_topic_stmt *sql.Stmt var get_activity_feed_by_watcher_stmt *sql.Stmt +var get_activity_count_by_watcher_stmt *sql.Stmt var add_email_stmt *sql.Stmt var update_email_stmt *sql.Stmt var verify_email_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 -var create_forum_stmt *sql.Stmt -var delete_forum_stmt *sql.Stmt -var update_forum_stmt *sql.Stmt var forum_entry_exists_stmt *sql.Stmt var group_entry_exists_stmt *sql.Stmt var delete_forum_perms_by_forum_stmt *sql.Stmt -var add_forum_perms_to_forum_stmt *sql.Stmt var add_forum_perms_to_forum_admins_stmt *sql.Stmt var add_forum_perms_to_forum_staff_stmt *sql.Stmt var add_forum_perms_to_forum_members_stmt *sql.Stmt -var add_forum_perms_to_group_stmt *sql.Stmt -//var forum_perm_exists_for_group_stmt *sql.Stmt var update_forum_perms_for_group_stmt *sql.Stmt -var update_setting_stmt *sql.Stmt -var add_plugin_stmt *sql.Stmt -var update_plugin_stmt *sql.Stmt -var update_user_stmt *sql.Stmt -var update_group_perms_stmt *sql.Stmt -var update_group_rank_stmt *sql.Stmt -var update_group_stmt *sql.Stmt -var create_group_stmt *sql.Stmt -var add_theme_stmt *sql.Stmt -var update_theme_stmt *sql.Stmt -var add_modlog_entry_stmt *sql.Stmt -var add_adminlog_entry_stmt *sql.Stmt var todays_post_count_stmt *sql.Stmt var todays_topic_count_stmt *sql.Stmt var todays_report_count_stmt *sql.Stmt @@ -112,12 +86,6 @@ func init_database() (err error) { return err } - log.Print("Preparing notify_one statement.") - notify_one_stmt, err = db.Prepare("INSERT INTO activity_stream_matches(watcher,asid) VALUES(?,?)") - if err != nil { - return err - } - log.Print("Preparing add_subscription statement.") add_subscription_stmt, err = db.Prepare("INSERT INTO activity_subscriptions(user,targetID,targetType,level) VALUES(?,?,?,2)") if err != nil { @@ -137,7 +105,13 @@ func init_database() (err error) { } 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` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?") + 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` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ? ORDER BY activity_stream.asid ASC LIMIT 8") + if err != nil { + return err + } + + log.Print("Preparing get_activity_count_by_watcher statement.") + get_activity_count_by_watcher_stmt, err = db.Prepare("SELECT count(*) FROM `activity_stream_matches` INNER JOIN `activity_stream` ON activity_stream_matches.asid = activity_stream.asid AND activity_stream_matches.watcher != activity_stream.actor WHERE `watcher` = ?") if err != nil { return err } @@ -160,79 +134,12 @@ func init_database() (err error) { return err } - log.Print("Preparing update_user_level statement.") - update_user_level_stmt, err = db.Prepare("UPDATE users SET level = ? WHERE uid = ?") - if err != nil { - return 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 { - return 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 { - return 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 { - return 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 { - return 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 { - return 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 { - return err - } - - log.Print("Preparing edit_profile_reply statement.") - edit_profile_reply_stmt, err = db.Prepare("UPDATE users_replies SET content = ?, parsed_content = ? WHERE rid = ?") - if err != nil { - return err - } - log.Print("Preparing delete_profile_reply statement.") delete_profile_reply_stmt, err = db.Prepare("DELETE FROM users_replies WHERE rid = ?") if err != nil { return err } - log.Print("Preparing create_forum statement.") - create_forum_stmt, err = db.Prepare("INSERT INTO forums(`name`,`desc`,`active`,`preset`) VALUES(?,?,?,?)") - if err != nil { - return err - } - - log.Print("Preparing delete_forum statement.") - //delete_forum_stmt, err = db.Prepare("delete from forums where fid = ?") - delete_forum_stmt, err = db.Prepare("update forums set name= '', active = 0 where fid = ?") - if err != nil { - return err - } - - log.Print("Preparing update_forum statement.") - update_forum_stmt, err = db.Prepare("update forums set `name` = ?, `desc` = ?, `active` = ?, `preset` = ? where fid = ?") - if err != nil { - return err - } - log.Print("Preparing forum_entry_exists statement.") forum_entry_exists_stmt, err = db.Prepare("SELECT `fid` FROM `forums` WHERE `name` = '' order by fid asc limit 1") if err != nil { @@ -251,12 +158,6 @@ func init_database() (err error) { return err } - log.Print("Preparing add_forum_perms_to_forum statement.") - add_forum_perms_to_forum_stmt, err = db.Prepare("INSERT INTO forums_permissions(gid,fid,preset,permissions) VALUES(?,?,?,?)") - if err != nil { - return err - } - 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") if err != nil { @@ -275,84 +176,6 @@ func init_database() (err error) { return err } - log.Print("Preparing add_forum_perms_to_group statement.") - add_forum_perms_to_group_stmt, err = db.Prepare("REPLACE INTO forums_permissions(gid,fid,preset,permissions) VALUES(?,?,?,?)") - if err != nil { - return err - } - - log.Print("Preparing update_setting statement.") - update_setting_stmt, err = db.Prepare("UPDATE settings SET content = ? WHERE name = ?") - if err != nil { - return err - } - - log.Print("Preparing add_plugin statement.") - add_plugin_stmt, err = db.Prepare("INSERT INTO plugins(uname,active) VALUES(?,?)") - if err != nil { - return err - } - - log.Print("Preparing update_plugin statement.") - update_plugin_stmt, err = db.Prepare("UPDATE plugins SET active = ? WHERE uname = ?") - if err != nil { - return err - } - - log.Print("Preparing add_theme statement.") - add_theme_stmt, err = db.Prepare("INSERT INTO `themes`(`uname`,`default`) VALUES(?,?)") - if err != nil { - return err - } - - log.Print("Preparing update_theme statement.") - update_theme_stmt, err = db.Prepare("update `themes` set `default` = ? where `uname` = ?") - if err != nil { - return err - } - - log.Print("Preparing update_user statement.") - update_user_stmt, err = db.Prepare("update `users` set `name` = ?,`email` = ?,`group` = ? where `uid` = ?") - if err != nil { - return err - } - - log.Print("Preparing update_group_rank statement.") - update_group_perms_stmt, err = db.Prepare("update `users_groups` set `permissions` = ? where `gid` = ?") - if err != nil { - return err - } - - log.Print("Preparing update_group_rank statement.") - update_group_rank_stmt, err = db.Prepare("update `users_groups` set `is_admin` = ?, `is_mod` = ?, `is_banned` = ? where `gid` = ?") - if err != nil { - return err - } - - log.Print("Preparing update_group statement.") - update_group_stmt, err = db.Prepare("update `users_groups` set `name` = ?, `tag` = ? where `gid` = ?") - if err != nil { - return err - } - - log.Print("Preparing create_group statement.") - create_group_stmt, err = db.Prepare("INSERT INTO users_groups(name,tag,is_admin,is_mod,is_banned,permissions) VALUES(?,?,?,?,?,?)") - if err != nil { - return err - } - - 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())") - if err != nil { - return err - } - - log.Print("Preparing add_adminlog_entry statement.") - add_adminlog_entry_stmt, err = db.Prepare("INSERT INTO moderation_logs(action,elementID,elementType,ipaddress,actorID,doneAt) VALUES(?,?,?,?,?,NOW())") - if err != nil { - return err - } - 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()") if err != nil { diff --git a/mysql.sql b/mysql.sql index a023ae4f..8db95612 100644 --- a/mysql.sql +++ b/mysql.sql @@ -193,8 +193,8 @@ CREATE TABLE `administration_logs`( 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 settings(`name`,`content`,`type`) VALUES ('bigpost_min_words','250','int'); +INSERT INTO settings(`name`,`content`,`type`) VALUES ('megapost_min_words','1000','int'); INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1); INSERT INTO users(`name`,`password`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`,`last_ip`) diff --git a/no_websockets.go b/no_websockets.go index ea76e359..12a90e7a 100644 --- a/no_websockets.go +++ b/no_websockets.go @@ -2,21 +2,35 @@ package main +import "errors" import "net/http" var ws_hub WS_Hub +var ws_nouser error = errors.New("This user isn't connected via WebSockets") type WS_Hub struct { } -func (_ *WS_Hub) GuestCount() int { +func (_ *WS_Hub) guest_count() int { return 0 } -func (_ *WS_Hub) UserCount() int { +func (_ *WS_Hub) user_count() int { return 0 } +func (hub *WS_Hub) broadcast_message(_ string) error { + return nil +} + +func (hub *WS_Hub) push_message(_ int, _ string) error { + return ws_nouser +} + +func(hub *WS_Hub) push_alert(_ int, _ string, _ string, _ int, _ int, _ int) error { + return ws_nouser +} + func route_websockets(_ http.ResponseWriter, _ *http.Request) { } diff --git a/panel_routes.go b/panel_routes.go index 4d2d2c3a..b589bc84 100644 --- a/panel_routes.go +++ b/panel_routes.go @@ -137,8 +137,8 @@ func route_panel(w http.ResponseWriter, r *http.Request){ } if enable_websockets { - uonline := ws_hub.UserCount() - gonline := ws_hub.GuestCount() + uonline := ws_hub.user_count() + gonline := ws_hub.guest_count() totonline := uonline + gonline var onlineColour string @@ -489,7 +489,6 @@ func route_panel_forums_edit_perms_submit(w http.ResponseWriter, r *http.Request return } - //_, err = update_forum_perms_for_group_stmt.Exec(perm_preset,perms,gid,fid) _, err = add_forum_perms_to_group_stmt.Exec(gid,fid,perm_preset,perms) if err != nil { InternalErrorJSQ(err,w,r,is_js) diff --git a/public/global.js b/public/global.js index 357dc1b6..221b26b1 100644 --- a/public/global.js +++ b/public/global.js @@ -1,4 +1,6 @@ var form_vars = {}; +var alertList = []; +var alertCount = 0; function post_link(event) { @@ -17,7 +19,6 @@ function load_alerts(menu_alerts) url:'/api/?action=get&module=alerts&format=json', success: function(data) { if("errmsg" in data) { - //console.log(data.errmsg); menu_alerts.find(".alertList").html("
"+data.errmsg+"
"); return; } @@ -36,12 +37,14 @@ function load_alerts(menu_alerts) } } - if("avatar" in msg) - { + if("avatar" in msg) { alist += "
"+mmsg+"
"; + alertList.push("
"+mmsg+"
"); anyAvatar = true + } else { + alist += "
"+mmsg+"
"; + alertList.push("
"+mmsg+"
"); } - else alist += "
"+mmsg+"
"; //console.log(msg); //console.log(mmsg); } @@ -52,14 +55,19 @@ function load_alerts(menu_alerts) //if(anyAvatar) menu_alerts.addClass("hasAvatars"); } menu_alerts.find(".alertList").html(alist); - if(data.msgs.length != 0) menu_alerts.find(".alert_counter").text(data.msgs.length); + if(data.msgCount != 0) menu_alerts.find(".alert_counter").text(data.msgCount); + alertCount = data.msgCount; }, error: function(magic,theStatus,error) { try { var data = JSON.parse(magic.responseText); if("errmsg" in data) errtxt = data.errmsg; else errtxt = "Unable to get the alerts"; - } catch(e) { errtxt = "Unable to get the alerts"; } + } catch(err) { + errtxt = "Unable to get the alerts"; + console.log(magic.responseText); + console.log(err); + } menu_alerts.find(".alertList").html("
"+errtxt+"
"); } }); @@ -81,9 +89,7 @@ $(document).ready(function(){ lastN++; } } - if(data.length > lastIndex) { - out[out.length - 1] += data.substring(lastIndex); - } + if(data.length > lastIndex) out[out.length - 1] += data.substring(lastIndex); return out; } @@ -96,8 +102,37 @@ $(document).ready(function(){ conn = false; } conn.onmessage = function(event) { - //console.log("WS_Message:"); - //console.log(event.data); + //console.log("WS_Message: ",event.data); + if(event.data[0] == "{") { + try { + var data = JSON.parse(event.data); + } catch(err) { console.log(err); } + + if ("msg" in data) { + var msg = data.msg + if("sub" in data) { + for(var i = 0; i < data.sub.length; i++) { + msg = msg.replace("\{"+i+"\}", data.sub[i]); + } + } + + if("avatar" in data) alertList.push("
"+msg+"
"); + else alertList.push("
"+msg+"
"); + if(alertList.length > 8) alertList.shift(); + //console.log("post alertList",alertList); + alertCount++; + + var alist = "" + for (var i = 0; i < alertList.length; i++) { + alist += alertList[i]; + } + + //console.log(alist); + $("#general_alerts").find(".alertList").html(alist); // Add support for other alert feeds like PM Alerts + $("#general_alerts").find(".alert_counter").text(alertCount); + } + } + var messages = event.data.split('\r'); for(var i = 0; i < messages.length; i++) { //console.log("Message:"); @@ -266,9 +301,6 @@ $(document).ready(function(){ var newContent = $(this).find('input').eq(0).val(); this.innerHTML = newContent; } - //console.log("field_name",field_name); - //console.log("field_type",field_type); - //console.log("newContent",newContent); this.setAttribute("data-value",newContent); out_data[field_name] = newContent; }); diff --git a/query_gen/main.go b/query_gen/main.go index b759a470..1e99a41c 100644 --- a/query_gen/main.go +++ b/query_gen/main.go @@ -61,7 +61,7 @@ type DB_Setter struct { type DB_Adapter interface { get_name() string simple_insert(string,string,string,string) error - //simple_replace(string,string,[]string,string) error + simple_replace(string,string,string,string) error simple_update(string,string,string,string) error simple_select(string,string,string,string,string/*,int,int*/) error simple_left_join(string,string,string,string,string,string,string/*,int,int*/) error @@ -79,6 +79,30 @@ func main() { } func write_statements(adapter DB_Adapter) error { + err := write_selects(adapter) + if err != nil { + return err + } + err = write_joins(adapter) + if err != nil { + return err + } + err = write_inserts(adapter) + if err != nil { + return err + } + err = write_replaces(adapter) + if err != nil { + return err + } + err = write_updates(adapter) + if err != nil { + return err + } + return nil +} + +func write_selects(adapter DB_Adapter) error { // url_prefix and url_name will be removed from this query in a later commit adapter.simple_select("get_user","users","name, group, is_super_admin, avatar, message, url_prefix, url_name, level","uid = ?","") @@ -124,7 +148,10 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_select("get_emails_by_user","emails","email, validated","uid = ?","") adapter.simple_select("get_topic_basic","topics","title, content","tid = ?","") - + return nil +} + +func write_joins(adapter DB_Adapter) error { adapter.simple_left_join("get_topic_list","topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.parentID, users.name, users.avatar","topics.createdBy = users.uid","","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy DESC") adapter.simple_left_join("get_topic_user","topics","users","topics.title, topics.content, topics.createdBy, topics.createdAt, topics.is_closed, topics.sticky, topics.parentID, topics.ipaddress, topics.postCount, topics.likeCount, users.name, users.avatar, users.group, users.url_prefix, users.url_name, users.level","topics.createdBy = users.uid","tid = ?","") @@ -136,7 +163,10 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_left_join("get_forum_topics","topics","users","topics.tid, topics.title, topics.content, topics.createdBy, topics.is_closed, topics.sticky, topics.createdAt, topics.lastReplyAt, topics.parentID, users.name, users.avatar","topics.createdBy = users.uid","topics.parentID = ?","topics.sticky DESC, topics.lastReplyAt DESC, topics.createdBy desc") adapter.simple_left_join("get_profile_replies","users_replies","users","users_replies.rid, users_replies.content, users_replies.createdBy, users_replies.createdAt, users_replies.lastEdit, users_replies.lastEditBy, users.avatar, users.name, users.group","users_replies.createdBy = users.uid","users_replies.uid = ?","") - + return nil +} + +func write_inserts(adapter DB_Adapter) error { adapter.simple_insert("create_topic","topics","parentID,title,content,parsed_content,createdAt,lastReplyAt,ipaddress,words,createdBy","?,?,?,?,NOW(),NOW(),?,?,?") adapter.simple_insert("create_report","topics","title,content,parsed_content,createdAt,lastReplyAt,createdBy,data,parentID,css_class","?,?,?,NOW(),NOW(),?,?,1,'report'") @@ -149,11 +179,39 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_insert("add_activity","activity_stream","actor,targetUser,event,elementType,elementID","?,?,?,?,?") + adapter.simple_insert("notify_one","activity_stream_matches","watcher,asid","?,?") + // Add an admin version of register_stmt with more flexibility? // create_account_stmt, err = db.Prepare("INSERT INTO adapter.simple_insert("register","users","name, email, password, salt, group, is_super_admin, session, active, message","?,?,?,?,?,0,?,?,''") + adapter.simple_insert("create_profile_reply","users_replies","uid,content,parsed_content,createdAt,createdBy","?,?,?,NOW(),?") + adapter.simple_insert("create_forum","forums","name, desc, active, preset","?,?,?,?") + + adapter.simple_insert("add_forum_perms_to_forum","forums_permissions","gid,fid,preset,permissions","?,?,?,?") + + adapter.simple_insert("add_plugin","plugins","uname,active","?,?") + + adapter.simple_insert("add_theme","themes","uname,default","?,?") + + + adapter.simple_insert("create_group","users_groups","name, tag, is_admin, is_mod, is_banned, permissions","?,?,?,?,?,?") + + adapter.simple_insert("add_modlog_entry","moderation_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,NOW()") + + adapter.simple_insert("add_adminlog_entry","administration_logs","action, elementID, elementType, ipaddress, actorID, doneAt","?,?,?,?,?,NOW()") + + return nil +} + +func write_replaces(adapter DB_Adapter) error { + adapter.simple_replace("add_forum_perms_to_group","forums_permissions","gid,fid,preset,permissions","?,?,?,?") + + return nil +} + +func write_updates(adapter DB_Adapter) error { adapter.simple_update("add_replies_to_topic","topics","postCount = postCount + ?, lastReplyAt = NOW()","tid = ?") adapter.simple_update("remove_replies_from_topic","topics","postCount = postCount - ?","tid = ?") @@ -192,6 +250,39 @@ func write_statements(adapter DB_Adapter) error { adapter.simple_update("activate_user","users","active = 1","uid = ?") + adapter.simple_update("update_user_level","users","level = ?","uid = ?") + + adapter.simple_update("increment_user_score","users","score = score + ?","uid = ?") + + adapter.simple_update("increment_user_posts","users","posts = posts + ?","uid = ?") + + adapter.simple_update("increment_user_bigposts","users","posts = posts + ?, bigposts = bigposts + ?","uid = ?") + + adapter.simple_update("increment_user_megaposts","users","posts = posts + ?, bigposts = bigposts + ?, megaposts = megaposts + ?","uid = ?") + + adapter.simple_update("increment_user_topics","users","topics = topics + ?","uid = ?") + + adapter.simple_update("edit_profile_reply","users_replies","content = ?, parsed_content = ?","rid = ?") + + //delete_forum_stmt, err = db.Prepare("delete from forums where fid = ?") + adapter.simple_update("delete_forum","forums","name= '', active = 0","fid = ?") + + adapter.simple_update("update_forum","forums","name = ?, desc = ?, active = ?, preset = ?","fid = ?") + + adapter.simple_update("update_setting","settings","content = ?","name = ?") + + adapter.simple_update("update_plugin","plugins","active = ?","uname = ?") + + adapter.simple_update("update_theme","themes","default = ?","uname = ?") + + adapter.simple_update("update_user","users","name = ?, email = ?, group = ?","uid = ?") + + adapter.simple_update("update_group_perms","users_groups","permissions = ?","gid = ?") + + adapter.simple_update("update_group_rank","users_groups","is_admin = ?, is_mod = ?, is_banned = ?","gid = ?") + + adapter.simple_update("update_group","users_groups","name = ?, tag = ?","gid = ?") + return nil } diff --git a/query_gen/mysql.go b/query_gen/mysql.go index a678d767..f62b7111 100644 --- a/query_gen/mysql.go +++ b/query_gen/mysql.go @@ -58,6 +58,44 @@ func (adapter *Mysql_Adapter) simple_insert(name string, table string, columns s return nil } +func (adapter *Mysql_Adapter) simple_replace(name string, table string, columns string, fields string) error { + if name == "" { + return errors.New("You need a name for this statement") + } + if table == "" { + return errors.New("You need a name for this table") + } + if len(columns) == 0 { + return errors.New("No columns found for simple_insert") + } + if len(fields) == 0 { + return errors.New("No input data found for simple_insert") + } + + var querystr string = "REPLACE INTO `" + table + "`(" + + // Escape the column names, just in case we've used a reserved keyword + for _, column := range _process_columns(columns) { + if column.Type == "function" { + querystr += column.Left + "," + } else { + querystr += "`" + column.Left + "`," + } + } + + // Remove the trailing comma + querystr = querystr[0:len(querystr) - 1] + + querystr += ") VALUES (" + for _, field := range _process_fields(fields) { + querystr += field.Name + "," + } + querystr = querystr[0:len(querystr) - 1] + + adapter.write_statement(name,querystr + ")") + return nil +} + func (adapter *Mysql_Adapter) simple_update(name string, table string, set string, where string) error { if name == "" { return errors.New("You need a name for this statement") diff --git a/routes.go b/routes.go index 6036a0a7..4d7caef0 100644 --- a/routes.go +++ b/routes.go @@ -3,7 +3,7 @@ package main import ( "log" -// "fmt" + "fmt" "strconv" "bytes" "regexp" @@ -705,12 +705,12 @@ func route_create_reply(w http.ResponseWriter, r *http.Request) { return } - _, err = add_replies_to_topic_stmt.Exec(1, tid) + _, err = add_replies_to_topic_stmt.Exec(1,tid) if err != nil { InternalError(err,w,r) return } - _, err = update_forum_cache_stmt.Exec(topic_name, tid, user.Name, user.ID, 1) + _, err = update_forum_cache_stmt.Exec(topic_name,tid,user.Name,user.ID,1) if err != nil { InternalError(err,w,r) return @@ -783,6 +783,11 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { return } + if createdBy == user.ID { + LocalError("You can't like your own topics",w,r,user) + return + } + err = has_liked_topic_stmt.QueryRow(user.ID, tid).Scan(&tid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) @@ -801,7 +806,6 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { return } - //score := words_to_score(words,true) score := 1 _, err = create_like_stmt.Exec(score,tid,"topics",user.ID) if err != nil { @@ -826,17 +830,15 @@ func route_like_topic(w http.ResponseWriter, r *http.Request) { return } - /*_, err = notify_watchers_stmt.Exec(lastId) - if err != nil { - InternalError(err,w,r) - return - }*/ _, err = notify_one_stmt.Exec(createdBy,lastId) if err != nil { InternalError(err,w,r) return } + // Live alerts, if the poster is online and WebSockets is enabled + _ = ws_hub.push_alert(createdBy,"like","topic",user.ID,createdBy,tid) + // Reload the topic... err = topics.Load(tid) if err != nil && err != sql.ErrNoRows { @@ -892,6 +894,11 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } + if createdBy == user.ID { + LocalError("You can't like your own replies",w,r,user) + return + } + err = has_liked_reply_stmt.QueryRow(user.ID, rid).Scan(&rid) if err != nil && err != sql.ErrNoRows { InternalError(err,w,r) @@ -910,7 +917,6 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } - //score := words_to_score(words,false) score := 1 _, err = create_like_stmt.Exec(score,rid,"replies",user.ID) if err != nil { @@ -941,6 +947,13 @@ func route_reply_like_submit(w http.ResponseWriter, r *http.Request) { return } + // Live alerts, if the poster is online and WebSockets is enabled + fmt.Println("Calling push_alert") + err = ws_hub.push_alert(createdBy,"like","post",user.ID,createdBy,rid) + if err != nil { + fmt.Println(err.Error()) + } + http.Redirect(w,r,"/topic/" + strconv.Itoa(tid),http.StatusSeeOther) } @@ -1764,12 +1777,18 @@ func route_api(w http.ResponseWriter, r *http.Request) { return } - var msglist string - var asid, actor_id, targetUser_id int - var event, elementType string - var elementID int - //--- - var targetUser *User + var msglist, event, elementType string + var asid, actor_id, targetUser_id, elementID int + var msgCount int + + err = get_activity_count_by_watcher_stmt.QueryRow(user.ID).Scan(&msgCount) + if err == sql.ErrNoRows { + PreError("Couldn't find the parent topic",w,r) + return + } else if err != nil { + InternalError(err,w,r) + return + } rows, err := get_activity_feed_by_watcher_stmt.Query(user.ID) if err != nil { @@ -1783,116 +1802,12 @@ func route_api(w http.ResponseWriter, r *http.Request) { InternalErrorJS(err,w,r) return } - - actor, err := users.CascadeGet(actor_id) + res, err := build_alert(event, elementType, actor_id, targetUser_id, elementID, user) if err != nil { - LocalErrorJS("Unable to find the actor",w,r) + LocalErrorJS(err.Error(),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)+`","avatar":"`+strings.Replace(actor.Avatar,"/","\\/",-1)+`"},` - 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}{replied to}{topic}" - "{x}{replied to}{your topic}{topic}" - "{x}{created a new topic}{topic}" - */ - - var act, post_act, url, area string - var start_frag, 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(topic.ID) - area = topic.Title - if targetUser_id == user.ID { - post_act = " your post in" - } - default: - LocalErrorJS("Invalid elementType",w,r) - } - - switch(event) { - case "like": - if elementType == "user" { - act = "likes" - end_frag = "" - if targetUser.ID == user.ID { - area = "you" - } - } else { - act = "liked" - } - case "mention": - if elementType == "user" { - act = "mentioned you on" - } else { - act = "mentioned you in" - post_act = "" - } - case "reply": act = "replied to" - } - - msglist += `{"msg":"{0} ` + start_frag + act + post_act + ` {1}` + end_frag + `","sub":["` + actor.Name + `","` + area + `"],"path":"` + url + `","avatar":"` + actor.Avatar + `"},` + msglist += res + "," } err = rows.Err() @@ -1905,8 +1820,8 @@ func route_api(w http.ResponseWriter, r *http.Request) { if len(msglist) != 0 { msglist = msglist[0:len(msglist)-1] } - w.Write([]byte(`{"msgs":[`+msglist+`]}`)) - //fmt.Println(`{"msgs":[`+msglist+`]}`) + w.Write([]byte(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`)) + //fmt.Println(`{"msgs":[` + msglist + `],"msgCount":` + strconv.Itoa(msgCount) + `}`) //case "topics": //case "forums": //case "users": diff --git a/setting.go b/setting.go index a318d8fa..76f28a72 100644 --- a/setting.go +++ b/setting.go @@ -43,7 +43,7 @@ func parseSetting(sname string, scontent string, stype string, constraint string if len(cons) < 2 { return "Invalid constraint! The second field wasn't set!" } - + con1, err := strconv.Atoi(cons[0]) if err != nil { return "Invalid contraint! The constraint field wasn't an integer!" @@ -52,12 +52,12 @@ func parseSetting(sname string, scontent string, stype string, constraint string if err != nil { return "Invalid contraint! The constraint field wasn't an integer!" } - + value, err := strconv.Atoi(scontent) if err != nil { return "Only integers are allowed in this setting x.x\nType mismatch in " + sname } - + if value < con1 || value > con2 { return "Only integers between a certain range are allowed in this setting" } @@ -66,4 +66,4 @@ func parseSetting(sname string, scontent string, stype string, constraint string settings[sname] = scontent } return "" -} \ No newline at end of file +} diff --git a/template_list.go b/template_list.go index ccf1498d..177daeb2 100644 --- a/template_list.go +++ b/template_list.go @@ -40,7 +40,7 @@ var menu_6 []byte = []byte(` `) var menu_7 []byte = []byte(` - {{end}} -