package matterclient
import (
"crypto/md5"
"encoding/json"
"fmt"
"strings"
"github.com/mattermost/mattermost-server/v6/model"
)
func (m *Client) parseResponse(rmsg *model.WebSocketResponse) {
m.logger.Debugf("getting response: %#v", rmsg)
}
func (m *Client) DeleteMessage(postID string) error {
_, err := m.Client.DeletePost(postID)
if err != nil {
return err
}
return nil
}
func (m *Client) EditMessage(postID string, text string) (string, error) {
post := &model.Post{Message: text, Id: postID}
res, _, err := m.Client.UpdatePost(postID, post)
if err != nil {
return "", err
}
return res.Id, nil
}
func (m *Client) GetFileLinks(filenames []string) []string {
uriScheme := "https://"
if m.NoTLS {
uriScheme = "http://"
}
var output []string
for _, f := range filenames {
res, _, err := m.Client.GetFileLink(f)
if err != nil {
// public links is probably disabled, create the link ourselves
output = append(output, uriScheme+m.Credentials.Server+model.APIURLSuffix+"/files/"+f)
continue
}
output = append(output, res)
}
return output
}
func (m *Client) GetPosts(channelID string, limit int) *model.PostList {
for {
res, resp, err := m.Client.GetPostsForChannel(channelID, 0, limit, "", true)
if err == nil {
return res
}
if err := m.HandleRatelimit("GetPostsForChannel", 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)
if err == nil {
return res
}
if err := m.HandleRatelimit("GetPostsSince", resp); err != nil {
return nil
}
}
}
func (m *Client) GetPublicLink(filename string) string {
res, _, err := m.Client.GetFileLink(filename)
if err != nil {
return ""
}
return res
}
func (m *Client) GetPublicLinks(filenames []string) []string {
var output []string
for _, f := range filenames {
res, _, err := m.Client.GetFileLink(f)
if err != nil {
continue
}
output = append(output, res)
}
return output
}
func (m *Client) PostMessage(channelID string, text string, rootID string) (string, error) {
post := &model.Post{
ChannelId: channelID,
Message: text,
RootId: rootID,
}
for {
res, resp, err := m.Client.CreatePost(post)
if err == nil {
return res.Id, nil
}
if err := m.HandleRatelimit("CreatePost", resp); err != nil {
return "", err
}
}
}
func (m *Client) PostMessageWithFiles(channelID string, text string, rootID string, fileIds []string) (string, error) {
post := &model.Post{
ChannelId: channelID,
Message: text,
RootId: rootID,
FileIds: fileIds,
}
for {
res, resp, err := m.Client.CreatePost(post)
if err == nil {
return res.Id, nil
}
if err := m.HandleRatelimit("CreatePost", resp); err != nil {
return "", err
}
}
}
func (m *Client) SearchPosts(query string) *model.PostList {
res, _, err := m.Client.SearchPosts(m.Team.ID, query, false)
if err != nil {
return nil
}
return res
}
// SendDirectMessage sends a direct message to specified user
func (m *Client) SendDirectMessage(toUserID string, msg string, rootID string) error {
return m.SendDirectMessageProps(toUserID, msg, rootID, nil)
}
func (m *Client) SendDirectMessageProps(toUserID string, msg string, rootID string, props map[string]interface{}) error {
m.logger.Debugf("SendDirectMessage to %s, msg %s", toUserID, msg)
for {
// create DM channel (only happens on first message)
_, resp, err := m.Client.CreateDirectChannel(m.User.Id, toUserID)
if err == nil {
break
}
if err := m.HandleRatelimit("CreateDirectChannel", resp); err != nil {
m.logger.Debugf("SendDirectMessage to %#v failed: %s", toUserID, err)
return err
}
}
channelName := model.GetDMNameFromIds(toUserID, m.User.Id)
// update our channels
if err := m.UpdateChannels(); err != nil {
m.logger.Errorf("failed to update channels: %#v", err)
}
// build & send the message
msg = strings.ReplaceAll(msg, "\r", "")
post := &model.Post{
ChannelId: m.GetChannelID(channelName, m.Team.ID),
Message: msg,
RootId: rootID,
}
post.SetProps(props)
for {
_, resp, err := m.Client.CreatePost(post)
if err == nil {
return nil
}
if err := m.HandleRatelimit("CreatePost", resp); err != nil {
return err
}
}
}
func (m *Client) UploadFile(data []byte, channelID string, filename string) (string, error) {
f, _, err := m.Client.UploadFile(data, channelID, filename)
if err != nil {
return "", err
}
return f.FileInfos[0].Id, nil
}
func (m *Client) parseActionPost(rmsg *Message) {
// add post to cache, if it already exists don't relay this again.
// this should fix reposts
if ok, _ := m.lruCache.ContainsOrAdd(digestString(rmsg.Raw.GetData()["post"].(string)), true); ok && rmsg.Raw.EventType() != model.WebsocketEventPostDeleted {
m.logger.Debugf("message %#v in cache, not processing again", rmsg.Raw.GetData()["post"].(string))
rmsg.Text = ""
return
}
var data model.Post
if err := json.NewDecoder(strings.NewReader(rmsg.Raw.GetData()["post"].(string))).Decode(&data); err != nil {
return
}
// we don't have the user, refresh the userlist
if m.GetUser(data.UserId) == nil {
m.logger.Infof("User '%v' is not known, ignoring message '%#v'",
data.UserId, data)
return
}
rmsg.Username = m.GetUserName(data.UserId)
rmsg.Channel = m.GetChannelName(data.ChannelId)
rmsg.UserID = data.UserId
rmsg.Type = data.Type
teamid, _ := rmsg.Raw.GetData()["team_id"].(string)
// edit messsages have no team_id for some reason
if teamid == "" {
// we can find the team_id from the channelid
teamid = m.GetChannelTeamID(data.ChannelId)
rmsg.Raw.GetData()["team_id"] = teamid
}
if teamid != "" {
rmsg.Team = m.GetTeamName(teamid)
}
// direct message
if rmsg.Raw.GetData()["channel_type"] == "D" {
rmsg.Channel = m.GetUser(data.UserId).Username
}
rmsg.Text = data.Message
rmsg.Post = &data
}
func (m *Client) parseMessage(rmsg *Message) {
switch rmsg.Raw.EventType() {
case model.WebsocketEventPosted, model.WebsocketEventPostEdited, model.WebsocketEventPostDeleted:
m.parseActionPost(rmsg)
case "user_updated":
if user, ok := rmsg.Raw.GetData()["user"].(*model.User); ok {
m.UpdateUser(user.Id)
}
case "group_added":
if err := m.UpdateChannels(); err != nil {
m.logger.Errorf("failed to update channels: %#v", err)
}
}
}
func digestString(s string) string {
return fmt.Sprintf("%x", md5.Sum([]byte(s))) //nolint:gosec
}