This commit is contained in:
Alex 2020-02-23 20:24:50 +01:00
parent 0f6be9663e
commit ec9bc9b752
10 changed files with 95 additions and 96 deletions

View File

@ -286,24 +286,24 @@ func (a *Account) eventInternal(event *Event) error {
if err != nil { if err != nil {
return err return err
} }
content := map[string]interface{} { content := map[string]interface{}{
"body": mxfile.Filename(), "body": mxfile.Filename(),
"filename": mxfile.Filename(), "filename": mxfile.Filename(),
"url": fmt.Sprintf("mxc://%s/%s", mxfile.MxcServer, mxfile.MxcMediaId), "url": fmt.Sprintf("mxc://%s/%s", mxfile.MxcServer, mxfile.MxcMediaId),
} }
if sz := mxfile.ImageSize(); sz != nil { if sz := mxfile.ImageSize(); sz != nil {
content["msgtype"] = "m.image" content["msgtype"] = "m.image"
content["info"] = map[string]interface{} { content["info"] = map[string]interface{}{
"mimetype": mxfile.Mimetype(), "mimetype": mxfile.Mimetype(),
"size": mxfile.Size(), "size": mxfile.Size(),
"w": sz.Width, "w": sz.Width,
"h": sz.Height, "h": sz.Height,
} }
} else { } else {
content["msgtype"] = "m.file" content["msgtype"] = "m.file"
content["info"] = map[string]interface{} { content["info"] = map[string]interface{}{
"mimetype": mxfile.Mimetype(), "mimetype": mxfile.Mimetype(),
"size": mxfile.Size(), "size": mxfile.Size(),
} }
} }
err = mx.SendAs(mx_room_id, "m.room.message", content, mx_user_id) err = mx.SendAs(mx_room_id, "m.room.message", content, mx_user_id)

View File

@ -41,7 +41,7 @@ func InitDb() error {
type DbCache struct { type DbCache struct {
gorm.Model gorm.Model
Key string `gorm:"unique_index"` Key string `gorm:"unique_index"`
Value string Value string
} }

View File

@ -136,12 +136,12 @@ type UserInfo struct {
// If non-empty, the Filename of the avatar object will be used by Easybridge // If non-empty, the Filename of the avatar object will be used by Easybridge
// to deduplicate the update events and prevent needless reuploads. // to deduplicate the update events and prevent needless reuploads.
// Example strategy that works for the mattermost backend: use the update timestamp as fictious file name // Example strategy that works for the mattermost backend: use the update timestamp as fictious file name
Avatar MediaObject Avatar MediaObject
} }
type RoomInfo struct { type RoomInfo struct {
Name string Name string
Topic string Topic string
// Same deduplication comment as for UserInfo.Avatar // Same deduplication comment as for UserInfo.Avatar
Picture MediaObject Picture MediaObject
@ -164,6 +164,6 @@ type MediaObject interface {
} }
type ImageSize struct { type ImageSize struct {
Width int Width int
Height int Height int
} }

View File

@ -1,16 +1,16 @@
package mattermost package mattermost
import ( import (
"net/http" "encoding/json"
"fmt" "fmt"
"io/ioutil"
"net/http"
_ "os" _ "os"
"strings" "strings"
"time" "time"
"io/ioutil"
"encoding/json"
"github.com/mattermost/mattermost-server/model"
"github.com/42wim/matterbridge/matterclient" "github.com/42wim/matterbridge/matterclient"
"github.com/mattermost/mattermost-server/model"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" . "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
@ -22,19 +22,18 @@ import (
type Mattermost struct { type Mattermost struct {
handler Handler handler Handler
server string server string
username string username string
teams map[string]bool teams map[string]bool
conn *matterclient.MMClient conn *matterclient.MMClient
handlerStopChan chan bool handlerStopChan chan bool
usermap map[string]string // map username to mm user id usermap map[string]string // map username to mm user id
sentjoinedmap map[string]bool // map username/room name to bool sentjoinedmap map[string]bool // map username/room name to bool
userdisplaynamemap map[UserID]string // map username to last displayname userdisplaynamemap map[UserID]string // map username to last displayname
} }
func (mm *Mattermost) SetHandler(h Handler) { func (mm *Mattermost) SetHandler(h Handler) {
mm.handler = h mm.handler = h
} }
@ -318,7 +317,7 @@ func (mm *Mattermost) handleConnected() {
// Update room info // Update room info
room_info := &RoomInfo{ room_info := &RoomInfo{
Name: ch.DisplayName, Name: ch.DisplayName,
Topic: ch.Header, Topic: ch.Header,
} }
for _, t := range mm.conn.OtherTeams { for _, t := range mm.conn.OtherTeams {
@ -446,8 +445,8 @@ func (mm *Mattermost) ensureJoined(user *model.User, roomId RoomID) {
if _, ok := mm.sentjoinedmap[cache_key]; !ok { if _, ok := mm.sentjoinedmap[cache_key]; !ok {
mm.handler.Event(&Event{ mm.handler.Event(&Event{
Author: userId, Author: userId,
Room: roomId, Room: roomId,
Type: EVENT_JOIN, Type: EVENT_JOIN,
}) })
mm.sentjoinedmap[cache_key] = true mm.sentjoinedmap[cache_key] = true
} }
@ -484,10 +483,10 @@ func (mm *Mattermost) handlePost(channel_name string, post *model.Post, only_mes
// Build message event // Build message event
msg_ev := &Event{ msg_ev := &Event{
Id: post.Id, Id: post.Id,
Author: userId, Author: userId,
Text: post.Message, Text: post.Message,
Type: EVENT_MESSAGE, Type: EVENT_MESSAGE,
} }
if post.Type == "me" { if post.Type == "me" {
msg_ev.Type = EVENT_ACTION msg_ev.Type = EVENT_ACTION
@ -511,7 +510,7 @@ func (mm *Mattermost) handlePost(channel_name string, post *model.Post, only_mes
} }
if file.Width > 0 { if file.Width > 0 {
media_object.ObjectImageSize = &ImageSize{ media_object.ObjectImageSize = &ImageSize{
Width: file.Width, Width: file.Width,
Height: file.Height, Height: file.Height,
} }
} }

View File

@ -58,10 +58,10 @@ func (m *FileMediaObject) URL() string {
// ---- // ----
type UrlMediaObject struct { type UrlMediaObject struct {
ObjectFilename string ObjectFilename string
ObjectSize int64 ObjectSize int64
ObjectMimetype string ObjectMimetype string
ObjectURL string ObjectURL string
ObjectImageSize *ImageSize ObjectImageSize *ImageSize
} }
@ -96,10 +96,10 @@ func (m *UrlMediaObject) URL() string {
// ---- // ----
type BlobMediaObject struct { type BlobMediaObject struct {
ObjectFilename string ObjectFilename string
ObjectMimetype string ObjectMimetype string
ObjectImageSize *ImageSize ObjectImageSize *ImageSize
ObjectData []byte ObjectData []byte
} }
func (m *BlobMediaObject) Filename() string { func (m *BlobMediaObject) Filename() string {
@ -129,6 +129,7 @@ func (m *BlobMediaObject) URL() string {
type nullCloseReader struct { type nullCloseReader struct {
io.Reader io.Reader
} }
func (ncr nullCloseReader) Close() error { func (ncr nullCloseReader) Close() error {
return nil return nil
} }
@ -136,10 +137,10 @@ func (ncr nullCloseReader) Close() error {
// ---- // ----
type LazyBlobMediaObject struct { type LazyBlobMediaObject struct {
ObjectFilename string ObjectFilename string
ObjectMimetype string ObjectMimetype string
ObjectImageSize *ImageSize ObjectImageSize *ImageSize
ObjectData []byte ObjectData []byte
GetFn func(o *LazyBlobMediaObject) error GetFn func(o *LazyBlobMediaObject) error
} }

View File

@ -3,12 +3,12 @@ package xmpp
import ( import (
"time" "time"
//"os" //"os"
"strings"
"fmt"
"crypto/tls" "crypto/tls"
"fmt"
"strings"
log "github.com/sirupsen/logrus"
gxmpp "github.com/mattn/go-xmpp" gxmpp "github.com/mattn/go-xmpp"
log "github.com/sirupsen/logrus"
. "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" . "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
) )
@ -22,16 +22,16 @@ type XMPP struct {
handler Handler handler Handler
connectorLoopNum int connectorLoopNum int
connected bool connected bool
timeout int timeout int
server string server string
port int port int
ssl bool ssl bool
jid string jid string
jid_localpart string jid_localpart string
password string password string
nickname string nickname string
conn *gxmpp.Client conn *gxmpp.Client
@ -42,7 +42,7 @@ func (xm *XMPP) SetHandler(h Handler) {
xm.handler = h xm.handler = h
} }
func(xm *XMPP) Protocol() string { func (xm *XMPP) Protocol() string {
return "xmpp" return "xmpp"
} }
@ -97,7 +97,7 @@ func (xm *XMPP) Configure(c Configuration) error {
go xm.connectLoop(xm.connectorLoopNum) go xm.connectLoop(xm.connectorLoopNum)
for i := 0; i < 42; i++ { for i := 0; i < 42; i++ {
time.Sleep(time.Duration(1)*time.Second) time.Sleep(time.Duration(1) * time.Second)
if xm.connected { if xm.connected {
return nil return nil
} }
@ -116,12 +116,12 @@ func (xm *XMPP) connectLoop(num int) {
InsecureSkipVerify: true, InsecureSkipVerify: true,
} }
options := gxmpp.Options{ options := gxmpp.Options{
Host: xm.server, Host: xm.server,
User: xm.jid, User: xm.jid,
Password: xm.password, Password: xm.password,
NoTLS: true, NoTLS: true,
StartTLS: xm.ssl, StartTLS: xm.ssl,
Session: true, Session: true,
TLSConfig: tc, TLSConfig: tc,
} }
var err error var err error
@ -237,8 +237,8 @@ func (xm *XMPP) handleXMPP() error {
user := UserID(remote[1] + "@" + remote[0]) user := UserID(remote[1] + "@" + remote[0])
event := &Event{ event := &Event{
Type: EVENT_JOIN, Type: EVENT_JOIN,
Room: RoomID(remote[0]), Room: RoomID(remote[0]),
Author: user, Author: user,
} }
if v.Type == "unavailable" { if v.Type == "unavailable" {
@ -264,8 +264,8 @@ func (xm *XMPP) SetUserInfo(info *UserInfo) error {
func (xm *XMPP) SetRoomInfo(roomId RoomID, info *RoomInfo) error { func (xm *XMPP) SetRoomInfo(roomId RoomID, info *RoomInfo) error {
if info.Topic != "" { if info.Topic != "" {
_, err := xm.conn.Send(gxmpp.Chat{ _, err := xm.conn.Send(gxmpp.Chat{
Type: "groupchat", Type: "groupchat",
Remote: string(roomId), Remote: string(roomId),
Subject: info.Topic, Subject: info.Topic,
}) })
if err != nil { if err != nil {
@ -324,16 +324,16 @@ func (xm *XMPP) Send(event *Event) error {
fmt.Printf("xm *XMPP Send %#v\n", event) fmt.Printf("xm *XMPP Send %#v\n", event)
if len(event.Recipient) > 0 { if len(event.Recipient) > 0 {
_, err := xm.conn.Send(gxmpp.Chat{ _, err := xm.conn.Send(gxmpp.Chat{
Type: "chat", Type: "chat",
Remote: string(event.Recipient), Remote: string(event.Recipient),
Text: event.Text, Text: event.Text,
}) })
return err return err
} else if len(event.Room) > 0 { } else if len(event.Room) > 0 {
_, err := xm.conn.Send(gxmpp.Chat{ _, err := xm.conn.Send(gxmpp.Chat{
Type: "groupchat", Type: "groupchat",
Remote: string(event.Room), Remote: string(event.Room),
Text: event.Text, Text: event.Text,
}) })
return err return err
} else { } else {
@ -346,4 +346,3 @@ func (xm *XMPP) Close() {
xm.conn = nil xm.conn = nil
xm.connectorLoopNum += 1 xm.connectorLoopNum += 1
} }

View File

@ -18,8 +18,8 @@ import (
"git.deuxfleurs.fr/Deuxfleurs/easybridge/appservice" "git.deuxfleurs.fr/Deuxfleurs/easybridge/appservice"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/irc" "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/irc"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/xmpp"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/mattermost" "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/mattermost"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector/xmpp"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib" "git.deuxfleurs.fr/Deuxfleurs/easybridge/mxlib"
) )
@ -102,7 +102,7 @@ func readRegistration(file string) mxlib.Registration {
AsToken: hex.EncodeToString(rnd[:32]), AsToken: hex.EncodeToString(rnd[:32]),
HsToken: hex.EncodeToString(rnd[32:]), HsToken: hex.EncodeToString(rnd[32:]),
SenderLocalpart: "_ezbr_", SenderLocalpart: "_ezbr_",
RateLimited: false, RateLimited: false,
Namespaces: mxlib.RegistrationNamespaceSet{ Namespaces: mxlib.RegistrationNamespaceSet{
Users: []mxlib.RegistrationNamespace{ Users: []mxlib.RegistrationNamespace{
mxlib.RegistrationNamespace{ mxlib.RegistrationNamespace{

View File

@ -1,12 +1,12 @@
package mxlib package mxlib
import ( import (
"strings"
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"strings"
"time" "time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -280,7 +280,7 @@ func (mx *Client) RoomAvatarAs(room string, pic connector.MediaObject, as_user s
"url": mo.MxcUri(), "url": mo.MxcUri(),
"info": map[string]interface{}{ "info": map[string]interface{}{
"mimetype": mo.Mimetype(), "mimetype": mo.Mimetype(),
"size": mo.Size(), "size": mo.Size(),
}, },
} }
return mx.PutStateAs(room, "m.room.avatar", "", content, as_user) return mx.PutStateAs(room, "m.room.avatar", "", content, as_user)
@ -309,7 +309,7 @@ func (mx *Client) UploadMedia(m connector.MediaObject) (*MediaObject, error) {
mx.Server+"/_matrix/media/r0/upload?filename="+url.QueryEscape(m.Filename()), mx.Server+"/_matrix/media/r0/upload?filename="+url.QueryEscape(m.Filename()),
reader) reader)
req.Header.Add("Content-Type", m.Mimetype()) req.Header.Add("Content-Type", m.Mimetype())
req.ContentLength = m.Size() // TODO: this wasn't specified as mandatory in the matrix client/server spec, do a PR to fix this req.ContentLength = m.Size() // TODO: this wasn't specified as mandatory in the matrix client/server spec, do a PR to fix this
var resp UploadResponse var resp UploadResponse
err = mx.DoAndParse(req, &resp) err = mx.DoAndParse(req, &resp)
@ -323,12 +323,12 @@ func (mx *Client) UploadMedia(m connector.MediaObject) (*MediaObject, error) {
} }
media := &MediaObject{ media := &MediaObject{
mxClient: mx, mxClient: mx,
filename: m.Filename(), filename: m.Filename(),
size: m.Size(), size: m.Size(),
mimetype: m.Mimetype(), mimetype: m.Mimetype(),
imageSize: m.ImageSize(), imageSize: m.ImageSize(),
MxcServer: mxc[0], MxcServer: mxc[0],
MxcMediaId: mxc[1], MxcMediaId: mxc[1],
} }
return media, nil return media, nil
@ -339,16 +339,16 @@ func (mx *Client) ParseMediaInfo(content map[string]interface{}) *MediaObject {
info := content["info"].(map[string]interface{}) info := content["info"].(map[string]interface{})
mxc := strings.Split(strings.Replace(content["url"].(string), "mxc://", "", 1), "/") mxc := strings.Split(strings.Replace(content["url"].(string), "mxc://", "", 1), "/")
media := &MediaObject{ media := &MediaObject{
mxClient: mx, mxClient: mx,
filename: content["body"].(string), filename: content["body"].(string),
size: int64(info["size"].(float64)), size: int64(info["size"].(float64)),
mimetype: info["mimetype"].(string), mimetype: info["mimetype"].(string),
MxcServer: mxc[0], MxcServer: mxc[0],
MxcMediaId: mxc[1], MxcMediaId: mxc[1],
} }
if content["msgtype"].(string) == "m.image" { if content["msgtype"].(string) == "m.image" {
media.imageSize = &connector.ImageSize{ media.imageSize = &connector.ImageSize{
Width: int(info["w"].(float64)), Width: int(info["w"].(float64)),
Height: int(info["h"].(float64)), Height: int(info["h"].(float64)),
} }
} }

View File

@ -1,21 +1,21 @@
package mxlib package mxlib
import ( import (
"io"
"fmt" "fmt"
"net/url" "io"
"net/http" "net/http"
"net/url"
"git.deuxfleurs.fr/Deuxfleurs/easybridge/connector" "git.deuxfleurs.fr/Deuxfleurs/easybridge/connector"
) )
type MediaObject struct { type MediaObject struct {
mxClient *Client mxClient *Client
filename string filename string
size int64 size int64
mimetype string mimetype string
imageSize *connector.ImageSize imageSize *connector.ImageSize
MxcServer string MxcServer string
MxcMediaId string MxcMediaId string
} }

View File

@ -10,7 +10,7 @@ type Registration struct {
AsToken string `yaml:"as_token"` AsToken string `yaml:"as_token"`
HsToken string `yaml:"hs_token"` HsToken string `yaml:"hs_token"`
SenderLocalpart string `yaml:"sender_localpart"` SenderLocalpart string `yaml:"sender_localpart"`
RateLimited bool `yaml:"rate_limited"` RateLimited bool `yaml:"rate_limited"`
Namespaces RegistrationNamespaceSet `yaml:"namespaces"` Namespaces RegistrationNamespaceSet `yaml:"namespaces"`
} }