Compare commits
23 Commits
rocketchat
...
v1.17.4
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6c442e239d | ||
![]() |
eaf92fca4d | ||
![]() |
06b7bad714 | ||
![]() |
19eec2ed03 | ||
![]() |
d99c54343a | ||
![]() |
308a110000 | ||
![]() |
4f406b2ce6 | ||
![]() |
e564c555d7 | ||
![]() |
f7ec9af9e8 | ||
![]() |
4d93a774ce | ||
![]() |
2595dd30bf | ||
![]() |
9190365289 | ||
![]() |
57794b3b9f | ||
![]() |
3c36f651be | ||
![]() |
8e6ddadba2 | ||
![]() |
8a87a71927 | ||
![]() |
0047e6f523 | ||
![]() |
7183095a28 | ||
![]() |
13c90893c7 | ||
![]() |
976fbcd07f | ||
![]() |
d97b077e85 | ||
![]() |
8950575bfb | ||
![]() |
11fc4c286f |
84
README.md
84
README.md
@@ -9,20 +9,20 @@ Letting people be where they want to be.<br />
|
||||
|
||||
<sup>
|
||||
|
||||
[Discord][mb-discord] |
|
||||
[Gitter][mb-gitter] |
|
||||
[IRC][mb-irc] |
|
||||
[Discord][mb-discord] |
|
||||
[Keybase][mb-keybase] |
|
||||
[Matrix][mb-matrix] |
|
||||
[Slack][mb-slack] |
|
||||
[Mattermost][mb-mattermost] |
|
||||
[MSTeams][mb-msteams] |
|
||||
[Rocket.Chat][mb-rocketchat] |
|
||||
[XMPP][mb-xmpp] |
|
||||
[Slack][mb-slack] |
|
||||
[Telegram][mb-telegram] |
|
||||
[Twitch][mb-twitch] |
|
||||
[WhatsApp][mb-whatsapp] |
|
||||
[XMPP][mb-xmpp] |
|
||||
[Zulip][mb-zulip] |
|
||||
[Telegram][mb-telegram] |
|
||||
[Keybase][mb-keybase] |
|
||||
[MSTeams][mb-msteams] |
|
||||
And more...
|
||||
</sup>
|
||||
|
||||
@@ -87,29 +87,29 @@ And more...
|
||||
|
||||
### Natively supported
|
||||
|
||||
- [Mattermost](https://github.com/mattermost/mattermost-server/) 4.x, 5.x
|
||||
- [IRC](http://www.mirc.com/servers.html)
|
||||
- [XMPP](https://xmpp.org)
|
||||
- [Gitter](https://gitter.im)
|
||||
- [Slack](https://slack.com)
|
||||
- [Discord](https://discordapp.com)
|
||||
- [Telegram](https://telegram.org)
|
||||
- [Rocket.chat](https://rocket.chat)
|
||||
- [Matrix](https://matrix.org)
|
||||
- [Microsoft Teams](https://teams.microsoft.com)
|
||||
- [Steam](https://store.steampowered.com/)
|
||||
- [Twitch](https://twitch.tv)
|
||||
- [Ssh-chat](https://github.com/shazow/ssh-chat)
|
||||
- [WhatsApp](https://www.whatsapp.com/)
|
||||
- [Zulip](https://zulipchat.com)
|
||||
- [Gitter](https://gitter.im)
|
||||
- [IRC](http://www.mirc.com/servers.html)
|
||||
- [Keybase](https://keybase.io)
|
||||
- [Matrix](https://matrix.org)
|
||||
- [Mattermost](https://github.com/mattermost/mattermost-server/) 4.x, 5.x
|
||||
- [Microsoft Teams](https://teams.microsoft.com)
|
||||
- [Rocket.chat](https://rocket.chat)
|
||||
- [Slack](https://slack.com)
|
||||
- [Ssh-chat](https://github.com/shazow/ssh-chat)
|
||||
- [Steam](https://store.steampowered.com/)
|
||||
- [Telegram](https://telegram.org)
|
||||
- [Twitch](https://twitch.tv)
|
||||
- [WhatsApp](https://www.whatsapp.com/)
|
||||
- [XMPP](https://xmpp.org)
|
||||
- [Zulip](https://zulipchat.com)
|
||||
|
||||
### 3rd party via matterbridge api
|
||||
|
||||
- [Discourse](https://github.com/DeclanHoare/matterbabble)
|
||||
- [Facebook messenger](https://github.com/VictorNine/fbridge)
|
||||
- [Minecraft](https://github.com/elytra/MatterLink)
|
||||
- [Reddit](https://github.com/bonehurtingjuice/mattereddit)
|
||||
- [Facebook messenger](https://github.com/VictorNine/fbridge)
|
||||
- [Discourse](https://github.com/DeclanHoare/matterbabble)
|
||||
- [Counter-Strike, half-life and more](https://forums.alliedmods.net/showthread.php?t=319430)
|
||||
|
||||
### API
|
||||
@@ -130,18 +130,18 @@ Used by the projects below. Feel free to make a PR to add your project to this l
|
||||
|
||||
Questions or want to test on your favorite platform? Join below:
|
||||
|
||||
- [Discord][mb-discord]
|
||||
- [Gitter][mb-gitter]
|
||||
- [IRC][mb-irc]
|
||||
- [Discord][mb-discord]
|
||||
- [Keybase][mb-keybase]
|
||||
- [Matrix][mb-matrix]
|
||||
- [Slack][mb-slack]
|
||||
- [Mattermost][mb-mattermost]
|
||||
- [Rocket.Chat][mb-rocketchat]
|
||||
- [XMPP][mb-xmpp] (matterbridge@conference.jabber.de)
|
||||
- [Twitch][mb-twitch]
|
||||
- [Zulip][mb-zulip]
|
||||
- [Slack][mb-slack]
|
||||
- [Telegram][mb-telegram]
|
||||
- [Keybase][mb-keybase]
|
||||
- [Twitch][mb-twitch]
|
||||
- [XMPP][mb-xmpp] (matterbridge@conference.jabber.de)
|
||||
- [Zulip][mb-zulip]
|
||||
|
||||
## Screenshots
|
||||
|
||||
@@ -151,7 +151,7 @@ See https://github.com/42wim/matterbridge/wiki
|
||||
|
||||
### Binaries
|
||||
|
||||
- Latest stable release [v1.17.1](https://github.com/42wim/matterbridge/releases/latest)
|
||||
- Latest stable release [v1.17.4](https://github.com/42wim/matterbridge/releases/latest)
|
||||
- Development releases (follows master) can be downloaded [here](https://dl.bintray.com/42wim/nightly/)
|
||||
|
||||
To install or upgrade just download the latest [binary](https://github.com/42wim/matterbridge/releases/latest) and follow the instructions on the [howto](https://github.com/42wim/matterbridge/wiki/How-to-create-your-config) for a step by step walkthrough for creating your configuration.
|
||||
@@ -324,32 +324,32 @@ Matterbridge wouldn't exist without these libraries:
|
||||
- gops - https://github.com/google/gops
|
||||
- gozulipbot - https://github.com/ifo/gozulipbot
|
||||
- irc - https://github.com/lrstanley/girc
|
||||
- mattermost - https://github.com/mattermost/mattermost-server
|
||||
- keybase - https://github.com/keybase/go-keybase-chat-bot
|
||||
- matrix - https://github.com/matrix-org/gomatrix
|
||||
- sshchat - https://github.com/shazow/ssh-chat
|
||||
- mattermost - https://github.com/mattermost/mattermost-server
|
||||
- msgraph.go - https://github.com/yaegashi/msgraph.go
|
||||
- slack - https://github.com/nlopes/slack
|
||||
- sshchat - https://github.com/shazow/ssh-chat
|
||||
- steam - https://github.com/Philipp15b/go-steam
|
||||
- telegram - https://github.com/go-telegram-bot-api/telegram-bot-api
|
||||
- xmpp - https://github.com/mattn/go-xmpp
|
||||
- whatsapp - https://github.com/Rhymen/go-whatsapp/
|
||||
- zulip - https://github.com/ifo/gozulipbot
|
||||
- tengo - https://github.com/d5/tengo
|
||||
- keybase - https://github.com/keybase/go-keybase-chat-bot
|
||||
- msgraph.go - https://github.com/yaegashi/msgraph.go
|
||||
- whatsapp - https://github.com/Rhymen/go-whatsapp/
|
||||
- xmpp - https://github.com/mattn/go-xmpp
|
||||
- zulip - https://github.com/ifo/gozulipbot
|
||||
|
||||
<!-- Links -->
|
||||
|
||||
[mb-discord]: https://discord.gg/AkKPtrQ
|
||||
[mb-gitter]: https://gitter.im/42wim/matterbridge
|
||||
[mb-irc]: https://webchat.freenode.net/?channels=matterbridgechat
|
||||
[mb-discord]: https://discord.gg/AkKPtrQ
|
||||
[mb-keybase]: https://keybase.io/team/matterbridge
|
||||
[mb-matrix]: https://riot.im/app/#/room/#matterbridge:matrix.org
|
||||
[mb-slack]: https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA
|
||||
[mb-mattermost]: https://framateam.org/signup_user_complete/?id=tfqm33ggop8x3qgu4boeieta6e
|
||||
[mb-msteams]: https://teams.microsoft.com/join/hj92x75gd3y7
|
||||
[mb-rocketchat]: https://open.rocket.chat/channel/matterbridge
|
||||
[mb-xmpp]: https://inverse.chat/
|
||||
[mb-slack]: https://join.slack.com/matterbridgechat/shared_invite/MjEwODMxNjU1NDMwLTE0OTk2MTU3NTMtMzZkZmRiNDZhOA
|
||||
[mb-telegram]: https://t.me/Matterbridge
|
||||
[mb-twitch]: https://www.twitch.tv/matterbridge
|
||||
[mb-whatsapp]: https://www.whatsapp.com/
|
||||
[mb-keybase]: https://keybase.io/team/matterbridge
|
||||
[mb-xmpp]: https://inverse.chat/
|
||||
[mb-zulip]: https://matterbridge.zulipchat.com/register/
|
||||
[mb-telegram]: https://t.me/Matterbridge
|
||||
[mb-msteams]: https://teams.microsoft.com/join/hj92x75gd3y7
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -74,6 +75,7 @@ func (b *Bridge) joinChannels(channels map[string]config.ChannelInfo, exists map
|
||||
for ID, channel := range channels {
|
||||
if !exists[ID] {
|
||||
b.Log.Infof("%s: joining %s (ID: %s)", b.Account, channel.Name, ID)
|
||||
time.Sleep(time.Duration(b.GetInt("JoinDelay")) * time.Millisecond)
|
||||
err := b.JoinChannel(channel)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -89,6 +89,7 @@ type Protocol struct {
|
||||
IgnoreNicks string // all protocols
|
||||
IgnoreMessages string // all protocols
|
||||
Jid string // xmpp
|
||||
JoinDelay string // all protocols
|
||||
Label string // all protocols
|
||||
Login string // mattermost, matrix
|
||||
MediaDownloadBlackList []string
|
||||
|
@@ -34,6 +34,8 @@ type Bdiscord struct {
|
||||
membersMutex sync.RWMutex
|
||||
userMemberMap map[string]*discordgo.Member
|
||||
nickMemberMap map[string]*discordgo.Member
|
||||
webhookCache map[string]string
|
||||
webhookMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func New(cfg *bridge.Config) bridge.Bridger {
|
||||
@@ -41,6 +43,7 @@ func New(cfg *bridge.Config) bridge.Bridger {
|
||||
b.userMemberMap = make(map[string]*discordgo.Member)
|
||||
b.nickMemberMap = make(map[string]*discordgo.Member)
|
||||
b.channelInfoMap = make(map[string]*config.ChannelInfo)
|
||||
b.webhookCache = make(map[string]string)
|
||||
if b.GetString("WebhookURL") != "" {
|
||||
b.Log.Debug("Configuring Discord Incoming Webhook")
|
||||
b.webhookID, b.webhookToken = b.splitURL(b.GetString("WebhookURL"))
|
||||
@@ -188,6 +191,8 @@ func (b *Bdiscord) JoinChannel(channel config.ChannelInfo) error {
|
||||
func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
||||
b.Log.Debugf("=> Receiving %#v", msg)
|
||||
|
||||
origMsgID := msg.ID
|
||||
|
||||
channelID := b.getChannelID(msg.Channel)
|
||||
if channelID == "" {
|
||||
return "", fmt.Errorf("Could not find channelID for %v", msg.Channel)
|
||||
@@ -230,6 +235,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
||||
|
||||
// If we are editing a message, delete the old message
|
||||
if msg.ID != "" {
|
||||
msg.ID = b.getCacheID(msg.ID)
|
||||
b.Log.Debugf("Deleting edited webhook message")
|
||||
err := b.c.ChannelMessageDelete(channelID, msg.ID)
|
||||
if err != nil {
|
||||
@@ -273,6 +279,8 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
||||
if msg == nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
b.updateCacheID(origMsgID, msg.ID)
|
||||
return msg.ID, nil
|
||||
}
|
||||
|
||||
@@ -283,6 +291,7 @@ func (b *Bdiscord) Send(msg config.Message) (string, error) {
|
||||
if msg.ID == "" {
|
||||
return "", nil
|
||||
}
|
||||
msg.ID = b.getCacheID(msg.ID)
|
||||
err := b.c.ChannelMessageDelete(channelID, msg.ID)
|
||||
return "", err
|
||||
}
|
||||
|
@@ -208,6 +208,40 @@ func (b *Bdiscord) splitURL(url string) (string, string) {
|
||||
return webhookURLSplit[webhookIdxID], webhookURLSplit[webhookIdxToken]
|
||||
}
|
||||
|
||||
// getcacheID tries to find a corresponding msgID in the webhook cache.
|
||||
// if not found returns the original request.
|
||||
func (b *Bdiscord) getCacheID(msgID string) string {
|
||||
b.webhookMutex.RLock()
|
||||
defer b.webhookMutex.RUnlock()
|
||||
for k, v := range b.webhookCache {
|
||||
if msgID == k {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return msgID
|
||||
}
|
||||
|
||||
// updateCacheID updates the cache so that the newID takes the place of
|
||||
// the original ID. This is used for edit/deletes in combination with webhooks
|
||||
// as editing a message via webhook means deleting the message and creating a
|
||||
// new message (with a new ID). This ID needs to be set instead of the original ID
|
||||
func (b *Bdiscord) updateCacheID(origID, newID string) {
|
||||
b.webhookMutex.Lock()
|
||||
match := false
|
||||
for k, v := range b.webhookCache {
|
||||
if v == origID {
|
||||
delete(b.webhookCache, k)
|
||||
b.webhookCache[origID] = newID
|
||||
match = true
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !match && origID != "" {
|
||||
b.webhookCache[origID] = newID
|
||||
}
|
||||
b.webhookMutex.Unlock()
|
||||
}
|
||||
|
||||
func enumerateUsernames(s string) []string {
|
||||
onlySpace := true
|
||||
for _, r := range s {
|
||||
|
@@ -54,12 +54,12 @@ func (b *Birc) handleFiles(msg *config.Message) bool {
|
||||
for _, f := range msg.Extra["file"] {
|
||||
fi := f.(config.FileInfo)
|
||||
if fi.Comment != "" {
|
||||
msg.Text += fi.Comment + ": "
|
||||
msg.Text += fi.Comment + " : "
|
||||
}
|
||||
if fi.URL != "" {
|
||||
msg.Text = fi.URL
|
||||
if fi.Comment != "" {
|
||||
msg.Text = fi.Comment + ": " + fi.URL
|
||||
msg.Text = fi.Comment + " : " + fi.URL
|
||||
}
|
||||
}
|
||||
b.Local <- config.Message{Text: msg.Text, Username: msg.Username, Channel: msg.Channel, Event: msg.Event}
|
||||
|
@@ -71,7 +71,15 @@ func (b *Bmsteams) Disconnect() error {
|
||||
}
|
||||
|
||||
func (b *Bmsteams) JoinChannel(channel config.ChannelInfo) error {
|
||||
go b.poll(channel.Name)
|
||||
go func(name string) {
|
||||
for {
|
||||
err := b.poll(name)
|
||||
if err != nil {
|
||||
b.Log.Errorf("polling failed for %s: %s. retrying in 5 seconds", name, err)
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
}
|
||||
}(channel.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -120,12 +128,12 @@ func (b *Bmsteams) getMessages(channel string) ([]msgraph.ChatMessage, error) {
|
||||
}
|
||||
|
||||
//nolint:gocognit
|
||||
func (b *Bmsteams) poll(channelName string) {
|
||||
func (b *Bmsteams) poll(channelName string) error {
|
||||
msgmap := make(map[string]time.Time)
|
||||
b.Log.Debug("getting initial messages")
|
||||
res, err := b.getMessages(channelName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
for _, msg := range res {
|
||||
msgmap[*msg.ID] = *msg.CreatedDateTime
|
||||
@@ -138,7 +146,7 @@ func (b *Bmsteams) poll(channelName string) {
|
||||
for {
|
||||
res, err := b.getMessages(channelName)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return err
|
||||
}
|
||||
for i := len(res) - 1; i >= 0; i-- {
|
||||
msg := res[i]
|
||||
|
@@ -2,6 +2,7 @@ package brocketchat
|
||||
|
||||
import (
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/matterbridge/Rocket.Chat.Go.SDK/models"
|
||||
)
|
||||
|
||||
func (b *Brocketchat) handleRocket() {
|
||||
@@ -38,6 +39,23 @@ func (b *Brocketchat) handleRocketHook(messages chan *config.Message) {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Brocketchat) handleStatusEvent(ev models.Message, rmsg *config.Message) bool {
|
||||
switch ev.Type {
|
||||
case "":
|
||||
// this is a normal message, no processing needed
|
||||
// return true so the message is not dropped
|
||||
return true
|
||||
case sUserJoined, sUserLeft:
|
||||
rmsg.Event = config.EventJoinLeave
|
||||
return true
|
||||
case sRoomChangedTopic:
|
||||
rmsg.Event = config.EventTopicChange
|
||||
return true
|
||||
}
|
||||
b.Log.Debugf("Dropping message with unknown type: %s", ev.Type)
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Brocketchat) handleRocketClient(messages chan *config.Message) {
|
||||
for message := range b.messageChan {
|
||||
// skip messages with same ID, apparently messages get duplicated for an unknown reason
|
||||
@@ -59,7 +77,12 @@ func (b *Brocketchat) handleRocketClient(messages chan *config.Message) {
|
||||
UserID: message.User.ID,
|
||||
ID: message.ID,
|
||||
}
|
||||
messages <- rmsg
|
||||
|
||||
// handleStatusEvent returns false if the message should be dropped
|
||||
// in that case it is probably some modification to the channel we do not want to relay
|
||||
if b.handleStatusEvent(m, rmsg) {
|
||||
messages <- rmsg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,6 +29,12 @@ type Brocketchat struct {
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
const (
|
||||
sUserJoined = "uj"
|
||||
sUserLeft = "ul"
|
||||
sRoomChangedTopic = "room_changed_topic"
|
||||
)
|
||||
|
||||
func New(cfg *bridge.Config) bridge.Bridger {
|
||||
newCache, err := lru.New(100)
|
||||
if err != nil {
|
||||
@@ -169,15 +175,6 @@ func (b *Brocketchat) Send(msg config.Message) (string, error) {
|
||||
|
||||
rmsg, err := b.c.SendMessage(smsg)
|
||||
if rmsg == nil {
|
||||
if strings.Contains(err.Error(), "Invalid or expired session, please login again") ||
|
||||
strings.Contains(err.Error(), "error-invalid-user") {
|
||||
b.Log.Info("Login expired, reconnecting..")
|
||||
err = b.apiLogin()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
b.Remote <- config.Message{Username: "system", Text: "rejoin", Channel: "", Account: b.Account, Event: config.EventRejoinChannels}
|
||||
}
|
||||
return "", err
|
||||
}
|
||||
return rmsg.ID, err
|
||||
|
@@ -137,12 +137,6 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
|
||||
hasOurCallbackID = ok && block.BlockID == "matterbridge_"+b.uuid
|
||||
}
|
||||
|
||||
// Skip any messages that we made ourselves or from 'slackbot' (see #527).
|
||||
if ev.Username == sSlackBotUser ||
|
||||
(b.rtm != nil && ev.Username == b.si.User.Name) || hasOurCallbackID {
|
||||
return true
|
||||
}
|
||||
|
||||
if ev.SubMessage != nil {
|
||||
// It seems ev.SubMessage.Edited == nil when slack unfurls.
|
||||
// Do not forward these messages. See Github issue #266.
|
||||
@@ -155,6 +149,16 @@ func (b *Bslack) skipMessageEvent(ev *slack.MessageEvent) bool {
|
||||
if ev.SubType == "message_replied" && ev.Hidden {
|
||||
return true
|
||||
}
|
||||
if len(ev.SubMessage.Blocks.BlockSet) == 1 {
|
||||
block, ok := ev.SubMessage.Blocks.BlockSet[0].(*slack.SectionBlock)
|
||||
hasOurCallbackID = ok && block.BlockID == "matterbridge_"+b.uuid
|
||||
}
|
||||
}
|
||||
|
||||
// Skip any messages that we made ourselves or from 'slackbot' (see #527).
|
||||
if ev.Username == sSlackBotUser ||
|
||||
(b.rtm != nil && ev.Username == b.si.User.Name) || hasOurCallbackID {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(ev.Files) > 0 {
|
||||
|
@@ -64,6 +64,7 @@ const (
|
||||
editSuffixConfig = "EditSuffix"
|
||||
iconURLConfig = "iconurl"
|
||||
noSendJoinConfig = "nosendjoinpart"
|
||||
messageLength = 3000
|
||||
)
|
||||
|
||||
func New(cfg *bridge.Config) bridge.Bridger {
|
||||
@@ -194,6 +195,7 @@ func (b *Bslack) Send(msg config.Message) (string, error) {
|
||||
b.Log.Debugf("=> Receiving %#v", msg)
|
||||
}
|
||||
|
||||
msg.Text = helper.ClipMessage(msg.Text, messageLength)
|
||||
msg.Text = b.replaceCodeFence(msg.Text)
|
||||
|
||||
// Make a action /me of the message
|
||||
|
@@ -23,7 +23,8 @@ Check:
|
||||
// HandleError received from WhatsApp
|
||||
func (b *Bwhatsapp) HandleError(err error) {
|
||||
// ignore received invalid data errors. https://github.com/42wim/matterbridge/issues/843
|
||||
if strings.Contains(err.Error(), "error processing data: received invalid data") {
|
||||
// ignore tag 174 errors. https://github.com/42wim/matterbridge/issues/1094
|
||||
if strings.Contains(err.Error(), "error processing data: received invalid data") || strings.Contains(err.Error(), "invalid string with tag 174") {
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -67,7 +67,7 @@ func (b *Bwhatsapp) Connect() error {
|
||||
// https://github.com/Rhymen/go-whatsapp#creating-a-connection
|
||||
b.Log.Debugln("Connecting to WhatsApp..")
|
||||
conn, err := whatsapp.NewConn(20 * time.Second)
|
||||
conn.SetClientVersion(0, 4, 1307)
|
||||
conn.SetClientVersion(0, 4, 2080)
|
||||
if err != nil {
|
||||
return errors.New("failed to connect to WhatsApp: " + err.Error())
|
||||
}
|
||||
|
34
bridge/xmpp/handler.go
Normal file
34
bridge/xmpp/handler.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package bxmpp
|
||||
|
||||
import (
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
"github.com/42wim/matterbridge/bridge/helper"
|
||||
"github.com/matterbridge/go-xmpp"
|
||||
)
|
||||
|
||||
// handleDownloadAvatar downloads the avatar of userid from channel
|
||||
// sends a EVENT_AVATAR_DOWNLOAD message to the gateway if successful.
|
||||
// logs an error message if it fails
|
||||
func (b *Bxmpp) handleDownloadAvatar(avatar xmpp.AvatarData) {
|
||||
rmsg := config.Message{
|
||||
Username: "system",
|
||||
Text: "avatar",
|
||||
Channel: b.parseChannel(avatar.From),
|
||||
Account: b.Account,
|
||||
UserID: avatar.From,
|
||||
Event: config.EventAvatarDownload,
|
||||
Extra: make(map[string][]interface{}),
|
||||
}
|
||||
if _, ok := b.avatarMap[avatar.From]; !ok {
|
||||
b.Log.Debugf("Avatar.From: %s", avatar.From)
|
||||
|
||||
err := helper.HandleDownloadSize(b.Log, &rmsg, avatar.From+".png", int64(len(avatar.Data)), b.General)
|
||||
if err != nil {
|
||||
b.Log.Error(err)
|
||||
return
|
||||
}
|
||||
helper.HandleDownloadData(b.Log, &rmsg, avatar.From+".png", rmsg.Text, "", &avatar.Data, b.General)
|
||||
b.Log.Debugf("Avatar download complete")
|
||||
b.Remote <- rmsg
|
||||
}
|
||||
}
|
30
bridge/xmpp/helpers.go
Normal file
30
bridge/xmpp/helpers.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package bxmpp
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
|
||||
"github.com/42wim/matterbridge/bridge/config"
|
||||
)
|
||||
|
||||
var pathRegex = regexp.MustCompile("[^a-zA-Z0-9]+")
|
||||
|
||||
// GetAvatar constructs a URL for a given user-avatar if it is available in the cache.
|
||||
func getAvatar(av map[string]string, userid string, general *config.Protocol) string {
|
||||
if hash, ok := av[userid]; ok {
|
||||
// NOTE: This does not happen in bridge/helper/helper.go but messes up XMPP
|
||||
id := pathRegex.ReplaceAllString(userid, "_")
|
||||
return general.MediaServerDownload + "/" + hash + "/" + id + ".png"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (b *Bxmpp) cacheAvatar(msg *config.Message) string {
|
||||
fi := msg.Extra["file"][0].(config.FileInfo)
|
||||
/* if we have a sha we have successfully uploaded the file to the media server,
|
||||
so we can now cache the sha */
|
||||
if fi.SHA != "" {
|
||||
b.Log.Debugf("Added %s to %s in avatarMap", fi.SHA, msg.UserID)
|
||||
b.avatarMap[msg.UserID] = fi.SHA
|
||||
}
|
||||
return ""
|
||||
}
|
@@ -23,12 +23,15 @@ type Bxmpp struct {
|
||||
xmppMap map[string]string
|
||||
connected bool
|
||||
sync.RWMutex
|
||||
|
||||
avatarMap map[string]string
|
||||
}
|
||||
|
||||
func New(cfg *bridge.Config) bridge.Bridger {
|
||||
return &Bxmpp{
|
||||
Config: cfg,
|
||||
xmppMap: make(map[string]string),
|
||||
Config: cfg,
|
||||
xmppMap: make(map[string]string),
|
||||
avatarMap: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +72,10 @@ func (b *Bxmpp) Send(msg config.Message) (string, error) {
|
||||
}
|
||||
b.Log.Debugf("=> Receiving %#v", msg)
|
||||
|
||||
if msg.Event == config.EventAvatarDownload {
|
||||
return b.cacheAvatar(&msg), nil
|
||||
}
|
||||
|
||||
// Upload a file (in XMPP case send the upload URL because XMPP has no native upload support).
|
||||
if msg.Extra != nil {
|
||||
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||
@@ -230,6 +237,12 @@ func (b *Bxmpp) handleXMPP() error {
|
||||
event = config.EventTopicChange
|
||||
}
|
||||
|
||||
avatar := getAvatar(b.avatarMap, v.Remote, b.General)
|
||||
if avatar == "" {
|
||||
b.Log.Debugf("Requesting avatar data")
|
||||
b.xc.AvatarRequestData(v.Remote)
|
||||
}
|
||||
|
||||
msgID := v.ID
|
||||
if v.ReplaceID != "" {
|
||||
msgID = v.ReplaceID
|
||||
@@ -239,6 +252,7 @@ func (b *Bxmpp) handleXMPP() error {
|
||||
Text: v.Text,
|
||||
Channel: b.parseChannel(v.Remote),
|
||||
Account: b.Account,
|
||||
Avatar: avatar,
|
||||
UserID: v.Remote,
|
||||
ID: msgID,
|
||||
Event: event,
|
||||
@@ -255,6 +269,8 @@ func (b *Bxmpp) handleXMPP() error {
|
||||
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||
b.Remote <- rmsg
|
||||
}
|
||||
case xmpp.AvatarData:
|
||||
b.handleDownloadAvatar(v)
|
||||
case xmpp.Presence:
|
||||
// Do nothing.
|
||||
}
|
||||
|
44
changelog.md
44
changelog.md
@@ -1,3 +1,47 @@
|
||||
# v1.17.4
|
||||
|
||||
## Bugfix
|
||||
|
||||
- general: Lowercase account names. Fixes #1108 (#1110)
|
||||
- msteams: Remove panics and retry polling on failure (msteams). Fixes #1104 (#1105
|
||||
- whatsapp: Update Rhymen/go-whatsapp. Fixes #1107 (#1109) (make whatsapp working again)
|
||||
- discord: Add an ID cache (discord). Fixes #1106 (#1111) (fix delete/edits with webhooks)
|
||||
|
||||
# v1.17.3
|
||||
|
||||
## Enhancements
|
||||
|
||||
- xmpp: Implement User Avatar spoofing of XMPP users #1090
|
||||
- rocketchat: Relay Joins/Topic changes in RocketChat bridge (#1085)
|
||||
- irc: Add JoinDelay option (irc). Fixes #1084 (#1098)
|
||||
- slack: Clip too long messages on 3000 length (slack). Fixes #1081 (#1102)
|
||||
|
||||
## Bugfix
|
||||
|
||||
- general: Fix the behavior of ShowTopicChange and SyncTopic (#1086)
|
||||
- slack: Prevent image/message looping (slack). Fixes #1088 (#1096)
|
||||
- whatsapp: Ignore non-critical errors (whatsapp). Fixes #1094 (#1100)
|
||||
- irc: Add extra space before colon in attachments (irc). Fixes #1089 (#1101)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@42wim, @ldruschk, @qaisjp, @Polynomdivision
|
||||
|
||||
# v1.17.2
|
||||
|
||||
## Enhancements
|
||||
|
||||
- slack: Update vendor slack-go/slack (#1068)
|
||||
- general: Update vendor d5/tengo (#1066)
|
||||
- general: Clarify terminology used in mapping group chat IDs to channels in config (#1079)
|
||||
|
||||
## Bugfix
|
||||
|
||||
- whatsapp: Update Rhymen/go-whatsapp vendor and whatsapp version (#1078). Fixes Media upload #1074
|
||||
- whatsapp: Reset start timestamp on reconnect (whatsapp). Fixes #1059 (#1064)
|
||||
|
||||
This release couldn't exist without the following contributors:
|
||||
@42wim, @jheiselman
|
||||
|
||||
# v1.17.1
|
||||
|
||||
## Enhancements
|
||||
|
@@ -108,7 +108,7 @@ func (gw *Gateway) AddBridge(cfg *config.Bridge) error {
|
||||
func (gw *Gateway) checkConfig(cfg *config.Bridge) {
|
||||
match := false
|
||||
for _, key := range gw.Router.Config.Viper().AllKeys() {
|
||||
if strings.HasPrefix(key, cfg.Account) {
|
||||
if strings.HasPrefix(key, strings.ToLower(cfg.Account)) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
|
@@ -169,7 +169,7 @@ func (gw *Gateway) ignoreEvent(event string, dest *bridge.Bridge) bool {
|
||||
switch event {
|
||||
case config.EventAvatarDownload:
|
||||
// Avatar downloads are only relevant for telegram and mattermost for now
|
||||
if dest.Protocol != "mattermost" && dest.Protocol != "telegram" {
|
||||
if dest.Protocol != "mattermost" && dest.Protocol != "telegram" && dest.Protocol != "xmpp" {
|
||||
return true
|
||||
}
|
||||
case config.EventJoinLeave:
|
||||
@@ -179,7 +179,7 @@ func (gw *Gateway) ignoreEvent(event string, dest *bridge.Bridge) bool {
|
||||
}
|
||||
case config.EventTopicChange:
|
||||
// only relay topic change when used in some way on other side
|
||||
if dest.GetBool("ShowTopicChange") && dest.GetBool("SyncTopic") {
|
||||
if !dest.GetBool("ShowTopicChange") && !dest.GetBool("SyncTopic") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
6
go.mod
6
go.mod
@@ -5,7 +5,7 @@ require (
|
||||
github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f
|
||||
github.com/Jeffail/gabs v1.1.1 // indirect
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0
|
||||
github.com/Rhymen/go-whatsapp v0.1.0
|
||||
github.com/Rhymen/go-whatsapp v0.1.1-0.20200421062035-31e8111ac334
|
||||
github.com/d5/tengo/v2 v2.1.2
|
||||
github.com/dfordsoft/golib v0.0.0-20180902042739-76ee6ab99bec
|
||||
github.com/fsnotify/fsnotify v1.4.7
|
||||
@@ -21,10 +21,10 @@ require (
|
||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20200226211841-4e48f3eaef3e
|
||||
github.com/labstack/echo/v4 v4.1.13
|
||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20200411204219-d5c18ce75048
|
||||
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200329150250-5812999b292b
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050
|
||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18
|
||||
github.com/matterbridge/logrus-prefixed-formatter v0.0.0-20180806162718-01618749af61
|
||||
|
12
go.sum
12
go.sum
@@ -12,8 +12,8 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0 h1:TO7d4rocnNFng6ZQrPe7U6WqHtK5eHEMrgrnnM/72IQ=
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20190816133340-b04c5a83c1c0/go.mod h1:HuVM+sZFzumUdKPWiz+IlCMb4RdsKdT3T+nQBKL+sYg=
|
||||
github.com/Rhymen/go-whatsapp v0.0.0/go.mod h1:rdQr95g2C1xcOfM7QGOhza58HeI3I+tZ/bbluv7VazA=
|
||||
github.com/Rhymen/go-whatsapp v0.1.0 h1:XTXhFIQ/fx9jKObUnUX2Q+nh58EyeHNhX7DniE8xeuA=
|
||||
github.com/Rhymen/go-whatsapp v0.1.0/go.mod h1:xJSy+okeRjKkQEH/lEYrnekXB3PG33fqL0I6ncAkV50=
|
||||
github.com/Rhymen/go-whatsapp v0.1.1-0.20200421062035-31e8111ac334 h1:kb1zvD+xd+XbPUdQ0lMxnRaQ76N5C9vMAClLi8Dyw1Y=
|
||||
github.com/Rhymen/go-whatsapp v0.1.1-0.20200421062035-31e8111ac334/go.mod h1:o7jjkvKnigfu432dMbQ/w4PH0Yp5u4Y6ysCNjUlcYCk=
|
||||
github.com/Rhymen/go-whatsapp/examples/echo v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:zgCiQtBtZ4P4gFWvwl9aashsdwOcbb/EHOGRmSzM8ME=
|
||||
github.com/Rhymen/go-whatsapp/examples/restoreSession v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:5sCUSpG616ZoSJhlt9iBNI/KXBqrVLcNUJqg7J9+8pU=
|
||||
github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d/go.mod h1:RdiyhanVEGXTam+mZ3k6Y3VDCCvXYCwReOoxGozqhHw=
|
||||
@@ -124,14 +124,14 @@ github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7 h1:BS9tqL0OCiOGuy/C
|
||||
github.com/lrstanley/girc v0.0.0-20190801035559-4fc93959e1a7/go.mod h1:liX5MxHPrwgHaKowoLkYGwbXfYABh1jbZ6FpElbGF1I=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d h1:F+Sr+C0ojSlYQ37BLylQtSFmyQULe3jbAygcyXQ9mVs=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20200411204219-d5c18ce75048 h1:B9HaistmV+MD8/33BXmZe1zPIn+RImAFVXNNSOrwU2E=
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20200411204219-d5c18ce75048/go.mod h1:c6MxwqHD+0HvtAJjsHMIdPCiAwGiQwPRPTp69ACMg8A=
|
||||
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3 h1:VP/DNRn2HtrVRN6+X3h4FDcQI2OOKT+88WUi21ZD1Kw=
|
||||
github.com/matterbridge/discordgo v0.18.1-0.20200308151012-aa40f01cbcc3/go.mod h1:5a1bHtG/38ofcx9cgwM5eTW/Pl4SpbQksNDnTRcGA2Y=
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible h1:oaOqwbg5HxHRxvAbd84ks0Okwoc1ISyUZ87EiVJFhGI=
|
||||
github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible/go.mod h1:igE6rUAn3jai2wCdsjFHfhUoekjrFthoEjFObKKwSb4=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200329150250-5812999b292b h1:ZYI2HCj9zPzI4Si1ouSOi/ImA2xSQLUCJPQsLWr8FE0=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200329150250-5812999b292b/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050 h1:kWkP1lXpkvtoNL08jkP3XQH/zvDOEXJpdCJd/DlIvMw=
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050/go.mod h1:ECDRehsR9TYTKCAsRS8/wLeOk6UUqDydw47ln7wG41Q=
|
||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6 h1:Kl65VJv38HjYFnnwH+MP6Z8hcJT5UHuSpHVU5vW1HH0=
|
||||
github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6/go.mod h1:+jWeaaUtXQbBRdKYWfjW6JDDYiI2XXE+3NnTjW5kg8g=
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20190212232658-7aa251978a18 h1:fLhwXtWGtfTgZVxHG1lcKjv+re7dRwyyuYFNu69xdho=
|
||||
|
@@ -15,7 +15,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
version = "1.17.2-dev"
|
||||
version = "1.17.4"
|
||||
githash string
|
||||
|
||||
flagConfig = flag.String("conf", "matterbridge.toml", "config file")
|
||||
|
@@ -177,6 +177,12 @@ StripNick=false
|
||||
#OPTIONAL (default false)
|
||||
ShowTopicChange=false
|
||||
|
||||
#Delay in milliseconds between channel joins
|
||||
#Only useful when you have a LOT of channels to join
|
||||
#See https://github.com/42wim/matterbridge/issues/1084
|
||||
#OPTIONAL (default 0)
|
||||
JoinDelay=0
|
||||
|
||||
###################################################################
|
||||
#XMPP section
|
||||
###################################################################
|
||||
@@ -1679,34 +1685,44 @@ enable=true
|
||||
# REQUIRED
|
||||
account="irc.freenode"
|
||||
|
||||
# channel to connect on that account
|
||||
# How to specify them for the different bridges:
|
||||
# The channel key in each gateway is mapped to a similar group chat ID on the chat platform
|
||||
# To find the group chat ID for different platforms, refer to the table below
|
||||
#
|
||||
# irc - #channel (# is required) (this needs to be lowercase!)
|
||||
# mattermost - channel (the channel name as seen in the URL, not the displayname)
|
||||
# gitter - username/room
|
||||
# xmpp - channel
|
||||
# slack - channel (without the #)
|
||||
# - ID:C123456 (where C123456 is the channel ID) does not work with webhook
|
||||
# discord - channel (without the #)
|
||||
# - ID:123456789 (where 123456789 is the channel ID)
|
||||
# (https://github.com/42wim/matterbridge/issues/57)
|
||||
# - category/channel (without the #) if you're using discord categories to group your channels
|
||||
# telegram - chatid (a large negative number, eg -123456789)
|
||||
# see (https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau)
|
||||
# hipchat - id_channel (see https://www.hipchat.com/account/xmpp for the correct channel)
|
||||
# rocketchat - #channel (# is required (also needed for private channels!)
|
||||
# matrix - #channel:server (eg #yourchannel:matrix.org)
|
||||
# - encrypted rooms are not supported in matrix
|
||||
# msteams - 19:xxxxxxxxxxxxxxxxxxxxxxxxxx@thread.skype
|
||||
# - You'll find the channel ID in the URL in the threadId=19:82abcxxxxxxxxx@thread.skype
|
||||
# steam - chatid (a large number).
|
||||
# The number in the URL when you click "enter chat room" in the browser
|
||||
# whatsapp - 48111222333-123455678999@g.us A unique group JID;
|
||||
# if you specify an empty string bridge will list all the possibilities
|
||||
# - "Group Name" if you specify a group name the bridge will hint its JID to specify
|
||||
# as group names might change in time and contain weird emoticons
|
||||
# zulip - stream/topic:topicname (without the #)
|
||||
# Platform | Identifier name | Example | Description
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# | channel | general | Do not include the # symbol
|
||||
# discord | channel id | ID:123456789 | See https://github.com/42wim/matterbridge/issues/57
|
||||
# | category/channel | Media/gaming | Without # symbol. If you're using discord categories to group your channels
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# gitter | username/room | general | As seen in the gitter.im URL
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# hipchat | id_channel | example needed | See https://www.hipchat.com/account/xmpp for the correct channel
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# irc | channel | #general | The # symbol is required and should be lowercase!
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# mattermost | channel | general | This is the channel name as seen in the URL, not the display name
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# matrix | #channel:server | #yourchannel:matrix.org | Encrypted rooms are not supported in matrix
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# msteams | threadId | 19:82abcxx@thread.skype | You'll find the threadId in the URL
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# rocketchat | channel | #channel | # is required for private channels too
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# slack | channel name | general | Do not include the # symbol
|
||||
# | channel id | ID:C123456 | The underlying ID of a channel. This doesn't work with
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# steam | chatid | example needed | The number in the URL when you click "enter chat room" in the browser
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# telegram | chatid | -123456789 | A large negative number. see https://www.linkedin.com/pulse/telegram-bots-beginners-marco-frau
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# whatsapp | group JID | 48111222333-123455678999@g.us | A unique group JID. If you specify an empty string, bridge will list all the possibilities
|
||||
# | "Group Name" | "Family Chat" | if you specify a group name, the bridge will find hint the JID to specify. Names can change over time and are not stable.
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# xmpp | channel | general | The room name
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
# zulip | stream/topic:topic | general/off-topic:food | Do not use the # when specifying a topic
|
||||
# -------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
#
|
||||
# REQUIRED
|
||||
channel="#testing"
|
||||
|
1481
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.pb.go
generated
vendored
1481
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.pb.go
generated
vendored
File diff suppressed because it is too large
Load Diff
78
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.proto
generated
vendored
78
vendor/github.com/Rhymen/go-whatsapp/binary/proto/def.proto
generated
vendored
@@ -56,6 +56,8 @@ message Location {
|
||||
}
|
||||
|
||||
message Point {
|
||||
optional int32 xDeprecated = 1;
|
||||
optional int32 yDeprecated = 2;
|
||||
optional double x = 3;
|
||||
optional double y = 4;
|
||||
}
|
||||
@@ -93,6 +95,7 @@ message ContextInfo {
|
||||
optional AdReplyInfo quotedAd = 23;
|
||||
optional MessageKey placeholderKey = 24;
|
||||
optional uint32 expiration = 25;
|
||||
optional int64 ephemeralSettingTimestamp = 26;
|
||||
}
|
||||
|
||||
message SenderKeyDistributionMessage {
|
||||
@@ -136,6 +139,11 @@ message LocationMessage {
|
||||
optional string name = 3;
|
||||
optional string address = 4;
|
||||
optional string url = 5;
|
||||
optional bool isLive = 6;
|
||||
optional uint32 accuracyInMeters = 7;
|
||||
optional float speedInMps = 8;
|
||||
optional uint32 degreesClockwiseFromMagneticNorth = 9;
|
||||
optional string comment = 11;
|
||||
optional bytes jpegThumbnail = 16;
|
||||
optional ContextInfo contextInfo = 17;
|
||||
}
|
||||
@@ -238,9 +246,29 @@ message ProtocolMessage {
|
||||
enum PROTOCOL_MESSAGE_TYPE {
|
||||
REVOKE = 0;
|
||||
EPHEMERAL_SETTING = 3;
|
||||
EPHEMERAL_SYNC_RESPONSE = 4;
|
||||
HISTORY_SYNC_NOTIFICATION = 5;
|
||||
}
|
||||
optional PROTOCOL_MESSAGE_TYPE type = 2;
|
||||
optional uint32 ephemeralExpiration = 4;
|
||||
optional int64 ephemeralSettingTimestamp = 5;
|
||||
optional HistorySyncNotification historySyncNotification = 6;
|
||||
}
|
||||
|
||||
message HistorySyncNotification {
|
||||
optional bytes fileSha256 = 1;
|
||||
optional uint64 fileLength = 2;
|
||||
optional bytes mediaKey = 3;
|
||||
optional bytes fileEncSha256 = 4;
|
||||
optional string directPath = 5;
|
||||
enum HISTORY_SYNC_NOTIFICATION_HISTORYSYNCTYPE {
|
||||
INITIAL_BOOTSTRAP = 0;
|
||||
INITIAL_STATUS_V3 = 1;
|
||||
FULL = 2;
|
||||
RECENT = 3;
|
||||
}
|
||||
optional HISTORY_SYNC_NOTIFICATION_HISTORYSYNCTYPE syncType = 6;
|
||||
optional uint32 chunkOrder = 7;
|
||||
}
|
||||
|
||||
message ContactsArrayMessage {
|
||||
@@ -355,6 +383,8 @@ message StickerMessage {
|
||||
optional int64 mediaKeyTimestamp = 10;
|
||||
optional uint32 firstFrameLength = 11;
|
||||
optional bytes firstFrameSidecar = 12;
|
||||
optional bool isAnimated = 13;
|
||||
optional bytes pngThumbnail = 16;
|
||||
optional ContextInfo contextInfo = 17;
|
||||
}
|
||||
|
||||
@@ -401,6 +431,12 @@ message TemplateButtonReplyMessage {
|
||||
optional uint32 selectedIndex = 4;
|
||||
}
|
||||
|
||||
message CatalogSnapshot {
|
||||
optional ImageMessage catalogImage = 1;
|
||||
optional string title = 2;
|
||||
optional string description = 3;
|
||||
}
|
||||
|
||||
message ProductSnapshot {
|
||||
optional ImageMessage productImage = 1;
|
||||
optional string productId = 2;
|
||||
@@ -417,6 +453,7 @@ message ProductSnapshot {
|
||||
message ProductMessage {
|
||||
optional ProductSnapshot product = 1;
|
||||
optional string businessOwnerJid = 2;
|
||||
optional CatalogSnapshot catalog = 4;
|
||||
optional ContextInfo contextInfo = 17;
|
||||
}
|
||||
|
||||
@@ -513,6 +550,8 @@ message WebFeatures {
|
||||
optional WEB_FEATURES_FLAG templateMessage = 30;
|
||||
optional WEB_FEATURES_FLAG templateMessageInteractivity = 31;
|
||||
optional WEB_FEATURES_FLAG ephemeralMessages = 32;
|
||||
optional WEB_FEATURES_FLAG e2ENotificationSync = 33;
|
||||
optional WEB_FEATURES_FLAG recentStickersV2 = 34;
|
||||
}
|
||||
|
||||
message TabletNotificationsInfo {
|
||||
@@ -537,6 +576,11 @@ message WebNotificationsInfo {
|
||||
}
|
||||
|
||||
message PaymentInfo {
|
||||
enum PAYMENT_INFO_CURRENCY {
|
||||
UNKNOWN_CURRENCY = 0;
|
||||
INR = 1;
|
||||
}
|
||||
optional PAYMENT_INFO_CURRENCY currencyDeprecated = 1;
|
||||
optional uint64 amount1000 = 2;
|
||||
optional string receiverJid = 3;
|
||||
enum PAYMENT_INFO_STATUS {
|
||||
@@ -559,6 +603,37 @@ message PaymentInfo {
|
||||
optional uint64 expiryTimestamp = 7;
|
||||
optional bool futureproofed = 8;
|
||||
optional string currency = 9;
|
||||
enum PAYMENT_INFO_TXNSTATUS {
|
||||
UNKNOWN = 0;
|
||||
PENDING_SETUP = 1;
|
||||
PENDING_RECEIVER_SETUP = 2;
|
||||
INIT = 3;
|
||||
SUCCESS = 4;
|
||||
COMPLETED = 5;
|
||||
FAILED = 6;
|
||||
FAILED_RISK = 7;
|
||||
FAILED_PROCESSING = 8;
|
||||
FAILED_RECEIVER_PROCESSING = 9;
|
||||
FAILED_DA = 10;
|
||||
FAILED_DA_FINAL = 11;
|
||||
REFUNDED_TXN = 12;
|
||||
REFUND_FAILED = 13;
|
||||
REFUND_FAILED_PROCESSING = 14;
|
||||
REFUND_FAILED_DA = 15;
|
||||
EXPIRED_TXN = 16;
|
||||
AUTH_CANCELED = 17;
|
||||
AUTH_CANCEL_FAILED_PROCESSING = 18;
|
||||
AUTH_CANCEL_FAILED = 19;
|
||||
COLLECT_INIT = 20;
|
||||
COLLECT_SUCCESS = 21;
|
||||
COLLECT_FAILED = 22;
|
||||
COLLECT_FAILED_RISK = 23;
|
||||
COLLECT_REJECTED = 24;
|
||||
COLLECT_EXPIRED = 25;
|
||||
COLLECT_CANCELED = 26;
|
||||
COLLECT_CANCELLING = 27;
|
||||
}
|
||||
optional PAYMENT_INFO_TXNSTATUS txnStatus = 10;
|
||||
}
|
||||
|
||||
message WebMessageInfo {
|
||||
@@ -668,4 +743,5 @@ message WebMessageInfo {
|
||||
optional PaymentInfo quotedPaymentInfo = 31;
|
||||
optional uint64 ephemeralStartTimestamp = 32;
|
||||
optional uint32 ephemeralDuration = 33;
|
||||
}
|
||||
}
|
||||
|
||||
|
3
vendor/github.com/Rhymen/go-whatsapp/conn.go
generated
vendored
3
vendor/github.com/Rhymen/go-whatsapp/conn.go
generated
vendored
@@ -90,6 +90,7 @@ type Conn struct {
|
||||
|
||||
longClientName string
|
||||
shortClientName string
|
||||
clientVersion string
|
||||
|
||||
loginSessionLock sync.RWMutex
|
||||
Proxy func(*http.Request) (*url.URL, error)
|
||||
@@ -121,6 +122,7 @@ func NewConn(timeout time.Duration) (*Conn, error) {
|
||||
|
||||
longClientName: "github.com/rhymen/go-whatsapp",
|
||||
shortClientName: "go-whatsapp",
|
||||
clientVersion: "0.1.0",
|
||||
}
|
||||
return wac, wac.connect()
|
||||
}
|
||||
@@ -135,6 +137,7 @@ func NewConnWithProxy(timeout time.Duration, proxy func(*http.Request) (*url.URL
|
||||
|
||||
longClientName: "github.com/rhymen/go-whatsapp",
|
||||
shortClientName: "go-whatsapp",
|
||||
clientVersion: "0.1.0",
|
||||
Proxy: proxy,
|
||||
}
|
||||
return wac, wac.connect()
|
||||
|
2
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
2
vendor/github.com/Rhymen/go-whatsapp/go.mod
generated
vendored
@@ -6,7 +6,7 @@ require (
|
||||
github.com/Rhymen/go-whatsapp/examples/sendImage v0.0.0-20190325075644-cc2581bbf24d // indirect
|
||||
github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc2581bbf24d // indirect
|
||||
github.com/golang/protobuf v1.3.0
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/pkg/errors v0.8.1
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
|
||||
)
|
||||
|
3
vendor/github.com/Rhymen/go-whatsapp/go.sum
generated
vendored
3
vendor/github.com/Rhymen/go-whatsapp/go.sum
generated
vendored
@@ -12,8 +12,9 @@ github.com/Rhymen/go-whatsapp/examples/sendTextMessages v0.0.0-20190325075644-cc
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk=
|
||||
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
|
||||
|
116
vendor/github.com/Rhymen/go-whatsapp/media.go
generated
vendored
116
vendor/github.com/Rhymen/go-whatsapp/media.go
generated
vendored
@@ -10,10 +10,8 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/Rhymen/go-whatsapp/crypto/cbc"
|
||||
@@ -95,7 +93,50 @@ func downloadMedia(url string) (file []byte, mac []byte, err error) {
|
||||
return data[:n-10], data[n-10 : n], nil
|
||||
}
|
||||
|
||||
func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (url string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) {
|
||||
type MediaConn struct {
|
||||
Status int `json:"status"`
|
||||
MediaConn struct {
|
||||
Auth string `json:"auth"`
|
||||
TTL int `json:"ttl"`
|
||||
Hosts []struct {
|
||||
Hostname string `json:"hostname"`
|
||||
IPs []string `json:"ips"`
|
||||
} `json:"hosts"`
|
||||
} `json:"media_conn"`
|
||||
}
|
||||
|
||||
func (wac *Conn) queryMediaConn() (hostname, auth string, ttl int, err error) {
|
||||
queryReq := []interface{}{"query", "mediaConn"}
|
||||
ch, err := wac.writeJson(queryReq)
|
||||
if err != nil {
|
||||
return "", "", 0, err
|
||||
}
|
||||
|
||||
var resp MediaConn
|
||||
select {
|
||||
case r := <-ch:
|
||||
if err = json.Unmarshal([]byte(r), &resp); err != nil {
|
||||
return "", "", 0, fmt.Errorf("error decoding query media conn response: %v", err)
|
||||
}
|
||||
case <-time.After(wac.msgTimeout):
|
||||
return "", "", 0, fmt.Errorf("query media conn timed out")
|
||||
}
|
||||
|
||||
if resp.Status != 200 {
|
||||
return "", "", 0, fmt.Errorf("query media conn responded with %d", resp.Status)
|
||||
}
|
||||
|
||||
return resp.MediaConn.Hosts[0].Hostname, resp.MediaConn.Auth, resp.MediaConn.TTL, nil
|
||||
}
|
||||
|
||||
var mediaTypeMap = map[MediaType]string{
|
||||
MediaImage: "/mms/image",
|
||||
MediaVideo: "/mms/video",
|
||||
MediaDocument: "/mms/document",
|
||||
MediaAudio: "/mms/audio",
|
||||
}
|
||||
|
||||
func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (downloadURL string, mediaKey []byte, fileEncSha256 []byte, fileSha256 []byte, fileLength uint64, err error) {
|
||||
data, err := ioutil.ReadAll(reader)
|
||||
if err != nil {
|
||||
return "", nil, nil, nil, 0, err
|
||||
@@ -128,67 +169,30 @@ func (wac *Conn) Upload(reader io.Reader, appInfo MediaType) (url string, mediaK
|
||||
sha.Write(append(enc, mac...))
|
||||
fileEncSha256 = sha.Sum(nil)
|
||||
|
||||
var filetype string
|
||||
switch appInfo {
|
||||
case MediaImage:
|
||||
filetype = "image"
|
||||
case MediaAudio:
|
||||
filetype = "audio"
|
||||
case MediaDocument:
|
||||
filetype = "document"
|
||||
case MediaVideo:
|
||||
filetype = "video"
|
||||
hostname, auth, _, err := wac.queryMediaConn()
|
||||
token := base64.URLEncoding.EncodeToString(fileEncSha256)
|
||||
q := url.Values{
|
||||
"auth": []string{auth},
|
||||
"token": []string{token},
|
||||
}
|
||||
path := mediaTypeMap[appInfo]
|
||||
uploadURL := url.URL{
|
||||
Scheme: "https",
|
||||
Host: hostname,
|
||||
Path: fmt.Sprintf("%s/%s", path, token),
|
||||
RawQuery: q.Encode(),
|
||||
}
|
||||
|
||||
uploadReq := []interface{}{"action", "encr_upload", filetype, base64.StdEncoding.EncodeToString(fileEncSha256)}
|
||||
ch, err := wac.writeJson(uploadReq)
|
||||
body := bytes.NewReader(append(enc, mac...))
|
||||
|
||||
req, err := http.NewRequest("POST", uploadURL.String(), body)
|
||||
if err != nil {
|
||||
return "", nil, nil, nil, 0, err
|
||||
}
|
||||
|
||||
var resp map[string]interface{}
|
||||
select {
|
||||
case r := <-ch:
|
||||
if err = json.Unmarshal([]byte(r), &resp); err != nil {
|
||||
return "", nil, nil, nil, 0, fmt.Errorf("error decoding upload response: %v", err)
|
||||
}
|
||||
case <-time.After(wac.msgTimeout):
|
||||
return "", nil, nil, nil, 0, fmt.Errorf("restore session init timed out")
|
||||
}
|
||||
|
||||
if int(resp["status"].(float64)) != 200 {
|
||||
return "", nil, nil, nil, 0, fmt.Errorf("upload responsed with %d", resp["status"])
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
w := multipart.NewWriter(&b)
|
||||
hashWriter, err := w.CreateFormField("hash")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
}
|
||||
io.Copy(hashWriter, strings.NewReader(base64.StdEncoding.EncodeToString(fileEncSha256)))
|
||||
|
||||
fileWriter, err := w.CreateFormFile("file", "blob")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
}
|
||||
io.Copy(fileWriter, bytes.NewReader(append(enc, mac...)))
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", resp["url"].(string), &b)
|
||||
if err != nil {
|
||||
return "", nil, nil, nil, 0, err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", w.FormDataContentType())
|
||||
req.Header.Set("Origin", "https://web.whatsapp.com")
|
||||
req.Header.Set("Referer", "https://web.whatsapp.com/")
|
||||
|
||||
req.URL.Query().Set("f", "j")
|
||||
|
||||
client := &http.Client{}
|
||||
// Submit the request
|
||||
res, err := client.Do(req)
|
||||
|
6
vendor/github.com/Rhymen/go-whatsapp/read.go
generated
vendored
6
vendor/github.com/Rhymen/go-whatsapp/read.go
generated
vendored
@@ -15,7 +15,10 @@ import (
|
||||
)
|
||||
|
||||
func (wac *Conn) readPump() {
|
||||
defer wac.wg.Done()
|
||||
defer func() {
|
||||
wac.wg.Done()
|
||||
_, _ = wac.Disconnect()
|
||||
}()
|
||||
|
||||
var readErr error
|
||||
var msgType int
|
||||
@@ -31,7 +34,6 @@ func (wac *Conn) readPump() {
|
||||
case <-readerFound:
|
||||
if readErr != nil {
|
||||
wac.handle(&ErrConnectionFailed{Err: readErr})
|
||||
_, _ = wac.Disconnect()
|
||||
return
|
||||
}
|
||||
msg, err := ioutil.ReadAll(reader)
|
||||
|
18
vendor/github.com/Rhymen/go-whatsapp/session.go
generated
vendored
18
vendor/github.com/Rhymen/go-whatsapp/session.go
generated
vendored
@@ -18,7 +18,7 @@ import (
|
||||
)
|
||||
|
||||
//represents the WhatsAppWeb client version
|
||||
var waVersion = []int{0, 3, 3324}
|
||||
var waVersion = []int{0, 4, 2080}
|
||||
|
||||
/*
|
||||
Session contains session individual information. To be able to resume the connection without scanning the qr code
|
||||
@@ -107,10 +107,10 @@ func CheckCurrentServerVersion() ([]int, error) {
|
||||
}
|
||||
|
||||
b64ClientId := base64.StdEncoding.EncodeToString(clientId)
|
||||
login := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName}, b64ClientId, true}
|
||||
login := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName, wac.clientVersion}, b64ClientId, true}
|
||||
loginChan, err := wac.writeJson(login)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error writing login", err)
|
||||
return nil, fmt.Errorf("error writing login: %s", err.Error())
|
||||
}
|
||||
|
||||
// Retrieve an answer from the websocket
|
||||
@@ -123,7 +123,7 @@ func CheckCurrentServerVersion() ([]int, error) {
|
||||
|
||||
var resp map[string]interface{}
|
||||
if err = json.Unmarshal([]byte(r), &resp); err != nil {
|
||||
return nil, fmt.Errorf("error decoding login", err)
|
||||
return nil, fmt.Errorf("error decoding login: %s", err.Error())
|
||||
}
|
||||
|
||||
// Take the curr property as X.Y.Z and split it into as int slice
|
||||
@@ -141,17 +141,17 @@ func CheckCurrentServerVersion() ([]int, error) {
|
||||
SetClientName sets the long and short client names that are sent to WhatsApp when logging in and displayed in the
|
||||
WhatsApp Web device list. As the values are only sent when logging in, changing them after logging in is not possible.
|
||||
*/
|
||||
func (wac *Conn) SetClientName(long, short string) error {
|
||||
func (wac *Conn) SetClientName(long, short, version string) error {
|
||||
if wac.session != nil && (wac.session.EncKey != nil || wac.session.MacKey != nil) {
|
||||
return fmt.Errorf("cannot change client name after logging in")
|
||||
}
|
||||
wac.longClientName, wac.shortClientName = long, short
|
||||
wac.longClientName, wac.shortClientName, wac.clientVersion = long, short, version
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
SetClientVersion sets WhatsApp client version
|
||||
Default value is 0.3.3324
|
||||
Default value is 0.4.2080
|
||||
*/
|
||||
func (wac *Conn) SetClientVersion(major int, minor int, patch int) {
|
||||
waVersion = []int{major, minor, patch}
|
||||
@@ -213,7 +213,7 @@ func (wac *Conn) Login(qrChan chan<- string) (Session, error) {
|
||||
}
|
||||
|
||||
session.ClientId = base64.StdEncoding.EncodeToString(clientId)
|
||||
login := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName}, session.ClientId, true}
|
||||
login := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName, wac.clientVersion}, session.ClientId, true}
|
||||
loginChan, err := wac.writeJson(login)
|
||||
if err != nil {
|
||||
return session, fmt.Errorf("error writing login: %v\n", err)
|
||||
@@ -369,7 +369,7 @@ func (wac *Conn) Restore() error {
|
||||
wac.listener.Unlock()
|
||||
|
||||
//admin init
|
||||
init := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName}, wac.session.ClientId, true}
|
||||
init := []interface{}{"admin", "init", waVersion, []string{wac.longClientName, wac.shortClientName, wac.clientVersion}, wac.session.ClientId, true}
|
||||
initChan, err := wac.writeJson(init)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error writing admin init: %v\n", err)
|
||||
|
4
vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go
generated
vendored
4
vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/models/message.go
generated
vendored
@@ -7,6 +7,7 @@ type Message struct {
|
||||
RoomID string `json:"rid"`
|
||||
Msg string `json:"msg"`
|
||||
EditedBy string `json:"editedBy,omitempty"`
|
||||
Type string `json:"t,omitempty"`
|
||||
|
||||
Groupable bool `json:"groupable,omitempty"`
|
||||
|
||||
@@ -16,6 +17,9 @@ type Message struct {
|
||||
|
||||
Mentions []User `json:"mentions,omitempty"`
|
||||
User *User `json:"u,omitempty"`
|
||||
|
||||
Attachments []Attachment `json:"attachments,omitempty"`
|
||||
|
||||
PostMessage
|
||||
|
||||
// Bot interface{} `json:"bot"`
|
||||
|
22
vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go
generated
vendored
22
vendor/github.com/matterbridge/Rocket.Chat.Go.SDK/realtime/messages.go
generated
vendored
@@ -191,6 +191,26 @@ func getMessageFromData(data interface{}) *models.Message {
|
||||
|
||||
func getMessageFromDocument(arg *gabs.Container) *models.Message {
|
||||
var ts *time.Time
|
||||
var attachments []models.Attachment
|
||||
|
||||
attachmentSrc, err := arg.Path("attachments").Children()
|
||||
if err != nil {
|
||||
attachments = make([]models.Attachment, 0)
|
||||
} else {
|
||||
attachments = make([]models.Attachment, len(attachmentSrc))
|
||||
for i, attachment := range attachmentSrc {
|
||||
attachments[i] = models.Attachment{
|
||||
Timestamp: stringOrZero(attachment.Path("ts").Data()),
|
||||
Title: stringOrZero(attachment.Path("title").Data()),
|
||||
TitleLink: stringOrZero(attachment.Path("title_link").Data()),
|
||||
TitleLinkDownload: stringOrZero(attachment.Path("title_link_download").Data()),
|
||||
ImageURL: stringOrZero(attachment.Path("image_url").Data()),
|
||||
|
||||
AuthorName: stringOrZero(arg.Path("u.name").Data()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
date := stringOrZero(arg.Path("ts.$date").Data())
|
||||
if len(date) > 0 {
|
||||
if ti, err := strconv.ParseFloat(date, 64); err == nil {
|
||||
@@ -202,11 +222,13 @@ func getMessageFromDocument(arg *gabs.Container) *models.Message {
|
||||
ID: stringOrZero(arg.Path("_id").Data()),
|
||||
RoomID: stringOrZero(arg.Path("rid").Data()),
|
||||
Msg: stringOrZero(arg.Path("msg").Data()),
|
||||
Type: stringOrZero(arg.Path("t").Data()),
|
||||
Timestamp: ts,
|
||||
User: &models.User{
|
||||
ID: stringOrZero(arg.Path("u._id").Data()),
|
||||
UserName: stringOrZero(arg.Path("u.username").Data()),
|
||||
},
|
||||
Attachments: attachments,
|
||||
}
|
||||
}
|
||||
|
||||
|
170
vendor/github.com/matterbridge/go-xmpp/xmpp.go
generated
vendored
170
vendor/github.com/matterbridge/go-xmpp/xmpp.go
generated
vendored
@@ -713,85 +713,119 @@ func (c *Client) Recv() (stanza interface{}, err error) {
|
||||
Errors: errsStr,
|
||||
}, nil
|
||||
}
|
||||
case v.Type == "result" && v.ID == "unsub1":
|
||||
// Unsubscribing MAY contain a pubsub element. But it does
|
||||
// not have to
|
||||
return PubsubUnsubscription{
|
||||
SubID: "",
|
||||
JID: v.From,
|
||||
Node: "",
|
||||
Errors: nil,
|
||||
}, nil
|
||||
case v.Query.XMLName.Local == "pubsub":
|
||||
case v.Type == "result":
|
||||
switch v.ID {
|
||||
case "sub1":
|
||||
// Subscription or unsubscription was successful
|
||||
var sub clientPubsubSubscription
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||
if err != nil {
|
||||
return PubsubSubscription{}, err
|
||||
}
|
||||
if v.Query.XMLName.Local == "pubsub" {
|
||||
// Subscription or unsubscription was successful
|
||||
var sub clientPubsubSubscription
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||
if err != nil {
|
||||
return PubsubSubscription{}, err
|
||||
}
|
||||
|
||||
return PubsubSubscription{
|
||||
SubID: sub.SubID,
|
||||
JID: sub.JID,
|
||||
Node: sub.Node,
|
||||
Errors: nil,
|
||||
}, nil
|
||||
case "unsub1":
|
||||
var sub clientPubsubSubscription
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||
if err != nil {
|
||||
return PubsubUnsubscription{}, err
|
||||
}
|
||||
|
||||
return PubsubUnsubscription{
|
||||
SubID: sub.SubID,
|
||||
JID: v.From,
|
||||
Node: sub.Node,
|
||||
Errors: nil,
|
||||
}, nil
|
||||
case "items1", "items3":
|
||||
var p clientPubsubItems
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
|
||||
if err != nil {
|
||||
return PubsubItems{}, err
|
||||
}
|
||||
|
||||
switch p.Node {
|
||||
case XMPPNS_AVATAR_PEP_DATA:
|
||||
return handleAvatarData(p.Items[0].Body,
|
||||
v.From,
|
||||
p.Items[0].ID)
|
||||
case XMPPNS_AVATAR_PEP_METADATA:
|
||||
return handleAvatarMetadata(p.Items[0].Body,
|
||||
v.From)
|
||||
default:
|
||||
return PubsubItems{
|
||||
p.Node,
|
||||
pubsubItemsToReturn(p.Items),
|
||||
return PubsubSubscription{
|
||||
SubID: sub.SubID,
|
||||
JID: sub.JID,
|
||||
Node: sub.Node,
|
||||
Errors: nil,
|
||||
}, nil
|
||||
}
|
||||
case "unsub1":
|
||||
if v.Query.XMLName.Local == "pubsub" {
|
||||
var sub clientPubsubSubscription
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &sub)
|
||||
if err != nil {
|
||||
return PubsubUnsubscription{}, err
|
||||
}
|
||||
|
||||
return PubsubUnsubscription{
|
||||
SubID: sub.SubID,
|
||||
JID: v.From,
|
||||
Node: sub.Node,
|
||||
Errors: nil,
|
||||
}, nil
|
||||
} else {
|
||||
// Unsubscribing MAY contain a pubsub element. But it does
|
||||
// not have to
|
||||
return PubsubUnsubscription{
|
||||
SubID: "",
|
||||
JID: v.From,
|
||||
Node: "",
|
||||
Errors: nil,
|
||||
}, nil
|
||||
}
|
||||
case "info1":
|
||||
if v.Query.XMLName.Space == XMPPNS_DISCO_ITEMS {
|
||||
var itemsQuery clientDiscoItemsQuery
|
||||
err := xml.Unmarshal(v.InnerXML, &itemsQuery)
|
||||
if err != nil {
|
||||
return []DiscoItem{}, err
|
||||
}
|
||||
|
||||
return DiscoItems{
|
||||
Jid: v.From,
|
||||
Items: clientDiscoItemsToReturn(itemsQuery.Items),
|
||||
}, nil
|
||||
}
|
||||
case "info3":
|
||||
if v.Query.XMLName.Space == XMPPNS_DISCO_INFO {
|
||||
var disco clientDiscoQuery
|
||||
err := xml.Unmarshal(v.InnerXML, &disco)
|
||||
if err != nil {
|
||||
return DiscoResult{}, err
|
||||
}
|
||||
|
||||
return DiscoResult{
|
||||
Features: clientFeaturesToReturn(disco.Features),
|
||||
Identities: clientIdentitiesToReturn(disco.Identities),
|
||||
}, nil
|
||||
}
|
||||
case "items1", "items3":
|
||||
if v.Query.XMLName.Local == "pubsub" {
|
||||
var p clientPubsubItems
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
|
||||
if err != nil {
|
||||
return PubsubItems{}, err
|
||||
}
|
||||
|
||||
switch p.Node {
|
||||
case XMPPNS_AVATAR_PEP_DATA:
|
||||
return handleAvatarData(p.Items[0].Body,
|
||||
v.From,
|
||||
p.Items[0].ID)
|
||||
case XMPPNS_AVATAR_PEP_METADATA:
|
||||
return handleAvatarMetadata(p.Items[0].Body,
|
||||
v.From)
|
||||
default:
|
||||
return PubsubItems{
|
||||
p.Node,
|
||||
pubsubItemsToReturn(p.Items),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
// Note: XEP-0084 states that metadata and data
|
||||
// should be fetched with an id of retrieve1.
|
||||
// Since we already have PubSub implemented, we
|
||||
// can just use items1 and items3 to do the same
|
||||
// as an Avatar node is just a PEP (PubSub) node.
|
||||
/*case "retrieve1":
|
||||
var p clientPubsubItems
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
|
||||
if err != nil {
|
||||
return PubsubItems{}, err
|
||||
}
|
||||
if v.Query.XMLName.Local == "pubsub" {
|
||||
var p clientPubsubItems
|
||||
err := xml.Unmarshal([]byte(v.Query.InnerXML), &p)
|
||||
if err != nil {
|
||||
return PubsubItems{}, err
|
||||
}
|
||||
|
||||
switch p.Node {
|
||||
case XMPPNS_AVATAR_PEP_DATA:
|
||||
return handleAvatarData(p.Items[0].Body,
|
||||
v.From,
|
||||
p.Items[0].ID)
|
||||
case XMPPNS_AVATAR_PEP_METADATA:
|
||||
return handleAvatarMetadata(p.Items[0].Body,
|
||||
v
|
||||
switch p.Node {
|
||||
case XMPPNS_AVATAR_PEP_DATA:
|
||||
return handleAvatarData(p.Items[0].Body,
|
||||
v.From,
|
||||
p.Items[0].ID)
|
||||
case XMPPNS_AVATAR_PEP_METADATA:
|
||||
return handleAvatarMetadata(p.Items[0].Body,
|
||||
v.From)
|
||||
}
|
||||
}*/
|
||||
}
|
||||
case v.Query.XMLName.Local == "":
|
||||
@@ -1049,6 +1083,8 @@ type clientIQ struct {
|
||||
Query XMLElement `xml:",any"`
|
||||
Error clientError
|
||||
Bind bindBind
|
||||
|
||||
InnerXML []byte `xml:",innerxml"`
|
||||
}
|
||||
|
||||
type clientError struct {
|
||||
|
99
vendor/github.com/matterbridge/go-xmpp/xmpp_disco.go
generated
vendored
Normal file
99
vendor/github.com/matterbridge/go-xmpp/xmpp_disco.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
package xmpp
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
)
|
||||
|
||||
const (
|
||||
XMPPNS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"
|
||||
XMPPNS_DISCO_INFO = "http://jabber.org/protocol/disco#info"
|
||||
)
|
||||
|
||||
type clientDiscoFeature struct {
|
||||
XMLName xml.Name `xml:"feature"`
|
||||
Var string `xml:"var,attr"`
|
||||
}
|
||||
|
||||
type clientDiscoIdentity struct {
|
||||
XMLName xml.Name `xml:"identity"`
|
||||
Category string `xml:"category,attr"`
|
||||
Type string `xml:"type,attr"`
|
||||
Name string `xml:"name,attr"`
|
||||
}
|
||||
|
||||
type clientDiscoQuery struct {
|
||||
XMLName xml.Name `xml:"query"`
|
||||
Features []clientDiscoFeature `xml:"feature"`
|
||||
Identities []clientDiscoIdentity `xml:"identity"`
|
||||
}
|
||||
|
||||
type clientDiscoItem struct {
|
||||
XMLName xml.Name `xml:"item"`
|
||||
Jid string `xml:"jid,attr"`
|
||||
Node string `xml:"node,attr"`
|
||||
Name string `xml:"name,attr"`
|
||||
}
|
||||
|
||||
type clientDiscoItemsQuery struct {
|
||||
XMLName xml.Name `xml:"query"`
|
||||
Items []clientDiscoItem `xml:"item"`
|
||||
}
|
||||
|
||||
type DiscoIdentity struct {
|
||||
Category string
|
||||
Type string
|
||||
Name string
|
||||
}
|
||||
|
||||
type DiscoItem struct {
|
||||
Jid string
|
||||
Name string
|
||||
Node string
|
||||
}
|
||||
|
||||
type DiscoResult struct {
|
||||
Features []string
|
||||
Identities []DiscoIdentity
|
||||
}
|
||||
|
||||
type DiscoItems struct {
|
||||
Jid string
|
||||
Items []DiscoItem
|
||||
}
|
||||
|
||||
func clientFeaturesToReturn(features []clientDiscoFeature) []string {
|
||||
var ret []string
|
||||
|
||||
for _, feature := range features {
|
||||
ret = append(ret, feature.Var)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func clientIdentitiesToReturn(identities []clientDiscoIdentity) []DiscoIdentity {
|
||||
var ret []DiscoIdentity
|
||||
|
||||
for _, id := range identities {
|
||||
ret = append(ret, DiscoIdentity{
|
||||
Category: id.Category,
|
||||
Type: id.Type,
|
||||
Name: id.Name,
|
||||
})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func clientDiscoItemsToReturn(items []clientDiscoItem) []DiscoItem {
|
||||
var ret []DiscoItem
|
||||
for _, item := range items {
|
||||
ret = append(ret, DiscoItem{
|
||||
Jid: item.Jid,
|
||||
Name: item.Name,
|
||||
Node: item.Node,
|
||||
})
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
20
vendor/github.com/matterbridge/go-xmpp/xmpp_information_query.go
generated
vendored
20
vendor/github.com/matterbridge/go-xmpp/xmpp_information_query.go
generated
vendored
@@ -10,10 +10,26 @@ const IQTypeSet = "set"
|
||||
const IQTypeResult = "result"
|
||||
|
||||
func (c *Client) Discovery() (string, error) {
|
||||
const namespace = "http://jabber.org/protocol/disco#items"
|
||||
// use getCookie for a pseudo random id.
|
||||
reqID := strconv.FormatUint(uint64(getCookie()), 10)
|
||||
return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, namespace, "")
|
||||
return c.RawInformationQuery(c.jid, c.domain, reqID, IQTypeGet, XMPPNS_DISCO_ITEMS, "")
|
||||
}
|
||||
|
||||
// Discover information about a node
|
||||
func (c *Client) DiscoverNodeInfo(node string) (string, error) {
|
||||
query := fmt.Sprintf("<query xmlns='%s' node='%s'/>", XMPPNS_DISCO_INFO, node)
|
||||
return c.RawInformation(c.jid, c.domain, "info3", IQTypeGet, query)
|
||||
}
|
||||
|
||||
// Discover items that the server exposes
|
||||
func (c *Client) DiscoverServerItems() (string, error) {
|
||||
return c.DiscoverEntityItems(c.domain)
|
||||
}
|
||||
|
||||
// Discover items that an entity exposes
|
||||
func (c *Client) DiscoverEntityItems(jid string) (string, error) {
|
||||
query := fmt.Sprintf("<query xmlns='%s'/>", XMPPNS_DISCO_ITEMS)
|
||||
return c.RawInformation(c.jid, jid, "info1", IQTypeGet, query)
|
||||
}
|
||||
|
||||
// RawInformationQuery sends an information query request to the server.
|
||||
|
6
vendor/modules.txt
vendored
6
vendor/modules.txt
vendored
@@ -15,7 +15,7 @@ github.com/Philipp15b/go-steam/protocol/steamlang
|
||||
github.com/Philipp15b/go-steam/rwu
|
||||
github.com/Philipp15b/go-steam/socialcache
|
||||
github.com/Philipp15b/go-steam/steamid
|
||||
# github.com/Rhymen/go-whatsapp v0.1.0
|
||||
# github.com/Rhymen/go-whatsapp v0.1.1-0.20200421062035-31e8111ac334
|
||||
github.com/Rhymen/go-whatsapp
|
||||
github.com/Rhymen/go-whatsapp/binary
|
||||
github.com/Rhymen/go-whatsapp/binary/proto
|
||||
@@ -95,7 +95,7 @@ github.com/labstack/gommon/random
|
||||
github.com/lrstanley/girc
|
||||
# github.com/magiconair/properties v1.8.1
|
||||
github.com/magiconair/properties
|
||||
# github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20190210153444-cc9d05784d5d
|
||||
# github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20200411204219-d5c18ce75048
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK/models
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK/realtime
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK/rest
|
||||
@@ -103,7 +103,7 @@ github.com/matterbridge/Rocket.Chat.Go.SDK/rest
|
||||
github.com/matterbridge/discordgo
|
||||
# github.com/matterbridge/emoji v2.1.1-0.20191117213217-af507f6b02db+incompatible
|
||||
github.com/matterbridge/emoji
|
||||
# github.com/matterbridge/go-xmpp v0.0.0-20200329150250-5812999b292b
|
||||
# github.com/matterbridge/go-xmpp v0.0.0-20200418225040-c8a3a57b4050
|
||||
github.com/matterbridge/go-xmpp
|
||||
# github.com/matterbridge/gomatrix v0.0.0-20200209224845-c2104d7936a6
|
||||
github.com/matterbridge/gomatrix
|
||||
|
Reference in New Issue
Block a user