Skip to content

Commit

Permalink
Add more things to new bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
tulir committed Jul 10, 2024
1 parent ca190f5 commit 982a9bf
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 40 deletions.
3 changes: 3 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
include:
- project: 'mautrix/ci'
file: '/gov2.yml'

variables:
BINARY_NAME_V2: mautrix-slack
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/yuin/goldmark v1.7.4
go.mau.fi/util v0.5.1-0.20240708204011-043c35cda49c
gopkg.in/yaml.v3 v3.0.1
maunium.net/go/mautrix v0.19.0-beta.1.0.20240709160900-fc7ed77e2630
maunium.net/go/mautrix v0.19.0-beta.1.0.20240710101752-e9097ad3a2c9
)

require (
Expand All @@ -34,4 +34,4 @@ require (
maunium.net/go/mauflag v1.0.0 // indirect
)

replace github.com/slack-go/slack => github.com/beeper/slackgo v0.0.0-20240709225243-e3f25fc5595e
replace github.com/slack-go/slack => github.com/beeper/slackgo v0.0.0-20240710101621-cfe3621af5cc
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/beeper/slackgo v0.0.0-20240709225243-e3f25fc5595e h1:GB0cG2XysNFP7+mFqoJlIkAMdFerVvdMywixR2MQfsk=
github.com/beeper/slackgo v0.0.0-20240709225243-e3f25fc5595e/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/beeper/slackgo v0.0.0-20240710101621-cfe3621af5cc h1:oEsfjMRWpETjrNonSDniyOx4q5euDckh663eyDbJTmg=
github.com/beeper/slackgo v0.0.0-20240710101621-cfe3621af5cc/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
Expand Down Expand Up @@ -73,5 +73,5 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
maunium.net/go/mauflag v1.0.0 h1:YiaRc0tEI3toYtJMRIfjP+jklH45uDHtT80nUamyD4M=
maunium.net/go/mauflag v1.0.0/go.mod h1:nLivPOpTpHnpzEh8jEdSL9UqO9+/KBJFmNRlwKfkPeA=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240709160900-fc7ed77e2630 h1:X+IuVExANBr0gfFQ22vpecvDzkiSCVAnFAYvyIZ+uOI=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240709160900-fc7ed77e2630/go.mod h1:bNQrvIftiwJ+7OjSh+Gza5xcncq1ooHk6oyDWq4B4sg=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240710101752-e9097ad3a2c9 h1:Ef016JcokEl17PynhncgowIS52YZcbl9frgI+sZC8kc=
maunium.net/go/mautrix v0.19.0-beta.1.0.20240710101752-e9097ad3a2c9/go.mod h1:bNQrvIftiwJ+7OjSh+Gza5xcncq1ooHk6oyDWq4B4sg=
59 changes: 45 additions & 14 deletions pkg/connector/chatinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (s *SlackClient) fetchChatInfo(ctx context.Context, channelID string, fetch
}
members.IsFull = len(members.Members) >= info.NumMembers
}
//members.TotalMemberCount = info.NumMembers
members.TotalMemberCount = info.NumMembers
name := s.Main.Config.FormatChannelName(&ChannelNameParams{
Channel: info,
TeamName: s.BootResp.Team.Name,
Expand All @@ -114,16 +114,52 @@ func (s *SlackClient) fetchChatInfo(ctx context.Context, channelID string, fetch
}, nil
}

func (s *SlackClient) getTeamInfo() *bridgev2.ChatInfo {
name := s.Main.Config.FormatTeamName(&s.BootResp.Team)
avatarURL, _ := s.BootResp.Team.Icon["image_230"].(string)
if s.BootResp.Team.Icon["image_default"] == true {
avatarURL = ""
}
return &bridgev2.ChatInfo{
Name: &name,
Topic: nil,
Avatar: makeAvatar(avatarURL),
Members: &bridgev2.ChatMemberList{
IsFull: false,
TotalMemberCount: 0,
Members: []bridgev2.ChatMember{{EventSender: s.makeEventSender(s.UserID)}},
PowerLevels: &bridgev2.PowerLevelChanges{EventsDefault: ptr.Ptr(100)},
},
IsSpace: ptr.Ptr(true),
}
}

func (s *SlackClient) GetChatInfo(ctx context.Context, portal *bridgev2.Portal) (*bridgev2.ChatInfo, error) {
_, channelID := slackid.ParsePortalID(portal.ID)
return s.fetchChatInfo(ctx, channelID, portal.MXID == "" || !s.Main.Config.ParticipantSyncOnlyOnCreate)
teamID, channelID := slackid.ParsePortalID(portal.ID)
if teamID == "" {
return nil, fmt.Errorf("invalid portal ID %q", portal.ID)
} else if channelID == "" {
return s.getTeamInfo(), nil
} else {
return s.fetchChatInfo(ctx, channelID, portal.MXID == "" || !s.Main.Config.ParticipantSyncOnlyOnCreate)
}
}

func makeAvatar(avatarURL string) *bridgev2.Avatar {
return &bridgev2.Avatar{
ID: networkid.AvatarID(avatarURL),
Get: func(ctx context.Context) ([]byte, error) {
return downloadPlainFile(ctx, avatarURL, "avatar")
},
Remove: avatarURL == "",
}
}

func (s *SlackClient) fetchUserInfo(ctx context.Context, userID string) (*bridgev2.UserInfo, error) {
var info *slack.User
var botInfo *slack.Bot
var err error
if userID[0] == 'b' || userID[0] == 'B' {
if userID[0] == 'B' {
botInfo, err = s.Client.GetBotInfoContext(ctx, userID)
} else {
info, err = s.Client.GetUserInfoContext(ctx, userID)
Expand All @@ -133,25 +169,20 @@ func (s *SlackClient) fetchUserInfo(ctx context.Context, userID string) (*bridge
}
var name *string
var avatarURL string
isBot := userID == "USLACKBOT" || botInfo != nil
isBot := userID == "USLACKBOT"
if info != nil {
name = ptr.Ptr(s.Main.Config.FormatDisplayname(info))
avatarURL = info.Profile.ImageOriginal
isBot = isBot || info.IsBot || info.IsAppUser
} else if botInfo != nil {
name = ptr.Ptr(s.Main.Config.FormatBotDisplayname(botInfo))
avatarURL = botInfo.Icons.Image72
isBot = true
}
return &bridgev2.UserInfo{
Identifiers: []string{fmt.Sprintf("slack-internal:%s", userID)},
Name: name,
Avatar: &bridgev2.Avatar{
ID: networkid.AvatarID(avatarURL),
Get: func(ctx context.Context) ([]byte, error) {
return downloadPlainFile(ctx, avatarURL, "user avatar")
},
Remove: avatarURL == "",
},
Identifiers: []string{fmt.Sprintf("slack-internal:%s", userID)},
Name: name,
Avatar: makeAvatar(avatarURL),
IsBot: &isBot,
ExtraUpdates: nil,
}, nil
Expand Down
63 changes: 44 additions & 19 deletions pkg/connector/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ import (
"context"
"fmt"
"strings"
"time"

"github.com/rs/zerolog"
"github.com/slack-go/slack"

"maunium.net/go/mautrix/bridge/status"
"maunium.net/go/mautrix/bridgev2"
"maunium.net/go/mautrix/bridgev2/networkid"
Expand Down Expand Up @@ -54,31 +54,39 @@ func makeSlackClient(log *zerolog.Logger, token, cookieToken string) *slack.Clie
func (s *SlackConnector) LoadUserLogin(ctx context.Context, login *bridgev2.UserLogin) error {
teamID, userID := slackid.ParseUserLoginID(login.ID)
token, ok := login.Metadata.Extra["token"].(string)
var sc *SlackClient
if !ok {
login.Client = &SlackClient{Main: s, UserLogin: login, UserID: userID, TeamID: teamID}
return nil
sc = &SlackClient{Main: s, UserLogin: login, UserID: userID, TeamID: teamID}
} else {
cookieToken, _ := login.Metadata.Extra["cookie_token"].(string)
client := makeSlackClient(&login.Log, token, cookieToken)
sc = &SlackClient{
Main: s,
UserLogin: login,
Client: client,
RTM: client.NewRTM(),
UserID: userID,
TeamID: teamID,
}
}
cookieToken, _ := login.Metadata.Extra["cookie_token"].(string)
client := makeSlackClient(&login.Log, token, cookieToken)
login.Client = &SlackClient{
Main: s,
UserLogin: login,
Client: client,
RTM: client.NewRTM(),
UserID: userID,
TeamID: teamID,
teamPortalKey := networkid.PortalKey{ID: slackid.MakeTeamPortalID(teamID)}
var err error
sc.TeamPortal, err = s.br.UnlockedGetPortalByID(ctx, teamPortalKey, false)
if err != nil {
return fmt.Errorf("failed to get team portal: %w", err)
}
return nil
}

type SlackClient struct {
Main *SlackConnector
UserLogin *bridgev2.UserLogin
Client *slack.Client
RTM *slack.RTM
UserID string
TeamID string
BootResp *slack.ClientBootResponse
Main *SlackConnector
UserLogin *bridgev2.UserLogin
Client *slack.Client
RTM *slack.RTM
UserID string
TeamID string
BootResp *slack.ClientBootResponse
TeamPortal *bridgev2.Portal
}

var _ bridgev2.NetworkAPI = (*SlackClient)(nil)
Expand Down Expand Up @@ -107,10 +115,27 @@ func (s *SlackClient) Connect(ctx context.Context) error {
}
return err
}
err = s.syncTeamPortal(ctx)
if err != nil {
return err
}
go s.RTM.ManageConnection()
return nil
}

func (s *SlackClient) syncTeamPortal(ctx context.Context) error {
info := s.getTeamInfo()
if s.TeamPortal.MXID == "" {
err := s.TeamPortal.CreateMatrixRoom(ctx, s.UserLogin, info)
if err != nil {
return err
}
} else {
s.TeamPortal.UpdateInfo(ctx, info, s.UserLogin, nil, time.Time{})
}
return nil
}

func (s *SlackClient) consumeEvents(ctx context.Context) {
for evt := range s.RTM.IncomingEvents {
s.HandleSlackEvent(evt.Data)
Expand Down
4 changes: 4 additions & 0 deletions pkg/connector/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ func (s *SlackTokenLogin) SubmitCookies(ctx context.Context, input map[string]st
}
sc := ul.Client.(*SlackClient)
sc.BootResp = info
err = sc.syncTeamPortal(ctx)
if err != nil {
return nil, fmt.Errorf("failed to sync team portal: %w", err)
}
go sc.RTM.ManageConnection()
return &bridgev2.LoginStep{
Type: bridgev2.LoginStepTypeComplete,
Expand Down
4 changes: 3 additions & 1 deletion pkg/msgconv/matrixfmt/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ func (mhp *MatrixHTMLParser) pillConverter(displayname, mxid, eventID string, ct
zerolog.Ctx(ctx.Ctx).Err(err).Msg("Failed to get portal by MXID to convert mention")
} else if portal != nil {
_, channelID := slackid.ParsePortalID(portal.ID)
return fmt.Sprintf("<#%s>", channelID)
if channelID != "" {
return fmt.Sprintf("<#%s>", channelID)
}
}
case '#':
// TODO add aliases for rooms so they can be mentioned easily
Expand Down
9 changes: 9 additions & 0 deletions pkg/slackid/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ func UserLoginIDToUserID(userLoginID networkid.UserLoginID) networkid.UserID {
return networkid.UserID(strings.ToLower(string(userLoginID)))
}

const TeamPortalChannelID = "@"

func MakeTeamPortalID(teamID string) networkid.PortalID {
return MakePortalID(teamID, TeamPortalChannelID)
}

func MakePortalID(teamID, channelID string) networkid.PortalID {
return networkid.PortalID(fmt.Sprintf("%s-%s", teamID, channelID))
}
Expand All @@ -99,6 +105,9 @@ func ParsePortalID(id networkid.PortalID) (teamID, channelID string) {
if len(parts) != 2 {
return "", ""
}
if parts[1] == TeamPortalChannelID {
parts[1] = ""
}
return parts[0], parts[1]
}

Expand Down

0 comments on commit 982a9bf

Please sign in to comment.