forked from jshiffer/matterbridge
Add initial steam support
This commit is contained in:
parent
1f91461853
commit
276ac840aa
@ -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)
|
||||
|
@ -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
|
||||
|
158
bridge/steam/steam.go
Normal file
158
bridge/steam/steam.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user