From 1afa05584bfb48794cde6bc534b27ea6a00a726a Mon Sep 17 00:00:00 2001 From: Cori Hudson Date: Fri, 23 Aug 2019 22:16:12 -0400 Subject: [PATCH] Hopefully make a functional keybase bridge --- bridge/config/config.go | 5 +- bridge/keybase/keybase.go | 178 ++++++++++++-------------------------- 2 files changed, 59 insertions(+), 124 deletions(-) diff --git a/bridge/config/config.go b/bridge/config/config.go index e5a4b758..4d5ac32e 100644 --- a/bridge/config/config.go +++ b/bridge/config/config.go @@ -87,7 +87,7 @@ type Protocol struct { IgnoreMessages string // all protocols Jid string // xmpp Label string // all protocols - Login string // mattermost, matrix + Login string // mattermost, matrix, keybase MediaDownloadBlackList []string MediaDownloadPath string // Basically MediaServerUpload, but instead of uploading it, just write it to a file on the same server. MediaDownloadSize int // all protocols @@ -131,7 +131,7 @@ type Protocol struct { StripNick bool // all protocols SyncTopic bool // slack TengoModifyMessage string // general - Team string // mattermost + Team string // mattermost, keybase Token string // gitter, slack, discord, api Topic string // zulip URL string // mattermost, slack // DEPRECATED @@ -145,6 +145,7 @@ type Protocol struct { VerboseJoinPart bool // IRC WebhookBindAddress string // mattermost, slack WebhookURL string // mattermost, slack + PaperKey string // keybase } type ChannelOptions struct { diff --git a/bridge/keybase/keybase.go b/bridge/keybase/keybase.go index f9c1c203..b2e3b602 100644 --- a/bridge/keybase/keybase.go +++ b/bridge/keybase/keybase.go @@ -1,145 +1,91 @@ package bmatrix import ( - "html" - "regexp" - "sync" + "strconv" "github.com/42wim/matterbridge/bridge" "github.com/42wim/matterbridge/bridge/config" - "github.com/42wim/matterbridge/bridge/helper" "github.com/keybase/go-keybase-chat-bot/kbchat" ) type Bkeybase struct { - kbc *kbchat.API - UserID string - sync.RWMutex - htmlTag *regexp.Regexp + kbc *kbchat.API + user string + channel string + team string *bridge.Config } func New(cfg *bridge.Config) bridge.Bridger { // idk what this does b := &Bkeybase{Config: cfg} - b.htmlTag = regexp.MustCompile("") + b.team = b.Config.GetString("Team") return b } func (b *Bkeybase) Connect() error { var err error - b.Log.Infof("Connecting %s", b.GetString("Server")) - b.mc, err = matrix.NewClient(b.GetString("Server"), "", "") + b.Log.Infof("Connecting %s", b.GetString("Team")) + b.kbc, err = kbchat.Start(kbchat.RunOptions{}) if err != nil { return err } - resp, err := b.mc.Login(&matrix.ReqLogin{ - Type: "m.login.password", - User: b.GetString("Login"), - Password: b.GetString("Password"), - }) - if err != nil { - return err - } - b.mc.SetCredentials(resp.UserID, resp.AccessToken) - b.UserID = resp.UserID + b.user = b.kbc.GetUsername() b.Log.Info("Connection succeeded") - go b.handlematrix() + go b.handleKeybase() return nil } -func (b *Bmatrix) Disconnect() error { +func (b *Bkeybase) Disconnect() error { return nil } -func (b *Bmatrix) JoinChannel(channel config.ChannelInfo) error { - resp, err := b.mc.JoinRoom(channel.Name, "", nil) - if err != nil { - return err - } +func (b *Bkeybase) JoinChannel(channel config.ChannelInfo) error { b.Lock() - b.RoomMap[resp.RoomID] = channel.Name + b.channel = channel.Name b.Unlock() - return err + return nil } -func (b *Bmatrix) Send(msg config.Message) (string, error) { +func (b *Bkeybase) Send(msg config.Message) (string, error) { b.Log.Debugf("=> Receiving %#v", msg) - channel := b.getRoomID(msg.Channel) - b.Log.Debugf("Channel %s maps to channel id %s", msg.Channel, channel) + // TODO: /me handling + // if msg.Event == config.EventUserAction { + // m := matrix.TextMessage{ + // MsgType: "m.emote", + // Body: msg.Username + msg.Text, + // } + // resp, err := b.mc.SendMessageEvent(channel, "m.room.message", m) + // if err != nil { + // return "", err + // } + // return resp.EventID, err + // } - // Make a action /me of the message - if msg.Event == config.EventUserAction { - m := matrix.TextMessage{ - MsgType: "m.emote", - Body: msg.Username + msg.Text, - } - resp, err := b.mc.SendMessageEvent(channel, "m.room.message", m) - if err != nil { - return "", err - } - return resp.EventID, err - } - - // Delete message - if msg.Event == config.EventMsgDelete { - if msg.ID == "" { - return "", nil - } - resp, err := b.mc.RedactEvent(channel, msg.ID, &matrix.ReqRedact{}) - if err != nil { - return "", err - } - return resp.EventID, err - } + // Delete message not supported by keybase go library yet // Upload a file if it exists - if msg.Extra != nil { - for _, rmsg := range helper.HandleExtra(&msg, b.General) { - if _, err := b.mc.SendText(channel, rmsg.Username+rmsg.Text); err != nil { - b.Log.Errorf("sendText failed: %s", err) - } - } - // check if we have files to upload (from slack, telegram or mattermost) - if len(msg.Extra["file"]) > 0 { - return b.handleUploadFiles(&msg, channel) - } - } + // kbchat does not support attachments yet // Edit message if we have an ID // matrix has no editing support // Use notices to send join/leave events - if msg.Event == config.EventJoinLeave { - resp, err := b.mc.SendNotice(channel, msg.Username+msg.Text) - if err != nil { - return "", err - } - return resp.EventID, err - } + // if msg.Event == config.EventJoinLeave { + // resp, err := b.mc.SendNotice(channel, msg.Username+msg.Text) + // if err != nil { + // return "", err + // } + // return resp.EventID, err + // } - username := html.EscapeString(msg.Username) - // check if we have a . if we have, we don't escape HTML. #696 - if b.htmlTag.MatchString(msg.Username) { - username = msg.Username - } - // Post normal message with HTML support (eg riot.im) - resp, err := b.mc.SendHTML(channel, msg.Username+msg.Text, username+helper.ParseMarkdown(msg.Text)) + // resp, err := b.mc.SendHTML(channel, msg.Username+msg.Text, username+helper.ParseMarkdown(msg.Text)) + resp, err := b.kbc.SendMessageByTeamName(b.team, msg.Username+msg.Text, &b.channel) if err != nil { return "", err } - return resp.EventID, err -} -func (b *Bmatrix) getRoomID(channel string) string { - b.RLock() - defer b.RUnlock() - for ID, name := range b.RoomMap { - if name == channel { - return ID - } - } - return "" + return strconv.Itoa(resp.Result.MsgID), err } func (b *Bkeybase) handleKeybase() { @@ -172,49 +118,37 @@ func (b *Bkeybase) handleKeybase() { func (b *Bkeybase) handleEvent(msg kbchat.Message) { b.Log.Debugf("== Receiving event: %#v", msg) - if ev.Sender != b.UserID { + if msg.Sender.Username != b.kbc.GetUsername() { // TODO download avatar // Create our message - rmsg := config.Message{Username: msg.Sender.Username, Channel: channel, Account: b.Account, UserID: ev.Sender, ID: ev.ID} + rmsg := config.Message{Username: msg.Sender.Username, Channel: msg.Channel.Name, ID: strconv.Itoa(msg.MsgID)} // Text must be a string - if rmsg.Text, ok = ev.Content["body"].(string); !ok { - b.Log.Errorf("Content[body] is not a string: %T\n%#v", - ev.Content["body"], ev.Content) + if msg.Content.Type != "text" { + b.Log.Errorf("message is not text") return } - // Remove homeserver suffix if configured - if b.GetBool("NoHomeServerSuffix") { - re := regexp.MustCompile("(.*?):.*") - rmsg.Username = re.ReplaceAllString(rmsg.Username, `$1`) - } - - // Delete event - if ev.Type == "m.room.redaction" { - rmsg.Event = config.EventMsgDelete - rmsg.ID = ev.Redacts - rmsg.Text = config.EventMsgDelete - b.Remote <- rmsg - return - } + // Delete event TODO + // if ev.Type == "m.room.redaction" { + // rmsg.Event = config.EventMsgDelete + // rmsg.ID = ev.Redacts + // rmsg.Text = config.EventMsgDelete + // b.Remote <- rmsg + // return + // } // Do we have a /me action - if ev.Content["msgtype"].(string) == "m.emote" { - rmsg.Event = config.EventUserAction - } + // if ev.Content["msgtype"].(string) == "m.emote" { + // rmsg.Event = config.EventUserAction + // } // Do we have attachments - if b.containsAttachment(ev.Content) { - err := b.handleDownloadFile(&rmsg, ev.Content) - if err != nil { - b.Log.Errorf("download failed: %#v", err) - } - } + // doesn't matter because we can't handle it yet - b.Log.Debugf("<= Sending message from %s on %s to gateway", ev.Sender, b.Account) + b.Log.Debugf("<= Sending message from %s on %s to gateway", msg.Sender.Username, msg.Channel.Name) b.Remote <- rmsg } }