From b30d6c3ee1cdb3640713eea461845a384013c1dc Mon Sep 17 00:00:00 2001 From: HekeHokkus Date: Thu, 28 Sep 2023 15:54:48 -0400 Subject: [PATCH 01/17] Update discord.go --- discord.go | 1 + 1 file changed, 1 insertion(+) diff --git a/discord.go b/discord.go index 8efd8fe..6fb1453 100644 --- a/discord.go +++ b/discord.go @@ -50,6 +50,7 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) { dd.commandHandlers[app.config.Section("discord").Key("start_command").MustString("start")] = dd.cmdStart dd.commandHandlers["lang"] = dd.cmdLang dd.commandHandlers["pin"] = dd.cmdPIN + dd.commandHandlers["invite"] = dd.cmdInvite for _, user := range app.storage.GetDiscord() { dd.users[user.ID] = user } From edf6c13f03cb9bb9fc8c90800e1432de2d384728 Mon Sep 17 00:00:00 2001 From: HekeHokkus Date: Thu, 28 Sep 2023 17:55:47 -0400 Subject: [PATCH 02/17] Update discord.go --- discord.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/discord.go b/discord.go index 6fb1453..b674ce9 100644 --- a/discord.go +++ b/discord.go @@ -128,6 +128,8 @@ func (d *DiscordDaemon) run() { d.inviteChannelName = invChannel } } + d.bot.Activity.Name = "/" + app.config.Section("discord").Key("start_command").MustString("start") + d.bot.Activity.Type = dg.ActivityTypeGame defer d.deregisterCommands() defer d.bot.Close() @@ -339,6 +341,18 @@ func (d *DiscordDaemon) registerCommands() { }, }, }, + { + Name: "invite", + Description: "Send an invite to a discord user (admin only).", + Options: []*dg.ApplicationCommandOption{ + { + Type: dg.ApplicationCommandOptionUser, + Name: "user", + Description: "User to Invite", + Required: true, + }, + }, + }, } commands[1].Options[0].Choices = make([]*dg.ApplicationCommandOptionChoice, len(d.app.storage.lang.Telegram)) i := 0 @@ -504,6 +518,13 @@ func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang str } } +func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang string) { + requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) + d.users[i.Interaction.Member.User.ID] = requestor + invuser := i.ApplicationCommandData().Options[0].StringValue() + // Check whether requestor is linked to the admin account +} + func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) { if m.GuildID != "" && d.channelName != "" { if d.channelID == "" { From 3538935d3ba3c472e07a6ae801b6e4870758ad47 Mon Sep 17 00:00:00 2001 From: HekeHokkus Date: Thu, 28 Sep 2023 19:37:35 -0400 Subject: [PATCH 03/17] Update discord.go Adding /invite command and Discord status message to the bot --- discord.go | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 93 insertions(+), 1 deletion(-) diff --git a/discord.go b/discord.go index b674ce9..733135a 100644 --- a/discord.go +++ b/discord.go @@ -351,6 +351,24 @@ func (d *DiscordDaemon) registerCommands() { Description: "User to Invite", Required: true, }, + { + Type: dg.ApplicationCommandOptionInteger, + Name: "expire after", + Description: "Time in minutes before expiration", + Required: false, + }, + { + Type: dg.ApplicationCommandOptionString, + Name: "label", + Description: "Label to apply to the user created with this invite", + Required: false, + }, + { + Type: dg.ApplicationCommandOptionString, + Name: "Profile", + Description: "Profile to apply to the user created with this invite", + Required: false, + }, }, }, } @@ -518,11 +536,85 @@ func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang str } } -func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang string) { +func (d *DiscordDaemon) cmdInvite(app *appContext, s *dg.Session, i *dg.InteractionCreate, lang string) { requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) d.users[i.Interaction.Member.User.ID] = requestor invuser := i.ApplicationCommandData().Options[0].StringValue() + label := i.ApplicationCommandData().Options[2].StringValue() + profile := i.ApplicationCommandData().Options[3].StringValue() + if i.ApplicationCommandData().Options[1] != "" { + expmin := i.ApplicationCommandData().Options[1] + } else { + expmin := 30 + } // Check whether requestor is linked to the admin account + // variation of app.GenerateInvite, some parts commented to potentially add back in later + app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) + currentTime := time.Now() + validTill = currentTime.Add(time.Minute*time.Duration(expmin)) + // make sure code doesn't begin with number + inviteCode := shortuuid.New() + _, err := strconv.Atoi(string(inviteCode[0])) + for err == nil { + inviteCode = shortuuid.New() + _, err = strconv.Atoi(string(inviteCode[0])) + } + var invite Invite + if label != "" { + invite.Label = label + } + invite.Created = currentTime + invite.RemainingUses = 1 + invite.UserExpiry = false + /*if invite.UserExpiry { + invite.UserMonths = req.UserMonths + invite.UserDays = req.UserDays + invite.UserHours = req.UserHours + invite.UserMinutes = req.UserMinutes + }*/ + invite.ValidTill = validTill + if invuser != "" && app.config.Section("invite_emails").Key("enabled").MustBool(false) { + addressValid := false + discord := "" + app.debug.Printf("%s: Sending invite message", inviteCode) + if discordEnabled && !strings.Contains(invuser, "@") { + users := app.discord.GetUsers(invuser) + if len(users) == 0 { + invite.SendTo = fmt.Sprintf("Failed: User not found: \"%s\"", invuser) + } else if len(users) > 1 { + invite.SendTo = fmt.Sprintf("Failed: Multiple users found: \"%s\"", invuser) + } else { + invite.SendTo = invuser + addressValid = true + discord = users[0].User.ID + } + } + if addressValid { + msg, err := app.email.constructInvite(inviteCode, invite, app, false) + if err != nil { + invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) + app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) + } else { + var err error + err = app.discord.SendDM(msg, discord) + if err != nil { + invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) + app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) + } else { + app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, invuser) + } + } + } + } + if profile != "" { + if _, ok := app.storage.GetProfileKey(profile); ok { + invite.Profile = profile + } else { + invite.Profile = "Default" + } + } + app.storage.SetInvitesKey(inviteCode, invite) + respondBool(200, true, gc) } func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) { From c43d5cf1b0b2fde14022f5de94f85672b435057e Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Sat, 30 Sep 2023 11:25:36 -0400 Subject: [PATCH 04/17] Update discord.go --- discord.go | 137 +++++++++++++++++++++++++---------------------------- 1 file changed, 64 insertions(+), 73 deletions(-) diff --git a/discord.go b/discord.go index 733135a..24f51da 100644 --- a/discord.go +++ b/discord.go @@ -3,9 +3,11 @@ package main import ( "fmt" "strings" + "strconv" "time" dg "github.com/bwmarrin/discordgo" + "github.com/lithammer/shortuuid/v3" "github.com/timshannon/badgerhold/v4" ) @@ -50,7 +52,7 @@ func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) { dd.commandHandlers[app.config.Section("discord").Key("start_command").MustString("start")] = dd.cmdStart dd.commandHandlers["lang"] = dd.cmdLang dd.commandHandlers["pin"] = dd.cmdPIN - dd.commandHandlers["invite"] = dd.cmdInvite + dd.commandHandlers["inv"] = dd.cmdInvite for _, user := range app.storage.GetDiscord() { dd.users[user.ID] = user } @@ -128,8 +130,8 @@ func (d *DiscordDaemon) run() { d.inviteChannelName = invChannel } } - d.bot.Activity.Name = "/" + app.config.Section("discord").Key("start_command").MustString("start") - d.bot.Activity.Type = dg.ActivityTypeGame + //dg.Activity.Name = "/" + d.app.config.Section("discord").Key("start_command").MustString("start") + //dg.Activity.Type = dg.ActivityTypeGame defer d.deregisterCommands() defer d.bot.Close() @@ -342,7 +344,7 @@ func (d *DiscordDaemon) registerCommands() { }, }, { - Name: "invite", + Name: "inv", Description: "Send an invite to a discord user (admin only).", Options: []*dg.ApplicationCommandOption{ { @@ -351,24 +353,24 @@ func (d *DiscordDaemon) registerCommands() { Description: "User to Invite", Required: true, }, - { - Type: dg.ApplicationCommandOptionInteger, - Name: "expire after", - Description: "Time in minutes before expiration", - Required: false, - }, - { - Type: dg.ApplicationCommandOptionString, - Name: "label", - Description: "Label to apply to the user created with this invite", - Required: false, - }, - { - Type: dg.ApplicationCommandOptionString, - Name: "Profile", - Description: "Profile to apply to the user created with this invite", - Required: false, - }, + //{ + // Type: dg.ApplicationCommandOptionInteger, + // Name: "expire after", + // Description: "Time in minutes before expiration", + // Required: false, + //}, + //{ + // Type: dg.ApplicationCommandOptionString, + // Name: "label", + // Description: "Label to apply to the user created with this invite", + // Required: false, + //}, + //{ + // Type: dg.ApplicationCommandOptionString, + // Name: "profile", + // Description: "Profile to apply to the user created with this invite", + // Required: false, + //}, }, }, } @@ -536,33 +538,35 @@ func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang str } } -func (d *DiscordDaemon) cmdInvite(app *appContext, s *dg.Session, i *dg.InteractionCreate, lang string) { +func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang string) { + channel, err := s.UserChannelCreate(i.Interaction.Member.User.ID) requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) d.users[i.Interaction.Member.User.ID] = requestor - invuser := i.ApplicationCommandData().Options[0].StringValue() - label := i.ApplicationCommandData().Options[2].StringValue() - profile := i.ApplicationCommandData().Options[3].StringValue() - if i.ApplicationCommandData().Options[1] != "" { - expmin := i.ApplicationCommandData().Options[1] - } else { - expmin := 30 - } - // Check whether requestor is linked to the admin account + invuser := fmt.Sprintf("%v", i.ApplicationCommandData().Options[0].Value) + d.app.debug.Println(invuser) +// label := i.ApplicationCommandData().Options[2].StringValue() +// profile := i.ApplicationCommandData().Options[3].StringValue() +// mins, err := strconv.Atoi(i.ApplicationCommandData().Options[1].StringValue()) + expmin := 30 +// if mins > 0 { +// expmin = mins +// } + // Check whether requestor is linked to the admin account* // variation of app.GenerateInvite, some parts commented to potentially add back in later - app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) + // d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) currentTime := time.Now() - validTill = currentTime.Add(time.Minute*time.Duration(expmin)) + validTill := currentTime.Add(time.Minute*time.Duration(expmin)) // make sure code doesn't begin with number inviteCode := shortuuid.New() - _, err := strconv.Atoi(string(inviteCode[0])) + _, err = strconv.Atoi(string(inviteCode[0])) for err == nil { inviteCode = shortuuid.New() _, err = strconv.Atoi(string(inviteCode[0])) } var invite Invite - if label != "" { - invite.Label = label - } + //if label != "" { + // invite.Label = label + //} invite.Created = currentTime invite.RemainingUses = 1 invite.UserExpiry = false @@ -573,48 +577,35 @@ func (d *DiscordDaemon) cmdInvite(app *appContext, s *dg.Session, i *dg.Interact invite.UserMinutes = req.UserMinutes }*/ invite.ValidTill = validTill - if invuser != "" && app.config.Section("invite_emails").Key("enabled").MustBool(false) { - addressValid := false + if invuser != "" && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { discord := "" - app.debug.Printf("%s: Sending invite message", inviteCode) - if discordEnabled && !strings.Contains(invuser, "@") { - users := app.discord.GetUsers(invuser) - if len(users) == 0 { - invite.SendTo = fmt.Sprintf("Failed: User not found: \"%s\"", invuser) - } else if len(users) > 1 { - invite.SendTo = fmt.Sprintf("Failed: Multiple users found: \"%s\"", invuser) - } else { - invite.SendTo = invuser - addressValid = true - discord = users[0].User.ID - } - } - if addressValid { - msg, err := app.email.constructInvite(inviteCode, invite, app, false) + d.app.debug.Printf("%s: Sending invite message", inviteCode) + invname, err := d.bot.GuildMember(d.guildID, invuser) + invite.SendTo = invname.User.Username + + msg, err := d.app.email.constructInvite(inviteCode, invite, d.app, false) + if err != nil { + invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) + d.app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) + } else { + var err error + err = d.app.discord.SendDM(msg, discord) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) - app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) + d.app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) } else { - var err error - err = app.discord.SendDM(msg, discord) - if err != nil { - invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) - app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) - } else { - app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, invuser) - } + d.app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, invuser) } } } - if profile != "" { - if _, ok := app.storage.GetProfileKey(profile); ok { - invite.Profile = profile - } else { - invite.Profile = "Default" - } - } - app.storage.SetInvitesKey(inviteCode, invite) - respondBool(200, true, gc) + //if profile != "" { + // if _, ok := d.app.storage.GetProfileKey(profile); ok { + // invite.Profile = profile + // } else { + // invite.Profile = "Default" + // } + //} + d.app.storage.SetInvitesKey(inviteCode, invite) } func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) { From 27f85f866e2add2ab3f0e93880735b502cd39f6a Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Sat, 30 Sep 2023 12:10:38 -0400 Subject: [PATCH 05/17] Update discord.go Hopefully functional, any errors are coming from elsewhere --- discord.go | 58 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/discord.go b/discord.go index 24f51da..c862955 100644 --- a/discord.go +++ b/discord.go @@ -130,8 +130,7 @@ func (d *DiscordDaemon) run() { d.inviteChannelName = invChannel } } - //dg.Activity.Name = "/" + d.app.config.Section("discord").Key("start_command").MustString("start") - //dg.Activity.Type = dg.ActivityTypeGame + err = d.bot.UpdateGameStatus(0, "/"+d.app.config.Section("discord").Key("start_command").MustString("start")) defer d.deregisterCommands() defer d.bot.Close() @@ -352,25 +351,25 @@ func (d *DiscordDaemon) registerCommands() { Name: "user", Description: "User to Invite", Required: true, + }, // running with just one option for now to mesh with what we've got, also may have the syntax wrong here + /*{ + Type: dg.ApplicationCommandOptionInteger, + Name: "expire after", + Description: "Time in minutes before expiration", + Required: false, }, - //{ - // Type: dg.ApplicationCommandOptionInteger, - // Name: "expire after", - // Description: "Time in minutes before expiration", - // Required: false, - //}, - //{ - // Type: dg.ApplicationCommandOptionString, - // Name: "label", - // Description: "Label to apply to the user created with this invite", - // Required: false, - //}, - //{ - // Type: dg.ApplicationCommandOptionString, - // Name: "profile", - // Description: "Profile to apply to the user created with this invite", - // Required: false, - //}, + { + Type: dg.ApplicationCommandOptionString, + Name: "label", + Description: "Label to apply to the user created with this invite", + Required: false, + }, + { + Type: dg.ApplicationCommandOptionString, + Name: "profile", + Description: "Profile to apply to the user created with this invite", + Required: false, + }, */ }, }, } @@ -542,18 +541,19 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s channel, err := s.UserChannelCreate(i.Interaction.Member.User.ID) requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) d.users[i.Interaction.Member.User.ID] = requestor + d.app.debug.Println("Requested by: %v: %s:", requestor.JellyfinID, d.users[i.Interaction.Member.User.ID].JellyfinID) invuser := fmt.Sprintf("%v", i.ApplicationCommandData().Options[0].Value) d.app.debug.Println(invuser) -// label := i.ApplicationCommandData().Options[2].StringValue() -// profile := i.ApplicationCommandData().Options[3].StringValue() -// mins, err := strconv.Atoi(i.ApplicationCommandData().Options[1].StringValue()) + //label := i.ApplicationCommandData().Options[2].StringValue() + //profile := i.ApplicationCommandData().Options[3].StringValue() + //mins, err := strconv.Atoi(i.ApplicationCommandData().Options[1].StringValue()) expmin := 30 -// if mins > 0 { -// expmin = mins -// } - // Check whether requestor is linked to the admin account* - // variation of app.GenerateInvite, some parts commented to potentially add back in later - // d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) + //if mins > 0 { + // expmin = mins + //} + // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct + // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options + //d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) currentTime := time.Now() validTill := currentTime.Add(time.Minute*time.Duration(expmin)) // make sure code doesn't begin with number From 729548334de6b3fa356d7fa5ec756c8fb36685b9 Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Sat, 30 Sep 2023 12:16:06 -0400 Subject: [PATCH 06/17] Update discord.go --- discord.go | 1 - 1 file changed, 1 deletion(-) diff --git a/discord.go b/discord.go index c862955..9246e14 100644 --- a/discord.go +++ b/discord.go @@ -541,7 +541,6 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s channel, err := s.UserChannelCreate(i.Interaction.Member.User.ID) requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) d.users[i.Interaction.Member.User.ID] = requestor - d.app.debug.Println("Requested by: %v: %s:", requestor.JellyfinID, d.users[i.Interaction.Member.User.ID].JellyfinID) invuser := fmt.Sprintf("%v", i.ApplicationCommandData().Options[0].Value) d.app.debug.Println(invuser) //label := i.ApplicationCommandData().Options[2].StringValue() From 49dfac514d21b1c69bc9628b2e1c804991ca570d Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Tue, 3 Oct 2023 23:22:20 -0400 Subject: [PATCH 07/17] Update discord.go --- discord.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/discord.go b/discord.go index 9246e14..f6c5433 100644 --- a/discord.go +++ b/discord.go @@ -551,6 +551,10 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s // expmin = mins //} // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct + requestoremail := GetEmailsKey(requestor.JfID) + if !requestoremail.admin { + d.app.err.Printf("User is not admin") + } // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options //d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) currentTime := time.Now() From b595d3ea03d786bcc326a1e8ae775a09fedb9346 Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Tue, 3 Oct 2023 23:37:24 -0400 Subject: [PATCH 08/17] Update discord.go --- discord.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/discord.go b/discord.go index f6c5433..2a9029f 100644 --- a/discord.go +++ b/discord.go @@ -551,7 +551,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s // expmin = mins //} // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct - requestoremail := GetEmailsKey(requestor.JfID) + requestoremail := d.app.storage.GetEmailsKey(requestor.JellyfinID) if !requestoremail.admin { d.app.err.Printf("User is not admin") } From dd93758b0e9d2d44bd807123a4a435acdd18538d Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Tue, 3 Oct 2023 23:59:42 -0400 Subject: [PATCH 09/17] Update discord.go --- discord.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/discord.go b/discord.go index 2a9029f..fc7a74f 100644 --- a/discord.go +++ b/discord.go @@ -551,8 +551,11 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s // expmin = mins //} // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct - requestoremail := d.app.storage.GetEmailsKey(requestor.JellyfinID) - if !requestoremail.admin { + requestoremail, ok := d.app.storage.GetEmailsKey(requestor.JellyfinID) + if !ok { + d.app.err.Printf("Failed to verify admin") + } + if !requestoremail.Admin { d.app.err.Printf("User is not admin") } // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options From e52e21a54b5855aaeda25b08d7605e514ed14d61 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Tue, 10 Oct 2023 13:45:29 +0100 Subject: [PATCH 10/17] discord: fix up /inv basic functionality sending now succeeds, and a reponse of "Invite sent." is given to the requester. Also some formatting changes. --- discord.go | 53 +++++++++++++++++++++++++++------------- lang/telegram/en-us.json | 6 +++-- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/discord.go b/discord.go index fc7a74f..f53b1d7 100644 --- a/discord.go +++ b/discord.go @@ -2,8 +2,8 @@ package main import ( "fmt" - "strings" "strconv" + "strings" "time" dg "github.com/bwmarrin/discordgo" @@ -351,7 +351,7 @@ func (d *DiscordDaemon) registerCommands() { Name: "user", Description: "User to Invite", Required: true, - }, // running with just one option for now to mesh with what we've got, also may have the syntax wrong here + }, // running with just one option for now to mesh with what we've got, also may have the syntax wrong here /*{ Type: dg.ApplicationCommandOptionInteger, Name: "expire after", @@ -539,10 +539,10 @@ func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang str func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang string) { channel, err := s.UserChannelCreate(i.Interaction.Member.User.ID) - requestor := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) - d.users[i.Interaction.Member.User.ID] = requestor - invuser := fmt.Sprintf("%v", i.ApplicationCommandData().Options[0].Value) - d.app.debug.Println(invuser) + requester := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) + d.users[i.Interaction.Member.User.ID] = requester + recipient := i.ApplicationCommandData().Options[0].UserValue(s) + // d.app.debug.Println(invuser) //label := i.ApplicationCommandData().Options[2].StringValue() //profile := i.ApplicationCommandData().Options[3].StringValue() //mins, err := strconv.Atoi(i.ApplicationCommandData().Options[1].StringValue()) @@ -551,17 +551,17 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s // expmin = mins //} // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct - requestoremail, ok := d.app.storage.GetEmailsKey(requestor.JellyfinID) + requesterEmail, ok := d.app.storage.GetEmailsKey(requester.JellyfinID) if !ok { d.app.err.Printf("Failed to verify admin") } - if !requestoremail.Admin { + if !requesterEmail.Admin { d.app.err.Printf("User is not admin") } // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options //d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) currentTime := time.Now() - validTill := currentTime.Add(time.Minute*time.Duration(expmin)) + validTill := currentTime.Add(time.Minute * time.Duration(expmin)) // make sure code doesn't begin with number inviteCode := shortuuid.New() _, err = strconv.Atoi(string(inviteCode[0])) @@ -583,24 +583,43 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s invite.UserMinutes = req.UserMinutes }*/ invite.ValidTill = validTill - if invuser != "" && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { - discord := "" + if recipient != nil && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { d.app.debug.Printf("%s: Sending invite message", inviteCode) - invname, err := d.bot.GuildMember(d.guildID, invuser) + invname, err := d.bot.GuildMember(d.guildID, recipient.ID) invite.SendTo = invname.User.Username msg, err := d.app.email.constructInvite(inviteCode, invite, d.app, false) if err != nil { - invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) + invite.SendTo = fmt.Sprintf("Failed to send to %s", RenderDiscordUsername(recipient)) d.app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) } else { var err error - err = d.app.discord.SendDM(msg, discord) + err = d.app.discord.SendDM(msg, recipient.ID) if err != nil { - invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) + invite.SendTo = fmt.Sprintf("Failed to send to %s", RenderDiscordUsername(recipient)) d.app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) + err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{ + Type: dg.InteractionResponseChannelMessageWithSource, + Data: &dg.InteractionResponseData{ + Content: d.app.storage.lang.Telegram[lang].Strings.get("sentInviteFailure"), + Flags: 64, // Ephemeral + }, + }) + if err != nil { + d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", RenderDiscordUsername(requester), err) + } } else { - d.app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, invuser) + d.app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, RenderDiscordUsername(recipient)) + err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{ + Type: dg.InteractionResponseChannelMessageWithSource, + Data: &dg.InteractionResponseData{ + Content: d.app.storage.lang.Telegram[lang].Strings.get("sentInvite"), + Flags: 64, // Ephemeral + }, + }) + if err != nil { + d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", RenderDiscordUsername(requester), err) + } } } } @@ -613,7 +632,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s //} d.app.storage.SetInvitesKey(inviteCode, invite) } - + func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) { if m.GuildID != "" && d.channelName != "" { if d.channelID == "" { diff --git a/lang/telegram/en-us.json b/lang/telegram/en-us.json index c5144e3..4cb03a7 100644 --- a/lang/telegram/en-us.json +++ b/lang/telegram/en-us.json @@ -11,6 +11,8 @@ "languageMessage": "Note: See available languages with {command}, and set language with {command} .", "languageMessageDiscord": "Note: set your language with /lang .", "languageSet": "Language set to {language}.", - "discordDMs": "Please check your DMs for a response." + "discordDMs": "Please check your DMs for a response.", + "sentInvite": "Sent invite.", + "sentInviteFailure": "Failed to send invite, check logs." } -} \ No newline at end of file +} From 10a32ad1ae0e9796b9fb4b93fcd2533e8925c249 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Tue, 10 Oct 2023 14:52:54 +0100 Subject: [PATCH 11/17] discord: re-add optional args --- discord.go | 79 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/discord.go b/discord.go index f53b1d7..3c187ec 100644 --- a/discord.go +++ b/discord.go @@ -351,17 +351,24 @@ func (d *DiscordDaemon) registerCommands() { Name: "user", Description: "User to Invite", Required: true, - }, // running with just one option for now to mesh with what we've got, also may have the syntax wrong here - /*{ + }, + { Type: dg.ApplicationCommandOptionInteger, - Name: "expire after", + Name: "expiry", Description: "Time in minutes before expiration", Required: false, }, + /* Label should be automatically set to something like "Discord invite for @username" { Type: dg.ApplicationCommandOptionString, Name: "label", - Description: "Label to apply to the user created with this invite", + Description: "Label given to this invite (shown on the Admin page)", + Required: false, + }, */ + { + Type: dg.ApplicationCommandOptionString, + Name: "user_label", + Description: "Label given to users created with this invite", Required: false, }, { @@ -369,7 +376,7 @@ func (d *DiscordDaemon) registerCommands() { Name: "profile", Description: "Profile to apply to the user created with this invite", Required: false, - }, */ + }, }, }, } @@ -546,7 +553,6 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s //label := i.ApplicationCommandData().Options[2].StringValue() //profile := i.ApplicationCommandData().Options[3].StringValue() //mins, err := strconv.Atoi(i.ApplicationCommandData().Options[1].StringValue()) - expmin := 30 //if mins > 0 { // expmin = mins //} @@ -558,10 +564,28 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s if !requesterEmail.Admin { d.app.err.Printf("User is not admin") } - // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options - //d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) + + var expiryMinutes int64 = 30 + userLabel := "" + profileName := "" + + for i, opt := range i.ApplicationCommandData().Options { + if i == 0 { + continue + } + switch opt.Name { + case "expiry": + expiryMinutes = opt.IntValue() + case "user_label": + userLabel = opt.StringValue() + case "profile": + profileName = opt.StringValue() + } + } + currentTime := time.Now() - validTill := currentTime.Add(time.Minute * time.Duration(expmin)) + + validTill := currentTime.Add(time.Minute * time.Duration(expiryMinutes)) // make sure code doesn't begin with number inviteCode := shortuuid.New() _, err = strconv.Atoi(string(inviteCode[0])) @@ -569,20 +593,23 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s inviteCode = shortuuid.New() _, err = strconv.Atoi(string(inviteCode[0])) } - var invite Invite - //if label != "" { - // invite.Label = label - //} - invite.Created = currentTime - invite.RemainingUses = 1 - invite.UserExpiry = false - /*if invite.UserExpiry { - invite.UserMonths = req.UserMonths - invite.UserDays = req.UserDays - invite.UserHours = req.UserHours - invite.UserMinutes = req.UserMinutes - }*/ - invite.ValidTill = validTill + + invite := Invite{ + Code: inviteCode, + Created: currentTime, + RemainingUses: 1, + UserExpiry: false, + ValidTill: validTill, + UserLabel: userLabel, + Profile: "Default", + Label: fmt.Sprintf("Discord Invite for %s", RenderDiscordUsername(recipient)), + } + if profileName != "" { + if _, ok := d.app.storage.GetProfileKey(profileName); ok { + invite.Profile = profileName + } + } + if recipient != nil && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { d.app.debug.Printf("%s: Sending invite message", inviteCode) invname, err := d.bot.GuildMember(d.guildID, recipient.ID) @@ -624,12 +651,6 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s } } //if profile != "" { - // if _, ok := d.app.storage.GetProfileKey(profile); ok { - // invite.Profile = profile - // } else { - // invite.Profile = "Default" - // } - //} d.app.storage.SetInvitesKey(inviteCode, invite) } From 62923d5e45f9bd8a03f9326832618b3e3abab005 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Tue, 10 Oct 2023 15:15:25 +0100 Subject: [PATCH 12/17] discord: register available profiles for /inv profiles are registered as options for /inv as startup. Note in description added to restart jfa-go to reload them. --- discord.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/discord.go b/discord.go index 3c187ec..72c93c2 100644 --- a/discord.go +++ b/discord.go @@ -349,13 +349,13 @@ func (d *DiscordDaemon) registerCommands() { { Type: dg.ApplicationCommandOptionUser, Name: "user", - Description: "User to Invite", + Description: "User to Invite.", Required: true, }, { Type: dg.ApplicationCommandOptionInteger, Name: "expiry", - Description: "Time in minutes before expiration", + Description: "Time in minutes before expiration.", Required: false, }, /* Label should be automatically set to something like "Discord invite for @username" @@ -368,13 +368,13 @@ func (d *DiscordDaemon) registerCommands() { { Type: dg.ApplicationCommandOptionString, Name: "user_label", - Description: "Label given to users created with this invite", + Description: "Label given to users created with this invite.", Required: false, }, { Type: dg.ApplicationCommandOptionString, Name: "profile", - Description: "Profile to apply to the user created with this invite", + Description: "Profile to apply. Restart jfa-go if there's any missing.", Required: false, }, }, @@ -383,7 +383,7 @@ func (d *DiscordDaemon) registerCommands() { commands[1].Options[0].Choices = make([]*dg.ApplicationCommandOptionChoice, len(d.app.storage.lang.Telegram)) i := 0 for code := range d.app.storage.lang.Telegram { - d.app.debug.Printf("Registering choice \"%s\":\"%s\"\n", d.app.storage.lang.Telegram[code].Meta.Name, code) + d.app.debug.Printf("Discord: registering lang choice \"%s\":\"%s\"\n", d.app.storage.lang.Telegram[code].Meta.Name, code) commands[1].Options[0].Choices[i] = &dg.ApplicationCommandOptionChoice{ Name: d.app.storage.lang.Telegram[code].Meta.Name, Value: code, @@ -391,6 +391,17 @@ func (d *DiscordDaemon) registerCommands() { i++ } + // FIXME: Maybe make this reload when profiles change + profiles := d.app.storage.GetProfiles() + commands[3].Options[3].Choices = make([]*dg.ApplicationCommandOptionChoice, len(profiles)) + for i, profile := range profiles { + d.app.debug.Printf("Discord: registering profile choice \"%s\"", profile.Name) + commands[3].Options[3].Choices[i] = &dg.ApplicationCommandOptionChoice{ + Name: profile.Name, + Value: profile.Name, + } + } + // d.deregisterCommands() d.commandIDs = make([]string, len(commands)) @@ -416,7 +427,7 @@ func (d *DiscordDaemon) deregisterCommands() { return } for _, cmd := range existingCommands { - if err := d.bot.ApplicationCommandDelete(d.bot.State.User.ID, "", cmd.ID); err != nil { + if err := d.bot.ApplicationCommandDelete(d.bot.State.User.ID, d.guildID, cmd.ID); err != nil { d.app.err.Printf("Failed to deregister command: %v", err) } } @@ -602,7 +613,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s ValidTill: validTill, UserLabel: userLabel, Profile: "Default", - Label: fmt.Sprintf("Discord Invite for %s", RenderDiscordUsername(recipient)), + Label: fmt.Sprintf("Discord: %s", RenderDiscordUsername(recipient)), } if profileName != "" { if _, ok := d.app.storage.GetProfileKey(profileName); ok { From 0366e5116d79df4d59985df8ae8c106d0fbfc365 Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Tue, 10 Oct 2023 11:14:57 -0400 Subject: [PATCH 13/17] Update discord.go Cleaning up a bit --- discord.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/discord.go b/discord.go index fc7a74f..cf1eb1b 100644 --- a/discord.go +++ b/discord.go @@ -550,15 +550,17 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s //if mins > 0 { // expmin = mins //} - // Need to check whether requestor is linked to the admin account *possibly add Admin bool to DiscordUser struct + // Check whether requestor is linked to the admin account requestoremail, ok := d.app.storage.GetEmailsKey(requestor.JellyfinID) if !ok { d.app.err.Printf("Failed to verify admin") } if !requestoremail.Admin { d.app.err.Printf("User is not admin") + //add response message + return } - // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other options + // variation of app.GenerateInvite, some parts commented to potentially add back in later with the other command options //d.app.debug.Println("Generating new invite with options: %s: %i: %s: %s", invuser, expmin, profile, label) currentTime := time.Now() validTill := currentTime.Add(time.Minute*time.Duration(expmin)) @@ -593,14 +595,17 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) d.app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) + //add response message } else { var err error err = d.app.discord.SendDM(msg, discord) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) d.app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) + //add response message } else { d.app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, invuser) + //add response message } } } From 525c13ff6ab9fe503932a3927a1d9994a4ea20a4 Mon Sep 17 00:00:00 2001 From: Violet Scheen Date: Tue, 10 Oct 2023 12:55:56 -0400 Subject: [PATCH 14/17] Update discord.go --- discord.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/discord.go b/discord.go index cf1eb1b..fd3de07 100644 --- a/discord.go +++ b/discord.go @@ -586,11 +586,9 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s }*/ invite.ValidTill = validTill if invuser != "" && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { - discord := "" d.app.debug.Printf("%s: Sending invite message", inviteCode) invname, err := d.bot.GuildMember(d.guildID, invuser) invite.SendTo = invname.User.Username - msg, err := d.app.email.constructInvite(inviteCode, invite, d.app, false) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) @@ -598,7 +596,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s //add response message } else { var err error - err = d.app.discord.SendDM(msg, discord) + err = d.app.discord.SendDM(msg, invuser) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", invuser) d.app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) From 7813c8c68b39182085436758abfe462dcdfba0aa Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Wed, 11 Oct 2023 11:35:08 +0100 Subject: [PATCH 15/17] discord: Use GenerateInviteCode in /inv --- discord.go | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/discord.go b/discord.go index fcfb27f..f402d3b 100644 --- a/discord.go +++ b/discord.go @@ -2,12 +2,10 @@ package main import ( "fmt" - "strconv" "strings" "time" dg "github.com/bwmarrin/discordgo" - "github.com/lithammer/shortuuid/v3" "github.com/timshannon/badgerhold/v4" ) @@ -599,16 +597,9 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s currentTime := time.Now() validTill := currentTime.Add(time.Minute * time.Duration(expiryMinutes)) - // make sure code doesn't begin with number - inviteCode := shortuuid.New() - _, err = strconv.Atoi(string(inviteCode[0])) - for err == nil { - inviteCode = shortuuid.New() - _, err = strconv.Atoi(string(inviteCode[0])) - } invite := Invite{ - Code: inviteCode, + Code: GenerateInviteCode(), Created: currentTime, RemainingUses: 1, UserExpiry: false, @@ -624,20 +615,20 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s } if recipient != nil && d.app.config.Section("invite_emails").Key("enabled").MustBool(false) { - d.app.debug.Printf("%s: Sending invite message", inviteCode) + d.app.debug.Printf("%s: Sending invite message", invite.Code) invname, err := d.bot.GuildMember(d.guildID, recipient.ID) invite.SendTo = invname.User.Username - msg, err := d.app.email.constructInvite(inviteCode, invite, d.app, false) + msg, err := d.app.email.constructInvite(invite.Code, invite, d.app, false) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", RenderDiscordUsername(recipient)) - d.app.err.Printf("%s: Failed to construct invite message: %v", inviteCode, err) + d.app.err.Printf("%s: Failed to construct invite message: %v", invite.Code, err) //add response message } else { var err error err = d.app.discord.SendDM(msg, recipient.ID) if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", RenderDiscordUsername(recipient)) - d.app.err.Printf("%s: %s: %v", inviteCode, invite.SendTo, err) + d.app.err.Printf("%s: %s: %v", invite.Code, invite.SendTo, err) err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{ Type: dg.InteractionResponseChannelMessageWithSource, Data: &dg.InteractionResponseData{ @@ -649,7 +640,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", RenderDiscordUsername(requester), err) } } else { - d.app.info.Printf("%s: Sent invite email to \"%s\"", inviteCode, RenderDiscordUsername(recipient)) + d.app.info.Printf("%s: Sent invite email to \"%s\"", invite.Code, RenderDiscordUsername(recipient)) err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{ Type: dg.InteractionResponseChannelMessageWithSource, Data: &dg.InteractionResponseData{ From 2fb2f3ee74460e2d94274f4cfdb2279e11270a0d Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Wed, 11 Oct 2023 11:38:55 +0100 Subject: [PATCH 16/17] discord: send error message when inv construction fails --- discord.go | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/discord.go b/discord.go index f402d3b..1d9caf2 100644 --- a/discord.go +++ b/discord.go @@ -555,6 +555,10 @@ func (d *DiscordDaemon) cmdLang(s *dg.Session, i *dg.InteractionCreate, lang str func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang string) { channel, err := s.UserChannelCreate(i.Interaction.Member.User.ID) + if err != nil { + d.app.err.Printf("Discord: Failed to create private channel with \"%s\": %v", i.Interaction.Member.User.Username, err) + return + } requester := d.MustGetUser(channel.ID, i.Interaction.Member.User.ID, i.Interaction.Member.User.Discriminator, i.Interaction.Member.User.Username) d.users[i.Interaction.Member.User.ID] = requester recipient := i.ApplicationCommandData().Options[0].UserValue(s) @@ -622,7 +626,16 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s if err != nil { invite.SendTo = fmt.Sprintf("Failed to send to %s", RenderDiscordUsername(recipient)) d.app.err.Printf("%s: Failed to construct invite message: %v", invite.Code, err) - //add response message + err := s.InteractionRespond(i.Interaction, &dg.InteractionResponse{ + Type: dg.InteractionResponseChannelMessageWithSource, + Data: &dg.InteractionResponseData{ + Content: d.app.storage.lang.Telegram[lang].Strings.get("sentInviteFailure"), + Flags: 64, // Ephemeral + }, + }) + if err != nil { + d.app.err.Printf("Discord: Failed to send message to \"%s\": %v", RenderDiscordUsername(requester), err) + } } else { var err error err = d.app.discord.SendDM(msg, recipient.ID) @@ -655,7 +668,7 @@ func (d *DiscordDaemon) cmdInvite(s *dg.Session, i *dg.InteractionCreate, lang s } } //if profile != "" { - d.app.storage.SetInvitesKey(inviteCode, invite) + d.app.storage.SetInvitesKey(invite.Code, invite) } func (d *DiscordDaemon) messageHandler(s *dg.Session, m *dg.MessageCreate) { From 2f3d5e4e3a20af5da0bd91a736e99191352e2928 Mon Sep 17 00:00:00 2001 From: Harvey Tindall Date: Wed, 11 Oct 2023 12:00:38 +0100 Subject: [PATCH 17/17] discord: update profile list when changes occur --- api-profiles.go | 4 ++++ discord.go | 41 ++++++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/api-profiles.go b/api-profiles.go index ce58cbb..b1594b2 100644 --- a/api-profiles.go +++ b/api-profiles.go @@ -104,6 +104,10 @@ func (app *appContext) CreateProfile(gc *gin.Context) { } } app.storage.SetProfileKey(req.Name, profile) + // Refresh discord bots, profile list + if discordEnabled { + app.discord.UpdateCommands() + } respondBool(200, true, gc) } diff --git a/discord.go b/discord.go index 1d9caf2..e11d9f0 100644 --- a/discord.go +++ b/discord.go @@ -24,6 +24,7 @@ type DiscordDaemon struct { app *appContext commandHandlers map[string]func(s *dg.Session, i *dg.InteractionCreate, lang string) commandIDs []string + commandDescriptions []*dg.ApplicationCommand } func newDiscordDaemon(app *appContext) (*DiscordDaemon, error) { @@ -222,7 +223,6 @@ func (d *DiscordDaemon) NewTempInvite(ageSeconds, maxUses int) (inviteURL, iconU d.app.err.Printf("Discord: Failed to get guild: %v", err) return } - // FIXME: Fix CSS, and handle no icon iconURL = guild.IconURL("256") return } @@ -310,7 +310,7 @@ func (d *DiscordDaemon) Shutdown() { } func (d *DiscordDaemon) registerCommands() { - commands := []*dg.ApplicationCommand{ + d.commandDescriptions = []*dg.ApplicationCommand{ { Name: d.app.config.Section("discord").Key("start_command").MustString("start"), Description: "Start the Discord linking process. The bot will send further instructions.", @@ -372,29 +372,28 @@ func (d *DiscordDaemon) registerCommands() { { Type: dg.ApplicationCommandOptionString, Name: "profile", - Description: "Profile to apply. Restart jfa-go if there's any missing.", + Description: "Profile to apply to the created user.", Required: false, }, }, }, } - commands[1].Options[0].Choices = make([]*dg.ApplicationCommandOptionChoice, len(d.app.storage.lang.Telegram)) + d.commandDescriptions[1].Options[0].Choices = make([]*dg.ApplicationCommandOptionChoice, len(d.app.storage.lang.Telegram)) i := 0 for code := range d.app.storage.lang.Telegram { d.app.debug.Printf("Discord: registering lang choice \"%s\":\"%s\"\n", d.app.storage.lang.Telegram[code].Meta.Name, code) - commands[1].Options[0].Choices[i] = &dg.ApplicationCommandOptionChoice{ + d.commandDescriptions[1].Options[0].Choices[i] = &dg.ApplicationCommandOptionChoice{ Name: d.app.storage.lang.Telegram[code].Meta.Name, Value: code, } i++ } - // FIXME: Maybe make this reload when profiles change profiles := d.app.storage.GetProfiles() - commands[3].Options[3].Choices = make([]*dg.ApplicationCommandOptionChoice, len(profiles)) + d.commandDescriptions[3].Options[3].Choices = make([]*dg.ApplicationCommandOptionChoice, len(profiles)) for i, profile := range profiles { d.app.debug.Printf("Discord: registering profile choice \"%s\"", profile.Name) - commands[3].Options[3].Choices[i] = &dg.ApplicationCommandOptionChoice{ + d.commandDescriptions[3].Options[3].Choices[i] = &dg.ApplicationCommandOptionChoice{ Name: profile.Name, Value: profile.Name, } @@ -402,12 +401,12 @@ func (d *DiscordDaemon) registerCommands() { // d.deregisterCommands() - d.commandIDs = make([]string, len(commands)) + d.commandIDs = make([]string, len(d.commandDescriptions)) // cCommands, err := d.bot.ApplicationCommandBulkOverwrite(d.bot.State.User.ID, d.guildID, commands) // if err != nil { // d.app.err.Printf("Discord: Cannot create commands: %v", err) // } - for i, cmd := range commands { + for i, cmd := range d.commandDescriptions { command, err := d.bot.ApplicationCommandCreate(d.bot.State.User.ID, d.guildID, cmd) if err != nil { d.app.err.Printf("Discord: Cannot create command \"%s\": %v", cmd.Name, err) @@ -426,11 +425,31 @@ func (d *DiscordDaemon) deregisterCommands() { } for _, cmd := range existingCommands { if err := d.bot.ApplicationCommandDelete(d.bot.State.User.ID, d.guildID, cmd.ID); err != nil { - d.app.err.Printf("Failed to deregister command: %v", err) + d.app.err.Printf("Discord: Failed to deregister command: %v", err) } } } +// UpdateCommands updates commands which have defined lists of options, to be used when changes occur. +func (d *DiscordDaemon) UpdateCommands() { + // Reload Profile List + profiles := d.app.storage.GetProfiles() + d.commandDescriptions[3].Options[3].Choices = make([]*dg.ApplicationCommandOptionChoice, len(profiles)) + for i, profile := range profiles { + d.app.debug.Printf("Discord: registering profile choice \"%s\"", profile.Name) + d.commandDescriptions[3].Options[3].Choices[i] = &dg.ApplicationCommandOptionChoice{ + Name: profile.Name, + Value: profile.Name, + } + } + cmd, err := d.bot.ApplicationCommandEdit(d.bot.State.User.ID, d.guildID, d.commandIDs[3], d.commandDescriptions[3]) + if err != nil { + d.app.err.Printf("Discord: Failed to update profile list: %v\n", err) + } else { + d.commandIDs[3] = cmd.ID + } +} + func (d *DiscordDaemon) commandHandler(s *dg.Session, i *dg.InteractionCreate) { if h, ok := d.commandHandlers[i.ApplicationCommandData().Name]; ok { if i.GuildID != "" && d.channelName != "" {