diff options
Diffstat (limited to 'matterclient/matterclient.go')
-rw-r--r-- | matterclient/matterclient.go | 294 |
1 files changed, 0 insertions, 294 deletions
diff --git a/matterclient/matterclient.go b/matterclient/matterclient.go deleted file mode 100644 index ffe88aa4..00000000 --- a/matterclient/matterclient.go +++ /dev/null @@ -1,294 +0,0 @@ -package matterclient - -import ( - "encoding/json" - "fmt" - "strings" - "sync" - "time" - - "github.com/gorilla/websocket" - lru "github.com/hashicorp/golang-lru" - "github.com/jpillora/backoff" - prefixed "github.com/matterbridge/logrus-prefixed-formatter" - "github.com/mattermost/mattermost-server/v5/model" - "github.com/sirupsen/logrus" -) - -type Credentials struct { - Login string - Team string - Pass string - Token string - CookieToken bool - Server string - NoTLS bool - SkipTLSVerify bool - SkipVersionCheck bool -} - -type Message struct { - Raw *model.WebSocketEvent - Post *model.Post - Team string - Channel string - Username string - Text string - Type string - UserID string -} - -//nolint:golint -type Team struct { - Team *model.Team - Id string - Channels []*model.Channel - MoreChannels []*model.Channel - Users map[string]*model.User -} - -type MMClient struct { - sync.RWMutex - *Credentials - - Team *Team - OtherTeams []*Team - Client *model.Client4 - User *model.User - Users map[string]*model.User - MessageChan chan *Message - WsClient *websocket.Conn - WsQuit bool - WsAway bool - WsConnected bool - WsSequence int64 - WsPingChan chan *model.WebSocketResponse - ServerVersion string - OnWsConnect func() - - logger *logrus.Entry - rootLogger *logrus.Logger - lruCache *lru.Cache - allevents bool -} - -// New will instantiate a new Matterclient with the specified login details without connecting. -func New(login string, pass string, team string, server string) *MMClient { - rootLogger := logrus.New() - rootLogger.SetFormatter(&prefixed.TextFormatter{ - PrefixPadding: 13, - DisableColors: true, - }) - - cred := &Credentials{ - Login: login, - Pass: pass, - Team: team, - Server: server, - } - - cache, _ := lru.New(500) - return &MMClient{ - Credentials: cred, - MessageChan: make(chan *Message, 100), - Users: make(map[string]*model.User), - rootLogger: rootLogger, - lruCache: cache, - logger: rootLogger.WithFields(logrus.Fields{"prefix": "matterclient"}), - } -} - -// SetDebugLog activates debugging logging on all Matterclient log output. -func (m *MMClient) SetDebugLog() { - m.rootLogger.SetFormatter(&prefixed.TextFormatter{ - PrefixPadding: 13, - DisableColors: true, - FullTimestamp: false, - ForceFormatting: true, - }) -} - -// SetLogLevel tries to parse the specified level and if successful sets -// the log level accordingly. Accepted levels are: 'debug', 'info', 'warn', -// 'error', 'fatal' and 'panic'. -func (m *MMClient) SetLogLevel(level string) { - l, err := logrus.ParseLevel(level) - if err != nil { - m.logger.Warnf("Failed to parse specified log-level '%s': %#v", level, err) - } else { - m.rootLogger.SetLevel(l) - } -} - -func (m *MMClient) EnableAllEvents() { - m.allevents = true -} - -// Login tries to connect the client with the loging details with which it was initialized. -func (m *MMClient) Login() error { - // check if this is a first connect or a reconnection - firstConnection := true - if m.WsConnected { - firstConnection = false - } - m.WsConnected = false - if m.WsQuit { - return nil - } - b := &backoff.Backoff{ - Min: time.Second, - Max: 5 * time.Minute, - Jitter: true, - } - - // do initialization setup - if err := m.initClient(firstConnection, b); err != nil { - return err - } - - if err := m.doLogin(firstConnection, b); err != nil { - return err - } - - if err := m.initUser(); err != nil { - return err - } - - if m.Team == nil { - validTeamNames := make([]string, len(m.OtherTeams)) - for i, t := range m.OtherTeams { - validTeamNames[i] = t.Team.Name - } - return fmt.Errorf("Team '%s' not found in %v", m.Credentials.Team, validTeamNames) - } - - m.wsConnect() - - return nil -} - -// Logout disconnects the client from the chat server. -func (m *MMClient) Logout() error { - m.logger.Debugf("logout as %s (team: %s) on %s", m.Credentials.Login, m.Credentials.Team, m.Credentials.Server) - m.WsQuit = true - m.WsClient.Close() - m.WsClient.UnderlyingConn().Close() - if strings.Contains(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN) { - m.logger.Debug("Not invalidating session in logout, credential is a token") - return nil - } - _, resp := m.Client.Logout() - if resp.Error != nil { - return resp.Error - } - return nil -} - -// WsReceiver implements the core loop that manages the connection to the chat server. In -// case of a disconnect it will try to reconnect. A call to this method is blocking until -// the 'WsQuite' field of the MMClient object is set to 'true'. -func (m *MMClient) WsReceiver() { - for { - var rawMsg json.RawMessage - var err error - - if m.WsQuit { - m.logger.Debug("exiting WsReceiver") - return - } - - if !m.WsConnected { - time.Sleep(time.Millisecond * 100) - continue - } - - if _, rawMsg, err = m.WsClient.ReadMessage(); err != nil { - m.logger.Error("error:", err) - // reconnect - m.wsConnect() - } - - var event model.WebSocketEvent - if err := json.Unmarshal(rawMsg, &event); err == nil && event.IsValid() { - m.logger.Debugf("WsReceiver event: %#v", event) - msg := &Message{Raw: &event, Team: m.Credentials.Team} - m.parseMessage(msg) - // check if we didn't empty the message - if msg.Text != "" { - m.MessageChan <- msg - continue - } - // if we have file attached but the message is empty, also send it - if msg.Post != nil { - if msg.Text != "" || len(msg.Post.FileIds) > 0 || msg.Post.Type == "slack_attachment" { - m.MessageChan <- msg - continue - } - } - if m.allevents { - m.MessageChan <- msg - continue - } - switch msg.Raw.Event { - case model.WEBSOCKET_EVENT_USER_ADDED, - model.WEBSOCKET_EVENT_USER_REMOVED, - model.WEBSOCKET_EVENT_CHANNEL_CREATED, - model.WEBSOCKET_EVENT_CHANNEL_DELETED: - m.MessageChan <- msg - continue - } - } - - var response model.WebSocketResponse - if err := json.Unmarshal(rawMsg, &response); err == nil && response.IsValid() { - m.logger.Debugf("WsReceiver response: %#v", response) - m.parseResponse(response) - } - } -} - -// StatusLoop implements a ping-cycle that ensures that the connection to the chat servers -// remains alive. In case of a disconnect it will try to reconnect. A call to this method -// is blocking until the 'WsQuite' field of the MMClient object is set to 'true'. -func (m *MMClient) StatusLoop() { - retries := 0 - backoff := time.Second * 60 - if m.OnWsConnect != nil { - m.OnWsConnect() - } - m.logger.Debug("StatusLoop:", m.OnWsConnect != nil) - for { - if m.WsQuit { - return - } - if m.WsConnected { - if err := m.checkAlive(); err != nil { - m.logger.Errorf("Connection is not alive: %#v", err) - } - select { - case <-m.WsPingChan: - m.logger.Debug("WS PONG received") - backoff = time.Second * 60 - case <-time.After(time.Second * 5): - if retries > 3 { - m.logger.Debug("StatusLoop() timeout") - m.Logout() - m.WsQuit = false - err := m.Login() - if err != nil { - m.logger.Errorf("Login failed: %#v", err) - break - } - if m.OnWsConnect != nil { - m.OnWsConnect() - } - go m.WsReceiver() - } else { - retries++ - backoff = time.Second * 5 - } - } - } - time.Sleep(backoff) - } -} |