mirror of
https://github.com/cwinfo/matterbridge.git
synced 2024-11-22 12:50:27 +00:00
Add initial zulip support
This commit is contained in:
parent
1605fbc012
commit
45296100df
@ -7,7 +7,7 @@ Click on one of the badges below to join the chat
|
|||||||
|
|
||||||
![matterbridge.gif](https://github.com/42wim/matterbridge/blob/master/img/matterbridge.gif)
|
![matterbridge.gif](https://github.com/42wim/matterbridge/blob/master/img/matterbridge.gif)
|
||||||
|
|
||||||
Simple bridge between IRC, XMPP, Gitter, Mattermost, Slack, Discord, Telegram, Rocket.Chat, Hipchat(via xmpp), Matrix, Steam and ssh-chat
|
Simple bridge between IRC, XMPP, Gitter, Mattermost, Slack, Discord, Telegram, Rocket.Chat, Hipchat(via xmpp), Matrix, Steam, ssh-chat and Zulip
|
||||||
Has a REST API.
|
Has a REST API.
|
||||||
Minecraft server chat support via [MatterLink](https://github.com/elytra/MatterLink)
|
Minecraft server chat support via [MatterLink](https://github.com/elytra/MatterLink)
|
||||||
|
|
||||||
@ -62,6 +62,7 @@ Accounts to one of the supported bridges
|
|||||||
* [Steam](https://store.steampowered.com/)
|
* [Steam](https://store.steampowered.com/)
|
||||||
* [Twitch](https://twitch.tv)
|
* [Twitch](https://twitch.tv)
|
||||||
* [Ssh-chat](https://github.com/shazow/ssh-chat)
|
* [Ssh-chat](https://github.com/shazow/ssh-chat)
|
||||||
|
* [Zulip](https://zulipchat.com)
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
See https://github.com/42wim/matterbridge/wiki
|
See https://github.com/42wim/matterbridge/wiki
|
||||||
@ -189,6 +190,7 @@ Matterbridge wouldn't exist without these libraries:
|
|||||||
* echo - https://github.com/labstack/echo
|
* echo - https://github.com/labstack/echo
|
||||||
* gitter - https://github.com/sromku/go-gitter
|
* gitter - https://github.com/sromku/go-gitter
|
||||||
* gops - https://github.com/google/gops
|
* gops - https://github.com/google/gops
|
||||||
|
* gozulipbot - https://github.com/ifo/gozulipbot
|
||||||
* irc - https://github.com/lrstanley/girc
|
* irc - https://github.com/lrstanley/girc
|
||||||
* mattermost - https://github.com/mattermost/platform
|
* mattermost - https://github.com/mattermost/platform
|
||||||
* matrix - https://github.com/matrix-org/gomatrix
|
* matrix - https://github.com/matrix-org/gomatrix
|
||||||
|
@ -107,6 +107,7 @@ type Protocol struct {
|
|||||||
StripNick bool // all protocols
|
StripNick bool // all protocols
|
||||||
Team string // mattermost
|
Team string // mattermost
|
||||||
Token string // gitter, slack, discord, api
|
Token string // gitter, slack, discord, api
|
||||||
|
Topic string // zulip
|
||||||
URL string // mattermost, slack // DEPRECATED
|
URL string // mattermost, slack // DEPRECATED
|
||||||
UseAPI bool // mattermost, slack
|
UseAPI bool // mattermost, slack
|
||||||
UseSASL bool // IRC
|
UseSASL bool // IRC
|
||||||
@ -159,6 +160,7 @@ type ConfigValues struct {
|
|||||||
Telegram map[string]Protocol
|
Telegram map[string]Protocol
|
||||||
Rocketchat map[string]Protocol
|
Rocketchat map[string]Protocol
|
||||||
Sshchat map[string]Protocol
|
Sshchat map[string]Protocol
|
||||||
|
Zulip map[string]Protocol
|
||||||
General Protocol
|
General Protocol
|
||||||
Gateway []Gateway
|
Gateway []Gateway
|
||||||
SameChannelGateway []SameChannelGateway
|
SameChannelGateway []SameChannelGateway
|
||||||
|
170
bridge/zulip/zulip.go
Normal file
170
bridge/zulip/zulip.go
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
package bzulip
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/42wim/matterbridge/bridge"
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
"github.com/42wim/matterbridge/bridge/helper"
|
||||||
|
gzb "github.com/matterbridge/gozulipbot"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Bzulip struct {
|
||||||
|
q *gzb.Queue
|
||||||
|
bot *gzb.Bot
|
||||||
|
streams map[int]string
|
||||||
|
*bridge.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg *bridge.Config) bridge.Bridger {
|
||||||
|
return &Bzulip{Config: cfg, streams: make(map[int]string)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Connect() error {
|
||||||
|
bot := gzb.Bot{APIKey: b.GetString("token"), APIURL: b.GetString("server") + "/api/v1/", Email: b.GetString("login")}
|
||||||
|
bot.Init()
|
||||||
|
q, err := bot.RegisterAll()
|
||||||
|
b.q = q
|
||||||
|
b.bot = &bot
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("Connect() %#v", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// init stream
|
||||||
|
b.getChannel(0)
|
||||||
|
b.Log.Info("Connection succeeded")
|
||||||
|
go b.handleQueue()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Disconnect() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) JoinChannel(channel config.ChannelInfo) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) Send(msg config.Message) (string, error) {
|
||||||
|
b.Log.Debugf("=> Receiving %#v", msg)
|
||||||
|
|
||||||
|
// Delete message
|
||||||
|
if msg.Event == config.EVENT_MSG_DELETE {
|
||||||
|
if msg.ID == "" {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
_, err := b.bot.UpdateMessage(msg.ID, "")
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload a file if it exists
|
||||||
|
if msg.Extra != nil {
|
||||||
|
for _, rmsg := range helper.HandleExtra(&msg, b.General) {
|
||||||
|
b.sendMessage(rmsg)
|
||||||
|
}
|
||||||
|
if len(msg.Extra["file"]) > 0 {
|
||||||
|
return b.handleUploadFile(&msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// edit the message if we have a msg ID
|
||||||
|
if msg.ID != "" {
|
||||||
|
_, err := b.bot.UpdateMessage(msg.ID, msg.Username+msg.Text)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post normal message
|
||||||
|
return b.sendMessage(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) getChannel(id int) string {
|
||||||
|
if name, ok := b.streams[id]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
streams, err := b.bot.GetRawStreams()
|
||||||
|
if err != nil {
|
||||||
|
b.Log.Errorf("getChannel: %#v", err)
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
for _, stream := range streams.Streams {
|
||||||
|
b.streams[stream.StreamID] = stream.Name
|
||||||
|
}
|
||||||
|
if name, ok := b.streams[id]; ok {
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) handleQueue() error {
|
||||||
|
for {
|
||||||
|
messages, _ := b.q.GetEvents()
|
||||||
|
for _, m := range messages {
|
||||||
|
b.Log.Debugf("== Receiving %#v", m)
|
||||||
|
// ignore our own messages
|
||||||
|
if m.SenderEmail == b.GetString("login") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
rmsg := config.Message{Username: m.SenderFullName, Text: m.Content, Channel: b.getChannel(m.StreamID), Account: b.Account, UserID: strconv.Itoa(m.SenderID), Avatar: m.AvatarURL}
|
||||||
|
b.Log.Debugf("<= Sending message from %s on %s to gateway", rmsg.Username, b.Account)
|
||||||
|
b.Log.Debugf("<= Message is %#v", rmsg)
|
||||||
|
b.Remote <- rmsg
|
||||||
|
b.q.LastEventID = m.ID
|
||||||
|
}
|
||||||
|
time.Sleep(time.Second * 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) sendMessage(msg config.Message) (string, error) {
|
||||||
|
topic := "matterbridge"
|
||||||
|
if b.GetString("topic") != "" {
|
||||||
|
topic = b.GetString("topic")
|
||||||
|
}
|
||||||
|
m := gzb.Message{
|
||||||
|
Stream: msg.Channel,
|
||||||
|
Topic: topic,
|
||||||
|
Content: msg.Username + msg.Text,
|
||||||
|
}
|
||||||
|
resp, err := b.bot.Message(m)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
defer resp.Body.Close()
|
||||||
|
res, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
var jr struct {
|
||||||
|
ID int `json:"id"`
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(res, &jr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strconv.Itoa(jr.ID), nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Bzulip) handleUploadFile(msg *config.Message) (string, error) {
|
||||||
|
for _, f := range msg.Extra["file"] {
|
||||||
|
fi := f.(config.FileInfo)
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text += fi.Comment + ": "
|
||||||
|
}
|
||||||
|
if fi.URL != "" {
|
||||||
|
msg.Text = fi.URL
|
||||||
|
if fi.Comment != "" {
|
||||||
|
msg.Text = fi.Comment + ": " + fi.URL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err := b.sendMessage(*msg)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/42wim/matterbridge/bridge/steam"
|
"github.com/42wim/matterbridge/bridge/steam"
|
||||||
"github.com/42wim/matterbridge/bridge/telegram"
|
"github.com/42wim/matterbridge/bridge/telegram"
|
||||||
"github.com/42wim/matterbridge/bridge/xmpp"
|
"github.com/42wim/matterbridge/bridge/xmpp"
|
||||||
|
"github.com/42wim/matterbridge/bridge/zulip"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
// "github.com/davecgh/go-spew/spew"
|
// "github.com/davecgh/go-spew/spew"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
@ -62,6 +63,7 @@ var bridgeMap = map[string]bridge.Factory{
|
|||||||
"steam": bsteam.New,
|
"steam": bsteam.New,
|
||||||
"telegram": btelegram.New,
|
"telegram": btelegram.New,
|
||||||
"xmpp": bxmpp.New,
|
"xmpp": bxmpp.New,
|
||||||
|
"zulip": bzulip.New,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -1155,6 +1155,90 @@ StripNick=false
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowTopicChange=false
|
ShowTopicChange=false
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
#zulip section
|
||||||
|
###################################################################
|
||||||
|
[zulip]
|
||||||
|
#You can configure multiple servers "[zulip.name]" or "[zulip.name2]"
|
||||||
|
#In this example we use [zulip.streamchat]
|
||||||
|
#REQUIRED
|
||||||
|
|
||||||
|
[zulip.streamchat]
|
||||||
|
#Token to connect with zulip API (called bot API key in Settings - Your bots)
|
||||||
|
#REQUIRED
|
||||||
|
Token="Yourtokenhere"
|
||||||
|
|
||||||
|
#Username of the bot, normally called yourbot-bot@yourserver.zulipchat.com
|
||||||
|
#See username in Settings - Your bots
|
||||||
|
#REQUIRED
|
||||||
|
Login="yourbot-bot@yourserver.zulipchat.com"
|
||||||
|
|
||||||
|
#Servername of your zulip instance
|
||||||
|
#REQUIRED
|
||||||
|
Server="https://yourserver.zulipchat.com"
|
||||||
|
|
||||||
|
#Topic of the messages matterbridge will use
|
||||||
|
#OPTIONAL (default "matterbridge")
|
||||||
|
Topic="matterbridge"
|
||||||
|
|
||||||
|
## RELOADABLE SETTINGS
|
||||||
|
## Settings below can be reloaded by editing the file
|
||||||
|
|
||||||
|
#Nicks you want to ignore.
|
||||||
|
#Messages from those users will not be sent to other bridges.
|
||||||
|
#OPTIONAL
|
||||||
|
IgnoreNicks="spammer1 spammer2"
|
||||||
|
|
||||||
|
#Messages you want to ignore.
|
||||||
|
#Messages matching these regexp will be ignored and not sent to other bridges
|
||||||
|
#See https://regex-golang.appspot.com/assets/html/index.html for more regex info
|
||||||
|
#OPTIONAL (example below ignores messages starting with ~~ or messages containing badword
|
||||||
|
IgnoreMessages="^~~ badword"
|
||||||
|
|
||||||
|
#messages you want to replace.
|
||||||
|
#it replaces outgoing messages from the bridge.
|
||||||
|
#so you need to place it by the sending bridge definition.
|
||||||
|
#regular expressions supported
|
||||||
|
#some examples:
|
||||||
|
#this replaces cat => dog and sleep => awake
|
||||||
|
#replacemessages=[ ["cat","dog"], ["sleep","awake"] ]
|
||||||
|
#this replaces every number with number. 123 => numbernumbernumber
|
||||||
|
#replacemessages=[ ["[0-9]","number"] ]
|
||||||
|
#optional (default empty)
|
||||||
|
ReplaceMessages=[ ["cat","dog"] ]
|
||||||
|
|
||||||
|
#nicks you want to replace.
|
||||||
|
#see replacemessages for syntaxa
|
||||||
|
#optional (default empty)
|
||||||
|
ReplaceNicks=[ ["user--","user"] ]
|
||||||
|
|
||||||
|
#extra label that can be used in the RemoteNickFormat
|
||||||
|
#optional (default empty)
|
||||||
|
Label=""
|
||||||
|
|
||||||
|
#RemoteNickFormat defines how remote users appear on this bridge
|
||||||
|
#The string "{NICK}" (case sensitive) will be replaced by the actual nick / username.
|
||||||
|
#The string "{BRIDGE}" (case sensitive) will be replaced by the sending bridge
|
||||||
|
#The string "{LABEL}" (case sensitive) will be replaced by label= field of the sending bridge
|
||||||
|
#The string "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
|
#OPTIONAL (default empty)
|
||||||
|
RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
||||||
|
|
||||||
|
#Enable to show users joins/parts from other bridges
|
||||||
|
#Currently works for messages from the following bridges: irc, mattermost, slack
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
#StripNick only allows alphanumerical nicks. See https://github.com/42wim/matterbridge/issues/285
|
||||||
|
#It will strip other characters from the nick
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
StripNick=false
|
||||||
|
|
||||||
|
#Enable to show topic changes from other bridges
|
||||||
|
#Only works hiding/show topic changes from slack bridge for now
|
||||||
|
#OPTIONAL (default false)
|
||||||
|
ShowTopicChange=false
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#API
|
#API
|
||||||
###################################################################
|
###################################################################
|
||||||
@ -1283,6 +1367,7 @@ enable=true
|
|||||||
# - encrypted rooms are not supported in matrix
|
# - encrypted rooms are not supported in matrix
|
||||||
#steam - chatid (a large number).
|
#steam - chatid (a large number).
|
||||||
# The number in the URL when you click "enter chat room" in the browser
|
# The number in the URL when you click "enter chat room" in the browser
|
||||||
|
#zulip - stream (without the #)
|
||||||
#
|
#
|
||||||
#REQUIRED
|
#REQUIRED
|
||||||
channel="#testing"
|
channel="#testing"
|
||||||
|
Loading…
Reference in New Issue
Block a user