forked from jshiffer/matterbridge
Add REST API support
This commit is contained in:
parent
930b639cc9
commit
73f01ad8d8
@ -1,13 +1,14 @@
|
|||||||
# matterbridge
|
# matterbridge
|
||||||
![matterbridge.gif](https://s15.postimg.org/qpjhp6y3f/matterbridge.gif)
|
![matterbridge.gif](https://s15.postimg.org/qpjhp6y3f/matterbridge.gif)
|
||||||
|
|
||||||
Simple bridge between mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat and Hipchat(via xmpp).
|
Simple bridge between mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat and Hipchat(via xmpp) with REST API.
|
||||||
|
|
||||||
* Relays public channel messages between multiple mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat and Hipchat (via xmpp). Pick and mix.
|
* Relays public channel messages between multiple mattermost, IRC, XMPP, Gitter, Slack, Discord, Telegram, Rocket.Chat and Hipchat (via xmpp). Pick and mix.
|
||||||
* Supports multiple channels.
|
* Supports multiple channels.
|
||||||
* Matterbridge can also work with private groups on your mattermost.
|
* Matterbridge can also work with private groups on your mattermost.
|
||||||
* Allow for bridging the same bridges, which means you can eg bridge between multiple mattermosts.
|
* Allow for bridging the same bridges, which means you can eg bridge between multiple mattermosts.
|
||||||
* The bridge is now a gateway which has support multiple in and out bridges. (and supports multiple gateways).
|
* The bridge is now a gateway which has support multiple in and out bridges. (and supports multiple gateways).
|
||||||
|
* REST API to read/post messages to bridges (WIP)
|
||||||
|
|
||||||
Look at [matterbridge.toml.sample] (https://github.com/42wim/matterbridge/blob/master/matterbridge.toml.sample) for documentation and an example.
|
Look at [matterbridge.toml.sample] (https://github.com/42wim/matterbridge/blob/master/matterbridge.toml.sample) for documentation and an example.
|
||||||
Look at [matterbridge.toml.simple] (https://github.com/42wim/matterbridge/blob/master/matterbridge.toml.simple) for a simple example.
|
Look at [matterbridge.toml.simple] (https://github.com/42wim/matterbridge/blob/master/matterbridge.toml.simple) for a simple example.
|
||||||
|
91
bridge/api/api.go
Normal file
91
bridge/api/api.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
|
log "github.com/Sirupsen/logrus"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
"github.com/zfjagann/golang-ring"
|
||||||
|
"net/http"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Api struct {
|
||||||
|
Config *config.Protocol
|
||||||
|
Remote chan config.Message
|
||||||
|
Account string
|
||||||
|
Messages ring.Ring
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiMessage struct {
|
||||||
|
Text string `json:"text"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Avatar string `json:"avatar"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var flog *log.Entry
|
||||||
|
var protocol = "api"
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
flog = log.WithFields(log.Fields{"module": protocol})
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(cfg config.Protocol, account string, c chan config.Message) *Api {
|
||||||
|
b := &Api{}
|
||||||
|
e := echo.New()
|
||||||
|
b.Messages = ring.Ring{}
|
||||||
|
b.Messages.SetCapacity(cfg.Buffer)
|
||||||
|
b.Config = &cfg
|
||||||
|
b.Account = account
|
||||||
|
b.Remote = c
|
||||||
|
e.GET("/api/messages", b.handleMessages)
|
||||||
|
e.POST("/api/message", b.handlePostMessage)
|
||||||
|
go func() {
|
||||||
|
flog.Fatal(e.Start(cfg.BindAddress))
|
||||||
|
}()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Api) Connect() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (b *Api) Disconnect() error {
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
func (b *Api) JoinChannel(channel string) error {
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Api) Send(msg config.Message) error {
|
||||||
|
b.Lock()
|
||||||
|
defer b.Unlock()
|
||||||
|
b.Messages.Enqueue(&msg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Api) handlePostMessage(c echo.Context) error {
|
||||||
|
message := &ApiMessage{}
|
||||||
|
if err := c.Bind(message); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.Remote <- config.Message{
|
||||||
|
Text: message.Text,
|
||||||
|
Username: message.Username,
|
||||||
|
Channel: "api",
|
||||||
|
Avatar: message.Avatar,
|
||||||
|
Account: b.Account,
|
||||||
|
}
|
||||||
|
return c.JSON(http.StatusOK, message)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Api) handleMessages(c echo.Context) error {
|
||||||
|
b.Lock()
|
||||||
|
defer b.Unlock()
|
||||||
|
for _, msg := range b.Messages.Values() {
|
||||||
|
c.JSONPretty(http.StatusOK, msg, " ")
|
||||||
|
}
|
||||||
|
b.Messages = ring.Ring{}
|
||||||
|
return nil
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package bridge
|
package bridge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/42wim/matterbridge/bridge/api"
|
||||||
"github.com/42wim/matterbridge/bridge/config"
|
"github.com/42wim/matterbridge/bridge/config"
|
||||||
"github.com/42wim/matterbridge/bridge/discord"
|
"github.com/42wim/matterbridge/bridge/discord"
|
||||||
"github.com/42wim/matterbridge/bridge/gitter"
|
"github.com/42wim/matterbridge/bridge/gitter"
|
||||||
@ -70,6 +71,9 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid
|
|||||||
case "rocketchat":
|
case "rocketchat":
|
||||||
b.Config = cfg.Rocketchat[name]
|
b.Config = cfg.Rocketchat[name]
|
||||||
b.Bridger = brocketchat.New(cfg.Rocketchat[name], bridge.Account, c)
|
b.Bridger = brocketchat.New(cfg.Rocketchat[name], bridge.Account, c)
|
||||||
|
case "api":
|
||||||
|
b.Config = cfg.Api[name]
|
||||||
|
b.Bridger = api.New(cfg.Api[name], bridge.Account, c)
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -14,16 +15,19 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
Text string
|
Text string
|
||||||
Channel string
|
Channel string
|
||||||
Username string
|
Username string
|
||||||
Avatar string
|
Avatar string
|
||||||
Account string
|
Account string
|
||||||
Event string
|
Event string
|
||||||
|
Protocol string
|
||||||
|
Timestamp time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type Protocol struct {
|
type Protocol struct {
|
||||||
BindAddress string // mattermost, slack
|
BindAddress string // mattermost, slack
|
||||||
|
Buffer int // api
|
||||||
IconURL string // mattermost, slack
|
IconURL string // mattermost, slack
|
||||||
IgnoreNicks string // all protocols
|
IgnoreNicks string // all protocols
|
||||||
Jid string // xmpp
|
Jid string // xmpp
|
||||||
@ -79,6 +83,7 @@ type SameChannelGateway struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
Api map[string]Protocol
|
||||||
IRC map[string]Protocol
|
IRC map[string]Protocol
|
||||||
Mattermost map[string]Protocol
|
Mattermost map[string]Protocol
|
||||||
Slack map[string]Protocol
|
Slack map[string]Protocol
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
# v0.9.3-dev
|
# v0.9.3-dev
|
||||||
|
## New features
|
||||||
|
* API: rest interface to read / post messages (see API section in matterbridge.toml.sample)
|
||||||
|
|
||||||
## Bugfix
|
## Bugfix
|
||||||
* slack: fix receiving messages from private channels #118
|
* slack: fix receiving messages from private channels #118
|
||||||
* slack: fix echo when using webhooks #119
|
* slack: fix echo when using webhooks #119
|
||||||
|
@ -86,6 +86,7 @@ func (gw *Gateway) handleReceive() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !gw.ignoreMessage(&msg) {
|
if !gw.ignoreMessage(&msg) {
|
||||||
|
msg.Timestamp = time.Now()
|
||||||
for _, br := range gw.Bridges {
|
for _, br := range gw.Bridges {
|
||||||
gw.handleMessage(msg, br)
|
gw.handleMessage(msg, br)
|
||||||
}
|
}
|
||||||
@ -165,6 +166,10 @@ func (gw *Gateway) handleMessage(msg config.Message, dest *bridge.Bridge) {
|
|||||||
}
|
}
|
||||||
log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel)
|
log.Debugf("Sending %#v from %s (%s) to %s (%s)", msg, msg.Account, originchannel, dest.Account, channel)
|
||||||
gw.modifyUsername(&msg, dest)
|
gw.modifyUsername(&msg, dest)
|
||||||
|
// for api we need originchannel as channel
|
||||||
|
if dest.Protocol == "api" {
|
||||||
|
msg.Channel = originchannel
|
||||||
|
}
|
||||||
err := dest.Send(msg)
|
err := dest.Send(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@ -199,6 +204,7 @@ func (gw *Gateway) modifyMessage(msg *config.Message, dest *bridge.Bridge) {
|
|||||||
|
|
||||||
func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) {
|
func (gw *Gateway) modifyUsername(msg *config.Message, dest *bridge.Bridge) {
|
||||||
br := gw.Bridges[msg.Account]
|
br := gw.Bridges[msg.Account]
|
||||||
|
msg.Protocol = br.Protocol
|
||||||
nick := gw.Config.General.RemoteNickFormat
|
nick := gw.Config.General.RemoteNickFormat
|
||||||
if nick == "" {
|
if nick == "" {
|
||||||
nick = dest.Config.RemoteNickFormat
|
nick = dest.Config.RemoteNickFormat
|
||||||
|
@ -486,6 +486,28 @@ RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
|
|||||||
#OPTIONAL (default false)
|
#OPTIONAL (default false)
|
||||||
ShowJoinPart=false
|
ShowJoinPart=false
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
#API
|
||||||
|
###################################################################
|
||||||
|
[api]
|
||||||
|
#You can configure multiple API hooks
|
||||||
|
#In this example we use [api.local]
|
||||||
|
#REQUIRED
|
||||||
|
|
||||||
|
[api.local]
|
||||||
|
#Address to listen on for API
|
||||||
|
#REQUIRED
|
||||||
|
BindAddress="127.0.0.1:4242"
|
||||||
|
|
||||||
|
#Amount of messages to keep in memory
|
||||||
|
Buffer=1000
|
||||||
|
|
||||||
|
#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 "{PROTOCOL}" (case sensitive) will be replaced by the protocol used by the bridge
|
||||||
|
#OPTIONAL (default empty)
|
||||||
|
RemoteNickFormat="{NICK}"
|
||||||
|
|
||||||
###################################################################
|
###################################################################
|
||||||
#General configuration
|
#General configuration
|
||||||
@ -572,6 +594,13 @@ enable=true
|
|||||||
#OPTIONAL - your irc channel key
|
#OPTIONAL - your irc channel key
|
||||||
key="yourkey"
|
key="yourkey"
|
||||||
|
|
||||||
|
#API example
|
||||||
|
#[[gateway.inout]]
|
||||||
|
#account="api.local"
|
||||||
|
#channel="api"
|
||||||
|
#To send data to the api:
|
||||||
|
#curl -XPOST -H 'Content-Type: application/json' -d '{"text":"test","username":"randomuser"}' http://localhost:4242/api/message
|
||||||
|
|
||||||
#If you want to do a 1:1 mapping between protocols where the channelnames are the same
|
#If you want to do a 1:1 mapping between protocols where the channelnames are the same
|
||||||
#e.g. slack and mattermost you can use the samechannelgateway configuration
|
#e.g. slack and mattermost you can use the samechannelgateway configuration
|
||||||
#the example configuration below send messages from channel testing on mattermost to
|
#the example configuration below send messages from channel testing on mattermost to
|
||||||
|
Loading…
Reference in New Issue
Block a user