cchat-discord/internal/discord/session/session.go

154 lines
3.7 KiB
Go
Raw Normal View History

2020-09-08 04:44:09 +00:00
package session
import (
"context"
2021-03-13 11:49:23 +00:00
"time"
2020-09-08 04:44:09 +00:00
2020-12-20 05:44:26 +00:00
"github.com/diamondburned/arikawa/v2/gateway"
"github.com/diamondburned/arikawa/v2/session"
2020-09-08 04:44:09 +00:00
"github.com/diamondburned/cchat"
2021-03-15 04:30:05 +00:00
"github.com/diamondburned/cchat-discord/internal/discord/session/guild"
"github.com/diamondburned/cchat-discord/internal/discord/session/guild/folder"
"github.com/diamondburned/cchat-discord/internal/discord/session/private"
"github.com/diamondburned/cchat-discord/internal/discord/state"
2021-03-13 11:49:23 +00:00
"github.com/diamondburned/cchat-discord/internal/funcutil"
2020-10-07 01:53:15 +00:00
"github.com/diamondburned/cchat/utils/empty"
2020-12-20 05:44:26 +00:00
"github.com/diamondburned/ningen/v2"
2020-09-08 04:44:09 +00:00
"github.com/pkg/errors"
)
2020-10-07 01:53:15 +00:00
var ErrMFA = session.ErrMFA
2020-09-08 04:44:09 +00:00
type Session struct {
empty.Session
private cchat.Server
state *state.Instance
2020-09-08 04:44:09 +00:00
}
2020-10-07 01:53:15 +00:00
func NewFromInstance(i *state.Instance) (cchat.Session, error) {
priv, err := private.New(i)
if err != nil {
return nil, errors.Wrap(err, "failed to make main private server")
}
return &Session{
private: priv,
state: i,
}, nil
2020-09-08 04:44:09 +00:00
}
func (s *Session) ID() cchat.ID {
return s.state.UserID.String()
2020-09-08 04:44:09 +00:00
}
2021-03-13 11:49:23 +00:00
func (s *Session) Name(ctx context.Context, l cchat.LabelContainer) (func(), error) {
2021-03-15 04:30:05 +00:00
return s.state.Labels.AddPresenceLabel(s.state.UserID, l), nil
2020-09-08 04:44:09 +00:00
}
func (s *Session) Disconnect() error {
2021-03-13 11:49:23 +00:00
return s.state.CloseGracefully()
2020-09-08 04:44:09 +00:00
}
func (s *Session) AsSessionSaver() cchat.SessionSaver { return s.state }
2020-09-08 04:44:09 +00:00
2021-03-13 11:49:23 +00:00
func (s *Session) Servers(container cchat.ServersContainer) (func(), error) {
if err := s.servers(container); err != nil {
return nil, err
}
2020-09-08 04:44:09 +00:00
2021-03-13 11:49:23 +00:00
retryFn := func() {
// We should set up a back-off here.
for s.servers(container) != nil {
time.Sleep(5 * time.Second)
}
}
2020-09-08 04:44:09 +00:00
2021-03-13 11:49:23 +00:00
stop := funcutil.JoinCancels(
// Reset the entire container when the session is closed.
s.state.AddHandler(func(*session.Closed) {
container.SetServers(nil)
}),
// Set the entire container again once reconnected.
s.state.AddHandler(func(*ningen.Connected) {
retryFn()
}),
// Update the entire container when we update the guild list. Blame
// Discord on this one.
s.state.AddHandler(func(update *gateway.UserSettingsUpdateEvent) {
if update.GuildFolders != nil || update.GuildPositions != nil {
retryFn()
}
}),
)
return stop, nil
2020-09-08 04:44:09 +00:00
}
func (s *Session) servers(container cchat.ServersContainer) error {
2020-12-20 05:44:26 +00:00
ready := s.state.Ready()
2020-09-08 04:44:09 +00:00
// If the user has guild folders:
2021-03-13 08:21:12 +00:00
if len(ready.UserSettings.GuildFolders) > 0 {
2020-09-08 04:44:09 +00:00
// TODO: account for missing guilds.
2020-12-20 05:44:26 +00:00
toplevels := make([]cchat.Server, 1, len(ready.UserSettings.GuildFolders)+1)
toplevels[0] = s.private
2020-09-08 04:44:09 +00:00
2020-12-20 05:44:26 +00:00
for _, guildFolder := range ready.UserSettings.GuildFolders {
2020-09-08 04:44:09 +00:00
// TODO: correct.
2021-03-13 11:49:23 +00:00
// TODO: correct how? What did I mean by this?
2020-09-08 04:44:09 +00:00
switch {
case guildFolder.ID != 0:
2020-09-08 04:44:09 +00:00
fallthrough
case len(guildFolder.GuildIDs) > 1:
toplevels = append(toplevels, folder.New(s.state, guildFolder))
2020-09-08 04:44:09 +00:00
case len(guildFolder.GuildIDs) == 1:
g, err := guild.NewFromID(s.state, guildFolder.GuildIDs[0])
2020-09-08 04:44:09 +00:00
if err != nil {
continue
}
toplevels = append(toplevels, g)
}
}
container.SetServers(toplevels)
2021-03-13 08:21:12 +00:00
return nil
}
2020-09-08 04:44:09 +00:00
// If the user doesn't have guild folders but has sorted their guilds
// before:
2021-03-13 08:21:12 +00:00
if len(ready.UserSettings.GuildPositions) > 0 {
2020-12-20 05:44:26 +00:00
guilds := make([]cchat.Server, 1, len(ready.UserSettings.GuildPositions)+1)
guilds[0] = s.private
2020-09-08 04:44:09 +00:00
2020-12-20 05:44:26 +00:00
for _, id := range ready.UserSettings.GuildPositions {
g, err := guild.NewFromID(s.state, id)
2020-09-08 04:44:09 +00:00
if err != nil {
continue
}
guilds = append(guilds, g)
}
container.SetServers(guilds)
2021-03-13 08:21:12 +00:00
return nil
}
2020-09-08 04:44:09 +00:00
// None of the above:
2021-03-13 08:21:12 +00:00
g, err := s.state.Guilds()
if err != nil {
return err
}
2021-03-13 08:21:12 +00:00
servers := make([]cchat.Server, len(g)+1)
servers[0] = s.private
2020-09-08 04:44:09 +00:00
2021-03-13 08:21:12 +00:00
for i := range g {
servers[i+1] = guild.New(s.state, &g[i])
2020-09-08 04:44:09 +00:00
}
2021-03-13 08:21:12 +00:00
container.SetServers(servers)
2020-09-08 04:44:09 +00:00
return nil
}