From 9cb169ddde129c8064fe83a834a13538b430b35b Mon Sep 17 00:00:00 2001 From: Haw Loeung Date: Sat, 22 Apr 2023 19:25:34 +1000 Subject: [PATCH] Add support for searching scrollback for specific posts/threads --- bridge/bridge.go | 1 + bridge/mastodon/mastodon.go | 4 + bridge/mattermost/mattermost.go | 4 + bridge/slack/slack.go | 4 + mm-go-irckit/service.go | 116 +++++++++++------- .../matterbridge/matterclient/messages.go | 21 +++- 6 files changed, 105 insertions(+), 45 deletions(-) diff --git a/bridge/bridge.go b/bridge/bridge.go index 46c5ce9d..cda5c5a4 100644 --- a/bridge/bridge.go +++ b/bridge/bridge.go @@ -51,6 +51,7 @@ type Bridger interface { GetPostsSince(channelID string, since int64) interface{} GetPosts(channelID string, limit int) interface{} + GetPostThread(postID string) interface{} SearchPosts(search string) interface{} ModifyPost(msgID, text string) error GetFileLinks(fileIDs []string) []string diff --git a/bridge/mastodon/mastodon.go b/bridge/mastodon/mastodon.go index 68dfbb17..71682fcb 100644 --- a/bridge/mastodon/mastodon.go +++ b/bridge/mastodon/mastodon.go @@ -202,6 +202,10 @@ func (m *Mastodon) GetPosts(channelID string, limit int) interface{} { return nil } +func (m *Mastodon) GetPostThread(postID string) interface{} { + return nil +} + func (m *Mastodon) GetChannelID(name, teamID string) string { return "" } diff --git a/bridge/mattermost/mattermost.go b/bridge/mattermost/mattermost.go index 7079f9b6..fb0aa894 100644 --- a/bridge/mattermost/mattermost.go +++ b/bridge/mattermost/mattermost.go @@ -1426,6 +1426,10 @@ func (m *Mattermost) GetPosts(channelID string, limit int) interface{} { return m.mc.GetPosts(channelID, limit) } +func (m *Mattermost) GetPostThread(postID string) interface{} { + return m.mc.GetPostThread(postID) +} + func (m *Mattermost) GetChannelID(name, teamID string) string { return m.mc.GetChannelID(name, teamID) } diff --git a/bridge/slack/slack.go b/bridge/slack/slack.go index 8fd8ff07..6b240d05 100644 --- a/bridge/slack/slack.go +++ b/bridge/slack/slack.go @@ -425,6 +425,10 @@ func (s *Slack) GetPosts(channelID string, limit int) interface{} { return nil } +func (s *Slack) GetPostThread(channelID string) interface{} { + return nil +} + func (s *Slack) GetChannelID(name, teamID string) string { return "" } diff --git a/mm-go-irckit/service.go b/mm-go-irckit/service.go index 4acceaa0..f8fc341a 100644 --- a/mm-go-irckit/service.go +++ b/mm-go-irckit/service.go @@ -272,6 +272,22 @@ func searchUsers(u *User, toUser *User, args []string, service string) { } } +func getChannelName(u *User, channelID string) string { + channelName := u.br.GetChannelName(channelID) + channelMembers := strings.Split(channelName, "__") + + logger.Warnf("HAW channelmembers: %d: %s (%s)", len(channelMembers), channelMembers, channelName) + + if len(channelMembers) != 2 { + return fmt.Sprintf("#%s", channelName) + } + + if channelMembers[0] == u.br.GetMe().User { + return channelMembers[1] + } + return channelMembers[0] +} + //nolint:funlen,gocognit,gocyclo,cyclop func scrollback(u *User, toUser *User, args []string, service string) { if service == "slack" { @@ -280,27 +296,26 @@ func scrollback(u *User, toUser *User, args []string, service string) { } if len(args) != 2 { - u.MsgUser(toUser, "need SCROLLBACK (#|) ") + u.MsgUser(toUser, "need SCROLLBACK (#||) ") u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)") return } + search := args[0] limit, err := strconv.Atoi(args[1]) if err != nil { - u.MsgUser(toUser, "need SCROLLBACK (#|) ") + u.MsgUser(toUser, "need SCROLLBACK (#||) ") u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)") return } - var channelID string - var spoof func(string, string, ...int) - scrollbackUser, exists := u.Srv.HasUser(args[0]) + var channelID, searchPostID string + scrollbackUser, exists := u.Srv.HasUser(search) switch { - case strings.HasPrefix(args[0], "#"): - channelName := strings.ReplaceAll(args[0], "#", "") + case strings.HasPrefix(search, "#"): + channelName := strings.ReplaceAll(search, "#", "") channelID = u.br.GetChannelID(channelName, u.br.GetMe().TeamID) - spoof = u.Srv.Channel(channelID).SpoofMessage case exists && scrollbackUser.Ghost: // We need to sort the two user IDs to construct the DM // channel name. @@ -308,13 +323,20 @@ func scrollback(u *User, toUser *User, args []string, service string) { sort.Strings(userIDs) channelName := userIDs[0] + "__" + userIDs[1] channelID = u.br.GetChannelID(channelName, u.br.GetMe().TeamID) + case len(search) == 26: + searchPostID = search default: - u.MsgUser(toUser, "need SCROLLBACK (#|) ") + u.MsgUser(toUser, "need SCROLLBACK (#||) ") u.MsgUser(toUser, "e.g. SCROLLBACK #bugs 10 (show last 10 lines from #bugs)") return } - list := u.br.GetPosts(channelID, limit) + var list interface{} + if searchPostID != "" { + list = u.br.GetPostThread(searchPostID) + } else { + list = u.br.GetPosts(channelID, limit) + } if list == nil || list.(*model.PostList) == nil || len(list.(*model.PostList).Order) == 0 { u.MsgUser(toUser, "no results") return @@ -323,8 +345,11 @@ func scrollback(u *User, toUser *User, args []string, service string) { postlist, _ := list.(*model.PostList) for i := len(postlist.Order) - 1; i >= 0; i-- { + if limit != 0 && len(postlist.Order) > limit && i < len(postlist.Order)-limit { + continue + } + p := postlist.Posts[postlist.Order[i]] - ts := time.Unix(0, p.CreateAt*int64(time.Millisecond)) props := p.GetProps() botname, override := props["override_username"].(string) @@ -338,23 +363,22 @@ func scrollback(u *User, toUser *User, args []string, service string) { nick = "system" } - for _, post := range strings.Split(p.Message, "\n") { - switch { // nolint:dupl - case (u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post") && strings.HasPrefix(args[0], "#") && nick != "system": - threadMsgID := u.prefixContext("", p.Id, p.RootId, "") - scrollbackMsg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, post) - spoof(nick, scrollbackMsg) - case strings.HasPrefix(args[0], "#"): - scrollbackMsg := "[" + ts.Format("2006-01-02 15:04") + "] " + post - spoof(nick, scrollbackMsg) - case u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post": - threadMsgID := u.prefixContext("", p.Id, p.RootId, "") - scrollbackMsg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, post) - u.MsgSpoofUser(scrollbackUser, nick, scrollbackMsg) - default: - scrollbackMsg := "[" + ts.Format("2006-01-02 15:04") + "]" + " <" + nick + "> " + post - u.MsgSpoofUser(scrollbackUser, nick, scrollbackMsg) + if searchPostID != "" && channelID == "" { + channelID = p.ChannelId + search = getChannelName(u, p.ChannelId) + if !strings.HasPrefix(search, "#") { + user := u.br.GetUser(search) + search = user.Nick + if override { + search = botname + } + scrollbackUser, _ = u.Srv.HasUser(search) } + logger.Warnf("HAW: %s: %s", p.ChannelId, search) + } + + for _, post := range strings.Split(p.Message, "\n") { + formatScrollbackMsg(u, channelID, search, scrollbackUser, nick, p, post) } if len(p.FileIds) == 0 { @@ -363,26 +387,32 @@ func scrollback(u *User, toUser *User, args []string, service string) { for _, fname := range u.br.GetFileLinks(p.FileIds) { fileMsg := "download file - " + fname - switch { // nolint:dupl - case (u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post") && strings.HasPrefix(args[0], "#"): - threadMsgID := u.prefixContext("", p.Id, p.RootId, "") - scrollbackMsg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, fileMsg) - spoof(nick, scrollbackMsg) - case u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post": - threadMsgID := u.prefixContext("", p.Id, p.RootId, "") - scrollbackMsg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, fileMsg) - u.MsgSpoofUser(scrollbackUser, nick, scrollbackMsg) - case strings.HasPrefix(args[0], "#"): - scrollbackMsg := "[" + ts.Format("2006-01-02 15:04") + "] " + fileMsg - spoof(nick, scrollbackMsg) - default: - scrollbackMsg := "[" + ts.Format("2006-01-02 15:04") + "]" + " <" + nick + "> " + fileMsg - u.MsgSpoofUser(scrollbackUser, nick, scrollbackMsg) - } + formatScrollbackMsg(u, channelID, search, scrollbackUser, nick, p, fileMsg) } } } +func formatScrollbackMsg(u *User, channelID string, channel string, user *User, nick string, p *model.Post, msgText string) { + ts := time.Unix(0, p.CreateAt*int64(time.Millisecond)) + + switch { + case (u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post") && strings.HasPrefix(channel, "#") && nick != "system": //nolint:goconst + threadMsgID := u.prefixContext("", p.Id, p.RootId, "") + msg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, msgText) + u.Srv.Channel(channelID).SpoofMessage(nick, msg) + case strings.HasPrefix(channel, "#"): + msg := "[" + ts.Format("2006-01-02 15:04") + "] " + msgText + u.Srv.Channel(channelID).SpoofMessage(nick, msg) + case u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost" || u.v.GetString(u.br.Protocol()+".threadcontext") == "mattermost+post": + threadMsgID := u.prefixContext("", p.Id, p.RootId, "") + msg := u.formatContextMessage(ts.Format("2006-01-02 15:04"), threadMsgID, msgText) + u.MsgSpoofUser(user, nick, msg) + default: + msg := "[" + ts.Format("2006-01-02 15:04") + "]" + " <" + nick + "> " + msgText + u.MsgSpoofUser(user, nick, msg) + } +} + func updatelastviewed(u *User, toUser *User, args []string, service string) { if service == "slack" { u.MsgUser(toUser, "not implemented") diff --git a/vendor/github.com/matterbridge/matterclient/messages.go b/vendor/github.com/matterbridge/matterclient/messages.go index 60363285..e44061ba 100644 --- a/vendor/github.com/matterbridge/matterclient/messages.go +++ b/vendor/github.com/matterbridge/matterclient/messages.go @@ -58,7 +58,7 @@ func (m *Client) GetFileLinks(filenames []string) []string { func (m *Client) GetPosts(channelID string, limit int) *model.PostList { for { - res, resp, err := m.Client.GetPostsForChannel(channelID, 0, limit, "", true) + res, resp, err := m.Client.GetPostsForChannel(channelID, 0, limit, "", false) if err == nil { return res } @@ -69,9 +69,26 @@ func (m *Client) GetPosts(channelID string, limit int) *model.PostList { } } +func (m *Client) GetPostThread(postID string) *model.PostList { + opts := model.GetPostsOptions{ + CollapsedThreads: false, + Direction: "up", + } + for { + res, resp, err := m.Client.GetPostThreadWithOpts(postID, "", opts) + if err == nil { + return res + } + + if err := m.HandleRatelimit("GetPostThread", resp); err != nil { + return nil + } + } +} + func (m *Client) GetPostsSince(channelID string, time int64) *model.PostList { for { - res, resp, err := m.Client.GetPostsSince(channelID, time, true) + res, resp, err := m.Client.GetPostsSince(channelID, time, false) if err == nil { return res }