Thumbnail

rani/matterbridge.git

Clone URL: https://git.buni.party/rani/matterbridge.git

Viewing file on branch master

1package bsshchat
2
3import (
4 "bufio"
5 "io"
6 "strings"
7
8 "github.com/matterbridge-org/matterbridge/bridge"
9 "github.com/matterbridge-org/matterbridge/bridge/config"
10 "github.com/matterbridge-org/matterbridge/bridge/helper"
11 "github.com/shazow/ssh-chat/sshd"
12)
13
14type Bsshchat struct {
15 r *bufio.Scanner
16 w io.WriteCloser
17 *bridge.Config
18}
19
20func New(cfg *bridge.Config) bridge.Bridger {
21 return &Bsshchat{Config: cfg}
22}
23
24func (b *Bsshchat) Connect() error {
25 b.Log.Infof("Connecting %s", b.GetString("Server"))
26
27 // connHandler will be called by 'sshd.ConnectShell()' below
28 // once the connection is established in order to handle it.
29 connErr := make(chan error, 1) // Needs to be buffered.
30 connSignal := make(chan struct{})
31 connHandler := func(r io.Reader, w io.WriteCloser) error {
32 b.r = bufio.NewScanner(r)
33 b.r.Scan()
34 b.w = w
35 if _, err := b.w.Write([]byte("/theme mono\r\n/quiet\r\n")); err != nil {
36 return err
37 }
38 close(connSignal) // Connection is established so we can signal the success.
39 return b.handleSSHChat()
40 }
41
42 go func() {
43 // As a successful connection will result in this returning after the Connection
44 // method has already returned point we NEED to have a buffered channel to still
45 // be able to write.
46 connErr <- sshd.ConnectShell(b.GetString("Server"), b.GetString("Nick"), connHandler)
47 }()
48
49 select {
50 case err := <-connErr:
51 b.Log.Error("Connection failed")
52 return err
53 case <-connSignal:
54 }
55 b.Log.Info("Connection succeeded")
56 return nil
57}
58
59func (b *Bsshchat) Disconnect() error {
60 return nil
61}
62
63func (b *Bsshchat) JoinChannel(channel config.ChannelInfo) error {
64 return nil
65}
66
67func (b *Bsshchat) Send(msg config.Message) (string, error) {
68 // ignore delete messages
69 if msg.Event == config.EventMsgDelete {
70 return "", nil
71 }
72 b.Log.Debugf("=> Receiving %#v", msg)
73 if msg.Extra != nil {
74 for _, rmsg := range helper.HandleExtra(&msg, b.General) {
75 if _, err := b.w.Write([]byte(rmsg.Username + rmsg.Text + "\r\n")); err != nil {
76 b.Log.Errorf("Could not send extra message: %#v", err)
77 }
78 }
79 if len(msg.Extra["file"]) > 0 {
80 return b.handleUploadFile(&msg)
81 }
82 }
83 _, err := b.w.Write([]byte(msg.Username + msg.Text + "\r\n"))
84 return "", err
85}
86
87/*
88func (b *Bsshchat) sshchatKeepAlive() chan bool {
89 done := make(chan bool)
90 go func() {
91 ticker := time.NewTicker(90 * time.Second)
92 defer ticker.Stop()
93 for {
94 select {
95 case <-ticker.C:
96 b.Log.Debugf("PING")
97 err := b.xc.PingC2S("", "")
98 if err != nil {
99 b.Log.Debugf("PING failed %#v", err)
100 }
101 case <-done:
102 return
103 }
104 }
105 }()
106 return done
107}
108*/
109
110func stripPrompt(s string) string {
111 pos := strings.LastIndex(s, "\033[K")
112 if pos < 0 {
113 return s
114 }
115 return s[pos+3:]
116}
117
118func (b *Bsshchat) handleSSHChat() error {
119 /*
120 done := b.sshchatKeepAlive()
121 defer close(done)
122 */
123 wait := true
124 for {
125 if b.r.Scan() {
126 // ignore messages from ourselves
127 if !strings.Contains(b.r.Text(), "\033[K") {
128 continue
129 }
130 if strings.Contains(b.r.Text(), "Rate limiting is in effect") {
131 continue
132 }
133 // skip our own messages
134 if !strings.HasPrefix(b.r.Text(), "["+b.GetString("Nick")+"] \x1b") {
135 continue
136 }
137 res := strings.Split(stripPrompt(b.r.Text()), ":")
138 if res[0] == "-> Set theme" {
139 wait = false
140 b.Log.Debugf("mono found, allowing")
141 continue
142 }
143 if !wait {
144 b.Log.Debugf("<= Message %#v", res)
145 rmsg := config.Message{Username: res[0], Text: strings.TrimSpace(strings.Join(res[1:], ":")), Channel: "sshchat", Account: b.Account, UserID: "nick"}
146 b.Remote <- rmsg
147 }
148 }
149 }
150}
151
152func (b *Bsshchat) handleUploadFile(msg *config.Message) (string, error) {
153 for _, f := range msg.Extra["file"] {
154 fi := f.(config.FileInfo)
155 if fi.Comment != "" {
156 msg.Text += fi.Comment + ": "
157 }
158 if fi.URL != "" {
159 msg.Text = fi.URL
160 if fi.Comment != "" {
161 msg.Text = fi.Comment + ": " + fi.URL
162 }
163 }
164 if _, err := b.w.Write([]byte(msg.Username + msg.Text + "\r\n")); err != nil {
165 b.Log.Errorf("Could not send file message: %#v", err)
166 }
167 }
168 return "", nil
169}
170