Update dependencies and remove old matterclient lib (#2067)
This commit is contained in:
parent
9459495484
commit
56e7bd01ca
72
go.mod
72
go.mod
@ -6,56 +6,54 @@ require (
|
||||
github.com/Philipp15b/go-steam v1.0.1-0.20200727090957-6ae9b3c0a560
|
||||
github.com/Rhymen/go-whatsapp v0.1.2-0.20211102134409-31a2e740845c
|
||||
github.com/SevereCloud/vksdk/v2 v2.16.0
|
||||
github.com/bwmarrin/discordgo v0.27.0
|
||||
github.com/d5/tengo/v2 v2.13.0
|
||||
github.com/bwmarrin/discordgo v0.27.1
|
||||
github.com/d5/tengo/v2 v2.16.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/gomarkdown/markdown v0.0.0-20221013030248-663e2500819c
|
||||
github.com/gomarkdown/markdown v0.0.0-20230716120725-531d2d74bc12
|
||||
github.com/google/gops v0.3.27
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/harmony-development/shibshib v0.0.0-20220101224523-c98059d09cfa
|
||||
github.com/hashicorp/golang-lru v0.6.0
|
||||
github.com/jpillora/backoff v1.0.0
|
||||
github.com/keybase/go-keybase-chat-bot v0.0.0-20221220212439-e48d9abd2c20
|
||||
github.com/kyokomi/emoji/v2 v2.2.12
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/lrstanley/girc v0.0.0-20221222153823-a92667a5c9b4
|
||||
github.com/labstack/echo/v4 v4.11.1
|
||||
github.com/lrstanley/girc v0.0.0-20230729130341-dd5853a5f1a6
|
||||
github.com/matterbridge/Rocket.Chat.Go.SDK v0.0.0-20211016222428-79310a412696
|
||||
github.com/matterbridge/go-xmpp v0.0.0-20211030125215-791a06c5f1be
|
||||
github.com/matterbridge/gomatrix v0.0.0-20220411225302-271e5088ea27
|
||||
github.com/matterbridge/gozulipbot v0.0.0-20211023205727-a19d6c1f3b75
|
||||
github.com/matterbridge/logrus-prefixed-formatter v0.5.3-0.20200523233437-d971309a77ba
|
||||
github.com/matterbridge/matterclient v0.0.0-20221106190440-8bcf49695e0d
|
||||
github.com/matterbridge/matterclient v0.0.0-20230329213635-bc6e42a4a84a
|
||||
github.com/matterbridge/telegram-bot-api/v6 v6.5.0
|
||||
github.com/mattermost/mattermost-server/v5 v5.39.3
|
||||
github.com/mattermost/mattermost-server/v6 v6.7.2
|
||||
github.com/mattn/godown v0.0.1
|
||||
github.com/mdp/qrterminal v1.0.1
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nelsonken/gomf v0.0.0-20190423072027-c65cc0469e94
|
||||
github.com/olahol/melody v1.1.2
|
||||
github.com/olahol/melody v1.1.4
|
||||
github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
|
||||
github.com/rs/xid v1.4.0
|
||||
github.com/rs/xid v1.5.0
|
||||
github.com/russross/blackfriday v1.6.0
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/shazow/ssh-chat v1.10.1
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/slack-go/slack v0.12.1
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/slack-go/slack v0.12.2
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/vincent-petithory/dataurl v1.0.0
|
||||
github.com/writeas/go-strip-markdown v2.0.1+incompatible
|
||||
github.com/yaegashi/msgraph.go v0.1.4
|
||||
github.com/zfjagann/golang-ring v0.0.0-20220330170733-19bcea1b6289
|
||||
go.mau.fi/whatsmeow v0.0.0-20230306190159-5caded34a872
|
||||
golang.org/x/image v0.6.0
|
||||
golang.org/x/oauth2 v0.6.0
|
||||
golang.org/x/text v0.8.0
|
||||
go.mau.fi/whatsmeow v0.0.0-20230805111647-405414b9b5c0
|
||||
golang.org/x/image v0.11.0
|
||||
golang.org/x/oauth2 v0.11.0
|
||||
golang.org/x/text v0.12.0
|
||||
gomod.garykim.dev/nc-talk v0.3.0
|
||||
google.golang.org/protobuf v1.29.1
|
||||
google.golang.org/protobuf v1.31.0
|
||||
layeh.com/gumble v0.0.0-20221205141517-d1df60a3cc14
|
||||
modernc.org/sqlite v1.21.0
|
||||
modernc.org/sqlite v1.25.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -65,17 +63,16 @@ require (
|
||||
github.com/apex/log v1.9.0 // indirect
|
||||
github.com/av-elier/go-decimal-to-rational v0.0.0-20191127152832-89e6aad02ecf // indirect
|
||||
github.com/blang/semver v3.5.1+incompatible // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/dyatlov/go-opengraph v0.0.0-20210112100619-dae8665a5b09 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gopackage/ddp v0.0.3 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/graph-gophers/graphql-go v1.3.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
@ -86,10 +83,9 @@ require (
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 // indirect
|
||||
github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d // indirect
|
||||
github.com/mattermost/logr v1.0.13 // indirect
|
||||
github.com/mattermost/logr/v2 v2.0.15 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
@ -102,7 +98,7 @@ require (
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pborman/uuid v1.2.1 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/philhofer/fwd v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
@ -113,8 +109,8 @@ require (
|
||||
github.com/shazow/rateio v0.0.0-20200113175441-4461efc8bdc4 // indirect
|
||||
github.com/sizeofint/webpanimation v0.0.0-20210809145948-1d2b32119882 // indirect
|
||||
github.com/skip2/go-qrcode v0.0.0-20190110000554-dc11ecdae0a9 // indirect
|
||||
github.com/spf13/afero v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/afero v1.9.5 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
@ -123,18 +119,14 @@ require (
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/wiggin77/cfg v1.0.2 // indirect
|
||||
github.com/wiggin77/merror v1.0.3 // indirect
|
||||
github.com/wiggin77/srslog v1.0.1 // indirect
|
||||
go.mau.fi/libsignal v0.1.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.8.0 // indirect
|
||||
go.uber.org/zap v1.21.0 // indirect
|
||||
golang.org/x/crypto v0.6.0 // indirect
|
||||
golang.org/x/crypto v0.12.0 // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/term v0.6.0 // indirect
|
||||
golang.org/x/net v0.14.0 // indirect
|
||||
golang.org/x/sys v0.11.0 // indirect
|
||||
golang.org/x/term v0.11.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
@ -145,9 +137,9 @@ require (
|
||||
lukechampine.com/uint128 v1.2.0 // indirect
|
||||
modernc.org/cc/v3 v3.40.0 // indirect
|
||||
modernc.org/ccgo/v3 v3.16.13 // indirect
|
||||
modernc.org/libc v1.22.3 // indirect
|
||||
modernc.org/libc v1.24.1 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/memory v1.6.0 // indirect
|
||||
modernc.org/opt v0.1.3 // indirect
|
||||
modernc.org/strutil v1.1.3 // indirect
|
||||
modernc.org/token v1.0.1 // indirect
|
||||
@ -156,4 +148,4 @@ require (
|
||||
|
||||
//replace github.com/matrix-org/gomatrix => github.com/matterbridge/gomatrix v0.0.0-20220205235239-607eb9ee6419
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
1
matterclient/README.md
Normal file
1
matterclient/README.md
Normal file
@ -0,0 +1 @@
|
||||
Find matterclient on https://github.com/matterbridge/matterclient
|
@ -1,226 +0,0 @@
|
||||
package matterclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
// GetChannels returns all channels we're members off
|
||||
func (m *MMClient) GetChannels() []*model.Channel {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
// our primary team channels first
|
||||
channels = append(channels, m.Team.Channels...)
|
||||
for _, t := range m.OtherTeams {
|
||||
if t.Id != m.Team.Id {
|
||||
channels = append(channels, t.Channels...)
|
||||
}
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
||||
func (m *MMClient) GetChannelHeader(channelId string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range m.OtherTeams {
|
||||
for _, channel := range append(t.Channels, t.MoreChannels...) {
|
||||
if channel.Id == channelId {
|
||||
return channel.Header
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getNormalisedName(channel *model.Channel) string {
|
||||
if channel.Type == model.CHANNEL_GROUP {
|
||||
// (deprecated in favor of ReplaceAll in go 1.12)
|
||||
res := strings.Replace(channel.DisplayName, ", ", "-", -1) //nolint: gocritic
|
||||
res = strings.Replace(res, " ", "_", -1) //nolint: gocritic
|
||||
return res
|
||||
}
|
||||
return channel.Name
|
||||
}
|
||||
|
||||
func (m *MMClient) GetChannelId(name string, teamId string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
if teamId != "" {
|
||||
return m.getChannelIdTeam(name, teamId)
|
||||
}
|
||||
|
||||
for _, t := range m.OtherTeams {
|
||||
for _, channel := range append(t.Channels, t.MoreChannels...) {
|
||||
if getNormalisedName(channel) == name {
|
||||
return channel.Id
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) getChannelIdTeam(name string, teamId string) string { //nolint:golint
|
||||
for _, t := range m.OtherTeams {
|
||||
if t.Id == teamId {
|
||||
for _, channel := range append(t.Channels, t.MoreChannels...) {
|
||||
if getNormalisedName(channel) == name {
|
||||
return channel.Id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetChannelName(channelId string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range m.OtherTeams {
|
||||
if t == nil {
|
||||
continue
|
||||
}
|
||||
for _, channel := range append(t.Channels, t.MoreChannels...) {
|
||||
if channel.Id == channelId {
|
||||
return getNormalisedName(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetChannelTeamId(id string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range append(m.OtherTeams, m.Team) {
|
||||
for _, channel := range append(t.Channels, t.MoreChannels...) {
|
||||
if channel.Id == id {
|
||||
return channel.TeamId
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetLastViewedAt(channelId string) int64 { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
res, resp := m.Client.GetChannelMember(channelId, m.User.Id, "")
|
||||
if resp.Error != nil {
|
||||
return model.GetMillis()
|
||||
}
|
||||
return res.LastViewedAt
|
||||
}
|
||||
|
||||
// GetMoreChannels returns existing channels where we're not a member off.
|
||||
func (m *MMClient) GetMoreChannels() []*model.Channel {
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
for _, t := range m.OtherTeams {
|
||||
channels = append(channels, t.MoreChannels...)
|
||||
}
|
||||
return channels
|
||||
}
|
||||
|
||||
// GetTeamFromChannel returns teamId belonging to channel (DM channels have no teamId).
|
||||
func (m *MMClient) GetTeamFromChannel(channelId string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
var channels []*model.Channel
|
||||
for _, t := range m.OtherTeams {
|
||||
channels = append(channels, t.Channels...)
|
||||
if t.MoreChannels != nil {
|
||||
channels = append(channels, t.MoreChannels...)
|
||||
}
|
||||
for _, c := range channels {
|
||||
if c.Id == channelId {
|
||||
if c.Type == model.CHANNEL_GROUP {
|
||||
return "G"
|
||||
}
|
||||
return t.Id
|
||||
}
|
||||
}
|
||||
channels = nil
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) JoinChannel(channelId string) error { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, c := range m.Team.Channels {
|
||||
if c.Id == channelId {
|
||||
m.logger.Debug("Not joining ", channelId, " already joined.")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
m.logger.Debug("Joining ", channelId)
|
||||
_, resp := m.Client.AddChannelMember(channelId, m.User.Id)
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateChannelsTeam(teamID string) error {
|
||||
mmchannels, resp := m.Client.GetChannelsForTeamForUser(teamID, m.User.Id, false, "")
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
for idx, t := range m.OtherTeams {
|
||||
if t.Id == teamID {
|
||||
m.Lock()
|
||||
m.OtherTeams[idx].Channels = mmchannels
|
||||
m.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
mmchannels, resp = m.Client.GetPublicChannelsForTeam(teamID, 0, 5000, "")
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
for idx, t := range m.OtherTeams {
|
||||
if t.Id == teamID {
|
||||
m.Lock()
|
||||
m.OtherTeams[idx].MoreChannels = mmchannels
|
||||
m.Unlock()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateChannels() error {
|
||||
if err := m.UpdateChannelsTeam(m.Team.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range m.OtherTeams {
|
||||
if err := m.UpdateChannelsTeam(t.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateChannelHeader(channelId string, header string) { //nolint:golint
|
||||
channel := &model.Channel{Id: channelId, Header: header}
|
||||
m.logger.Debugf("updating channelheader %#v, %#v", channelId, header)
|
||||
_, resp := m.Client.UpdateChannel(channel)
|
||||
if resp.Error != nil {
|
||||
m.logger.Error(resp.Error)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateLastViewed(channelId string) error { //nolint:golint
|
||||
m.logger.Debugf("posting lastview %#v", channelId)
|
||||
view := &model.ChannelView{ChannelId: channelId}
|
||||
_, resp := m.Client.ViewChannel(m.User.Id, view)
|
||||
if resp.Error != nil {
|
||||
m.logger.Errorf("ChannelView update for %s failed: %s", channelId, resp.Error)
|
||||
return resp.Error
|
||||
}
|
||||
return nil
|
||||
}
|
@ -1,297 +0,0 @@
|
||||
package matterclient
|
||||
|
||||
import (
|
||||
"crypto/md5" //nolint:gosec
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/jpillora/backoff"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
func (m *MMClient) doLogin(firstConnection bool, b *backoff.Backoff) error {
|
||||
var resp *model.Response
|
||||
var appErr *model.AppError
|
||||
var logmsg = "trying login"
|
||||
var err error
|
||||
for {
|
||||
m.logger.Debugf("%s %s %s %s", logmsg, m.Credentials.Team, m.Credentials.Login, m.Credentials.Server)
|
||||
if m.Credentials.Token != "" {
|
||||
resp, err = m.doLoginToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
m.User, resp = m.Client.Login(m.Credentials.Login, m.Credentials.Pass)
|
||||
}
|
||||
appErr = resp.Error
|
||||
if appErr != nil {
|
||||
d := b.Duration()
|
||||
m.logger.Debug(appErr.DetailedError)
|
||||
if firstConnection {
|
||||
if appErr.Message == "" {
|
||||
return errors.New(appErr.DetailedError)
|
||||
}
|
||||
return errors.New(appErr.Message)
|
||||
}
|
||||
m.logger.Debugf("LOGIN: %s, reconnecting in %s", appErr, d)
|
||||
time.Sleep(d)
|
||||
logmsg = "retrying login"
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
// reset timer
|
||||
b.Reset()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) doLoginToken() (*model.Response, error) {
|
||||
var resp *model.Response
|
||||
var logmsg = "trying login"
|
||||
m.Client.AuthType = model.HEADER_BEARER
|
||||
m.Client.AuthToken = m.Credentials.Token
|
||||
if m.Credentials.CookieToken {
|
||||
m.logger.Debugf(logmsg + " with cookie (MMAUTH) token")
|
||||
m.Client.HttpClient.Jar = m.createCookieJar(m.Credentials.Token)
|
||||
} else {
|
||||
m.logger.Debugf(logmsg + " with personal token")
|
||||
}
|
||||
m.User, resp = m.Client.GetMe("")
|
||||
if resp.Error != nil {
|
||||
return resp, resp.Error
|
||||
}
|
||||
if m.User == nil {
|
||||
m.logger.Errorf("LOGIN TOKEN: %s is invalid", m.Credentials.Pass)
|
||||
return resp, errors.New("invalid token")
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (m *MMClient) handleLoginToken() error {
|
||||
switch {
|
||||
case strings.Contains(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN):
|
||||
token := strings.Split(m.Credentials.Pass, model.SESSION_COOKIE_TOKEN+"=")
|
||||
if len(token) != 2 {
|
||||
return errors.New("incorrect MMAUTHTOKEN. valid input is MMAUTHTOKEN=yourtoken")
|
||||
}
|
||||
m.Credentials.Token = token[1]
|
||||
m.Credentials.CookieToken = true
|
||||
case strings.Contains(m.Credentials.Pass, "token="):
|
||||
token := strings.Split(m.Credentials.Pass, "token=")
|
||||
if len(token) != 2 {
|
||||
return errors.New("incorrect personal token. valid input is token=yourtoken")
|
||||
}
|
||||
m.Credentials.Token = token[1]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) initClient(firstConnection bool, b *backoff.Backoff) error {
|
||||
uriScheme := "https://"
|
||||
if m.NoTLS {
|
||||
uriScheme = "http://"
|
||||
}
|
||||
// login to mattermost
|
||||
m.Client = model.NewAPIv4Client(uriScheme + m.Credentials.Server)
|
||||
m.Client.HttpClient.Transport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}, //nolint:gosec
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
}
|
||||
m.Client.HttpClient.Timeout = time.Second * 10
|
||||
|
||||
// handle MMAUTHTOKEN and personal token
|
||||
if err := m.handleLoginToken(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if server alive, retry until
|
||||
if err := m.serverAlive(firstConnection, b); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// initialize user and teams
|
||||
func (m *MMClient) initUser() error {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
// we only load all team data on initial login.
|
||||
// all other updates are for channels from our (primary) team only.
|
||||
//m.logger.Debug("initUser(): loading all team data")
|
||||
teams, resp := m.Client.GetTeamsForUser(m.User.Id, "")
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
for _, team := range teams {
|
||||
idx := 0
|
||||
max := 200
|
||||
usermap := make(map[string]*model.User)
|
||||
mmusers, resp := m.Client.GetUsersInTeam(team.Id, idx, max, "")
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
for len(mmusers) > 0 {
|
||||
for _, user := range mmusers {
|
||||
usermap[user.Id] = user
|
||||
}
|
||||
mmusers, resp = m.Client.GetUsersInTeam(team.Id, idx, max, "")
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
idx++
|
||||
time.Sleep(time.Millisecond * 200)
|
||||
}
|
||||
m.logger.Infof("found %d users in team %s", len(usermap), team.Name)
|
||||
|
||||
t := &Team{Team: team, Users: usermap, Id: team.Id}
|
||||
|
||||
mmchannels, resp := m.Client.GetChannelsForTeamForUser(team.Id, m.User.Id, false, "")
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
t.Channels = mmchannels
|
||||
mmchannels, resp = m.Client.GetPublicChannelsForTeam(team.Id, 0, 5000, "")
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
t.MoreChannels = mmchannels
|
||||
m.OtherTeams = append(m.OtherTeams, t)
|
||||
if team.Name == m.Credentials.Team {
|
||||
m.Team = t
|
||||
m.logger.Debugf("initUser(): found our team %s (id: %s)", team.Name, team.Id)
|
||||
}
|
||||
// add all users
|
||||
for k, v := range t.Users {
|
||||
m.Users[k] = v
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) serverAlive(firstConnection bool, b *backoff.Backoff) error {
|
||||
defer b.Reset()
|
||||
for {
|
||||
d := b.Duration()
|
||||
// bogus call to get the serverversion
|
||||
_, resp := m.Client.Logout()
|
||||
if resp.Error != nil {
|
||||
return fmt.Errorf("%#v", resp.Error.Error())
|
||||
}
|
||||
if firstConnection && !m.SkipVersionCheck && !supportedVersion(resp.ServerVersion) {
|
||||
return fmt.Errorf("unsupported mattermost version: %s", resp.ServerVersion)
|
||||
}
|
||||
if !m.SkipVersionCheck {
|
||||
m.ServerVersion = resp.ServerVersion
|
||||
if m.ServerVersion == "" {
|
||||
m.logger.Debugf("Server not up yet, reconnecting in %s", d)
|
||||
time.Sleep(d)
|
||||
} else {
|
||||
m.logger.Infof("Found version %s", m.ServerVersion)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MMClient) wsConnect() {
|
||||
b := &backoff.Backoff{
|
||||
Min: time.Second,
|
||||
Max: 5 * time.Minute,
|
||||
Jitter: true,
|
||||
}
|
||||
|
||||
m.WsConnected = false
|
||||
wsScheme := "wss://"
|
||||
if m.NoTLS {
|
||||
wsScheme = "ws://"
|
||||
}
|
||||
|
||||
// setup websocket connection
|
||||
wsurl := wsScheme + m.Credentials.Server + model.API_URL_SUFFIX_V4 + "/websocket"
|
||||
header := http.Header{}
|
||||
header.Set(model.HEADER_AUTH, "BEARER "+m.Client.AuthToken)
|
||||
|
||||
m.logger.Debugf("WsClient: making connection: %s", wsurl)
|
||||
for {
|
||||
wsDialer := &websocket.Dialer{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: m.SkipTLSVerify}, //nolint:gosec
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
}
|
||||
var err error
|
||||
m.WsClient, _, err = wsDialer.Dial(wsurl, header)
|
||||
if err != nil {
|
||||
d := b.Duration()
|
||||
m.logger.Debugf("WSS: %s, reconnecting in %s", err, d)
|
||||
time.Sleep(d)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
m.logger.Debug("WsClient: connected")
|
||||
m.WsSequence = 1
|
||||
m.WsPingChan = make(chan *model.WebSocketResponse)
|
||||
// only start to parse WS messages when login is completely done
|
||||
m.WsConnected = true
|
||||
}
|
||||
|
||||
func (m *MMClient) createCookieJar(token string) *cookiejar.Jar {
|
||||
var cookies []*http.Cookie
|
||||
jar, _ := cookiejar.New(nil)
|
||||
firstCookie := &http.Cookie{
|
||||
Name: "MMAUTHTOKEN",
|
||||
Value: token,
|
||||
Path: "/",
|
||||
Domain: m.Credentials.Server,
|
||||
}
|
||||
cookies = append(cookies, firstCookie)
|
||||
cookieURL, _ := url.Parse("https://" + m.Credentials.Server)
|
||||
jar.SetCookies(cookieURL, cookies)
|
||||
return jar
|
||||
}
|
||||
|
||||
func (m *MMClient) checkAlive() error {
|
||||
// check if session still is valid
|
||||
_, resp := m.Client.GetMe("")
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
m.logger.Debug("WS PING")
|
||||
return m.sendWSRequest("ping", nil)
|
||||
}
|
||||
|
||||
func (m *MMClient) sendWSRequest(action string, data map[string]interface{}) error {
|
||||
req := &model.WebSocketRequest{}
|
||||
req.Seq = m.WsSequence
|
||||
req.Action = action
|
||||
req.Data = data
|
||||
m.WsSequence++
|
||||
m.logger.Debugf("sendWsRequest %#v", req)
|
||||
return m.WsClient.WriteJSON(req)
|
||||
}
|
||||
|
||||
func supportedVersion(version string) bool {
|
||||
if strings.HasPrefix(version, "3.8.0") ||
|
||||
strings.HasPrefix(version, "3.9.0") ||
|
||||
strings.HasPrefix(version, "3.10.0") ||
|
||||
strings.HasPrefix(version, "4.") ||
|
||||
strings.HasPrefix(version, "5.") {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func digestString(s string) string {
|
||||
return fmt.Sprintf("%x", md5.Sum([]byte(s))) //nolint:gosec
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
package matterclient
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
func (m *MMClient) parseActionPost(rmsg *Message) {
|
||||
// add post to cache, if it already exists don't relay this again.
|
||||
// this should fix reposts
|
||||
if ok, _ := m.lruCache.ContainsOrAdd(digestString(rmsg.Raw.Data["post"].(string)), true); ok && rmsg.Raw.Event != model.WEBSOCKET_EVENT_POST_DELETED {
|
||||
m.logger.Debugf("message %#v in cache, not processing again", rmsg.Raw.Data["post"].(string))
|
||||
rmsg.Text = ""
|
||||
return
|
||||
}
|
||||
data := model.PostFromJson(strings.NewReader(rmsg.Raw.Data["post"].(string)))
|
||||
// we don't have the user, refresh the userlist
|
||||
if m.GetUser(data.UserId) == nil {
|
||||
m.logger.Infof("User '%v' is not known, ignoring message '%#v'",
|
||||
data.UserId, data)
|
||||
return
|
||||
}
|
||||
rmsg.Username = m.GetUserName(data.UserId)
|
||||
rmsg.Channel = m.GetChannelName(data.ChannelId)
|
||||
rmsg.UserID = data.UserId
|
||||
rmsg.Type = data.Type
|
||||
teamid, _ := rmsg.Raw.Data["team_id"].(string)
|
||||
// edit messsages have no team_id for some reason
|
||||
if teamid == "" {
|
||||
// we can find the team_id from the channelid
|
||||
teamid = m.GetChannelTeamId(data.ChannelId)
|
||||
rmsg.Raw.Data["team_id"] = teamid
|
||||
}
|
||||
if teamid != "" {
|
||||
rmsg.Team = m.GetTeamName(teamid)
|
||||
}
|
||||
// direct message
|
||||
if rmsg.Raw.Data["channel_type"] == "D" {
|
||||
rmsg.Channel = m.GetUser(data.UserId).Username
|
||||
}
|
||||
rmsg.Text = data.Message
|
||||
rmsg.Post = data
|
||||
}
|
||||
|
||||
func (m *MMClient) parseMessage(rmsg *Message) {
|
||||
switch rmsg.Raw.Event {
|
||||
case model.WEBSOCKET_EVENT_POSTED, model.WEBSOCKET_EVENT_POST_EDITED, model.WEBSOCKET_EVENT_POST_DELETED:
|
||||
m.parseActionPost(rmsg)
|
||||
case "user_updated":
|
||||
user := rmsg.Raw.Data["user"].(map[string]interface{})
|
||||
if _, ok := user["id"].(string); ok {
|
||||
m.UpdateUser(user["id"].(string))
|
||||
}
|
||||
case "group_added":
|
||||
if err := m.UpdateChannels(); err != nil {
|
||||
m.logger.Errorf("failed to update channels: %#v", err)
|
||||
}
|
||||
/*
|
||||
case model.ACTION_USER_REMOVED:
|
||||
m.handleWsActionUserRemoved(&rmsg)
|
||||
case model.ACTION_USER_ADDED:
|
||||
m.handleWsActionUserAdded(&rmsg)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MMClient) parseResponse(rmsg model.WebSocketResponse) {
|
||||
if rmsg.Data != nil {
|
||||
// ping reply
|
||||
if rmsg.Data["text"].(string) == "pong" {
|
||||
m.WsPingChan <- &rmsg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MMClient) DeleteMessage(postId string) error { //nolint:golint
|
||||
_, resp := m.Client.DeletePost(postId)
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) EditMessage(postId string, text string) (string, error) { //nolint:golint
|
||||
post := &model.Post{Message: text, Id: postId}
|
||||
res, resp := m.Client.UpdatePost(postId, post)
|
||||
if resp.Error != nil {
|
||||
return "", resp.Error
|
||||
}
|
||||
return res.Id, nil
|
||||
}
|
||||
|
||||
func (m *MMClient) GetFileLinks(filenames []string) []string {
|
||||
uriScheme := "https://"
|
||||
if m.NoTLS {
|
||||
uriScheme = "http://"
|
||||
}
|
||||
|
||||
var output []string
|
||||
for _, f := range filenames {
|
||||
res, resp := m.Client.GetFileLink(f)
|
||||
if resp.Error != nil {
|
||||
// public links is probably disabled, create the link ourselves
|
||||
output = append(output, uriScheme+m.Credentials.Server+model.API_URL_SUFFIX_V4+"/files/"+f)
|
||||
continue
|
||||
}
|
||||
output = append(output, res)
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func (m *MMClient) GetPosts(channelId string, limit int) *model.PostList { //nolint:golint
|
||||
res, resp := m.Client.GetPostsForChannel(channelId, 0, limit, "", true)
|
||||
if resp.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m *MMClient) GetPostsSince(channelId string, time int64) *model.PostList { //nolint:golint
|
||||
res, resp := m.Client.GetPostsSince(channelId, time, true)
|
||||
if resp.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m *MMClient) GetPublicLink(filename string) string {
|
||||
res, resp := m.Client.GetFileLink(filename)
|
||||
if resp.Error != nil {
|
||||
return ""
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (m *MMClient) GetPublicLinks(filenames []string) []string {
|
||||
var output []string
|
||||
for _, f := range filenames {
|
||||
res, resp := m.Client.GetFileLink(f)
|
||||
if resp.Error != nil {
|
||||
continue
|
||||
}
|
||||
output = append(output, res)
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
func (m *MMClient) PostMessage(channelId string, text string, rootId string) (string, error) { //nolint:golint
|
||||
post := &model.Post{ChannelId: channelId, Message: text, RootId: rootId}
|
||||
res, resp := m.Client.CreatePost(post)
|
||||
if resp.Error != nil {
|
||||
return "", resp.Error
|
||||
}
|
||||
return res.Id, nil
|
||||
}
|
||||
|
||||
func (m *MMClient) PostMessageWithFiles(channelId string, text string, rootId string, fileIds []string) (string, error) { //nolint:golint
|
||||
post := &model.Post{ChannelId: channelId, Message: text, RootId: rootId, FileIds: fileIds}
|
||||
res, resp := m.Client.CreatePost(post)
|
||||
if resp.Error != nil {
|
||||
return "", resp.Error
|
||||
}
|
||||
return res.Id, nil
|
||||
}
|
||||
|
||||
func (m *MMClient) SearchPosts(query string) *model.PostList {
|
||||
res, resp := m.Client.SearchPosts(m.Team.Id, query, false)
|
||||
if resp.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// SendDirectMessage sends a direct message to specified user
|
||||
func (m *MMClient) SendDirectMessage(toUserId string, msg string, rootId string) { //nolint:golint
|
||||
m.SendDirectMessageProps(toUserId, msg, rootId, nil)
|
||||
}
|
||||
|
||||
func (m *MMClient) SendDirectMessageProps(toUserId string, msg string, rootId string, props map[string]interface{}) { //nolint:golint
|
||||
m.logger.Debugf("SendDirectMessage to %s, msg %s", toUserId, msg)
|
||||
// create DM channel (only happens on first message)
|
||||
_, resp := m.Client.CreateDirectChannel(m.User.Id, toUserId)
|
||||
if resp.Error != nil {
|
||||
m.logger.Debugf("SendDirectMessage to %#v failed: %s", toUserId, resp.Error)
|
||||
return
|
||||
}
|
||||
channelName := model.GetDMNameFromIds(toUserId, m.User.Id)
|
||||
|
||||
// update our channels
|
||||
if err := m.UpdateChannels(); err != nil {
|
||||
m.logger.Errorf("failed to update channels: %#v", err)
|
||||
}
|
||||
|
||||
// build & send the message
|
||||
msg = strings.Replace(msg, "\r", "", -1)
|
||||
post := &model.Post{ChannelId: m.GetChannelId(channelName, m.Team.Id), Message: msg, RootId: rootId, Props: props}
|
||||
m.Client.CreatePost(post)
|
||||
}
|
||||
|
||||
func (m *MMClient) UploadFile(data []byte, channelId string, filename string) (string, error) { //nolint:golint
|
||||
f, resp := m.Client.UploadFile(data, channelId, filename)
|
||||
if resp.Error != nil {
|
||||
return "", resp.Error
|
||||
}
|
||||
return f.FileInfos[0].Id, nil
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
package matterclient
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
func (m *MMClient) GetNickName(userId string) string { //nolint:golint
|
||||
user := m.GetUser(userId)
|
||||
if user != nil {
|
||||
return user.Nickname
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetStatus(userId string) string { //nolint:golint
|
||||
res, resp := m.Client.GetUserStatus(userId, "")
|
||||
if resp.Error != nil {
|
||||
return ""
|
||||
}
|
||||
if res.Status == model.STATUS_AWAY {
|
||||
return "away"
|
||||
}
|
||||
if res.Status == model.STATUS_ONLINE {
|
||||
return "online"
|
||||
}
|
||||
return "offline"
|
||||
}
|
||||
|
||||
func (m *MMClient) GetStatuses() map[string]string {
|
||||
var ids []string
|
||||
statuses := make(map[string]string)
|
||||
for id := range m.Users {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
res, resp := m.Client.GetUsersStatusesByIds(ids)
|
||||
if resp.Error != nil {
|
||||
return statuses
|
||||
}
|
||||
for _, status := range res {
|
||||
statuses[status.UserId] = "offline"
|
||||
if status.Status == model.STATUS_AWAY {
|
||||
statuses[status.UserId] = "away"
|
||||
}
|
||||
if status.Status == model.STATUS_ONLINE {
|
||||
statuses[status.UserId] = "online"
|
||||
}
|
||||
}
|
||||
return statuses
|
||||
}
|
||||
|
||||
func (m *MMClient) GetTeamId() string { //nolint:golint
|
||||
return m.Team.Id
|
||||
}
|
||||
|
||||
// GetTeamName returns the name of the specified teamId
|
||||
func (m *MMClient) GetTeamName(teamId string) string { //nolint:golint
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for _, t := range m.OtherTeams {
|
||||
if t.Id == teamId {
|
||||
return t.Team.Name
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetUser(userId string) *model.User { //nolint:golint
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
_, ok := m.Users[userId]
|
||||
if !ok {
|
||||
res, resp := m.Client.GetUser(userId, "")
|
||||
if resp.Error != nil {
|
||||
return nil
|
||||
}
|
||||
m.Users[userId] = res
|
||||
}
|
||||
return m.Users[userId]
|
||||
}
|
||||
|
||||
func (m *MMClient) GetUserName(userId string) string { //nolint:golint
|
||||
user := m.GetUser(userId)
|
||||
if user != nil {
|
||||
return user.Username
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *MMClient) GetUsers() map[string]*model.User {
|
||||
users := make(map[string]*model.User)
|
||||
m.RLock()
|
||||
defer m.RUnlock()
|
||||
for k, v := range m.Users {
|
||||
users[k] = v
|
||||
}
|
||||
return users
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateUsers() error {
|
||||
idx := 0
|
||||
max := 200
|
||||
mmusers, resp := m.Client.GetUsers(idx, max, "")
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
for len(mmusers) > 0 {
|
||||
m.Lock()
|
||||
for _, user := range mmusers {
|
||||
m.Users[user.Id] = user
|
||||
}
|
||||
m.Unlock()
|
||||
mmusers, resp = m.Client.GetUsers(idx, max, "")
|
||||
time.Sleep(time.Millisecond * 300)
|
||||
if resp.Error != nil {
|
||||
return errors.New(resp.Error.DetailedError)
|
||||
}
|
||||
idx++
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateUserNick(nick string) error {
|
||||
user := m.User
|
||||
user.Nickname = nick
|
||||
_, resp := m.Client.UpdateUser(user)
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UsernamesInChannel(channelId string) []string { //nolint:golint
|
||||
res, resp := m.Client.GetChannelMembers(channelId, 0, 50000, "")
|
||||
if resp.Error != nil {
|
||||
m.logger.Errorf("UsernamesInChannel(%s) failed: %s", channelId, resp.Error)
|
||||
return []string{}
|
||||
}
|
||||
allusers := m.GetUsers()
|
||||
result := []string{}
|
||||
for _, member := range *res {
|
||||
result = append(result, allusers[member.UserId].Nickname)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateStatus(userId string, status string) error { //nolint:golint
|
||||
_, resp := m.Client.UpdateUserStatus(userId, &model.Status{Status: status})
|
||||
if resp.Error != nil {
|
||||
return resp.Error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MMClient) UpdateUser(userId string) { //nolint:golint
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
res, resp := m.Client.GetUser(userId, "")
|
||||
if resp.Error != nil {
|
||||
return
|
||||
}
|
||||
m.Users[userId] = res
|
||||
}
|
2
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
2
vendor/github.com/bwmarrin/discordgo/discord.go
generated
vendored
@ -22,7 +22,7 @@ import (
|
||||
)
|
||||
|
||||
// VERSION of DiscordGo, follows Semantic Versioning. (http://semver.org/)
|
||||
const VERSION = "0.27.0"
|
||||
const VERSION = "0.27.1"
|
||||
|
||||
// New creates a new Discord session with provided token.
|
||||
// If the token is for a bot, it must be prefixed with "Bot "
|
||||
|
1
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
1
vendor/github.com/bwmarrin/discordgo/restapi.go
generated
vendored
<