2020-02-17 22:17:13 +00:00
|
|
|
package mattermost
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
_ "os"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/mattermost/mattermost-server/model"
|
|
|
|
"github.com/42wim/matterbridge/matterclient"
|
|
|
|
|
|
|
|
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
|
|
|
|
)
|
|
|
|
|
|
|
|
// User id format: nickname@server
|
|
|
|
// Room id format: room_name@team@server
|
|
|
|
|
|
|
|
type Mattermost struct {
|
|
|
|
handler Handler
|
|
|
|
|
|
|
|
server string
|
|
|
|
username string
|
|
|
|
team string
|
|
|
|
|
|
|
|
conn *matterclient.MMClient
|
|
|
|
handlerStopChan chan bool
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (mm *Mattermost) SetHandler(h Handler) {
|
|
|
|
mm.handler = h
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Protocol() string {
|
|
|
|
return "mattermost"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Configure(c Configuration) error {
|
|
|
|
if mm.conn != nil {
|
|
|
|
mm.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
mm.server, err = c.GetString("server")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
mm.username, err = c.GetString("username")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
mm.team, err = c.GetString("team")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
password, _ := c.GetString("password", "")
|
|
|
|
token, _ := c.GetString("token", "")
|
|
|
|
if token != "" {
|
|
|
|
password = "token=" + token
|
|
|
|
}
|
|
|
|
mm.conn = matterclient.New(mm.username, password, mm.team, mm.server)
|
|
|
|
err = mm.conn.Login()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
go mm.conn.WsReceiver()
|
|
|
|
go mm.conn.StatusLoop()
|
|
|
|
|
|
|
|
fmt.Printf("CLIENT4: %#v\n", mm.conn.Client)
|
|
|
|
|
|
|
|
for i := 0; i < 42; i++ {
|
|
|
|
time.Sleep(time.Duration(1) * time.Second)
|
|
|
|
if mm.conn.WsConnected {
|
|
|
|
mm.handleConnected()
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return fmt.Errorf("Failed to connect after 42s attempting")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) User() UserID {
|
|
|
|
return UserID(mm.username + "@" + mm.server)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) getTeamIdByName(name string) string {
|
|
|
|
for _, team := range mm.conn.OtherTeams {
|
|
|
|
if team.Team.Name == name {
|
|
|
|
return team.Id
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) checkRoomId(id RoomID) (string, error) {
|
|
|
|
x := strings.Split(string(id), "@")
|
|
|
|
if len(x) == 1 {
|
|
|
|
return "", fmt.Errorf("Please write whole room ID with team and server: %s@%s@%s", id, mm.team, mm.server)
|
|
|
|
}
|
|
|
|
if len(x) == 2 {
|
|
|
|
return x[0], nil
|
|
|
|
}
|
|
|
|
if len(x) != 3 || x[2] != mm.server {
|
|
|
|
return "", fmt.Errorf("Invalid room ID: %s", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
team_id := mm.getTeamIdByName(x[1])
|
|
|
|
if team_id == "" {
|
|
|
|
return "", fmt.Errorf("Team not found: %s", id)
|
|
|
|
}
|
|
|
|
|
|
|
|
ch_id := mm.conn.GetChannelId(x[0], team_id)
|
|
|
|
if ch_id == "" {
|
|
|
|
return "", fmt.Errorf("Channel not found: %s", id)
|
|
|
|
}
|
|
|
|
return ch_id, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) reverseRoomId(id string) RoomID {
|
|
|
|
team := mm.conn.GetChannelTeamId(id)
|
|
|
|
if team == "" {
|
|
|
|
return RoomID(fmt.Sprintf("%s@%s", id, mm.server))
|
|
|
|
} else {
|
|
|
|
teamName := mm.conn.GetTeamName(team)
|
|
|
|
name := mm.conn.GetChannelName(id)
|
|
|
|
fmt.Printf("CHANNEL NAME: %s TEAM: %s\n", name, teamName)
|
|
|
|
return RoomID(fmt.Sprintf("%s@%s@%s", name, teamName, mm.server))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) checkUserId(id UserID) (string, error) {
|
|
|
|
x := strings.Split(string(id), "@")
|
|
|
|
if len(x) == 1 {
|
|
|
|
return "", fmt.Errorf("Please write whole user ID with server: %s@%s", id, mm.server)
|
|
|
|
}
|
|
|
|
if len(x) != 2 || x[1] != mm.server {
|
|
|
|
return "", fmt.Errorf("Invalid user ID: %s", id)
|
|
|
|
}
|
|
|
|
return x[0], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) SetUserInfo(info *UserInfo) error {
|
|
|
|
return fmt.Errorf("Not implemented")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) SetRoomInfo(roomId RoomID, info *RoomInfo) error {
|
|
|
|
ch, err := mm.checkRoomId(roomId)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.Topic != "" {
|
|
|
|
mm.conn.UpdateChannelHeader(ch, info.Topic)
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.Picture != nil {
|
|
|
|
err = fmt.Errorf("Not supported: channel picture on mattermost")
|
|
|
|
}
|
|
|
|
|
|
|
|
if info.Name != "" {
|
|
|
|
err = fmt.Errorf("Not supported: channel name on mattermost")
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Join(roomId RoomID) error {
|
|
|
|
ch, err := mm.checkRoomId(roomId)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return mm.conn.JoinChannel(ch)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Invite(userId UserID, roomId RoomID) error {
|
|
|
|
return fmt.Errorf("Not supported: invite on mattermost")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Leave(roomId RoomID) {
|
|
|
|
// Not supported? TODO
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Send(event *Event) error {
|
|
|
|
// TODO: actions
|
|
|
|
// TODO: attachements
|
|
|
|
|
|
|
|
if event.Room != "" {
|
|
|
|
ch, err := mm.checkRoomId(event.Room)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
_, err = mm.conn.PostMessage(ch, event.Text, "")
|
|
|
|
return err
|
|
|
|
} else if event.Recipient != "" {
|
|
|
|
ui, err := mm.checkUserId(event.Recipient)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
mm.conn.SendDirectMessage(ui, event.Text, "")
|
|
|
|
return nil
|
|
|
|
} else {
|
|
|
|
return fmt.Errorf("Invalid target")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) Close() {
|
|
|
|
mm.conn.WsQuit = true
|
|
|
|
if mm.handlerStopChan != nil {
|
|
|
|
mm.handlerStopChan <- true
|
|
|
|
mm.handlerStopChan = nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) handleConnected() {
|
|
|
|
mm.handlerStopChan = make(chan bool)
|
|
|
|
go mm.handleLoop(mm.conn.MessageChan, mm.handlerStopChan)
|
|
|
|
|
|
|
|
fmt.Printf("Connected to mattermost\n")
|
|
|
|
|
|
|
|
chans := mm.conn.GetChannels()
|
|
|
|
for _, ch := range chans {
|
|
|
|
if len(strings.Split(ch.Name, "__")) == 2 {
|
|
|
|
continue // This is a DM channel
|
|
|
|
}
|
|
|
|
id := mm.reverseRoomId(ch.Id)
|
|
|
|
chName := ch.DisplayName
|
|
|
|
if teamName := mm.conn.GetTeamName(ch.TeamId); teamName != "" {
|
|
|
|
chName = teamName + " / " + chName
|
|
|
|
}
|
|
|
|
mm.handler.Joined(id)
|
|
|
|
mm.handler.RoomInfoUpdated(id, UserID(""), &RoomInfo{
|
|
|
|
Name: chName,
|
|
|
|
Topic: ch.Header,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mm *Mattermost) handleLoop(msgCh chan *matterclient.Message, quitCh chan bool) {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-quitCh:
|
|
|
|
break
|
|
|
|
case msg := <-msgCh:
|
2020-02-18 15:14:31 +00:00
|
|
|
fmt.Printf("Mattermost: %#v\n", msg)
|
2020-02-17 22:17:13 +00:00
|
|
|
if len(strings.Split(msg.Channel, "__")) == 2 {
|
|
|
|
// Private message
|
|
|
|
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 {
|
|
|
|
fmt.Printf("Could not find channel: %s %s\n", msg.Channel, msg.Team)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
user := UserID(fmt.Sprintf("%s@%s", msg.Username, mm.server))
|
2020-02-18 15:14:31 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-17 22:17:13 +00:00
|
|
|
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,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|