summaryrefslogtreecommitdiff
path: root/teleirc/matterbridge/bridge/sshchat/sshchat.go
diff options
context:
space:
mode:
Diffstat (limited to 'teleirc/matterbridge/bridge/sshchat/sshchat.go')
-rw-r--r--teleirc/matterbridge/bridge/sshchat/sshchat.go169
1 files changed, 169 insertions, 0 deletions
diff --git a/teleirc/matterbridge/bridge/sshchat/sshchat.go b/teleirc/matterbridge/bridge/sshchat/sshchat.go
new file mode 100644
index 0000000..6b78c22
--- /dev/null
+++ b/teleirc/matterbridge/bridge/sshchat/sshchat.go
@@ -0,0 +1,169 @@
+package bsshchat
+
+import (
+ "bufio"
+ "io"
+ "strings"
+
+ "github.com/42wim/matterbridge/bridge"
+ "github.com/42wim/matterbridge/bridge/config"
+ "github.com/42wim/matterbridge/bridge/helper"
+ "github.com/shazow/ssh-chat/sshd"
+)
+
+type Bsshchat struct {
+ r *bufio.Scanner
+ w io.WriteCloser
+ *bridge.Config
+}
+
+func New(cfg *bridge.Config) bridge.Bridger {
+ return &Bsshchat{Config: cfg}
+}
+
+func (b *Bsshchat) Connect() error {
+ b.Log.Infof("Connecting %s", b.GetString("Server"))
+
+ // connHandler will be called by 'sshd.ConnectShell()' below
+ // once the connection is established in order to handle it.
+ connErr := make(chan error, 1) // Needs to be buffered.
+ connSignal := make(chan struct{})
+ connHandler := func(r io.Reader, w io.WriteCloser) error {
+ b.r = bufio.NewScanner(r)
+ b.r.Scan()
+ b.w = w
+ if _, err := b.w.Write([]byte("/theme mono\r\n/quiet\r\n")); err != nil {
+ return err
+ }
+ close(connSignal) // Connection is established so we can signal the success.
+ return b.handleSSHChat()
+ }
+
+ go func() {
+ // As a successful connection will result in this returning after the Connection
+ // method has already returned point we NEED to have a buffered channel to still
+ // be able to write.
+ connErr <- sshd.ConnectShell(b.GetString("Server"), b.GetString("Nick"), connHandler)
+ }()
+
+ select {
+ case err := <-connErr:
+ b.Log.Error("Connection failed")
+ return err
+ case <-connSignal:
+ }
+ b.Log.Info("Connection succeeded")
+ return nil
+}
+
+func (b *Bsshchat) Disconnect() error {
+ return nil
+}
+
+func (b *Bsshchat) JoinChannel(channel config.ChannelInfo) error {
+ return nil
+}
+
+func (b *Bsshchat) Send(msg config.Message) (string, error) {
+ // ignore delete messages
+ if msg.Event == config.EventMsgDelete {
+ return "", nil
+ }
+ b.Log.Debugf("=> Receiving %#v", msg)
+ if msg.Extra != nil {
+ for _, rmsg := range helper.HandleExtra(&msg, b.General) {
+ if _, err := b.w.Write([]byte(rmsg.Username + rmsg.Text + "\r\n")); err != nil {
+ b.Log.Errorf("Could not send extra message: %#v", err)
+ }
+ }
+ if len(msg.Extra["file"]) > 0 {
+ return b.handleUploadFile(&msg)
+ }
+ }
+ _, err := b.w.Write([]byte(msg.Username + msg.Text + "\r\n"))
+ return "", err
+}
+
+/*
+func (b *Bsshchat) sshchatKeepAlive() chan bool {
+ done := make(chan bool)
+ go func() {
+ ticker := time.NewTicker(90 * time.Second)
+ defer ticker.Stop()
+ for {
+ select {
+ case <-ticker.C:
+ b.Log.Debugf("PING")
+ err := b.xc.PingC2S("", "")
+ if err != nil {
+ b.Log.Debugf("PING failed %#v", err)
+ }
+ case <-done:
+ return
+ }
+ }
+ }()
+ return done
+}
+*/
+
+func stripPrompt(s string) string {
+ pos := strings.LastIndex(s, "\033[K")
+ if pos < 0 {
+ return s
+ }
+ return s[pos+3:]
+}
+
+func (b *Bsshchat) handleSSHChat() error {
+ /*
+ done := b.sshchatKeepAlive()
+ defer close(done)
+ */
+ wait := true
+ for {
+ if b.r.Scan() {
+ // ignore messages from ourselves
+ if !strings.Contains(b.r.Text(), "\033[K") {
+ continue
+ }
+ if strings.Contains(b.r.Text(), "Rate limiting is in effect") {
+ continue
+ }
+ // skip our own messages
+ if !strings.HasPrefix(b.r.Text(), "["+b.GetString("Nick")+"] \x1b") {
+ continue
+ }
+ res := strings.Split(stripPrompt(b.r.Text()), ":")
+ if res[0] == "-> Set theme" {
+ wait = false
+ b.Log.Debugf("mono found, allowing")
+ continue
+ }
+ if !wait {
+ b.Log.Debugf("<= Message %#v", res)
+ rmsg := config.Message{Username: res[0], Text: strings.TrimSpace(strings.Join(res[1:], ":")), Channel: "sshchat", Account: b.Account, UserID: "nick"}
+ b.Remote <- rmsg
+ }
+ }
+ }
+}
+
+func (b *Bsshchat) 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
+ }
+ }
+ if _, err := b.w.Write([]byte(msg.Username + msg.Text + "\r\n")); err != nil {
+ b.Log.Errorf("Could not send file message: %#v", err)
+ }
+ }
+ return "", nil
+}