diff --git a/config/config.go b/config/config.go index 831a996..72ea15a 100644 --- a/config/config.go +++ b/config/config.go @@ -9,6 +9,8 @@ import ( lua "github.com/yuin/gopher-lua" ) +const Name = "discordo" + //go:embed config.lua var LuaConfig []byte diff --git a/ui/core.go b/ui/core.go index f17d650..a9d08ec 100644 --- a/ui/core.go +++ b/ui/core.go @@ -1,14 +1,11 @@ package ui import ( - "context" "strings" "github.com/ayntgl/discordo/config" - "github.com/diamondburned/arikawa/v3/api" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/arikawa/v3/gateway" - "github.com/diamondburned/arikawa/v3/state" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" lua "github.com/yuin/gopher-lua" @@ -37,7 +34,7 @@ type Core struct { MessageInput *MessageInput Config *config.Config - State *state.State + State *State focused focused } @@ -101,38 +98,8 @@ func (c *Core) Run(token string) error { c.Application.EnableMouse(lua.LVAsBool(c.Config.State.GetGlobal("mouse"))) - identifyProperties, ok := c.Config.State.GetGlobal("identifyProperties").(*lua.LTable) - if !ok { - identifyProperties = c.Config.State.NewTable() - } - - userAgent := lua.LVAsString(identifyProperties.RawGetString("userAgent")) - - c.State = state.NewWithIdentifier(gateway.NewIdentifier(gateway.IdentifyCommand{ - Token: token, - Intents: nil, - Properties: gateway.IdentifyProperties{ - Browser: lua.LVAsString(identifyProperties.RawGetString("browser")), - BrowserVersion: lua.LVAsString(identifyProperties.RawGetString("browserVersion")), - BrowserUserAgent: userAgent, - OS: lua.LVAsString(identifyProperties.RawGetString("os")), - }, - // The official client sets the compress field as false. - Compress: false, - })) - - // For user accounts, all of the guilds, the user is in, are dispatched in the READY gateway event. Whereas, the guilds are dispatched discretely in the GUILD_CREATE gateway events for bot accounts. - if !strings.HasPrefix(c.State.Token, "Bot") { - api.UserAgent = userAgent - c.State.AddHandler(c.onStateReady) - } else { - c.State.AddIntents(gateway.IntentGuilds | gateway.IntentGuildMessages) - } - - c.State.AddHandler(c.onStateGuildCreate) - c.State.AddHandler(c.onStateGuildDelete) - c.State.AddHandler(c.onStateMessageCreate) - return c.State.Open(context.Background()) + c.State = NewState(token, c) + return c.State.Run() } func (c *Core) register() { diff --git a/ui/state.go b/ui/state.go new file mode 100644 index 0000000..01cfefd --- /dev/null +++ b/ui/state.go @@ -0,0 +1,146 @@ +package ui + +import ( + "context" + "fmt" + "runtime" + "strings" + + "github.com/ayntgl/discordo/config" + "github.com/diamondburned/arikawa/v3/api" + "github.com/diamondburned/arikawa/v3/discord" + "github.com/diamondburned/arikawa/v3/gateway" + "github.com/diamondburned/arikawa/v3/state" + "github.com/rivo/tview" +) + +func init() { + api.UserAgent = fmt.Sprintf("%s/%s %s/%s", config.Name, "0.1", "arikawa", "v3") + gateway.DefaultIdentity = gateway.IdentifyProperties{ + OS: runtime.GOOS, + Browser: config.Name, + } +} + +type State struct { + *state.State + core *Core +} + +func NewState(token string, c *Core) *State { + return &State{ + State: state.New(token), + core: c, + } +} + +func (s *State) Run() error { + // Add the essential intents to the identify data for bot accounts. + if strings.HasPrefix(s.Token, "Bot") { + s.AddIntents(gateway.IntentGuilds | gateway.IntentGuildMessages) + } + + s.AddHandler(s.ready) + s.AddHandler(s.guildCreate) + s.AddHandler(s.guildDelete) + s.AddHandler(s.messageCreate) + return s.Open(context.Background()) +} + +func (s *State) ready(r *gateway.ReadyEvent) { + rootNode := s.core.GuildsTree.GetRoot() + for _, gf := range r.UserSettings.GuildFolders { + if gf.ID == 0 { + for _, gID := range gf.GuildIDs { + g, err := s.State.Cabinet.Guild(gID) + if err != nil { + return + } + + guildNode := tview.NewTreeNode(g.Name) + guildNode.SetReference(g.ID) + rootNode.AddChild(guildNode) + } + } else { + var b strings.Builder + + if gf.Color != discord.NullColor { + b.WriteByte('[') + b.WriteString(gf.Color.String()) + b.WriteByte(']') + } else { + b.WriteString("[#ED4245]") + } + + if gf.Name != "" { + b.WriteString(gf.Name) + } else { + b.WriteString("Folder") + } + + b.WriteString("[-]") + + folderNode := tview.NewTreeNode(b.String()) + rootNode.AddChild(folderNode) + + for _, gID := range gf.GuildIDs { + g, err := s.State.Cabinet.Guild(gID) + if err != nil { + return + } + + guildNode := tview.NewTreeNode(g.Name) + guildNode.SetReference(g.ID) + folderNode.AddChild(guildNode) + } + } + + } + + s.core.GuildsTree.SetCurrentNode(rootNode) + s.core.Application.SetFocus(s.core.GuildsTree) +} + +func (s *State) guildCreate(g *gateway.GuildCreateEvent) { + guildNode := tview.NewTreeNode(g.Name) + guildNode.SetReference(g.ID) + + rootNode := s.core.GuildsTree.GetRoot() + rootNode.AddChild(guildNode) + + s.core.GuildsTree.SetCurrentNode(rootNode) + s.core.Application.SetFocus(s.core.GuildsTree) + s.core.Application.Draw() +} + +func (s *State) guildDelete(g *gateway.GuildDeleteEvent) { + rootNode := s.core.GuildsTree.GetRoot() + var parentNode *tview.TreeNode + rootNode.Walk(func(node, _ *tview.TreeNode) bool { + if node.GetReference() == g.ID { + parentNode = node + return false + } + + return true + }) + + if parentNode != nil { + rootNode.RemoveChild(parentNode) + } + + s.core.Application.Draw() +} + +func (s *State) messageCreate(m *gateway.MessageCreateEvent) { + if s.core.ChannelsTree.SelectedChannel != nil && s.core.ChannelsTree.SelectedChannel.ID == m.ChannelID { + _, err := s.core.MessagesPanel.Write(buildMessage(s.core, m.Message)) + if err != nil { + return + } + + if len(s.core.MessagesPanel.GetHighlights()) == 0 { + s.core.MessagesPanel.ScrollToEnd() + } + } +} diff --git a/ui/util.go b/ui/util.go index ad6063e..606530d 100644 --- a/ui/util.go +++ b/ui/util.go @@ -5,7 +5,6 @@ import ( "strings" "github.com/diamondburned/arikawa/v3/discord" - "github.com/diamondburned/arikawa/v3/state" lua "github.com/yuin/gopher-lua" ) @@ -59,7 +58,7 @@ func findMessageByID(ms []discord.Message, mID discord.MessageID) (int, *discord return -1, nil } -func hasPermission(s *state.State, cID discord.ChannelID, p discord.Permissions) bool { +func hasPermission(s *State, cID discord.ChannelID, p discord.Permissions) bool { perm, err := s.Permissions(cID, s.Ready().User.ID) if err != nil { return false