summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWim <wim@42.be>2017-06-22 01:02:05 +0200
committerWim <wim@42.be>2017-06-22 01:02:05 +0200
commit276ac840aacf01532ef33f0d461775daacb23880 (patch)
tree6047f397f28eb2080aca3e96d9631a37be914c44
parent1f914618538920db4bfec7b106ee97038b157c9b (diff)
downloadmatterbridge-msglm-276ac840aacf01532ef33f0d461775daacb23880.tar.gz
matterbridge-msglm-276ac840aacf01532ef33f0d461775daacb23880.tar.bz2
matterbridge-msglm-276ac840aacf01532ef33f0d461775daacb23880.zip
Add initial steam support
-rw-r--r--bridge/bridge.go4
-rw-r--r--bridge/config/config.go2
-rw-r--r--bridge/steam/steam.go158
-rw-r--r--matterbridge.toml.sample52
4 files changed, 216 insertions, 0 deletions
diff --git a/bridge/bridge.go b/bridge/bridge.go
index fa00ea44..2cf56c0b 100644
--- a/bridge/bridge.go
+++ b/bridge/bridge.go
@@ -10,6 +10,7 @@ import (
"github.com/42wim/matterbridge/bridge/mattermost"
"github.com/42wim/matterbridge/bridge/rocketchat"
"github.com/42wim/matterbridge/bridge/slack"
+ "github.com/42wim/matterbridge/bridge/steam"
"github.com/42wim/matterbridge/bridge/telegram"
"github.com/42wim/matterbridge/bridge/xmpp"
log "github.com/Sirupsen/logrus"
@@ -75,6 +76,9 @@ func New(cfg *config.Config, bridge *config.Bridge, c chan config.Message) *Brid
case "matrix":
b.Config = cfg.Matrix[name]
b.Bridger = bmatrix.New(cfg.Matrix[name], bridge.Account, c)
+ case "steam":
+ b.Config = cfg.Steam[name]
+ b.Bridger = bsteam.New(cfg.Steam[name], bridge.Account, c)
case "api":
b.Config = cfg.Api[name]
b.Bridger = api.New(cfg.Api[name], bridge.Account, c)
diff --git a/bridge/config/config.go b/bridge/config/config.go
index 79715b53..7f27115b 100644
--- a/bridge/config/config.go
+++ b/bridge/config/config.go
@@ -39,6 +39,7 @@ type ChannelInfo struct {
}
type Protocol struct {
+ AuthCode string // steam
BindAddress string // mattermost, slack
Buffer int // api
EditSuffix string // mattermost, slack, discord, telegram, gitter
@@ -109,6 +110,7 @@ type Config struct {
Mattermost map[string]Protocol
Matrix map[string]Protocol
Slack map[string]Protocol
+ Steam map[string]Protocol
Gitter map[string]Protocol
Xmpp map[string]Protocol
Discord map[string]Protocol
diff --git a/bridge/steam/steam.go b/bridge/steam/steam.go
new file mode 100644
index 00000000..491612d1
--- /dev/null
+++ b/bridge/steam/steam.go
@@ -0,0 +1,158 @@
+package bsteam
+
+import (
+ "fmt"
+ "github.com/42wim/matterbridge/bridge/config"
+ "github.com/Philipp15b/go-steam"
+ "github.com/Philipp15b/go-steam/protocol/steamlang"
+ "github.com/Philipp15b/go-steam/steamid"
+ log "github.com/Sirupsen/logrus"
+ //"io/ioutil"
+ "strconv"
+ "sync"
+ "time"
+)
+
+type Bsteam struct {
+ c *steam.Client
+ connected chan struct{}
+ Config *config.Protocol
+ Remote chan config.Message
+ Account string
+ userMap map[steamid.SteamId]string
+ sync.RWMutex
+}
+
+var flog *log.Entry
+var protocol = "steam"
+
+func init() {
+ flog = log.WithFields(log.Fields{"module": protocol})
+}
+
+func New(cfg config.Protocol, account string, c chan config.Message) *Bsteam {
+ b := &Bsteam{}
+ b.Config = &cfg
+ b.Remote = c
+ b.Account = account
+ b.userMap = make(map[steamid.SteamId]string)
+ b.connected = make(chan struct{})
+ return b
+}
+
+func (b *Bsteam) Connect() error {
+ flog.Info("Connecting")
+ b.c = steam.NewClient()
+ go b.handleEvents()
+ go b.c.Connect()
+ select {
+ case <-b.connected:
+ flog.Info("Connection succeeded")
+ case <-time.After(time.Second * 30):
+ return fmt.Errorf("connection timed out")
+ }
+ return nil
+}
+
+func (b *Bsteam) Disconnect() error {
+ b.c.Disconnect()
+ return nil
+
+}
+
+func (b *Bsteam) JoinChannel(channel string) error {
+ id, err := steamid.NewId(channel)
+ if err != nil {
+ return err
+ }
+ b.c.Social.JoinChat(id)
+ return nil
+}
+
+func (b *Bsteam) Send(msg config.Message) error {
+ id, err := steamid.NewId(msg.Channel)
+ if err != nil {
+ return err
+ }
+ b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text)
+ return nil
+}
+
+func (b *Bsteam) getNick(id steamid.SteamId) string {
+ b.RLock()
+ defer b.RUnlock()
+ if name, ok := b.userMap[id]; ok {
+ return name
+ }
+ return "unknown"
+}
+
+func (b *Bsteam) handleEvents() {
+ myLoginInfo := new(steam.LogOnDetails)
+ myLoginInfo.Username = b.Config.Login
+ myLoginInfo.Password = b.Config.Password
+ myLoginInfo.AuthCode = b.Config.AuthCode
+ // Attempt to read existing auth hash to avoid steam guard.
+ // Maybe works
+ //myLoginInfo.SentryFileHash, _ = ioutil.ReadFile("sentry")
+ for event := range b.c.Events() {
+ //flog.Info(event)
+ switch e := event.(type) {
+ case *steam.ChatMsgEvent:
+ flog.Debugf("Receiving ChatMsgEvent: %#v", e)
+ flog.Debugf("Sending message from %s on %s to gateway", b.getNick(e.ChatterId), b.Account)
+ msg := config.Message{Username: b.getNick(e.ChatterId), Text: e.Message, Channel: strconv.FormatInt(int64(e.ChatRoomId), 10), Account: b.Account, UserID: strconv.FormatInt(int64(e.ChatterId), 10)}
+ b.Remote <- msg
+ case *steam.PersonaStateEvent:
+ flog.Debugf("PersonaStateEvent: %#v\n", e)
+ b.Lock()
+ b.userMap[e.FriendId] = e.Name
+ b.Unlock()
+ case *steam.ConnectedEvent:
+ b.c.Auth.LogOn(myLoginInfo)
+ case *steam.MachineAuthUpdateEvent:
+ /*
+ flog.Info("authupdate", e)
+ flog.Info("hash", e.Hash)
+ ioutil.WriteFile("sentry", e.Hash, 0666)
+ */
+ case *steam.LogOnFailedEvent:
+ flog.Info("Logon failed", e)
+ switch e.Result {
+ case steamlang.EResult_AccountLogonDeniedNeedTwoFactorCode:
+ {
+ flog.Info("Steam guard isn't letting me in! Enter 2FA code:")
+ var code string
+ fmt.Scanf("%s", &code)
+ myLoginInfo.TwoFactorCode = code
+ }
+ case steamlang.EResult_AccountLogonDenied:
+ {
+ flog.Info("Steam guard isn't letting me in! Enter auth code:")
+ var code string
+ fmt.Scanf("%s", &code)
+ myLoginInfo.AuthCode = code
+ }
+ default:
+ log.Errorf("LogOnFailedEvent: ", e.Result)
+ // TODO: Handle EResult_InvalidLoginAuthCode
+ return
+ }
+ case *steam.LoggedOnEvent:
+ flog.Debugf("LoggedOnEvent: %#v", e)
+ b.connected <- struct{}{}
+ flog.Debugf("setting online")
+ b.c.Social.SetPersonaState(steamlang.EPersonaState_Online)
+ case *steam.DisconnectedEvent:
+ flog.Info("Disconnected")
+ flog.Info("Attempting to reconnect...")
+ b.c.Connect()
+ case steam.FatalErrorEvent:
+ flog.Error(e)
+ case error:
+ flog.Error(e)
+ default:
+ flog.Debugf("unknown event %#v", e)
+ }
+ }
+}
diff --git a/matterbridge.toml.sample b/matterbridge.toml.sample
index ecc921b1..12034930 100644
--- a/matterbridge.toml.sample
+++ b/matterbridge.toml.sample
@@ -656,6 +656,55 @@ RemoteNickFormat="[{PROTOCOL}] <{NICK}> "
#OPTIONAL (default false)
ShowJoinPart=false
+###################################################################
+#steam section
+###################################################################
+[steam]
+#You can configure multiple servers "[steam.name]" or "[steam.name2]"
+#In this example we use [steam.gamechat]
+#REQUIRED
+
+[matrix.gamechat]
+#login/pass of your bot.
+#Use a dedicated user for this and not your own account!
+#REQUIRED
+Login="yourlogin"
+Password="yourpass"
+
+#steamguard mail authcode (not the 2FA code)
+#OPTIONAL
+Authcode="ABCE12"
+
+#Whether to prefix messages from other bridges to matrix with the sender's nick.
+#Useful if username overrides for incoming webhooks isn't enabled on the
+#matrix server. If you set PrefixMessagesWithNick to true, each message
+#from bridge to matrix will by default be prefixed by the RemoteNickFormat setting. i
+#OPTIONAL (default false)
+PrefixMessagesWithNick=false
+
+#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"
+
+#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="[{PROTOCOL}] <{NICK}> "
+
+#Enable to show users joins/parts from other bridges
+#Only works hiding/show messages from irc and mattermost bridge for now
+#OPTIONAL (default false)
+ShowJoinPart=false
+
###################################################################
#API
@@ -744,6 +793,9 @@ enable=true
#rocketchat - #channel (# is required (also needed for private channels!)
#matrix - #channel:server (eg #yourchannel:matrix.org)
# - 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
+ #
#REQUIRED
channel="#testing"