diff --git a/src/GrillBot.App/Actions/Api/V1/Guild/GetGuildDetail.cs b/src/GrillBot.App/Actions/Api/V1/Guild/GetGuildDetail.cs index 515182e0..e6ec27e7 100644 --- a/src/GrillBot.App/Actions/Api/V1/Guild/GetGuildDetail.cs +++ b/src/GrillBot.App/Actions/Api/V1/Guild/GetGuildDetail.cs @@ -1,4 +1,5 @@ using AutoMapper; +using GrillBot.App.Managers.DataResolve; using GrillBot.Cache.Services; using GrillBot.Common.Extensions.Discord; using GrillBot.Common.Managers.Localization; @@ -11,7 +12,6 @@ using GrillBot.Core.Services.PointsService; using GrillBot.Core.Services.PointsService.Models; using GrillBot.Core.Services.UserMeasures; -using GrillBot.Data.Models.API; using GrillBot.Data.Models.API.Guilds; using GrillBot.Database.Models.Guilds; @@ -28,8 +28,11 @@ public class GetGuildDetail : ApiAction private IAuditLogServiceClient AuditLogServiceClient { get; } private IUserMeasuresServiceClient UserMeasuresService { get; } + private readonly DataResolveManager _dataResolve; + public GetGuildDetail(ApiRequestContext apiContext, GrillBotDatabaseBuilder databaseBuilder, IMapper mapper, IDiscordClient discordClient, GrillBotCacheBuilder cacheBuilder, - ITextsManager texts, IPointsServiceClient pointsServiceClient, IAuditLogServiceClient auditLogServiceClient, IUserMeasuresServiceClient userMeasuresService) : base(apiContext) + ITextsManager texts, IPointsServiceClient pointsServiceClient, IAuditLogServiceClient auditLogServiceClient, IUserMeasuresServiceClient userMeasuresService, + DataResolveManager dataResolve) : base(apiContext) { DatabaseBuilder = databaseBuilder; Mapper = mapper; @@ -39,6 +42,7 @@ public GetGuildDetail(ApiRequestContext apiContext, GrillBotDatabaseBuilder data PointsServiceClient = pointsServiceClient; AuditLogServiceClient = auditLogServiceClient; UserMeasuresService = userMeasuresService; + _dataResolve = dataResolve; } public override async Task ProcessAsync() @@ -58,22 +62,25 @@ public override async Task ProcessAsync() detail.DatabaseReport = await CreateDatabaseReportAsync(id); detail = Mapper.Map(discordGuild, detail); if (!string.IsNullOrEmpty(dbGuild.AdminChannelId)) - detail.AdminChannel = Mapper.Map(await discordGuild.GetChannelAsync(dbGuild.AdminChannelId.ToUlong())); + detail.AdminChannel = await _dataResolve.GetChannelAsync(discordGuild.Id, dbGuild.AdminChannelId.ToUlong()); if (!string.IsNullOrEmpty(dbGuild.EmoteSuggestionChannelId)) - detail.EmoteSuggestionChannel = Mapper.Map(await discordGuild.GetChannelAsync(dbGuild.EmoteSuggestionChannelId.ToUlong())); + detail.EmoteSuggestionChannel = await _dataResolve.GetChannelAsync(discordGuild.Id, dbGuild.EmoteSuggestionChannelId.ToUlong()); if (!string.IsNullOrEmpty(dbGuild.BoosterRoleId)) - detail.BoosterRole = Mapper.Map(discordGuild.GetRole(dbGuild.BoosterRoleId.ToUlong())); + detail.BoosterRole = await _dataResolve.GetRoleAsync(dbGuild.BoosterRoleId.ToUlong()); if (!string.IsNullOrEmpty(dbGuild.MuteRoleId)) - detail.MutedRole = Mapper.Map(discordGuild.GetRole(dbGuild.MuteRoleId.ToUlong())); + detail.MutedRole = await _dataResolve.GetRoleAsync(dbGuild.MuteRoleId.ToUlong()); if (!string.IsNullOrEmpty(dbGuild.VoteChannelId)) - detail.VoteChannel = Mapper.Map(await discordGuild.GetChannelAsync(dbGuild.VoteChannelId.ToUlong())); + detail.VoteChannel = await _dataResolve.GetChannelAsync(discordGuild.Id, dbGuild.VoteChannelId.ToUlong()); if (!string.IsNullOrEmpty(dbGuild.BotRoomChannelId)) - detail.BotRoomChannel = Mapper.Map(await discordGuild.GetChannelAsync(dbGuild.BotRoomChannelId.ToUlong())); + detail.BotRoomChannel = await _dataResolve.GetChannelAsync(discordGuild.Id, dbGuild.BotRoomChannelId.ToUlong()); + + if (!string.IsNullOrEmpty(dbGuild.AssociationRoleId)) + detail.AssociationRole = await _dataResolve.GetRoleAsync(dbGuild.AssociationRoleId.ToUlong()); var guildUsers = await discordGuild.GetUsersAsync(); detail.UserStatusReport = guildUsers diff --git a/src/GrillBot.App/Actions/Api/V1/Guild/UpdateGuild.cs b/src/GrillBot.App/Actions/Api/V1/Guild/UpdateGuild.cs index 50d629cb..a81e3d43 100644 --- a/src/GrillBot.App/Actions/Api/V1/Guild/UpdateGuild.cs +++ b/src/GrillBot.App/Actions/Api/V1/Guild/UpdateGuild.cs @@ -26,10 +26,8 @@ public override async Task ProcessAsync() { var id = (ulong)Parameters[0]!; var parameters = (UpdateGuildParams)Parameters[1]!; - - var guild = await DiscordClient.GetGuildAsync(id); - if (guild == null) - throw new NotFoundException(Texts["GuildModule/GuildDetail/NotFound", ApiContext.Language]); + var guild = await DiscordClient.GetGuildAsync(id) + ?? throw new NotFoundException(Texts["GuildModule/GuildDetail/NotFound", ApiContext.Language]); await using var repository = DatabaseBuilder.CreateRepository(); @@ -59,6 +57,11 @@ public override async Task ProcessAsync() else dbGuild.BotRoomChannelId = parameters.BotRoomChannelId; + if (!string.IsNullOrEmpty(parameters.AssociationRoleId) && guild.GetRole(parameters.AssociationRoleId.ToUlong()) == null) + ThrowValidationException("AssociationRoleNotFound", parameters.AssociationRoleId, nameof(parameters.AssociationRoleId)); + else + dbGuild.AssociationRoleId = parameters.AssociationRoleId; + dbGuild.EmoteSuggestionsFrom = parameters.EmoteSuggestionsValidity?.From; dbGuild.EmoteSuggestionsTo = parameters.EmoteSuggestionsValidity?.To; diff --git a/src/GrillBot.App/Handlers/Ready/GuildSynchronizationHandler.cs b/src/GrillBot.App/Handlers/Ready/GuildSynchronizationHandler.cs index 1505861d..9b87fbf6 100644 --- a/src/GrillBot.App/Handlers/Ready/GuildSynchronizationHandler.cs +++ b/src/GrillBot.App/Handlers/Ready/GuildSynchronizationHandler.cs @@ -36,6 +36,8 @@ public async Task ProcessAsync() dbGuild.VoteChannelId = null; if (CanResetRoleId(dbGuild.MuteRoleId, guild)) dbGuild.MuteRoleId = null; + if (CanResetRoleId(dbGuild.AssociationRoleId, guild)) + dbGuild.AssociationRoleId = null; } await repository.CommitAsync(); diff --git a/src/GrillBot.App/Handlers/RoleDeleted/GuildConfigurationRoleDeletedHandler.cs b/src/GrillBot.App/Handlers/RoleDeleted/GuildConfigurationRoleDeletedHandler.cs index faeed4fa..cbc1e5ab 100644 --- a/src/GrillBot.App/Handlers/RoleDeleted/GuildConfigurationRoleDeletedHandler.cs +++ b/src/GrillBot.App/Handlers/RoleDeleted/GuildConfigurationRoleDeletedHandler.cs @@ -2,6 +2,8 @@ using GrillBot.Common.Managers.Events.Contracts; using GrillBot.Core.RabbitMQ.Publisher; using GrillBot.Core.Services.AuditLog.Enums; +using GrillBot.Database.Enums; +using GrillBot.Database.Services.Repository; namespace GrillBot.App.Handlers.RoleDeleted; @@ -27,6 +29,7 @@ public async Task ProcessAsync(IRole role) var log = new List(); ModifyMutedRoleId(role, guild, log); + ModifyAssociationRoleId(role, guild, log); if (log.Count == 0) return; @@ -44,6 +47,15 @@ private static void ModifyMutedRoleId(IRole role, Database.Entity.Guild guild, L guild.MuteRoleId = null; } + private static void ModifyAssociationRoleId(IRole role, Database.Entity.Guild guild, List log) + { + if (string.IsNullOrEmpty(guild.AssociationRoleId) || guild.AssociationRoleId != role.Id.ToString()) + return; + + log.Add($"Removed AssociationRoleId value and cleared user flags. OldValue: {guild.AssociationRoleId}"); + guild.AssociationRoleId = null; + } + private async Task WriteToAuditLogAsync(IGuild guild, List log) { var logRequest = new LogRequest(LogType.Info, DateTime.UtcNow, guild.Id.ToString()) diff --git a/src/GrillBot.Data/Models/API/Guilds/GuildDetail.cs b/src/GrillBot.Data/Models/API/Guilds/GuildDetail.cs index 921272b3..3859c07b 100644 --- a/src/GrillBot.Data/Models/API/Guilds/GuildDetail.cs +++ b/src/GrillBot.Data/Models/API/Guilds/GuildDetail.cs @@ -95,4 +95,5 @@ public class GuildDetail : Guild public Dictionary UserStatusReport { get; set; } = new(); public Dictionary ClientTypeReport { get; set; } = new(); public GuildDatabaseReport DatabaseReport { get; set; } = null!; + public Role? AssociationRole { get; set; } } diff --git a/src/GrillBot.Data/Models/API/Guilds/UpdateGuildParams.cs b/src/GrillBot.Data/Models/API/Guilds/UpdateGuildParams.cs index 1efaa482..f4a1f801 100644 --- a/src/GrillBot.Data/Models/API/Guilds/UpdateGuildParams.cs +++ b/src/GrillBot.Data/Models/API/Guilds/UpdateGuildParams.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using GrillBot.Core.Extensions; using GrillBot.Core.Infrastructure; using GrillBot.Core.Validation; @@ -10,22 +11,31 @@ namespace GrillBot.Data.Models.API.Guilds; public class UpdateGuildParams : IDictionaryObject { [DiscordId] + [StringLength(30)] public string? MuteRoleId { get; set; } [DiscordId] + [StringLength(30)] public string? AdminChannelId { get; set; } [DiscordId] + [StringLength(30)] public string? EmoteSuggestionChannelId { get; set; } [DiscordId] + [StringLength(30)] public string? VoteChannelId { get; set; } [DiscordId] + [StringLength(30)] public string? BotRoomChannelId { get; set; } public RangeParams? EmoteSuggestionsValidity { get; set; } + [DiscordId] + [StringLength(30)] + public string? AssociationRoleId { get; set; } + public Dictionary ToDictionary() { var result = new Dictionary @@ -34,7 +44,8 @@ public class UpdateGuildParams : IDictionaryObject { nameof(AdminChannelId), AdminChannelId }, { nameof(EmoteSuggestionChannelId), EmoteSuggestionChannelId }, { nameof(VoteChannelId), VoteChannelId }, - { nameof(BotRoomChannelId), BotRoomChannelId } + { nameof(BotRoomChannelId), BotRoomChannelId }, + { nameof(AssociationRoleId), AssociationRoleId } }; result.MergeDictionaryObjects(EmoteSuggestionsValidity, nameof(EmoteSuggestionsValidity)); diff --git a/src/GrillBot.Data/Models/API/Users/GetUserListParams.cs b/src/GrillBot.Data/Models/API/Users/GetUserListParams.cs index a572693e..1a1efc4b 100644 --- a/src/GrillBot.Data/Models/API/Users/GetUserListParams.cs +++ b/src/GrillBot.Data/Models/API/Users/GetUserListParams.cs @@ -75,7 +75,7 @@ public class GetUserListParams : IQueryableModel, IDiction } if (Flags != null && Flags > 0) - query = query.Where(o => (o.Flags & Flags) == Flags); + query = query.Where(o => (o.Flags & Flags) != 0); if (HaveBirthday) query = query.Where(o => o.Birthday != null); diff --git a/src/GrillBot.Data/Resources/Localization/messages.cs.json b/src/GrillBot.Data/Resources/Localization/messages.cs.json index 862ac0f2..070db6ca 100644 --- a/src/GrillBot.Data/Resources/Localization/messages.cs.json +++ b/src/GrillBot.Data/Resources/Localization/messages.cs.json @@ -214,7 +214,8 @@ "MuteRoleNotFound": "Nepodařilo se dohledat roli, která reprezentuje umlčení uživatele při unverify.", "EmoteSuggestionChannelNotFound": "Nepodařilo se dohledat kanál pro návrhy emotů.", "VoteChannelNotFound": "Nepodařilo se dohledat kanál pro veřejná hlasování.", - "BotRoomChannelNotFound": "Nepodařilo se dohledat kanál pro boty." + "BotRoomChannelNotFound": "Nepodařilo se dohledat kanál pro boty.", + "AssociationRoleNotFound": "Nepodařilo se dohledat roli spolku." } }, "MathModule": { diff --git a/src/GrillBot.Data/Resources/Localization/messages.en-US.json b/src/GrillBot.Data/Resources/Localization/messages.en-US.json index 59b51859..b10bdfe1 100644 --- a/src/GrillBot.Data/Resources/Localization/messages.en-US.json +++ b/src/GrillBot.Data/Resources/Localization/messages.en-US.json @@ -214,7 +214,8 @@ "MuteRoleNotFound": "Failed to find the role that represents silencing the user on unverify.", "EmoteSuggestionChannelNotFound": "Failed to find channel for emote suggestions.", "VoteChannelNotFound": "Could not find public polling channel.", - "BotRoomChannelNotFound": "Could not find channel for bots." + "BotRoomChannelNotFound": "Could not find channel for bots.", + "AssociationRoleNotFound": "Could not found association role." } }, "MathModule": { diff --git a/src/GrillBot.Database/Entity/Guild.cs b/src/GrillBot.Database/Entity/Guild.cs index 817c20ff..7de45cbf 100644 --- a/src/GrillBot.Database/Entity/Guild.cs +++ b/src/GrillBot.Database/Entity/Guild.cs @@ -42,6 +42,9 @@ public class Guild [StringLength(30)] public string? BotRoomChannelId { get; set; } + [StringLength(30)] + public string? AssociationRoleId { get; set; } + public ISet Users { get; set; } public ISet Invites { get; set; } public ISet Channels { get; set; } diff --git a/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.Designer.cs b/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.Designer.cs new file mode 100644 index 00000000..cd4331d7 --- /dev/null +++ b/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.Designer.cs @@ -0,0 +1,919 @@ +// +using System; +using System.Collections.Generic; +using GrillBot.Database.Entity; +using GrillBot.Database.Services; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace GrillBot.Database.Migrations +{ + [DbContext(typeof(GrillBotContext))] + [Migration("20240229062550_AssociationRoleId")] + partial class AssociationRoleId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("GrillBot.Database.Entity.ApiClient", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property>("AllowedMethods") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("LastUse") + .HasColumnType("timestamp without time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UseCount") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ApiClients"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.AutoReplyItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Flags") + .HasColumnType("bigint"); + + b.Property("Reply") + .IsRequired() + .HasColumnType("text"); + + b.Property("Template") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoReplies"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.EmoteStatisticItem", b => + { + b.Property("EmoteId") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("UserId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("FirstOccurence") + .HasColumnType("timestamp without time zone"); + + b.Property("IsEmoteSupported") + .HasColumnType("boolean"); + + b.Property("LastOccurence") + .HasColumnType("timestamp without time zone"); + + b.Property("UseCount") + .HasColumnType("bigint"); + + b.HasKey("EmoteId", "UserId", "GuildId"); + + b.HasIndex("GuildId", "UserId"); + + b.ToTable("Emotes"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.EmoteSuggestion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ApprovedForVote") + .HasColumnType("boolean"); + + b.Property("CommunityApproved") + .HasColumnType("boolean"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("Description") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("DownVotes") + .HasColumnType("integer"); + + b.Property("EmoteName") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Filename") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("FromUserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GuildId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ImageData") + .IsRequired() + .HasColumnType("bytea"); + + b.Property("SuggestionMessageId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UpVotes") + .HasColumnType("integer"); + + b.Property("VoteEndsAt") + .HasColumnType("timestamp without time zone"); + + b.Property("VoteFinished") + .HasColumnType("boolean"); + + b.Property("VoteMessageId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "FromUserId"); + + b.ToTable("EmoteSuggestions"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Guild", b => + { + b.Property("Id") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("AdminChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("AssociationRoleId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("BoosterRoleId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("BotRoomChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmoteSuggestionChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("EmoteSuggestionsFrom") + .HasColumnType("timestamp without time zone"); + + b.Property("EmoteSuggestionsTo") + .HasColumnType("timestamp without time zone"); + + b.Property("MuteRoleId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("VoteChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Id"); + + b.ToTable("Guilds"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildChannel", b => + { + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ChannelType") + .HasColumnType("integer"); + + b.Property("Flags") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ParentChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("PinCount") + .HasColumnType("integer"); + + b.Property("RolePermissionsCount") + .HasColumnType("integer"); + + b.Property("UserPermissionsCount") + .HasColumnType("integer"); + + b.HasKey("GuildId", "ChannelId"); + + b.HasIndex("GuildId", "ParentChannelId"); + + b.ToTable("Channels"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildUser", b => + { + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UserId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GivenReactions") + .HasColumnType("bigint"); + + b.Property("IsInGuild") + .HasColumnType("boolean"); + + b.Property("Nickname") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("ObtainedReactions") + .HasColumnType("bigint"); + + b.Property("UsedInviteCode") + .HasMaxLength(20) + .HasColumnType("character varying(20)"); + + b.HasKey("GuildId", "UserId"); + + b.HasIndex("UsedInviteCode"); + + b.HasIndex("UserId"); + + b.ToTable("GuildUsers"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildUserChannel", b => + { + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ChannelId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UserId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Count") + .HasColumnType("bigint"); + + b.Property("FirstMessageAt") + .HasColumnType("timestamp without time zone"); + + b.Property("LastMessageAt") + .HasColumnType("timestamp without time zone"); + + b.HasKey("GuildId", "ChannelId", "UserId"); + + b.HasIndex("UserId"); + + b.HasIndex("GuildId", "UserId"); + + b.ToTable("UserChannels"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Invite", b => + { + b.Property("Code") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("CreatorId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GuildId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Code"); + + b.HasIndex("GuildId", "CreatorId"); + + b.ToTable("Invites"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Nickname", b => + { + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UserId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Id") + .HasColumnType("bigint"); + + b.Property("NicknameValue") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.HasKey("GuildId", "UserId", "Id"); + + b.ToTable("Nicknames"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.RemindMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("At") + .HasColumnType("timestamp without time zone"); + + b.Property("FromUserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Language") + .IsRequired() + .HasColumnType("text"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text"); + + b.Property("OriginalMessageId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Postpone") + .HasColumnType("integer"); + + b.Property("RemindMessageId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("ToUserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Id"); + + b.HasIndex("FromUserId"); + + b.HasIndex("ToUserId"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.SearchItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GuildId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("MessageContent") + .IsRequired() + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("UserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.HasIndex("GuildId", "ChannelId"); + + b.ToTable("SearchItems"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.SelfunverifyKeepable", b => + { + b.Property("GroupName") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("GroupName", "Name"); + + b.ToTable("SelfunverifyKeepables"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Unverify", b => + { + b.Property("GuildId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("UserId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property>("Channels") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("EndAt") + .HasColumnType("timestamp without time zone"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property>("Roles") + .IsRequired() + .HasColumnType("jsonb"); + + b.Property("SetOperationId") + .HasColumnType("bigint"); + + b.Property("StartAt") + .HasColumnType("timestamp without time zone"); + + b.HasKey("GuildId", "UserId"); + + b.HasIndex("SetOperationId") + .IsUnique(); + + b.ToTable("Unverifies"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.UnverifyLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .IsRequired() + .HasColumnType("text"); + + b.Property("FromUserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("GuildId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("Operation") + .HasColumnType("integer"); + + b.Property("ToUserId") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "FromUserId"); + + b.HasIndex("GuildId", "ToUserId"); + + b.ToTable("UnverifyLogs"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.User", b => + { + b.Property("Id") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("AvatarUrl") + .HasMaxLength(1024) + .HasColumnType("character varying(1024)"); + + b.Property("Birthday") + .HasColumnType("timestamp without time zone"); + + b.Property("Flags") + .HasColumnType("integer"); + + b.Property("GlobalAlias") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("Language") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("SelfUnverifyMinimalTime") + .HasColumnType("text"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.EmoteStatisticItem", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("EmoteStatistics") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "User") + .WithMany("EmoteStatistics") + .HasForeignKey("GuildId", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.EmoteSuggestion", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "FromUser") + .WithMany() + .HasForeignKey("GuildId", "FromUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUser"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildChannel", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("Channels") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildChannel", "ParentChannel") + .WithMany() + .HasForeignKey("GuildId", "ParentChannelId"); + + b.Navigation("Guild"); + + b.Navigation("ParentChannel"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildUser", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("Users") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.Invite", "UsedInvite") + .WithMany("UsedUsers") + .HasForeignKey("UsedInviteCode"); + + b.HasOne("GrillBot.Database.Entity.User", "User") + .WithMany("Guilds") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("UsedInvite"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildUserChannel", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.User", null) + .WithMany("Channels") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildChannel", "Channel") + .WithMany("Users") + .HasForeignKey("GuildId", "ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "User") + .WithMany("Channels") + .HasForeignKey("GuildId", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Invite", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("Invites") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "Creator") + .WithMany("CreatedInvites") + .HasForeignKey("GuildId", "CreatorId"); + + b.Navigation("Creator"); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Nickname", b => + { + b.HasOne("GrillBot.Database.Entity.GuildUser", "User") + .WithMany("Nicknames") + .HasForeignKey("GuildId", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.RemindMessage", b => + { + b.HasOne("GrillBot.Database.Entity.User", "FromUser") + .WithMany("OutgoingReminders") + .HasForeignKey("FromUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.User", "ToUser") + .WithMany("IncomingReminders") + .HasForeignKey("ToUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUser"); + + b.Navigation("ToUser"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.SearchItem", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("Searches") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.User", "User") + .WithMany("SearchItems") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildChannel", "Channel") + .WithMany("SearchItems") + .HasForeignKey("GuildId", "ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Unverify", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("Unverifies") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.UnverifyLog", "UnverifyLog") + .WithOne("Unverify") + .HasForeignKey("GrillBot.Database.Entity.Unverify", "SetOperationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "GuildUser") + .WithOne("Unverify") + .HasForeignKey("GrillBot.Database.Entity.Unverify", "GuildId", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("GuildUser"); + + b.Navigation("UnverifyLog"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.UnverifyLog", b => + { + b.HasOne("GrillBot.Database.Entity.Guild", "Guild") + .WithMany("UnverifyLogs") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "FromUser") + .WithMany() + .HasForeignKey("GuildId", "FromUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("GrillBot.Database.Entity.GuildUser", "ToUser") + .WithMany() + .HasForeignKey("GuildId", "ToUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("FromUser"); + + b.Navigation("Guild"); + + b.Navigation("ToUser"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Guild", b => + { + b.Navigation("Channels"); + + b.Navigation("EmoteStatistics"); + + b.Navigation("Invites"); + + b.Navigation("Searches"); + + b.Navigation("Unverifies"); + + b.Navigation("UnverifyLogs"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildChannel", b => + { + b.Navigation("SearchItems"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.GuildUser", b => + { + b.Navigation("Channels"); + + b.Navigation("CreatedInvites"); + + b.Navigation("EmoteStatistics"); + + b.Navigation("Nicknames"); + + b.Navigation("Unverify"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.Invite", b => + { + b.Navigation("UsedUsers"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.UnverifyLog", b => + { + b.Navigation("Unverify"); + }); + + modelBuilder.Entity("GrillBot.Database.Entity.User", b => + { + b.Navigation("Channels"); + + b.Navigation("Guilds"); + + b.Navigation("IncomingReminders"); + + b.Navigation("OutgoingReminders"); + + b.Navigation("SearchItems"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.cs b/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.cs new file mode 100644 index 00000000..32d55f7f --- /dev/null +++ b/src/GrillBot.Database/Migrations/20240229062550_AssociationRoleId.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace GrillBot.Database.Migrations +{ + /// + public partial class AssociationRoleId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AssociationRoleId", + table: "Guilds", + type: "character varying(30)", + maxLength: 30, + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AssociationRoleId", + table: "Guilds"); + } + } +} diff --git a/src/GrillBot.Database/Migrations/GrillBotContextModelSnapshot.cs b/src/GrillBot.Database/Migrations/GrillBotContextModelSnapshot.cs index d110d895..948b87c8 100644 --- a/src/GrillBot.Database/Migrations/GrillBotContextModelSnapshot.cs +++ b/src/GrillBot.Database/Migrations/GrillBotContextModelSnapshot.cs @@ -192,6 +192,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(30) .HasColumnType("character varying(30)"); + b.Property("AssociationRoleId") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + b.Property("BoosterRoleId") .HasMaxLength(30) .HasColumnType("character varying(30)");