diff --git a/channels.go b/channels.go index 7439961..ae5c81e 100644 --- a/channels.go +++ b/channels.go @@ -114,8 +114,32 @@ func (m *Client) GetChannelTeamID(id string) string { m.RLock() defer m.RUnlock() - for _, t := range append(m.OtherTeams, m.Team) { - for _, channel := range append(t.Channels, t.MoreChannels...) { + if m.Team != nil { + for _, channel := range m.Team.Channels { + if channel.Id == id { + return channel.TeamId + } + } + + for _, channel := range m.Team.MoreChannels { + if channel.Id == id { + return channel.TeamId + } + } + } + + for _, t := range m.OtherTeams { + if m.Team != nil && t.ID == m.Team.ID { + continue + } + + for _, channel := range t.Channels { + if channel.Id == id { + return channel.TeamId + } + } + + for _, channel := range t.MoreChannels { if channel.Id == id { return channel.TeamId } @@ -207,6 +231,7 @@ func (m *Client) JoinChannel(channelID string) error { } func (m *Client) UpdateChannelsTeam(teamID string) error { + var ( mmchannels []*model.Channel resp *model.Response diff --git a/matterclient.go b/matterclient.go index 60100ee..4999c47 100644 --- a/matterclient.go +++ b/matterclient.go @@ -40,6 +40,7 @@ type Team struct { Channels []*model.Channel MoreChannels []*model.Channel Users map[string]*model.User + LastUserSync time.Time } type Message struct { @@ -58,7 +59,7 @@ type Client struct { *Credentials Team *Team - OtherTeams []*Team + OtherTeams map[string]*Team Client *model.Client4 User *model.User Users map[string]*model.User @@ -146,8 +147,8 @@ func (m *Client) Login() error { if m.Team == nil { validTeamNames := make([]string, len(m.OtherTeams)) - for i, t := range m.OtherTeams { - validTeamNames[i] = t.Team.Name + for _, t := range m.OtherTeams { + validTeamNames = append(validTeamNames, t.Team.Name) } return fmt.Errorf("Team '%s' not found in %v", m.Credentials.Team, validTeamNames) @@ -305,6 +306,12 @@ func (m *Client) serverAlive(b *backoff.Backoff) error { func (m *Client) initUser() error { ctx := context.TODO() + m.Lock() + if m.OtherTeams == nil { + m.OtherTeams = make(map[string]*Team) + } + m.Unlock() + m.Lock() defer m.Unlock() // we only load all team data on initial login. @@ -315,6 +322,22 @@ func (m *Client) initUser() error { } for _, team := range teams { + m.Lock() + existingTeam, exists := m.OtherTeams[team.Id] + m.Unlock() + + if exists && time.Since(existingTeam.LastUserSync) < 15*time.Minute { + m.logger.Debugf("skipping user fetch for team %s: cache is only %v old", team.Name, time.Since(existingTeam.LastUserSync).Round(time.Second)) + m.Lock() + if team.Name == m.Credentials.Team { + m.Team = existingTeam + } + m.Unlock() + continue + } + + m.logger.Debugf("fetching users for team %s (cache expired or missing)", team.Name) + idx := 0 max := 200 usermap := make(map[string]*model.User) @@ -339,18 +362,20 @@ func (m *Client) initUser() error { time.Sleep(time.Millisecond * 200) } m.logger.Debugf("found %d users in team %s", len(usermap), team.Name) + + t := &Team{ + Team: team, + Users: usermap, + ID: team.Id, + LastUserSync: time.Now(), + } + // add all users for k, v := range usermap { m.Users[k] = v } - t := &Team{ - Team: team, - Users: usermap, - ID: team.Id, - } - - m.OtherTeams = append(m.OtherTeams, t) + m.OtherTeams[team.Id] = t if team.Name == m.Credentials.Team { m.Team = t @@ -622,6 +647,11 @@ func (m *Client) WsReceiver(ctx context.Context) { m.logger.Debugf("WsReceiver event: %#v", event) + eventType := event.EventType() + if eventType == model.WebsocketEventNewUser || eventType == model.WebsocketEventUserUpdated { + go m.syncSingleUser(ctx, event) + } + msg := &Message{ Raw: event, Team: m.Credentials.Team, @@ -761,3 +791,36 @@ func (m *Client) antiIdle(ctx context.Context, channelID string, interval int) { } } } + +func (m *Client) syncSingleUser(ctx context.Context, event *model.WebSocketEvent) { + userID, ok := event.GetData()["user_id"].(string) + if !ok { + return + } + + user, _, err := m.Client.GetUser(ctx, userID, "") + if err != nil { + m.logger.Errorf("syncSingleUser failed to get user %s: %v", userID, err) + return + } + + m.logger.Debugf("dynamically caching updated/new user: %s", user.Username) + + m.Lock() + defer m.Unlock() + + if m.Users == nil { + m.Users = make(map[string]*model.User) + } + m.Users[user.Id] = user + + if teamID, hasTeam := event.GetData()["team_id"].(string); hasTeam { + if team, exists := m.OtherTeams[teamID]; exists { + if team.Users == nil { + team.Users = make(map[string]*model.User) + } + team.Users[user.Id] = user + m.logger.Debugf("added/updated user %s in map for team %s", user.Username, team.Team.Name) + } + } +}