summaryrefslogtreecommitdiff
path: root/teleirc/matterbridge/bridge/steam
diff options
context:
space:
mode:
authorMistivia <i@mistivia.com>2025-11-02 15:27:18 +0800
committerMistivia <i@mistivia.com>2025-11-02 15:27:18 +0800
commite9c24f4af7ed56760f6db7941827d09f6db9020b (patch)
tree62128c43b883ce5e3148113350978755779bb5de /teleirc/matterbridge/bridge/steam
parent58d5e7cfda4781d8a57ec52aefd02983835c301a (diff)
add matterbridge
Diffstat (limited to 'teleirc/matterbridge/bridge/steam')
-rw-r--r--teleirc/matterbridge/bridge/steam/handlers.go126
-rw-r--r--teleirc/matterbridge/bridge/steam/steam.go95
2 files changed, 221 insertions, 0 deletions
diff --git a/teleirc/matterbridge/bridge/steam/handlers.go b/teleirc/matterbridge/bridge/steam/handlers.go
new file mode 100644
index 0000000..fa5015c
--- /dev/null
+++ b/teleirc/matterbridge/bridge/steam/handlers.go
@@ -0,0 +1,126 @@
+package bsteam
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/42wim/matterbridge/bridge/config"
+ "github.com/Philipp15b/go-steam"
+ "github.com/Philipp15b/go-steam/protocol/steamlang"
+)
+
+func (b *Bsteam) handleChatMsg(e *steam.ChatMsgEvent) {
+ b.Log.Debugf("Receiving ChatMsgEvent: %#v", e)
+ b.Log.Debugf("<= Sending message from %s on %s to gateway", b.getNick(e.ChatterId), b.Account)
+ var channel int64
+ if e.ChatRoomId == 0 {
+ channel = int64(e.ChatterId)
+ } else {
+ // for some reason we have to remove 0x18000000000000
+ // TODO
+ // https://github.com/42wim/matterbridge/pull/630#discussion_r238102751
+ // channel = int64(e.ChatRoomId) & 0xfffffffffffff
+ channel = int64(e.ChatRoomId) - 0x18000000000000
+ }
+ msg := config.Message{
+ Username: b.getNick(e.ChatterId),
+ Text: e.Message,
+ Channel: strconv.FormatInt(channel, 10),
+ Account: b.Account,
+ UserID: strconv.FormatInt(int64(e.ChatterId), 10),
+ }
+ b.Remote <- msg
+}
+
+func (b *Bsteam) handleEvents() {
+ myLoginInfo := &steam.LogOnDetails{
+ Username: b.GetString("Login"),
+ Password: b.GetString("Password"),
+ AuthCode: b.GetString("AuthCode"),
+ }
+ // TODO Attempt to read existing auth hash to avoid steam guard.
+ // Maybe works
+ //myLoginInfo.SentryFileHash, _ = ioutil.ReadFile("sentry")
+ for event := range b.c.Events() {
+ switch e := event.(type) {
+ case *steam.ChatMsgEvent:
+ b.handleChatMsg(e)
+ case *steam.PersonaStateEvent:
+ b.Log.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:
+ // TODO sentry files for 2 auth
+ /*
+ b.Log.Info("authupdate", e)
+ b.Log.Info("hash", e.Hash)
+ ioutil.WriteFile("sentry", e.Hash, 0666)
+ */
+ case *steam.LogOnFailedEvent:
+ b.Log.Info("Logon failed", e)
+ err := b.handleLogOnFailed(e, myLoginInfo)
+ if err != nil {
+ b.Log.Error(err)
+ return
+ }
+ case *steam.LoggedOnEvent:
+ b.Log.Debugf("LoggedOnEvent: %#v", e)
+ b.connected <- struct{}{}
+ b.Log.Debugf("setting online")
+ b.c.Social.SetPersonaState(steamlang.EPersonaState_Online)
+ case *steam.DisconnectedEvent:
+ b.Log.Info("Disconnected")
+ b.Log.Info("Attempting to reconnect...")
+ b.c.Connect()
+ case steam.FatalErrorEvent:
+ b.Log.Errorf("steam FatalErrorEvent: %#v", e)
+ default:
+ b.Log.Debugf("unknown event %#v", e)
+ }
+ }
+}
+
+func (b *Bsteam) handleLogOnFailed(e *steam.LogOnFailedEvent, myLoginInfo *steam.LogOnDetails) error {
+ switch e.Result {
+ case steamlang.EResult_AccountLoginDeniedNeedTwoFactor:
+ b.Log.Info("Steam guard isn't letting me in! Enter 2FA code:")
+ var code string
+ fmt.Scanf("%s", &code)
+ // TODO https://github.com/42wim/matterbridge/pull/630#discussion_r238103978
+ myLoginInfo.TwoFactorCode = code
+ case steamlang.EResult_AccountLogonDenied:
+ b.Log.Info("Steam guard isn't letting me in! Enter auth code:")
+ var code string
+ fmt.Scanf("%s", &code)
+ // TODO https://github.com/42wim/matterbridge/pull/630#discussion_r238103978
+ myLoginInfo.AuthCode = code
+ case steamlang.EResult_InvalidLoginAuthCode:
+ return fmt.Errorf("Steam guard: invalid login auth code: %#v ", e.Result)
+ default:
+ return fmt.Errorf("LogOnFailedEvent: %#v ", e.Result)
+ // TODO: Handle EResult_InvalidLoginAuthCode
+ }
+ return nil
+}
+
+// handleFileInfo handles config.FileInfo and adds correct file comment or URL to msg.Text.
+// Returns error if cast fails.
+func (b *Bsteam) handleFileInfo(msg *config.Message, f interface{}) error {
+ if _, ok := f.(config.FileInfo); !ok {
+ return fmt.Errorf("handleFileInfo cast failed %#v", f)
+ }
+ 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
+ }
+ }
+ return nil
+}
diff --git a/teleirc/matterbridge/bridge/steam/steam.go b/teleirc/matterbridge/bridge/steam/steam.go
new file mode 100644
index 0000000..5a577a2
--- /dev/null
+++ b/teleirc/matterbridge/bridge/steam/steam.go
@@ -0,0 +1,95 @@
+package bsteam
+
+import (
+ "fmt"
+ "sync"
+ "time"
+
+ "github.com/42wim/matterbridge/bridge"
+ "github.com/42wim/matterbridge/bridge/config"
+ "github.com/42wim/matterbridge/bridge/helper"
+ "github.com/Philipp15b/go-steam"
+ "github.com/Philipp15b/go-steam/protocol/steamlang"
+ "github.com/Philipp15b/go-steam/steamid"
+)
+
+type Bsteam struct {
+ c *steam.Client
+ connected chan struct{}
+ userMap map[steamid.SteamId]string
+ sync.RWMutex
+ *bridge.Config
+}
+
+func New(cfg *bridge.Config) bridge.Bridger {
+ b := &Bsteam{Config: cfg}
+ b.userMap = make(map[steamid.SteamId]string)
+ b.connected = make(chan struct{})
+ return b
+}
+
+func (b *Bsteam) Connect() error {
+ b.Log.Info("Connecting")
+ b.c = steam.NewClient()
+ go b.handleEvents()
+ go b.c.Connect()
+ select {
+ case <-b.connected:
+ b.Log.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 config.ChannelInfo) error {
+ id, err := steamid.NewId(channel.Name)
+ if err != nil {
+ return err
+ }
+ b.c.Social.JoinChat(id)
+ return nil
+}
+
+func (b *Bsteam) Send(msg config.Message) (string, error) {
+ // ignore delete messages
+ if msg.Event == config.EventMsgDelete {
+ return "", nil
+ }
+ id, err := steamid.NewId(msg.Channel)
+ if err != nil {
+ return "", err
+ }
+
+ // Handle files
+ if msg.Extra != nil {
+ for _, rmsg := range helper.HandleExtra(&msg, b.General) {
+ b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, rmsg.Username+rmsg.Text)
+ }
+ for i := range msg.Extra["file"] {
+ if err := b.handleFileInfo(&msg, msg.Extra["file"][i]); err != nil {
+ b.Log.Error(err)
+ }
+ b.c.Social.SendMessage(id, steamlang.EChatEntryType_ChatMsg, msg.Username+msg.Text)
+ }
+ return "", nil
+ }
+
+ 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"
+}