mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-21 10:12:00 -08: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)
|
||||
|
||||
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.
|
||||
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/)
|
||||
* [Twitch](https://twitch.tv)
|
||||
* [Ssh-chat](https://github.com/shazow/ssh-chat)
|
||||
* [Zulip](https://zulipchat.com)
|
||||
|
||||
# Screenshots
|
||||
See https://github.com/42wim/matterbridge/wiki
|
||||
@ -189,6 +190,7 @@ Matterbridge wouldn't exist without these libraries:
|
||||
* echo - https://github.com/labstack/echo
|
||||
* gitter - https://github.com/sromku/go-gitter
|
||||
* gops - https://github.com/google/gops
|
||||
* gozulipbot - https://github.com/ifo/gozulipbot
|
||||
* irc - https://github.com/lrstanley/girc
|
||||
* mattermost - https://github.com/mattermost/platform
|
||||
* matrix - https://github.com/matrix-org/gomatrix
|
||||
|
@ -107,6 +107,7 @@ type Protocol struct {
|
||||
StripNick bool // all protocols
|
||||
Team string // mattermost
|
||||
Token string // gitter, slack, discord, api
|
||||
Topic string // zulip
|
||||
URL string // mattermost, slack // DEPRECATED
|
||||
UseAPI bool // mattermost, slack
|
||||
UseSASL bool // IRC
|
||||
@ -159,6 +160,7 @@ type ConfigValues struct {
|
||||
Telegram map[string]Protocol
|
||||
Rocketchat map[string]Protocol
|
||||
Sshchat map[string]Protocol
|
||||
Zulip map[string]Protocol
|
||||
General Protocol
|
||||
Gateway []Gateway
|
||||
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/telegram"
|
||||
"github.com/42wim/matterbridge/bridge/xmpp"
|
||||
"github.com/42wim/matterbridge/bridge/zulip"
|
||||
log "github.com/sirupsen/logrus"
|
||||
// "github.com/davecgh/go-spew/spew"
|
||||
"crypto/sha1"
|
||||
@ -62,6 +63,7 @@ var bridgeMap = map[string]bridge.Factory{
|
||||
"steam": bsteam.New,
|
||||
"telegram": btelegram.New,
|
||||
"xmpp": bxmpp.New,
|
||||
"zulip": bzulip.New,
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
@ -1155,6 +1155,90 @@ StripNick=false
|
||||
#OPTIONAL (default 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
|
||||
###################################################################
|
||||
@ -1283,6 +1367,7 @@ enable=true
|
||||
# - encrypted rooms are not supported in matrix
|
||||
#steam - chatid (a large number).
|
||||
# The number in the URL when you click "enter chat room" in the browser
|
||||
#zulip - stream (without the #)
|
||||
#
|
||||
#REQUIRED
|
||||
channel="#testing"
|
||||
|
Loading…
Reference in New Issue
Block a user