diff --git a/discordo.go b/discordo.go index 9699fc4..f191e64 100644 --- a/discordo.go +++ b/discordo.go @@ -1,16 +1,12 @@ package main import ( - "os" "sort" "strings" "github.com/atotto/clipboard" - "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/rigormorrtiss/discordgo" "github.com/rigormorrtiss/discordo/ui" "github.com/rigormorrtiss/discordo/util" "github.com/rivo/tview" @@ -25,9 +21,9 @@ var ( messageInputField *tview.InputField mainFlex *tview.Flex - conf *util.Config - discordState *state.State - channel *discord.Channel + conf *util.Config + session *discordgo.Session + channel *discordgo.Channel ) func main() { @@ -66,15 +62,7 @@ func main() { messageInputField = ui.NewMessageInputField(onMessageInputFieldInputCapture, conf.Theme) mainFlex = ui.NewMainFlex(guildsTreeView, channelsTreeView, messagesTextView, messageInputField) - api.UserAgent = "" + - "Mozilla/5.0 (X11; Linux x86_64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) " + - "Chrome/92.0.4515.131 Safari/537.36" - gateway.DefaultIdentity.Browser = "Chrome" - gateway.DefaultIdentity.OS = "Linux" - gateway.DefaultIdentity.Device = "" - - token := os.Getenv("DISCORDO_TOKEN") + token := conf.Token if t := util.GetPassword("token"); t != "" { token = t } @@ -84,7 +72,12 @@ func main() { SetRoot(mainFlex, true). SetFocus(guildsTreeView) - discordState = newState(token) + session = newSession() + session.Token = token + session.Identify.Token = token + if err := session.Open(); err != nil { + panic(err) + } } else { loginForm = ui.NewLoginForm(onLoginFormLoginButtonSelected) app.SetRoot(loginForm, true) @@ -118,7 +111,7 @@ func onMessageInputFieldInputCapture(e *tcell.EventKey) *tcell.EventKey { return nil } - discordState.SendMessage(channel.ID, t) + session.ChannelMessageSend(channel.ID, t) messageInputField.SetText("") case tcell.KeyCtrlV: text, _ := clipboard.ReadAll() @@ -129,23 +122,30 @@ func onMessageInputFieldInputCapture(e *tcell.EventKey) *tcell.EventKey { return e } -func newState(token string) (s *state.State) { - var err error - s, err = state.New(token) +func newSession() *discordgo.Session { + s, err := discordgo.New() if err != nil { panic(err) } - s.AddHandler(onSessionReady) - s.AddHandler(onSessionMessageCreate) - if err = s.Open(s.Context()); err != nil { - panic(err) - } + s.UserAgent = "" + + "Mozilla/5.0 (X11; Linux x86_64) " + + "AppleWebKit/537.36 (KHTML, like Gecko) " + + "Chrome/92.0.4515.131 Safari/537.36" + s.Identify.Compress = false + s.Identify.Intents = 0 + s.Identify.LargeThreshold = 0 + s.Identify.Properties.Device = "" + s.Identify.Properties.Browser = "Chrome" + s.Identify.Properties.OS = "Linux" - return + s.AddHandlerOnce(onSessionReady) + s.AddHandler(onSessionMessageCreate) + + return s } -func onSessionReady(r *gateway.ReadyEvent) { +func onSessionReady(_ *discordgo.Session, r *discordgo.Ready) { rootN := guildsTreeView.GetRoot() for _, g := range r.Guilds { gn := tview.NewTreeNode(g.Name). @@ -156,10 +156,9 @@ func onSessionReady(r *gateway.ReadyEvent) { guildsTreeView.SetCurrentNode(rootN) } -func onSessionMessageCreate(m *gateway.MessageCreateEvent) { +func onSessionMessageCreate(_ *discordgo.Session, m *discordgo.MessageCreate) { if channel != nil && channel.ID == m.ChannelID { - me, _ := discordState.Cabinet.Me() - util.WriteMessage(messagesTextView, me.ID, m.Message) + util.WriteMessage(messagesTextView, m.Message, session.State.Ready.User.ID) } } @@ -168,8 +167,9 @@ func onGuildsTreeViewSelected(gn *tview.TreeNode) { messagesTextView.SetTitle("") messagesTextView.Clear() - gID := gn.GetReference().(discord.GuildID) - cs, _ := discordState.Cabinet.Channels(gID) + gID := gn.GetReference().(string) + g, _ := session.State.Guild(gID) + cs := g.Channels sort.Slice(cs, func(i, j int) bool { return cs[i].Position < cs[j].Position }) @@ -181,7 +181,7 @@ func onGuildsTreeViewSelected(gn *tview.TreeNode) { // Category channels CategoryLoop: for _, c := range cs { - if c.Type == discord.GuildCategory { + if c.Type == discordgo.ChannelTypeGuildCategory { for _, child := range cs { if child.ParentID == c.ID { cn := tview.NewTreeNode(c.Name). @@ -203,12 +203,12 @@ CategoryLoop: } func onChannelsTreeViewSelected(n *tview.TreeNode) { - cID := n.GetReference().(discord.ChannelID) - c, _ := discordState.Cabinet.Channel(cID) + cID := n.GetReference().(string) + c, _ := session.State.Channel(cID) switch c.Type { - case discord.GuildCategory: + case discordgo.ChannelTypeGuildCategory: n.SetExpanded(!n.IsExpanded()) - case discord.GuildText, discord.GuildNews: + case discordgo.ChannelTypeGuildText, discordgo.ChannelTypeGuildNews: if len(n.GetChildren()) == 0 { channel = c app.SetFocus(messageInputField) @@ -224,24 +224,13 @@ func onChannelsTreeViewSelected(n *tview.TreeNode) { } else { n.SetExpanded(!n.IsExpanded()) } - case discord.GuildNewsThread, discord.GuildPrivateThread, discord.GuildPublicThread: - channel = c - app.SetFocus(messageInputField) - messagesTextView.Clear() - messagesTextView.SetTitle(c.Name) - - go writeMessages(c.ID) - case discord.GuildStageVoice, discord.GuildVoice: - messagesTextView.Clear() - messagesTextView.SetTitle(c.Name) } } -func writeMessages(cID discord.ChannelID) { - msgs, _ := discordState.Messages(cID, conf.GetMessagesLimit) - me, _ := discordState.Cabinet.Me() +func writeMessages(cID string) { + msgs, _ := session.ChannelMessages(cID, conf.GetMessagesLimit, "", "", "") for i := len(msgs) - 1; i >= 0; i-- { - util.WriteMessage(messagesTextView, me.ID, msgs[i]) + util.WriteMessage(messagesTextView, msgs[i], session.State.Ready.User.ID) } } @@ -252,29 +241,33 @@ func onLoginFormLoginButtonSelected() { return } - // Make a scratch HTTP client without a token - client := api.NewClient("") + session = newSession() // Try to login without TOTP - l, err := client.Login(email, password) + lr, err := util.Login(session, email, password) if err != nil { panic(err) } - if l.Token != "" && !l.MFA { + if lr.Token != "" && !lr.MFA { app. SetRoot(mainFlex, true). SetFocus(guildsTreeView) - discordState = newState(l.Token) - go util.SetPassword("token", l.Token) - } else if l.MFA { + session.Token = lr.Token + session.Identify.Token = lr.Token + if err = session.Open(); err != nil { + panic(err) + } + + go util.SetPassword("token", lr.Token) + } else if lr.MFA { loginForm = ui.NewMfaLoginForm(func() { code := loginForm.GetFormItem(0).(*tview.InputField).GetText() if code == "" { return } - l, err := client.TOTP(code, l.Ticket) + lr, err = util.TOTP(session, code, lr.Ticket) if err != nil { panic(err) } @@ -283,8 +276,13 @@ func onLoginFormLoginButtonSelected() { SetRoot(mainFlex, true). SetFocus(guildsTreeView) - discordState = newState(l.Token) - go util.SetPassword("token", l.Token) + session.Token = lr.Token + session.Identify.Token = lr.Token + if err = session.Open(); err != nil { + panic(err) + } + + go util.SetPassword("token", lr.Token) }) app.SetRoot(loginForm, true) diff --git a/go.mod b/go.mod index 3d19ac1..d867485 100644 --- a/go.mod +++ b/go.mod @@ -4,8 +4,8 @@ go 1.16 require ( github.com/atotto/clipboard v0.1.4 - github.com/diamondburned/arikawa/v3 v3.0.0-20210817064836-eece98903ab1 github.com/gdamore/tcell/v2 v2.4.0 + github.com/rigormorrtiss/discordgo v0.23.3-0.20210821171441-1f1f1a283940 github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2 github.com/zalando/go-keyring v0.1.1 ) diff --git a/go.sum b/go.sum index 8475408..276f6c7 100644 --- a/go.sum +++ b/go.sum @@ -1,128 +1,61 @@ -github.com/99designs/keyring v1.1.6 h1:kVDC2uCgVwecxCk+9zoCt2uEL6dt+dfVzMvGgnVcIuM= -github.com/99designs/keyring v1.1.6/go.mod h1:16e0ds7LGQQcT59QqkTg72Hh5ShM51Byv5PEmW6uoRU= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU= -github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= +github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= +github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= github.com/danieljoos/wincred v1.1.0 h1:3RNcEpBg4IhIChZdFRSdlQt1QjCp1sMAPIrOnm7Yf8g= github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= -github.com/danieljoos/wincred v1.1.1 h1:FgOybUqUGGwgBz+ga92qD4f/ZPvuPryRjashrk/p9IA= -github.com/danieljoos/wincred v1.1.1/go.mod h1:gSBQmTx6G0VmLowygiA7ZD0p0E09HJ68vta8z/RT2d0= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/diamondburned/arikawa/v3 v3.0.0-20210711201954-9651328b74d3 h1:pkLTxFSFSgjHd8234CuO6lgb2GOZ8m1vI1sbusx5c8Y= -github.com/diamondburned/arikawa/v3 v3.0.0-20210711201954-9651328b74d3/go.mod h1:sNqM/iGXuH87wEH1rpQBEY1PR0AAkRKJuUhJGOdo7To= -github.com/diamondburned/arikawa/v3 v3.0.0-20210812184548-e97dcb750c7c h1:z8ZrHZO9jZN4Iy7bXD+jzLkv0IPqoZJbrFfD4nVMUSg= -github.com/diamondburned/arikawa/v3 v3.0.0-20210812184548-e97dcb750c7c/go.mod h1:sNqM/iGXuH87wEH1rpQBEY1PR0AAkRKJuUhJGOdo7To= -github.com/diamondburned/arikawa/v3 v3.0.0-20210817064836-eece98903ab1 h1:G9lzJO+/R/r8Hj4h6n6eCkLe73EM39OCCEmLv5lDgSk= -github.com/diamondburned/arikawa/v3 v3.0.0-20210817064836-eece98903ab1/go.mod h1:sNqM/iGXuH87wEH1rpQBEY1PR0AAkRKJuUhJGOdo7To= -github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= -github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= -github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= -github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.3.3/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= -github.com/gdamore/tcell/v2 v2.3.11 h1:ECO6WqHGbKZ3HrSL7bG/zArMCmLaNr5vcjjMVnLHpzc= -github.com/gdamore/tcell/v2 v2.3.11/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= github.com/gdamore/tcell/v2 v2.4.0 h1:W6dxJEmaxYvhICFoTY3WrLLEXsQ11SaFnKGVEXW57KM= github.com/gdamore/tcell/v2 v2.4.0/go.mod h1:cTTuF84Dlj/RqmaCIV5p4w8uG1zWdk0SF6oBpwHp4fU= -github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= -github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc= -github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= -github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= -github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= -github.com/keybase/go-keychain v0.0.0-20201121013009-976c83ec27a6 h1:Mj0fhP9dzHKPijsmli/XbXMDKe1/KWy5xKci8e3nmBg= -github.com/keybase/go-keychain v0.0.0-20201121013009-976c83ec27a6/go.mod h1:N83iQ9rnnzi2KZuTu+0xBcD1JNWn1jSN140ggAF7HeE= -github.com/keybase/go.dbus v0.0.0-20200324223359-a94be52c0b03/go.mod h1:a8clEhrrGV/d76/f9r2I41BwANMihfZYV9C223vaxqE= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= -github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821163811-db65d56a4b18 h1:D0sC2reaRk7X1bxOItwZZQYVxSPPeRKXSJ7uXZkAv2c= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821163811-db65d56a4b18/go.mod h1:Gyt2AvlO/hpjiDzHiTBknKGgwL/dTL+BHbiNXdXE5bU= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821170026-7f73e903f58c h1:SAkw14xJXJFTBmQVu0n5dkOzEgAhKBqIys/KZC590x8= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821170026-7f73e903f58c/go.mod h1:Gyt2AvlO/hpjiDzHiTBknKGgwL/dTL+BHbiNXdXE5bU= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821171441-1f1f1a283940 h1:Qg0MhvFI7Mg4Za9/Htou4y3nDaU0uABMYRys4U1WK4g= +github.com/rigormorrtiss/discordgo v0.23.3-0.20210821171441-1f1f1a283940/go.mod h1:Gyt2AvlO/hpjiDzHiTBknKGgwL/dTL+BHbiNXdXE5bU= github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2 h1:I5N0WNMgPSq5NKUFspB4jMJ6n2P0ipz5FlOlB4BXviQ= github.com/rivo/tview v0.0.0-20210624165335-29d673af0ce2/go.mod h1:IxQujbYMAh4trWr0Dwa8jfciForjVmxyHpskZX6aydQ= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/zalando/go-keyring v0.1.1 h1:w2V9lcx/Uj4l+dzAf1m9s+DJ1O8ROkEHnynonHjTcYE= github.com/zalando/go-keyring v0.1.1/go.mod h1:OIC+OZ28XbmwFxU/Rp9V7eKzZjamBJwRzC8UFJH9+L8= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E= -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2 h1:46ULzRKLh1CwgRq2dC5SlBzEqqNCi8rreOZnNrbqcIY= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069 h1:siQdpVirKtzPhKl3lZWozZraCFObP8S1v6PRp0bLrtU= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/ui/flex.go b/ui/flex.go index d79abfc..1bbe096 100644 --- a/ui/flex.go +++ b/ui/flex.go @@ -5,7 +5,7 @@ import ( ) // NewMainFlex creates and returns a new main flex. -func NewMainFlex(gTreeV *tview.TreeView, cTreeV *tview.TreeView, textV *tview.TextView, i *tview.InputField) (mf *tview.Flex) { +func NewMainFlex(gTreeV *tview.TreeView, cTreeV *tview.TreeView, textV *tview.TextView, i *tview.InputField) *tview.Flex { lf := tview.NewFlex(). SetDirection(tview.FlexRow). AddItem(gTreeV, 0, 1, false). @@ -14,9 +14,9 @@ func NewMainFlex(gTreeV *tview.TreeView, cTreeV *tview.TreeView, textV *tview.Te SetDirection(tview.FlexRow). AddItem(textV, 0, 1, false). AddItem(i, 3, 1, false) - mf = tview.NewFlex(). + mf := tview.NewFlex(). AddItem(lf, 0, 1, false). - AddItem(rf, 0, 5, false) + AddItem(rf, 0, 4, false) return mf } diff --git a/ui/forms.go b/ui/forms.go index 6a404a6..4798dcb 100644 --- a/ui/forms.go +++ b/ui/forms.go @@ -5,33 +5,33 @@ import ( "github.com/rivo/tview" ) -func newBaseLoginForm() (f *tview.Form) { - f = tview.NewForm() +func newBaseLoginForm() *tview.Form { + f := tview.NewForm() f. SetButtonsAlign(tview.AlignCenter). SetButtonBackgroundColor(tcell.GetColor("#5865F2")). SetBorder(true). SetBorderPadding(0, 0, 1, 0) - return + return f } // NewLoginForm creates and returns a new login form. -func NewLoginForm(onLoginFormLoginButtonSelected func()) (f *tview.Form) { - f = newBaseLoginForm() +func NewLoginForm(onLoginFormLoginButtonSelected func()) *tview.Form { + f := newBaseLoginForm() f. AddInputField("Email", "", 0, nil, nil). AddPasswordField("Password", "", 0, 0, nil). AddButton("Login", onLoginFormLoginButtonSelected) - return + return f } // NewMfaLoginForm creates and returns a new MFA login form. -func NewMfaLoginForm(onMfaLoginFormLoginButtonSelected func()) (f *tview.Form) { - f = newBaseLoginForm(). +func NewMfaLoginForm(onMfaLoginFormLoginButtonSelected func()) *tview.Form { + f := newBaseLoginForm(). AddPasswordField("Code", "", 0, 0, nil). AddButton("Login", onMfaLoginFormLoginButtonSelected) - return + return f } diff --git a/ui/inputfields.go b/ui/inputfields.go index 7cf3ec9..5c76139 100644 --- a/ui/inputfields.go +++ b/ui/inputfields.go @@ -7,8 +7,8 @@ import ( ) // NewMessageInputField creates and returns a new message inputfield. -func NewMessageInputField(onMessageInputFieldInputCapture func(*tcell.EventKey) *tcell.EventKey, t *util.Theme) (i *tview.InputField) { - i = tview.NewInputField() +func NewMessageInputField(onMessageInputFieldInputCapture func(*tcell.EventKey) *tcell.EventKey, t *util.Theme) *tview.InputField { + i := tview.NewInputField() i. SetPlaceholder("Message..."). SetPlaceholderTextColor(tcell.ColorWhite). @@ -18,5 +18,5 @@ func NewMessageInputField(onMessageInputFieldInputCapture func(*tcell.EventKey) SetBorder(true). SetBorderPadding(0, 0, 1, 0) - return + return i } diff --git a/ui/textviews.go b/ui/textviews.go index 3fff362..ed81584 100644 --- a/ui/textviews.go +++ b/ui/textviews.go @@ -5,9 +5,9 @@ import ( ) // NewMessagesTextView creates and returns a new messages textview. -func NewMessagesTextView(app *tview.Application) (textV *tview.TextView) { - textV = tview.NewTextView() - textV. +func NewMessagesTextView(app *tview.Application) *tview.TextView { + v := tview.NewTextView() + v. SetDynamicColors(true). SetWordWrap(true). ScrollToEnd(). @@ -18,5 +18,5 @@ func NewMessagesTextView(app *tview.Application) (textV *tview.TextView) { SetBorderPadding(0, 0, 1, 0). SetTitleAlign(tview.AlignLeft) - return + return v } diff --git a/ui/treeviews.go b/ui/treeviews.go index 4ddc9c6..404b324 100644 --- a/ui/treeviews.go +++ b/ui/treeviews.go @@ -1,48 +1,46 @@ package ui import ( - "github.com/diamondburned/arikawa/v3/discord" + "github.com/rigormorrtiss/discordgo" "github.com/rivo/tview" ) // NewGuildsTreeView creates and returns a new guilds treeview. -func NewGuildsTreeView(onGuildsTreeViewSelected func(*tview.TreeNode)) (treeV *tview.TreeView) { - treeN := tview.NewTreeNode("") - treeV = tview.NewTreeView() - treeV. +func NewGuildsTreeView(onGuildsTreeViewSelected func(*tview.TreeNode)) *tview.TreeView { + v := tview.NewTreeView() + v. SetTopLevel(1). - SetRoot(treeN). + SetRoot(tview.NewTreeNode("")). SetSelectedFunc(onGuildsTreeViewSelected). SetBorder(true). SetBorderPadding(0, 0, 1, 0). SetTitle("Guilds"). SetTitleAlign(tview.AlignLeft) - return + return v } // NewChannelsTreeView creates and returns a new channels treeview. -func NewChannelsTreeView(onChannelsTreeViewSelected func(*tview.TreeNode)) (treeV *tview.TreeView) { - treeN := tview.NewTreeNode("") - treeV = tview.NewTreeView() - treeV. +func NewChannelsTreeView(onChannelsTreeViewSelected func(*tview.TreeNode)) *tview.TreeView { + v := tview.NewTreeView() + v. SetTopLevel(1). - SetRoot(treeN). + SetRoot(tview.NewTreeNode("")). SetSelectedFunc(onChannelsTreeViewSelected). SetBorder(true). SetBorderPadding(0, 0, 1, 0). SetTitle("Channels"). SetTitleAlign(tview.AlignLeft) - return + return v } // NewTextChannelTreeNode creates and returns a new text channel treenode. -func NewTextChannelTreeNode(c discord.Channel) (n *tview.TreeNode) { - n = tview.NewTreeNode("[::d]#" + c.Name + "[::-]"). +func NewTextChannelTreeNode(c *discordgo.Channel) *tview.TreeNode { + n := tview.NewTreeNode("[::d]#" + c.Name + "[::-]"). SetReference(c.ID) - return + return n } // GetTreeNodeByReference gets the TreeNode that has reference r from the given treeview. @@ -60,9 +58,9 @@ func GetTreeNodeByReference(r interface{}, treeV *tview.TreeView) (mn *tview.Tre } // CreateTopLevelTreeNodes creates treenodes for the top-level (orphan) channels. -func CreateTopLevelTreeNodes(rootN *tview.TreeNode, cs []discord.Channel) { +func CreateTopLevelTreeNodes(rootN *tview.TreeNode, cs []*discordgo.Channel) { for _, c := range cs { - if (c.Type == discord.GuildText || c.Type == discord.GuildNews) && (c.ParentID == 0 || c.ParentID == discord.NullChannelID) { + if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) && (c.ParentID == "") { cn := NewTextChannelTreeNode(c) rootN.AddChild(cn) continue @@ -71,9 +69,9 @@ func CreateTopLevelTreeNodes(rootN *tview.TreeNode, cs []discord.Channel) { } // CreateSecondLevelTreeNodes creates treenodes for the second-level (category children) channels. -func CreateSecondLevelTreeNodes(channelsTreeView *tview.TreeView, rootN *tview.TreeNode, cs []discord.Channel) { +func CreateSecondLevelTreeNodes(channelsTreeView *tview.TreeView, rootN *tview.TreeNode, cs []*discordgo.Channel) { for _, c := range cs { - if (c.Type == discord.GuildText || c.Type == discord.GuildNews) && (c.ParentID != 0 && c.ParentID != discord.NullChannelID) { + if (c.Type == discordgo.ChannelTypeGuildText || c.Type == discordgo.ChannelTypeGuildNews) && (c.ParentID != "") { if pn := GetTreeNodeByReference(c.ParentID, channelsTreeView); pn != nil { cn := NewTextChannelTreeNode(c) pn.AddChild(cn) diff --git a/util/config.go b/util/config.go index 3ae1c5d..be73d8c 100644 --- a/util/config.go +++ b/util/config.go @@ -14,8 +14,9 @@ type Theme struct { // Config consists of fields, such as theme, mouse, so on, that may be customized by the user. type Config struct { + Token string `json:"token,omitempty"` Mouse bool `json:"mouse,omitempty"` - GetMessagesLimit uint `json:"getMessagesLimit,omitempty"` + GetMessagesLimit int `json:"getMessagesLimit,omitempty"` Theme *Theme `json:"theme,omitempty"` } diff --git a/util/discord.go b/util/discord.go index 0acbf74..e6a3bbe 100644 --- a/util/discord.go +++ b/util/discord.go @@ -1,24 +1,22 @@ package util import ( + "encoding/json" "fmt" "strings" - "github.com/diamondburned/arikawa/v3/discord" + "github.com/rigormorrtiss/discordgo" "github.com/rivo/tview" ) // WriteMessage parses and writes the parsed message to the provided textview. -func WriteMessage(v *tview.TextView, clientID discord.UserID, m discord.Message) { +func WriteMessage(v *tview.TextView, m *discordgo.Message, clientID string) { var b strings.Builder switch m.Type { - case discord.DefaultMessage, discord.InlinedReplyMessage: + case discordgo.MessageTypeDefault, discordgo.MessageTypeReply: parseMessage(v, &b, m, clientID) fmt.Fprintln(v, b.String()) - case discord.ThreadStarterMessage: - parseMessage(v, &b, *m.ReferencedMessage, clientID) - fmt.Fprintln(v, b.String()) - case discord.GuildMemberJoinMessage: + case discordgo.MessageTypeGuildMemberJoin: b.WriteString("[#5865F2]") b.WriteString(m.Author.Username) b.WriteString("[-]") @@ -27,11 +25,11 @@ func WriteMessage(v *tview.TextView, clientID discord.UserID, m discord.Message) } } -func parseMessage(v *tview.TextView, b *strings.Builder, m discord.Message, clientID discord.UserID) { +func parseMessage(v *tview.TextView, b *strings.Builder, m *discordgo.Message, clientID string) { // $ ╭ AUTHOR_USERNAME (BOT) MESSAGE_CONTENT*linebreak* - parseReferencedMessage(b, clientID, m.ReferencedMessage) + parseReferencedMessage(b, m.ReferencedMessage, clientID) // $ AUTHOR_USERNAME (BOT)*spacee* - parseAuthor(b, clientID, m.Author) + parseAuthor(b, m.Author, clientID) // $ MESSAGE_CONTENT parseContent(b, m, clientID) // $ *space*(edited) @@ -42,20 +40,20 @@ func parseMessage(v *tview.TextView, b *strings.Builder, m discord.Message, clie parseAttachments(b, m.Attachments) } -func parseContent(b *strings.Builder, m discord.Message, clientID discord.UserID) { +func parseContent(b *strings.Builder, m *discordgo.Message, clientID string) { if m.Content != "" { m.Content = parseMessageMentions(m.Content, m.Mentions, clientID) b.WriteString(m.Content) } } -func parseEditedTimestamp(b *strings.Builder, t discord.Timestamp) { - if t.IsValid() { +func parseEditedTimestamp(b *strings.Builder, t discordgo.Timestamp) { + if t != "" { b.WriteString(" [::d](edited)[::-]") } } -func parseMessageMentions(content string, mentions []discord.GuildUser, clientID discord.UserID) string { +func parseMessageMentions(content string, mentions []*discordgo.User, clientID string) string { for _, mUser := range mentions { var color string if mUser.ID == clientID { @@ -66,10 +64,10 @@ func parseMessageMentions(content string, mentions []discord.GuildUser, clientID content = strings.NewReplacer( // <@USER_ID> - "<@"+mUser.ID.String()+">", + "<@"+mUser.ID+">", color+"@"+mUser.Username+"[-:-]", // <@!USER_ID> - "<@!"+mUser.ID.String()+">", + "<@!"+mUser.ID+">", color+"@"+mUser.Username+"[-:-]", ).Replace(content) } @@ -77,13 +75,13 @@ func parseMessageMentions(content string, mentions []discord.GuildUser, clientID return content } -func parseEmbeds(b *strings.Builder, embeds []discord.Embed) { +func parseEmbeds(b *strings.Builder, embeds []*discordgo.MessageEmbed) { for range embeds { b.WriteString("\n") } } -func parseAttachments(b *strings.Builder, attachments []discord.Attachment) { +func parseAttachments(b *strings.Builder, attachments []*discordgo.MessageAttachment) { for _, a := range attachments { b.WriteString("\n[") b.WriteString(a.Filename) @@ -92,7 +90,7 @@ func parseAttachments(b *strings.Builder, attachments []discord.Attachment) { } } -func parseAuthor(b *strings.Builder, clientID discord.UserID, u discord.User) { +func parseAuthor(b *strings.Builder, u *discordgo.User, clientID string) { if u.ID == clientID { b.WriteString("[#57F287]") } else { @@ -107,7 +105,7 @@ func parseAuthor(b *strings.Builder, clientID discord.UserID, u discord.User) { } } -func parseReferencedMessage(b *strings.Builder, clientID discord.UserID, rm *discord.Message) { +func parseReferencedMessage(b *strings.Builder, rm *discordgo.Message, clientID string) { if rm != nil { b.WriteString(" ╭ ") @@ -131,3 +129,55 @@ func parseReferencedMessage(b *strings.Builder, clientID discord.UserID, rm *dis b.WriteString("[::-]\n") } } + +type loginResponse struct { + MFA bool `json:"mfa"` + SMS bool `json:"sms"` + Ticket string `json:"ticket"` + Token string `json:"token"` +} + +// Login creates a new request to the `/login` endpoint for essential login information. +func Login(s *discordgo.Session, email, password string) (*loginResponse, error) { + data := struct { + Email string `json:"email"` + Password string `json:"password"` + }{email, password} + resp, err := s.RequestWithBucketID("POST", discordgo.EndpointLogin, data, discordgo.EndpointLogin) + if err != nil { + return nil, err + } + + var lr loginResponse + err = json.Unmarshal(resp, &lr) + if err != nil { + return nil, err + } + + return &lr, nil +} + +// TOTP creates a new request to `/mfa/totp` endpoint for time-based one-time +// passcode for essential login information +func TOTP(s *discordgo.Session, code, ticket string) (*loginResponse, error) { + var data struct { + Code string `json:"code"` + Ticket string `json:"ticket"` + } + data.Code = code + data.Ticket = ticket + + endpoint := discordgo.EndpointAuth + "mfa/totp" + resp, err := s.RequestWithBucketID("POST", endpoint, data, endpoint) + if err != nil { + return nil, err + } + + var lr *loginResponse + err = json.Unmarshal(resp, &lr) + if err != nil { + return nil, err + } + + return lr, nil +}