diff --git a/DiscordBot/CommandHandlers/ButtonHandler.cs b/DiscordBot/CommandHandlers/ButtonHandler.cs index f6776b3..f063155 100644 --- a/DiscordBot/CommandHandlers/ButtonHandler.cs +++ b/DiscordBot/CommandHandlers/ButtonHandler.cs @@ -34,7 +34,7 @@ namespace DiscordBot.CommandHandlers if(await _handlerFunctions.IsRaidSignUpAllowed(component, parsedRaidId, ids[0])) { roles = await _httpService.GetRoles(parsedRaidId, component.User.Id); - await component.RespondAsync("Please choose a role.", components: SignUpMessage.buildMessage(roles, parsedRaidId, ids[0], false) , ephemeral: true); + await component.RespondAsync("Please choose a role.", components: RoleSelectionMessage.buildMessage(roles, parsedRaidId, ids[0], false) , ephemeral: true); } break; case Constants.ComponentIds.MAYBE_BUTTON: @@ -43,7 +43,7 @@ namespace DiscordBot.CommandHandlers if(await _handlerFunctions.IsRaidSignUpAllowed(component, parsedRaidId, ids[0])) { roles = await _httpService.GetRoles(parsedRaidId, component.User.Id); - await component.RespondAsync("Please choose a role.", components: SignUpMessage.buildMessage(roles, parsedRaidId, ids[0], true) , ephemeral: true); + await component.RespondAsync("Please choose a role.", components: RoleSelectionMessage.buildMessage(roles, parsedRaidId, ids[0], true) , ephemeral: true); } break; case Constants.ComponentIds.SIGN_OFF_BUTTON: diff --git a/DiscordBot/CommandHandlers/HandlerFunctions.cs b/DiscordBot/CommandHandlers/HandlerFunctions.cs index b28d9f1..419dd10 100644 --- a/DiscordBot/CommandHandlers/HandlerFunctions.cs +++ b/DiscordBot/CommandHandlers/HandlerFunctions.cs @@ -22,13 +22,7 @@ namespace DiscordBot.CommandHandlers { if(! await _httpService.DoesUserExist(component.User.Id)) { - var mb = new ModalBuilder() - .WithTitle("Create Account") - .WithCustomId($"{Constants.ComponentIds.CREATE_ACCOUNT_MODAL}-{raidId}-{pressedButtonId}") - .AddTextInput("Name", Constants.ComponentIds.NAME_TEXT_BOX, placeholder: component.User.Username, required: true, value: component.User.Username) - .AddTextInput("Guild Wars 2 Account", Constants.ComponentIds.ACCOUNT_TEXT_BOX, placeholder: "Account.1234", required: true); - - await component.RespondWithModalAsync(mb.Build()); + await component.RespondWithModalAsync(CreateAccountModal.buildMessage(raidId, pressedButtonId, component.User.Username)); return false; } Tuple signUpAllowed = await _httpService.IsSignUpAllowed(raidId, component.User.Id); diff --git a/DiscordBot/CommandHandlers/ModalHandler.cs b/DiscordBot/CommandHandlers/ModalHandler.cs index fc43f05..79a5e30 100644 --- a/DiscordBot/CommandHandlers/ModalHandler.cs +++ b/DiscordBot/CommandHandlers/ModalHandler.cs @@ -41,24 +41,26 @@ namespace DiscordBot.CommandHandlers } //sign up - if(ids.Length > 2 && int.TryParse(ids[1], out int parsedRaidId) && await _handlerFunctions.IsRaidSignUpAllowed(modal, parsedRaidId, ids[2])) + CreateAccountModal.Parameters createAccountParameters = CreateAccountModal.ParseId(modal.Data.CustomId); + if(await _handlerFunctions.IsRaidSignUpAllowed(modal, createAccountParameters.RaidId, createAccountParameters.ButtonId)) { - List roles = await _httpService.GetRoles(parsedRaidId, modal.User.Id); - await modal.RespondAsync("Please choose a role.", components: SignUpMessage.buildMessage(roles, parsedRaidId, ids[2], false) , ephemeral: true); + List roles = await _httpService.GetRoles(createAccountParameters.RaidId, modal.User.Id); + await modal.RespondAsync("Please choose a role.", + components: RoleSelectionMessage.buildMessage(roles, createAccountParameters.RaidId, createAccountParameters.ButtonId, false), + ephemeral: true); return; } await _handlerFunctions.Respond(modal); break; case Constants.ComponentIds.SIGN_UP_EXTERNAL_MODAL: string userName = components.First(x => x.CustomId == Constants.ComponentIds.NAME_TEXT_BOX).Value; - int raidId = int.Parse(ids[1]); - int roleId = int.Parse(ids[2]); + ExternalUserNameModal.Parameters modalParameters = ExternalUserNameModal.ParseId(modal.Data.CustomId); ApiSignUp signUpExternal = new ApiSignUp() { - raidId = raidId, + raidId = modalParameters.RaidId, userName = userName, signedUpByUserId = modal.User.Id, - roleId = roleId + roleId = modalParameters.RoleId }; await _httpService.SignUp(signUpExternal); await modal.RespondAsync($"signed up {userName}", ephemeral: true); diff --git a/DiscordBot/CommandHandlers/SelectMenuHandler.cs b/DiscordBot/CommandHandlers/SelectMenuHandler.cs index 1e01965..caffe81 100644 --- a/DiscordBot/CommandHandlers/SelectMenuHandler.cs +++ b/DiscordBot/CommandHandlers/SelectMenuHandler.cs @@ -22,49 +22,63 @@ namespace DiscordBot.CommandHandlers public async Task Handler(SocketMessageComponent component) { string[] ids = component.Data.CustomId.Split('-'); - List roles = new List(); - int parsedRaidId = 0; - if(ids.Length > 1) - { - int.TryParse(ids[1],out parsedRaidId); - } - switch(ids[0]) { case Constants.ComponentIds.SIGN_UP_DROP_DOWN: - ulong userId = 0; - if(ids.Length >= 4) + RoleSelectionMessage.Parameters roleParameters = RoleSelectionMessage.ParseId(component.Data.CustomId); + ulong userIdToSignUp = component.User.Id;; + ulong signedUpByUserId = 0; + if(roleParameters.UserIdToSignUp != 0) { - ulong.TryParse(ids[3],out userId); + userIdToSignUp = roleParameters.UserIdToSignUp; + signedUpByUserId = component.User.Id; } - await ManageSignUp(ids[2], parsedRaidId, component, userId); - await component.RespondAsync("successfully signed up", ephemeral: true); + await ManageSignUp(roleParameters.ButtonType, roleParameters.RaidId, component, userIdToSignUp, signedUpByUserId); break; case Constants.ComponentIds.SIGN_UP_EXTERNAL_DROP_DOWN: - await component.RespondWithModalAsync(CreateUserNameModal(parsedRaidId, int.Parse(component.Data.Values.First()))); + ExternalRoleSelectionMessage.Parameters externalRoleParameters = ExternalRoleSelectionMessage.ParseId(component.Data.CustomId); + await component.RespondWithModalAsync(ExternalUserNameModal.buildMessage(externalRoleParameters.RaidId, int.Parse(component.Data.Values.First()))); + break; + case Constants.ComponentIds.ACCOUNT_SELECT_DROP_DOWN: + AccountSelectionMessage.Parameters accountParameters = AccountSelectionMessage.ParseId(component.Data.CustomId); + int accountId = int.Parse(component.Data.Values.First()); + await SignUp(accountParameters.ButtonType, accountParameters.RaidId, accountParameters.RoleId, accountParameters.UserIdToSignUp, accountId, accountParameters.SignedUpByUserId); + await component.RespondAsync("successfully signed up", ephemeral: true); break; } } - private async Task ManageSignUp(string buttonType, int raidId, SocketMessageComponent component, ulong userIdToSignUp) + private async Task ManageSignUp(string buttonType, int raidId, SocketMessageComponent component, ulong userIdToSignUp, ulong signedUpByUserId = 0) { if(! int.TryParse(component.Data.Values.First(), out int parsedRoleId)) return; - ApiSignUp signUp = new ApiSignUp() + List accounts = await _httpService.GetSignUpAccounts(userIdToSignUp, raidId); + if(accounts.Count == 1) { - raidId = raidId, - roleId = parsedRoleId - }; - - if(userIdToSignUp == 0) + ApiGuildWars2Account account = accounts.First(); + await SignUp(buttonType, raidId, parsedRoleId, userIdToSignUp, account.GuildWars2AccountId, signedUpByUserId); + await component.RespondAsync("successfully signed up", ephemeral: true); + } + else if(accounts.Count > 1) { - signUp.userId = component.User.Id; + await component.RespondAsync("Please choose an account.", components: AccountSelectionMessage.buildMessage(accounts, raidId, buttonType, parsedRoleId, userIdToSignUp, signedUpByUserId) , ephemeral: true); } else { - signUp.userId = userIdToSignUp; - signUp.signedUpByUserId = component.User.Id; + await component.RespondAsync("no suitable Guild Wars 2 account found.", ephemeral: true); } + } + + private async Task SignUp(string buttonType, int raidId, int roleId, ulong userIdToSignUp, int gw2AccountId, ulong signedUpByUserId = 0) + { + ApiSignUp signUp = new ApiSignUp() + { + raidId = raidId, + roleId = roleId, + gw2AccountId = gw2AccountId, + userId = userIdToSignUp, + signedUpByUserId = signedUpByUserId + }; switch(buttonType) { @@ -82,15 +96,5 @@ namespace DiscordBot.CommandHandlers break; } } - - private Modal CreateUserNameModal(int raidId, int roleId) - { - var mb = new ModalBuilder() - .WithTitle("Create Account") - .WithCustomId($"{Constants.ComponentIds.SIGN_UP_EXTERNAL_MODAL}-{raidId}-{roleId}") - .AddTextInput("Name", Constants.ComponentIds.NAME_TEXT_BOX, placeholder: "Name", required: true); - - return mb.Build(); - } } } \ No newline at end of file diff --git a/DiscordBot/CommandHandlers/SlashCommandHandler.cs b/DiscordBot/CommandHandlers/SlashCommandHandler.cs index a948178..1e46578 100644 --- a/DiscordBot/CommandHandlers/SlashCommandHandler.cs +++ b/DiscordBot/CommandHandlers/SlashCommandHandler.cs @@ -26,11 +26,19 @@ namespace DiscordBot.CommandHandlers public async Task Handler(SocketSlashCommand command) { - switch (command.Data.Name) + Tuple commandExecutionAllowed = await _httpService.IsSlashCommandAllowed(command.User.Id, command.Data.Name); + if(commandExecutionAllowed.Item1) { - case Constants.SlashCommands.RAID: - await HandleRaidCommands(command); - break; + switch (command.Data.Name) + { + case Constants.SlashCommands.RAID: + await HandleRaidCommands(command); + break; + } + } + else + { + await command.RespondAsync(commandExecutionAllowed.Item2, ephemeral:true); } } @@ -103,7 +111,7 @@ namespace DiscordBot.CommandHandlers await command.RespondAsync(signUpAllowed.Item2, ephemeral: true); return; } - await command.RespondAsync("Please choose a role.", components: SignUpMessage.buildMessage(roles, raidId, Constants.ComponentIds.SIGN_UP_BUTTON, false, user.Id) , ephemeral: true); + await command.RespondAsync("Please choose a role.", components: RoleSelectionMessage.buildMessage(roles, raidId, Constants.ComponentIds.SIGN_UP_BUTTON, false, user.Id) , ephemeral: true); } else { @@ -129,23 +137,7 @@ namespace DiscordBot.CommandHandlers await command.RespondAsync(signUpAllowed.Item2, ephemeral: true); return; } - - var signUpSelect = new SelectMenuBuilder() - .WithPlaceholder("Select an option") - .WithCustomId($"{Constants.ComponentIds.SIGN_UP_EXTERNAL_DROP_DOWN}-{raidId}") - .WithMinValues(1) - .WithMaxValues(1); - - foreach(ApiRole role in roles) - { - if(role.IsSignUpAllowed) - signUpSelect.AddOption(role.Name, role.roleId.ToString(), role.Description); - } - - var builder = new ComponentBuilder() - .WithSelectMenu(signUpSelect, 0); - - await command.RespondAsync("Please choose a role.", components: builder.Build() , ephemeral: true); + await command.RespondAsync("Please choose a role.", components: ExternalRoleSelectionMessage.buildMessage(roles, raidId) , ephemeral: true); } private async Task SendMessages(string message, int raidId) diff --git a/DiscordBot/Constants.cs b/DiscordBot/Constants.cs index beff081..040745c 100644 --- a/DiscordBot/Constants.cs +++ b/DiscordBot/Constants.cs @@ -13,6 +13,7 @@ public const string SIGN_UP_DROP_DOWN = "signUpDropDown"; public const string SIGN_UP_EXTERNAL_DROP_DOWN = "signUpExternalDropDown"; + public const string ACCOUNT_SELECT_DROP_DOWN = "accountSelectDropDown"; public const string NAME_TEXT_BOX = "nameTextbox"; public const string ACCOUNT_TEXT_BOX = "accountTextBox"; diff --git a/DiscordBot/Messages/AccountSelectionMessage.cs b/DiscordBot/Messages/AccountSelectionMessage.cs new file mode 100644 index 0000000..1a7583b --- /dev/null +++ b/DiscordBot/Messages/AccountSelectionMessage.cs @@ -0,0 +1,64 @@ +using Discord; +using SharedClasses.SharedModels; + +namespace DiscordBot.Messages +{ + public class AccountSelectionMessage + { + public static MessageComponent buildMessage(List accounts, int raidId, string buttonType, int roleId, ulong userIdToSignUp, ulong signedUpByUserId) + { + var signUpSelect = new SelectMenuBuilder() + .WithPlaceholder("Select an account") + .WithCustomId($"{Constants.ComponentIds.ACCOUNT_SELECT_DROP_DOWN}-{raidId}-{buttonType}-{roleId}-{userIdToSignUp}-{signedUpByUserId}") + .WithMinValues(1) + .WithMaxValues(1); + + foreach(ApiGuildWars2Account account in accounts) + { + signUpSelect.AddOption(account.AccountName, account.GuildWars2AccountId.ToString()); + } + + var builder = new ComponentBuilder() + .WithSelectMenu(signUpSelect, 0); + + return builder.Build(); + } + + public static Parameters ParseId(string customId) + { + Parameters parameters = new Parameters(); + + string[] ids = customId.Split('-'); + if(ids.Length > 1) + { + int.TryParse(ids[1],out parameters.RaidId); + } + if(ids.Length > 2) + { + parameters.ButtonType = ids[2]; + } + if(ids.Length > 3) + { + int.TryParse(ids[3],out parameters.RoleId); + } + if(ids.Length > 4) + { + ulong.TryParse(ids[4],out parameters.UserIdToSignUp); + } + if(ids.Length > 5) + { + ulong.TryParse(ids[5],out parameters.SignedUpByUserId); + } + return parameters; + } + + public class Parameters + { + public int RaidId; + public string ButtonType = string.Empty; + public int RoleId; + public ulong UserIdToSignUp; + public ulong SignedUpByUserId; + } + } +} \ No newline at end of file diff --git a/DiscordBot/Messages/CreateAccountModal.cs b/DiscordBot/Messages/CreateAccountModal.cs new file mode 100644 index 0000000..7a7ab0d --- /dev/null +++ b/DiscordBot/Messages/CreateAccountModal.cs @@ -0,0 +1,40 @@ +using Discord; + +namespace DiscordBot.Messages +{ + public class CreateAccountModal + { + public static Modal buildMessage(int raidId, string pressedButtonId, string defaultUserName) + { + var mb = new ModalBuilder() + .WithTitle("Create Account") + .WithCustomId($"{Constants.ComponentIds.CREATE_ACCOUNT_MODAL}-{raidId}-{pressedButtonId}") + .AddTextInput("Name", Constants.ComponentIds.NAME_TEXT_BOX, placeholder: defaultUserName, required: true, value: defaultUserName) + .AddTextInput("Guild Wars 2 Account", Constants.ComponentIds.ACCOUNT_TEXT_BOX, placeholder: "Account.1234", required: true); + + return mb.Build(); + } + + public static Parameters ParseId(string customId) + { + Parameters parameters = new Parameters(); + + string[] ids = customId.Split('-'); + if(ids.Length > 1) + { + int.TryParse(ids[1],out parameters.RaidId); + } + if(ids.Length > 2) + { + parameters.ButtonId = ids[2]; + } + return parameters; + } + + public class Parameters + { + public int RaidId; + public string ButtonId = string.Empty; + } + } +} \ No newline at end of file diff --git a/DiscordBot/Messages/SignUpMessage.cs b/DiscordBot/Messages/ExternalRoleSelectionMessage.cs similarity index 56% rename from DiscordBot/Messages/SignUpMessage.cs rename to DiscordBot/Messages/ExternalRoleSelectionMessage.cs index ff55bb5..63f0607 100644 --- a/DiscordBot/Messages/SignUpMessage.cs +++ b/DiscordBot/Messages/ExternalRoleSelectionMessage.cs @@ -1,24 +1,21 @@ using Discord; -using Discord.WebSocket; -using System; -using System.ComponentModel.DataAnnotations; using SharedClasses.SharedModels; namespace DiscordBot.Messages { - public class SignUpMessage + public class ExternalRoleSelectionMessage { - public static MessageComponent buildMessage(List roles, int raidId, string buttonType, bool allRoles, ulong userIdToSignUp = 0) + public static MessageComponent buildMessage(List roles, int raidId) { var signUpSelect = new SelectMenuBuilder() .WithPlaceholder("Select an option") - .WithCustomId($"{Constants.ComponentIds.SIGN_UP_DROP_DOWN}-{raidId}-{buttonType}-{userIdToSignUp}") + .WithCustomId($"{Constants.ComponentIds.SIGN_UP_EXTERNAL_DROP_DOWN}-{raidId}") .WithMinValues(1) .WithMaxValues(1); foreach(ApiRole role in roles) { - if(allRoles || role.IsSignUpAllowed) + if(role.IsSignUpAllowed) signUpSelect.AddOption(role.Name, role.roleId.ToString(), role.Description); } @@ -27,5 +24,22 @@ namespace DiscordBot.Messages return builder.Build(); } + + public static Parameters ParseId(string customId) + { + Parameters parameters = new Parameters(); + + string[] ids = customId.Split('-'); + if(ids.Length > 1) + { + int.TryParse(ids[1],out parameters.RaidId); + } + return parameters; + } + + public class Parameters + { + public int RaidId; + } } } \ No newline at end of file diff --git a/DiscordBot/Messages/ExternalUserNameModal.cs b/DiscordBot/Messages/ExternalUserNameModal.cs new file mode 100644 index 0000000..b5d36a7 --- /dev/null +++ b/DiscordBot/Messages/ExternalUserNameModal.cs @@ -0,0 +1,43 @@ +using Discord; +using Discord.WebSocket; +using System; +using System.ComponentModel.DataAnnotations; +using SharedClasses.SharedModels; + +namespace DiscordBot.Messages +{ + public class ExternalUserNameModal + { + public static Modal buildMessage(int raidId, int roleId) + { + var mb = new ModalBuilder() + .WithTitle("Create Account") + .WithCustomId($"{Constants.ComponentIds.SIGN_UP_EXTERNAL_MODAL}-{raidId}-{roleId}") + .AddTextInput("Name", Constants.ComponentIds.NAME_TEXT_BOX, placeholder: "Name", required: true); + + return mb.Build(); + } + + public static Parameters ParseId(string customId) + { + Parameters parameters = new Parameters(); + + string[] ids = customId.Split('-'); + if(ids.Length > 1) + { + int.TryParse(ids[1],out parameters.RaidId); + } + if(ids.Length > 2) + { + int.TryParse(ids[2],out parameters.RoleId); + } + return parameters; + } + + public class Parameters + { + public int RaidId; + public int RoleId; + } + } +} \ No newline at end of file diff --git a/DiscordBot/Messages/RoleSelectionMessage.cs b/DiscordBot/Messages/RoleSelectionMessage.cs new file mode 100644 index 0000000..4a95d14 --- /dev/null +++ b/DiscordBot/Messages/RoleSelectionMessage.cs @@ -0,0 +1,55 @@ +using Discord; +using SharedClasses.SharedModels; + +namespace DiscordBot.Messages +{ + public class RoleSelectionMessage + { + public static MessageComponent buildMessage(List roles, int raidId, string buttonType, bool allRoles, ulong userIdToSignUp = 0) + { + var signUpSelect = new SelectMenuBuilder() + .WithPlaceholder("Select an option") + .WithCustomId($"{Constants.ComponentIds.SIGN_UP_DROP_DOWN}-{raidId}-{buttonType}-{userIdToSignUp}") + .WithMinValues(1) + .WithMaxValues(1); + + foreach(ApiRole role in roles) + { + if(allRoles || role.IsSignUpAllowed) + signUpSelect.AddOption(role.Name, role.roleId.ToString(), role.Description); + } + + var builder = new ComponentBuilder() + .WithSelectMenu(signUpSelect, 0); + + return builder.Build(); + } + + public static Parameters ParseId(string customId) + { + Parameters parameters = new Parameters(); + + string[] ids = customId.Split('-'); + if(ids.Length > 1) + { + int.TryParse(ids[1],out parameters.RaidId); + } + if(ids.Length > 2) + { + parameters.ButtonType = ids[2]; + } + if(ids.Length > 3) + { + ulong.TryParse(ids[3],out parameters.UserIdToSignUp); + } + return parameters; + } + + public class Parameters + { + public int RaidId; + public string ButtonType = string.Empty; + public ulong UserIdToSignUp; + } + } +} \ No newline at end of file diff --git a/DiscordBot/Services/HttpService.cs b/DiscordBot/Services/HttpService.cs index 01a0507..a8e5c65 100644 --- a/DiscordBot/Services/HttpService.cs +++ b/DiscordBot/Services/HttpService.cs @@ -187,5 +187,36 @@ namespace DiscordBot.Services } return new ApiRaid.Role.User(); } + + public async Task> GetSignUpAccounts(ulong userId, int raidId) + { + var httpClient = _httpClientFactory.CreateClient(Constants.HTTP_CLIENT_NAME); + + var httpResponseMessage = await httpClient.GetAsync($"DiscordBot/GetSignUpAccounts/{userId}/{raidId}"); + + if (httpResponseMessage.IsSuccessStatusCode) + { + using var contentStream = + await httpResponseMessage.Content.ReadAsStreamAsync(); + + return await JsonSerializer.DeserializeAsync>(contentStream, _serializerOptions); + } + return new List(); + } + + public async Task> IsSlashCommandAllowed(ulong userId, string command) + { + var httpClient = _httpClientFactory.CreateClient(Constants.HTTP_CLIENT_NAME); + + var httpResponseMessage = await httpClient.GetAsync($"DiscordBot/IsSlashCommandAllowed/{userId}/{command}"); + + if (!httpResponseMessage.IsSuccessStatusCode) + { + ProblemDetails problemDetails = await httpResponseMessage.Content.ReadFromJsonAsync(_serializerOptions) ?? new ProblemDetails(); + string errorMessage = string.IsNullOrEmpty(problemDetails.Detail) ? string.Empty : problemDetails.Detail; + return new Tuple(false, errorMessage); + } + return new Tuple(true, string.Empty); + } } } \ No newline at end of file