diff --git a/NadekoBot.sln b/NadekoBot.sln index 42b343e5..8c235940 100644 --- a/NadekoBot.sln +++ b/NadekoBot.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.3 +VisualStudioVersion = 15.0.26430.12 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{04929013-5BAB-42B0-B9B2-8F2BB8F16AF2}" EndProject @@ -33,7 +33,4 @@ Global GlobalSection(NestedProjects) = preSolution {45EC1473-C678-4857-A544-07DFE0D0B478} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5F3F555C-855F-4BE8-B526-D062D3E8ACA4} - EndGlobalSection EndGlobal diff --git a/global.json b/global.json index 68be1221..3b965cc4 100644 --- a/global.json +++ b/global.json @@ -1,3 +1,3 @@ { - "sdk": { "version": "2.0.0" } + "sdk": { "version": "1.0.1" } } \ No newline at end of file diff --git a/src/NadekoBot/Common/Attributes/Aliases.cs b/src/NadekoBot/Common/Attributes/Aliases.cs index e6c95f67..7f365078 100644 --- a/src/NadekoBot/Common/Attributes/Aliases.cs +++ b/src/NadekoBot/Common/Attributes/Aliases.cs @@ -2,11 +2,12 @@ using System.Runtime.CompilerServices; using Discord.Commands; using NadekoBot.Services.Impl; + namespace NadekoBot.Common.Attributes { public class Aliases : AliasAttribute { - public Aliases([CallerMemberName] string memberName = "") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd.Split(' ').Skip(1).ToArray()) + public Aliases([CallerMemberName] string memberName = "") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_cmd").Split(' ').Skip(1).ToArray()) { } } diff --git a/src/NadekoBot/Common/Attributes/Description.cs b/src/NadekoBot/Common/Attributes/Description.cs index 7ebbac47..1b0e7957 100644 --- a/src/NadekoBot/Common/Attributes/Description.cs +++ b/src/NadekoBot/Common/Attributes/Description.cs @@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes { public class Description : SummaryAttribute { - public Description([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Desc) + public Description([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_desc")) { } diff --git a/src/NadekoBot/Common/Attributes/NadekoCommand.cs b/src/NadekoBot/Common/Attributes/NadekoCommand.cs index eda997fd..a471e007 100644 --- a/src/NadekoBot/Common/Attributes/NadekoCommand.cs +++ b/src/NadekoBot/Common/Attributes/NadekoCommand.cs @@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes { public class NadekoCommand : CommandAttribute { - public NadekoCommand([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Cmd) + public NadekoCommand([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant() + "_cmd").Split(' ')[0]) { } diff --git a/src/NadekoBot/Common/Attributes/Usage.cs b/src/NadekoBot/Common/Attributes/Usage.cs index 97d342ee..2991c6aa 100644 --- a/src/NadekoBot/Common/Attributes/Usage.cs +++ b/src/NadekoBot/Common/Attributes/Usage.cs @@ -6,7 +6,7 @@ namespace NadekoBot.Common.Attributes { public class Usage : RemarksAttribute { - public Usage([CallerMemberName] string memberName="") : base(Localization.LoadCommand(memberName.ToLowerInvariant()).Usage) + public Usage([CallerMemberName] string memberName="") : base(Localization.LoadCommandString(memberName.ToLowerInvariant()+"_usage")) { } diff --git a/src/NadekoBot/Common/CommandData.cs b/src/NadekoBot/Common/CommandData.cs deleted file mode 100644 index 59712eae..00000000 --- a/src/NadekoBot/Common/CommandData.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace NadekoBot.Common -{ - public class CommandData - { - public string Cmd { get; set; } - public string Usage { get; set; } - public string Desc { get; set; } - } -} diff --git a/src/NadekoBot/Migrations/20170913022654_total-xp.Designer.cs b/src/NadekoBot/Migrations/20170913022654_total-xp.Designer.cs deleted file mode 100644 index 6764dd56..00000000 --- a/src/NadekoBot/Migrations/20170913022654_total-xp.Designer.cs +++ /dev/null @@ -1,1949 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using NadekoBot.Services.Database; -using NadekoBot.Services.Database.Models; - -namespace NadekoBot.Migrations -{ - [DbContext(typeof(NadekoContext))] - [Migration("20170913022654_total-xp")] - partial class totalxp - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Action"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Seconds"); - - b.Property("UserThreshold"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("AntiRaidSetting"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AntiSpamSettingId"); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.HasKey("Id"); - - b.HasIndex("AntiSpamSettingId"); - - b.ToTable("AntiSpamIgnore"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Action"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("MessageThreshold"); - - b.Property("MuteTime"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("AntiSpamSetting"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("ItemId"); - - b.Property("Type"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("BlacklistItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlockedCmdOrMdl", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("BotConfigId1"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.HasIndex("BotConfigId1"); - - b.ToTable("BlockedCmdOrMdl"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BetflipMultiplier"); - - b.Property("Betroll100Multiplier"); - - b.Property("Betroll67Multiplier"); - - b.Property("Betroll91Multiplier"); - - b.Property("BufferSize"); - - b.Property("CurrencyDropAmount"); - - b.Property("CurrencyDropAmountMax"); - - b.Property("CurrencyGenerationChance"); - - b.Property("CurrencyGenerationCooldown"); - - b.Property("CurrencyName"); - - b.Property("CurrencyPluralName"); - - b.Property("CurrencySign"); - - b.Property("CustomReactionsStartWith"); - - b.Property("DMHelpString"); - - b.Property("DateAdded"); - - b.Property("DefaultPrefix"); - - b.Property("ErrorColor"); - - b.Property("ForwardMessages"); - - b.Property("ForwardToAllOwners"); - - b.Property("HelpString"); - - b.Property("Locale"); - - b.Property("MigrationVersion"); - - b.Property("MinimumBetAmount"); - - b.Property("OkColor"); - - b.Property("PermissionVersion"); - - b.Property("RemindMessageFormat"); - - b.Property("RotatingStatuses"); - - b.Property("TriviaCurrencyReward"); - - b.Property("XpMinutesTimeout") - .ValueGeneratedOnAdd() - .HasDefaultValue(5); - - b.Property("XpPerMessage") - .ValueGeneratedOnAdd() - .HasDefaultValue(3); - - b.HasKey("Id"); - - b.ToTable("BotConfig"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BaseDestroyed"); - - b.Property("CallUser"); - - b.Property("ClashWarId"); - - b.Property("DateAdded"); - - b.Property("SequenceNumber"); - - b.Property("Stars"); - - b.Property("TimeAdded"); - - b.HasKey("Id"); - - b.HasIndex("ClashWarId"); - - b.ToTable("ClashCallers"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("EnemyClan"); - - b.Property("GuildId"); - - b.Property("Size"); - - b.Property("StartedAt"); - - b.Property("WarState"); - - b.HasKey("Id"); - - b.ToTable("ClashOfClans"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b => - { - b.Property("ClubId"); - - b.Property("UserId"); - - b.HasKey("ClubId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("ClubApplicants"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b => - { - b.Property("ClubId"); - - b.Property("UserId"); - - b.HasKey("ClubId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("ClubBans"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Discrim"); - - b.Property("ImageUrl"); - - b.Property("MinimumLevelReq"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(20); - - b.Property("OwnerId"); - - b.Property("Xp"); - - b.HasKey("Id"); - - b.HasAlternateKey("Name", "Discrim"); - - b.HasIndex("OwnerId") - .IsUnique(); - - b.ToTable("Clubs"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Mapping"); - - b.Property("Trigger"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("CommandAlias"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("CommandName"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Seconds"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("CommandCooldown"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandPrice", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("CommandName"); - - b.Property("DateAdded"); - - b.Property("Price"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.HasIndex("Price") - .IsUnique(); - - b.ToTable("CommandPrice"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("InternalTrigger"); - - b.Property("Modifier"); - - b.Property("UnitType"); - - b.HasKey("Id"); - - b.ToTable("ConversionUnits"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("Currency"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("Reason"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.ToTable("CurrencyTransactions"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AutoDeleteTrigger"); - - b.Property("ContainsAnywhere"); - - b.Property("DateAdded"); - - b.Property("DmResponse"); - - b.Property("GuildId"); - - b.Property("IsRegex"); - - b.Property("OwnerOnly"); - - b.Property("Response"); - - b.Property("Trigger"); - - b.HasKey("Id"); - - b.ToTable("CustomReactions"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AvatarId"); - - b.Property("ClubId"); - - b.Property("DateAdded"); - - b.Property("Discriminator"); - - b.Property("LastLevelUp") - .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 906, DateTimeKind.Local)); - - b.Property("LastXpGain"); - - b.Property("NotifyOnLevelUp"); - - b.Property("TotalXp"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasAlternateKey("UserId"); - - b.HasIndex("ClubId"); - - b.ToTable("DiscordUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("Donators"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Text"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("EightBallResponses"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("ItemId"); - - b.Property("ItemType"); - - b.Property("XpSettingsId"); - - b.HasKey("Id"); - - b.HasIndex("XpSettingsId"); - - b.ToTable("ExcludedItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildConfigId1"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.HasIndex("GuildConfigId1"); - - b.ToTable("FilterChannelId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Word"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("FilteredWord"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildId"); - - b.Property("Type"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("FollowedStream"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("GCChannelId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AutoAssignRoleId"); - - b.Property("AutoDeleteByeMessages"); - - b.Property("AutoDeleteByeMessagesTimer"); - - b.Property("AutoDeleteGreetMessages"); - - b.Property("AutoDeleteGreetMessagesTimer"); - - b.Property("AutoDeleteSelfAssignedRoleMessages"); - - b.Property("ByeMessageChannelId"); - - b.Property("ChannelByeMessageText"); - - b.Property("ChannelGreetMessageText"); - - b.Property("CleverbotEnabled"); - - b.Property("DateAdded"); - - b.Property("DefaultMusicVolume"); - - b.Property("DeleteMessageOnCommand"); - - b.Property("DmGreetMessageText"); - - b.Property("ExclusiveSelfAssignedRoles"); - - b.Property("FilterInvites"); - - b.Property("FilterWords"); - - b.Property("GameVoiceChannel"); - - b.Property("GreetMessageChannelId"); - - b.Property("GuildId"); - - b.Property("Locale"); - - b.Property("LogSettingId"); - - b.Property("MuteRoleName"); - - b.Property("PermissionRole"); - - b.Property("Prefix"); - - b.Property("RootPermissionId"); - - b.Property("SendChannelByeMessage"); - - b.Property("SendChannelGreetMessage"); - - b.Property("SendDmGreetMessage"); - - b.Property("TimeZoneId"); - - b.Property("VerboseErrors"); - - b.Property("VerbosePermissions"); - - b.Property("VoicePlusTextEnabled"); - - b.Property("WarningsInitialized"); - - b.HasKey("Id"); - - b.HasIndex("GuildId") - .IsUnique(); - - b.HasIndex("LogSettingId"); - - b.HasIndex("RootPermissionId"); - - b.ToTable("GuildConfigs"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildRepeater", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildId"); - - b.Property("Interval"); - - b.Property("Message"); - - b.Property("StartTimeOfDay"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("GuildRepeater"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("LogSettingId"); - - b.HasKey("Id"); - - b.HasIndex("LogSettingId"); - - b.ToTable("IgnoredLogChannels"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("LogSettingId"); - - b.HasKey("Id"); - - b.HasIndex("LogSettingId"); - - b.ToTable("IgnoredVoicePresenceCHannels"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelCreated"); - - b.Property("ChannelCreatedId"); - - b.Property("ChannelDestroyed"); - - b.Property("ChannelDestroyedId"); - - b.Property("ChannelId"); - - b.Property("ChannelUpdated"); - - b.Property("ChannelUpdatedId"); - - b.Property("DateAdded"); - - b.Property("IsLogging"); - - b.Property("LogOtherId"); - - b.Property("LogUserPresence"); - - b.Property("LogUserPresenceId"); - - b.Property("LogVoicePresence"); - - b.Property("LogVoicePresenceId"); - - b.Property("LogVoicePresenceTTSId"); - - b.Property("MessageDeleted"); - - b.Property("MessageDeletedId"); - - b.Property("MessageUpdated"); - - b.Property("MessageUpdatedId"); - - b.Property("UserBanned"); - - b.Property("UserBannedId"); - - b.Property("UserJoined"); - - b.Property("UserJoinedId"); - - b.Property("UserLeft"); - - b.Property("UserLeftId"); - - b.Property("UserMutedId"); - - b.Property("UserPresenceChannelId"); - - b.Property("UserUnbanned"); - - b.Property("UserUnbannedId"); - - b.Property("UserUpdated"); - - b.Property("UserUpdatedId"); - - b.Property("VoicePresenceChannelId"); - - b.HasKey("Id"); - - b.ToTable("LogSettings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("ModuleName"); - - b.Property("Prefix"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("ModulePrefixes"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Author"); - - b.Property("AuthorId"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.ToTable("MusicPlaylists"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("MutedUserId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Tag"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("NsfwBlacklitedTag"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("NextId"); - - b.Property("PrimaryTarget"); - - b.Property("PrimaryTargetId"); - - b.Property("SecondaryTarget"); - - b.Property("SecondaryTargetName"); - - b.Property("State"); - - b.HasKey("Id"); - - b.HasIndex("NextId") - .IsUnique(); - - b.ToTable("Permission"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Index"); - - b.Property("PrimaryTarget"); - - b.Property("PrimaryTargetId"); - - b.Property("SecondaryTarget"); - - b.Property("SecondaryTargetName"); - - b.Property("State"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("Permissionv2"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Status"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("PlayingStatus"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("MusicPlaylistId"); - - b.Property("Provider"); - - b.Property("ProviderType"); - - b.Property("Query"); - - b.Property("Title"); - - b.Property("Uri"); - - b.HasKey("Id"); - - b.HasIndex("MusicPlaylistId"); - - b.ToTable("PlaylistSong"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuthorId"); - - b.Property("AuthorName") - .IsRequired(); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("Keyword") - .IsRequired(); - - b.Property("Text") - .IsRequired(); - - b.HasKey("Id"); - - b.ToTable("Quotes"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Icon"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("RaceAnimals"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("IsPrivate"); - - b.Property("Message"); - - b.Property("ServerId"); - - b.Property("UserId"); - - b.Property("When"); - - b.HasKey("Id"); - - b.ToTable("Reminders"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AmountRewardedThisMonth"); - - b.Property("DateAdded"); - - b.Property("LastReward"); - - b.Property("PatreonUserId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("RewardedUsers"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("RoleId"); - - b.HasKey("Id"); - - b.HasIndex("GuildId", "RoleId") - .IsUnique(); - - b.ToTable("SelfAssignableRoles"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuthorId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Index"); - - b.Property("Name"); - - b.Property("Price"); - - b.Property("RoleId"); - - b.Property("RoleName"); - - b.Property("Type"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("ShopEntry"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("ShopEntryId"); - - b.Property("Text"); - - b.HasKey("Id"); - - b.HasIndex("ShopEntryId"); - - b.ToTable("ShopEntryItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("RoleId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("SlowmodeIgnoredRole"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("SlowmodeIgnoredUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("ChannelId"); - - b.Property("ChannelName"); - - b.Property("CommandText"); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("GuildName"); - - b.Property("Index"); - - b.Property("VoiceChannelId"); - - b.Property("VoiceChannelName"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("StartupCommand"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("StreamRoleSettingsId"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("StreamRoleSettingsId"); - - b.ToTable("StreamRoleBlacklistedUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AddRoleId"); - - b.Property("DateAdded"); - - b.Property("Enabled"); - - b.Property("FromRoleId"); - - b.Property("GuildConfigId"); - - b.Property("Keyword"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("StreamRoleSettings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("StreamRoleSettingsId"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("StreamRoleSettingsId"); - - b.ToTable("StreamRoleWhitelistedUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UnmuteAt"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("UnmuteTimer"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("UserId"); - - b.Property("type"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("PokeGame"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AwardedXp"); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("LastLevelUp") - .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 13, 4, 26, 53, 910, DateTimeKind.Local)); - - b.Property("NotifyOnLevelUp"); - - b.Property("UserId"); - - b.Property("Xp"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "GuildId") - .IsUnique(); - - b.ToTable("UserXpStats"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("RoleId"); - - b.Property("VoiceChannelId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("VcRoleInfo"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AffinityId"); - - b.Property("ClaimerId"); - - b.Property("DateAdded"); - - b.Property("Price"); - - b.Property("WaifuId"); - - b.HasKey("Id"); - - b.HasIndex("AffinityId"); - - b.HasIndex("ClaimerId"); - - b.HasIndex("WaifuId") - .IsUnique(); - - b.ToTable("WaifuInfo"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Item"); - - b.Property("ItemEmoji"); - - b.Property("Price"); - - b.Property("WaifuInfoId"); - - b.HasKey("Id"); - - b.HasIndex("WaifuInfoId"); - - b.ToTable("WaifuItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("NewId"); - - b.Property("OldId"); - - b.Property("UpdateType"); - - b.Property("UserId"); - - 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(); - - b.Property("DateAdded"); - - b.Property("Forgiven"); - - b.Property("ForgivenBy"); - - b.Property("GuildId"); - - b.Property("Moderator"); - - b.Property("Reason"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.ToTable("Warnings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Count"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Punishment"); - - b.Property("Time"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("WarningPunishment"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Level"); - - b.Property("RoleId"); - - b.Property("XpSettingsId"); - - b.HasKey("Id"); - - b.HasAlternateKey("Level"); - - b.HasIndex("XpSettingsId"); - - b.ToTable("XpRoleReward"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("NotifyMessage"); - - b.Property("ServerExcluded"); - - b.Property("XpRoleRewardExclusive"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("XpSettings"); - }); - - 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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => - { - b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting") - .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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("Blacklist") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlockedCmdOrMdl", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("BlockedCommands") - .HasForeignKey("BotConfigId"); - - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("BlockedModules") - .HasForeignKey("BotConfigId1"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar") - .WithMany("Bases") - .HasForeignKey("ClashWarId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Applicants") - .HasForeignKey("ClubId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Bans") - .HasForeignKey("ClubId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Owner") - .WithOne() - .HasForeignKey("NadekoBot.Services.Database.Models.ClubInfo", "OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("CommandAliases") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("CommandCooldowns") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandPrice", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("CommandPrices") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Users") - .HasForeignKey("ClubId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("EightBallResponses") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.XpSettings") - .WithMany("ExclusionList") - .HasForeignKey("XpSettingsId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilterInvitesChannelIds") - .HasForeignKey("GuildConfigId"); - - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilterWordsChannelIds") - .HasForeignKey("GuildConfigId1"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilteredWords") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FollowedStreams") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("GenerateCurrencyChannelIds") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany() - .HasForeignKey("LogSettingId"); - - b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission") - .WithMany() - .HasForeignKey("RootPermissionId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildRepeater", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("GuildRepeaters") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany("IgnoredChannels") - .HasForeignKey("LogSettingId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany("IgnoredVoicePresenceChannelIds") - .HasForeignKey("LogSettingId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("ModulePrefixes") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("MutedUsers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("NsfwBlacklistedTags") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => - { - b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") - .WithOne("Previous") - .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("Permissions") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("RotatingStatusMessages") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => - { - b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist") - .WithMany("Songs") - .HasForeignKey("MusicPlaylistId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("RaceAnimals") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("ShopEntries") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ShopEntry") - .WithMany("Items") - .HasForeignKey("ShopEntryId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("SlowmodeIgnoredRoles") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("SlowmodeIgnoredUsers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("StartupCommands") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings") - .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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings") - .WithMany("Whitelist") - .HasForeignKey("StreamRoleSettingsId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("UnmuteTimers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("VcRoleInfos") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Affinity") - .WithMany() - .HasForeignKey("AffinityId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Claimer") - .WithMany() - .HasForeignKey("ClaimerId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Waifu") - .WithOne() - .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo") - .WithMany("Items") - .HasForeignKey("WaifuInfoId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New") - .WithMany() - .HasForeignKey("NewId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Old") - .WithMany() - .HasForeignKey("OldId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("WarnPunishments") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => - { - b.HasOne("NadekoBot.Services.Database.Models.XpSettings") - .WithMany("RoleRewards") - .HasForeignKey("XpSettingsId"); - }); - - 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); - }); - } - } -} diff --git a/src/NadekoBot/Migrations/20170913022654_total-xp.cs b/src/NadekoBot/Migrations/20170913022654_total-xp.cs deleted file mode 100644 index f608e696..00000000 --- a/src/NadekoBot/Migrations/20170913022654_total-xp.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace NadekoBot.Migrations -{ - public partial class totalxp : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "TotalXp", - table: "DiscordUser", - nullable: false, - defaultValue: 0); - - migrationBuilder.Sql(MigrationQueries.TotalXp); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "TotalXp", - table: "DiscordUser"); - } - } -} diff --git a/src/NadekoBot/Migrations/20170915034808_club-admins.Designer.cs b/src/NadekoBot/Migrations/20170915034808_club-admins.Designer.cs deleted file mode 100644 index d7b4c4d9..00000000 --- a/src/NadekoBot/Migrations/20170915034808_club-admins.Designer.cs +++ /dev/null @@ -1,1951 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using NadekoBot.Services.Database; -using NadekoBot.Services.Database.Models; - -namespace NadekoBot.Migrations -{ - [DbContext(typeof(NadekoContext))] - [Migration("20170915034808_club-admins")] - partial class clubadmins - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { - modelBuilder - .HasAnnotation("ProductVersion", "1.1.1"); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Action"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Seconds"); - - b.Property("UserThreshold"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("AntiRaidSetting"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AntiSpamSettingId"); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.HasKey("Id"); - - b.HasIndex("AntiSpamSettingId"); - - b.ToTable("AntiSpamIgnore"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Action"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("MessageThreshold"); - - b.Property("MuteTime"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("AntiSpamSetting"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("ItemId"); - - b.Property("Type"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("BlacklistItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlockedCmdOrMdl", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("BotConfigId1"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.HasIndex("BotConfigId1"); - - b.ToTable("BlockedCmdOrMdl"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BetflipMultiplier"); - - b.Property("Betroll100Multiplier"); - - b.Property("Betroll67Multiplier"); - - b.Property("Betroll91Multiplier"); - - b.Property("BufferSize"); - - b.Property("CurrencyDropAmount"); - - b.Property("CurrencyDropAmountMax"); - - b.Property("CurrencyGenerationChance"); - - b.Property("CurrencyGenerationCooldown"); - - b.Property("CurrencyName"); - - b.Property("CurrencyPluralName"); - - b.Property("CurrencySign"); - - b.Property("CustomReactionsStartWith"); - - b.Property("DMHelpString"); - - b.Property("DateAdded"); - - b.Property("DefaultPrefix"); - - b.Property("ErrorColor"); - - b.Property("ForwardMessages"); - - b.Property("ForwardToAllOwners"); - - b.Property("HelpString"); - - b.Property("Locale"); - - b.Property("MigrationVersion"); - - b.Property("MinimumBetAmount"); - - b.Property("OkColor"); - - b.Property("PermissionVersion"); - - b.Property("RemindMessageFormat"); - - b.Property("RotatingStatuses"); - - b.Property("TriviaCurrencyReward"); - - b.Property("XpMinutesTimeout") - .ValueGeneratedOnAdd() - .HasDefaultValue(5); - - b.Property("XpPerMessage") - .ValueGeneratedOnAdd() - .HasDefaultValue(3); - - b.HasKey("Id"); - - b.ToTable("BotConfig"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BaseDestroyed"); - - b.Property("CallUser"); - - b.Property("ClashWarId"); - - b.Property("DateAdded"); - - b.Property("SequenceNumber"); - - b.Property("Stars"); - - b.Property("TimeAdded"); - - b.HasKey("Id"); - - b.HasIndex("ClashWarId"); - - b.ToTable("ClashCallers"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("EnemyClan"); - - b.Property("GuildId"); - - b.Property("Size"); - - b.Property("StartedAt"); - - b.Property("WarState"); - - b.HasKey("Id"); - - b.ToTable("ClashOfClans"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b => - { - b.Property("ClubId"); - - b.Property("UserId"); - - b.HasKey("ClubId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("ClubApplicants"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b => - { - b.Property("ClubId"); - - b.Property("UserId"); - - b.HasKey("ClubId", "UserId"); - - b.HasIndex("UserId"); - - b.ToTable("ClubBans"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Discrim"); - - b.Property("ImageUrl"); - - b.Property("MinimumLevelReq"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(20); - - b.Property("OwnerId"); - - b.Property("Xp"); - - b.HasKey("Id"); - - b.HasAlternateKey("Name", "Discrim"); - - b.HasIndex("OwnerId") - .IsUnique(); - - b.ToTable("Clubs"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Mapping"); - - b.Property("Trigger"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("CommandAlias"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("CommandName"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Seconds"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("CommandCooldown"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandPrice", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("CommandName"); - - b.Property("DateAdded"); - - b.Property("Price"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.HasIndex("Price") - .IsUnique(); - - b.ToTable("CommandPrice"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("InternalTrigger"); - - b.Property("Modifier"); - - b.Property("UnitType"); - - b.HasKey("Id"); - - b.ToTable("ConversionUnits"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("Currency"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("Reason"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.ToTable("CurrencyTransactions"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AutoDeleteTrigger"); - - b.Property("ContainsAnywhere"); - - b.Property("DateAdded"); - - b.Property("DmResponse"); - - b.Property("GuildId"); - - b.Property("IsRegex"); - - b.Property("OwnerOnly"); - - b.Property("Response"); - - b.Property("Trigger"); - - b.HasKey("Id"); - - b.ToTable("CustomReactions"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AvatarId"); - - b.Property("ClubId"); - - b.Property("DateAdded"); - - b.Property("Discriminator"); - - b.Property("IsClubAdmin"); - - b.Property("LastLevelUp") - .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 660, DateTimeKind.Local)); - - b.Property("LastXpGain"); - - b.Property("NotifyOnLevelUp"); - - b.Property("TotalXp"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasAlternateKey("UserId"); - - b.HasIndex("ClubId"); - - b.ToTable("DiscordUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Amount"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("Donators"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Text"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("EightBallResponses"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("ItemId"); - - b.Property("ItemType"); - - b.Property("XpSettingsId"); - - b.HasKey("Id"); - - b.HasIndex("XpSettingsId"); - - b.ToTable("ExcludedItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildConfigId1"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.HasIndex("GuildConfigId1"); - - b.ToTable("FilterChannelId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Word"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("FilteredWord"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildId"); - - b.Property("Type"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("FollowedStream"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("GCChannelId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AutoAssignRoleId"); - - b.Property("AutoDeleteByeMessages"); - - b.Property("AutoDeleteByeMessagesTimer"); - - b.Property("AutoDeleteGreetMessages"); - - b.Property("AutoDeleteGreetMessagesTimer"); - - b.Property("AutoDeleteSelfAssignedRoleMessages"); - - b.Property("ByeMessageChannelId"); - - b.Property("ChannelByeMessageText"); - - b.Property("ChannelGreetMessageText"); - - b.Property("CleverbotEnabled"); - - b.Property("DateAdded"); - - b.Property("DefaultMusicVolume"); - - b.Property("DeleteMessageOnCommand"); - - b.Property("DmGreetMessageText"); - - b.Property("ExclusiveSelfAssignedRoles"); - - b.Property("FilterInvites"); - - b.Property("FilterWords"); - - b.Property("GameVoiceChannel"); - - b.Property("GreetMessageChannelId"); - - b.Property("GuildId"); - - b.Property("Locale"); - - b.Property("LogSettingId"); - - b.Property("MuteRoleName"); - - b.Property("PermissionRole"); - - b.Property("Prefix"); - - b.Property("RootPermissionId"); - - b.Property("SendChannelByeMessage"); - - b.Property("SendChannelGreetMessage"); - - b.Property("SendDmGreetMessage"); - - b.Property("TimeZoneId"); - - b.Property("VerboseErrors"); - - b.Property("VerbosePermissions"); - - b.Property("VoicePlusTextEnabled"); - - b.Property("WarningsInitialized"); - - b.HasKey("Id"); - - b.HasIndex("GuildId") - .IsUnique(); - - b.HasIndex("LogSettingId"); - - b.HasIndex("RootPermissionId"); - - b.ToTable("GuildConfigs"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildRepeater", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("GuildId"); - - b.Property("Interval"); - - b.Property("Message"); - - b.Property("StartTimeOfDay"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("GuildRepeater"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("LogSettingId"); - - b.HasKey("Id"); - - b.HasIndex("LogSettingId"); - - b.ToTable("IgnoredLogChannels"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("LogSettingId"); - - b.HasKey("Id"); - - b.HasIndex("LogSettingId"); - - b.ToTable("IgnoredVoicePresenceCHannels"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelCreated"); - - b.Property("ChannelCreatedId"); - - b.Property("ChannelDestroyed"); - - b.Property("ChannelDestroyedId"); - - b.Property("ChannelId"); - - b.Property("ChannelUpdated"); - - b.Property("ChannelUpdatedId"); - - b.Property("DateAdded"); - - b.Property("IsLogging"); - - b.Property("LogOtherId"); - - b.Property("LogUserPresence"); - - b.Property("LogUserPresenceId"); - - b.Property("LogVoicePresence"); - - b.Property("LogVoicePresenceId"); - - b.Property("LogVoicePresenceTTSId"); - - b.Property("MessageDeleted"); - - b.Property("MessageDeletedId"); - - b.Property("MessageUpdated"); - - b.Property("MessageUpdatedId"); - - b.Property("UserBanned"); - - b.Property("UserBannedId"); - - b.Property("UserJoined"); - - b.Property("UserJoinedId"); - - b.Property("UserLeft"); - - b.Property("UserLeftId"); - - b.Property("UserMutedId"); - - b.Property("UserPresenceChannelId"); - - b.Property("UserUnbanned"); - - b.Property("UserUnbannedId"); - - b.Property("UserUpdated"); - - b.Property("UserUpdatedId"); - - b.Property("VoicePresenceChannelId"); - - b.HasKey("Id"); - - b.ToTable("LogSettings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("ModuleName"); - - b.Property("Prefix"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("ModulePrefixes"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Author"); - - b.Property("AuthorId"); - - b.Property("DateAdded"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.ToTable("MusicPlaylists"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("MutedUserId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Tag"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("NsfwBlacklitedTag"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("NextId"); - - b.Property("PrimaryTarget"); - - b.Property("PrimaryTargetId"); - - b.Property("SecondaryTarget"); - - b.Property("SecondaryTargetName"); - - b.Property("State"); - - b.HasKey("Id"); - - b.HasIndex("NextId") - .IsUnique(); - - b.ToTable("Permission"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Index"); - - b.Property("PrimaryTarget"); - - b.Property("PrimaryTargetId"); - - b.Property("SecondaryTarget"); - - b.Property("SecondaryTargetName"); - - b.Property("State"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("Permissionv2"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Status"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("PlayingStatus"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("MusicPlaylistId"); - - b.Property("Provider"); - - b.Property("ProviderType"); - - b.Property("Query"); - - b.Property("Title"); - - b.Property("Uri"); - - b.HasKey("Id"); - - b.HasIndex("MusicPlaylistId"); - - b.ToTable("PlaylistSong"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuthorId"); - - b.Property("AuthorName") - .IsRequired(); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("Keyword") - .IsRequired(); - - b.Property("Text") - .IsRequired(); - - b.HasKey("Id"); - - b.ToTable("Quotes"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("DateAdded"); - - b.Property("Icon"); - - b.Property("Name"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("RaceAnimals"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("ChannelId"); - - b.Property("DateAdded"); - - b.Property("IsPrivate"); - - b.Property("Message"); - - b.Property("ServerId"); - - b.Property("UserId"); - - b.Property("When"); - - b.HasKey("Id"); - - b.ToTable("Reminders"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RewardedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AmountRewardedThisMonth"); - - b.Property("DateAdded"); - - b.Property("LastReward"); - - b.Property("PatreonUserId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("RewardedUsers"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("RoleId"); - - b.HasKey("Id"); - - b.HasIndex("GuildId", "RoleId") - .IsUnique(); - - b.ToTable("SelfAssignableRoles"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AuthorId"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Index"); - - b.Property("Name"); - - b.Property("Price"); - - b.Property("RoleId"); - - b.Property("RoleName"); - - b.Property("Type"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("ShopEntry"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("ShopEntryId"); - - b.Property("Text"); - - b.HasKey("Id"); - - b.HasIndex("ShopEntryId"); - - b.ToTable("ShopEntryItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("RoleId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("SlowmodeIgnoredRole"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("SlowmodeIgnoredUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("BotConfigId"); - - b.Property("ChannelId"); - - b.Property("ChannelName"); - - b.Property("CommandText"); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("GuildName"); - - b.Property("Index"); - - b.Property("VoiceChannelId"); - - b.Property("VoiceChannelName"); - - b.HasKey("Id"); - - b.HasIndex("BotConfigId"); - - b.ToTable("StartupCommand"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("StreamRoleSettingsId"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("StreamRoleSettingsId"); - - b.ToTable("StreamRoleBlacklistedUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleSettings", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AddRoleId"); - - b.Property("DateAdded"); - - b.Property("Enabled"); - - b.Property("FromRoleId"); - - b.Property("GuildConfigId"); - - b.Property("Keyword"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("StreamRoleSettings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("StreamRoleSettingsId"); - - b.Property("UserId"); - - b.Property("Username"); - - b.HasKey("Id"); - - b.HasIndex("StreamRoleSettingsId"); - - b.ToTable("StreamRoleWhitelistedUser"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("UnmuteAt"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("UnmuteTimer"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UserPokeTypes", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("UserId"); - - b.Property("type"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("PokeGame"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AwardedXp"); - - b.Property("DateAdded"); - - b.Property("GuildId"); - - b.Property("LastLevelUp") - .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 665, DateTimeKind.Local)); - - b.Property("NotifyOnLevelUp"); - - b.Property("UserId"); - - b.Property("Xp"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "GuildId") - .IsUnique(); - - b.ToTable("UserXpStats"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("RoleId"); - - b.Property("VoiceChannelId"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("VcRoleInfo"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("AffinityId"); - - b.Property("ClaimerId"); - - b.Property("DateAdded"); - - b.Property("Price"); - - b.Property("WaifuId"); - - b.HasKey("Id"); - - b.HasIndex("AffinityId"); - - b.HasIndex("ClaimerId"); - - b.HasIndex("WaifuId") - .IsUnique(); - - b.ToTable("WaifuInfo"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Item"); - - b.Property("ItemEmoji"); - - b.Property("Price"); - - b.Property("WaifuInfoId"); - - b.HasKey("Id"); - - b.HasIndex("WaifuInfoId"); - - b.ToTable("WaifuItem"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("NewId"); - - b.Property("OldId"); - - b.Property("UpdateType"); - - b.Property("UserId"); - - 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(); - - b.Property("DateAdded"); - - b.Property("Forgiven"); - - b.Property("ForgivenBy"); - - b.Property("GuildId"); - - b.Property("Moderator"); - - b.Property("Reason"); - - b.Property("UserId"); - - b.HasKey("Id"); - - b.ToTable("Warnings"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("Count"); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("Punishment"); - - b.Property("Time"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId"); - - b.ToTable("WarningPunishment"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("Level"); - - b.Property("RoleId"); - - b.Property("XpSettingsId"); - - b.HasKey("Id"); - - b.HasAlternateKey("Level"); - - b.HasIndex("XpSettingsId"); - - b.ToTable("XpRoleReward"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b => - { - b.Property("Id") - .ValueGeneratedOnAdd(); - - b.Property("DateAdded"); - - b.Property("GuildConfigId"); - - b.Property("NotifyMessage"); - - b.Property("ServerExcluded"); - - b.Property("XpRoleRewardExclusive"); - - b.HasKey("Id"); - - b.HasIndex("GuildConfigId") - .IsUnique(); - - b.ToTable("XpSettings"); - }); - - 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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiSpamIgnore", b => - { - b.HasOne("NadekoBot.Services.Database.Models.AntiSpamSetting") - .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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("Blacklist") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.BlockedCmdOrMdl", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("BlockedCommands") - .HasForeignKey("BotConfigId"); - - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("BlockedModules") - .HasForeignKey("BotConfigId1"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar") - .WithMany("Bases") - .HasForeignKey("ClashWarId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubApplicants", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Applicants") - .HasForeignKey("ClubId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubBans", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Bans") - .HasForeignKey("ClubId") - .OnDelete(DeleteBehavior.Cascade); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ClubInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Owner") - .WithOne() - .HasForeignKey("NadekoBot.Services.Database.Models.ClubInfo", "OwnerId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandAlias", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("CommandAliases") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("CommandCooldowns") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandPrice", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("CommandPrices") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.DiscordUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ClubInfo", "Club") - .WithMany("Users") - .HasForeignKey("ClubId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("EightBallResponses") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.XpSettings") - .WithMany("ExclusionList") - .HasForeignKey("XpSettingsId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilterInvitesChannelIds") - .HasForeignKey("GuildConfigId"); - - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilterWordsChannelIds") - .HasForeignKey("GuildConfigId1"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FilteredWords") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("FollowedStreams") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("GenerateCurrencyChannelIds") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany() - .HasForeignKey("LogSettingId"); - - b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission") - .WithMany() - .HasForeignKey("RootPermissionId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildRepeater", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("GuildRepeaters") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany("IgnoredChannels") - .HasForeignKey("LogSettingId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => - { - b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") - .WithMany("IgnoredVoicePresenceChannelIds") - .HasForeignKey("LogSettingId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("ModulePrefixes") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.MutedUserId", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("MutedUsers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.NsfwBlacklitedTag", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("NsfwBlacklistedTags") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => - { - b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") - .WithOne("Previous") - .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.Permissionv2", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("Permissions") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("RotatingStatusMessages") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => - { - b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist") - .WithMany("Songs") - .HasForeignKey("MusicPlaylistId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("RaceAnimals") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntry", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("ShopEntries") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.ShopEntryItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.ShopEntry") - .WithMany("Items") - .HasForeignKey("ShopEntryId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredRole", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("SlowmodeIgnoredRoles") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.SlowmodeIgnoredUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("SlowmodeIgnoredUsers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StartupCommand", b => - { - b.HasOne("NadekoBot.Services.Database.Models.BotConfig") - .WithMany("StartupCommands") - .HasForeignKey("BotConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleBlacklistedUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings") - .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); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.StreamRoleWhitelistedUser", b => - { - b.HasOne("NadekoBot.Services.Database.Models.StreamRoleSettings") - .WithMany("Whitelist") - .HasForeignKey("StreamRoleSettingsId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.UnmuteTimer", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("UnmuteTimers") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("VcRoleInfos") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuInfo", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Affinity") - .WithMany() - .HasForeignKey("AffinityId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Claimer") - .WithMany() - .HasForeignKey("ClaimerId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Waifu") - .WithOne() - .HasForeignKey("NadekoBot.Services.Database.Models.WaifuInfo", "WaifuId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuItem", b => - { - b.HasOne("NadekoBot.Services.Database.Models.WaifuInfo") - .WithMany("Items") - .HasForeignKey("WaifuInfoId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WaifuUpdate", b => - { - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "New") - .WithMany() - .HasForeignKey("NewId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "Old") - .WithMany() - .HasForeignKey("OldId"); - - b.HasOne("NadekoBot.Services.Database.Models.DiscordUser", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.WarningPunishment", b => - { - b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") - .WithMany("WarnPunishments") - .HasForeignKey("GuildConfigId"); - }); - - modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b => - { - b.HasOne("NadekoBot.Services.Database.Models.XpSettings") - .WithMany("RoleRewards") - .HasForeignKey("XpSettingsId"); - }); - - 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); - }); - } - } -} diff --git a/src/NadekoBot/Migrations/20170915034808_club-admins.cs b/src/NadekoBot/Migrations/20170915034808_club-admins.cs deleted file mode 100644 index b1c0d3e6..00000000 --- a/src/NadekoBot/Migrations/20170915034808_club-admins.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace NadekoBot.Migrations -{ - public partial class clubadmins : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "IsClubAdmin", - table: "DiscordUser", - nullable: false, - defaultValue: false); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "IsClubAdmin", - table: "DiscordUser"); - } - } -} diff --git a/src/NadekoBot/Migrations/MigrationQueries.cs b/src/NadekoBot/Migrations/MigrationQueries.cs index b0d8413a..201f0c34 100644 --- a/src/NadekoBot/Migrations/MigrationQueries.cs +++ b/src/NadekoBot/Migrations/MigrationQueries.cs @@ -34,9 +34,5 @@ INSERT INTO DiscordUser FROM DiscordUser_tmp; DROP TABLE DiscordUser_tmp;"; - public static string TotalXp { get; } = -@"UPDATE DiscordUser -SET TotalXp = ifnull((SELECT SUM(Xp) FROM UserXpStats WHERE UserId = DiscordUser.UserId), 0)"; - } } \ No newline at end of file diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index cb6b041e..25117604 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -462,18 +462,14 @@ namespace NadekoBot.Migrations b.Property("Discriminator"); - b.Property("IsClubAdmin"); - b.Property("LastLevelUp") .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 660, DateTimeKind.Local)); + .HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 236, DateTimeKind.Local)); b.Property("LastXpGain"); b.Property("NotifyOnLevelUp"); - b.Property("TotalXp"); - b.Property("UserId"); b.Property("Username"); @@ -1366,7 +1362,7 @@ namespace NadekoBot.Migrations b.Property("LastLevelUp") .ValueGeneratedOnAdd() - .HasDefaultValue(new DateTime(2017, 9, 15, 5, 48, 8, 665, DateTimeKind.Local)); + .HasDefaultValue(new DateTime(2017, 9, 11, 22, 0, 31, 238, DateTimeKind.Local)); b.Property("NotifyOnLevelUp"); diff --git a/src/NadekoBot/Modules/Administration/SelfCommands.cs b/src/NadekoBot/Modules/Administration/SelfCommands.cs index 32d902df..622e1b6b 100644 --- a/src/NadekoBot/Modules/Administration/SelfCommands.cs +++ b/src/NadekoBot/Modules/Administration/SelfCommands.cs @@ -30,9 +30,8 @@ namespace NadekoBot.Modules.Administration private readonly IImagesService _images; private readonly MusicService _music; private readonly IBotConfigProvider _bc; - private readonly NadekoBot _bot; - public SelfCommands(DbService db, NadekoBot bot, DiscordSocketClient client, + public SelfCommands(DbService db, DiscordSocketClient client, MusicService music, IImagesService images, IBotConfigProvider bc) { _db = db; @@ -40,7 +39,6 @@ namespace NadekoBot.Modules.Administration _images = images; _music = music; _bc = bc; - _bot = bot; } [NadekoCommand, Usage, Description, Aliases] @@ -351,7 +349,7 @@ namespace NadekoBot.Modules.Administration [OwnerOnly] public async Task SetGame([Remainder] string game = null) { - await _bot.SetGameAsync(game).ConfigureAwait(false); + await _client.SetGameAsync(game).ConfigureAwait(false); await ReplyConfirmLocalized("set_game").ConfigureAwait(false); } diff --git a/src/NadekoBot/Modules/Administration/Services/PlayingRotateService.cs b/src/NadekoBot/Modules/Administration/Services/PlayingRotateService.cs index d0cd5eef..9786d085 100644 --- a/src/NadekoBot/Modules/Administration/Services/PlayingRotateService.cs +++ b/src/NadekoBot/Modules/Administration/Services/PlayingRotateService.cs @@ -7,7 +7,6 @@ using NadekoBot.Modules.Music.Services; using NadekoBot.Services; using NadekoBot.Services.Database.Models; using NLog; -using System.Threading.Tasks; namespace NadekoBot.Modules.Administration.Services { @@ -17,7 +16,6 @@ namespace NadekoBot.Modules.Administration.Services private readonly DiscordSocketClient _client; private readonly MusicService _music; private readonly Logger _log; - private readonly IDataCache _cache; private readonly Replacer _rep; private readonly DbService _db; private readonly IBotConfigProvider _bcp; @@ -29,60 +27,50 @@ namespace NadekoBot.Modules.Administration.Services public int Index { get; set; } } - public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, - MusicService music, DbService db, IDataCache cache, NadekoBot bot) + public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, MusicService music, DbService db) { _client = client; _bcp = bcp; _music = music; _db = db; _log = LogManager.GetCurrentClassLogger(); - _cache = cache; + _rep = new ReplacementBuilder() + .WithClient(client) + .WithStats(client) + .WithMusic(music) + .Build(); - if (client.ShardId == 0) + _t = new Timer(async (objState) => { - - _rep = new ReplacementBuilder() - .WithClient(client) - .WithStats(client) - .WithMusic(music) - .Build(); - - _t = new Timer(async (objState) => + try { - try - { - bcp.Reload(); + bcp.Reload(); - var state = (TimerState)objState; - if (!BotConfig.RotatingStatuses) - return; - if (state.Index >= BotConfig.RotatingStatusMessages.Count) - state.Index = 0; + var state = (TimerState)objState; + if (!BotConfig.RotatingStatuses) + return; + if (state.Index >= BotConfig.RotatingStatusMessages.Count) + state.Index = 0; - if (!BotConfig.RotatingStatusMessages.Any()) - return; - var status = BotConfig.RotatingStatusMessages[state.Index++].Status; - if (string.IsNullOrWhiteSpace(status)) - return; + if (!BotConfig.RotatingStatusMessages.Any()) + return; + var status = BotConfig.RotatingStatusMessages[state.Index++].Status; + if (string.IsNullOrWhiteSpace(status)) + return; - status = _rep.Replace(status); + status = _rep.Replace(status); - try - { - await bot.SetGameAsync(status).ConfigureAwait(false); - } - catch (Exception ex) - { - _log.Warn(ex); - } - } + try { await client.SetGameAsync(status).ConfigureAwait(false); } catch (Exception ex) { - _log.Warn("Rotating playing status errored.\n" + ex); + _log.Warn(ex); } - }, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); - } + } + catch (Exception ex) + { + _log.Warn("Rotating playing status errored.\n" + ex); + } + }, new TimerState(), TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); } } } diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index 33af0699..9867dbcb 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -58,7 +58,8 @@ namespace NadekoBot.Modules.CustomReactions if (channel == null) { - await _service.AddGcr(cr).ConfigureAwait(false); + Array.Resize(ref _service.GlobalReactions, _service.GlobalReactions.Length + 1); + _service.GlobalReactions[_service.GlobalReactions.Length - 1] = cr; } else { @@ -236,7 +237,8 @@ namespace NadekoBot.Modules.CustomReactions if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null) { uow.CustomReactions.Remove(toDelete); - await _service.DelGcr(toDelete.Id); + //todo 91 i can dramatically improve performance of this, if Ids are ordered. + _service.GlobalReactions = _service.GlobalReactions.Where(cr => cr?.Id != toDelete.Id).ToArray(); success = true; } else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId) diff --git a/src/NadekoBot/Modules/CustomReactions/Services/CustomReactionsService.cs b/src/NadekoBot/Modules/CustomReactions/Services/CustomReactionsService.cs index 4cada529..2944ab6c 100644 --- a/src/NadekoBot/Modules/CustomReactions/Services/CustomReactionsService.cs +++ b/src/NadekoBot/Modules/CustomReactions/Services/CustomReactionsService.cs @@ -15,7 +15,6 @@ using NadekoBot.Modules.CustomReactions.Extensions; using NadekoBot.Modules.Permissions.Common; using NadekoBot.Modules.Permissions.Services; using NadekoBot.Services.Impl; -using Newtonsoft.Json; namespace NadekoBot.Modules.CustomReactions.Services { @@ -33,11 +32,9 @@ namespace NadekoBot.Modules.CustomReactions.Services private readonly CommandHandler _cmd; private readonly IBotConfigProvider _bc; private readonly NadekoStrings _strings; - private readonly IDataCache _cache; public CustomReactionsService(PermissionService perms, DbService db, NadekoStrings strings, - DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow, - IDataCache cache) + DiscordSocketClient client, CommandHandler cmd, IBotConfigProvider bc, IUnitOfWork uow) { _log = LogManager.GetCurrentClassLogger(); _db = db; @@ -46,38 +43,12 @@ namespace NadekoBot.Modules.CustomReactions.Services _cmd = cmd; _bc = bc; _strings = strings; - _cache = cache; - - var sub = _cache.Redis.GetSubscriber(); - sub.Subscribe("gcr.added", (ch, msg) => - { - Array.Resize(ref GlobalReactions, GlobalReactions.Length + 1); - GlobalReactions[GlobalReactions.Length - 1] = JsonConvert.DeserializeObject(msg); - }, StackExchange.Redis.CommandFlags.FireAndForget); - sub.Subscribe("gcr.deleted", (ch, msg) => - { - var id = int.Parse(msg); - GlobalReactions = GlobalReactions.Where(cr => cr?.Id != id).ToArray(); - }, StackExchange.Redis.CommandFlags.FireAndForget); - + var items = uow.CustomReactions.GetAll(); - GuildReactions = new ConcurrentDictionary(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => g.ToArray())); GlobalReactions = items.Where(g => g.GuildId == null || g.GuildId == 0).ToArray(); } - public Task AddGcr(CustomReaction cr) - { - var sub = _cache.Redis.GetSubscriber(); - return sub.PublishAsync("gcr.added", JsonConvert.SerializeObject(cr)); - } - - public Task DelGcr(int id) - { - var sub = _cache.Redis.GetSubscriber(); - return sub.PublishAsync("gcr.deleted", id); - } - public void ClearStats() => ReactionStats.Clear(); public CustomReaction TryGetCustomReaction(IUserMessage umsg) diff --git a/src/NadekoBot/Modules/Gambling/FlowerShopCommands.cs b/src/NadekoBot/Modules/Gambling/FlowerShopCommands.cs index 6f50b7c3..660b0d33 100644 --- a/src/NadekoBot/Modules/Gambling/FlowerShopCommands.cs +++ b/src/NadekoBot/Modules/Gambling/FlowerShopCommands.cs @@ -331,7 +331,7 @@ namespace NadekoBot.Modules.Gambling var embed = new EmbedBuilder().WithOkColor(); if (entry.Type == ShopEntryType.Role) - return embed.AddField(efb => efb.WithName(GetText("name")).WithValue(GetText("shop_role", Format.Bold(Context.Guild.GetRole(entry.RoleId)?.Name ?? "MISSING_ROLE"))).WithIsInline(true)) + return embed.AddField(efb => efb.WithName(GetText("name")).WithValue(GetText("shop_role", Format.Bold(entry.RoleName))).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("price")).WithValue(entry.Price.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("type")).WithValue(entry.Type.ToString()).WithIsInline(true)); else if (entry.Type == ShopEntryType.List) @@ -349,7 +349,7 @@ namespace NadekoBot.Modules.Gambling { if (entry.Type == ShopEntryType.Role) { - return GetText("shop_role", Format.Bold(Context.Guild.GetRole(entry.RoleId)?.Name ?? "MISSING_ROLE")); + return GetText("shop_role", Format.Bold(entry.RoleName)); } else if (entry.Type == ShopEntryType.List) { diff --git a/src/NadekoBot/Modules/Games/Games.cs b/src/NadekoBot/Modules/Games/Games.cs index 07fd450e..4d7a0ea3 100644 --- a/src/NadekoBot/Modules/Games/Games.cs +++ b/src/NadekoBot/Modules/Games/Games.cs @@ -38,7 +38,7 @@ namespace NadekoBot.Modules.Games } [NadekoCommand, Usage, Description, Aliases] - public async Task EightBall([Remainder] string question = null) + public async Task _8Ball([Remainder] string question = null) { if (string.IsNullOrWhiteSpace(question)) return; diff --git a/src/NadekoBot/Modules/Music/Common/SongBuffer.cs b/src/NadekoBot/Modules/Music/Common/SongBuffer.cs index 2193877f..8f76be79 100644 --- a/src/NadekoBot/Modules/Music/Common/SongBuffer.cs +++ b/src/NadekoBot/Modules/Music/Common/SongBuffer.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; using System.IO; using System.Threading; +using System.Threading.Tasks; namespace NadekoBot.Modules.Music.Common { @@ -17,16 +18,27 @@ namespace NadekoBot.Modules.Music.Common public string SongUri { get; private set; } + //private volatile bool restart = false; + public SongBuffer(string songUri, string skipTo, bool isLocal) { _log = LogManager.GetCurrentClassLogger(); + //_log.Warn(songUri); this.SongUri = songUri; this._isLocal = isLocal; try { this.p = StartFFmpegProcess(SongUri, 0); + var t = Task.Run(() => + { + this.p.BeginErrorReadLine(); + this.p.ErrorDataReceived += P_ErrorDataReceived; + this.p.WaitForExit(); + }); + this._outStream = this.p.StandardOutput.BaseStream; + } catch (System.ComponentModel.Win32Exception) { @@ -56,14 +68,113 @@ Check the guides for your platform on how to setup ffmpeg correctly: Arguments = args, UseShellExecute = false, RedirectStandardOutput = true, - RedirectStandardError = false, + RedirectStandardError = true, CreateNoWindow = true, }); } + private void P_ErrorDataReceived(object sender, DataReceivedEventArgs e) + { + if (string.IsNullOrWhiteSpace(e.Data)) + return; + _log.Error(">>> " + e.Data); + if (e.Data?.Contains("Error in the pull function") == true) + { + _log.Error("Ignore this."); + //restart = true; + } + } + private readonly object locker = new object(); private readonly bool _isLocal; + public Task StartBuffering(CancellationToken cancelToken) + { + var toReturn = new TaskCompletionSource(); + var _ = Task.Run(() => + { + try + { + + ////int maxLoopsPerSec = 25; + //var sw = Stopwatch.StartNew(); + ////var delay = 1000 / maxLoopsPerSec; + //int currentLoops = 0; + //int _bytesSent = 0; + //try + //{ + // //do + // //{ + // // if (restart) + // // { + // // var cur = _bytesSent / 3840 / (1000 / 20.0f); + // // _log.Info("Restarting"); + // // try { this.p.StandardOutput.Dispose(); } catch { } + // // try { this.p.Dispose(); } catch { } + // // this.p = StartFFmpegProcess(SongUri, cur); + // // } + // // restart = false; + // ++currentLoops; + // byte[] buffer = new byte[readSize]; + // int bytesRead = 1; + // while (!cancelToken.IsCancellationRequested && !this.p.HasExited) + // { + // bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, readSize, cancelToken).ConfigureAwait(false); + // _bytesSent += bytesRead; + // if (bytesRead == 0) + // break; + // bool written; + // do + // { + // lock (locker) + // written = _outStream.Write(buffer, 0, bytesRead); + // if (!written) + // await Task.Delay(2000, cancelToken); + // } + // while (!written && !cancelToken.IsCancellationRequested); + // lock (locker) + // if (_outStream.Length > 200_000 || bytesRead == 0) + // if (toReturn.TrySetResult(true)) + // _log.Info("Prebuffering finished in {0}", sw.Elapsed.TotalSeconds.ToString("F2")); + + // //_log.Info(_outStream.Length); + // await Task.Delay(10); + // } + // //if (cancelToken.IsCancellationRequested) + // // _log.Info("Song canceled"); + // //else if (p.HasExited) + // // _log.Info("Song buffered completely (FFmpeg exited)"); + // //else if (bytesRead == 0) + // // _log.Info("Nothing read"); + // //} + // //while (restart && !cancelToken.IsCancellationRequested); + //return Task.CompletedTask; + toReturn.TrySetResult(true); + } + catch (System.ComponentModel.Win32Exception) + { + _log.Error(@"You have not properly installed or configured FFMPEG. +Please install and configure FFMPEG to play music. +Check the guides for your platform on how to setup ffmpeg correctly: + Windows Guide: https://goo.gl/OjKk8F + Linux Guide: https://goo.gl/ShjCUo"); + } + catch (OperationCanceledException) { } + catch (InvalidOperationException) { } // when ffmpeg is disposed + catch (Exception ex) + { + _log.Info(ex); + } + finally + { + if (toReturn.TrySetResult(false)) + _log.Info("Prebuffering failed"); + } + }, cancelToken); + + return toReturn.Task; + } + public int Read(byte[] b, int offset, int toRead) { lock (locker) @@ -92,4 +203,215 @@ Check the guides for your platform on how to setup ffmpeg correctly: this.p.Dispose(); } } -} \ No newline at end of file +} + +//namespace NadekoBot.Services.Music +//{ +// /// +// /// Create a buffer for a song file. It will create multiples files to ensure, that radio don't fill up disk space. +// /// It also help for large music by deleting files that are already seen. +// /// +// class SongBuffer : Stream +// { +// public SongBuffer(MusicPlayer musicPlayer, string basename, SongInfo songInfo, int skipTo, int maxFileSize) +// { +// MusicPlayer = musicPlayer; +// Basename = basename; +// SongInfo = songInfo; +// SkipTo = skipTo; +// MaxFileSize = maxFileSize; +// CurrentFileStream = new FileStream(this.GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); +// _log = LogManager.GetCurrentClassLogger(); +// } + +// MusicPlayer MusicPlayer { get; } + +// private string Basename { get; } + +// private SongInfo SongInfo { get; } + +// private int SkipTo { get; } + +// private int MaxFileSize { get; } = 2.MiB(); + +// private long FileNumber = -1; + +// private long NextFileToRead = 0; + +// public bool BufferingCompleted { get; private set; } = false; + +// private ulong CurrentBufferSize = 0; + +// private FileStream CurrentFileStream; +// private Logger _log; + +// public Task BufferSong(CancellationToken cancelToken) => +// Task.Run(async () => +// { +// Process p = null; +// FileStream outStream = null; +// try +// { +// p = Process.Start(new ProcessStartInfo +// { +// FileName = "ffmpeg", +// Arguments = $"-ss {SkipTo} -i {SongInfo.Uri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel quiet", +// UseShellExecute = false, +// RedirectStandardOutput = true, +// RedirectStandardError = false, +// CreateNoWindow = true, +// }); + +// byte[] buffer = new byte[81920]; +// int currentFileSize = 0; +// ulong prebufferSize = 100ul.MiB(); + +// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read); +// while (!p.HasExited) //Also fix low bandwidth +// { +// int bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false); +// if (currentFileSize >= MaxFileSize) +// { +// try +// { +// outStream.Dispose(); +// } +// catch { } +// outStream = new FileStream(Basename + "-" + ++FileNumber, FileMode.Append, FileAccess.Write, FileShare.Read); +// currentFileSize = bytesRead; +// } +// else +// { +// currentFileSize += bytesRead; +// } +// CurrentBufferSize += Convert.ToUInt64(bytesRead); +// await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false); +// while (CurrentBufferSize > prebufferSize) +// await Task.Delay(100, cancelToken); +// } +// BufferingCompleted = true; +// } +// catch (System.ComponentModel.Win32Exception) +// { +// var oldclr = Console.ForegroundColor; +// Console.ForegroundColor = ConsoleColor.Red; +// Console.WriteLine(@"You have not properly installed or configured FFMPEG. +//Please install and configure FFMPEG to play music. +//Check the guides for your platform on how to setup ffmpeg correctly: +// Windows Guide: https://goo.gl/OjKk8F +// Linux Guide: https://goo.gl/ShjCUo"); +// Console.ForegroundColor = oldclr; +// } +// catch (Exception ex) +// { +// Console.WriteLine($"Buffering stopped: {ex.Message}"); +// } +// finally +// { +// if (outStream != null) +// outStream.Dispose(); +// if (p != null) +// { +// try +// { +// p.Kill(); +// } +// catch { } +// p.Dispose(); +// } +// } +// }); + +// /// +// /// Return the next file to read, and delete the old one +// /// +// /// Name of the file to read +// private string GetNextFile() +// { +// string filename = Basename + "-" + NextFileToRead; + +// if (NextFileToRead != 0) +// { +// try +// { +// CurrentBufferSize -= Convert.ToUInt64(new FileInfo(Basename + "-" + (NextFileToRead - 1)).Length); +// File.Delete(Basename + "-" + (NextFileToRead - 1)); +// } +// catch { } +// } +// NextFileToRead++; +// return filename; +// } + +// private bool IsNextFileReady() +// { +// return NextFileToRead <= FileNumber; +// } + +// private void CleanFiles() +// { +// for (long i = NextFileToRead - 1; i <= FileNumber; i++) +// { +// try +// { +// File.Delete(Basename + "-" + i); +// } +// catch { } +// } +// } + +// //Stream part + +// public override bool CanRead => true; + +// public override bool CanSeek => false; + +// public override bool CanWrite => false; + +// public override long Length => (long)CurrentBufferSize; + +// public override long Position { get; set; } = 0; + +// public override void Flush() { } + +// public override int Read(byte[] buffer, int offset, int count) +// { +// int read = CurrentFileStream.Read(buffer, offset, count); +// if (read < count) +// { +// if (!BufferingCompleted || IsNextFileReady()) +// { +// CurrentFileStream.Dispose(); +// CurrentFileStream = new FileStream(GetNextFile(), FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write); +// read += CurrentFileStream.Read(buffer, read + offset, count - read); +// } +// if (read < count) +// Array.Clear(buffer, read, count - read); +// } +// return read; +// } + +// public override long Seek(long offset, SeekOrigin origin) +// { +// throw new NotImplementedException(); +// } + +// public override void SetLength(long value) +// { +// throw new NotImplementedException(); +// } + +// public override void Write(byte[] buffer, int offset, int count) +// { +// throw new NotImplementedException(); +// } + +// public new void Dispose() +// { +// CurrentFileStream.Dispose(); +// MusicPlayer.SongCancelSource.Cancel(); +// CleanFiles(); +// base.Dispose(); +// } +// } +//} \ No newline at end of file diff --git a/src/NadekoBot/Modules/NSFW/NSFW.cs b/src/NadekoBot/Modules/NSFW/NSFW.cs index 1ca27691..5e3591db 100644 --- a/src/NadekoBot/Modules/NSFW/NSFW.cs +++ b/src/NadekoBot/Modules/NSFW/NSFW.cs @@ -16,13 +16,9 @@ using NadekoBot.Modules.NSFW.Exceptions; namespace NadekoBot.Modules.NSFW { - // thanks to halitalf for adding autoboob and autobutt features :D public class NSFW : NadekoTopLevelModule { private static readonly ConcurrentDictionary _autoHentaiTimers = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary _autoBoobTimers = new ConcurrentDictionary(); - private static readonly ConcurrentDictionary _autoButtTimers = new ConcurrentDictionary(); - private static readonly ConcurrentHashSet _hentaiBombBlacklist = new ConcurrentHashSet(); private async Task InternalHentai(IMessageChannel channel, string tag, bool noError) @@ -53,34 +49,10 @@ namespace NadekoBot.Modules.NSFW .WithDescription($"[{GetText("tag")}: {tag}]({img})")) .ConfigureAwait(false); } - private async Task InternalBoobs(IMessageChannel Channel) - { - try - { - JToken obj; - obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.oboobs.ru/boobs/{new NadekoRandom().Next(0, 10330)}").ConfigureAwait(false))[0]; - await Channel.SendMessageAsync($"http://media.oboobs.ru/{obj["preview"]}").ConfigureAwait(false); - } - catch (Exception ex) - { - await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false); - } - } - - private async Task InternalButts(IMessageChannel Channel) - { - try - { - JToken obj; - obj = JArray.Parse(await _service.Http.GetStringAsync($"http://api.obutts.ru/butts/{new NadekoRandom().Next(0, 4335)}").ConfigureAwait(false))[0]; - await Channel.SendMessageAsync($"http://media.obutts.ru/{obj["preview"]}").ConfigureAwait(false); - } - catch (Exception ex) - { - await Channel.SendErrorAsync(ex.Message).ConfigureAwait(false); - } - } + [NadekoCommand, Usage, Description, Aliases] + public Task Hentai([Remainder] string tag = null) => + InternalHentai(Context.Channel, tag, false); #if !GLOBAL_NADEKO [NadekoCommand, Usage, Description, Aliases] [RequireUserPermission(ChannelPermission.ManageMessages)] @@ -93,7 +65,7 @@ namespace NadekoBot.Modules.NSFW if (!_autoHentaiTimers.TryRemove(Context.Channel.Id, out t)) return; t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer - await ReplyConfirmLocalized("stopped").ConfigureAwait(false); + await ReplyConfirmLocalized("autohentai_stopped").ConfigureAwait(false); return; } @@ -127,90 +99,8 @@ namespace NadekoBot.Modules.NSFW interval, string.Join(", ", tagsArr)).ConfigureAwait(false); } - - [NadekoCommand, Usage, Description, Aliases] - [RequireUserPermission(ChannelPermission.ManageMessages)] - public async Task AutoBoobs(int interval = 0) - { - Timer t; - - if (interval == 0) - { - if (!_autoBoobTimers.TryRemove(Context.Channel.Id, out t)) return; - - t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer - await ReplyConfirmLocalized("stopped").ConfigureAwait(false); - return; - } - - if (interval < 20) - return; - - t = new Timer(async (state) => - { - try - { - await InternalBoobs(Context.Channel).ConfigureAwait(false); - } - catch - { - // ignored - } - }, null, interval * 1000, interval * 1000); - - _autoBoobTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) => - { - old.Change(Timeout.Infinite, Timeout.Infinite); - return t; - }); - - await ReplyConfirmLocalized("started", interval).ConfigureAwait(false); - } - - [NadekoCommand, Usage, Description, Aliases] - [RequireUserPermission(ChannelPermission.ManageMessages)] - public async Task AutoButts(int interval = 0) - { - Timer t; - - if (interval == 0) - { - if (!_autoButtTimers.TryRemove(Context.Channel.Id, out t)) return; - - t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer - await ReplyConfirmLocalized("stopped").ConfigureAwait(false); - return; - } - - if (interval < 20) - return; - - t = new Timer(async (state) => - { - try - { - await InternalButts(Context.Channel).ConfigureAwait(false); - } - catch - { - // ignored - } - }, null, interval * 1000, interval * 1000); - - _autoButtTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) => - { - old.Change(Timeout.Infinite, Timeout.Infinite); - return t; - }); - - await ReplyConfirmLocalized("started", interval).ConfigureAwait(false); - } #endif - [NadekoCommand, Usage, Description, Aliases] - public Task Hentai([Remainder] string tag = null) => - InternalHentai(Context.Channel, tag, false); - [NadekoCommand, Usage, Description, Aliases] public async Task HentaiBomb([Remainder] string tag = null) { @@ -309,7 +199,7 @@ namespace NadekoBot.Modules.NSFW tag = tag.Trim().ToLowerInvariant(); var added = _service.ToggleBlacklistedTag(Context.Guild.Id, tag); - if (added) + if(added) await ReplyConfirmLocalized("blacklisted_tag_add", tag).ConfigureAwait(false); else await ReplyConfirmLocalized("blacklisted_tag_remove", tag).ConfigureAwait(false); diff --git a/src/NadekoBot/Modules/Permissions/Services/PermissionsService.cs b/src/NadekoBot/Modules/Permissions/Services/PermissionsService.cs index 9b218758..4329850c 100644 --- a/src/NadekoBot/Modules/Permissions/Services/PermissionsService.cs +++ b/src/NadekoBot/Modules/Permissions/Services/PermissionsService.cs @@ -135,11 +135,11 @@ namespace NadekoBot.Modules.Permissions.Services { var oldPrefixes = new[] { ".", ";", "!!", "!m", "!", "+", "-", "$", ">" }; uow._context.Database.ExecuteSqlCommand( - @"UPDATE Permissionv2 + $@"UPDATE {nameof(Permissionv2)} SET secondaryTargetName=trim(substr(secondaryTargetName, 3)) WHERE secondaryTargetName LIKE '!!%' OR secondaryTargetName LIKE '!m%'; -UPDATE Permissionv2 +UPDATE {nameof(Permissionv2)} SET secondaryTargetName=substr(secondaryTargetName, 2) WHERE secondaryTargetName LIKE '.%' OR secondaryTargetName LIKE '~%' OR diff --git a/src/NadekoBot/Modules/Searches/Common/SearchImageCacher.cs b/src/NadekoBot/Modules/Searches/Common/SearchImageCacher.cs index 8bd5d919..323a5eae 100644 --- a/src/NadekoBot/Modules/Searches/Common/SearchImageCacher.cs +++ b/src/NadekoBot/Modules/Searches/Common/SearchImageCacher.cs @@ -76,13 +76,11 @@ namespace NadekoBot.Modules.Searches.Common if (images.Length == 0) return null; var toReturn = images[_rng.Next(images.Length)]; -#if !GLOBAL_NADEKO foreach (var dledImg in images) { if(dledImg != toReturn) _cache.Add(dledImg); } -#endif return toReturn; } } diff --git a/src/NadekoBot/Modules/Searches/Services/AnimeSearchService.cs b/src/NadekoBot/Modules/Searches/Services/AnimeSearchService.cs index 1a372d8c..638db338 100644 --- a/src/NadekoBot/Modules/Searches/Services/AnimeSearchService.cs +++ b/src/NadekoBot/Modules/Searches/Services/AnimeSearchService.cs @@ -11,14 +11,10 @@ namespace NadekoBot.Modules.Searches.Services public class AnimeSearchService : INService { private readonly Logger _log; - private readonly IDataCache _cache; - private readonly HttpClient _http; - public AnimeSearchService(IDataCache cache) + public AnimeSearchService() { _log = LogManager.GetCurrentClassLogger(); - _cache = cache; - _http = new HttpClient(); } public async Task GetAnimeData(string query) @@ -29,16 +25,11 @@ namespace NadekoBot.Modules.Searches.Services { var link = "https://aniapi.nadekobot.me/anime/" + Uri.EscapeDataString(query.Replace("/", " ")); - link = link.ToLowerInvariant(); - var (ok, data) = await _cache.TryGetAnimeDataAsync(link).ConfigureAwait(false); - if (!ok) + using (var http = new HttpClient()) { - data = await _http.GetStringAsync(link).ConfigureAwait(false); - await _cache.SetAnimeDataAsync(link, data).ConfigureAwait(false); + var res = await http.GetStringAsync(link).ConfigureAwait(false); + return JsonConvert.DeserializeObject(res); } - - - return JsonConvert.DeserializeObject(data); } catch { @@ -53,17 +44,12 @@ namespace NadekoBot.Modules.Searches.Services try { - var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " ")); - link = link.ToLowerInvariant(); - var (ok, data) = await _cache.TryGetAnimeDataAsync(link).ConfigureAwait(false); - if (!ok) + var link = "https://aniapi.nadekobot.me/manga/" + Uri.EscapeDataString(query.Replace("/", " ")); + using (var http = new HttpClient()) { - data = await _http.GetStringAsync(link).ConfigureAwait(false); - await _cache.SetAnimeDataAsync(link, data).ConfigureAwait(false); + var res = await http.GetStringAsync(link).ConfigureAwait(false); + return JsonConvert.DeserializeObject(res); } - - - return JsonConvert.DeserializeObject(data); } catch { diff --git a/src/NadekoBot/Modules/Xp/Club.cs b/src/NadekoBot/Modules/Xp/Club.cs index 6ef7b5b5..a911ab4f 100644 --- a/src/NadekoBot/Modules/Xp/Club.cs +++ b/src/NadekoBot/Modules/Xp/Club.cs @@ -26,27 +26,6 @@ namespace NadekoBot.Modules.Xp _client = client; } - [NadekoCommand, Usage, Description, Aliases] - public async Task ClubAdmin([Remainder]IUser toAdmin) - { - bool admin; - try - { - admin = _service.ToggleAdmin(Context.User, toAdmin); - } - catch (InvalidOperationException) - { - await ReplyErrorLocalized("club_admin_error").ConfigureAwait(false); - return; - } - - if(admin) - await ReplyConfirmLocalized("club_admin_add", Format.Bold(toAdmin.ToString())).ConfigureAwait(false); - else - await ReplyConfirmLocalized("club_admin_remove", Format.Bold(toAdmin.ToString())).ConfigureAwait(false); - - } - [NadekoCommand, Usage, Description, Aliases] public async Task ClubCreate([Remainder]string clubName) { @@ -118,14 +97,7 @@ namespace NadekoBot.Modules.Xp .AddField("Level Req.", club.MinimumLevelReq.ToString(), true) .AddField("Members", string.Join("\n", club.Users .Skip(page * 10) - .Take(10) - .OrderByDescending(x => x.IsClubAdmin) - .Select(x => - { - if (x.IsClubAdmin) - return x.ToString() + "⭐"; - return x.ToString(); - })), false); + .Take(10)), false); if (Uri.IsWellFormedUriString(club.ImageUrl, UriKind.Absolute)) return embed.WithThumbnailUrl(club.ImageUrl); @@ -140,7 +112,7 @@ namespace NadekoBot.Modules.Xp if (--page < 0) return Task.CompletedTask; - var club = _service.GetClubWithBansAndApplications(Context.User.Id); + var club = _service.GetBansAndApplications(Context.User.Id); if (club == null) return ReplyErrorLocalized("club_not_exists"); @@ -159,8 +131,7 @@ namespace NadekoBot.Modules.Xp return new EmbedBuilder() .WithTitle(GetText("club_bans_for", club.ToString())) - .WithDescription(toShow) - .WithOkColor(); + .WithDescription(toShow); }, bans.Length / 10); } @@ -172,11 +143,11 @@ namespace NadekoBot.Modules.Xp if (--page < 0) return Task.CompletedTask; - var club = _service.GetClubWithBansAndApplications(Context.User.Id); + var club = _service.GetBansAndApplications(Context.User.Id); if (club == null) return ReplyErrorLocalized("club_not_exists"); - var apps = club + var bans = club .Applicants .Select(x => x.User) .ToArray(); @@ -184,17 +155,16 @@ namespace NadekoBot.Modules.Xp return Context.Channel.SendPaginatedConfirmAsync(_client, page, curPage => { - var toShow = string.Join("\n", apps + var toShow = string.Join("\n", bans .Skip(page * 10) .Take(10) .Select(x => x.ToString())); return new EmbedBuilder() .WithTitle(GetText("club_apps_for", club.ToString())) - .WithDescription(toShow) - .WithOkColor(); + .WithDescription(toShow); - }, apps.Length / 10); + }, bans.Length / 10); } [NadekoCommand, Usage, Description, Aliases] @@ -312,7 +282,7 @@ namespace NadekoBot.Modules.Xp } else { - await ReplyErrorLocalized("club_disband_error").ConfigureAwait(false); + await ReplyErrorLocalized("club_disaband_error").ConfigureAwait(false); } } diff --git a/src/NadekoBot/Modules/Xp/Services/ClubService.cs b/src/NadekoBot/Modules/Xp/Services/ClubService.cs index 362067eb..f8d08f66 100644 --- a/src/NadekoBot/Modules/Xp/Services/ClubService.cs +++ b/src/NadekoBot/Modules/Xp/Services/ClubService.cs @@ -27,11 +27,10 @@ namespace NadekoBot.Modules.Xp.Services { var du = uow.DiscordUsers.GetOrCreate(user); uow._context.SaveChanges(); - var xp = new LevelStats(du.TotalXp); + var xp = new LevelStats(uow.Xp.GetTotalUserXp(user.Id)); if (xp.Level >= 5 && du.Club == null) { - du.IsClubAdmin = true; du.Club = new ClubInfo() { Name = clubName, @@ -53,27 +52,6 @@ namespace NadekoBot.Modules.Xp.Services return true; } - public bool ToggleAdmin(IUser owner, IUser toAdmin) - { - bool newState; - using (var uow = _db.UnitOfWork) - { - var club = uow.Clubs.GetByOwner(owner.Id); - var adminUser = uow.DiscordUsers.GetOrCreate(toAdmin); - - if (club.OwnerId == adminUser.Id) - return true; - - if (club == null || club.Owner.UserId != owner.Id || - !club.Users.Contains(adminUser)) - throw new InvalidOperationException(); - - newState = adminUser.IsClubAdmin = !adminUser.IsClubAdmin; - uow.Complete(); - } - return newState; - } - public ClubInfo GetClubByMember(IUser user) { using (var uow = _db.UnitOfWork) @@ -129,7 +107,7 @@ namespace NadekoBot.Modules.Xp.Services uow._context.SaveChanges(); if (du.Club != null - || new LevelStats(du.TotalXp).Level < club.MinimumLevelReq + || new LevelStats(uow.Xp.GetTotalUserXp(user.Id)).Level < club.MinimumLevelReq || club.Bans.Any(x => x.UserId == du.Id) || club.Applicants.Any(x => x.UserId == du.Id)) { @@ -156,7 +134,11 @@ namespace NadekoBot.Modules.Xp.Services discordUser = null; using (var uow = _db.UnitOfWork) { - var club = uow.Clubs.GetByOwnerOrAdmin(clubOwnerUserId); + var club = uow.Clubs.GetByOwner(clubOwnerUserId, + set => set.Include(x => x.Applicants) + .ThenInclude(x => x.Club) + .Include(x => x.Applicants) + .ThenInclude(x => x.User)); if (club == null) return false; @@ -165,7 +147,6 @@ namespace NadekoBot.Modules.Xp.Services return false; applicant.User.Club = club; - applicant.User.IsClubAdmin = false; club.Applicants.Remove(applicant); //remove that user's all other applications @@ -178,11 +159,15 @@ namespace NadekoBot.Modules.Xp.Services return true; } - public ClubInfo GetClubWithBansAndApplications(ulong ownerUserId) + public ClubInfo GetBansAndApplications(ulong ownerUserId) { using (var uow = _db.UnitOfWork) { - return uow.Clubs.GetByOwnerOrAdmin(ownerUserId); + return uow.Clubs.GetByOwner(ownerUserId, + x => x.Include(y => y.Bans) + .ThenInclude(y => y.User) + .Include(y => y.Applicants) + .ThenInclude(y => y.User)); } } @@ -195,7 +180,6 @@ namespace NadekoBot.Modules.Xp.Services return false; du.Club = null; - du.IsClubAdmin = false; uow.Complete(); } return true; @@ -237,7 +221,9 @@ namespace NadekoBot.Modules.Xp.Services { using (var uow = _db.UnitOfWork) { - club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); + club = uow.Clubs.GetByOwner(ownerUserId, + set => set.Include(x => x.Applicants) + .ThenInclude(x => x.User)); if (club == null) return false; @@ -270,7 +256,9 @@ namespace NadekoBot.Modules.Xp.Services { using (var uow = _db.UnitOfWork) { - club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); + club = uow.Clubs.GetByOwner(ownerUserId, + set => set.Include(x => x.Bans) + .ThenInclude(x => x.User)); if (club == null) return false; @@ -289,7 +277,7 @@ namespace NadekoBot.Modules.Xp.Services { using (var uow = _db.UnitOfWork) { - club = uow.Clubs.GetByOwnerOrAdmin(ownerUserId); + club = uow.Clubs.GetByOwner(ownerUserId); if (club == null) return false; diff --git a/src/NadekoBot/Modules/Xp/Services/XpService.cs b/src/NadekoBot/Modules/Xp/Services/XpService.cs index 09fa7ec9..78dcc5f9 100644 --- a/src/NadekoBot/Modules/Xp/Services/XpService.cs +++ b/src/NadekoBot/Modules/Xp/Services/XpService.cs @@ -36,7 +36,6 @@ namespace NadekoBot.Modules.Xp.Services private readonly IImagesService _images; private readonly Logger _log; private readonly NadekoStrings _strings; - private readonly IDataCache _cache; private readonly FontCollection _fonts = new FontCollection(); public const int XP_REQUIRED_LVL_1 = 36; @@ -55,6 +54,9 @@ namespace NadekoBot.Modules.Xp.Services private readonly ConcurrentQueue _addMessageXp = new ConcurrentQueue(); + private readonly ConcurrentDictionary _imageStreams + = new ConcurrentDictionary(); + private readonly Timer updateXpTimer; private readonly HttpClient http = new HttpClient(); private FontFamily _usernameFontFamily; @@ -67,7 +69,7 @@ namespace NadekoBot.Modules.Xp.Services public XpService(CommandHandler cmd, IBotConfigProvider bc, IEnumerable allGuildConfigs, IImagesService images, - DbService db, NadekoStrings strings, IDataCache cache) + DbService db, NadekoStrings strings) { _db = db; _cmd = cmd; @@ -75,7 +77,6 @@ namespace NadekoBot.Modules.Xp.Services _images = images; _log = LogManager.GetCurrentClassLogger(); _strings = strings; - _cache = cache; //load settings allGuildConfigs = allGuildConfigs.Where(x => x.XpSettings != null); @@ -144,13 +145,12 @@ namespace NadekoBot.Modules.Xp.Services du.LastXpGain = DateTime.UtcNow; - var globalXp = du.TotalXp; + var globalXp = uow.Xp.GetTotalUserXp(item.Key.User.Id); var oldGlobalLevelData = new LevelStats(globalXp); var newGlobalLevelData = new LevelStats(globalXp + xp); var oldGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); usr.Xp += xp; - du.TotalXp += xp; if (du.Club != null) du.Club.Xp += xp; var newGuildLevelData = new LevelStats(usr.Xp + usr.AwardedXp); @@ -308,11 +308,11 @@ namespace NadekoBot.Modules.Xp.Services } } - public DiscordUser[] GetUserXps(int page) + public (ulong UserId, int TotalXp)[] GetUserXps(int page) { using (var uow = _db.UnitOfWork) { - return uow.DiscordUsers.GetUsersXpLeaderboardFor(page); + return uow.Xp.GetUsersFor(page); } } @@ -403,6 +403,17 @@ namespace NadekoBot.Modules.Xp.Services return _rewardedUsers.Add(userId); } + public LevelStats GetGlobalUserStats(ulong userId) + { + int totalXp; + using (var uow = _db.UnitOfWork) + { + totalXp = uow.Xp.GetTotalUserXp(userId); + } + + return new LevelStats(totalXp); + } + public FullUserStats GetUserStats(IGuildUser user) { DiscordUser du; @@ -414,8 +425,8 @@ namespace NadekoBot.Modules.Xp.Services { du = uow.DiscordUsers.GetOrCreate(user); stats = uow.Xp.GetOrCreateUser(user.GuildId, user.Id); - totalXp = du.TotalXp; - globalRank = uow.DiscordUsers.GetUserGlobalRanking(user.Id); + totalXp = uow.Xp.GetTotalUserXp(user.Id); + globalRank = uow.Xp.GetUserGlobalRanking(user.Id); guildRank = uow.Xp.GetUserGuildRanking(user.Id, user.GuildId); } @@ -539,7 +550,7 @@ namespace NadekoBot.Modules.Xp.Services } } - public Task GenerateImageAsync(IGuildUser user) + public Task> GenerateImageAsync(IGuildUser user) { return GenerateImageAsync(GetUserStats(user)); } @@ -555,166 +566,170 @@ namespace NadekoBot.Modules.Xp.Services _timeFont = _fonts.Find("Whitney-Bold").CreateFont(20); } - public Task GenerateImageAsync(FullUserStats stats) => Task.Run(async () => + public Task> GenerateImageAsync(FullUserStats stats) => Task.Run(async () => { - using (var img = Image.Load(_images.XpCard.ToArray())) + var img = Image.Load(_images.XpCard.ToArray()); + + var username = stats.User.ToString(); + var usernameFont = _usernameFontFamily + .CreateFont(username.Length <= 6 + ? 50 + : 50 - username.Length); + + img.DrawText("@" + username, usernameFont, Rgba32.White, + new PointF(130, 5)); + + // level + + img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White, + new PointF(47, 137)); + + img.DrawText(stats.Guild.Level.ToString(), _levelFont, Rgba32.White, + new PointF(47, 285)); + + //club name + + var clubName = stats.User.Club?.ToString() ?? "-"; + + var clubFont = _clubFontFamily + .CreateFont(clubName.Length <= 8 + ? 35 + : 35 - (clubName.Length / 2)); + + img.DrawText(clubName, clubFont, Rgba32.White, + new PointF(650 - clubName.Length * 10, 40)); + + var pen = new Pen(Rgba32.Black, 1); + var brush = Brushes.Solid(Rgba32.White); + var xpBgBrush = Brushes.Solid(new Rgba32(0, 0, 0, 0.4f)); + + var global = stats.Global; + var guild = stats.Guild; + + //xp bar + + img.FillPolygon(xpBgBrush, new[] { + new PointF(321, 104), + new PointF(321 + (450 * (global.LevelXp / (float)global.RequiredXp)), 104), + new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235), + new PointF(286, 235), + }); + img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen, + new PointF(430, 130)); + + img.FillPolygon(xpBgBrush, new[] { + new PointF(282, 248), + new PointF(282 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 248), + new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379), + new PointF(247, 379), + }); + img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen, + new PointF(400, 270)); + + if (stats.FullGuildStats.AwardedXp != 0) { - - var username = stats.User.ToString(); - var usernameFont = _usernameFontFamily - .CreateFont(username.Length <= 6 - ? 50 - : 50 - username.Length); - - img.DrawText("@" + username, usernameFont, Rgba32.White, - new PointF(130, 5)); - - // level - - img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White, - new PointF(47, 137)); - - img.DrawText(stats.Guild.Level.ToString(), _levelFont, Rgba32.White, - new PointF(47, 285)); - - //club name - - var clubName = stats.User.Club?.ToString() ?? "-"; - - var clubFont = _clubFontFamily - .CreateFont(clubName.Length <= 8 - ? 35 - : 35 - (clubName.Length / 2)); - - img.DrawText(clubName, clubFont, Rgba32.White, - new PointF(650 - clubName.Length * 10, 40)); - - var pen = new Pen(Rgba32.Black, 1); - var brush = Brushes.Solid(Rgba32.White); - var xpBgBrush = Brushes.Solid(new Rgba32(0, 0, 0, 0.4f)); - - var global = stats.Global; - var guild = stats.Guild; - - //xp bar - - img.FillPolygon(xpBgBrush, new[] { - new PointF(321, 104), - new PointF(321 + (450 * (global.LevelXp / (float)global.RequiredXp)), 104), - new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235), - new PointF(286, 235), - }); - img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen, - new PointF(430, 130)); - - img.FillPolygon(xpBgBrush, new[] { - new PointF(282, 248), - new PointF(282 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 248), - new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379), - new PointF(247, 379), - }); - img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen, - new PointF(400, 270)); - - if (stats.FullGuildStats.AwardedXp != 0) - { - var sign = stats.FullGuildStats.AwardedXp > 0 - ? "+ " - : ""; - img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _awardedFont, brush, pen, - new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335)); - } - - //ranking - - img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White, - new PointF(148, 170)); - - img.DrawText(stats.GuildRanking.ToString(), _rankFont, Rgba32.White, - new PointF(148, 317)); - - //time on this level - - string GetTimeSpent(DateTime time) - { - var offset = DateTime.UtcNow - time; - return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m"; - } - - img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _timeFont, Rgba32.White, - new PointF(50, 197)); - - img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White, - new PointF(50, 344)); - - //avatar - - if (stats.User.AvatarId != null) - { - try - { - var avatarUrl = stats.User.RealAvatarUrl(); - - var (succ, data) = await _cache.TryGetImageDataAsync(avatarUrl); - if (!succ) - { - using (var temp = await http.GetStreamAsync(avatarUrl)) - using (var tempDraw = Image.Load(temp).Resize(69, 70)) - { - ApplyRoundedCorners(tempDraw, 35); - data = tempDraw.ToStream().ToArray(); - } - - await _cache.SetImageDataAsync(avatarUrl, data); - } - var toDraw = Image.Load(data); - - - img.DrawImage(toDraw, - 1, - new Size(69, 70), - new Point(32, 10)); - } - catch (Exception ex) - { - _log.Warn(ex); - } - } - - //club image - - if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl)) - { - var imgUrl = stats.User.Club.ImageUrl; - try - { - var (succ, data) = await _cache.TryGetImageDataAsync(imgUrl); - if (!succ) - { - using (var temp = await http.GetStreamAsync(imgUrl)) - using (var tempDraw = Image.Load(temp).Resize(45, 45)) - { - ApplyRoundedCorners(tempDraw, 22.5f); - data = tempDraw.ToStream().ToArray(); - } - - await _cache.SetImageDataAsync(imgUrl, data); - } - var toDraw = Image.Load(data); - - img.DrawImage(toDraw, - 1, - new Size(45, 45), - new Point(722, 25)); - } - catch (Exception ex) - { - _log.Warn(ex); - } - } - - return img.Resize(432, 211).ToStream(); + var sign = stats.FullGuildStats.AwardedXp > 0 + ? "+ " + : ""; + img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _awardedFont, brush, pen, + new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335)); } + + //ranking + + img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White, + new PointF(148, 170)); + + img.DrawText(stats.GuildRanking.ToString(), _rankFont, Rgba32.White, + new PointF(148, 317)); + + //time on this level + + string GetTimeSpent(DateTime time) + { + var offset = DateTime.UtcNow - time; + return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m"; + } + + img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _timeFont, Rgba32.White, + new PointF(50, 197)); + + img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White, + new PointF(50, 344)); + + //avatar + + if (stats.User.AvatarId != null) + { + try + { + var avatarUrl = stats.User.RealAvatarUrl(); + + byte[] s; + if (!_imageStreams.TryGetValue(avatarUrl, out s)) + { + using (var temp = await http.GetStreamAsync(avatarUrl)) + { + var tempDraw = Image.Load(temp); + tempDraw = tempDraw.Resize(69, 70); + ApplyRoundedCorners(tempDraw, 35); + s = tempDraw.ToStream().ToArray(); + } + + _imageStreams.AddOrUpdate(avatarUrl, s, (k, v) => s); + } + var toDraw = Image.Load(s); + + + img.DrawImage(toDraw, + 1, + new Size(69, 70), + new Point(32, 10)); + } + catch (Exception ex) + { + _log.Warn(ex); + } + } + + //club image + + if (!string.IsNullOrWhiteSpace(stats.User.Club?.ImageUrl)) + { + var imgUrl = stats.User.Club.ImageUrl; + try + { + byte[] s; + if (!_imageStreams.TryGetValue(imgUrl, out s)) + { + using (var temp = await http.GetStreamAsync(imgUrl)) + { + var tempDraw = Image.Load(temp); + tempDraw = tempDraw.Resize(45, 45); + ApplyRoundedCorners(tempDraw, 22.5f); + s = tempDraw.ToStream().ToArray(); + } + + _imageStreams.AddOrUpdate(imgUrl, s, (k, v) => s); + } + var toDraw = Image.Load(s); + + img.DrawImage(toDraw, + 1, + new Size(45, 45), + new Point(722, 25)); + } + catch (Exception ex) + { + _log.Warn(ex); + } + } + + var arr = img.ToStream().ToArray(); + + //_log.Info("{0:F2} KB", arr.Length * 1.0f / 1.KB()); + + return img; }); diff --git a/src/NadekoBot/Modules/Xp/Xp.cs b/src/NadekoBot/Modules/Xp/Xp.cs index a3356372..ad687792 100644 --- a/src/NadekoBot/Modules/Xp/Xp.cs +++ b/src/NadekoBot/Modules/Xp/Xp.cs @@ -1,12 +1,10 @@ using Discord; using Discord.Commands; using Discord.WebSocket; -using NadekoBot.Common; using NadekoBot.Common.Attributes; using NadekoBot.Extensions; using NadekoBot.Modules.Xp.Common; using NadekoBot.Modules.Xp.Services; -using NadekoBot.Services; using NadekoBot.Services.Database.Models; using System.Diagnostics; using System.Linq; @@ -17,55 +15,23 @@ namespace NadekoBot.Modules.Xp public partial class Xp : NadekoTopLevelModule { private readonly DiscordSocketClient _client; - private readonly DbService _db; - public Xp(DiscordSocketClient client,DbService db) + public Xp(DiscordSocketClient client) { _client = client; - _db = db; } - //[NadekoCommand, Usage, Description, Aliases] - //[RequireContext(ContextType.Guild)] - //[OwnerOnly] - //public async Task Populate() - //{ - // var rng = new NadekoRandom(); - // using (var uow = _db.UnitOfWork) - // { - // for (var i = 0ul; i < 1000000; i++) - // { - // uow.DiscordUsers.Add(new DiscordUser() - // { - // AvatarId = i.ToString(), - // Discriminator = "1234", - // UserId = i, - // Username = i.ToString(), - // Club = null, - // }); - // var xp = uow.Xp.GetOrCreateUser(Context.Guild.Id, i); - // xp.Xp = rng.Next(100, 100000); - // } - // uow.Complete(); - // } - //} - [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - //[Ratelimit(30)] public async Task Experience([Remainder]IUser user = null) { user = user ?? Context.User; - var sw = Stopwatch.StartNew(); + await Context.Channel.TriggerTypingAsync(); var img = await _service.GenerateImageAsync((IGuildUser)user); - sw.Stop(); - _log.Info("Generating finished in {0:F2}s", sw.Elapsed.TotalSeconds); - sw.Restart(); - await Context.Channel.SendFileAsync(img, $"{user.Id}_xp.png") + + await Context.Channel.SendFileAsync(img.ToStream(), $"{user.Id}_xp.png") .ConfigureAwait(false); - sw.Stop(); - _log.Info("Sending finished in {0:F2}s", sw.Elapsed.TotalSeconds); } [NadekoCommand, Usage, Description, Aliases] @@ -74,7 +40,7 @@ namespace NadekoBot.Modules.Xp { page--; - if (page < 0 || page > 100) + if (page < 0) return Task.CompletedTask; var roles = _service.GetRoleRewards(Context.Guild.Id) @@ -203,7 +169,7 @@ namespace NadekoBot.Modules.Xp [RequireContext(ContextType.Guild)] public Task XpLeaderboard(int page = 1) { - if (--page < 0 || page > 100) + if (--page < 0) return Task.CompletedTask; return Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) => @@ -244,28 +210,32 @@ namespace NadekoBot.Modules.Xp [RequireContext(ContextType.Guild)] public async Task XpGlobalLeaderboard(int page = 1) { - if (--page < 0 || page > 100) + if (--page < 0) return; - var users = _service.GetUserXps(page); - var embed = new EmbedBuilder() - .WithTitle(GetText("global_leaderboard")) - .WithOkColor(); - - if (!users.Any()) - embed.WithDescription("-"); - else + await Context.Channel.SendPaginatedConfirmAsync(_client, page, async (curPage) => { - for (int i = 0; i < users.Length; i++) - { - var user = users[i]; - embed.AddField( - $"#{(i + 1 + page * 9)} {(user.ToString())}", - $"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp"); - } - } + var users = _service.GetUserXps(curPage); - await Context.Channel.EmbedAsync(embed); + var embed = new EmbedBuilder() + .WithTitle(GetText("global_leaderboard")) + .WithOkColor(); + + if (!users.Any()) + return embed.WithDescription("-"); + else + { + for (int i = 0; i < users.Length; i++) + { + var user = await Context.Guild.GetUserAsync(users[i].UserId).ConfigureAwait(false); + embed.AddField( + $"#{(i + 1 + curPage * 9)} {(user?.ToString() ?? users[i].UserId.ToString())}", + $"{GetText("level_x", LevelStats.FromXp(users[i].TotalXp).Level)} - {users[i].TotalXp}xp"); + } + + return embed; + } + }, addPaginatedFooter: false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index 95fd9574..a92380ca 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -20,8 +20,6 @@ using NadekoBot.Common.ShardCom; using NadekoBot.Common.TypeReaders; using NadekoBot.Common.TypeReaders.Models; using NadekoBot.Services.Database; -using StackExchange.Redis; -using Newtonsoft.Json; namespace NadekoBot { @@ -141,7 +139,6 @@ namespace NadekoBot .AddManual>(AllGuildConfigs) //todo wrap this .AddManual(this) .AddManual(uow) - .AddManual(new RedisCache()) .LoadFrom(Assembly.GetEntryAssembly()) .Build(); @@ -242,6 +239,13 @@ namespace NadekoBot #if GLOBAL_NADEKO isPublicNadeko = true; #endif + //_log.Info(string.Join(", ", CommandService.Commands + // .Distinct(x => x.Name + x.Module.Name) + // .SelectMany(x => x.Aliases) + // .GroupBy(x => x) + // .Where(x => x.Count() > 1) + // .Select(x => x.Key + $"({x.Count()})"))); + //unload modules which are not available on the public bot if(isPublicNadeko) @@ -252,7 +256,6 @@ namespace NadekoBot .ForEach(x => CommandService.RemoveModuleAsync(x)); Ready.TrySetResult(true); - HandleStatusChanges(); _log.Info($"Shard {Client.ShardId} ready."); //_log.Info(await stats.Print().ConfigureAwait(false)); } @@ -315,51 +318,5 @@ namespace NadekoBot } })).Start(); } - - private void HandleStatusChanges() - { - var sub = Services.GetService().Redis.GetSubscriber(); - sub.Subscribe("status.game_set", async (ch, game) => - { - try - { - var obj = new { Name = default(string) }; - obj = JsonConvert.DeserializeAnonymousType(game, obj); - await Client.SetGameAsync(obj.Name).ConfigureAwait(false); - } - catch (Exception ex) - { - _log.Warn(ex); - } - }, CommandFlags.FireAndForget); - - sub.Subscribe("status.stream_set", async (ch, streamData) => - { - try - { - var obj = new { Name = "", Url = "" }; - obj = JsonConvert.DeserializeAnonymousType(streamData, obj); - await Client.SetGameAsync(obj.Name, obj.Url, StreamType.Twitch).ConfigureAwait(false); - } - catch (Exception ex) - { - _log.Warn(ex); - } - }, CommandFlags.FireAndForget); - } - - public Task SetGameAsync(string game) - { - var obj = new { Name = game }; - var sub = Services.GetService().Redis.GetSubscriber(); - return sub.PublishAsync("status.game_set", JsonConvert.SerializeObject(obj)); - } - - public Task SetStreamAsync(string name, string url) - { - var obj = new { Name = name, Url = url }; - var sub = Services.GetService().Redis.GetSubscriber(); - return sub.PublishAsync("status.game_set", JsonConvert.SerializeObject(obj)); - } } } diff --git a/src/NadekoBot/NadekoBot.csproj b/src/NadekoBot/NadekoBot.csproj index da1a1e22..ff8ed03e 100644 --- a/src/NadekoBot/NadekoBot.csproj +++ b/src/NadekoBot/NadekoBot.csproj @@ -1,18 +1,30 @@  - netcoreapp2.0 - 2.0.0 - exe - $(AssetTargetFallback);dnxcore50;portable-net45+win8+wpa81 + General purpose Discord bot written in C#. + Kwoth + Kwoth + Kwoth + netcoreapp1.1 + true + NadekoBot + Exe + NadekoBot + 1.1.1 + $(PackageTargetFallback);dnxcore50;portable-net45+win8+wpa81 + false + false + false + false + False + 1.0.0.0 + 1.0.0.0 nadeko_icon.ico win7-x64 - Debug;Release;global_nadeko - latest - 1.9.1 + 1.4.1 $(VersionPrefix).$(VersionSuffix) $(VersionPrefix) @@ -47,24 +59,27 @@ - - - - + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -72,12 +87,22 @@ $(NoWarn);CS1573;CS1591 + + latest + + - true + latest - - + + + + + + + Designer + diff --git a/src/NadekoBot/NadekoBot.nuspec b/src/NadekoBot/NadekoBot.nuspec new file mode 100644 index 00000000..109f83d5 --- /dev/null +++ b/src/NadekoBot/NadekoBot.nuspec @@ -0,0 +1,15 @@ + + + + NadekoBot + 1.4.0-2$suffix$ + NadekoBot + Kwoth + Kwoth + General purpose discord chat bot written in C#. + nadeko;bot;nadekobot;discord bot + https://github.com/Kwoth/NadekoBot + https://choosealicense.com/licenses/unlicense/ + false + + \ No newline at end of file diff --git a/src/NadekoBot/NadekoBot.xproj.DotSettings b/src/NadekoBot/NadekoBot.xproj.DotSettings new file mode 100644 index 00000000..c5dd7773 --- /dev/null +++ b/src/NadekoBot/NadekoBot.xproj.DotSettings @@ -0,0 +1,7 @@ + + True + True + True + True + True + True \ No newline at end of file diff --git a/src/NadekoBot/Properties/AssemblyInfo.cs b/src/NadekoBot/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..ca3bd293 --- /dev/null +++ b/src/NadekoBot/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NadekoBot")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyInformationalVersion("1.0")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("f8225ac4-3cbc-40b4-bcf3-1cacf276bf29")] diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 957e8059..079f5fc4 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -3589,7 +3589,7 @@ `{0}xpex Role Excluded-Role` `{0}xpex Server` - Exclude a channel, role or current server from the xp system. + Exclude a user or a role from the xp system, or whole current server. xpnotify xpn @@ -3780,31 +3780,4 @@ Clears nsfw cache. - - clubadmin - - - `{0}clubadmin` - - - Assigns (or unassigns) staff role to the member of the club. Admins can ban, kick and accept applications. - - - autoboobs - - - Posts a boobs every X seconds. 20 seconds minimum. Provide no arguments to disable. - - - `{0}autoboobs 30` or `{0}autoboobs` - - - autobutts - - - Posts a butts every X seconds. 20 seconds minimum. Provide no arguments to disable. - - - `{0}autobutts 30` or `{0}autobutts` - diff --git a/src/NadekoBot/Services/Database/Models/CustomReaction.cs b/src/NadekoBot/Services/Database/Models/CustomReaction.cs index cd57bc35..2f268849 100644 --- a/src/NadekoBot/Services/Database/Models/CustomReaction.cs +++ b/src/NadekoBot/Services/Database/Models/CustomReaction.cs @@ -1,5 +1,4 @@ -using Newtonsoft.Json; -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; using System.Text.RegularExpressions; namespace NadekoBot.Services.Database.Models @@ -7,9 +6,7 @@ namespace NadekoBot.Services.Database.Models public class CustomReaction : DbEntity { public ulong? GuildId { get; set; } - [NotMapped] - [JsonIgnore] public Regex Regex { get; set; } public string Response { get; set; } public string Trigger { get; set; } @@ -19,7 +16,6 @@ namespace NadekoBot.Services.Database.Models public bool AutoDeleteTrigger { get; set; } public bool DmResponse { get; set; } - [JsonIgnore] public bool IsGlobal => !GuildId.HasValue; public bool ContainsAnywhere { get; set; } diff --git a/src/NadekoBot/Services/Database/Models/DiscordUser.cs b/src/NadekoBot/Services/Database/Models/DiscordUser.cs index 654408e2..6c02388d 100644 --- a/src/NadekoBot/Services/Database/Models/DiscordUser.cs +++ b/src/NadekoBot/Services/Database/Models/DiscordUser.cs @@ -10,9 +10,6 @@ namespace NadekoBot.Services.Database.Models public string AvatarId { get; set; } public ClubInfo Club { get; set; } - public bool IsClubAdmin { get; set; } - - public int TotalXp { get; set; } public DateTime LastLevelUp { get; set; } = DateTime.UtcNow; public DateTime LastXpGain { get; set; } = DateTime.MinValue; public XpNotificationType NotifyOnLevelUp { get; set; } diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index 5142e8e5..5c04c816 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -3,21 +3,23 @@ using System.Collections.Generic; using System.Linq; using NadekoBot.Services.Database.Models; using NadekoBot.Extensions; +using Microsoft.EntityFrameworkCore.Infrastructure; using System; -using Microsoft.EntityFrameworkCore.Design; -using Microsoft.Data.Sqlite; -using System.IO; namespace NadekoBot.Services.Database { - public class NadekoContextFactory : IDesignTimeDbContextFactory - { - public NadekoContext CreateDbContext(string[] args) + + public class NadekoContextFactory : IDbContextFactory + { + /// + /// :\ Used for migrations + /// + /// + /// + public NadekoContext Create(DbContextFactoryOptions options) { - var optionsBuilder = new DbContextOptionsBuilder(); - var builder = new SqliteConnectionStringBuilder("Data Source=data/NadekoBot.db"); - builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource); - optionsBuilder.UseSqlite(builder.ToString()); + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite("Filename=./data/NadekoBot.db"); var ctx = new NadekoContext(optionsBuilder.Options); ctx.Database.SetCommandTimeout(60); return ctx; @@ -56,7 +58,12 @@ namespace NadekoBot.Services.Database public DbSet ModulePrefixes { get; set; } public DbSet RewardedUsers { get; set; } - public NadekoContext(DbContextOptions options) : base(options) + public NadekoContext() : base() + { + + } + + public NadekoContext(DbContextOptions options) : base(options) { } @@ -224,7 +231,7 @@ namespace NadekoBot.Services.Database musicPlaylistEntity .HasMany(p => p.Songs) .WithOne() - .OnDelete(DeleteBehavior.Cascade); + .OnDelete(Microsoft.EntityFrameworkCore.Metadata.DeleteBehavior.Cascade); #endregion @@ -322,7 +329,7 @@ namespace NadekoBot.Services.Database #region ClubManytoMany modelBuilder.Entity() - .HasKey(t => new { t.ClubId, t.UserId }); + .HasKey(t => new { t.ClubId, t.UserId }); modelBuilder.Entity() .HasOne(pt => pt.User) @@ -333,7 +340,7 @@ namespace NadekoBot.Services.Database .WithMany(x => x.Applicants); modelBuilder.Entity() - .HasKey(t => new { t.ClubId, t.UserId }); + .HasKey(t => new { t.ClubId, t.UserId }); modelBuilder.Entity() .HasOne(pt => pt.User) diff --git a/src/NadekoBot/Services/Database/Repositories/IClubRepository.cs b/src/NadekoBot/Services/Database/Repositories/IClubRepository.cs index 66ad3d92..086d638b 100644 --- a/src/NadekoBot/Services/Database/Repositories/IClubRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IClubRepository.cs @@ -10,7 +10,6 @@ namespace NadekoBot.Services.Database.Repositories int GetNextDiscrim(string clubName); ClubInfo GetByName(string v, int discrim, Func, IQueryable> func = null); ClubInfo GetByOwner(ulong userId, Func, IQueryable> func = null); - ClubInfo GetByOwnerOrAdmin(ulong userId); ClubInfo GetByMember(ulong userId, Func, IQueryable> func = null); ClubInfo[] GetClubLeaderboardPage(int page); } diff --git a/src/NadekoBot/Services/Database/Repositories/IDiscordUserRepository.cs b/src/NadekoBot/Services/Database/Repositories/IDiscordUserRepository.cs index fb9360b7..480d0723 100644 --- a/src/NadekoBot/Services/Database/Repositories/IDiscordUserRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IDiscordUserRepository.cs @@ -6,7 +6,5 @@ namespace NadekoBot.Services.Database.Repositories public interface IDiscordUserRepository : IRepository { DiscordUser GetOrCreate(IUser original); - int GetUserGlobalRanking(ulong id); - DiscordUser[] GetUsersXpLeaderboardFor(int page); } } diff --git a/src/NadekoBot/Services/Database/Repositories/IXpRepository.cs b/src/NadekoBot/Services/Database/Repositories/IXpRepository.cs index f62394d7..667dd315 100644 --- a/src/NadekoBot/Services/Database/Repositories/IXpRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IXpRepository.cs @@ -5,7 +5,10 @@ namespace NadekoBot.Services.Database.Repositories public interface IXpRepository : IRepository { UserXpStats GetOrCreateUser(ulong guildId, ulong userId); - int GetUserGuildRanking(ulong userId, ulong guildId); + int GetTotalUserXp(ulong userId); UserXpStats[] GetUsersFor(ulong guildId, int page); + (ulong UserId, int TotalXp)[] GetUsersFor(int page); + int GetUserGlobalRanking(ulong userId); + int GetUserGuildRanking(ulong userId, ulong guildId); } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/ClubRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/ClubRepository.cs index 7eabbb1c..eb09e8b0 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/ClubRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/ClubRepository.cs @@ -24,30 +24,6 @@ namespace NadekoBot.Services.Database.Repositories.Impl return func(_set).FirstOrDefault(x => x.Owner.UserId == userId); } - public ClubInfo GetByOwnerOrAdmin(ulong userId) - { - return _set - .Include(x => x.Bans) - .ThenInclude(x => x.User) - .Include(x => x.Applicants) - .ThenInclude(x => x.User) - .Include(x => x.Owner) - .FirstOrDefault(x => x.Owner.UserId == userId) ?? - _context.Set() - .Include(x => x.Club) - .ThenInclude(x => x.Users) - .Include(x => x.Club) - .ThenInclude(x => x.Bans) - .ThenInclude(x => x.User) - .Include(x => x.Club) - .ThenInclude(x => x.Applicants) - .ThenInclude(x => x.User) - .Include(x => x.Club) - .ThenInclude(x => x.Owner) - .FirstOrDefault(x => x.UserId == userId && x.IsClubAdmin) - ?.Club; - } - public ClubInfo GetByName(string name, int discrim, Func, IQueryable> func = null) { if (func == null) diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/DiscordUserRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/DiscordUserRepository.cs index 16938a0d..6fa22ebc 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/DiscordUserRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/DiscordUserRepository.cs @@ -37,23 +37,5 @@ namespace NadekoBot.Services.Database.Repositories.Impl return toReturn; } - - public int GetUserGlobalRanking(ulong id) - { - return _set.Count(x => x.TotalXp > - _set.Where(y => y.UserId == id) - .DefaultIfEmpty() - .Sum(y => y.TotalXp)); - } - - public DiscordUser[] GetUsersXpLeaderboardFor(int page) - { - return _set - .OrderByDescending(x => x.TotalXp) - .Skip(page * 9) - .Take(9) - .AsEnumerable() - .ToArray(); - } } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/XpRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/XpRepository.cs index b411cdad..43d35202 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/XpRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/XpRepository.cs @@ -29,6 +29,11 @@ namespace NadekoBot.Services.Database.Repositories.Impl return usr; } + public int GetTotalUserXp(ulong userId) + { + return _set.Where(x => x.UserId == userId).Sum(x => x.Xp); + } + public UserXpStats[] GetUsersFor(ulong guildId, int page) { return _set.Where(x => x.GuildId == guildId) @@ -38,6 +43,15 @@ namespace NadekoBot.Services.Database.Repositories.Impl .ToArray(); } + public int GetUserGlobalRanking(ulong userId) + { + return _set + .GroupBy(x => x.UserId) + .Count(x => x.Sum(y => y.Xp) > _set + .Where(y => y.UserId == userId) + .Sum(y => y.Xp)) + 1; + } + public int GetUserGuildRanking(ulong userId, ulong guildId) { return _set @@ -48,5 +62,16 @@ namespace NadekoBot.Services.Database.Repositories.Impl .DefaultIfEmpty() .Sum())) + 1; } + + public (ulong UserId, int TotalXp)[] GetUsersFor(int page) + { + return _set.GroupBy(x => x.UserId) + .OrderByDescending(x => x.Sum(y => y.Xp)) + .Skip(page * 9) + .Take(9) + .AsEnumerable() + .Select(x => (x.Key, x.Sum(y => y.Xp))) + .ToArray(); + } } } \ No newline at end of file diff --git a/src/NadekoBot/Services/DbService.cs b/src/NadekoBot/Services/DbService.cs index 56c6940a..5bc9f6bf 100644 --- a/src/NadekoBot/Services/DbService.cs +++ b/src/NadekoBot/Services/DbService.cs @@ -1,28 +1,25 @@ -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; using NadekoBot.Services.Database; -using System; -using System.IO; using System.Linq; namespace NadekoBot.Services { public class DbService { - private readonly DbContextOptions options; - private readonly DbContextOptions migrateOptions; + private readonly DbContextOptions options; + private readonly DbContextOptions migrateOptions; + + private readonly string _connectionString; public DbService(IBotCredentials creds) { - var builder = new SqliteConnectionStringBuilder(creds.Db.ConnectionString); - builder.DataSource = Path.Combine(AppContext.BaseDirectory, builder.DataSource); - - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite(builder.ToString()); + _connectionString = creds.Db.ConnectionString; + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite(creds.Db.ConnectionString); options = optionsBuilder.Options; - optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite(builder.ToString(), x => x.SuppressForeignKeyEnforcement()); + optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlite(creds.Db.ConnectionString, x => x.SuppressForeignKeyEnforcement()); migrateOptions = optionsBuilder.Options; } diff --git a/src/NadekoBot/Services/IDataCache.cs b/src/NadekoBot/Services/IDataCache.cs deleted file mode 100644 index 3be7ad35..00000000 --- a/src/NadekoBot/Services/IDataCache.cs +++ /dev/null @@ -1,18 +0,0 @@ -using StackExchange.Redis; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NadekoBot.Services -{ - public interface IDataCache - { - ConnectionMultiplexer Redis { get; } - Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key); - Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key); - Task SetImageDataAsync(string key, byte[] data); - Task SetAnimeDataAsync(string link, string data); - } -} diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index 0ee0dea9..e8a96de5 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -90,13 +90,18 @@ namespace NadekoBot.Services.Impl ulong.TryParse(data[nameof(ClientId)], out ulong clId); ClientId = clId; + //var scId = data[nameof(SoundCloudClientId)]; + //SoundCloudClientId = scId; + //SoundCloudClientId = string.IsNullOrWhiteSpace(scId) + // ? + // : scId; CarbonKey = data[nameof(CarbonKey)]; var dbSection = data.GetSection("db"); Db = new DBConfig(string.IsNullOrWhiteSpace(dbSection["Type"]) ? "sqlite" : dbSection["Type"], string.IsNullOrWhiteSpace(dbSection["ConnectionString"]) - ? "Data Source=data/NadekoBot.db" + ? "Filename=./data/NadekoBot.db" : dbSection["ConnectionString"]); } catch (Exception ex) @@ -120,7 +125,7 @@ namespace NadekoBot.Services.Impl public string SoundCloudClientId { get; set; } = ""; public string CleverbotApiKey { get; } = ""; public string CarbonKey { get; set; } = ""; - public DBConfig Db { get; set; } = new DBConfig("sqlite", "Data Source=data/NadekoBot.db"); + public DBConfig Db { get; set; } = new DBConfig("sqlite", "Filename=./data/NadekoBot.db"); public int TotalShards { get; set; } = 1; public string PatreonAccessToken { get; set; } = ""; public string PatreonCampaignId { get; set; } = "334038"; diff --git a/src/NadekoBot/Services/Impl/Localization.cs b/src/NadekoBot/Services/Impl/Localization.cs index 438153a0..d781054b 100644 --- a/src/NadekoBot/Services/Impl/Localization.cs +++ b/src/NadekoBot/Services/Impl/Localization.cs @@ -5,9 +5,6 @@ using System.Linq; using Discord; using NLog; using NadekoBot.Services.Database.Models; -using NadekoBot.Common; -using Newtonsoft.Json; -using System.IO; namespace NadekoBot.Services.Impl { @@ -19,14 +16,6 @@ namespace NadekoBot.Services.Impl public ConcurrentDictionary GuildCultureInfos { get; } public CultureInfo DefaultCultureInfo { get; private set; } = CultureInfo.CurrentCulture; - private static readonly Dictionary _commandData; - - static Localization() - { - _commandData = JsonConvert.DeserializeObject>( - File.ReadAllText("./data/command_strings.json")); - } - private Localization() { } public Localization(IBotConfigProvider bcp, IEnumerable gcs, DbService db) { @@ -128,19 +117,10 @@ namespace NadekoBot.Services.Impl return info ?? DefaultCultureInfo; } - public static CommandData LoadCommand(string key) + public static string LoadCommandString(string key) { - _commandData.TryGetValue(key, out var toReturn); - - if (toReturn == null) - return new CommandData - { - Cmd = key, - Desc = key, - Usage = key, - }; - - return toReturn; + string toReturn = Resources.CommandStrings.ResourceManager.GetString(key); + return string.IsNullOrWhiteSpace(toReturn) ? key : toReturn; } } } diff --git a/src/NadekoBot/Services/Impl/RedisCache.cs b/src/NadekoBot/Services/Impl/RedisCache.cs deleted file mode 100644 index 84083ef8..00000000 --- a/src/NadekoBot/Services/Impl/RedisCache.cs +++ /dev/null @@ -1,40 +0,0 @@ -using StackExchange.Redis; -using System.Threading.Tasks; - -namespace NadekoBot.Services.Impl -{ - public class RedisCache : IDataCache - { - public ConnectionMultiplexer Redis { get; } - private readonly IDatabase _db; - - public RedisCache() - { - Redis = ConnectionMultiplexer.Connect("127.0.0.1"); - Redis.PreserveAsyncOrder = false; - _db = Redis.GetDatabase(); - } - - public async Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key) - { - byte[] x = await _db.StringGetAsync("image_" + key); - return (x != null, x); - } - - public Task SetImageDataAsync(string key, byte[] data) - { - return _db.StringSetAsync("image_" + key, data); - } - - public async Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key) - { - string x = await _db.StringGetAsync("anime_" + key); - return (x != null, x); - } - - public Task SetAnimeDataAsync(string key, string data) - { - return _db.StringSetAsync("anime_" + key, data); - } - } -} diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index 24bc273e..8e94ceec 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -20,7 +20,7 @@ namespace NadekoBot.Services.Impl private readonly IBotCredentials _creds; private readonly DateTime _started; - public const string BotVersion = "1.9.0"; + public const string BotVersion = "1.8.4"; public string Author => "Kwoth#2560"; public string Library => "Discord.Net"; diff --git a/src/NadekoBot/Services/LogSetup.cs b/src/NadekoBot/Services/LogSetup.cs index 9cf85799..0d3234ee 100644 --- a/src/NadekoBot/Services/LogSetup.cs +++ b/src/NadekoBot/Services/LogSetup.cs @@ -11,7 +11,7 @@ namespace NadekoBot.Services var logConfig = new LoggingConfiguration(); var consoleTarget = new ColoredConsoleTarget() { - Layout = @"${date:format=HH\:mm\:ss} ${logger:shortName=True} | ${message}" + Layout = @"${date:format=HH\:mm\:ss} ${logger} | ${message}" }; logConfig.AddTarget("Console", consoleTarget); diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index ebd9c435..1ee47eed 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -13,6 +13,7 @@ "customreactions_stats_not_found": "No stats for that trigger found, no action taken.", "customreactions_trigger": "Trigger", "customreactions_redacted_too_long": "Redecated because it's too long.", + "nsfw_autohentai_stopped": "Autohentai stopped.", "nsfw_not_found": "No results found.", "nsfw_blacklisted_tag_list": "List of blacklisted tags:", "nsfw_blacklisted_tag": "One or more tags you've used are blacklisted", @@ -867,10 +868,5 @@ "xp_club_icon_set": "New club icon set.", "xp_club_bans_for": "Bans for {0} club", "xp_club_apps_for": "Applicants for {0} club", - "xp_club_leaderboard": "Club leaderboard - page {0}", - "xp_club_admin_add": "{0} is now a club admin.", - "xp_club_admin_remove": "{0} is no longer club admin.", - "xp_club_admin_error": "Error. You are either not the owner of the club, or that user is not in your club.", - "nsfw_started": "Started. Reposting every {0}s.", - "nsfw_stopped": "Stopped reposting." + "xp_club_leaderboard": "Club leaderboard - page {0}" } \ No newline at end of file diff --git a/src/NadekoBot/credentials_example.json b/src/NadekoBot/credentials_example.json index 5074f8e0..5260d8c0 100644 --- a/src/NadekoBot/credentials_example.json +++ b/src/NadekoBot/credentials_example.json @@ -13,7 +13,7 @@ "CarbonKey": "", "Db": { "Type": "sqlite", - "ConnectionString": "Data Source=data/NadekoBot.db" + "ConnectionString": "Filename=./data/NadekoBot.db" }, "TotalShards": 1, "PatreonAccessToken": "", diff --git a/src/NadekoBot/data/command_strings.json b/src/NadekoBot/data/command_strings.json deleted file mode 100644 index d8f0ccd2..00000000 --- a/src/NadekoBot/data/command_strings.json +++ /dev/null @@ -1,2057 +0,0 @@ -{ - "h": { - "Cmd": "help h", - "Desc": "Either shows a help for a single command, or DMs you help link if no arguments are specified.", - "Usage": "`{0}h {0}cmds` or `{0}h`" - }, - "hgit": { - "Cmd": "hgit", - "Desc": "Generates the commandlist.md file.", - "Usage": "`{0}hgit`" - }, - "donate": { - "Cmd": "donate", - "Desc": "Instructions for helping the project financially.", - "Usage": "`{0}donate`" - }, - "modules": { - "Cmd": "modules mdls", - "Desc": "Lists all bot modules.", - "Usage": "`{0}modules`" - }, - "commands": { - "Cmd": "commands cmds", - "Desc": "List all of the bot's commands from a certain module. You can either specify the full name or only the first few letters of the module name.", - "Usage": "`{0}commands Administration` or `{0}cmds Admin`" - }, - "greetdel": { - "Cmd": "greetdel grdel", - "Desc": "Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion.", - "Usage": "`{0}greetdel 0` or `{0}greetdel 30`" - }, - "greet": { - "Cmd": "greet", - "Desc": "Toggles anouncements on the current channel when someone joins the server.", - "Usage": "`{0}greet`" - }, - "greetmsg": { - "Cmd": "greetmsg", - "Desc": "Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from instead of a regular text, if you want the message to be embedded.", - "Usage": "`{0}greetmsg Welcome, %user%.`" - }, - "bye": { - "Cmd": "bye", - "Desc": "Toggles anouncements on the current channel when someone leaves the server.", - "Usage": "`{0}bye`" - }, - "byemsg": { - "Cmd": "byemsg", - "Desc": "Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from instead of a regular text, if you want the message to be embedded.", - "Usage": "`{0}byemsg %user% has left.`" - }, - "byedel": { - "Cmd": "byedel", - "Desc": "Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion.", - "Usage": "`{0}byedel 0` or `{0}byedel 30`" - }, - "greetdm": { - "Cmd": "greetdm", - "Desc": "Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled).", - "Usage": "`{0}greetdm`" - }, - "logserver": { - "Cmd": "logserver", - "Desc": "Enables or Disables ALL log events. If enabled, all log events will log to this channel.", - "Usage": "`{0}logserver enable` or `{0}logserver disable`" - }, - "logignore": { - "Cmd": "logignore", - "Desc": "Toggles whether the `.logserver` command ignores this channel. Useful if you have hidden admin channel and public log channel.", - "Usage": "`{0}logignore`" - }, - "userpresence": { - "Cmd": "userpresence", - "Desc": "Starts logging to this channel when someone from the server goes online/offline/idle.", - "Usage": "`{0}userpresence`" - }, - "voicepresence": { - "Cmd": "voicepresence", - "Desc": "Toggles logging to this channel whenever someone joins or leaves a voice channel you are currently in.", - "Usage": "`{0}voicepresence`" - }, - "repeatinvoke": { - "Cmd": "repeatinvoke repinv", - "Desc": "Immediately shows the repeat message on a certain index and restarts its timer.", - "Usage": "`{0}repinv 1`" - }, - "repeat": { - "Cmd": "repeat", - "Desc": "Repeat a message every `X` minutes in the current channel. You can instead specify time of day for the message to be repeated at daily (make sure you've set your server's timezone). You can have up to 5 repeating messages on the server in total.", - "Usage": "`{0}repeat 5 Hello there` or `{0}repeat 17:30 tea time`" - }, - "rotateplaying": { - "Cmd": "rotateplaying ropl", - "Desc": "Toggles rotation of playing status of the dynamic strings you previously specified.", - "Usage": "`{0}ropl`" - }, - "addplaying": { - "Cmd": "addplaying adpl", - "Desc": "Adds a specified string to the list of playing strings to rotate. Supported placeholders: `%servers%`, `%users%`, `%playing%`, `%queued%`, `%time%`, `%shardid%`, `%shardcount%`, `%shardguilds%`.", - "Usage": "`{0}adpl`" - }, - "listplaying": { - "Cmd": "listplaying lipl", - "Desc": "Lists all playing statuses with their corresponding number.", - "Usage": "`{0}lipl`" - }, - "removeplaying": { - "Cmd": "removeplaying rmpl repl", - "Desc": "Removes a playing string on a given number.", - "Usage": "`{0}rmpl`" - }, - "slowmode": { - "Cmd": "slowmode", - "Desc": "Toggles slowmode. Disable by specifying no parameters. To enable, specify a number of messages each user can send, and an interval in seconds. For example 1 message every 5 seconds.", - "Usage": "`{0}slowmode 1 5` or `{0}slowmode`" - }, - "cleanvplust": { - "Cmd": "cleanvplust cv+t", - "Desc": "Deletes all text channels ending in `-voice` for which voicechannels are not found. Use at your own risk.", - "Usage": "`{0}cleanv+t`" - }, - "voiceplustext": { - "Cmd": "voice+text v+t", - "Desc": "Creates a text channel for each voice channel only users in that voice channel can see. If you are server owner, keep in mind you will see them all the time regardless.", - "Usage": "`{0}v+t`" - }, - "scsc": { - "Cmd": "scsc", - "Desc": "Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance.", - "Usage": "`{0}scsc`" - }, - "jcsc": { - "Cmd": "jcsc", - "Desc": "Joins current channel to an instance of cross server channel using the token.", - "Usage": "`{0}jcsc TokenHere`" - }, - "lcsc": { - "Cmd": "lcsc", - "Desc": "Leaves a cross server channel instance from this channel.", - "Usage": "`{0}lcsc`" - }, - "asar": { - "Cmd": "asar", - "Desc": "Adds a role to the list of self-assignable roles.", - "Usage": "`{0}asar Gamer`" - }, - "rsar": { - "Cmd": "rsar", - "Desc": "Removes a specified role from the list of self-assignable roles.", - "Usage": "`{0}rsar`" - }, - "lsar": { - "Cmd": "lsar", - "Desc": "Lists all self-assignable roles.", - "Usage": "`{0}lsar`" - }, - "tesar": { - "Cmd": "togglexclsar tesar", - "Desc": "Toggles whether the self-assigned roles are exclusive. (So that any person can have only one of the self assignable roles)", - "Usage": "`{0}tesar`" - }, - "iam": { - "Cmd": "iam", - "Desc": "Adds a role to you that you choose. Role must be on a list of self-assignable roles.", - "Usage": "`{0}iam Gamer`" - }, - "iamnot": { - "Cmd": "iamnot iamn", - "Desc": "Removes a specified role from you. Role must be on a list of self-assignable roles.", - "Usage": "`{0}iamn Gamer`" - }, - "addcustreact": { - "Cmd": "addcustreact acr", - "Desc": "Add a custom reaction with a trigger and a response. Running this command in server requires the Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: ", - "Usage": "`{0}acr \"hello\" Hi there %user%`" - }, - "listcustreact": { - "Cmd": "listcustreact lcr", - "Desc": "Lists global or server custom reactions (20 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. Specifying `all` argument instead of the number will DM you a text file with a list of all custom reactions.", - "Usage": "`{0}lcr 1` or `{0}lcr all`" - }, - "listcustreactg": { - "Cmd": "listcustreactg lcrg", - "Desc": "Lists global or server custom reactions (20 commands per page) grouped by trigger, and show a number of responses for each. Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions.", - "Usage": "`{0}lcrg 1`" - }, - "showcustreact": { - "Cmd": "showcustreact scr", - "Desc": "Shows a custom reaction's response on a given ID.", - "Usage": "`{0}scr 1`" - }, - "delcustreact": { - "Cmd": "delcustreact dcr", - "Desc": "Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration privileges and removes server custom reaction.", - "Usage": "`{0}dcr 5`" - }, - "autoassignrole": { - "Cmd": "autoassignrole aar", - "Desc": "Automaticaly assigns a specified role to every user who joins the server.", - "Usage": "`{0}aar` to disable, `{0}aar Role Name` to enable" - }, - "leave": { - "Cmd": "leave", - "Desc": "Makes Nadeko leave the server. Either server name or server ID is required.", - "Usage": "`{0}leave 123123123331`" - }, - "delmsgoncmd": { - "Cmd": "delmsgoncmd", - "Desc": "Toggles the automatic deletion of the user's successful command message to prevent chat flood.", - "Usage": "`{0}delmsgoncmd`" - }, - "restart": { - "Cmd": "restart", - "Desc": "Restarts the bot. Might not work.", - "Usage": "`{0}restart`" - }, - "setrole": { - "Cmd": "setrole sr", - "Desc": "Sets a role for a given user.", - "Usage": "`{0}sr @User Guest`" - }, - "removerole": { - "Cmd": "removerole rr", - "Desc": "Removes a role from a given user.", - "Usage": "`{0}rr @User Admin`" - }, - "renamerole": { - "Cmd": "renamerole renr", - "Desc": "Renames a role. The role you are renaming must be lower than bot's highest role.", - "Usage": "`{0}renr \"First role\" SecondRole`" - }, - "removeallroles": { - "Cmd": "removeallroles rar", - "Desc": "Removes all roles from a mentioned user.", - "Usage": "`{0}rar @User`" - }, - "createrole": { - "Cmd": "createrole cr", - "Desc": "Creates a role with a given name.", - "Usage": "`{0}cr Awesome Role`" - }, - "rolecolor": { - "Cmd": "rolecolor roleclr", - "Desc": "Set a role's color to the hex or 0-255 rgb color value provided.", - "Usage": "`{0}roleclr Admin 255 200 100` or `{0}roleclr Admin ffba55`" - }, - "ban": { - "Cmd": "ban b", - "Desc": "Bans a user by ID or name with an optional message.", - "Usage": "`{0}b \"@some Guy\" Your behaviour is toxic.`" - }, - "softban": { - "Cmd": "softban sb", - "Desc": "Bans and then unbans a user by ID or name with an optional message.", - "Usage": "`{0}sb \"@some Guy\" Your behaviour is toxic.`" - }, - "kick": { - "Cmd": "kick k", - "Desc": "Kicks a mentioned user.", - "Usage": "`{0}k \"@some Guy\" Your behaviour is toxic.`" - }, - "mute": { - "Cmd": "mute", - "Desc": "Mutes a mentioned user both from speaking and chatting. You can also specify time in minutes (up to 1440) for how long the user should be muted.", - "Usage": "`{0}mute @Someone` or `{0}mute 30 @Someone`" - }, - "voiceunmute": { - "Cmd": "voiceunmute", - "Desc": "Gives a previously voice-muted user a permission to speak.", - "Usage": "`{0}voiceunmute @Someguy`" - }, - "deafen": { - "Cmd": "deafen deaf", - "Desc": "Deafens mentioned user or users.", - "Usage": "`{0}deaf \"@Someguy\"` or `{0}deaf \"@Someguy\" \"@Someguy\"`" - }, - "undeafen": { - "Cmd": "undeafen undef", - "Desc": "Undeafens mentioned user or users.", - "Usage": "`{0}undef \"@Someguy\"` or `{0}undef \"@Someguy\" \"@Someguy\"`" - }, - "delvoichanl": { - "Cmd": "delvoichanl dvch", - "Desc": "Deletes a voice channel with a given name.", - "Usage": "`{0}dvch VoiceChannelName`" - }, - "creatvoichanl": { - "Cmd": "creatvoichanl cvch", - "Desc": "Creates a new voice channel with a given name.", - "Usage": "`{0}cvch VoiceChannelName`" - }, - "deltxtchanl": { - "Cmd": "deltxtchanl dtch", - "Desc": "Deletes a text channel with a given name.", - "Usage": "`{0}dtch TextChannelName`" - }, - "creatxtchanl": { - "Cmd": "creatxtchanl ctch", - "Desc": "Creates a new text channel with a given name.", - "Usage": "`{0}ctch TextChannelName`" - }, - "settopic": { - "Cmd": "settopic st", - "Desc": "Sets a topic on the current channel.", - "Usage": "`{0}st My new topic`" - }, - "setchanlname": { - "Cmd": "setchanlname schn", - "Desc": "Changes the name of the current channel.", - "Usage": "`{0}schn NewName`" - }, - "prune": { - "Cmd": "prune clear", - "Desc": "`{0}prune` removes all Nadeko's messages in the last 100 messages. `{0}prune X` removes last `X` number of messages from the channel (up to 100). `{0}prune @Someone` removes all Someone's messages in the last 100 messages. `{0}prune @Someone X` removes last `X` number of 'Someone's' messages in the channel.", - "Usage": "`{0}prune` or `{0}prune 5` or `{0}prune @Someone` or `{0}prune @Someone X`" - }, - "die": { - "Cmd": "die", - "Desc": "Shuts the bot down.", - "Usage": "`{0}die`" - }, - "setname": { - "Cmd": "setname newnm", - "Desc": "Gives the bot a new name.", - "Usage": "`{0}newnm BotName`" - }, - "setnick": { - "Cmd": "setnick", - "Desc": "Changes the nickname of the bot on this server. You can also target other users to change their nickname.", - "Usage": "`{0}setnick BotNickname` or `{0}setnick @SomeUser New Nickname`" - }, - "setavatar": { - "Cmd": "setavatar setav", - "Desc": "Sets a new avatar image for the NadekoBot. Argument is a direct link to an image.", - "Usage": "`{0}setav http://i.imgur.com/xTG3a1I.jpg`" - }, - "setgame": { - "Cmd": "setgame", - "Desc": "Sets the bots game.", - "Usage": "`{0}setgame with snakes`" - }, - "send": { - "Cmd": "send", - "Desc": "Sends a message to someone on a different server through the bot. Separate server and channel/user ids with `|` and prefix the channel id with `c:` and the user id with `u:`.", - "Usage": "`{0}send serverid|c:channelid message` or `{0}send serverid|u:userid message`" - }, - "mentionrole": { - "Cmd": "mentionrole menro", - "Desc": "Mentions every person from the provided role or roles (separated by a ',') on this server.", - "Usage": "`{0}menro RoleName`" - }, - "unstuck": { - "Cmd": "unstuck", - "Desc": "Clears the message queue.", - "Usage": "`{0}unstuck`" - }, - "donators": { - "Cmd": "donators", - "Desc": "List of the lovely people who donated to keep this project alive.", - "Usage": "`{0}donators`" - }, - "donadd": { - "Cmd": "donadd", - "Desc": "Add a donator to the database.", - "Usage": "`{0}donadd Donate Amount`" - }, - "savechat": { - "Cmd": "savechat", - "Desc": "Saves a number of messages to a text file and sends it to you.", - "Usage": "`{0}savechat 150`" - }, - "remind": { - "Cmd": "remind", - "Desc": "Sends a message to you or a channel after certain amount of time. First argument is `me`/`here`/'channelname'. Second argument is time in a descending order (mo>w>d>h>m) example: 1w5d3h10m. Third argument is a (multiword) message.", - "Usage": "`{0}remind me 1d5h Do something` or `{0}remind #general 1m Start now!`" - }, - "remindtemplate": { - "Cmd": "remindtemplate", - "Desc": "Sets message for when the remind is triggered. Available placeholders are `%user%` - user who ran the command, `%message%` - Message specified in the remind, `%target%` - target channel of the remind.", - "Usage": "`{0}remindtemplate %user%, do %message%!`" - }, - "serverinfo": { - "Cmd": "serverinfo sinfo", - "Desc": "Shows info about the server the bot is on. If no server is supplied, it defaults to current one.", - "Usage": "`{0}sinfo Some Server`" - }, - "channelinfo": { - "Cmd": "channelinfo cinfo", - "Desc": "Shows info about the channel. If no channel is supplied, it defaults to current one.", - "Usage": "`{0}cinfo #some-channel`" - }, - "userinfo": { - "Cmd": "userinfo uinfo", - "Desc": "Shows info about the user. If no user is supplied, it defaults a user running the command.", - "Usage": "`{0}uinfo @SomeUser`" - }, - "whosplaying": { - "Cmd": "whosplaying whpl", - "Desc": "Shows a list of users who are playing the specified game.", - "Usage": "`{0}whpl Overwatch`" - }, - "inrole": { - "Cmd": "inrole", - "Desc": "Lists every person from the specified role on this server. You can use role ID, role name.", - "Usage": "`{0}inrole Some Role`" - }, - "checkmyperms": { - "Cmd": "checkmyperms", - "Desc": "Checks your user-specific permissions on this channel.", - "Usage": "`{0}checkmyperms`" - }, - "stats": { - "Cmd": "stats", - "Desc": "Shows some basic stats for Nadeko.", - "Usage": "`{0}stats`" - }, - "userid": { - "Cmd": "userid uid", - "Desc": "Shows user ID.", - "Usage": "`{0}uid` or `{0}uid @SomeGuy`" - }, - "channelid": { - "Cmd": "channelid cid", - "Desc": "Shows current channel ID.", - "Usage": "`{0}cid`" - }, - "serverid": { - "Cmd": "serverid sid", - "Desc": "Shows current server ID.", - "Usage": "`{0}sid`" - }, - "roles": { - "Cmd": "roles", - "Desc": "List roles on this server or a roles of a specific user if specified. Paginated, 20 roles per page.", - "Usage": "`{0}roles 2` or `{0}roles @Someone`" - }, - "channeltopic": { - "Cmd": "channeltopic ct", - "Desc": "Sends current channel's topic as a message.", - "Usage": "`{0}ct`" - }, - "chnlfilterinv": { - "Cmd": "chnlfilterinv cfi", - "Desc": "Toggles automatic deletion of invites posted in the channel. Does not negate the `{0}srvrfilterinv` enabled setting. Does not affect the Bot Owner.", - "Usage": "`{0}cfi`" - }, - "srvrfilterinv": { - "Cmd": "srvrfilterinv sfi", - "Desc": "Toggles automatic deletion of invites posted in the server. Does not affect the Bot Owner.", - "Usage": "`{0}sfi`" - }, - "chnlfilterwords": { - "Cmd": "chnlfilterwords cfw", - "Desc": "Toggles automatic deletion of messages containing filtered words on the channel. Does not negate the `{0}srvrfilterwords` enabled setting. Does not affect the Bot Owner.", - "Usage": "`{0}cfw`" - }, - "filterword": { - "Cmd": "fw", - "Desc": "Adds or removes (if it exists) a word from the list of filtered words. Use`{0}sfw` or `{0}cfw` to toggle filtering.", - "Usage": "`{0}fw poop`" - }, - "lstfilterwords": { - "Cmd": "lstfilterwords lfw", - "Desc": "Shows a list of filtered words.", - "Usage": "`{0}lfw`" - }, - "srvrfilterwords": { - "Cmd": "srvrfilterwords sfw", - "Desc": "Toggles automatic deletion of messages containing filtered words on the server. Does not affect the Bot Owner.", - "Usage": "`{0}sfw`" - }, - "permrole": { - "Cmd": "permrole pr", - "Desc": "Sets a role which can change permissions. Supply no parameters to see the current one. Default is 'Nadeko'.", - "Usage": "`{0}pr role`" - }, - "verbose": { - "Cmd": "verbose v", - "Desc": "Sets whether to show when a command/module is blocked.", - "Usage": "`{0}verbose true`" - }, - "srvrmdl": { - "Cmd": "srvrmdl sm", - "Desc": "Sets a module's permission at the server level.", - "Usage": "`{0}sm ModuleName enable`" - }, - "srvrcmd": { - "Cmd": "srvrcmd sc", - "Desc": "Sets a command's permission at the server level.", - "Usage": "`{0}sc \"command name\" disable`" - }, - "rolemdl": { - "Cmd": "rolemdl rm", - "Desc": "Sets a module's permission at the role level.", - "Usage": "`{0}rm ModuleName enable MyRole`" - }, - "rolecmd": { - "Cmd": "rolecmd rc", - "Desc": "Sets a command's permission at the role level.", - "Usage": "`{0}rc \"command name\" disable MyRole`" - }, - "chnlmdl": { - "Cmd": "chnlmdl cm", - "Desc": "Sets a module's permission at the channel level.", - "Usage": "`{0}cm ModuleName enable SomeChannel`" - }, - "chnlcmd": { - "Cmd": "chnlcmd cc", - "Desc": "Sets a command's permission at the channel level.", - "Usage": "`{0}cc \"command name\" enable SomeChannel`" - }, - "usrmdl": { - "Cmd": "usrmdl um", - "Desc": "Sets a module's permission at the user level.", - "Usage": "`{0}um ModuleName enable SomeUsername`" - }, - "usrcmd": { - "Cmd": "usrcmd uc", - "Desc": "Sets a command's permission at the user level.", - "Usage": "`{0}uc \"command name\" enable SomeUsername`" - }, - "allsrvrmdls": { - "Cmd": "allsrvrmdls asm", - "Desc": "Enable or disable all modules for your server.", - "Usage": "`{0}asm [enable/disable]`" - }, - "allchnlmdls": { - "Cmd": "allchnlmdls acm", - "Desc": "Enable or disable all modules in a specified channel.", - "Usage": "`{0}acm enable #SomeChannel`" - }, - "allrolemdls": { - "Cmd": "allrolemdls arm", - "Desc": "Enable or disable all modules for a specific role.", - "Usage": "`{0}arm [enable/disable] MyRole`" - }, - "userblacklist": { - "Cmd": "ubl", - "Desc": "Either [add]s or [rem]oves a user specified by a Mention or an ID from a blacklist.", - "Usage": "`{0}ubl add @SomeUser` or `{0}ubl rem 12312312313`" - }, - "channelblacklist": { - "Cmd": "cbl", - "Desc": "Either [add]s or [rem]oves a channel specified by an ID from a blacklist.", - "Usage": "`{0}cbl rem 12312312312`" - }, - "serverblacklist": { - "Cmd": "sbl", - "Desc": "Either [add]s or [rem]oves a server specified by a Name or an ID from a blacklist.", - "Usage": "`{0}sbl add 12312321312` or `{0}sbl rem SomeTrashServer`" - }, - "cmdcooldown": { - "Cmd": "cmdcooldown cmdcd", - "Desc": "Sets a cooldown per user for a command. Set it to 0 to remove the cooldown.", - "Usage": "`{0}cmdcd \"some cmd\" 5`" - }, - "allcmdcooldowns": { - "Cmd": "allcmdcooldowns acmdcds", - "Desc": "Shows a list of all commands and their respective cooldowns.", - "Usage": "`{0}acmdcds`" - }, - "addquote": { - "Cmd": ".", - "Desc": "Adds a new quote with the specified name and message.", - "Usage": "`{0}. sayhi Hi`" - }, - "showquote": { - "Cmd": "..", - "Desc": "Shows a random quote with a specified name.", - "Usage": "`{0}.. abc`" - }, - "quotesearch": { - "Cmd": "qsearch", - "Desc": "Shows a random quote for a keyword that contains any text specified in the search.", - "Usage": "`{0}qsearch keyword text`" - }, - "quoteid": { - "Cmd": "quoteid qid", - "Desc": "Displays the quote with the specified ID number. Quote ID numbers can be found by typing `.liqu [num]` where `[num]` is a number of a page which contains 15 quotes.", - "Usage": "`{0}qid 123456`" - }, - "quotedelete": { - "Cmd": "quotedel qdel", - "Desc": "Deletes a quote with the specified ID. You have to be either server Administrator or the creator of the quote to delete it.", - "Usage": "`{0}qdel 123456`" - }, - "draw": { - "Cmd": "draw", - "Desc": "Draws a card from this server's deck. You can draw up to 10 cards by supplying a number of cards to draw.", - "Usage": "`{0}draw` or `{0}draw 5`" - }, - "drawnew": { - "Cmd": "drawnew", - "Desc": "Draws a card from the NEW deck of cards. You can draw up to 10 cards by supplying a number of cards to draw.", - "Usage": "`{0}drawnew` or `{0}drawnew 5`" - }, - "shuffleplaylist": { - "Cmd": "shuffle sh plsh", - "Desc": "Shuffles the current playlist.", - "Usage": "`{0}plsh`" - }, - "flip": { - "Cmd": "flip", - "Desc": "Flips coin(s) - heads or tails, and shows an image.", - "Usage": "`{0}flip` or `{0}flip 3`" - }, - "betflip": { - "Cmd": "betflip bf", - "Desc": "Bet to guess will the result be heads or tails. Guessing awards you 1.95x the currency you've bet (rounded up). Multiplier can be changed by the bot owner.", - "Usage": "`{0}bf 5 heads` or `{0}bf 3 t`" - }, - "roll": { - "Cmd": "roll", - "Desc": "Rolls 0-100. If you supply a number `X` it rolls up to 30 normal dice. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`. `Y` can be a letter 'F' if you want to roll fate dice instead of dnd.", - "Usage": "`{0}roll` or `{0}roll 7` or `{0}roll 3d5` or `{0}roll 5dF`" - }, - "rolluo": { - "Cmd": "rolluo", - "Desc": "Rolls `X` normal dice (up to 30) unordered. If you split 2 numbers with letter `d` (`xdy`) it will roll `X` dice from 1 to `y`.", - "Usage": "`{0}rolluo` or `{0}rolluo 7` or `{0}rolluo 3d5`" - }, - "nroll": { - "Cmd": "nroll", - "Desc": "Rolls in a given range.", - "Usage": "`{0}nroll 5` (rolls 0-5) or `{0}nroll 5-15`" - }, - "race": { - "Cmd": "race", - "Desc": "Starts a new animal race.", - "Usage": "`{0}race`" - }, - "joinrace": { - "Cmd": "joinrace jr", - "Desc": "Joins a new race. You can specify an amount of currency for betting (optional). You will get YourBet*(participants-1) back if you win.", - "Usage": "`{0}jr` or `{0}jr 5`" - }, - "nunchi": { - "Cmd": "nunchi", - "Desc": "Creates or joins an existing nunchi game. Users have to count up by 1 from the starting number shown by the bot. If someone makes a mistake (types an incorrent number, or repeats the same number) they are out of the game and a new round starts without them. Minimum 3 users required.", - "Usage": "`{0}nunchi`" - }, - "connect4": { - "Cmd": "connect4 con4", - "Desc": "Creates or joins an existing connect4 game. 2 players are required for the game. Objective of the game is to get 4 of your pieces next to each other in a vertical, horizontal or diagonal line.", - "Usage": "`{0}connect4`" - }, - "raffle": { - "Cmd": "raffle", - "Desc": "Prints a name and ID of a random user from the online list from the (optional) role.", - "Usage": "`{0}raffle` or `{0}raffle RoleName`" - }, - "give": { - "Cmd": "give", - "Desc": "Give someone a certain amount of currency.", - "Usage": "`{0}give 1 @SomeGuy`" - }, - "award": { - "Cmd": "award", - "Desc": "Awards someone a certain amount of currency. You can also specify a role name to award currency to all users in a role.", - "Usage": "`{0}award 100 @person` or `{0}award 5 Role Of Gamblers`" - }, - "take": { - "Cmd": "take", - "Desc": "Takes a certain amount of currency from someone.", - "Usage": "`{0}take 1 @SomeGuy`" - }, - "betroll": { - "Cmd": "betroll br", - "Desc": "Bets a certain amount of currency and rolls a dice. Rolling over 66 yields x2 of your currency, over 90 - x4 and 100 x10.", - "Usage": "`{0}br 5`" - }, - "wheeloffortune": { - "Cmd": "wheeloffortune wheel", - "Desc": "Bets a certain amount of currency on the wheel of fortune. Wheel can stop on one of many different multipliers. Won amount is rounded down to the nearest whole number.", - "Usage": "`{0}wheel 10`" - }, - "leaderboard": { - "Cmd": "leaderboard lb", - "Desc": "Displays the bot's currency leaderboard.", - "Usage": "`{0}lb`" - }, - "trivia": { - "Cmd": "trivia t", - "Desc": "Starts a game of trivia. You can add `nohint` to prevent hints. First player to get to 10 points wins by default. You can specify a different number. 30 seconds per question.", - "Usage": "`{0}t` or `{0}t 5 nohint`" - }, - "tl": { - "Cmd": "tl", - "Desc": "Shows a current trivia leaderboard.", - "Usage": "`{0}tl`" - }, - "tq": { - "Cmd": "tq", - "Desc": "Quits current trivia after current question.", - "Usage": "`{0}tq`" - }, - "typestart": { - "Cmd": "typestart", - "Desc": "Starts a typing contest.", - "Usage": "`{0}typestart`" - }, - "typestop": { - "Cmd": "typestop", - "Desc": "Stops a typing contest on the current channel.", - "Usage": "`{0}typestop`" - }, - "typeadd": { - "Cmd": "typeadd", - "Desc": "Adds a new article to the typing contest.", - "Usage": "`{0}typeadd wordswords`" - }, - "pollend": { - "Cmd": "pollend", - "Desc": "Stops active poll on this server and prints the results in this channel.", - "Usage": "`{0}pollend`" - }, - "pick": { - "Cmd": "pick", - "Desc": "Picks the currency planted in this channel. 60 seconds cooldown.", - "Usage": "`{0}pick`" - }, - "plant": { - "Cmd": "plant", - "Desc": "Spend an amount of currency to plant it in this channel. Default is 1. (If bot is restarted or crashes, the currency will be lost)", - "Usage": "`{0}plant` or `{0}plant 5`" - }, - "gencurrency": { - "Cmd": "gencurrency gc", - "Desc": "Toggles currency generation on this channel. Every posted message will have chance to spawn currency. Chance is specified by the Bot Owner. (default is 2%)", - "Usage": "`{0}gc`" - }, - "leet": { - "Cmd": "leet", - "Desc": "Converts a text to leetspeak with 6 (1-6) severity levels", - "Usage": "`{0}leet 3 Hello`" - }, - "choose": { - "Cmd": "choose", - "Desc": "Chooses a thing from a list of things", - "Usage": "`{0}choose Get up;Sleep;Sleep more`" - }, - "": { - "Cmd": null, - "Desc": null, - "Usage": null - }, - "rps": { - "Cmd": "rps", - "Desc": "Play a game of Rocket-Paperclip-Scissors with Nadeko.", - "Usage": "`{0}rps scissors`" - }, - "linux": { - "Cmd": "linux", - "Desc": "Prints a customizable Linux interjection", - "Usage": "`{0}linux Spyware Windows`" - }, - "next": { - "Cmd": "next n", - "Desc": "Goes to the next song in the queue. You have to be in the same voice channel as the bot. You can skip multiple songs, but in that case songs will not be requeued if {0}rcs or {0}rpl is enabled.", - "Usage": "`{0}n` or `{0}n 5`" - }, - "play": { - "Cmd": "play start", - "Desc": "If no arguments are specified, acts as `{0}next 1` command. If you specify a song number, it will jump to that song. If you specify a search query, acts as a `{0}q` command", - "Usage": "`{0}play` or `{0}play 5` or `{0}play Dream Of Venice`" - }, - "stop": { - "Cmd": "stop s", - "Desc": "Stops the music and preserves the current song index. Stays in the channel.", - "Usage": "`{0}s`" - }, - "destroy": { - "Cmd": "destroy d", - "Desc": "Completely stops the music and unbinds the bot from the channel. (may cause weird behaviour)", - "Usage": "`{0}d`" - }, - "pause": { - "Cmd": "pause p", - "Desc": "Pauses or Unpauses the song.", - "Usage": "`{0}p`" - }, - "queue": { - "Cmd": "queue q yq", - "Desc": "Queue a song using keywords or a link. Bot will join your voice channel. **You must be in a voice channel**.", - "Usage": "`{0}q Dream Of Venice`" - }, - "queuenext": { - "Cmd": "queuenext qn", - "Desc": "Works the same as `{0}queue` command, except it enqueues the new song after the current one. **You must be in a voice channel**.", - "Usage": "`{0}qn Dream Of Venice`" - }, - "queuesearch": { - "Cmd": "queuesearch qs yqs", - "Desc": "Search for top 5 youtube song result using keywords, and type the index of the song to play that song. Bot will join your voice channel. **You must be in a voice channel**.", - "Usage": "`{0}qs Dream Of Venice`" - }, - "soundcloudqueue": { - "Cmd": "soundcloudqueue sq", - "Desc": "Queue a soundcloud song using keywords. Bot will join your voice channel. **You must be in a voice channel**.", - "Usage": "`{0}sq Dream Of Venice`" - }, - "listqueue": { - "Cmd": "listqueue lq", - "Desc": "Lists 10 currently queued songs per page. Default page is 1.", - "Usage": "`{0}lq` or `{0}lq 2`" - }, - "nowplaying": { - "Cmd": "nowplaying np", - "Desc": "Shows the song that the bot is currently playing.", - "Usage": "`{0}np`" - }, - "volume": { - "Cmd": "volume vol", - "Desc": "Sets the music playback volume (0-100%)", - "Usage": "`{0}vol 50`" - }, - "defvol": { - "Cmd": "defvol dv", - "Desc": "Sets the default music volume when music playback is started (0-100). Persists through restarts.", - "Usage": "`{0}dv 80`" - }, - "max": { - "Cmd": "max", - "Desc": "Sets the music playback volume to 100%.", - "Usage": "`{0}max`" - }, - "half": { - "Cmd": "half", - "Desc": "Sets the music playback volume to 50%.", - "Usage": "`{0}half`" - }, - "playlist": { - "Cmd": "playlist pl", - "Desc": "Queues up to 500 songs from a youtube playlist specified by a link, or keywords.", - "Usage": "`{0}pl playlist link or name`" - }, - "soundcloudpl": { - "Cmd": "soundcloudpl scpl", - "Desc": "Queue a Soundcloud playlist using a link.", - "Usage": "`{0}scpl soundcloudseturl`" - }, - "localpl": { - "Cmd": "localplaylst lopl", - "Desc": "Queues all songs from a directory.", - "Usage": "`{0}lopl C:/music/classical`" - }, - "radio": { - "Cmd": "radio ra", - "Desc": "Queues a radio stream from a link. It can be a direct mp3 radio stream, .m3u, .pls .asx or .xspf (Usage Video: )", - "Usage": "`{0}ra radio link here`" - }, - "local": { - "Cmd": "local lo", - "Desc": "Queues a local file by specifying a full path.", - "Usage": "`{0}lo C:/music/mysong.mp3`" - }, - "move": { - "Cmd": "move mv", - "Desc": "Moves the bot to your voice channel. (works only if music is already playing)", - "Usage": "`{0}mv`" - }, - "songremove": { - "Cmd": "songremove srm", - "Desc": "Remove a song by its # in the queue, or 'all' to remove all songs from the queue and reset the song index.", - "Usage": "`{0}srm 5`" - }, - "movesong": { - "Cmd": "movesong ms", - "Desc": "Moves a song from one position to another.", - "Usage": "`{0}ms 5>3`" - }, - "setmaxqueue": { - "Cmd": "setmaxqueue smq", - "Desc": "Sets a maximum queue size. Supply 0 or no argument to have no limit.", - "Usage": "`{0}smq 50` or `{0}smq`" - }, - "cleanup": { - "Cmd": "cleanup", - "Desc": "Cleans up hanging voice connections.", - "Usage": "`{0}cleanup`" - }, - "reptcursong": { - "Cmd": "reptcursong rcs", - "Desc": "Toggles repeat of current song.", - "Usage": "`{0}rcs`" - }, - "repeatpl": { - "Cmd": "rpeatplaylst rpl", - "Desc": "Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue).", - "Usage": "`{0}rpl`" - }, - "save": { - "Cmd": "save", - "Desc": "Saves a playlist under a certain name. Playlist name must be no longer than 20 characters and must not contain dashes.", - "Usage": "`{0}save classical1`" - }, - "streamrole": { - "Cmd": "streamrole", - "Desc": "Sets a role which is monitored for streamers (FromRole), and a role to add if a user from 'FromRole' is streaming (AddRole). When a user from 'FromRole' starts streaming, they will receive an 'AddRole'. Provide no arguments to disable", - "Usage": "`{0}streamrole \"Eligible Streamers\" \"Featured Streams\"`" - }, - "load": { - "Cmd": "load", - "Desc": "Loads a saved playlist using its ID. Use `{0}pls` to list all saved playlists and `{0}save` to save new ones.", - "Usage": "`{0}load 5`" - }, - "playlists": { - "Cmd": "playlists pls", - "Desc": "Lists all playlists. Paginated, 20 per page. Default page is 0.", - "Usage": "`{0}pls 1`" - }, - "deleteplaylist": { - "Cmd": "deleteplaylist delpls", - "Desc": "Deletes a saved playlist. Works only if you made it or if you are the bot owner.", - "Usage": "`{0}delpls animu-5`" - }, - "goto": { - "Cmd": "goto", - "Desc": "Goes to a specific time in seconds in a song.", - "Usage": "`{0}goto 30`" - }, - "autoplay": { - "Cmd": "autoplay ap", - "Desc": "Toggles autoplay - When the song is finished, automatically queue a related Youtube song. (Works only for Youtube songs and when queue is empty)", - "Usage": "`{0}ap`" - }, - "lolchamp": { - "Cmd": "lolchamp", - "Desc": "Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role.", - "Usage": "`{0}lolchamp Riven` or `{0}lolchamp Annie sup`" - }, - "lolban": { - "Cmd": "lolban", - "Desc": "Shows top banned champions ordered by ban rate.", - "Usage": "`{0}lolban`" - }, - "smashcast": { - "Cmd": "smashcast hb", - "Desc": "Notifies this channel when a certain user starts streaming.", - "Usage": "`{0}smashcast SomeStreamer`" - }, - "twitch": { - "Cmd": "twitch tw", - "Desc": "Notifies this channel when a certain user starts streaming.", - "Usage": "`{0}twitch SomeStreamer`" - }, - "mixer": { - "Cmd": "mixer bm", - "Desc": "Notifies this channel when a certain user starts streaming.", - "Usage": "`{0}mixer SomeStreamer`" - }, - "removestream": { - "Cmd": "removestream rms", - "Desc": "Removes notifications of a certain streamer from a certain platform on this channel.", - "Usage": "`{0}rms Twitch SomeGuy` or `{0}rms mixer SomeOtherGuy`" - }, - "liststreams": { - "Cmd": "liststreams ls", - "Desc": "Lists all streams you are following on this server.", - "Usage": "`{0}ls`" - }, - "convert": { - "Cmd": "convert", - "Desc": "Convert quantities. Use `{0}convertlist` to see supported dimensions and currencies.", - "Usage": "`{0}convert m km 1000`" - }, - "convertlist": { - "Cmd": "convertlist", - "Desc": "List of the convertible dimensions and currencies.", - "Usage": "`{0}convertlist`" - }, - "wowjoke": { - "Cmd": "wowjoke", - "Desc": "Get one of Kwoth's penultimate WoW jokes.", - "Usage": "`{0}wowjoke`" - }, - "calculate": { - "Cmd": "calculate calc", - "Desc": "Evaluate a mathematical expression.", - "Usage": "`{0}calc 1+1`" - }, - "osu": { - "Cmd": "osu", - "Desc": "Shows osu stats for a player.", - "Usage": "`{0}osu Name` or `{0}osu Name taiko`" - }, - "osub": { - "Cmd": "osub", - "Desc": "Shows information about an osu beatmap.", - "Usage": "`{0}osub https://osu.ppy.sh/s/127712`" - }, - "osu5": { - "Cmd": "osu5", - "Desc": "Displays a user's top 5 plays.", - "Usage": "`{0}osu5 Name`" - }, - "pokemon": { - "Cmd": "pokemon poke", - "Desc": "Searches for a pokemon.", - "Usage": "`{0}poke Sylveon`" - }, - "pokemonability": { - "Cmd": "pokemonability pokeab", - "Desc": "Searches for a pokemon ability.", - "Usage": "`{0}pokeab overgrow`" - }, - "memelist": { - "Cmd": "memelist", - "Desc": "Pulls a list of memes you can use with `{0}memegen` from http://memegen.link/templates/", - "Usage": "`{0}memelist`" - }, - "memegen": { - "Cmd": "memegen", - "Desc": "Generates a meme from memelist with top and bottom text.", - "Usage": "`{0}memegen biw \"gets iced coffee\" \"in the winter\"`" - }, - "weather": { - "Cmd": "weather we", - "Desc": "Shows weather data for a specified city. You can also specify a country after a comma.", - "Usage": "`{0}we Moscow, RU`" - }, - "youtube": { - "Cmd": "youtube yt", - "Desc": "Searches youtubes and shows the first result", - "Usage": "`{0}yt query`" - }, - "anime": { - "Cmd": "anime ani aq", - "Desc": "Queries anilist for an anime and shows the first result.", - "Usage": "`{0}ani aquarion evol`" - }, - "imdb": { - "Cmd": "imdb omdb", - "Desc": "Queries omdb for movies or series, show first result.", - "Usage": "`{0}imdb Batman vs Superman`" - }, - "manga": { - "Cmd": "manga mang mq", - "Desc": "Queries anilist for a manga and shows the first result.", - "Usage": "`{0}mq Shingeki no kyojin`" - }, - "randomcat": { - "Cmd": "randomcat meow", - "Desc": "Shows a random cat image.", - "Usage": "`{0}meow`" - }, - "randomdog": { - "Cmd": "randomdog woof", - "Desc": "Shows a random dog image.", - "Usage": "`{0}woof`" - }, - "image": { - "Cmd": "image img", - "Desc": "Pulls the first image found using a search parameter. Use `{0}rimg` for different results.", - "Usage": "`{0}img cute kitten`" - }, - "randomimage": { - "Cmd": "randomimage rimg", - "Desc": "Pulls a random image using a search parameter.", - "Usage": "`{0}rimg cute kitten`" - }, - "lmgtfy": { - "Cmd": "lmgtfy", - "Desc": "Google something for an idiot.", - "Usage": "`{0}lmgtfy query`" - }, - "google": { - "Cmd": "google g", - "Desc": "Get a Google search link for some terms.", - "Usage": "`{0}google query`" - }, - "hearthstone": { - "Cmd": "hearthstone hs", - "Desc": "Searches for a Hearthstone card and shows its image. Takes a while to complete.", - "Usage": "`{0}hs Ysera`" - }, - "urbandict": { - "Cmd": "urbandict ud", - "Desc": "Searches Urban Dictionary for a word.", - "Usage": "`{0}ud Pineapple`" - }, - "hashtag": { - "Cmd": "#", - "Desc": "Searches Tagdef.com for a hashtag.", - "Usage": "`{0}# ff`" - }, - "catfact": { - "Cmd": "catfact", - "Desc": "Shows a random catfact from ", - "Usage": "`{0}catfact`" - }, - "yomama": { - "Cmd": "yomama ym", - "Desc": "Shows a random joke from ", - "Usage": "`{0}ym`" - }, - "randjoke": { - "Cmd": "randjoke rj", - "Desc": "Shows a random joke from ", - "Usage": "`{0}rj`" - }, - "chucknorris": { - "Cmd": "chucknorris cn", - "Desc": "Shows a random Chuck Norris joke from ", - "Usage": "`{0}cn`" - }, - "magicitem": { - "Cmd": "magicitem mi", - "Desc": "Shows a random magic item from ", - "Usage": "`{0}mi`" - }, - "revav": { - "Cmd": "revav", - "Desc": "Returns a Google reverse image search for someone's avatar.", - "Usage": "`{0}revav @SomeGuy`" - }, - "revimg": { - "Cmd": "revimg", - "Desc": "Returns a Google reverse image search for an image from a link.", - "Usage": "`{0}revimg Image link`" - }, - "safebooru": { - "Cmd": "safebooru", - "Desc": "Shows a random image from safebooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +)", - "Usage": "`{0}safebooru yuri+kissing`" - }, - "wiki": { - "Cmd": "wikipedia wiki", - "Desc": "Gives you back a wikipedia link", - "Usage": "`{0}wiki query`" - }, - "color": { - "Cmd": "color", - "Desc": "Shows you what color corresponds to that hex.", - "Usage": "`{0}color 00ff00`" - }, - "videocall": { - "Cmd": "videocall", - "Desc": "Creates a private video call link for you and other mentioned people. The link is sent to mentioned people via a private message.", - "Usage": "`{0}videocall \"@the First\" \"@Xyz\"`" - }, - "avatar": { - "Cmd": "avatar av", - "Desc": "Shows a mentioned person's avatar.", - "Usage": "`{0}av @SomeGuy`" - }, - "hentai": { - "Cmd": "hentai", - "Desc": "Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed.", - "Usage": "`{0}hentai yuri`" - }, - "danbooru": { - "Cmd": "danbooru", - "Desc": "Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +)", - "Usage": "`{0}danbooru yuri+kissing`" - }, - "atfbooru": { - "Cmd": "atfbooru atf", - "Desc": "Shows a random hentai image from atfbooru with a given tag. Tag is optional but preferred.", - "Usage": "`{0}atfbooru yuri+kissing`" - }, - "gelbooru": { - "Cmd": "gelbooru", - "Desc": "Shows a random hentai image from gelbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +)", - "Usage": "`{0}gelbooru yuri+kissing`" - }, - "rule34": { - "Cmd": "rule34", - "Desc": "Shows a random image from rule34.xx with a given tag. Tag is optional but preferred. (multiple tags are appended with +)", - "Usage": "`{0}rule34 yuri+kissing`" - }, - "e621": { - "Cmd": "e621", - "Desc": "Shows a random hentai image from e621.net with a given tag. Tag is optional but preferred. Use spaces for multiple tags.", - "Usage": "`{0}e621 yuri kissing`" - }, - "boobs": { - "Cmd": "boobs", - "Desc": "Real adult content.", - "Usage": "`{0}boobs`" - }, - "butts": { - "Cmd": "butts ass butt", - "Desc": "Real adult content.", - "Usage": "`{0}butts` or `{0}ass`" - }, - "translate": { - "Cmd": "translate trans", - "Desc": "Translates from>to text. From the given language to the destination language.", - "Usage": "`{0}trans en>fr Hello`" - }, - "translangs": { - "Cmd": "translangs", - "Desc": "Lists the valid languages for translation.", - "Usage": "`{0}translangs`" - }, - "guide": { - "Cmd": "readme guide", - "Desc": "Sends a readme and a guide links to the channel.", - "Usage": "`{0}readme` or `{0}guide`" - }, - "calcops": { - "Cmd": "calcops", - "Desc": "Shows all available operations in the `{0}calc` command", - "Usage": "`{0}calcops`" - }, - "delallquotes": { - "Cmd": "delallq daq", - "Desc": "Deletes all quotes on a specified keyword.", - "Usage": "`{0}delallq kek`" - }, - "greetdmmsg": { - "Cmd": "greetdmmsg", - "Desc": "Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from instead of a regular text, if you want the message to be embedded.", - "Usage": "`{0}greetdmmsg Welcome to the server, %user%`." - }, - "cash": { - "Cmd": "$ currency $$ $$$ cash cur", - "Desc": "Check how much currency a person has. (Defaults to yourself)", - "Usage": "`{0}$` or `{0}$ @SomeGuy`" - }, - "listperms": { - "Cmd": "listperms lp", - "Desc": "Lists whole permission chain with their indexes. You can specify an optional page number if there are a lot of permissions.", - "Usage": "`{0}lp` or `{0}lp 3`" - }, - "allusrmdls": { - "Cmd": "allusrmdls aum", - "Desc": "Enable or disable all modules for a specific user.", - "Usage": "`{0}aum enable @someone`" - }, - "moveperm": { - "Cmd": "moveperm mp", - "Desc": "Moves permission from one position to another in the Permissions list.", - "Usage": "`{0}mp 2 4`" - }, - "removeperm": { - "Cmd": "removeperm rp", - "Desc": "Removes a permission from a given position in the Permissions list.", - "Usage": "`{0}rp 1`" - }, - "migratedata": { - "Cmd": "migratedata", - "Desc": "Migrate data from old bot configuration", - "Usage": "`{0}migratedata`" - }, - "checkstream": { - "Cmd": "checkstream cs", - "Desc": "Checks if a user is online on a certain streaming platform.", - "Usage": "`{0}cs twitch MyFavStreamer`" - }, - "showemojis": { - "Cmd": "showemojis se", - "Desc": "Shows a name and a link to every SPECIAL emoji in the message.", - "Usage": "`{0}se A message full of SPECIAL emojis`" - }, - "deckshuffle": { - "Cmd": "deckshuffle dsh", - "Desc": "Reshuffles all cards back into the deck.", - "Usage": "`{0}dsh`" - }, - "forwardmessages": { - "Cmd": "fwmsgs", - "Desc": "Toggles forwarding of non-command messages sent to bot's DM to the bot owners", - "Usage": "`{0}fwmsgs`" - }, - "forwardtoall": { - "Cmd": "fwtoall", - "Desc": "Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json file", - "Usage": "`{0}fwtoall`" - }, - "resetpermissions": { - "Cmd": "resetperms", - "Desc": "Resets the bot's permissions module on this server to the default value.", - "Usage": "`{0}resetperms`" - }, - "antiraid": { - "Cmd": "antiraid", - "Desc": "Sets an anti-raid protection on the server. First argument is number of people which will trigger the protection. Second one is a time interval in which that number of people needs to join in order to trigger the protection, and third argument is punishment for those people (Kick, Ban, Mute)", - "Usage": "`{0}antiraid 5 20 Kick`" - }, - "antispam": { - "Cmd": "antispam", - "Desc": "Stops people from repeating same message X times in a row. You can specify to either mute, kick or ban the offenders. Max message count is 10.", - "Usage": "`{0}antispam 3 Mute` or `{0}antispam 4 Kick` or `{0}antispam 6 Ban`" - }, - "chatmute": { - "Cmd": "chatmute", - "Desc": "Prevents a mentioned user from chatting in text channels.", - "Usage": "`{0}chatmute @Someone`" - }, - "voicemute": { - "Cmd": "voicemute", - "Desc": "Prevents a mentioned user from speaking in voice channels.", - "Usage": "`{0}voicemute @Someone`" - }, - "konachan": { - "Cmd": "konachan", - "Desc": "Shows a random hentai image from konachan with a given tag. Tag is optional but preferred.", - "Usage": "`{0}konachan yuri`" - }, - "setmuterole": { - "Cmd": "setmuterole", - "Desc": "Sets a name of the role which will be assigned to people who should be muted. Default is nadeko-mute.", - "Usage": "`{0}setmuterole Silenced`" - }, - "adsarm": { - "Cmd": "adsarm", - "Desc": "Toggles the automatic deletion of confirmations for `{0}iam` and `{0}iamn` commands.", - "Usage": "`{0}adsarm`" - }, - "setstream": { - "Cmd": "setstream", - "Desc": "Sets the bots stream. First argument is the twitch link, second argument is stream name.", - "Usage": "`{0}setstream TWITCHLINK Hello`" - }, - "chatunmute": { - "Cmd": "chatunmute", - "Desc": "Removes a mute role previously set on a mentioned user with `{0}chatmute` which prevented him from chatting in text channels.", - "Usage": "`{0}chatunmute @Someone`" - }, - "unmute": { - "Cmd": "unmute", - "Desc": "Unmutes a mentioned user previously muted with `{0}mute` command.", - "Usage": "`{0}unmute @Someone`" - }, - "xkcd": { - "Cmd": "xkcd", - "Desc": "Shows a XKCD comic. No arguments will retrieve random one. Number argument will retrieve a specific comic, and \"latest\" will get the latest one.", - "Usage": "`{0}xkcd` or `{0}xkcd 1400` or `{0}xkcd latest`" - }, - "placelist": { - "Cmd": "placelist", - "Desc": "Shows the list of available tags for the `{0}place` command.", - "Usage": "`{0}placelist`" - }, - "place": { - "Cmd": "place", - "Desc": "Shows a placeholder image of a given tag. Use `{0}placelist` to see all available tags. You can specify the width and height of the image as the last two optional arguments.", - "Usage": "`{0}place Cage` or `{0}place steven 500 400`" - }, - "togethertube": { - "Cmd": "togethertube totube", - "Desc": "Creates a new room on and shows the link in the chat.", - "Usage": "`{0}totube`" - }, - "poll": { - "Cmd": "poll ppoll", - "Desc": "Creates a public poll which requires users to type a number of the voting option in the channel command is ran in.", - "Usage": "`{0}ppoll Question?;Answer1;Answ 2;A_3`" - }, - "autotranslang": { - "Cmd": "autotranslang atl", - "Desc": "Sets your source and target language to be used with `{0}at`. Specify no arguments to remove previously set value.", - "Usage": "`{0}atl en>fr`" - }, - "autotranslate": { - "Cmd": "autotrans at", - "Desc": "Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set \"del\" argument to automatically delete all translated user messages.", - "Usage": "`{0}at` or `{0}at del`" - }, - "listquotes": { - "Cmd": "listquotes liqu", - "Desc": "Lists all quotes on the server ordered alphabetically. 15 Per page.", - "Usage": "`{0}liqu` or `{0}liqu 3`" - }, - "typedel": { - "Cmd": "typedel", - "Desc": "Deletes a typing article given the ID.", - "Usage": "`{0}typedel 3`" - }, - "typelist": { - "Cmd": "typelist", - "Desc": "Lists added typing articles with their IDs. 15 per page.", - "Usage": "`{0}typelist` or `{0}typelist 3`" - }, - "listservers": { - "Cmd": "listservers", - "Desc": "Lists servers the bot is on with some basic info. 15 per page.", - "Usage": "`{0}listservers 3`" - }, - "hentaibomb": { - "Cmd": "hentaibomb", - "Desc": "Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred.", - "Usage": "`{0}hentaibomb yuri`" - }, - "cleverbot": { - "Cmd": "cleverbot", - "Desc": "Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled.", - "Usage": "`{0}cleverbot`" - }, - "shorten": { - "Cmd": "shorten", - "Desc": "Attempts to shorten an URL, if it fails, returns the input URL.", - "Usage": "`{0}shorten https://google.com`" - }, - "mcping": { - "Cmd": "minecraftping mcping", - "Desc": "Pings a minecraft server.", - "Usage": "`{0}mcping 127.0.0.1:25565`" - }, - "mcq": { - "Cmd": "minecraftquery mcq", - "Desc": "Finds information about a minecraft server.", - "Usage": "`{0}mcq server:ip`" - }, - "wikia": { - "Cmd": "wikia", - "Desc": "Gives you back a wikia link", - "Usage": "`{0}wikia mtg Vigilance` or `{0}wikia mlp Dashy`" - }, - "yandere": { - "Cmd": "yandere", - "Desc": "Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +)", - "Usage": "`{0}yandere tag1+tag2`" - }, - "magicthegathering": { - "Cmd": "magicthegathering mtg", - "Desc": "Searches for a Magic The Gathering card.", - "Usage": "`{0}magicthegathering about face` or `{0}mtg about face`" - }, - "yodify": { - "Cmd": "yodify yoda", - "Desc": "Translates your normal sentences into Yoda styled sentences!", - "Usage": "`{0}yoda my feelings hurt`" - }, - "attack": { - "Cmd": "attack", - "Desc": "Attacks a target with the given move. Use `{0}movelist` to see a list of moves your type can use.", - "Usage": "`{0}attack \"vine whip\" @someguy`" - }, - "heal": { - "Cmd": "heal", - "Desc": "Heals someone. Revives those who fainted. Costs a NadekoFlower. ", - "Usage": "`{0}heal @someone`" - }, - "movelist": { - "Cmd": "movelist ml", - "Desc": "Lists the moves you are able to use", - "Usage": "`{0}ml`" - }, - "settype": { - "Cmd": "settype", - "Desc": "Set your poketype. Costs a NadekoFlower. Provide no arguments to see a list of available types.", - "Usage": "`{0}settype fire` or `{0}settype`" - }, - "type": { - "Cmd": "type", - "Desc": "Get the poketype of the target.", - "Usage": "`{0}type @someone`" - }, - "hangmanlist": { - "Cmd": "hangmanlist", - "Desc": "Shows a list of hangman term types.", - "Usage": "`{0}hangmanlist`" - }, - "hangman": { - "Cmd": "hangman", - "Desc": "Starts a game of hangman in the channel. Use `{0}hangmanlist` to see a list of available term types. Defaults to 'all'.", - "Usage": "`{0}hangman` or `{0}hangman movies`" - }, - "hangmanstop": { - "Cmd": "hangmanstop", - "Desc": "Stops the active hangman game on this channel if it exists.", - "Usage": "`{0}hangmanstop`" - }, - "crstatsclear": { - "Cmd": "crstatsclear", - "Desc": "Resets the counters on `{0}crstats`. You can specify a trigger to clear stats only for that trigger.", - "Usage": "`{0}crstatsclear` or `{0}crstatsclear rng`" - }, - "crstats": { - "Cmd": "crstats", - "Desc": "Shows a list of custom reactions and the number of times they have been executed. Paginated with 10 per page. Use `{0}crstatsclear` to reset the counters.", - "Usage": "`{0}crstats` or `{0}crstats 3`" - }, - "overwatch": { - "Cmd": "overwatch ow", - "Desc": "Show's basic stats on a player (competitive rank, playtime, level etc) Region codes are: `eu` `us` `cn` `kr`", - "Usage": "`{0}ow us Battletag#1337` or `{0}overwatch eu Battletag#2016`" - }, - "acro": { - "Cmd": "acrophobia acro", - "Desc": "Starts an Acrophobia game. Second argument is optional round length in seconds. (default is 60)", - "Usage": "`{0}acro` or `{0}acro 30`" - }, - "logevents": { - "Cmd": "logevents", - "Desc": "Shows a list of all events you can subscribe to with `{0}log`", - "Usage": "`{0}logevents`" - }, - "log": { - "Cmd": "log", - "Desc": "Toggles logging event. Disables it if it is active anywhere on the server. Enables if it isn't active. Use `{0}logevents` to see a list of all events you can subscribe to.", - "Usage": "`{0}log userpresence` or `{0}log userbanned`" - }, - "fairplay": { - "Cmd": "fairplay fp", - "Desc": "Toggles fairplay. While enabled, the bot will prioritize songs from users who didn't have their song recently played instead of the song's position in the queue.", - "Usage": "`{0}fp`" - }, - "songautodelete": { - "Cmd": "songautodelete sad", - "Desc": "Toggles whether the song should be automatically removed from the music queue when it finishes playing.", - "Usage": "`{0}sad`" - }, - "define": { - "Cmd": "define def", - "Desc": "Finds a definition of a word.", - "Usage": "`{0}def heresy`" - }, - "setmaxplaytime": { - "Cmd": "setmaxplaytime smp", - "Desc": "Sets a maximum number of seconds (>14) a song can run before being skipped automatically. Set 0 to have no limit.", - "Usage": "`{0}smp 0` or `{0}smp 270`" - }, - "activity": { - "Cmd": "activity", - "Desc": "Checks for spammers.", - "Usage": "`{0}activity`" - }, - "autohentai": { - "Cmd": "autohentai", - "Desc": "Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable.", - "Usage": "`{0}autohentai 30 yuri|tail|long_hair` or `{0}autohentai`" - }, - "setstatus": { - "Cmd": "setstatus", - "Desc": "Sets the bot's status. (Online/Idle/Dnd/Invisible)", - "Usage": "`{0}setstatus Idle`" - }, - "rotaterolecolor": { - "Cmd": "rotaterolecolor rrc", - "Desc": "Rotates a roles color on an interval with a list of supplied colors. First argument is interval in seconds (Minimum 60). Second argument is a role, followed by a space-separated list of colors in hex. Provide a rolename with a 0 interval to disable.", - "Usage": "`{0}rrc 60 MyLsdRole #ff0000 #00ff00 #0000ff` or `{0}rrc 0 MyLsdRole`" - }, - "createinvite": { - "Cmd": "createinvite crinv", - "Desc": "Creates a new invite which has infinite max uses and never expires.", - "Usage": "`{0}crinv`" - }, - "pollstats": { - "Cmd": "pollstats", - "Desc": "Shows the poll results without stopping the poll on this server.", - "Usage": "`{0}pollstats`" - }, - "repeatlist": { - "Cmd": "repeatlist replst", - "Desc": "Shows currently repeating messages and their indexes.", - "Usage": "`{0}repeatlist`" - }, - "repeatremove": { - "Cmd": "repeatremove reprm", - "Desc": "Removes a repeating message on a specified index. Use `{0}repeatlist` to see indexes.", - "Usage": "`{0}reprm 2`" - }, - "antilist": { - "Cmd": "antilist antilst", - "Desc": "Shows currently enabled protection features.", - "Usage": "`{0}antilist`" - }, - "antispamignore": { - "Cmd": "antispamignore", - "Desc": "Toggles whether antispam ignores current channel. Antispam must be enabled.", - "Usage": "`{0}antispamignore`" - }, - "cmdcosts": { - "Cmd": "cmdcosts", - "Desc": "Shows a list of command costs. Paginated with 9 commands per page.", - "Usage": "`{0}cmdcosts` or `{0}cmdcosts 2`" - }, - "commandcost": { - "Cmd": "commandcost cmdcost", - "Desc": "Sets a price for a command. Running that command will take currency from users. Set 0 to remove the price.", - "Usage": "`{0}cmdcost 0 !!q` or `{0}cmdcost 1 {0}8ball`" - }, - "startevent": { - "Cmd": "startevent", - "Desc": "Starts one of the events seen on public nadeko.", - "Usage": "`{0}startevent flowerreaction`" - }, - "slotstats": { - "Cmd": "slotstats", - "Desc": "Shows the total stats of the slot command for this bot's session.", - "Usage": "`{0}slotstats`" - }, - "slottest": { - "Cmd": "slottest", - "Desc": "Tests to see how much slots payout for X number of plays.", - "Usage": "`{0}slottest 1000`" - }, - "slot": { - "Cmd": "slot", - "Desc": "Play Nadeko slots. Max bet is 9999. 1.5 second cooldown per user.", - "Usage": "`{0}slot 5`" - }, - "waifuclaimeraffinity": { - "Cmd": "affinity", - "Desc": "Sets your affinity towards someone you want to be claimed by. Setting affinity will reduce their `{0}claim` on you by 20%. You can leave second argument empty to clear your affinity. 30 minutes cooldown.", - "Usage": "`{0}affinity @MyHusband` or `{0}affinity`" - }, - "waifuclaim": { - "Cmd": "claimwaifu claim", - "Desc": "Claim a waifu for yourself by spending currency. You must spend at least 10% more than her current value unless she set `{0}affinity` towards you.", - "Usage": "`{0}claim 50 @Himesama`" - }, - "waifugift": { - "Cmd": "waifugift gift gifts", - "Desc": "Gift an item to someone. This will increase their waifu value by 50% of the gifted item's value if they don't have affinity set towards you, or 100% if they do. Provide no arguments to see a list of items that you can gift.", - "Usage": "`{0}gifts` or `{0}gift Rose @Himesama`" - }, - "waifuleaderboard": { - "Cmd": "waifus waifulb", - "Desc": "Shows top 9 waifus. You can specify another page to show other waifus.", - "Usage": "`{0}waifus` or `{0}waifulb 3`" - }, - "divorce": { - "Cmd": "divorce", - "Desc": "Releases your claim on a specific waifu. You will get some of the money you've spent back unless that waifu has an affinity towards you. 6 hours cooldown.", - "Usage": "`{0}divorce @CheatingSloot`" - }, - "waifuinfo": { - "Cmd": "waifuinfo waifustats", - "Desc": "Shows waifu stats for a target person. Defaults to you if no user is provided.", - "Usage": "`{0}waifuinfo @MyCrush` or `{0}waifuinfo`" - }, - "mal": { - "Cmd": "mal", - "Desc": "Shows basic info from a MyAnimeList profile.", - "Usage": "`{0}mal straysocks`" - }, - "setmusicchannel": { - "Cmd": "setmusicchannel smch", - "Desc": "Sets the current channel as the default music output channel. This will output playing, finished, paused and removed songs to that channel instead of the channel where the first song was queued in.", - "Usage": "`{0}smch`" - }, - "reloadimages": { - "Cmd": "reloadimages", - "Desc": "Reloads images bot is using. Safe to use even when bot is being used heavily.", - "Usage": "`{0}reloadimages`" - }, - "shardstats": { - "Cmd": "shardstats", - "Desc": "Stats for shards. Paginated with 25 shards per page.", - "Usage": "`{0}shardstats` or `{0}shardstats 2`" - }, - "restartshard": { - "Cmd": "restartshard", - "Desc": "Try (re)connecting a shard with a certain shardid when it dies. No one knows will it work. Keep an eye on the console for errors.", - "Usage": "`{0}restartshard 2`" - }, - "shardid": { - "Cmd": "shardid", - "Desc": "Shows which shard is a certain guild on, by guildid.", - "Usage": "`{0}shardid 117523346618318850`" - }, - "tictactoe": { - "Cmd": "tictactoe ttt", - "Desc": "Starts a game of tic tac toe. Another user must run the command in the same channel in order to accept the challenge. Use numbers 1-9 to play. 15 seconds per move.", - "Usage": "{0}ttt" - }, - "timezones": { - "Cmd": "timezones", - "Desc": "Lists all timezones available on the system to be used with `{0}timezone`.", - "Usage": "`{0}timezones`" - }, - "timezone": { - "Cmd": "timezone", - "Desc": "Sets this guilds timezone. This affects bot's time output in this server (logs, etc..)", - "Usage": "`{0}timezone` or `{0}timezone GMT Standard Time`" - }, - "languagesetdefault": { - "Cmd": "langsetdefault langsetd", - "Desc": "Sets the bot's default response language. All servers which use a default locale will use this one. Setting to `default` will use the host's current culture. Provide no arguments to see currently set language.", - "Usage": "`{0}langsetd en-US` or `{0}langsetd default`" - }, - "languageset": { - "Cmd": "languageset langset", - "Desc": "Sets this server's response language. If bot's response strings have been translated to that language, bot will use that language in this server. Reset by using `default` as the locale name. Provide no arguments to see currently set language.", - "Usage": "`{0}langset de-DE ` or `{0}langset default`" - }, - "languageslist": { - "Cmd": "languageslist langli", - "Desc": "List of languages for which translation (or part of it) exist atm.", - "Usage": "`{0}langli`" - }, - "rategirl": { - "Cmd": "rategirl", - "Desc": "Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart.", - "Usage": "`{0}rategirl @SomeGurl`" - }, - "lucky7test": { - "Cmd": "lucky7test l7t", - "Desc": "Tests the l7 command.", - "Usage": "`{0}l7t 10000`" - }, - "lucky7": { - "Cmd": "lucky7 l7", - "Desc": "Bet currency on the game and start rolling 3 sided dice. At any point you can choose to [m]ove (roll again) or [s]tay (get the amount bet times the current multiplier).", - "Usage": "`{0}l7 10` or `{0}l7 move` or `{0}l7 s`" - }, - "vcrolelist": { - "Cmd": "vcrolelist", - "Desc": "Shows a list of currently set voice channel roles.", - "Usage": "`{0}vcrolelist`" - }, - "vcrole": { - "Cmd": "vcrole", - "Desc": "Sets or resets a role which will be given to users who join the voice channel you're in when you run this command. Provide no role name to disable. You must be in a voice channel to run this command.", - "Usage": "`{0}vcrole SomeRole` or `{0}vcrole`" - }, - "crad": { - "Cmd": "crad", - "Desc": "Toggles whether the message triggering the custom reaction will be automatically deleted.", - "Usage": "`{0}crad 59`" - }, - "crdm": { - "Cmd": "crdm", - "Desc": "Toggles whether the response message of the custom reaction will be sent as a direct message.", - "Usage": "`{0}crdm 44`" - }, - "crca": { - "Cmd": "crca", - "Desc": "Toggles whether the custom reaction will trigger if the triggering message contains the keyword (instead of only starting with it).", - "Usage": "`{0}crca 44`" - }, - "aliaslist": { - "Cmd": "aliaslist cmdmaplist aliases", - "Desc": "Shows the list of currently set aliases. Paginated.", - "Usage": "`{0}aliaslist` or `{0}aliaslist 3`" - }, - "alias": { - "Cmd": "alias cmdmap", - "Desc": "Create a custom alias for a certain Nadeko command. Provide no alias to remove the existing one.", - "Usage": "`{0}alias allin $bf 100 h` or `{0}alias \"linux thingy\" >loonix Spyware Windows`" - }, - "warnlog": { - "Cmd": "warnlog", - "Desc": "See a list of warnings of a certain user.", - "Usage": "`{0}warnlog @b1nzy`" - }, - "warnlogall": { - "Cmd": "warnlogall", - "Desc": "See a list of all warnings on the server. 15 users per page.", - "Usage": "`{0}warnlogall` or `{0}warnlogall 2`" - }, - "warn": { - "Cmd": "warn", - "Desc": "Warns a user.", - "Usage": "`{0}warn @b1nzy Very rude person`" - }, - "startupcommandadd": { - "Cmd": "scadd", - "Desc": "Adds a command to the list of commands which will be executed automatically in the current channel, in the order they were added in, by the bot when it startups up.", - "Usage": "`{0}scadd .stats`" - }, - "startupcommandremove": { - "Cmd": "scrm", - "Desc": "Removes a startup command with the provided command text.", - "Usage": "`{0}scrm .stats`" - }, - "startupcommandsclear": { - "Cmd": "scclr", - "Desc": "Removes all startup commands.", - "Usage": "`{0}scclr`" - }, - "startupcommands": { - "Cmd": "sclist", - "Desc": "Lists all startup commands in the order they will be executed in.", - "Usage": "`{0}sclist`" - }, - "unban": { - "Cmd": "unban", - "Desc": "Unbans a user with the provided user#discrim or id.", - "Usage": "`{0}unban kwoth#1234` or `{0}unban 123123123`" - }, - "wait": { - "Cmd": "wait", - "Desc": "Used only as a startup command. Waits a certain number of miliseconds before continuing the execution of the following startup commands.", - "Usage": "`{0}wait 3000`" - }, - "warnclear": { - "Cmd": "warnclear warnc", - "Desc": "Clears all warnings from a certain user.", - "Usage": "`{0}warnclear @PoorDude`" - }, - "warnpunishlist": { - "Cmd": "warnpunishlist warnpl", - "Desc": "Lists punishments for warnings.", - "Usage": "`{0}warnpunishlist`" - }, - "warnpunish": { - "Cmd": "warnpunish warnp", - "Desc": "Sets a punishment for a certain number of warnings. Provide no punishment to remove.", - "Usage": "`{0}warnpunish 5 Ban` or `{0}warnpunish 3`" - }, - "claimpatreonrewards": { - "Cmd": "clparew", - "Desc": "Claim patreon rewards. If you're subscribed to bot owner's patreon you can use this command to claim your rewards - assuming bot owner did setup has their patreon key.", - "Usage": "`{0}clparew`" - }, - "ping": { - "Cmd": "ping", - "Desc": "Ping the bot to see if there are latency issues.", - "Usage": "`{0}ping`" - }, - "slowmodewhitelist": { - "Cmd": "slowmodewl", - "Desc": "Ignores a role or a user from the slowmode feature.", - "Usage": "`{0}slowmodewl SomeRole` or `{0}slowmodewl AdminDude`" - }, - "time": { - "Cmd": "time", - "Desc": "Shows the current time and timezone in the specified location.", - "Usage": "`{0}time London, UK`" - }, - "patreonrewardsreload": { - "Cmd": "parewrel", - "Desc": "Forces the update of the list of patrons who are eligible for the reward.", - "Usage": "`{0}parewrel`" - }, - "shopadd": { - "Cmd": "shopadd", - "Desc": "Adds an item to the shop by specifying type price and name. Available types are role and list.", - "Usage": "`{0}shopadd role 1000 Rich`" - }, - "shopremove": { - "Cmd": "shoprem shoprm", - "Desc": "Removes an item from the shop by its ID.", - "Usage": "`{0}shoprm 1`" - }, - "shop": { - "Cmd": "shop", - "Desc": "Lists this server's administrators' shop. Paginated.", - "Usage": "`{0}shop` or `{0}shop 2`" - }, - "rolehoist": { - "Cmd": "rolehoist rh", - "Desc": "Toggles whether this role is displayed in the sidebar or not.", - "Usage": "`{0}rh Guests` or `{0}rh \"Space Wizards\"`" - }, - "buy": { - "Cmd": "buy", - "Desc": "Buys an item from the shop on a given index. If buying items, make sure that the bot can DM you.", - "Usage": "`{0}buy 2`" - }, - "gamevoicechannel": { - "Cmd": "gvc", - "Desc": "Toggles game voice channel feature in the voice channel you're currently in. Users who join the game voice channel will get automatically redirected to the voice channel with the name of their current game, if it exists. Can't move users to channels that the bot has no connect permission for. One per server.", - "Usage": "`{0}gvc`" - }, - "shoplistadd": { - "Cmd": "shoplistadd", - "Desc": "Adds an item to the list of items for sale in the shop entry given the index. You usually want to run this command in the secret channel, so that the unique items are not leaked.", - "Usage": "`{0}shoplistadd 1 Uni-que-Steam-Key`" - }, - "gcmd": { - "Cmd": "globalcommand gcmd", - "Desc": "Toggles whether a command can be used on any server.", - "Usage": "`{0}gcmd .stats`" - }, - "gmod": { - "Cmd": "globalmodule gmod", - "Desc": "Toggles whether a module can be used on any server.", - "Usage": "`{0}gmod nsfw`" - }, - "lgp": { - "Cmd": "listglobalperms lgp", - "Desc": "Lists global permissions set by the bot owner.", - "Usage": "`{0}lgp`" - }, - "resetglobalpermissions": { - "Cmd": "resetglobalperms", - "Desc": "Resets global permissions set by bot owner.", - "Usage": "`{0}resetglobalperms`" - }, - "prefix": { - "Cmd": "prefix", - "Desc": "Sets this server's prefix for all bot commands. Provide no arguments to see the current server prefix.", - "Usage": "`{0}prefix +`" - }, - "defprefix": { - "Cmd": "defprefix", - "Desc": "Sets bot's default prefix for all bot commands. Provide no arguments to see the current default prefix. This will not change this server's current prefix.", - "Usage": "`{0}defprefix +`" - }, - "verboseerror": { - "Cmd": "verboseerror ve", - "Desc": "Toggles whether the bot should print command errors when a command is incorrectly used.", - "Usage": "`{0}ve`" - }, - "streamrolekeyword": { - "Cmd": "streamrolekw srkw", - "Desc": "Sets keyword which is required in the stream's title in order for the streamrole to apply. Provide no keyword in order to reset.", - "Usage": "`{0}srkw` or `{0}srkw PUBG`" - }, - "streamroleblacklist": { - "Cmd": "streamrolebl srbl", - "Desc": "Adds or removes a blacklisted user. Blacklisted users will never receive the stream role.", - "Usage": "`{0}srbl add @b1nzy#1234` or `{0}srbl rem @b1nzy#1234`" - }, - "streamrolewhitelist": { - "Cmd": "streamrolewl srwl", - "Desc": "Adds or removes a whitelisted user. Whitelisted users will receive the stream role even if they don't have the specified keyword in their stream title.", - "Usage": "`{0}srwl add @b1nzy#1234` or `{0}srwl rem @b1nzy#1234`" - }, - "botconfigedit": { - "Cmd": "botconfigedit bce", - "Desc": "Sets one of available bot config settings to a specified value. Use the command without any parameters to get a list of available settings.", - "Usage": "`{0}bce CurrencyName b1nzy` or `{0}bce`" - }, - "nsfwtagblacklist": { - "Cmd": "nsfwtagbl nsfwtbl", - "Desc": "Toggles whether the tag is blacklisted or not in nsfw searches. Provide no parameters to see the list of blacklisted tags.", - "Usage": "`{0}nsfwtbl poop`" - }, - "experience": { - "Cmd": "experience xp", - "Desc": "Shows your xp stats. Specify the user to show that user's stats instead.", - "Usage": "`{0}xp`" - }, - "xpexclusionlist": { - "Cmd": "xpexclusionlist xpexl", - "Desc": "Shows the roles and channels excluded from the XP system on this server, as well as whether the whole server is excluded.", - "Usage": "`{0}xpexl`" - }, - "xpexclude": { - "Cmd": "xpexclude xpex", - "Desc": "Exclude a channel, role or current server from the xp system.", - "Usage": "`{0}xpex Role Excluded-Role` `{0}xpex Server`" - }, - "xpnotify": { - "Cmd": "xpnotify xpn", - "Desc": "Sets how the bot should notify you when you get a `server` or `global` level. You can set `dm` (for the bot to send a direct message), `channel` (to get notified in the channel you sent the last message in) or `none` to disable.", - "Usage": "`{0}xpn global dm` `{0}xpn server channel`" - }, - "xprolerewards": { - "Cmd": "xprolerewards xprrs", - "Desc": "Shows currently set role rewards.", - "Usage": "`{0}xprrs`" - }, - "xprolereward": { - "Cmd": "xprolereward xprr", - "Desc": "Sets a role reward on a specified level. Provide no role name in order to remove the role reward.", - "Usage": "`{0}xprr 3 Social`" - }, - "xpleaderboard": { - "Cmd": "xpleaderboard xplb", - "Desc": "Shows current server's xp leaderboard.", - "Usage": "`{0}xplb`" - }, - "xpgloballeaderboard": { - "Cmd": "xpgleaderboard xpglb", - "Desc": "Shows the global xp leaderboard.", - "Usage": "`{0}xpglb`" - }, - "xpadd": { - "Cmd": "xpadd", - "Desc": "Adds xp to a user on the server. This does not affect their global ranking. You can use negative values.", - "Usage": "`{0}xpadd 100 @b1nzy`" - }, - "clubcreate": { - "Cmd": "clubcreate", - "Desc": "Creates a club. You must be atleast level 5 and not be in the club already.", - "Usage": "`{0}clubcreate b1nzy's friends`" - }, - "clubinformation": { - "Cmd": "clubinfo", - "Desc": "Shows information about the club.", - "Usage": "`{0}clubinfo b1nzy's friends#123`" - }, - "clubapply": { - "Cmd": "clubapply", - "Desc": "Apply to join a club. You must meet that club's minimum level requirement, and not be on its ban list.", - "Usage": "`{0}clubapply b1nzy's friends#123`" - }, - "clubaccept": { - "Cmd": "clubaccept", - "Desc": "Accept a user who applied to your club.", - "Usage": "`{0}clubaccept b1nzy#1337`" - }, - "clubleave": { - "Cmd": "clubleave", - "Desc": "Leaves the club you're currently in.", - "Usage": "`{0}clubleave`" - }, - "clubdisband": { - "Cmd": "clubdisband", - "Desc": "Disbands the club you're the owner of. This action is irreversible.", - "Usage": "`{0}clubdisband`" - }, - "clubkick": { - "Cmd": "clubkick", - "Desc": "Kicks the user from the club. You must be the club owner. They will be able to apply again.", - "Usage": "`{0}clubkick b1nzy#1337`" - }, - "clubban": { - "Cmd": "clubban", - "Desc": "Bans the user from the club. You must be the club owner. They will not be able to apply again.", - "Usage": "`{0}clubban b1nzy#1337`" - }, - "clubunban": { - "Cmd": "clubunban", - "Desc": "Unbans the previously banned user from the club. You must be the club owner.", - "Usage": "`{0}clubunban b1nzy#1337`" - }, - "clublevelreq": { - "Cmd": "clublevelreq", - "Desc": "Sets the club required level to apply to join the club. You must be club owner. You can't set this number below 5.", - "Usage": "`{0}clublevelreq 7`" - }, - "clubicon": { - "Cmd": "clubicon", - "Desc": "Sets the club icon.", - "Usage": "`{0}clubicon https://i.imgur.com/htfDMfU.png`" - }, - "clubapps": { - "Cmd": "clubapps", - "Desc": "Shows the list of users who have applied to your club. Paginated. You must be club owner to use this command.", - "Usage": "`{0}clubapps 2`" - }, - "clubbans": { - "Cmd": "clubbans", - "Desc": "Shows the list of users who have banned from your club. Paginated. You must be club owner to use this command.", - "Usage": "`{0}clubbans 2`" - }, - "clubleaderboard": { - "Cmd": "clublb", - "Desc": "Shows club rankings on the specified page.", - "Usage": "`{0}clublb 2`" - }, - "nsfwclearcache": { - "Cmd": "nsfwcc", - "Desc": "Clears nsfw cache.", - "Usage": "`{0}nsfwcc`" - }, - "clubadmin": { - "Cmd": "clubadmin", - "Desc": "Assigns (or unassigns) staff role to the member of the club. Admins can ban, kick and accept applications.", - "Usage": "`{0}clubadmin`" - }, - "autoboobs": { - "Cmd": "autoboobs", - "Desc": "Posts a boobs every X seconds. 20 seconds minimum. Provide no arguments to disable.", - "Usage": "`{0}autoboobs 30` or `{0}autoboobs`" - }, - "autobutts": { - "Cmd": "autobutts", - "Desc": "Posts a butts every X seconds. 20 seconds minimum. Provide no arguments to disable.", - "Usage": "`{0}autobutts 30` or `{0}autobutts`" - }, - "eightball": { - "cmd": "8ball", - "desc": "Ask the 8ball a yes/no question.", - "usage": "`{0}8ball`" - } -} \ No newline at end of file