From 83391fe5c005dd9f0c7a54621ee6d167674d16fe Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Sun, 30 Jul 2023 10:33:04 -0700 Subject: [PATCH] CachedBlocklist support for the chat room --- pkg/controller/chat/chat.go | 57 +++++++++++++++++++++++++++++++++++++ pkg/models/blocklist.go | 44 +++++++++++++++++++++++++++- pkg/models/friend.go | 2 +- 3 files changed, 101 insertions(+), 2 deletions(-) diff --git a/pkg/controller/chat/chat.go b/pkg/controller/chat/chat.go index c275e38..9a1b24f 100644 --- a/pkg/controller/chat/chat.go +++ b/pkg/controller/chat/chat.go @@ -1,12 +1,16 @@ package chat import ( + "bytes" + "encoding/json" "fmt" + "io" "net/http" "strings" "time" "code.nonshy.com/nonshy/website/pkg/config" + "code.nonshy.com/nonshy/website/pkg/log" "code.nonshy.com/nonshy/website/pkg/models" "code.nonshy.com/nonshy/website/pkg/photo" "code.nonshy.com/nonshy/website/pkg/session" @@ -99,6 +103,11 @@ func Landing() http.HandlerFunc { return } + // Send over their blocklist to the chat server. + if err := SendBlocklist(currentUser); err != nil { + log.Error("SendBlocklist: %s", err) + } + // Redirect them to the chat room. templates.Redirect(w, strings.TrimSuffix(chatURL, "/")+"/?jwt="+ss) return @@ -117,3 +126,51 @@ func Landing() http.HandlerFunc { } }) } + +// SendBlocklist syncs the user blocklist to the chat server prior to sending them over. +func SendBlocklist(user *models.User) error { + // Get the user's blocklist. + blockedUsernames := models.BlockedUsernames(user.ID) + log.Info("SendBlocklist(%s) to BareRTC: %d blocked usernames", user.Username, len(blockedUsernames)) + + // API request struct for BareRTC /api/blocklist endpoint. + var request = struct { + APIKey string + Username string + Blocklist []string + }{ + config.Current.CronAPIKey, + user.Username, + blockedUsernames, + } + + // JSON request body. + jsonStr, err := json.Marshal(request) + if err != nil { + return err + } + + // Make the API request to BareRTC. + var url = config.Current.BareRTC.URL + "/api/blocklist" + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{ + Timeout: 10 * time.Second, + } + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + log.Error("SendBlocklist: error syncing blocklist to BareRTC: status %d body %s", resp.StatusCode, body) + } + + return nil +} diff --git a/pkg/models/blocklist.go b/pkg/models/blocklist.go index 144611c..7aabc29 100644 --- a/pkg/models/blocklist.go +++ b/pkg/models/blocklist.go @@ -3,6 +3,7 @@ package models import ( "time" + "code.nonshy.com/nonshy/website/pkg/log" "gorm.io/gorm" ) @@ -91,7 +92,7 @@ func PaginateBlockList(user *User, pager *Pagination) ([]*User, error) { return GetUsers(user, userIDs) } -// BlockedUserIDs returns all user IDs blocked by the user. +// BlockedUserIDs returns all user IDs blocked by the user (bidirectional, source or target user). func BlockedUserIDs(userId uint64) []uint64 { var ( bs = []*Block{} @@ -108,6 +109,47 @@ func BlockedUserIDs(userId uint64) []uint64 { return userIDs } +// BlockedUserIDsByUser returns all user IDs blocked by the user (one directional only) +func BlockedUserIDsByUser(userId uint64) []uint64 { + var ( + bs = []*Block{} + userIDs = []uint64{} + ) + DB.Where("source_user_id = ?", userId).Find(&bs) + for _, row := range bs { + for _, uid := range []uint64{row.TargetUserID, row.SourceUserID} { + if uid != userId { + userIDs = append(userIDs, uid) + } + } + } + return userIDs +} + +// BlockedUsernames returns all usernames blocked by the user. +func BlockedUsernames(userId uint64) []string { + var ( + userIDs = BlockedUserIDsByUser(userId) + usernames = []string{} + ) + + if len(userIDs) == 0 { + return usernames + } + + if res := DB.Table( + "users", + ).Select( + "username", + ).Where( + "id IN ?", userIDs, + ).Scan(&usernames); res.Error != nil { + log.Error("BlockedUsernames(%d): %s", userId, res.Error) + } + + return usernames +} + // UnblockUser removes targetUserID from your blocklist. func UnblockUser(sourceUserID, targetUserID uint64) error { result := DB.Where( diff --git a/pkg/models/friend.go b/pkg/models/friend.go index 2745a1a..6722858 100644 --- a/pkg/models/friend.go +++ b/pkg/models/friend.go @@ -125,7 +125,7 @@ func FriendIDsAreExplicit(userId uint64) []uint64 { ).Scan(&userIDs) if err.Error != nil { - log.Error("SQL error collecting explicit FriendIDs for %d: %s", userId, err) + log.Error("SQL error collecting explicit FriendIDs for %d: %s", userId, err.Error) } return userIDs