diff --git a/DiscordBot/CommandHandlers/ButtonHandler.cs b/DiscordBot/CommandHandlers/ButtonHandler.cs index c91763a..5dcfaea 100644 --- a/DiscordBot/CommandHandlers/ButtonHandler.cs +++ b/DiscordBot/CommandHandlers/ButtonHandler.cs @@ -54,6 +54,16 @@ namespace DiscordBot.CommandHandlers await _httpService.SignOff(signOff); await component.RespondAsync("Signed Off", ephemeral: true); break; + case Constants.ComponentIds.OPT_OUT_BUTTON: + if(await _httpService.ReminderOptOut(component.User.Id)) + { + await component.RespondAsync("You opted out of the raid reminders."); + } + else + { + await component.RespondAsync("Opting out failed, please try again later or change the setting on the website."); + } + break; } } } diff --git a/DiscordBot/Constants.cs b/DiscordBot/Constants.cs index 3e0237f..b15ddb9 100644 --- a/DiscordBot/Constants.cs +++ b/DiscordBot/Constants.cs @@ -10,6 +10,7 @@ public const string BACKUP_BUTTON = "backupButton"; public const string FLEX_BUTTON = "flexButton"; public const string SIGN_OFF_BUTTON = "signOffButton"; + public const string OPT_OUT_BUTTON = "optOutButton"; public const string ROLE_SELECT_DROP_DOWN = "roleSelectDropDown"; public const string ROLE_SELECT_EXTERNAL_DROP_DOWN = "roleSelectExternalDropDown"; diff --git a/DiscordBot/Controllers/RaidController.cs b/DiscordBot/Controllers/RaidController.cs index 3587afa..cb37f5d 100644 --- a/DiscordBot/Controllers/RaidController.cs +++ b/DiscordBot/Controllers/RaidController.cs @@ -95,5 +95,12 @@ namespace DiscordBot.Controllers { await DiscordBot.CommandHandlers.HandlerFunctions.RenameUser(_client, user.userId, user.Name, user.Account, user.ServerIds); } + + [HttpGet] + [Route("[action]/{userId}")] + public async Task SendReminderOptOutMessage(ulong userId) + { + await ReminderSubscriptionMessage.sendMessage(_client, userId); + } } } \ No newline at end of file diff --git a/DiscordBot/Messages/ReminderSubscriptionMessage.cs b/DiscordBot/Messages/ReminderSubscriptionMessage.cs new file mode 100644 index 0000000..e4a524e --- /dev/null +++ b/DiscordBot/Messages/ReminderSubscriptionMessage.cs @@ -0,0 +1,32 @@ +using Discord; +using Discord.WebSocket; + +namespace DiscordBot.Messages +{ + public class ReminderSubscriptionMessage + { + public static async Task sendMessage(DiscordSocketClient client, ulong userId) + { + var builder = new ComponentBuilder() + .WithButton("Opt Out", $"{Constants.ComponentIds.OPT_OUT_BUTTON}", ButtonStyle.Danger); + + string message = "Hi, I'm Raid-o-Tron. \n" + + "I will send you reminders for raids you have signed up for.\n" + + "The reminders will look like\n" + + "> Testraid: The raid starts in 30 minutes. \n" + + "You can opt out of the reminders here or change it any time at https://lieb.games \n" + + " ------------------------------------------- \n" + + "Hi, ich bin Raid-o-Tron. \n" + + "Ich werde dir Erinnerungen für Raid an denen du dich angemeldet hast schicken.\n" + + "Die Erinnerungen werden so aussehen:\n" + + "> Testraid: The raid starts in 30 minutes. \n" + + "Du kannst dich von den Erinnerungen hier abmelden oder deine Einstellungen jederzeit auf https://lieb.games ändern."; + + var user = await client.GetUserAsync(userId); + if(user != null) + { + await user.SendMessageAsync(message, components: builder.Build()); + } + } + } +} \ No newline at end of file diff --git a/DiscordBot/Services/HttpService.cs b/DiscordBot/Services/HttpService.cs index e691bbc..b5d2007 100644 --- a/DiscordBot/Services/HttpService.cs +++ b/DiscordBot/Services/HttpService.cs @@ -242,5 +242,20 @@ namespace DiscordBot.Services } return new Tuple(true, string.Empty); } + + public async Task ReminderOptOut(ulong userId) + { + var httpClient = _httpClientFactory.CreateClient(Constants.HTTP_CLIENT_NAME); + + var httpResponseMessage = await httpClient.GetAsync($"DiscordBot/ReminderOptOut/{userId}"); + if (httpResponseMessage.IsSuccessStatusCode) + { + using var contentStream = + await httpResponseMessage.Content.ReadAsStreamAsync(); + + return await JsonSerializer.DeserializeAsync(contentStream, _serializerOptions); + } + return false; + } } } \ No newline at end of file diff --git a/Lieb/Controllers/DiscordBotController.cs b/Lieb/Controllers/DiscordBotController.cs index af52036..a6c3287 100644 --- a/Lieb/Controllers/DiscordBotController.cs +++ b/Lieb/Controllers/DiscordBotController.cs @@ -250,5 +250,12 @@ namespace Lieb.Controllers } return Ok(); } + + [HttpGet] + [Route("[action]/{userId}")] + public async Task ReminderOptOut(ulong userId) + { + return Ok(await _userService.ReminderOptOut(userId)); + } } } \ No newline at end of file diff --git a/Lieb/Data/DiscordService.cs b/Lieb/Data/DiscordService.cs index b432e1e..077098e 100644 --- a/Lieb/Data/DiscordService.cs +++ b/Lieb/Data/DiscordService.cs @@ -160,16 +160,62 @@ namespace Lieb.Data } } - public async Task SendMessageToRaidUsers(string message, Raid raid) + { + if(raid == null) return false; + + HashSet userIds = new HashSet(); + foreach(RaidSignUp signUp in raid.SignUps) + { + if(signUp.LiebUserId.HasValue) + { + userIds.Add(signUp.LiebUserId.Value); + } + } + return await SendMessageToUsers(message, raid.Title, userIds); + } + + public async Task SendGroupReminder(RaidReminder reminder, Raid raid) + { + using var context = _contextFactory.CreateDbContext(); + HashSet groupMembers = context.LiebUsers.Where(u => u.RoleAssignments.Where(r => r.LiebRole.LiebRoleId == reminder.RoleId).Any()).Select(u => u.Id).ToHashSet(); + HashSet userIds; + switch(reminder.RoleType) + { + case RaidReminder.RoleReminderType.All: + userIds = groupMembers; + break; + case RaidReminder.RoleReminderType.SignedUp: + userIds = groupMembers.Where(m => raid.SignUps.Where(s => s.LiebUserId == m).Any()).ToHashSet(); + break; + case RaidReminder.RoleReminderType.NotSignedUp: + userIds = groupMembers.Where(m => !raid.SignUps.Where(s => s.LiebUserId == m).Any()).ToHashSet(); + break; + default: + userIds = new HashSet(); + break; + } + if (await SendMessageToUsers(reminder.Message, raid.Title, userIds)) + { + reminder.Sent = true; + context.Update(reminder); + await context.SaveChangesAsync(); + } + } + + public async Task SendMessageToUsers(string message, string raidTitle, HashSet userIds) { try { + using var context = _contextFactory.CreateDbContext(); + HashSet userIdsToSendTo = context.LiebUsers + .Where(u => u.ReminderSubscription == userIds.Contains(u.Id)) + .Select(u => u.Id) + .ToHashSet(); + var httpClient = _httpClientFactory.CreateClient(Constants.HttpClientName); - if(raid == null) return false; - - ApiUserReminder apiReminder = ConvertUserReminder(message, raid); + ApiUserReminder apiReminder = CreateUserReminder(message, raidTitle, userIds); var raidItemJson = new StringContent( JsonSerializer.Serialize(apiReminder), @@ -184,21 +230,12 @@ namespace Lieb.Data return false; } - public static ApiUserReminder ConvertUserReminder(string message, Raid raid) + public static ApiUserReminder CreateUserReminder(string message, string raidTitle, HashSet userIds) { ApiUserReminder apiReminder = new ApiUserReminder() { - Message = $"{raid.Title}: {message}" + Message = $"{raidTitle}: {message}" }; - apiReminder.UserIds = new List(); - HashSet userIds = new HashSet(); - foreach(RaidSignUp signUp in raid.SignUps) - { - if(signUp.LiebUserId.HasValue) - { - userIds.Add(signUp.LiebUserId.Value); - } - } apiReminder.UserIds = userIds.ToList(); return apiReminder; } @@ -249,51 +286,6 @@ namespace Lieb.Data #endregion ChannelReminder -#region GroupReminder - public async Task SendGroupReminder(RaidReminder reminder, string raidTitle) - { - using var context = _contextFactory.CreateDbContext(); - HashSet groupMembers = context.LiebUsers.Where(u => u.RoleAssignments.Where(r => r.LiebRole.LiebRoleId == reminder.RoleId).Any()).Select(u => u.Id).ToHashSet(); - if (await SendMessageToGroup(reminder.Message, raidTitle, groupMembers)) - { - reminder.Sent = true; - context.Update(reminder); - await context.SaveChangesAsync(); - } - } - - public async Task SendMessageToGroup(string message, string raidTitle, HashSet userIds) - { - try - { - var httpClient = _httpClientFactory.CreateClient(Constants.HttpClientName); - - ApiUserReminder apiReminder = ConvertGroupReminder(message, raidTitle, userIds); - - var raidItemJson = new StringContent( - JsonSerializer.Serialize(apiReminder), - Encoding.UTF8, - Application.Json); - - var httpResponseMessage = await httpClient.PostAsync("raid/SendUserReminder", raidItemJson); - - return httpResponseMessage.IsSuccessStatusCode; - } - catch {} - return false; - } - - public static ApiUserReminder ConvertGroupReminder(string message, string raidTitle, HashSet groupIds) - { - ApiUserReminder apiReminder = new ApiUserReminder() - { - Message = $"{raidTitle}: {message}" - }; - apiReminder.UserIds = groupIds.ToList(); - return apiReminder; - } -#endregion GroupReminder - private async Task UpdateDiscordMessages(IEnumerable messages, Raid raid) { foreach(ApiRaid.DiscordMessage message in messages) @@ -406,5 +398,17 @@ namespace Lieb.Data } catch {} } + + public async Task SendReminderOptOutMessage(ulong userId) + { + try + { + var httpClient = _httpClientFactory.CreateClient(Constants.HttpClientName); + var httpResponseMessage = await httpClient.GetAsync($"raid/SendReminderOptOutMessage/{userId}"); + + httpResponseMessage.EnsureSuccessStatusCode(); + } + catch {} + } } } \ No newline at end of file diff --git a/Lieb/Data/RaidService.cs b/Lieb/Data/RaidService.cs index 988c328..8d7061a 100644 --- a/Lieb/Data/RaidService.cs +++ b/Lieb/Data/RaidService.cs @@ -519,7 +519,7 @@ namespace Lieb.Data await _discordService.SendChannelReminder(reminder, raid.Title); break; case RaidReminder.ReminderType.Group: - await _discordService.SendGroupReminder(reminder, raid.Title); + await _discordService.SendGroupReminder(reminder, raid); break; } } diff --git a/Lieb/Data/UserService.cs b/Lieb/Data/UserService.cs index 61ae279..3ad69c3 100644 --- a/Lieb/Data/UserService.cs +++ b/Lieb/Data/UserService.cs @@ -95,6 +95,7 @@ namespace Lieb.Data context.RoleAssignments.Add(roleAssignment); await context.SaveChangesAsync(); } + await _discordService.SendReminderOptOutMessage(newUser.Id); } public async Task EditUser(LiebUser user) @@ -343,5 +344,17 @@ namespace Lieb.Data } } } + + public async Task ReminderOptOut(ulong userId) + { + using var context = _contextFactory.CreateDbContext(); + LiebUser? user = await context.LiebUsers + .FirstOrDefaultAsync(u => u.Id == userId); + if(user == null) return false; + + user.ReminderSubscription = false; + await context.SaveChangesAsync(); + return true; + } } } diff --git a/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.Designer.cs b/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.Designer.cs new file mode 100644 index 0000000..ec40402 --- /dev/null +++ b/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.Designer.cs @@ -0,0 +1,659 @@ +// +using System; +using Lieb.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Lieb.Migrations +{ + [DbContext(typeof(LiebContext))] + [Migration("20221209181937_AddRoleReminderTypeAndSubscription")] + partial class AddRoleReminderTypeAndSubscription + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.10"); + + modelBuilder.Entity("Lieb.Models.DiscordSettings", b => + { + b.Property("DiscordSettingsId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChangeUserNames") + .HasColumnType("INTEGER"); + + b.Property("DiscordLogChannel") + .HasColumnType("INTEGER"); + + b.HasKey("DiscordSettingsId"); + + b.ToTable("DiscordSettings", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Equipped", b => + { + b.Property("EquippedId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CanTank") + .HasColumnType("INTEGER"); + + b.Property("GuildWars2AccountId") + .HasColumnType("INTEGER"); + + b.Property("GuildWars2BuildId") + .HasColumnType("INTEGER"); + + b.HasKey("EquippedId"); + + b.HasIndex("GuildWars2AccountId"); + + b.HasIndex("GuildWars2BuildId"); + + b.ToTable("Equipped", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.GuildWars2Account", b => + { + b.Property("GuildWars2AccountId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AccountName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("LiebUserId") + .HasColumnType("INTEGER"); + + b.HasKey("GuildWars2AccountId"); + + b.HasIndex("LiebUserId"); + + b.ToTable("GuildWars2Account", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.GuildWars2Build", b => + { + b.Property("GuildWars2BuildId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Alacrity") + .HasColumnType("INTEGER"); + + b.Property("BuildName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("TEXT"); + + b.Property("Class") + .HasColumnType("INTEGER"); + + b.Property("DamageType") + .HasColumnType("INTEGER"); + + b.Property("EliteSpecialization") + .HasColumnType("INTEGER"); + + b.Property("Might") + .HasColumnType("INTEGER"); + + b.Property("Quickness") + .HasColumnType("INTEGER"); + + b.Property("Source") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("SourceLink") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UseInRandomRaid") + .HasColumnType("INTEGER"); + + b.HasKey("GuildWars2BuildId"); + + b.ToTable("GuildWars2Build", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.DiscordRaidMessage", b => + { + b.Property("DiscordRaidMessageId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DiscordChannelId") + .HasColumnType("INTEGER"); + + b.Property("DiscordGuildId") + .HasColumnType("INTEGER"); + + b.Property("DiscordMessageId") + .HasColumnType("INTEGER"); + + b.Property("RaidId") + .HasColumnType("INTEGER"); + + b.Property("RaidTemplateId") + .HasColumnType("INTEGER"); + + b.HasKey("DiscordRaidMessageId"); + + b.HasIndex("RaidId"); + + b.HasIndex("RaidTemplateId"); + + b.ToTable("DiscordRaidMessage", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.Raid", b => + { + b.Property("RaidId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("EndTimeUTC") + .HasColumnType("TEXT"); + + b.Property("EventType") + .HasColumnType("INTEGER"); + + b.Property("FreeForAllTimeUTC") + .HasColumnType("TEXT"); + + b.Property("Guild") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MoveFlexUsers") + .HasColumnType("INTEGER"); + + b.Property("Organizer") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RaidOwnerId") + .HasColumnType("INTEGER"); + + b.Property("RaidType") + .HasColumnType("INTEGER"); + + b.Property("RequiredRole") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("StartTimeUTC") + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("VoiceChat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("RaidId"); + + b.ToTable("Raid", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidReminder", b => + { + b.Property("RaidReminderId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DiscordChannelId") + .HasColumnType("INTEGER"); + + b.Property("DiscordServerId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("RaidId") + .HasColumnType("INTEGER"); + + b.Property("RaidTemplateId") + .HasColumnType("INTEGER"); + + b.Property("ReminderTimeUTC") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleType") + .HasColumnType("INTEGER"); + + b.Property("Sent") + .HasColumnType("INTEGER"); + + b.Property("TimeType") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("RaidReminderId"); + + b.HasIndex("RaidId"); + + b.HasIndex("RaidTemplateId"); + + b.ToTable("RaidReminder", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidRole", b => + { + b.Property("RaidRoleId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("IsRandomSignUpRole") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("TEXT"); + + b.Property("RaidId") + .HasColumnType("INTEGER"); + + b.Property("RaidTemplateId") + .HasColumnType("INTEGER"); + + b.Property("Spots") + .HasColumnType("INTEGER"); + + b.HasKey("RaidRoleId"); + + b.HasIndex("RaidId"); + + b.HasIndex("RaidTemplateId"); + + b.ToTable("RaidRole", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidSignUp", b => + { + b.Property("RaidSignUpId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ExternalUserName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("GuildWars2AccountId") + .HasColumnType("INTEGER"); + + b.Property("LiebUserId") + .HasColumnType("INTEGER"); + + b.Property("RaidId") + .HasColumnType("INTEGER"); + + b.Property("RaidRoleId") + .HasColumnType("INTEGER"); + + b.Property("SignUpType") + .HasColumnType("INTEGER"); + + b.HasKey("RaidSignUpId"); + + b.HasIndex("GuildWars2AccountId"); + + b.HasIndex("LiebUserId"); + + b.HasIndex("RaidId"); + + b.HasIndex("RaidRoleId"); + + b.ToTable("RaidSignUp", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidTemplate", b => + { + b.Property("RaidTemplateId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreateDaysBefore") + .HasColumnType("INTEGER"); + + b.Property("Description") + .IsRequired() + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("EventType") + .HasColumnType("INTEGER"); + + b.Property("FreeForAllTime") + .HasColumnType("TEXT"); + + b.Property("Guild") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("MoveFlexUsers") + .HasColumnType("INTEGER"); + + b.Property("Organizer") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RaidOwnerId") + .HasColumnType("INTEGER"); + + b.Property("RaidType") + .HasColumnType("INTEGER"); + + b.Property("RequiredRole") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("TimeZone") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Title") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("VoiceChat") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("RaidTemplateId"); + + b.ToTable("RaidTemplate", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.LiebRole", b => + { + b.Property("LiebRoleId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("LevelToAssign") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("LiebRoleId"); + + b.ToTable("LiebRole", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.LiebUser", b => + { + b.Property("Id") + .HasColumnType("INTEGER"); + + b.Property("AlwaysSignUpWithMainAccount") + .HasColumnType("INTEGER"); + + b.Property("BannedUntil") + .HasColumnType("TEXT"); + + b.Property("Birthday") + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("LastSignUpAt") + .HasColumnType("TEXT"); + + b.Property("MainGW2Account") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("TEXT"); + + b.Property("Pronouns") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("TEXT"); + + b.Property("ReminderSubscription") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("LiebUser", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.RoleAssignment", b => + { + b.Property("RoleAssignmentId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LiebRoleId") + .HasColumnType("INTEGER"); + + b.Property("LiebUserId") + .HasColumnType("INTEGER"); + + b.HasKey("RoleAssignmentId"); + + b.HasIndex("LiebRoleId"); + + b.HasIndex("LiebUserId"); + + b.ToTable("RoleAssignment", (string)null); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Equipped", b => + { + b.HasOne("Lieb.Models.GuildWars2.GuildWars2Account", "GuildWars2Account") + .WithMany("EquippedBuilds") + .HasForeignKey("GuildWars2AccountId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Lieb.Models.GuildWars2.GuildWars2Build", "GuildWars2Build") + .WithMany("EquippedRoles") + .HasForeignKey("GuildWars2BuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildWars2Account"); + + b.Navigation("GuildWars2Build"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.GuildWars2Account", b => + { + b.HasOne("Lieb.Models.LiebUser", null) + .WithMany("GuildWars2Accounts") + .HasForeignKey("LiebUserId"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.DiscordRaidMessage", b => + { + b.HasOne("Lieb.Models.GuildWars2.Raid.Raid", null) + .WithMany("DiscordRaidMessages") + .HasForeignKey("RaidId"); + + b.HasOne("Lieb.Models.GuildWars2.Raid.RaidTemplate", null) + .WithMany("DiscordRaidMessages") + .HasForeignKey("RaidTemplateId"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidReminder", b => + { + b.HasOne("Lieb.Models.GuildWars2.Raid.Raid", null) + .WithMany("Reminders") + .HasForeignKey("RaidId"); + + b.HasOne("Lieb.Models.GuildWars2.Raid.RaidTemplate", null) + .WithMany("Reminders") + .HasForeignKey("RaidTemplateId"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidRole", b => + { + b.HasOne("Lieb.Models.GuildWars2.Raid.Raid", null) + .WithMany("Roles") + .HasForeignKey("RaidId"); + + b.HasOne("Lieb.Models.GuildWars2.Raid.RaidTemplate", null) + .WithMany("Roles") + .HasForeignKey("RaidTemplateId"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidSignUp", b => + { + b.HasOne("Lieb.Models.GuildWars2.GuildWars2Account", "GuildWars2Account") + .WithMany() + .HasForeignKey("GuildWars2AccountId"); + + b.HasOne("Lieb.Models.LiebUser", "LiebUser") + .WithMany() + .HasForeignKey("LiebUserId"); + + b.HasOne("Lieb.Models.GuildWars2.Raid.Raid", "Raid") + .WithMany("SignUps") + .HasForeignKey("RaidId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Lieb.Models.GuildWars2.Raid.RaidRole", "RaidRole") + .WithMany() + .HasForeignKey("RaidRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildWars2Account"); + + b.Navigation("LiebUser"); + + b.Navigation("Raid"); + + b.Navigation("RaidRole"); + }); + + modelBuilder.Entity("Lieb.Models.RoleAssignment", b => + { + b.HasOne("Lieb.Models.LiebRole", "LiebRole") + .WithMany("RoleAssignments") + .HasForeignKey("LiebRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Lieb.Models.LiebUser", "LiebUser") + .WithMany("RoleAssignments") + .HasForeignKey("LiebUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LiebRole"); + + b.Navigation("LiebUser"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.GuildWars2Account", b => + { + b.Navigation("EquippedBuilds"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.GuildWars2Build", b => + { + b.Navigation("EquippedRoles"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.Raid", b => + { + b.Navigation("DiscordRaidMessages"); + + b.Navigation("Reminders"); + + b.Navigation("Roles"); + + b.Navigation("SignUps"); + }); + + modelBuilder.Entity("Lieb.Models.GuildWars2.Raid.RaidTemplate", b => + { + b.Navigation("DiscordRaidMessages"); + + b.Navigation("Reminders"); + + b.Navigation("Roles"); + }); + + modelBuilder.Entity("Lieb.Models.LiebRole", b => + { + b.Navigation("RoleAssignments"); + }); + + modelBuilder.Entity("Lieb.Models.LiebUser", b => + { + b.Navigation("GuildWars2Accounts"); + + b.Navigation("RoleAssignments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.cs b/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.cs new file mode 100644 index 0000000..c16e948 --- /dev/null +++ b/Lieb/Migrations/20221209181937_AddRoleReminderTypeAndSubscription.cs @@ -0,0 +1,37 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Lieb.Migrations +{ + public partial class AddRoleReminderTypeAndSubscription : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "RoleType", + table: "RaidReminder", + type: "INTEGER", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "ReminderSubscription", + table: "LiebUser", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "RoleType", + table: "RaidReminder"); + + migrationBuilder.DropColumn( + name: "ReminderSubscription", + table: "LiebUser"); + } + } +} diff --git a/Lieb/Migrations/LiebContextModelSnapshot.cs b/Lieb/Migrations/LiebContextModelSnapshot.cs index 6acfa23..0e7efc7 100644 --- a/Lieb/Migrations/LiebContextModelSnapshot.cs +++ b/Lieb/Migrations/LiebContextModelSnapshot.cs @@ -247,6 +247,9 @@ namespace Lieb.Migrations b.Property("RoleId") .HasColumnType("INTEGER"); + b.Property("RoleType") + .HasColumnType("INTEGER"); + b.Property("Sent") .HasColumnType("INTEGER"); @@ -469,6 +472,9 @@ namespace Lieb.Migrations .HasMaxLength(60) .HasColumnType("TEXT"); + b.Property("ReminderSubscription") + .HasColumnType("INTEGER"); + b.HasKey("Id"); b.ToTable("LiebUser", (string)null); diff --git a/Lieb/Models/GuildWars2/Raid/RaidReminder.cs b/Lieb/Models/GuildWars2/Raid/RaidReminder.cs index c32117c..3341e57 100644 --- a/Lieb/Models/GuildWars2/Raid/RaidReminder.cs +++ b/Lieb/Models/GuildWars2/Raid/RaidReminder.cs @@ -18,6 +18,13 @@ namespace Lieb.Models.GuildWars2.Raid Dynamic = 2 } + public enum RoleReminderType + { + All = 0, + SignedUp = 1, + NotSignedUp = 2 + } + public int RaidReminderId { get; set; } [Required] @@ -40,6 +47,8 @@ namespace Lieb.Models.GuildWars2.Raid public ulong DiscordChannelId { get; set; } public int RoleId {get; set; } + + public RoleReminderType RoleType {get; set;} public bool Sent { get; set; } = false; } diff --git a/Lieb/Models/LiebUser.cs b/Lieb/Models/LiebUser.cs index 07ed22e..0aecac5 100644 --- a/Lieb/Models/LiebUser.cs +++ b/Lieb/Models/LiebUser.cs @@ -22,6 +22,7 @@ namespace Lieb.Models public DateTime? LastSignUpAt { get; set; } public int MainGW2Account { get; set; } public bool AlwaysSignUpWithMainAccount { get; set; } = false; + public bool ReminderSubscription { get; set; } = true; public ICollection GuildWars2Accounts { get; set; } = new List(); public ICollection RoleAssignments { get; set; } = new List(); } diff --git a/Lieb/Pages/Raids/RaidEdit/DynamicReminderEdit.razor b/Lieb/Pages/Raids/RaidEdit/DynamicReminderEdit.razor index 889b568..0f4cf14 100644 --- a/Lieb/Pages/Raids/RaidEdit/DynamicReminderEdit.razor +++ b/Lieb/Pages/Raids/RaidEdit/DynamicReminderEdit.razor @@ -14,30 +14,24 @@ Hours Minutes Type - @{bool channelReminderExists = _raidReminders.Where(r => r.Type == RaidReminder.ReminderType.Channel).Any(); - bool groupReminderExists = _raidReminders.Where(r => r.Type == RaidReminder.ReminderType.Group).Any();} - @if(channelReminderExists && groupReminderExists) + @if(_raidReminders.Where(r => r.Type == RaidReminder.ReminderType.Group).Any()) { Group - Server - Channel - } - else if(channelReminderExists) - { - - Server - Channel - } - else if(groupReminderExists) - { - Group - - + Signed Up } else { + } + @if(_raidReminders.Where(r => r.Type == RaidReminder.ReminderType.Channel).Any()) + { + Server + Channel + } + else + { + } Message @@ -66,6 +60,14 @@ } + + + + + +