Handle mattermost private messages
This commit is contained in:
parent
78c7d1deae
commit
cf13f2b5af
2 changed files with 131 additions and 75 deletions
|
@ -8,14 +8,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func roomAlias(protocol string, id RoomID) string {
|
func roomAlias(protocol string, id RoomID) string {
|
||||||
id2 := strings.ReplaceAll(string(id), "#", "")
|
return fmt.Sprintf("_ezbr__%s__%s", safeStringForId(string(id)), protocol)
|
||||||
id2 = strings.ReplaceAll(id2, "@", "__")
|
|
||||||
|
|
||||||
return fmt.Sprintf("_ezbr__%s__%s", id2, protocol)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func userMxId(protocol string, id UserID) string {
|
func userMxId(protocol string, id UserID) string {
|
||||||
id2 := strings.ReplaceAll(string(id), "@", "__")
|
return fmt.Sprintf("_ezbr__%s__%s", safeStringForId(string(id)), protocol)
|
||||||
|
}
|
||||||
return fmt.Sprintf("_ezbr__%s__%s", id2, protocol)
|
|
||||||
|
func safeStringForId(in string) string {
|
||||||
|
id2 := strings.ReplaceAll(in, "#", "")
|
||||||
|
id2 = strings.ReplaceAll(id2, "@", "__")
|
||||||
|
id2 = strings.ReplaceAll(id2, ":", "_")
|
||||||
|
return id2
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ import (
|
||||||
_ "os"
|
_ "os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/mattermost/mattermost-server/model"
|
"github.com/mattermost/mattermost-server/model"
|
||||||
"github.com/42wim/matterbridge/matterclient"
|
"github.com/42wim/matterbridge/matterclient"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
|
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
|
||||||
)
|
)
|
||||||
|
@ -24,6 +26,8 @@ type Mattermost struct {
|
||||||
|
|
||||||
conn *matterclient.MMClient
|
conn *matterclient.MMClient
|
||||||
handlerStopChan chan bool
|
handlerStopChan chan bool
|
||||||
|
|
||||||
|
usermap map[string]string // map username to user id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -57,12 +61,18 @@ func (mm *Mattermost) Configure(c Configuration) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notls, err := c.GetBool("no_tls", false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
password, _ := c.GetString("password", "")
|
password, _ := c.GetString("password", "")
|
||||||
token, _ := c.GetString("token", "")
|
token, _ := c.GetString("token", "")
|
||||||
if token != "" {
|
if token != "" {
|
||||||
password = "token=" + token
|
password = "token=" + token
|
||||||
}
|
}
|
||||||
mm.conn = matterclient.New(mm.username, password, mm.team, mm.server)
|
mm.conn = matterclient.New(mm.username, password, mm.team, mm.server)
|
||||||
|
mm.conn.Credentials.NoTLS = notls
|
||||||
err = mm.conn.Login()
|
err = mm.conn.Login()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -139,7 +149,15 @@ func (mm *Mattermost) checkUserId(id UserID) (string, error) {
|
||||||
if len(x) != 2 || x[1] != mm.server {
|
if len(x) != 2 || x[1] != mm.server {
|
||||||
return "", fmt.Errorf("Invalid user ID: %s", id)
|
return "", fmt.Errorf("Invalid user ID: %s", id)
|
||||||
}
|
}
|
||||||
return x[0], nil
|
if user_id, ok := mm.usermap[x[0]]; ok {
|
||||||
|
return user_id, nil
|
||||||
|
}
|
||||||
|
u, resp := mm.conn.Client.GetUserByUsername(x[0], "")
|
||||||
|
if u == nil || resp.Error != nil {
|
||||||
|
return "", fmt.Errorf("Not found: %s (%s)", x[0], resp.Error)
|
||||||
|
}
|
||||||
|
mm.usermap[x[0]] = u.Id
|
||||||
|
return u.Id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mm *Mattermost) SetUserInfo(info *UserInfo) error {
|
func (mm *Mattermost) SetUserInfo(info *UserInfo) error {
|
||||||
|
@ -177,6 +195,11 @@ func (mm *Mattermost) Join(roomId RoomID) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mm *Mattermost) Invite(userId UserID, roomId RoomID) error {
|
func (mm *Mattermost) Invite(userId UserID, roomId RoomID) error {
|
||||||
|
if roomId == "" {
|
||||||
|
_, err := mm.checkUserId(userId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Errorf("Not supported: invite on mattermost")
|
return fmt.Errorf("Not supported: invite on mattermost")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,26 +208,46 @@ func (mm *Mattermost) Leave(roomId RoomID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mm *Mattermost) Send(event *Event) error {
|
func (mm *Mattermost) Send(event *Event) error {
|
||||||
// TODO: actions
|
|
||||||
// TODO: attachements
|
// TODO: attachements
|
||||||
|
// TODO: verify private messages work
|
||||||
|
|
||||||
|
post := &model.Post{
|
||||||
|
Message: event.Text,
|
||||||
|
}
|
||||||
|
if event.Type == EVENT_ACTION {
|
||||||
|
post.Type = "me"
|
||||||
|
}
|
||||||
|
|
||||||
if event.Room != "" {
|
if event.Room != "" {
|
||||||
ch, err := mm.checkRoomId(event.Room)
|
ch, err := mm.checkRoomId(event.Room)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = mm.conn.PostMessage(ch, event.Text, "")
|
post.ChannelId = ch
|
||||||
return err
|
|
||||||
} else if event.Recipient != "" {
|
} else if event.Recipient != "" {
|
||||||
ui, err := mm.checkUserId(event.Recipient)
|
ui, err := mm.checkUserId(event.Recipient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mm.conn.SendDirectMessage(ui, event.Text, "")
|
|
||||||
return nil
|
_, resp := mm.conn.Client.CreateDirectChannel(mm.conn.User.Id, ui)
|
||||||
|
if resp.Error != nil {
|
||||||
|
return resp.Error
|
||||||
|
}
|
||||||
|
channelName := model.GetDMNameFromIds(ui, mm.conn.User.Id)
|
||||||
|
|
||||||
|
err = mm.conn.UpdateChannels()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
post.ChannelId = mm.conn.GetChannelId(channelName, "")
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("Invalid target")
|
return fmt.Errorf("Invalid target")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_, resp := mm.conn.Client.CreatePost(post)
|
||||||
|
return resp.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mm *Mattermost) Close() {
|
func (mm *Mattermost) Close() {
|
||||||
|
@ -217,6 +260,7 @@ func (mm *Mattermost) Close() {
|
||||||
|
|
||||||
func (mm *Mattermost) handleConnected() {
|
func (mm *Mattermost) handleConnected() {
|
||||||
mm.handlerStopChan = make(chan bool)
|
mm.handlerStopChan = make(chan bool)
|
||||||
|
mm.usermap = make(map[string]string)
|
||||||
go mm.handleLoop(mm.conn.MessageChan, mm.handlerStopChan)
|
go mm.handleLoop(mm.conn.MessageChan, mm.handlerStopChan)
|
||||||
|
|
||||||
fmt.Printf("Connected to mattermost\n")
|
fmt.Printf("Connected to mattermost\n")
|
||||||
|
@ -246,69 +290,79 @@ func (mm *Mattermost) handleLoop(msgCh chan *matterclient.Message, quitCh chan b
|
||||||
break
|
break
|
||||||
case msg := <-msgCh:
|
case msg := <-msgCh:
|
||||||
fmt.Printf("Mattermost: %#v\n", msg)
|
fmt.Printf("Mattermost: %#v\n", msg)
|
||||||
if len(strings.Split(msg.Channel, "__")) == 2 {
|
fmt.Printf("Mattermost raw: %#v\n", msg.Raw)
|
||||||
// Private message
|
err := mm.handlePosted(msg.Raw)
|
||||||
ids := strings.Split(msg.Channel, "__")
|
|
||||||
my_id := mm.conn.User.Id
|
|
||||||
var them *model.User
|
|
||||||
if ids[0] == my_id {
|
|
||||||
them = mm.conn.GetUser(ids[1])
|
|
||||||
} else {
|
|
||||||
them = mm.conn.GetUser(ids[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
if them != nil {
|
|
||||||
user := UserID(fmt.Sprintf("%s@%s", them.Username, mm.server))
|
|
||||||
mm.handler.Event(&Event{
|
|
||||||
Author: user,
|
|
||||||
Text: msg.Text,
|
|
||||||
Type: EVENT_MESSAGE,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var room RoomID
|
|
||||||
if msg.Team == "" {
|
|
||||||
room = RoomID(fmt.Sprintf("%s@%s", msg.Channel, mm.server))
|
|
||||||
} else {
|
|
||||||
room = RoomID(fmt.Sprintf("%s@%s@%s", msg.Channel, msg.Team, mm.server))
|
|
||||||
}
|
|
||||||
_, err := mm.checkRoomId(room)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Could not find channel: %s %s\n", msg.Channel, msg.Team)
|
log.Warnf("Mattermost error: %s", err)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
user := UserID(fmt.Sprintf("%s@%s", msg.Username, mm.server))
|
|
||||||
|
|
||||||
if strings.Contains(msg.Text, "updated the channel header") {
|
|
||||||
splits := strings.SplitN(msg.Text, "to: ", 2)
|
|
||||||
if len(splits) == 2 {
|
|
||||||
if user == mm.User() {
|
|
||||||
user = UserID("")
|
|
||||||
}
|
|
||||||
mm.handler.RoomInfoUpdated(room, user, &RoomInfo{
|
|
||||||
Topic: splits[1],
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if user == mm.User() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// TODO don't join everytime
|
|
||||||
mm.handler.Event(&Event{
|
|
||||||
Author: user,
|
|
||||||
Room: room,
|
|
||||||
Type: EVENT_JOIN,
|
|
||||||
})
|
|
||||||
mm.handler.Event(&Event{
|
|
||||||
Author: user,
|
|
||||||
Room: room,
|
|
||||||
Text: msg.Text,
|
|
||||||
Type: EVENT_MESSAGE,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (mm *Mattermost) handlePosted(msg *model.WebSocketEvent) error {
|
||||||
|
channel_name := msg.Data["channel_name"].(string)
|
||||||
|
post_str := msg.Data["post"].(string)
|
||||||
|
var post model.Post
|
||||||
|
err := json.Unmarshal([]byte(post_str), &post)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip self messages
|
||||||
|
if post.UserId == mm.conn.User.Id {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find sending user
|
||||||
|
user := mm.conn.GetUser(post.UserId)
|
||||||
|
if user == nil {
|
||||||
|
return fmt.Errorf("Invalid user")
|
||||||
|
}
|
||||||
|
userId := UserID(fmt.Sprintf("%s@%s", user.Username, mm.server))
|
||||||
|
|
||||||
|
// Build message event
|
||||||
|
msg_ev := &Event{
|
||||||
|
Author: userId,
|
||||||
|
Text: post.Message,
|
||||||
|
Type: EVENT_MESSAGE,
|
||||||
|
}
|
||||||
|
if post.Type == "me" {
|
||||||
|
msg_ev.Type = EVENT_ACTION
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch as PM or as room message
|
||||||
|
if len(strings.Split(channel_name, "__")) == 2 {
|
||||||
|
// Private message, no need to find room id
|
||||||
|
if user.Id == mm.conn.User.Id {
|
||||||
|
// Skip self sent messages
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
mm.handler.Event(msg_ev)
|
||||||
|
} else {
|
||||||
|
roomId := mm.reverseRoomId(post.ChannelId)
|
||||||
|
if roomId == "" {
|
||||||
|
return fmt.Errorf("Invalid channel id")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO don't join everytime
|
||||||
|
mm.handler.Event(&Event{
|
||||||
|
Author: userId,
|
||||||
|
Room: roomId,
|
||||||
|
Type: EVENT_JOIN,
|
||||||
|
})
|
||||||
|
|
||||||
|
if post.Type == "system_header_change" {
|
||||||
|
new_header := post.Props["new_header"].(string)
|
||||||
|
mm.handler.RoomInfoUpdated(roomId, userId, &RoomInfo{
|
||||||
|
Topic: new_header,
|
||||||
|
})
|
||||||
|
} else if post.Type == "" || post.Type == "me" {
|
||||||
|
msg_ev.Room = roomId
|
||||||
|
mm.handler.Event(msg_ev)
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("Unhandled post type: %s", post.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue