Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for searching scrollback for specific posts/threads #533

Merged
merged 2 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bridge/bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions bridge/mastodon/mastodon.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
}
Expand Down
4 changes: 4 additions & 0 deletions bridge/mattermost/mattermost.go
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,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)
}
Expand Down
4 changes: 4 additions & 0 deletions bridge/slack/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 ""
}
Expand Down
134 changes: 89 additions & 45 deletions mm-go-irckit/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,20 @@ func searchUsers(u *User, toUser *User, args []string, service string) {
}
}

func getMattermostChannelName(u *User, channelID string) string {
channelName := u.br.GetChannelName(channelID)
channelMembers := strings.Split(channelName, "__")

if len(channelMembers) != 2 {
return 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" {
Expand All @@ -280,51 +294,75 @@ func scrollback(u *User, toUser *User, args []string, service string) {
}

if len(args) != 2 {
u.MsgUser(toUser, "need SCROLLBACK (#<channel>|<user>) <lines>")
u.MsgUser(toUser, "need SCROLLBACK (#<channel>|<user>|<post/thread ID>) <lines>")
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 (#<channel>|<user>) <lines>")
u.MsgUser(toUser, "need SCROLLBACK (#<channel>|<user>|<post/thread ID>) <lines>")
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.
userIDs := []string{u.User, scrollbackUser.User}
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 (#<channel>|<user>) <lines>")
u.MsgUser(toUser, "need SCROLLBACK (#<channel>|<user>|<post/thread ID>) <lines>")
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
}

postlist, _ := list.(*model.PostList)

for i := len(postlist.Order) - 1; i >= 0; i-- {
p := postlist.Posts[postlist.Order[i]]
ts := time.Unix(0, p.CreateAt*int64(time.Millisecond))
// Workaround https://github.com/mattermost/mattermost-server/issues/23081
plOrder := postlist.Order
if searchPostID != "" {
plOrder = append(plOrder, searchPostID)
}
skipRoot := false

for i := len(plOrder) - 1; i >= 0; i-- {
if limit != 0 && len(plOrder) > limit && i < len(plOrder)-limit {
continue
}

p := postlist.Posts[plOrder[i]]

// Workaround https://github.com/mattermost/mattermost-server/issues/23081
if searchPostID != "" && p.Id == searchPostID {
if skipRoot {
continue
}
skipRoot = true
}

props := p.GetProps()
botname, override := props["override_username"].(string)
Expand All @@ -338,49 +376,55 @@ 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, "scrollback")
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, "scrollback")
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 = getMattermostChannelName(u, p.ChannelId)
if !strings.HasPrefix(search, "#") {
user := u.br.GetUser(search)
search = user.Nick
if override {
search = botname
}
scrollbackUser, _ = u.Srv.HasUser(search)
}
}

for _, post := range strings.Split(p.Message, "\n") {
formatScrollbackMsg(u, channelID, search, scrollbackUser, nick, p, post)
}

if len(p.FileIds) == 0 {
continue
}

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, "scrollback_file")
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, "scrollback_file")
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)
}
}

u.MsgUser(toUser, fmt.Sprintf("scrollback results shown in %s", search))
}

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, "scrollback")
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, "scrollback")
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) {
Expand Down
Loading