diff --git a/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs b/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs index d094aacf7..952e326b0 100644 --- a/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs +++ b/src/NadekoBot.Generators/Command/CommandAttributesGenerator.cs @@ -171,6 +171,7 @@ public class CmdAttribute : System.Attribute foreach (var method in model.Methods) { tw.WriteLine("[NadekoCommand]"); + tw.WriteLine("[NadekoDescription]"); tw.WriteLine("[Aliases]"); tw.WriteLine($"public partial {method.ReturnType} {method.MethodName}({string.Join(", ", method.Params)});"); } diff --git a/src/NadekoBot.Tests/BotStringsTests.cs b/src/NadekoBot.Tests/BotStringsTests.cs index 8e609539e..87bbb5482 100644 --- a/src/NadekoBot.Tests/BotStringsTests.cs +++ b/src/NadekoBot.Tests/BotStringsTests.cs @@ -14,6 +14,7 @@ namespace NadekoBot.Tests private const string responsesPath = "../../../../NadekoBot/data/strings/responses"; private const string commandsPath = "../../../../NadekoBot/data/strings/commands"; private const string aliasesPath = "../../../../NadekoBot/data/aliases.yml"; + [Test] public void AllCommandNamesHaveStrings() { diff --git a/src/NadekoBot/.editorconfig b/src/NadekoBot/.editorconfig index e881fac07..cf85ce77f 100644 --- a/src/NadekoBot/.editorconfig +++ b/src/NadekoBot/.editorconfig @@ -337,6 +337,7 @@ resharper_csharp_wrap_parameters_style = chop_if_long resharper_force_chop_compound_if_expression = false resharper_keep_existing_linebreaks = false resharper_max_formal_parameters_on_line = 3 +resharper_place_simple_embedded_statement_on_same_line = false resharper_wrap_chained_binary_expressions = chop_if_long resharper_wrap_chained_binary_patterns = chop_if_long resharper_wrap_chained_method_calls = chop_if_long @@ -345,4 +346,4 @@ resharper_csharp_wrap_before_first_type_parameter_constraint = true resharper_csharp_place_type_constraints_on_same_line = false resharper_csharp_wrap_before_extends_colon = true resharper_csharp_place_constructor_initializer_on_same_line = false -resharper_force_attribute_style = separate \ No newline at end of file +resharper_force_attribute_style = separate diff --git a/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs b/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs index 70976f425..48d506d9c 100644 --- a/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs +++ b/src/NadekoBot/Common/Attributes/NadekoModuleAttribute.cs @@ -1,3 +1,5 @@ +using System.Runtime.CompilerServices; + namespace NadekoBot.Common.Attributes; [AttributeUsage(AttributeTargets.Class)] @@ -7,4 +9,22 @@ internal sealed class NadekoModuleAttribute : GroupAttribute : base(moduleName) { } +} + +[AttributeUsage(AttributeTargets.Method)] +internal sealed class NadekoDescriptionAttribute : SummaryAttribute +{ + public NadekoDescriptionAttribute([CallerMemberName] string name = "") + : base(name) + { + } +} + +[AttributeUsage(AttributeTargets.Method)] +internal sealed class NadekoUsageAttribute : RemarksAttribute +{ + public NadekoUsageAttribute([CallerMemberName] string name = "") + : base(name) + { + } } \ No newline at end of file diff --git a/src/NadekoBot/Common/TypeReaders/BotCommandTypeReader.cs b/src/NadekoBot/Common/TypeReaders/BotCommandTypeReader.cs index d24e16669..bc5c94131 100644 --- a/src/NadekoBot/Common/TypeReaders/BotCommandTypeReader.cs +++ b/src/NadekoBot/Common/TypeReaders/BotCommandTypeReader.cs @@ -1,5 +1,5 @@ #nullable disable -using NadekoBot.Modules.CustomReactions; +using NadekoBot.Modules.NadekoExpressions; namespace NadekoBot.Common.TypeReaders; @@ -35,12 +35,12 @@ public sealed class CommandOrCrTypeReader : NadekoTypeReader { private readonly CommandService _cmds; private readonly CommandHandler _commandHandler; - private readonly CustomReactionsService _crs; + private readonly NadekoExpressionsService _exprs; - public CommandOrCrTypeReader(CommandService cmds, CustomReactionsService crs, CommandHandler commandHandler) + public CommandOrCrTypeReader(CommandService cmds, NadekoExpressionsService exprs, CommandHandler commandHandler) { _cmds = cmds; - _crs = crs; + _exprs = exprs; _commandHandler = commandHandler; } @@ -48,7 +48,7 @@ public sealed class CommandOrCrTypeReader : NadekoTypeReader { input = input.ToUpperInvariant(); - if (_crs.ReactionExists(context.Guild?.Id, input)) + if (_exprs.ExpressionExists(context.Guild?.Id, input)) return TypeReaderResult.FromSuccess(new CommandOrCrInfo(input, CommandOrCrInfo.Type.Custom)); var cmd = await new CommandTypeReader(_commandHandler, _cmds).ReadAsync(context, input); diff --git a/src/NadekoBot/Common/TypeReaders/ModuleTypeReader.cs b/src/NadekoBot/Common/TypeReaders/ModuleTypeReader.cs index 026e87910..a463afaaf 100644 --- a/src/NadekoBot/Common/TypeReaders/ModuleTypeReader.cs +++ b/src/NadekoBot/Common/TypeReaders/ModuleTypeReader.cs @@ -34,7 +34,7 @@ public sealed class ModuleOrCrTypeReader : NadekoTypeReader var module = _cmds.Modules.GroupBy(m => m.GetTopLevelModule()) .FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input) ?.Key; - if (module is null && input != "ACTUALCUSTOMREACTIONS") + if (module is null && input != "ACTUALEXPRESSIONS") return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such module found.")); return Task.FromResult(TypeReaderResult.FromSuccess(new ModuleOrCrInfo { Name = input })); diff --git a/src/NadekoBot/Db/Extensions/CustomReactionsExtensions.cs b/src/NadekoBot/Db/Extensions/CustomReactionsExtensions.cs deleted file mode 100644 index bbdf21291..000000000 --- a/src/NadekoBot/Db/Extensions/CustomReactionsExtensions.cs +++ /dev/null @@ -1,18 +0,0 @@ -#nullable disable -using LinqToDB; -using Microsoft.EntityFrameworkCore; -using NadekoBot.Services.Database.Models; - -namespace NadekoBot.Db; - -public static class CustomReactionsExtensions -{ - public static int ClearFromGuild(this DbSet crs, ulong guildId) - => crs.Delete(x => x.GuildId == guildId); - - public static IEnumerable ForId(this DbSet crs, ulong id) - => crs.AsNoTracking().AsQueryable().Where(x => x.GuildId == id).ToList(); - - public static CustomReaction GetByGuildIdAndInput(this DbSet crs, ulong? guildId, string input) - => crs.FirstOrDefault(x => x.GuildId == guildId && x.Trigger.ToUpper() == input); -} \ No newline at end of file diff --git a/src/NadekoBot/Db/Extensions/NadekoExpressionExtensions.cs b/src/NadekoBot/Db/Extensions/NadekoExpressionExtensions.cs new file mode 100644 index 000000000..9a7b9877b --- /dev/null +++ b/src/NadekoBot/Db/Extensions/NadekoExpressionExtensions.cs @@ -0,0 +1,18 @@ +#nullable disable +using LinqToDB; +using Microsoft.EntityFrameworkCore; +using NadekoBot.Services.Database.Models; + +namespace NadekoBot.Db; + +public static class NadekoExpressionExtensions +{ + public static int ClearFromGuild(this DbSet exprs, ulong guildId) + => exprs.Delete(x => x.GuildId == guildId); + + public static IEnumerable ForId(this DbSet exprs, ulong id) + => exprs.AsNoTracking().AsQueryable().Where(x => x.GuildId == id).ToList(); + + public static CustomReaction GetByGuildIdAndInput(this DbSet exprs, ulong? guildId, string input) + => exprs.FirstOrDefault(x => x.GuildId == guildId && x.Trigger.ToUpper() == input); +} \ No newline at end of file diff --git a/src/NadekoBot/Db/NadekoContext.cs b/src/NadekoBot/Db/NadekoContext.cs index 07ae202a1..f26871a9e 100644 --- a/src/NadekoBot/Db/NadekoContext.cs +++ b/src/NadekoBot/Db/NadekoContext.cs @@ -34,7 +34,7 @@ public class NadekoContext : DbContext public DbSet Reminders { get; set; } public DbSet SelfAssignableRoles { get; set; } public DbSet MusicPlaylists { get; set; } - public DbSet CustomReactions { get; set; } + public DbSet Expressions { get; set; } public DbSet CurrencyTransactions { get; set; } public DbSet WaifuUpdates { get; set; } public DbSet Warnings { get; set; } @@ -62,6 +62,8 @@ public class NadekoContext : DbContext public DbSet NsfwBlacklistedTags { get; set; } public DbSet AutoTranslateChannels { get; set; } public DbSet AutoTranslateUsers { get; set; } + + public DbSet Permissions { get; set; } public NadekoContext(DbContextOptions options) : base(options) diff --git a/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.Designer.cs b/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.Designer.cs new file mode 100644 index 000000000..8f7662b9c --- /dev/null +++ b/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.Designer.cs @@ -0,0 +1,2726 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NadekoBot.Services.Database; + +#nullable disable + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoContext))] + [Migration("20220102102344_crs-rename-to-expressions-perm-rename")] + partial class crsrenametoexpressionspermrename + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("Discrim") + .HasColumnType("INTEGER"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("MinimumLevelReq") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("Name", "Discrim"); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now')"); + + b.Property("LastXpGain") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("datetime('now', '-1 years')"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("PunishDuration") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.Property("UserThreshold") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiRaidSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Mapping") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandAlias"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Url") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId1") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique(); + + b.ToTable("GroupName"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteByeMessages") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteGreetMessages") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("BoostMessage") + .HasColumnType("TEXT"); + + b.Property("BoostMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("INTEGER"); + + b.Property("ByeMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelByeMessageText") + .HasColumnType("TEXT"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DmGreetMessageText") + .HasColumnType("TEXT"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GreetMessageChannelId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("SendBoostMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelByeMessage") + .HasColumnType("INTEGER"); + + b.Property("SendChannelGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("SendDmGreetMessage") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .HasColumnType("INTEGER"); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklistedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Tag") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.ToTable("NsfwBlacklistedTags"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MusicPlaylistId") + .HasColumnType("INTEGER"); + + b.Property("Provider") + .HasColumnType("TEXT"); + + b.Property("ProviderType") + .HasColumnType("INTEGER"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Question") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("Poll"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollAnswer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("PollId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("VoteIndex") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollVote"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("EmoteName") + .HasColumnType("TEXT"); + + b.Property("ReactionRoleMessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ReactionRoleMessageId"); + + b.ToTable("ReactionRole"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Exclusive") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ReactionRoleMessage"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PatreonUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PatreonUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelRequirement") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValue(new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local)); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AwardedXp"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.HasIndex("Xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique(); + + b.ToTable("UserXpStats"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Db.Models.ClubInfo", "Club") + .WithMany("Users") + .HasForeignKey("ClubId"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiAltSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GroupName", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Answers") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Poll", null) + .WithMany("Votes") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ReactionRoleMessage", null) + .WithMany("ReactionRoles") + .HasForeignKey("ReactionRoleMessageId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleMessage", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("ReactionRoleMessages") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnbanTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.UnroleTimer", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo", null) + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("NadekoBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("ReactionRoleMessages"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Poll", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ReactionRoleMessage", b => + { + b.Navigation("ReactionRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.cs b/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.cs new file mode 100644 index 000000000..b3661603a --- /dev/null +++ b/src/NadekoBot/Migrations/20220102102344_crs-rename-to-expressions-perm-rename.cs @@ -0,0 +1,103 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace NadekoBot.Migrations +{ + public partial class crsrenametoexpressionspermrename : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Permissionv2_GuildConfigs_GuildConfigId", + table: "Permissionv2"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Permissionv2", + table: "Permissionv2"); + + migrationBuilder.DropPrimaryKey( + name: "PK_CustomReactions", + table: "CustomReactions"); + + migrationBuilder.RenameTable( + name: "Permissionv2", + newName: "Permissions"); + + migrationBuilder.RenameTable( + name: "CustomReactions", + newName: "Expressions"); + + migrationBuilder.RenameIndex( + name: "IX_Permissionv2_GuildConfigId", + table: "Permissions", + newName: "IX_Permissions_GuildConfigId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Permissions", + table: "Permissions", + column: "Id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Expressions", + table: "Expressions", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Permissions_GuildConfigs_GuildConfigId", + table: "Permissions", + column: "GuildConfigId", + principalTable: "GuildConfigs", + principalColumn: "Id"); + + migrationBuilder.Sql(@"UPDATE Permissions +SET SecondaryTargetName='ACTUALEXPRESSIONS' +WHERE SecondaryTargetName='ActualCustomReactions' COLLATE NOCASE;"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Permissions_GuildConfigs_GuildConfigId", + table: "Permissions"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Permissions", + table: "Permissions"); + + migrationBuilder.DropPrimaryKey( + name: "PK_Expressions", + table: "Expressions"); + + migrationBuilder.RenameTable( + name: "Permissions", + newName: "Permissionv2"); + + migrationBuilder.RenameTable( + name: "Expressions", + newName: "CustomReactions"); + + migrationBuilder.RenameIndex( + name: "IX_Permissions_GuildConfigId", + table: "Permissionv2", + newName: "IX_Permissionv2_GuildConfigId"); + + migrationBuilder.AddPrimaryKey( + name: "PK_Permissionv2", + table: "Permissionv2", + column: "Id"); + + migrationBuilder.AddPrimaryKey( + name: "PK_CustomReactions", + table: "CustomReactions", + column: "Id"); + + migrationBuilder.AddForeignKey( + name: "FK_Permissionv2_GuildConfigs_GuildConfigId", + table: "Permissionv2", + column: "GuildConfigId", + principalTable: "GuildConfigs", + principalColumn: "Id"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoContextModelSnapshot.cs index 7d7adb681..51de5e129 100644 --- a/src/NadekoBot/Migrations/NadekoContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoContextModelSnapshot.cs @@ -5,6 +5,8 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using NadekoBot.Services.Database; +#nullable disable + namespace NadekoBot.Migrations { [DbContext(typeof(NadekoContext))] @@ -13,8 +15,7 @@ namespace NadekoBot.Migrations protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "5.0.8"); + modelBuilder.HasAnnotation("ProductVersion", "6.0.1"); modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b => { @@ -549,7 +550,7 @@ namespace NadekoBot.Migrations b.HasKey("Id"); - b.ToTable("CustomReactions"); + b.ToTable("Expressions"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.DelMsgOnCmdChannel", b => @@ -681,28 +682,6 @@ namespace NadekoBot.Migrations b.ToTable("FilterChannelId"); }); - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("INTEGER"); - - b.Property("DateAdded") - .HasColumnType("TEXT"); - - b.Property("GuildConfigId") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("FilterLinksChannelId"); - }); - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => { b.Property("Id") @@ -725,6 +704,28 @@ namespace NadekoBot.Migrations b.ToTable("FilteredWord"); }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => { b.Property("Id") @@ -1177,7 +1178,7 @@ namespace NadekoBot.Migrations b.HasIndex("GuildConfigId"); - b.ToTable("Permissionv2"); + b.ToTable("Permissions"); }); modelBuilder.Entity("NadekoBot.Services.Database.Models.PlantedCurrency", b => @@ -2311,13 +2312,6 @@ namespace NadekoBot.Migrations .HasForeignKey("GuildConfigId1"); }); - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) - .WithMany("FilterLinksChannelIds") - .HasForeignKey("GuildConfigId"); - }); - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => { b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) @@ -2325,6 +2319,13 @@ namespace NadekoBot.Migrations .HasForeignKey("GuildConfigId"); }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => { b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig") @@ -2629,14 +2630,14 @@ namespace NadekoBot.Migrations b.Navigation("FeedSubs"); - b.Navigation("FilteredWords"); - b.Navigation("FilterInvitesChannelIds"); b.Navigation("FilterLinksChannelIds"); b.Navigation("FilterWordsChannelIds"); + b.Navigation("FilteredWords"); + b.Navigation("FollowedStreams"); b.Navigation("GenerateCurrencyChannelIds"); diff --git a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs index 6bad4b7fb..c267778cf 100644 --- a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs +++ b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommands.cs @@ -110,7 +110,7 @@ namespace NadekoBot.Modules.Administration //[NadekoCommand, Usage, Description, Aliases] //[OwnerOnly] //public partial Task DeleteUnusedCrnQ() => - // SqlExec(DangerousCommandsService.DeleteUnusedCustomReactionsAndQuotes); + // SqlExec(DangerousCommandsService.DeleteUnusedExpressionsAndQuotes); } } } diff --git a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommandsService.cs b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommandsService.cs index e49d8e4af..6264852f2 100644 --- a/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommandsService.cs +++ b/src/NadekoBot/Modules/Administration/DangerousCommands/DangerousCommandsService.cs @@ -31,7 +31,7 @@ SET ClubId=NULL, DELETE FROM ClubApplicants; DELETE FROM ClubBans; DELETE FROM Clubs;"; -// public const string DeleteUnusedCustomReactionsAndQuotes = @"DELETE FROM CustomReactions +// public const string DeleteUnusedExpressionsAndQuotes = @"DELETE FROM Expressions //WHERE UseCount=0 AND (DateAdded < date('now', '-7 day') OR DateAdded is null); //DELETE FROM Quotes diff --git a/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs b/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs index 4f6a0f14e..63fdbc988 100644 --- a/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs +++ b/src/NadekoBot/Modules/CustomReactions/ExportedExpr.cs @@ -1,7 +1,7 @@ #nullable disable using NadekoBot.Services.Database.Models; -namespace NadekoBot.Modules.CustomReactions; +namespace NadekoBot.Modules.NadekoExpressions; public class ExportedExpr { diff --git a/src/NadekoBot/Modules/CustomReactions/ExprField.cs b/src/NadekoBot/Modules/CustomReactions/ExprField.cs new file mode 100644 index 000000000..c22b39f7d --- /dev/null +++ b/src/NadekoBot/Modules/CustomReactions/ExprField.cs @@ -0,0 +1,10 @@ +namespace NadekoBot.Modules.NadekoExpressions; + +public enum ExprField +{ + AutoDelete, + DmResponse, + AllowTarget, + ContainsAnywhere, + Message +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactionExtensions.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionExtensions.cs similarity index 96% rename from src/NadekoBot/Modules/CustomReactions/CustomReactionExtensions.cs rename to src/NadekoBot/Modules/CustomReactions/NadekoExpressionExtensions.cs index cfebc9122..1a266778e 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactionExtensions.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionExtensions.cs @@ -2,9 +2,9 @@ using NadekoBot.Services.Database.Models; using System.Runtime.CompilerServices; -namespace NadekoBot.Modules.CustomReactions; +namespace NadekoBot.Modules.NadekoExpressions; -public static class CustomReactionExtensions +public static class NadekoExpressionExtensions { private static string ResolveTriggerString(this string str, DiscordSocketClient client) => str.Replace("%bot.mention%", client.CurrentUser.Mention, StringComparison.Ordinal); diff --git a/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs index 9ace7bf7b..a9819660e 100644 --- a/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressions.cs @@ -1,8 +1,11 @@ #nullable disable -namespace NadekoBot.Modules.CustomReactions; +namespace NadekoBot.Modules.NadekoExpressions; -public partial class NadekoExpressions : NadekoModule +// todo string.join to .Join(", ") + +[Name("Expressions")] +public partial class NadekoExpressions : NadekoModule { public enum All { @@ -23,7 +26,7 @@ public partial class NadekoExpressions : NadekoModule || (ctx.Guild is not null && ((IGuildUser)ctx.User).GuildPermissions.Administrator); [Cmd] - public async partial Task AddCustReact(string key, [Leftover] string message) + public async partial Task ExprAdd(string key, [Leftover] string message) { if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key)) return; @@ -34,19 +37,19 @@ public partial class NadekoExpressions : NadekoModule return; } - var cr = await _service.AddAsync(ctx.Guild?.Id, key, message); + var ex = await _service.AddAsync(ctx.Guild?.Id, key, message); await ctx.Channel.EmbedAsync(_eb.Create() .WithOkColor() .WithTitle(GetText(strs.new_cust_react)) - .WithDescription($"#{cr.Id}") + .WithDescription($"#{ex.Id}") .AddField(GetText(strs.trigger), key) .AddField(GetText(strs.response), message.Length > 1024 ? GetText(strs.redacted_too_long) : message)); } [Cmd] - public async partial Task EditCustReact(kwum id, [Leftover] string message) + public async partial Task ExprEdit(kwum id, [Leftover] string message) { var channel = ctx.Channel as ITextChannel; if (string.IsNullOrWhiteSpace(message) || id < 0) @@ -59,13 +62,13 @@ public partial class NadekoExpressions : NadekoModule return; } - var cr = await _service.EditAsync(ctx.Guild?.Id, id, message); - if (cr is not null) + var ex = await _service.EditAsync(ctx.Guild?.Id, id, message); + if (ex is not null) await ctx.Channel.EmbedAsync(_eb.Create() .WithOkColor() .WithTitle(GetText(strs.edited_cust_react)) .WithDescription($"#{id}") - .AddField(GetText(strs.trigger), cr.Trigger) + .AddField(GetText(strs.trigger), ex.Trigger) .AddField(GetText(strs.response), message.Length > 1024 ? GetText(strs.redacted_too_long) : message)); else @@ -74,14 +77,14 @@ public partial class NadekoExpressions : NadekoModule [Cmd] [Priority(1)] - public async partial Task ListCustReact(int page = 1) + public async partial Task ExprList(int page = 1) { if (--page < 0 || page > 999) return; - var customReactions = _service.GetCustomReactionsFor(ctx.Guild?.Id); + var expressions = _service.GetExpressionsFor(ctx.Guild?.Id); - if (customReactions is null || !customReactions.Any()) + if (expressions is null || !expressions.Any()) { await ReplyErrorLocalizedAsync(strs.no_found); return; @@ -90,28 +93,28 @@ public partial class NadekoExpressions : NadekoModule await ctx.SendPaginatedConfirmAsync(page, curPage => { - var desc = customReactions.OrderBy(cr => cr.Trigger) + var desc = expressions.OrderBy(ex => ex.Trigger) .Skip(curPage * 20) .Take(20) - .Select(cr => $"{(cr.ContainsAnywhere ? "🗯" : "◾")}" - + $"{(cr.DmResponse ? "✉" : "◾")}" - + $"{(cr.AutoDeleteTrigger ? "❌" : "◾")}" - + $"`{(kwum)cr.Id}` {cr.Trigger}" - + (string.IsNullOrWhiteSpace(cr.Reactions) + .Select(ex => $"{(ex.ContainsAnywhere ? "🗯" : "◾")}" + + $"{(ex.DmResponse ? "✉" : "◾")}" + + $"{(ex.AutoDeleteTrigger ? "❌" : "◾")}" + + $"`{(kwum)ex.Id}` {ex.Trigger}" + + (string.IsNullOrWhiteSpace(ex.Reactions) ? string.Empty - : " // " + string.Join(" ", cr.GetReactions()))) + : " // " + string.Join(" ", ex.GetReactions()))) .Join('\n'); return _eb.Create().WithOkColor().WithTitle(GetText(strs.custom_reactions)).WithDescription(desc); }, - customReactions.Length, + expressions.Length, 20); } [Cmd] - public async partial Task ShowCustReact(kwum id) + public async partial Task ExprShow(kwum id) { - var found = _service.GetCustomReaction(ctx.Guild?.Id, id); + var found = _service.GetExpression(ctx.Guild?.Id, id); if (found is null) { @@ -128,7 +131,7 @@ public partial class NadekoExpressions : NadekoModule } [Cmd] - public async partial Task DelCustReact(kwum id) + public async partial Task ExprDelete(kwum id) { if (!AdminInGuildOrOwnerInDm()) { @@ -136,21 +139,21 @@ public partial class NadekoExpressions : NadekoModule return; } - var cr = await _service.DeleteAsync(ctx.Guild?.Id, id); + var ex = await _service.DeleteAsync(ctx.Guild?.Id, id); - if (cr is not null) + if (ex is not null) await ctx.Channel.EmbedAsync(_eb.Create() .WithOkColor() .WithTitle(GetText(strs.deleted)) .WithDescription($"#{id}") - .AddField(GetText(strs.trigger), cr.Trigger.TrimTo(1024)) - .AddField(GetText(strs.response), cr.Response.TrimTo(1024))); + .AddField(GetText(strs.trigger), ex.Trigger.TrimTo(1024)) + .AddField(GetText(strs.response), ex.Response.TrimTo(1024))); else await ReplyErrorLocalizedAsync(strs.no_found_id); } [Cmd] - public async partial Task CrReact(kwum id, params string[] emojiStrs) + public async partial Task ExprReact(kwum id, params string[] emojiStrs) { if (!AdminInGuildOrOwnerInDm()) { @@ -158,8 +161,8 @@ public partial class NadekoExpressions : NadekoModule return; } - var cr = _service.GetCustomReaction(ctx.Guild?.Id, id); - if (cr is null) + var ex = _service.GetExpression(ctx.Guild?.Id, id); + if (ex is null) { await ReplyErrorLocalizedAsync(strs.no_found); return; @@ -167,7 +170,7 @@ public partial class NadekoExpressions : NadekoModule if (emojiStrs.Length == 0) { - await _service.ResetCrReactions(ctx.Guild?.Id, id); + await _service.ResetExprReactions(ctx.Guild?.Id, id); await ReplyConfirmLocalizedAsync(strs.crr_reset(Format.Bold(id.ToString()))); return; } @@ -196,39 +199,39 @@ public partial class NadekoExpressions : NadekoModule return; } - await _service.SetCrReactions(ctx.Guild?.Id, id, succ); + await _service.SetExprReactions(ctx.Guild?.Id, id, succ); await ReplyConfirmLocalizedAsync(strs.crr_set(Format.Bold(id.ToString()), - string.Join(", ", succ.Select(x => x.ToString())))); + succ.Select(static x => x.ToString()).Join(", "))); } [Cmd] - public partial Task CrCa(kwum id) - => InternalCrEdit(id, CustomReactionsService.CrField.ContainsAnywhere); + public partial Task ExprCa(kwum id) + => InternalExprEdit(id, ExprField.ContainsAnywhere); [Cmd] - public partial Task CrDm(kwum id) - => InternalCrEdit(id, CustomReactionsService.CrField.DmResponse); + public partial Task ExprDm(kwum id) + => InternalExprEdit(id, ExprField.DmResponse); [Cmd] - public partial Task CrAd(kwum id) - => InternalCrEdit(id, CustomReactionsService.CrField.AutoDelete); + public partial Task ExprAd(kwum id) + => InternalExprEdit(id, ExprField.AutoDelete); [Cmd] - public partial Task CrAt(kwum id) - => InternalCrEdit(id, CustomReactionsService.CrField.AllowTarget); + public partial Task ExprAt(kwum id) + => InternalExprEdit(id, ExprField.AllowTarget); [Cmd] [OwnerOnly] - public async partial Task CrsReload() + public async partial Task ExprsReload() { - await _service.TriggerReloadCustomReactions(); + await _service.TriggerReloadExpressions(); await ctx.OkAsync(); } - private async Task InternalCrEdit(kwum id, CustomReactionsService.CrField option) + private async Task InternalExprEdit(kwum id, ExprField option) { if (!AdminInGuildOrOwnerInDm()) { @@ -236,7 +239,7 @@ public partial class NadekoExpressions : NadekoModule return; } - var (success, newVal) = await _service.ToggleCrOptionAsync(id, option); + var (success, newVal) = await _service.ToggleExprOptionAsync(id, option); if (!success) { await ReplyErrorLocalizedAsync(strs.no_found_id); @@ -254,19 +257,19 @@ public partial class NadekoExpressions : NadekoModule [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.Administrator)] - public async partial Task CrClear() + public async partial Task ExprClear() { if (await PromptUserConfirmAsync(_eb.Create() .WithTitle("Custom reaction clear") .WithDescription("This will delete all custom reactions on this server."))) { - var count = _service.DeleteAllCustomReactions(ctx.Guild.Id); + var count = _service.DeleteAllExpressions(ctx.Guild.Id); await ReplyConfirmLocalizedAsync(strs.cleared(count)); } } [Cmd] - public async partial Task CrsExport() + public async partial Task ExprsExport() { if (!AdminInGuildOrOwnerInDm()) { @@ -276,16 +279,16 @@ public partial class NadekoExpressions : NadekoModule _ = ctx.Channel.TriggerTypingAsync(); - var serialized = _service.ExportCrs(ctx.Guild?.Id); + var serialized = _service.ExportExpressions(ctx.Guild?.Id); await using var stream = await serialized.ToStream(); - await ctx.Channel.SendFileAsync(stream, "crs-export.yml"); + await ctx.Channel.SendFileAsync(stream, "exprs-export.yml"); } [Cmd] #if GLOBAL_NADEKO - [OwnerOnly] + [OwnerOnly] #endif - public async partial Task CrsImport([Leftover] string input = null) + public async partial Task ExprsImport([Leftover] string input = null) { if (!AdminInGuildOrOwnerInDm()) { @@ -316,7 +319,7 @@ public partial class NadekoExpressions : NadekoModule } } - var succ = await _service.ImportCrsAsync(ctx.Guild?.Id, input); + var succ = await _service.ImportExpressionsAsync(ctx.Guild?.Id, input); if (!succ) { await ReplyErrorLocalizedAsync(strs.expr_import_invalid_data); diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactionsService.cs b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs similarity index 56% rename from src/NadekoBot/Modules/CustomReactions/CustomReactionsService.cs rename to src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs index c04e564b6..8cd85dac7 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactionsService.cs +++ b/src/NadekoBot/Modules/CustomReactions/NadekoExpressionsService.cs @@ -10,33 +10,28 @@ using System.Runtime.CompilerServices; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; -namespace NadekoBot.Modules.CustomReactions; +namespace NadekoBot.Modules.NadekoExpressions; -public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor +// todo recheck whether ACTUALEXPRESSIONS perm works +// todo run db migration and rename ACTUALCUSTOMREACTIONS to ACTUALEXPRESSIONS + +public sealed class NadekoExpressionsService : IEarlyBehavior, IReadyExecutor { - public enum CrField - { - AutoDelete, - DmResponse, - AllowTarget, - ContainsAnywhere, - Message - } - private const string MentionPh = "%bot.mention%"; + private const string MENTION_PH = "%bot.mention%"; - private const string _prependExport = - @"# Keys are triggers, Each key has a LIST of custom reactions in the following format: + private const string PREPEND_EXPORT = + @"# Keys are triggers, Each key has a LIST of expressions in the following format: # - res: Response string -# id: Alphanumeric id used for commands related to the custom reaction. (Note, when using .crsimport, a new id will be generated.) +# id: Alphanumeric id used for commands related to the expression. (Note, when using .exprsimport, a new id will be generated.) # react: # - -# at: Whether custom reaction allows targets (see .h .crat) -# ca: Whether custom reaction expects trigger anywhere (see .h .crca) -# dm: Whether custom reaction DMs the response (see .h .crdm) -# ad: Whether custom reaction automatically deletes triggering message (see .h .crad) +# at: Whether expression allows targets (see .h .exprat) +# ca: Whether expression expects trigger anywhere (see .h .exprca) +# dm: Whether expression DMs the response (see .h .exprdm) +# ad: Whether expression automatically deletes triggering message (see .h .exprad) "; @@ -53,19 +48,19 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor public int Priority => 0; - private readonly object _gcrWriteLock = new(); + private readonly object _gexprWriteLock = new(); - private readonly TypedKey _gcrAddedKey = new("gcr.added"); - private readonly TypedKey _gcrDeletedkey = new("gcr.deleted"); - private readonly TypedKey _gcrEditedKey = new("gcr.edited"); - private readonly TypedKey _crsReloadedKey = new("crs.reloaded"); + private readonly TypedKey _gexprAddedKey = new("gexpr.added"); + private readonly TypedKey _gexprDeletedkey = new("gexpr.deleted"); + private readonly TypedKey _gexprEditedKey = new("gexpr.edited"); + private readonly TypedKey _exprsReloadedKey = new("exprs.reloaded"); - // it is perfectly fine to have global customreactions as an array - // 1. custom reactions are almost never added (compared to how many times they are being looped through) + // it is perfectly fine to have global expressions as an array + // 1. expressions are almost never added (compared to how many times they are being looped through) // 2. only need write locks for this as we'll rebuild+replace the array on every edit // 3. there's never many of them (at most a thousand, usually < 100) - private CustomReaction[] _globalReactions; - private ConcurrentDictionary _newGuildReactions; + private CustomReaction[] globalReactions; + private ConcurrentDictionary newGuildReactions; private readonly DbService _db; private readonly DiscordSocketClient _client; @@ -81,7 +76,7 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor private bool ready; - public CustomReactionsService( + public NadekoExpressionsService( PermissionService perms, DbService db, IBotStrings strings, @@ -105,10 +100,10 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor _eb = eb; _rng = new NadekoRandom(); - _pubSub.Sub(_crsReloadedKey, OnCrsShouldReload); - pubSub.Sub(_gcrAddedKey, OnGcrAdded); - pubSub.Sub(_gcrDeletedkey, OnGcrDeleted); - pubSub.Sub(_gcrEditedKey, OnGcrEdited); + _pubSub.Sub(_exprsReloadedKey, OnExprsShouldReload); + pubSub.Sub(_gexprAddedKey, OnGexprAdded); + pubSub.Sub(_gexprDeletedkey, OnGexprDeleted); + pubSub.Sub(_gexprEditedKey, OnGexprEdited); bot.JoinedGuild += OnJoinedGuild; _client.LeftGuild += OnLeftGuild; @@ -117,39 +112,39 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor private async Task ReloadInternal(IReadOnlyList allGuildIds) { await using var uow = _db.GetDbContext(); - var guildItems = await uow.CustomReactions.AsNoTracking() + var guildItems = await uow.Expressions.AsNoTracking() .Where(x => allGuildIds.Contains(x.GuildId.Value)) .ToListAsync(); - _newGuildReactions = guildItems.GroupBy(k => k.GuildId!.Value) + newGuildReactions = guildItems.GroupBy(k => k.GuildId!.Value) .ToDictionary(g => g.Key, g => g.Select(x => { - x.Trigger = x.Trigger.Replace(MentionPh, _bot.Mention); + x.Trigger = x.Trigger.Replace(MENTION_PH, _bot.Mention); return x; }) .ToArray()) .ToConcurrent(); - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - var globalItems = uow.CustomReactions.AsNoTracking() + var globalItems = uow.Expressions.AsNoTracking() .Where(x => x.GuildId == null || x.GuildId == 0) .AsEnumerable() .Select(x => { - x.Trigger = x.Trigger.Replace(MentionPh, _bot.Mention); + x.Trigger = x.Trigger.Replace(MENTION_PH, _bot.Mention); return x; }) .ToArray(); - _globalReactions = globalItems; + globalReactions = globalItems; } ready = true; } - private CustomReaction TryGetCustomReaction(IUserMessage umsg) + private CustomReaction TryGetExpression(IUserMessage umsg) { if (!ready) return null; @@ -159,37 +154,37 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor var content = umsg.Content.Trim().ToLowerInvariant(); - if (_newGuildReactions.TryGetValue(channel.Guild.Id, out var reactions) && reactions.Length > 0) + if (newGuildReactions.TryGetValue(channel.Guild.Id, out var reactions) && reactions.Length > 0) { - var cr = MatchCustomReactions(content, reactions); - if (cr is not null) - return cr; + var expr = MatchExpressions(content, reactions); + if (expr is not null) + return expr; } - var localGrs = _globalReactions; + var localGrs = globalReactions; - return MatchCustomReactions(content, localGrs); + return MatchExpressions(content, localGrs); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private CustomReaction MatchCustomReactions(in ReadOnlySpan content, CustomReaction[] crs) + private CustomReaction MatchExpressions(in ReadOnlySpan content, CustomReaction[] exprs) { var result = new List(1); - for (var i = 0; i < crs.Length; i++) + for (var i = 0; i < exprs.Length; i++) { - var cr = crs[i]; - var trigger = cr.Trigger; + var expr = exprs[i]; + var trigger = expr.Trigger; if (content.Length > trigger.Length) { // if input is greater than the trigger, it can only work if: // it has CA enabled - if (cr.ContainsAnywhere) + if (expr.ContainsAnywhere) { // if ca is enabled, we have to check if it is a word within the content var wp = content.GetWordPosition(trigger); // if it is, then that's valid - if (wp != WordPosition.None) result.Add(cr); + if (wp != WordPosition.None) result.Add(expr); // if it's not, then it cant' work under any circumstance, // because content is greater than the trigger length @@ -199,12 +194,12 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor // if CA is disabled, and CR has AllowTarget, then the // content has to start with the trigger followed by a space - if (cr.AllowTarget + if (expr.AllowTarget && content.StartsWith(trigger, StringComparison.OrdinalIgnoreCase) && content[trigger.Length] == ' ') - result.Add(cr); + result.Add(expr); } - else if (content.Length < cr.Trigger.Length) + else if (content.Length < expr.Trigger.Length) { // if input length is less than trigger length, it means // that the reaction can never be triggered @@ -213,7 +208,7 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor { // if input length is the same as trigger length // reaction can only trigger if the strings are equal - if (content.SequenceEqual(cr.Trigger)) result.Add(cr); + if (content.SequenceEqual(expr.Trigger)) result.Add(expr); } } @@ -229,21 +224,21 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor public async Task RunBehavior(IGuild guild, IUserMessage msg) { - // maybe this message is a custom reaction - var cr = TryGetCustomReaction(msg); + // maybe this message is an expression + var expr = TryGetExpression(msg); - if (cr is null || cr.Response == "-") + if (expr is null || expr.Response == "-") return false; - if (await _cmdCds.TryBlock(guild, msg.Author, cr.Trigger)) + if (await _cmdCds.TryBlock(guild, msg.Author, expr.Trigger)) return false; try { - if (_gperm.BlockedModules.Contains("ActualCustomReactions")) + if (_gperm.BlockedModules.Contains("ACTUALEXPRESSIONS")) { Log.Information( - "User {UserName} [{UserId}] tried to use a custom reaction but 'ActualCustomReactions' are globally disabled.", + "User {UserName} [{UserId}] tried to use an expression but 'ActualExpressions' are globally disabled", msg.Author.ToString(), msg.Author.Id); @@ -253,7 +248,7 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor if (guild is SocketGuild sg) { var pc = _perms.GetCacheFor(guild.Id); - if (!pc.Permissions.CheckPermissions(msg, cr.Trigger, "ActualCustomReactions", out var index)) + if (!pc.Permissions.CheckPermissions(msg, expr.Trigger, "ACTUALEXPRESSIONS", out var index)) { if (pc.Verbose) { @@ -276,9 +271,9 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor } } - var sentMsg = await cr.Send(msg, _client, false); + var sentMsg = await expr.Send(msg, _client, false); - var reactions = cr.GetReactions(); + var reactions = expr.GetReactions(); foreach (var reaction in reactions) { try @@ -289,14 +284,14 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor { Log.Warning("Unable to add reactions to message {Message} in server {GuildId}", sentMsg.Id, - cr.GuildId); + expr.GuildId); break; } await Task.Delay(1000); } - if (cr.AutoDeleteTrigger) + if (expr.AutoDeleteTrigger) try { await msg.DeleteAsync(); @@ -310,7 +305,7 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor msg.Channel.Id, msg.Author.Id, msg.Author.ToString(), - cr.Trigger); + expr.Trigger); return true; } @@ -322,61 +317,61 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor return false; } - public async Task ResetCrReactions(ulong? maybeGuildId, int id) + public async Task ResetExprReactions(ulong? maybeGuildId, int id) { - CustomReaction cr; + CustomReaction expr; await using var uow = _db.GetDbContext(); - cr = uow.CustomReactions.GetById(id); - if (cr is null) + expr = uow.Expressions.GetById(id); + if (expr is null) return; - cr.Reactions = string.Empty; + expr.Reactions = string.Empty; await uow.SaveChangesAsync(); } - private Task UpdateInternalAsync(ulong? maybeGuildId, CustomReaction cr) + private Task UpdateInternalAsync(ulong? maybeGuildId, CustomReaction expr) { if (maybeGuildId is { } guildId) - UpdateInternal(guildId, cr); + UpdateInternal(guildId, expr); else - return _pubSub.Pub(_gcrEditedKey, cr); + return _pubSub.Pub(_gexprEditedKey, expr); return Task.CompletedTask; } - private void UpdateInternal(ulong? maybeGuildId, CustomReaction cr) + private void UpdateInternal(ulong? maybeGuildId, CustomReaction expr) { if (maybeGuildId is { } guildId) - _newGuildReactions.AddOrUpdate(guildId, - new[] { cr }, + newGuildReactions.AddOrUpdate(guildId, + new[] { expr }, (_, old) => { var newArray = old.ToArray(); for (var i = 0; i < newArray.Length; i++) - if (newArray[i].Id == cr.Id) - newArray[i] = cr; + if (newArray[i].Id == expr.Id) + newArray[i] = expr; return newArray; }); else - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - var crs = _globalReactions; - for (var i = 0; i < crs.Length; i++) - if (crs[i].Id == cr.Id) - crs[i] = cr; + var exprs = globalReactions; + for (var i = 0; i < exprs.Length; i++) + if (exprs[i].Id == expr.Id) + exprs[i] = expr; } } - private Task AddInternalAsync(ulong? maybeGuildId, CustomReaction cr) + private Task AddInternalAsync(ulong? maybeGuildId, CustomReaction expr) { // only do this for perf purposes - cr.Trigger = cr.Trigger.Replace(MentionPh, _client.CurrentUser.Mention); + expr.Trigger = expr.Trigger.Replace(MENTION_PH, _client.CurrentUser.Mention); if (maybeGuildId is { } guildId) - _newGuildReactions.AddOrUpdate(guildId, new[] { cr }, (_, old) => old.With(cr)); + newGuildReactions.AddOrUpdate(guildId, new[] { expr }, (_, old) => old.With(expr)); else - return _pubSub.Pub(_gcrAddedKey, cr); + return _pubSub.Pub(_gexprAddedKey, expr); return Task.CompletedTask; } @@ -385,125 +380,128 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor { if (maybeGuildId is { } guildId) { - _newGuildReactions.AddOrUpdate(guildId, + newGuildReactions.AddOrUpdate(guildId, Array.Empty(), (key, old) => DeleteInternal(old, id, out _)); return Task.CompletedTask; } - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - var cr = Array.Find(_globalReactions, item => item.Id == id); - if (cr is not null) return _pubSub.Pub(_gcrDeletedkey, cr.Id); + var expr = Array.Find(globalReactions, item => item.Id == id); + if (expr is not null) return _pubSub.Pub(_gexprDeletedkey, expr.Id); } return Task.CompletedTask; } - private CustomReaction[] DeleteInternal(IReadOnlyList crs, int id, out CustomReaction deleted) + private CustomReaction[] DeleteInternal( + IReadOnlyList exprs, + int id, + out CustomReaction deleted) { deleted = null; - if (crs is null || crs.Count == 0) - return crs as CustomReaction[] ?? crs?.ToArray(); + if (exprs is null || exprs.Count == 0) + return exprs as CustomReaction[] ?? exprs?.ToArray(); - var newCrs = new CustomReaction[crs.Count - 1]; - for (int i = 0, k = 0; i < crs.Count; i++, k++) + var newExprs = new CustomReaction[exprs.Count - 1]; + for (int i = 0, k = 0; i < exprs.Count; i++, k++) { - if (crs[i].Id == id) + if (exprs[i].Id == id) { - deleted = crs[i]; + deleted = exprs[i]; k--; continue; } - newCrs[k] = crs[i]; + newExprs[k] = exprs[i]; } - return newCrs; + return newExprs; } - public async Task SetCrReactions(ulong? guildId, int id, IEnumerable emojis) + public async Task SetExprReactions(ulong? guildId, int id, IEnumerable emojis) { - CustomReaction cr; + CustomReaction expr; await using (var uow = _db.GetDbContext()) { - cr = uow.CustomReactions.GetById(id); - if (cr is null) + expr = uow.Expressions.GetById(id); + if (expr is null) return; - cr.Reactions = string.Join("@@@", emojis); + expr.Reactions = string.Join("@@@", emojis); await uow.SaveChangesAsync(); } - await UpdateInternalAsync(guildId, cr); + await UpdateInternalAsync(guildId, expr); } - public async Task<(bool Sucess, bool NewValue)> ToggleCrOptionAsync(int id, CrField field) + public async Task<(bool Sucess, bool NewValue)> ToggleExprOptionAsync(int id, ExprField field) { var newVal = false; - CustomReaction cr; + CustomReaction expr; await using (var uow = _db.GetDbContext()) { - cr = uow.CustomReactions.GetById(id); - if (cr is null) + expr = uow.Expressions.GetById(id); + if (expr is null) return (false, false); - if (field == CrField.AutoDelete) - newVal = cr.AutoDeleteTrigger = !cr.AutoDeleteTrigger; - else if (field == CrField.ContainsAnywhere) - newVal = cr.ContainsAnywhere = !cr.ContainsAnywhere; - else if (field == CrField.DmResponse) - newVal = cr.DmResponse = !cr.DmResponse; - else if (field == CrField.AllowTarget) - newVal = cr.AllowTarget = !cr.AllowTarget; + if (field == ExprField.AutoDelete) + newVal = expr.AutoDeleteTrigger = !expr.AutoDeleteTrigger; + else if (field == ExprField.ContainsAnywhere) + newVal = expr.ContainsAnywhere = !expr.ContainsAnywhere; + else if (field == ExprField.DmResponse) + newVal = expr.DmResponse = !expr.DmResponse; + else if (field == ExprField.AllowTarget) + newVal = expr.AllowTarget = !expr.AllowTarget; await uow.SaveChangesAsync(); } - await UpdateInternalAsync(cr.GuildId, cr); + await UpdateInternalAsync(expr.GuildId, expr); return (true, newVal); } - public CustomReaction GetCustomReaction(ulong? guildId, int id) + public CustomReaction GetExpression(ulong? guildId, int id) { using var uow = _db.GetDbContext(); - var cr = uow.CustomReactions.GetById(id); - if (cr is null || cr.GuildId != guildId) + var expr = uow.Expressions.GetById(id); + if (expr is null || expr.GuildId != guildId) return null; - return cr; + return expr; } - public int DeleteAllCustomReactions(ulong guildId) + public int DeleteAllExpressions(ulong guildId) { using var uow = _db.GetDbContext(); - var count = uow.CustomReactions.ClearFromGuild(guildId); + var count = uow.Expressions.ClearFromGuild(guildId); uow.SaveChanges(); - _newGuildReactions.TryRemove(guildId, out _); + newGuildReactions.TryRemove(guildId, out _); return count; } - public bool ReactionExists(ulong? guildId, string input) + public bool ExpressionExists(ulong? guildId, string input) { using var uow = _db.GetDbContext(); - var cr = uow.CustomReactions.GetByGuildIdAndInput(guildId, input); - return cr is not null; + var expr = uow.Expressions.GetByGuildIdAndInput(guildId, input); + return expr is not null; } - public string ExportCrs(ulong? guildId) + public string ExportExpressions(ulong? guildId) { - var crs = GetCustomReactionsFor(guildId); + var exprs = GetExpressionsFor(guildId); - var crsDict = crs.GroupBy(x => x.Trigger).ToDictionary(x => x.Key, x => x.Select(ExportedExpr.FromModel)); + var exprsDict = exprs.GroupBy(x => x.Trigger).ToDictionary(x => x.Key, x => x.Select(ExportedExpr.FromModel)); - return _prependExport + _exportSerializer.Serialize(crsDict).UnescapeUnicodeCodePoints(); + return PREPEND_EXPORT + _exportSerializer.Serialize(exprsDict).UnescapeUnicodeCodePoints(); } - public async Task ImportCrsAsync(ulong? guildId, string input) + public async Task ImportExpressionsAsync(ulong? guildId, string input) { Dictionary> data; try @@ -521,22 +519,22 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor foreach (var entry in data) { var trigger = entry.Key; - await uow.CustomReactions.AddRangeAsync(entry.Value.Where(cr => !string.IsNullOrWhiteSpace(cr.Res)) - .Select(cr => new CustomReaction + await uow.Expressions.AddRangeAsync(entry.Value.Where(expr => !string.IsNullOrWhiteSpace(expr.Res)) + .Select(expr => new CustomReaction { GuildId = guildId, - Response = cr.Res, - Reactions = cr.React?.Join("@@@"), + Response = expr.Res, + Reactions = expr.React?.Join("@@@"), Trigger = trigger, - AllowTarget = cr.At, - ContainsAnywhere = cr.Ca, - DmResponse = cr.Dm, - AutoDeleteTrigger = cr.Ad + AllowTarget = expr.At, + ContainsAnywhere = expr.Ca, + DmResponse = expr.Dm, + AutoDeleteTrigger = expr.Ad })); } await uow.SaveChangesAsync(); - await TriggerReloadCustomReactions(); + await TriggerReloadExpressions(); return true; } @@ -545,54 +543,54 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor public Task OnReadyAsync() => ReloadInternal(_bot.GetCurrentGuildIds()); - private ValueTask OnCrsShouldReload(bool _) + private ValueTask OnExprsShouldReload(bool _) => new(ReloadInternal(_bot.GetCurrentGuildIds())); - private ValueTask OnGcrAdded(CustomReaction c) + private ValueTask OnGexprAdded(CustomReaction c) { - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - var newGlobalReactions = new CustomReaction[_globalReactions.Length + 1]; - Array.Copy(_globalReactions, newGlobalReactions, _globalReactions.Length); - newGlobalReactions[_globalReactions.Length] = c; - _globalReactions = newGlobalReactions; + var newGlobalReactions = new CustomReaction[globalReactions.Length + 1]; + Array.Copy(globalReactions, newGlobalReactions, globalReactions.Length); + newGlobalReactions[globalReactions.Length] = c; + globalReactions = newGlobalReactions; } return default; } - private ValueTask OnGcrEdited(CustomReaction c) + private ValueTask OnGexprEdited(CustomReaction c) { - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - for (var i = 0; i < _globalReactions.Length; i++) - if (_globalReactions[i].Id == c.Id) + for (var i = 0; i < globalReactions.Length; i++) + if (globalReactions[i].Id == c.Id) { - _globalReactions[i] = c; + globalReactions[i] = c; return default; } - // if edited cr is not found?! + // if edited expr is not found?! // add it - OnGcrAdded(c); + OnGexprAdded(c); } return default; } - private ValueTask OnGcrDeleted(int id) + private ValueTask OnGexprDeleted(int id) { - lock (_gcrWriteLock) + lock (_gexprWriteLock) { - var newGlobalReactions = DeleteInternal(_globalReactions, id, out _); - _globalReactions = newGlobalReactions; + var newGlobalReactions = DeleteInternal(globalReactions, id, out _); + globalReactions = newGlobalReactions; } return default; } - public Task TriggerReloadCustomReactions() - => _pubSub.Pub(_crsReloadedKey, true); + public Task TriggerReloadExpressions() + => _pubSub.Pub(_exprsReloadedKey, true); #endregion @@ -600,7 +598,7 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor private Task OnLeftGuild(SocketGuild arg) { - _newGuildReactions.TryRemove(arg.Id, out _); + newGuildReactions.TryRemove(arg.Id, out _); return Task.CompletedTask; } @@ -608,9 +606,9 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor private async Task OnJoinedGuild(GuildConfig gc) { await using var uow = _db.GetDbContext(); - var crs = await uow.CustomReactions.AsNoTracking().Where(x => x.GuildId == gc.GuildId).ToArrayAsync(); + var exprs = await uow.Expressions.AsNoTracking().Where(x => x.GuildId == gc.GuildId).ToArrayAsync(); - _newGuildReactions[gc.GuildId] = crs; + newGuildReactions[gc.GuildId] = exprs; } #endregion @@ -620,59 +618,59 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor public async Task AddAsync(ulong? guildId, string key, string message) { key = key.ToLowerInvariant(); - var cr = new CustomReaction { GuildId = guildId, Trigger = key, Response = message }; + var expr = new CustomReaction { GuildId = guildId, Trigger = key, Response = message }; - if (cr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) - cr.AllowTarget = true; + if (expr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) + expr.AllowTarget = true; await using (var uow = _db.GetDbContext()) { - uow.CustomReactions.Add(cr); + uow.Expressions.Add(expr); await uow.SaveChangesAsync(); } - await AddInternalAsync(guildId, cr); + await AddInternalAsync(guildId, expr); - return cr; + return expr; } public async Task EditAsync(ulong? guildId, int id, string message) { await using var uow = _db.GetDbContext(); - var cr = uow.CustomReactions.GetById(id); + var expr = uow.Expressions.GetById(id); - if (cr is null || cr.GuildId != guildId) + if (expr is null || expr.GuildId != guildId) return null; // disable allowtarget if message had target, but it was removed from it if (!message.Contains("%target%", StringComparison.OrdinalIgnoreCase) - && cr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) - cr.AllowTarget = false; + && expr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) + expr.AllowTarget = false; - cr.Response = message; + expr.Response = message; // enable allow target if message is edited to contain target - if (cr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) - cr.AllowTarget = true; + if (expr.Response.Contains("%target%", StringComparison.OrdinalIgnoreCase)) + expr.AllowTarget = true; await uow.SaveChangesAsync(); - await UpdateInternalAsync(guildId, cr); + await UpdateInternalAsync(guildId, expr); - return cr; + return expr; } public async Task DeleteAsync(ulong? guildId, int id) { await using var uow = _db.GetDbContext(); - var toDelete = uow.CustomReactions.GetById(id); + var toDelete = uow.Expressions.GetById(id); if (toDelete is null) return null; if ((toDelete.IsGlobal() && guildId is null) || guildId == toDelete.GuildId) { - uow.CustomReactions.Remove(toDelete); + uow.Expressions.Remove(toDelete); await uow.SaveChangesAsync(); await DeleteInternalAsync(guildId, id); return toDelete; @@ -682,12 +680,12 @@ public sealed class CustomReactionsService : IEarlyBehavior, IReadyExecutor } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public CustomReaction[] GetCustomReactionsFor(ulong? maybeGuildId) + public CustomReaction[] GetExpressionsFor(ulong? maybeGuildId) { if (maybeGuildId is { } guildId) - return _newGuildReactions.TryGetValue(guildId, out var crs) ? crs : Array.Empty(); + return newGuildReactions.TryGetValue(guildId, out var exprs) ? exprs : Array.Empty(); - return _globalReactions; + return globalReactions; } #endregion diff --git a/src/NadekoBot/Modules/Help/CommandJsonObject.cs b/src/NadekoBot/Modules/Help/CommandJsonObject.cs new file mode 100644 index 000000000..e24ec510a --- /dev/null +++ b/src/NadekoBot/Modules/Help/CommandJsonObject.cs @@ -0,0 +1,13 @@ +#nullable disable +namespace NadekoBot.Modules.Help; + +internal class CommandJsonObject +{ + public string[] Aliases { get; set; } + public string Description { get; set; } + public string[] Usage { get; set; } + public string Submodule { get; set; } + public string Module { get; set; } + public List Options { get; set; } + public string[] Requirements { get; set; } +} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Help/Help.cs b/src/NadekoBot/Modules/Help/Help.cs index 4bf12f302..c49f4e4c8 100644 --- a/src/NadekoBot/Modules/Help/Help.cs +++ b/src/NadekoBot/Modules/Help/Help.cs @@ -12,8 +12,9 @@ namespace NadekoBot.Modules.Help; public partial class Help : NadekoModule { - public const string PatreonUrl = "https://patreon.com/nadekobot"; - public const string PaypalUrl = "https://paypal.me/Kwoth"; + public const string PATREON_URL = "https://patreon.com/nadekobot"; + public const string PAYPAL_URL = "https://paypal.me/Kwoth"; + private readonly CommandService _cmds; private readonly BotConfigService _bss; private readonly GlobalPermissionService _perms; @@ -106,8 +107,8 @@ public partial class Help : NadekoModule return strs.module_description_help; case "administration": return strs.module_description_administration; - case "customreactions": - return strs.module_description_customreactions; + case "expressions": + return strs.module_description_expressions; case "searches": return strs.module_description_searches; case "utility": @@ -313,7 +314,7 @@ public partial class Help : NadekoModule .Select(com => { List optHelpStr = null; - var opt = ((NadekoOptionsAttribute)com.Attributes.FirstOrDefault(x + var opt = ((NadekoOptionsAttribute)com.Attributes.FirstOrDefault(static x => x is NadekoOptionsAttribute)) ?.OptionType; if (opt is not null) optHelpStr = HelpService.GetCommandOptionHelpList(opt); @@ -371,7 +372,7 @@ public partial class Help : NadekoModule var versionListString = Encoding.UTF8.GetString(ms.ToArray()); var versionList = JsonSerializer.Deserialize>(versionListString); - if (!versionList.Contains(StatsService.BotVersion)) + if (versionList is not null && !versionList.Contains(StatsService.BotVersion)) { // save the file with new version added // versionList.Add(StatsService.BotVersion); @@ -410,16 +411,5 @@ public partial class Help : NadekoModule [Cmd] public async partial Task Donate() - => await ReplyConfirmLocalizedAsync(strs.donate(PatreonUrl, PaypalUrl)); -} - -internal class CommandJsonObject -{ - public string[] Aliases { get; set; } - public string Description { get; set; } - public string[] Usage { get; set; } - public string Submodule { get; set; } - public string Module { get; set; } - public List Options { get; set; } - public string[] Requirements { get; set; } + => await ReplyConfirmLocalizedAsync(strs.donate(PATREON_URL, PAYPAL_URL)); } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Help/HelpService.cs b/src/NadekoBot/Modules/Help/HelpService.cs index 08a93f480..750562418 100644 --- a/src/NadekoBot/Modules/Help/HelpService.cs +++ b/src/NadekoBot/Modules/Help/HelpService.cs @@ -62,11 +62,13 @@ public class HelpService : ILateExecutor, INService var alias = com.Aliases.Skip(1).FirstOrDefault(); if (alias is not null) str += $" **/ `{prefix + alias}`**"; + var em = _eb.Create().AddField(str, $"{com.RealSummary(_strings, guild?.Id, prefix)}", true); _dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides); var reqs = GetCommandRequirements(com, overrides); - if (reqs.Any()) em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs)); + if (reqs.Any()) + em.AddField(GetText(strs.requires, guild), string.Join("\n", reqs)); em.AddField(_strings.GetText(strs.usage), string.Join("\n", @@ -128,6 +130,7 @@ public class HelpService : ILateExecutor, INService { if (userPerm.ChannelPermission is { } cPerm) userPermString = GetPreconditionString(cPerm); + if (userPerm.GuildPermission is { } gPerm) userPermString = GetPreconditionString(gPerm); } @@ -149,11 +152,11 @@ public class HelpService : ILateExecutor, INService } public static string GetPreconditionString(ChannelPerm perm) - => (perm + " Channel Permission").Replace("Guild", "Server", StringComparison.InvariantCulture); + => (perm + " Channel Permission").Replace("Guild", "Server"); public static string GetPreconditionString(GuildPerm perm) - => (perm + " Server Permission").Replace("Guild", "Server", StringComparison.InvariantCulture); + => (perm + " Server Permission").Replace("Guild", "Server"); - private string GetText(LocStr str, IGuild guild, params object[] replacements) + private string GetText(LocStr str, IGuild guild) => _strings.GetText(str, guild?.Id); } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs index f0c652cf8..744e6ffda 100644 --- a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs +++ b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs @@ -39,9 +39,9 @@ public static class PermissionExtensions string moduleName) { if (!((perm.SecondaryTarget == SecondaryPermissionType.Command - && perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) + && string.Equals(perm.SecondaryTargetName, commandName, StringComparison.InvariantCultureIgnoreCase)) || (perm.SecondaryTarget == SecondaryPermissionType.Module - && perm.SecondaryTargetName.ToLowerInvariant() == moduleName.ToLowerInvariant()) + && string.Equals(perm.SecondaryTargetName, moduleName, StringComparison.InvariantCultureIgnoreCase)) || perm.SecondaryTarget == SecondaryPermissionType.AllModules)) return null; diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 006aaeb82..766d562e3 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -44,8 +44,6 @@ public partial class Searches : NadekoModule public async partial Task Rip([Leftover] IGuildUser usr) { var av = usr.RealAvatarUrl(); - if (av is null) - return; await using var picStream = await _service.GetRipPictureAsync(usr.Nickname ?? usr.Username, av); await ctx.Channel.SendFileAsync(picStream, "rip.png", @@ -220,7 +218,7 @@ public partial class Searches : NadekoModule var oterms = query?.Trim(); if (!await ValidateQuery(query)) return; - query = WebUtility.UrlEncode(oterms).Replace(' ', '+'); + query = WebUtility.UrlEncode(oterms)?.Replace(' ', '+'); try { var res = await _google.GetImageAsync(oterms); diff --git a/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs b/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs index c3109b80b..f47f18e68 100644 --- a/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/NadekoBot/Modules/Utility/Info/InfoCommands.cs @@ -17,9 +17,17 @@ public partial class Utility _stats = stats; } + [Cmd] + [OwnerOnly] + public partial Task ServerInfo([Leftover] string guildName) + => InternalServerInfo(guildName); + [Cmd] [RequireContext(ContextType.Guild)] - public async partial Task ServerInfo(string guildName = null) + public partial Task ServerInfo() + => InternalServerInfo(); + + private async Task InternalServerInfo(string guildName = null) { var channel = (ITextChannel)ctx.Channel; guildName = guildName?.ToUpperInvariant(); @@ -103,7 +111,7 @@ public partial class Utility .WithOkColor(); var av = user.RealAvatarUrl(); - if (av is not null && av.IsAbsoluteUri) + if (av.IsAbsoluteUri) embed.WithThumbnailUrl(av.ToString()); await ctx.Channel.EmbedAsync(embed); } diff --git a/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs b/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs index 213aa3573..fb33ec976 100644 --- a/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs +++ b/src/NadekoBot/Modules/Utility/Quote/QuoteCommands.cs @@ -276,10 +276,10 @@ public partial class Utility quotes = uow.Quotes.GetForGuild(ctx.Guild.Id).ToList(); } - var crsDict = quotes.GroupBy(x => x.Keyword) + var exprsDict = quotes.GroupBy(x => x.Keyword) .ToDictionary(x => x.Key, x => x.Select(ExportedQuote.FromModel)); - var text = _prependExport + _exportSerializer.Serialize(crsDict).UnescapeUnicodeCodePoints(); + var text = _prependExport + _exportSerializer.Serialize(exprsDict).UnescapeUnicodeCodePoints(); await using var stream = await text.ToStream(); await ctx.Channel.SendFileAsync(stream, "quote-export.yml"); @@ -317,7 +317,7 @@ public partial class Utility } } - var succ = await ImportCrsAsync(ctx.Guild.Id, input); + var succ = await ImportExprsAsync(ctx.Guild.Id, input); if (!succ) { await ReplyErrorLocalizedAsync(strs.expr_import_invalid_data); @@ -327,7 +327,7 @@ public partial class Utility await ctx.OkAsync(); } - private async Task ImportCrsAsync(ulong guildId, string input) + private async Task ImportExprsAsync(ulong guildId, string input) { Dictionary> data; try diff --git a/src/NadekoBot/Services/Settings/BotConfigService.cs b/src/NadekoBot/Services/Settings/BotConfigService.cs index 98ee0dd6c..0570d4a3b 100644 --- a/src/NadekoBot/Services/Settings/BotConfigService.cs +++ b/src/NadekoBot/Services/Settings/BotConfigService.cs @@ -31,5 +31,21 @@ public sealed class BotConfigService : ConfigServiceBase private void Migrate() { if (data.Version < 2) ModifyConfig(c => c.Version = 2); + + if (data.Version < 3) + { + ModifyConfig(c => + { + c.Version = 3; + c.Blocked.Modules = c.Blocked.Modules?.Select(static x + => string.Equals(x, + "ActualCustomReactions", + StringComparison.InvariantCultureIgnoreCase) + ? "ACTUALEXPRESSIONS" + : x) + .Distinct() + .ToHashSet(); + }); + } } } \ No newline at end of file diff --git a/src/NadekoBot/_Extensions/ArrayExtensions.cs b/src/NadekoBot/_Extensions/ArrayExtensions.cs index 8dc43a237..208333797 100644 --- a/src/NadekoBot/_Extensions/ArrayExtensions.cs +++ b/src/NadekoBot/_Extensions/ArrayExtensions.cs @@ -1,6 +1,6 @@ namespace NadekoBot.Extensions; -// made for customreactions because they almost never get added +// made for expressions because they almost never get added // and they get looped through constantly public static class ArrayExtensions { @@ -13,10 +13,10 @@ public static class ArrayExtensions /// A new array with the new element at the end public static T[] With(this T[] input, T added) { - var newCrs = new T[input.Length + 1]; - Array.Copy(input, 0, newCrs, 0, input.Length); - newCrs[input.Length] = added; - return newCrs; + var newExprs = new T[input.Length + 1]; + Array.Copy(input, 0, newExprs, 0, input.Length); + newExprs[input.Length] = added; + return newExprs; } /// diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 550d3f65d..2de9aec4d 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -1,5 +1,4 @@ using Humanizer.Localisation; -using NadekoBot.Modules.Administration.Services; using SixLabors.Fonts; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Drawing; @@ -120,20 +119,16 @@ public static class Extensions IBotStrings strings, ulong? guildId, string prefix) - => string.Format(strings.GetCommandStrings(cmd.Name, guildId).Desc, prefix); + => string.Format(strings.GetCommandStrings(cmd.Summary, guildId).Desc, prefix); public static string[] RealRemarksArr( this CommandInfo cmd, IBotStrings strings, ulong? guildId, string prefix) - => Array.ConvertAll(strings.GetCommandStrings(cmd.MethodName(), guildId).Args, + => Array.ConvertAll(strings.GetCommandStrings(cmd.Remarks, guildId).Args, arg => GetFullUsage(cmd.Name, arg, prefix)); - private static string MethodName(this CommandInfo cmd) - => ((NadekoCommandAttribute?)cmd.Attributes.FirstOrDefault(x => x is NadekoCommandAttribute))?.MethodName - ?? cmd.Name; - private static string GetFullUsage(string commandName, string args, string prefix) => $"{prefix}{commandName} {string.Format(args, prefix)}"; diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index 197a5c26b..075a7bc33 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -92,29 +92,6 @@ iam: iamnot: - iamnot - iamn -addcustreact: -- addcustreact -- acr -- expradd -- exadd -- exa -listcustreact: -- listcustreact -- lcr -- exprli -- exl -showcustreact: -- showcustreact -- scr -- exs -delcustreact: -- delcustreact -- dcr -- exprdel -- exd -crclear: -- crclear -- exclear fwclear: - fwclear aliasesclear: @@ -900,25 +877,6 @@ languageslist: - langli rategirl: - rategirl -crreact: -- crreact -- crr -crad: -- crad -- exad -crat: -- crat -- exat -crdm: -- crdm -- exdm -crca: -- crca -- exca -crsreload: -- crsreload -- expreload -- exrel aliaslist: - aliaslist - cmdmaplist @@ -1142,10 +1100,6 @@ feedremove: feedlist: - feedlist - feeds -editcustreact: -- editcustreact -- ecr -- exe say: - say sqlexec: @@ -1238,12 +1192,6 @@ economy: - economy purgeuser: - purgeuser -crsimport: - - crsimport - - eximport -crsexport: - - crsexport - - exexport imageonlychannel: - imageonlychannel - imageonly @@ -1257,4 +1205,49 @@ quotesimport: - quotesimport - qimport showembed: - - showembed \ No newline at end of file + - showembed +# NadekoExpressions +exprreact: + - exreact + - exr +exprad: + - exad +exprat: + - exat +exprdm: + - exdm +exprca: + - exca +exprsreload: + - expreload + - exrel +expradd: + - expradd + - exadd + - exa +exprlist: + - exprlist + - exl + - exprli + - exlist + - exli +exprshow: + - exprshow + - exs + - exshow +exprdelete: + - exprdel + - exd + - exdel +exprclear: + - exprclear + - exc + - exclear +expredit: + - expredit + - exe + - exedit +exprsimport: + - eximport +exprsexport: + - exexport \ No newline at end of file diff --git a/src/NadekoBot/data/bot.yml b/src/NadekoBot/data/bot.yml index 9eaf1a89e..5af9905a5 100644 --- a/src/NadekoBot/data/bot.yml +++ b/src/NadekoBot/data/bot.yml @@ -1,5 +1,5 @@ # DO NOT CHANGE -version: 2 +version: 3 # Most commands, when executed, have a small colored line # next to the response. The color depends whether the command # is completed, errored or in progress (pending) diff --git a/src/NadekoBot/data/strings/responses/responses.de-DE.json b/src/NadekoBot/data/strings/responses/responses.de-DE.json index 52ed5fdc9..d39f55c9a 100644 --- a/src/NadekoBot/data/strings/responses/responses.de-DE.json +++ b/src/NadekoBot/data/strings/responses/responses.de-DE.json @@ -937,7 +937,7 @@ "module_description_music": "Spiele Musik von YouTube, lokalen Dateien und Radio Streams", "module_description_utility": "Verwalte benutzerdefinierte Zitate, wiederholte Nachrichten und überprüfe Fakten über den Server", "module_description_administration": "Moderation, bestrafe Nutzer, richte selbst zuweisbare Rollen und Willkommensnachrichten ein", - "module_description_customreactions": "Richte benutzerdefinierte Bot-antworten für bestimmte Wörter oder Sätze ein", + "module_description_expressions": "Richte benutzerdefinierte Bot-antworten für bestimmte Wörter oder Sätze ein", "module_description_permissions": "Richte Berechtigungen für Befehle ein, filtere Wörter und richte Abklingzeiten für Befehle ein", "module_description_searches": "Suche nach Witzen, Bilder von Tieren, Anime und Manga", "module_description_xp": "Erhalte XP basierend auf Chataktivität, prüfe Nutzer XP-karten", diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index b090c14f9..6d388a2da 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -950,7 +950,7 @@ "module_description_music": "Play music from youtube, local files soundcloud and radio streams", "module_description_utility": "Manage custom quotes, repeating messages and check facts about the server", "module_description_administration": "Moderation, punish users, setup self assignable roles and greet messages", - "module_description_customreactions": "Setup custom bot responses to certain words or phrases", + "module_description_expressions": "Setup custom bot responses to certain words or phrases", "module_description_permissions": "Setup perms for commands, filter words and set up command cooldowns", "module_description_searches": "Search for jokes, images of animals, anime and manga", "module_description_xp": "Gain xp based on chat activity, check users' xp cards", diff --git a/src/NadekoBot/data/strings/responses/responses.es-ES.json b/src/NadekoBot/data/strings/responses/responses.es-ES.json index f0e8ed278..26d1b9618 100644 --- a/src/NadekoBot/data/strings/responses/responses.es-ES.json +++ b/src/NadekoBot/data/strings/responses/responses.es-ES.json @@ -937,7 +937,7 @@ "module_description_music": "Reproduce música de YouTube, archivos locales, SoundCloud y radios.", "module_description_utility": "Administra citas personalizadas, repeticiones de mensajes y revisa datos sobre el servidor", "module_description_administration": "Moderación, castigos, configuración de roles autoasignables y saludos", - "module_description_customreactions": "Ajusta las respuestas del bot a ciertas palabras o frases", + "module_description_expressions": "Ajusta las respuestas del bot a ciertas palabras o frases", "module_description_permissions": "Ajusta permisos para los comandos, filtro de palabras y configura enfriamiento para los comandos.", "module_description_searches": "Busca bromas, imágenes de animales, anime y manga", "module_description_xp": "Gana EXP según la actividad del chat, revisa la tarjeta de EXP de los usuarios.", diff --git a/src/NadekoBot/data/strings/responses/responses.fr-FR.json b/src/NadekoBot/data/strings/responses/responses.fr-FR.json index 1a26152c7..270b7fccd 100644 --- a/src/NadekoBot/data/strings/responses/responses.fr-FR.json +++ b/src/NadekoBot/data/strings/responses/responses.fr-FR.json @@ -937,7 +937,7 @@ "module_description_music": "Jouez de la musique à partir de youtube, des fichiers locaux soundcloud et des flux radio", "module_description_utility": "Gérez les citations personnalisés, répéteurs et consulter les faits à propos du serveur", "module_description_administration": "Modération, punition des utilisateurs, configuration de rôles auto-assignables et messages d'accueil", - "module_description_customreactions": "Configurer des réponses de bot personnalisées à certains mots ou expressions", + "module_description_expressions": "Configurer des réponses de bot personnalisées à certains mots ou expressions", "module_description_permissions": "Configurer les autorisations pour les commandes, filtrer les mots et configurer les temps de recharge des commandes", "module_description_searches": "Recherche de blagues, d'images d'animaux, d'anime et de manga", "module_description_xp": "Gagnez de l'XP en fonction de l'activité de tchat, vérifiez les cartes XP des utilisateurs", diff --git a/src/NadekoBot/data/strings/responses/responses.id-ID.json b/src/NadekoBot/data/strings/responses/responses.id-ID.json index f813058e3..03e88e7d9 100644 --- a/src/NadekoBot/data/strings/responses/responses.id-ID.json +++ b/src/NadekoBot/data/strings/responses/responses.id-ID.json @@ -937,7 +937,7 @@ "module_description_music": "Memainkan musik dari youtube, file lokal soundcloud dan stream radio", "module_description_utility": "Mengatur kutipan kustom, pesan ulang dan cek fakta tentang server", "module_description_administration": "Moderasi, pengguna terhukum, persiapkan penetapan role mandiri dan pesan salam", - "module_description_customreactions": "Persiapkan penanggapan bot yang kustom ke kata-kata atau frase yang ditentukan", + "module_description_expressions": "Persiapkan penanggapan bot yang kustom ke kata-kata atau frase yang ditentukan", "module_description_permissions": "Persiapkan permisi untuk perintah, kata sensor dan persiapkan pertenangan perintah", "module_description_searches": "Mencari lelucon, gamba binatang, anime dan manga", "module_description_xp": "Mendapatkan xp berdasarkan aktivitas di chat, cek kartu xp pengguna", diff --git a/src/NadekoBot/data/strings/responses/responses.nl-NL.json b/src/NadekoBot/data/strings/responses/responses.nl-NL.json index 8c54553a3..5487490e3 100644 --- a/src/NadekoBot/data/strings/responses/responses.nl-NL.json +++ b/src/NadekoBot/data/strings/responses/responses.nl-NL.json @@ -937,7 +937,7 @@ "module_description_music": "Speel muziek van youtube, lokale bestanden soundcloud en radio streams", "module_description_utility": "Beheer speciale citaten, herhalende berichten en controleer feiten over de server", "module_description_administration": "Moderatie, gebruikers straffen, zelf in te delen rollen en begroetingsberichten", - "module_description_customreactions": "Stel speciale bot reacties in op bepaalde woorden of zinnen", + "module_description_expressions": "Stel speciale bot reacties in op bepaalde woorden of zinnen", "module_description_permissions": "Rechten instellen voor commando's, woorden filteren en cooldowns instellen", "module_description_searches": "Zoek naar grappen, afbeeldingen van dieren, anime en manga", "module_description_xp": "Xp verdienen op basis van chat-activiteit, xp-kaarten van gebruikers controleren", diff --git a/src/NadekoBot/data/strings/responses/responses.pl-PL.json b/src/NadekoBot/data/strings/responses/responses.pl-PL.json index 0a78c0ac8..a95700249 100644 --- a/src/NadekoBot/data/strings/responses/responses.pl-PL.json +++ b/src/NadekoBot/data/strings/responses/responses.pl-PL.json @@ -937,7 +937,7 @@ "module_description_music": "Odtwarzaj muzykę z youtube, plików lokalnych, soundcloud'a i radia internetowego", "module_description_utility": "Zarządzaj customowymi cytatami, powtarzającymi wiadomościami i sprawdź fakty na temat serwera", "module_description_administration": "Moderacja, kary dla użytkowników, ustaw role do samodzielnego przypisania oraz wiadomości powitalne", - "module_description_customreactions": "Ustaw customowe odpowiedzi bota na określone słowa bądź zdania", + "module_description_expressions": "Ustaw customowe odpowiedzi bota na określone słowa bądź zdania", "module_description_permissions": "Ustaw uprawnienia dla komend, filtruj słowa i ustaw cooldown'y dla komend", "module_description_searches": "Wyszukaj żarty, obrazki ze zwierzętami, anime i mangą.", "module_description_xp": "Zdobywaj xp bazujące na aktywności na czacie, sprawdź karty xp użytkowników.", diff --git a/src/NadekoBot/data/strings/responses/responses.pt-BR.json b/src/NadekoBot/data/strings/responses/responses.pt-BR.json index 92965792b..d6bfe7290 100644 --- a/src/NadekoBot/data/strings/responses/responses.pt-BR.json +++ b/src/NadekoBot/data/strings/responses/responses.pt-BR.json @@ -937,7 +937,7 @@ "module_description_music": "Toque músicas do YouTube, arquivos locais do SoundCloud e rádios ao vivo", "module_description_utility": "Controle falas customizadas, mensagens repetidas e veja fatos sobre o servidor", "module_description_administration": "Moderação, punir usuários, configurar cargos dados á si mesmo e mensagens de boas vindas", - "module_description_customreactions": "Configure respostas customizáveis para o bot para certas palavras ou frases", + "module_description_expressions": "Configure respostas customizáveis para o bot para certas palavras ou frases", "module_description_permissions": "Configure permissões para comandos, filtro de palavras e configure intervalo de comandos", "module_description_searches": "Procure por piadas, imagens de animais, anime e manga", "module_description_xp": "Ganhe xp baseado na atividade em chat, verifique cartão de xp do usuário", diff --git a/src/NadekoBot/data/strings/responses/responses.ru-RU.json b/src/NadekoBot/data/strings/responses/responses.ru-RU.json index c5d38b8b3..88d5c2031 100644 --- a/src/NadekoBot/data/strings/responses/responses.ru-RU.json +++ b/src/NadekoBot/data/strings/responses/responses.ru-RU.json @@ -937,7 +937,7 @@ "module_description_music": "Воспроизведение музыки с YouTube, локальных файлов, звукового облака и радиопотоков", "module_description_utility": "Управляйте кастомными цитатами, повторяйте сообщения и проверяйте факты о сервере", "module_description_administration": "Модерация, наказание пользователей, установка самопределяемых ролей и приветственные сообщения", - "module_description_customreactions": "Настройка пользовательских ответов бота на определенные слова или фразы", + "module_description_expressions": "Настройка пользовательских ответов бота на определенные слова или фразы", "module_description_permissions": "Настройка разрешений для команд, фильтрация слов и настройка времени восстановления команд", "module_description_searches": "Поиск шуток, изображений животных, аниме и манги", "module_description_xp": "Получайте опыт на основе активности в чате, проверяйте карты опыта пользователей", diff --git a/src/NadekoBot/data/strings/responses/responses.uk-UA.json b/src/NadekoBot/data/strings/responses/responses.uk-UA.json index 96d931ec0..4b80d986e 100644 --- a/src/NadekoBot/data/strings/responses/responses.uk-UA.json +++ b/src/NadekoBot/data/strings/responses/responses.uk-UA.json @@ -937,7 +937,7 @@ "module_description_music": "Відтворюйте музику з YouTube, локальні файли soundcloud та радіопотоки", "module_description_utility": "Керуйте власними цитатами, повторюваними повідомленнями та перевіряйте факти про сервер", "module_description_administration": "Модеруйте, карайте користувачів, налаштовуйте самостійно призначені ролі та вітайте повідомлення", - "module_description_customreactions": "Налаштуйте власні відповіді бота на певні слова чи фрази", + "module_description_expressions": "Налаштуйте власні відповіді бота на певні слова чи фрази", "module_description_permissions": "Налаштуйте дозволи для команд, фільтруйте слова та налаштуйте час відновлення", "module_description_searches": "Шукайте жарти, зображення тварин, аніме та мангу", "module_description_xp": "Отримайте ХР на основі активності в чаті, перевірте картки ХР користувачів",