From 4ac636670684f0b070455585b6b9c94973ccba43 Mon Sep 17 00:00:00 2001 From: Alexander Date: Thu, 21 Jan 2021 22:50:04 +0100 Subject: [PATCH] Allow the XMPP bridge to use slack compatible webhooks (xmpp) (#1364) * Add mod_slack_webhook support to the XMPP bridge * Replace b.webhookURL with b.GetString * Do not return a message ID on webhook POST * Add the XMPP webhook to the sample configuration --- bridge/xmpp/xmpp.go | 57 +++++++++++++++++++++++++++++++++++----- matterbridge.toml.sample | 5 ++++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/bridge/xmpp/xmpp.go b/bridge/xmpp/xmpp.go index 45c5beb0..e92c3d69 100644 --- a/bridge/xmpp/xmpp.go +++ b/bridge/xmpp/xmpp.go @@ -1,8 +1,11 @@ package bxmpp import ( + "bytes" "crypto/tls" + "encoding/json" "fmt" + "net/http" "strings" "sync" "time" @@ -86,14 +89,21 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { } // Upload a file (in XMPP case send the upload URL because XMPP has no native upload support). + var err error if msg.Extra != nil { for _, rmsg := range helper.HandleExtra(&msg, b.General) { b.Log.Debugf("=> Sending attachement message %#v", rmsg) - if _, err := b.xc.Send(xmpp.Chat{ - Type: "groupchat", - Remote: rmsg.Channel + "@" + b.GetString("Muc"), - Text: rmsg.Username + rmsg.Text, - }); err != nil { + if b.GetString("WebhookURL") != "" { + err = b.postSlackCompatibleWebhook(msg) + } else { + _, err = b.xc.Send(xmpp.Chat{ + Type: "groupchat", + Remote: rmsg.Channel + "@" + b.GetString("Muc"), + Text: rmsg.Username + rmsg.Text, + }) + } + + if err != nil { b.Log.WithError(err).Error("Unable to send message with share URL.") } } @@ -102,13 +112,24 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { } } + if b.GetString("WebhookURL") != "" { + b.Log.Debugf("Sending message using Webhook") + err := b.postSlackCompatibleWebhook(msg) + if err != nil { + b.Log.Errorf("Failed to send message using webhook: %s", err) + return "", err + } + + return "", nil + } + + // Post normal message. var msgReplaceID string msgID := xid.New().String() if msg.ID != "" { msgID = msg.ID msgReplaceID = msg.ID } - // Post normal message. b.Log.Debugf("=> Sending message %#v", msg) if _, err := b.xc.Send(xmpp.Chat{ Type: "groupchat", @@ -122,6 +143,25 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) { return msgID, nil } +func (b *Bxmpp) postSlackCompatibleWebhook(msg config.Message) error { + type XMPPWebhook struct { + Username string `json:"username"` + Text string `json:"text"` + } + webhookBody, err := json.Marshal(XMPPWebhook{ + Username: msg.Username, + Text: msg.Text, + }) + if err != nil { + b.Log.Errorf("Failed to marshal webhook: %s", err) + return err + } + + resp, err := http.Post(b.GetString("WebhookURL")+"/"+msg.Channel, "application/json", bytes.NewReader(webhookBody)) + resp.Body.Close() + return err +} + func (b *Bxmpp) createXMPP() error { if !strings.Contains(b.GetString("Jid"), "@") { return fmt.Errorf("the Jid %s doesn't contain an @", b.GetString("Jid")) @@ -378,6 +418,11 @@ func (b *Bxmpp) skipMessage(message xmpp.Chat) bool { return true } + // Ignore messages posted by our webhook + if b.GetString("WebhookURL") != "" && strings.Contains(message.ID, "webhookbot") { + return true + } + // skip delayed messages return !message.Stamp.IsZero() && time.Since(message.Stamp).Minutes() > 5 } diff --git a/matterbridge.toml.sample b/matterbridge.toml.sample index a92892b0..a398961a 100644 --- a/matterbridge.toml.sample +++ b/matterbridge.toml.sample @@ -310,6 +310,11 @@ StripNick=false #OPTIONAL (default false) ShowTopicChange=false +#Enable sending messages using a webhook instead of regular MUC messages. +#Only works with a prosody server using mod_slack_webhook. Does not support editing. +#OPTIONAL (default "") +WebhookURL="https://yourdomain/prosody/msg/someid" + ################################################################### #mattermost section ###################################################################