From 91008be48dc9d6071b202b863a44ea06df9e505e Mon Sep 17 00:00:00 2001 From: xsftk Date: Sat, 11 Nov 2017 14:06:48 +0700 Subject: [PATCH 01/22] .crca fix? https://github.com/Kwoth/NadekoBot/issues/1455 GetWordPosition should ignore non valid characters now most thai/chinese/japanese words arent separated by space iirc --- .../CustomReactions/Extensions/Extensions.cs | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs index 9d6f6f6c..6c8cc4cb 100644 --- a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs +++ b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs @@ -2,16 +2,16 @@ using AngleSharp.Dom.Html; using Discord; using Discord.WebSocket; +using NadekoBot.Common; +using NadekoBot.Common.Replacements; +using NadekoBot.Core.Services.Database.Models; using NadekoBot.Extensions; using NadekoBot.Modules.CustomReactions.Services; -using NadekoBot.Core.Services.Database.Models; using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; -using NadekoBot.Common; -using NadekoBot.Common.Replacements; namespace NadekoBot.Modules.CustomReactions.Extensions { @@ -89,7 +89,7 @@ namespace NadekoBot.Modules.CustomReactions.Extensions public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client) => cr.Trigger.ResolveTriggerString(ctx, client); - public static Task ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, bool containsAnywhere) + public static Task ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, bool containsAnywhere) => cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client), containsAnywhere); public static async Task Send(this CustomReaction cr, IUserMessage ctx, DiscordSocketClient client, CustomReactionsService crs) @@ -127,14 +127,35 @@ namespace NadekoBot.Modules.CustomReactions.Extensions public static WordPosition GetWordPosition(this string str, string word) { - if (str.StartsWith(word + " ")) - return WordPosition.Start; - else if (str.EndsWith(" " + word)) - return WordPosition.End; - else if (str.Contains(" " + word + " ")) - return WordPosition.Middle; - else + var indexOfWord = str.IndexOf(word); + if (indexOfWord == -1) return WordPosition.None; + + if (indexOfWord == 0) // on start + { + if (word.Length < str.Length &&str.isInvalidWordChar(word.Length)) // filter char after word index + return WordPosition.Start; + } + else if ((indexOfWord + word.Length) == str.Length) // on end + { + if (str.isInvalidWordChar(indexOfWord-1)) // filter char before word index + return WordPosition.End; + } + else if (str.isInvalidWordChar(indexOfWord-1) && str.isInvalidWordChar(indexOfWord + word.Length)) // on middle + return WordPosition.Middle; + + return WordPosition.None; + } + + private static bool isInvalidWordChar(this string str, int index) + { + var ch = str[index]; + if ((byte)ch > 64 && (byte)ch <= 90) // must be A-Z + return false; + if ((byte)ch > 97 && (byte)ch <= 122) // a-z + return false; + + return true; } } @@ -145,4 +166,4 @@ namespace NadekoBot.Modules.CustomReactions.Extensions Middle, End, } -} +} \ No newline at end of file From 4f3e2565a49e0c82647ed246c869eef089913599 Mon Sep 17 00:00:00 2001 From: xsftk Date: Sat, 11 Nov 2017 15:04:58 +0700 Subject: [PATCH 02/22] .crca fix? https://github.com/Kwoth/NadekoBot/issues/1455 GetWordPosition should ignore special characters now chinese sentence doesnt have space as word separator nor a word separator at all, same goes for thai,etc. iirc :) --- .../Modules/CustomReactions/Extensions/Extensions.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs index 6c8cc4cb..7e24cff6 100644 --- a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs +++ b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs @@ -133,15 +133,15 @@ namespace NadekoBot.Modules.CustomReactions.Extensions if (indexOfWord == 0) // on start { - if (word.Length < str.Length &&str.isInvalidWordChar(word.Length)) // filter char after word index + if (word.Length < str.Length && str.isInvalidWordChar(word.Length)) // filter char after word index return WordPosition.Start; } else if ((indexOfWord + word.Length) == str.Length) // on end { - if (str.isInvalidWordChar(indexOfWord-1)) // filter char before word index + if (str.isInvalidWordChar(indexOfWord - 1)) // filter char before word index return WordPosition.End; } - else if (str.isInvalidWordChar(indexOfWord-1) && str.isInvalidWordChar(indexOfWord + word.Length)) // on middle + else if (str.isInvalidWordChar(indexOfWord - 1) && str.isInvalidWordChar(indexOfWord + word.Length)) // on middle return WordPosition.Middle; return WordPosition.None; @@ -149,10 +149,10 @@ namespace NadekoBot.Modules.CustomReactions.Extensions private static bool isInvalidWordChar(this string str, int index) { - var ch = str[index]; - if ((byte)ch > 64 && (byte)ch <= 90) // must be A-Z + var ch = (ushort)str[index]; + if (ch > 64 && ch <= 90) // must be A-Z return false; - if ((byte)ch > 97 && (byte)ch <= 122) // a-z + if (ch > 97 && ch <= 122) // a-z return false; return true; From adb850d3068be46059f329930672c2fd60a3ca15 Mon Sep 17 00:00:00 2001 From: xsftk Date: Sat, 11 Nov 2017 15:19:18 +0700 Subject: [PATCH 03/22] lil fix --- .../Modules/CustomReactions/Extensions/Extensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs index 7e24cff6..1711b95c 100644 --- a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs +++ b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs @@ -150,9 +150,9 @@ namespace NadekoBot.Modules.CustomReactions.Extensions private static bool isInvalidWordChar(this string str, int index) { var ch = (ushort)str[index]; - if (ch > 64 && ch <= 90) // must be A-Z + if (ch >= 65 && ch <= 90) // must be A-Z return false; - if (ch > 97 && ch <= 122) // a-z + if (ch >= 97 && ch <= 122) // a-z return false; return true; From 497e25b19932b4e2027bb149ec6bad6621021138 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 12 Nov 2017 06:50:12 +0100 Subject: [PATCH 04/22] Removed leftover thing --- .../Modules/Searches/Services/SearchesService.cs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs index 2755cfb1..098364d9 100644 --- a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs +++ b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs @@ -132,22 +132,6 @@ namespace NadekoBot.Modules.Searches.Services return Task.CompletedTask; }; - if (client.ShardId == 0) - { - _t = new Timer(async _ => - { - var r = _cache.Redis.GetDatabase(); - try - { - - } - catch (Exception ex) - { - _log.Warn(ex); - } - }, null, TimeSpan.Zero, TimeSpan.FromHours(1)); - } - //joke commands if (File.Exists("data/wowjokes.json")) { From ee929c6dfc3edacc926c05e2788ab0b6edb2c9ee Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 12 Nov 2017 07:57:01 +0100 Subject: [PATCH 05/22] .novel fixed, close #1819 --- NadekoBot.Core/Modules/Searches/AnimeSearchCommands.cs | 4 ++-- .../Modules/Searches/Services/AnimeSearchService.cs | 2 ++ NadekoBot.Core/Modules/Searches/Services/SearchesService.cs | 1 - src/NadekoBot/_strings/ResponseStrings.en-US.json | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/NadekoBot.Core/Modules/Searches/AnimeSearchCommands.cs b/NadekoBot.Core/Modules/Searches/AnimeSearchCommands.cs index fb1b0bd0..0fe17431 100644 --- a/NadekoBot.Core/Modules/Searches/AnimeSearchCommands.cs +++ b/NadekoBot.Core/Modules/Searches/AnimeSearchCommands.cs @@ -26,7 +26,7 @@ namespace NadekoBot.Modules.Searches if (novelData == null) { - await ReplyErrorLocalized("error_finding_novel").ConfigureAwait(false); + await ReplyErrorLocalized("failed_finding_novel").ConfigureAwait(false); return; } @@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Searches .WithTitle(novelData.Title) .WithUrl(novelData.Link) .WithImageUrl(novelData.ImageUrl) - .AddField(efb => efb.WithName(GetText("authors")).WithValue(String.Join("\n", novelData.Authors)).WithIsInline(true)) + .AddField(efb => efb.WithName(GetText("authors")).WithValue(string.Join("\n", novelData.Authors)).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("status")).WithValue(novelData.Status).WithIsInline(true)) .AddField(efb => efb.WithName(GetText("genres")).WithValue(string.Join(" ", novelData.Genres.Any() ? novelData.Genres : new[] { "none" })).WithIsInline(true)) .WithFooter(efb => efb.WithText(GetText("score") + " " + novelData.Score)); diff --git a/NadekoBot.Core/Modules/Searches/Services/AnimeSearchService.cs b/NadekoBot.Core/Modules/Searches/Services/AnimeSearchService.cs index e236fa51..daa5492c 100644 --- a/NadekoBot.Core/Modules/Searches/Services/AnimeSearchService.cs +++ b/NadekoBot.Core/Modules/Searches/Services/AnimeSearchService.cs @@ -67,6 +67,8 @@ namespace NadekoBot.Modules.Searches.Services var document = await BrowsingContext.New(config).OpenAsync(link); var imageElem = document.QuerySelector("div.seriesimg > img"); + if (imageElem == null) + return null; var imageUrl = ((IHtmlImageElement)imageElem).Source; var descElem = document.QuerySelector("div#editdescription > p"); diff --git a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs index 098364d9..8656a038 100644 --- a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs +++ b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs @@ -51,7 +51,6 @@ namespace NadekoBot.Modules.Searches.Services public ConcurrentDictionary AutoButtTimers { get; } = new ConcurrentDictionary(); private readonly ConcurrentDictionary> _blacklistedTags = new ConcurrentDictionary>(); - private readonly Timer _t; private readonly SemaphoreSlim _cryptoLock = new SemaphoreSlim(1, 1); public async Task CryptoData() diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index 12b5ba93..dfabc637 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -923,5 +923,5 @@ "administration_invalid": "Invalid / Can't be found ({0})", "administration_mass_kill_in_progress": "Mass Banning and Blacklisting of {0} users is in progress...", "administration_mass_kill_completed": "Mass Banning and Blacklisting of {0} users is complete.", - "searches_error_finding_novel": "Can't find that novel. Make sure you've typed the exact full name, and that it exists on novelupdates.com" + "searches_failed_finding_novel": "Can't find that novel. Make sure you've typed the exact full name, and that it exists on novelupdates.com" } \ No newline at end of file From 35005b92b36eef6a28077ee148448cbf10528a93 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 12 Nov 2017 08:15:06 +0100 Subject: [PATCH 06/22] Maybe fixes #1811 --- NadekoBot.Core/Modules/Administration/LocalizationCommands.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NadekoBot.Core/Modules/Administration/LocalizationCommands.cs b/NadekoBot.Core/Modules/Administration/LocalizationCommands.cs index d91a50a8..677eff0d 100644 --- a/NadekoBot.Core/Modules/Administration/LocalizationCommands.cs +++ b/NadekoBot.Core/Modules/Administration/LocalizationCommands.cs @@ -47,6 +47,7 @@ namespace NadekoBot.Modules.Administration [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] + [Priority(0)] public async Task LanguageSet() { var cul = _localization.GetCultureInfo(Context.Guild); @@ -57,6 +58,7 @@ namespace NadekoBot.Modules.Administration [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequireUserPermission(GuildPermission.Administrator)] + [Priority(1)] public async Task LanguageSet(string name) { try From 4e371275369d49146d9c19248f12df7304666bf7 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 12 Nov 2017 08:18:40 +0100 Subject: [PATCH 07/22] Possibly fix #1821 --- NadekoBot.Core/Modules/Utility/InfoCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Utility/InfoCommands.cs b/NadekoBot.Core/Modules/Utility/InfoCommands.cs index 96243dcc..26fca5c4 100644 --- a/NadekoBot.Core/Modules/Utility/InfoCommands.cs +++ b/NadekoBot.Core/Modules/Utility/InfoCommands.cs @@ -118,7 +118,7 @@ namespace NadekoBot.Modules.Utility [OwnerOnly] public async Task Activity(int page = 1) { - const int activityPerPage = 15; + const int activityPerPage = 10; page -= 1; if (page < 0) From 95584cba6236d124ef49cd4f237a322ec5b893fe Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 12 Nov 2017 08:43:51 +0100 Subject: [PATCH 08/22] upped version to 2.4.4 --- NadekoBot.Core/Services/Impl/StatsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NadekoBot.Core/Services/Impl/StatsService.cs b/NadekoBot.Core/Services/Impl/StatsService.cs index d05ff01f..044cda71 100644 --- a/NadekoBot.Core/Services/Impl/StatsService.cs +++ b/NadekoBot.Core/Services/Impl/StatsService.cs @@ -21,7 +21,7 @@ namespace NadekoBot.Core.Services.Impl private readonly IBotCredentials _creds; private readonly DateTime _started; - public const string BotVersion = "2.4.3"; + public const string BotVersion = "2.4.4"; public string Author => "Kwoth#2560"; public string Library => "Discord.Net"; From c4689f267a8bc51d6cfccea412aee79c645aff53 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 14 Nov 2017 06:17:22 +0100 Subject: [PATCH 09/22] fixed #1826 --- NadekoBot.Core/Modules/Utility/Common/Patreon/PatreonPledge.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Utility/Common/Patreon/PatreonPledge.cs b/NadekoBot.Core/Modules/Utility/Common/Patreon/PatreonPledge.cs index 9960039f..ae46aeaa 100644 --- a/NadekoBot.Core/Modules/Utility/Common/Patreon/PatreonPledge.cs +++ b/NadekoBot.Core/Modules/Utility/Common/Patreon/PatreonPledge.cs @@ -7,7 +7,7 @@ public object declined_since { get; set; } public bool is_twitch_pledge { get; set; } public bool patron_pays_fees { get; set; } - public int pledge_cap_cents { get; set; } + public int? pledge_cap_cents { get; set; } } public class Address From fcc006ccc0d46c388a807b37f084a9c6232cfe54 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 14 Nov 2017 06:18:50 +0100 Subject: [PATCH 10/22] small string update --- src/NadekoBot/_strings/ResponseStrings.en-US.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index 12b5ba93..b40fb3eb 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -841,8 +841,10 @@ "xp_level_up_channel": "Congratulations {0}, You've reached level {1}!", "xp_level_up_dm": "Congratulations {0}, You've reached level {1} on {2} server!", "xp_level_up_global": "Congratulations {0}, You've reached global level {1}!", - "xp_role_reward_cleared": "Level {0} will no longer reward a role.", + "xp_role_reward_cleared": "Reaching level {0} will no longer reward a role.", "xp_role_reward_added": "Users who reach level {0} will receive {1} role.", + "xp_cur_reward_cleared": "Reaching level {0} will no longer reward any {1}.", + "xp_cur_reward_added": "Users who reach level {0} will receive {1}.", "xp_role_rewards": "Role Rewards", "xp_level_x": "Level {0}", "xp_no_role_rewards": "No role reward on this page.", From 461dfd553f1c158618db31c7259118f40374f5df Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 02:42:48 +0100 Subject: [PATCH 11/22] currency levelup rewards wip --- .../Modules/Xp/Services/XpService.cs | 44 ++++++++++++++++++ NadekoBot.Core/Modules/Xp/Xp.cs | 45 ++++++++----------- .../Services/Database/Models/XpSettings.cs | 20 +++++++++ .../Impl/GuildConfigRepository.cs | 2 + NadekoBot.Core/Services/Impl/StatsService.cs | 2 +- 5 files changed, 85 insertions(+), 28 deletions(-) diff --git a/NadekoBot.Core/Modules/Xp/Services/XpService.cs b/NadekoBot.Core/Modules/Xp/Services/XpService.cs index 65d9c818..5125ec42 100644 --- a/NadekoBot.Core/Modules/Xp/Services/XpService.cs +++ b/NadekoBot.Core/Modules/Xp/Services/XpService.cs @@ -241,6 +241,50 @@ namespace NadekoBot.Modules.Xp.Services }, token); } + public void SetCurrencyReward(ulong guildId, int level, int amount) + { + using (var uow = _db.UnitOfWork) + { + var settings = uow.GuildConfigs.XpSettingsFor(guildId); + + if (amount <= 0) + { + var toRemove = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level); + if (toRemove != null) + { + uow._context.Remove(toRemove); + settings.CurrencyRewards.Remove(toRemove); + } + } + else + { + + var rew = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level); + + if (rew != null) + rew.Amount = amount; + else + settings.CurrencyRewards.Add(new XpCurrencyReward() + { + Level = level, + Amount = amount, + }); + } + + uow.Complete(); + } + } + + public IEnumerable GetCurrencyRewards(ulong id) + { + using (var uow = _db.UnitOfWork) + { + return uow.GuildConfigs.XpSettingsFor(id) + .CurrencyRewards + .ToArray(); + } + } + public IEnumerable GetRoleRewards(ulong id) { using (var uow = _db.UnitOfWork) diff --git a/NadekoBot.Core/Modules/Xp/Xp.cs b/NadekoBot.Core/Modules/Xp/Xp.cs index aa4224f5..0e2a7a6e 100644 --- a/NadekoBot.Core/Modules/Xp/Xp.cs +++ b/NadekoBot.Core/Modules/Xp/Xp.cs @@ -23,34 +23,10 @@ namespace NadekoBot.Modules.Xp _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)] + //todo add ratelimit attribute //[Ratelimit(30)] public async Task Experience([Remainder]IUser user = null) { @@ -82,7 +58,7 @@ namespace NadekoBot.Modules.Xp .Take(9); var embed = new EmbedBuilder() - .WithTitle(GetText("role_rewards")) + .WithTitle(GetText("level_up_rewards")) .WithOkColor(); if (!roles.Any()) @@ -116,6 +92,21 @@ namespace NadekoBot.Modules.Xp await ReplyConfirmLocalized("role_reward_added", level, Format.Bold(role.ToString())).ConfigureAwait(false); } + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task XpCurrencyReward(int level, int amount=0) + { + if (level < 1 || amount < 0) + return; + + _service.SetCurrencyReward(Context.Guild.Id, level, amount); + + if (amount == 0) + await ReplyConfirmLocalized("cur_reward_cleared", level).ConfigureAwait(false); + else + await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount.ToString())).ConfigureAwait(false); + } + public enum NotifyPlace { Server = 0, diff --git a/NadekoBot.Core/Services/Database/Models/XpSettings.cs b/NadekoBot.Core/Services/Database/Models/XpSettings.cs index ca04d36b..6e5acd42 100644 --- a/NadekoBot.Core/Services/Database/Models/XpSettings.cs +++ b/NadekoBot.Core/Services/Database/Models/XpSettings.cs @@ -8,6 +8,7 @@ namespace NadekoBot.Core.Services.Database.Models public GuildConfig GuildConfig { get; set; } public HashSet RoleRewards { get; set; } = new HashSet(); + public HashSet CurrencyRewards { get; set; } = new HashSet(); public bool XpRoleRewardExclusive { get; set; } public string NotifyMessage { get; set; } = "Congratulations {0}! You have reached level {1}!"; public HashSet ExclusionList { get; set; } = new HashSet(); @@ -35,6 +36,25 @@ namespace NadekoBot.Core.Services.Database.Models } } + public class XpCurrencyReward : DbEntity + { + public int XpSettingsId { get; set; } + public XpSettings XpSettings { get; set; } + + public int Level { get; set; } + public int Amount { get; set; } + + public override int GetHashCode() + { + return Level.GetHashCode() ^ XpSettingsId.GetHashCode(); + } + + public override bool Equals(object obj) + { + return obj is XpCurrencyReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId; + } + } + public class ExcludedItem : DbEntity { public ulong ItemId { get; set; } diff --git a/NadekoBot.Core/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/NadekoBot.Core/Services/Database/Repositories/Impl/GuildConfigRepository.cs index 63e8a314..59ee27b7 100644 --- a/NadekoBot.Core/Services/Database/Repositories/Impl/GuildConfigRepository.cs +++ b/NadekoBot.Core/Services/Database/Repositories/Impl/GuildConfigRepository.cs @@ -200,6 +200,8 @@ namespace NadekoBot.Core.Services.Database.Repositories.Impl set => set.Include(x => x.XpSettings) .ThenInclude(x => x.RoleRewards) .Include(x => x.XpSettings) + .ThenInclude(x => x.CurrencyRewards) + .Include(x => x.XpSettings) .ThenInclude(x => x.ExclusionList)); if (gc.XpSettings == null) diff --git a/NadekoBot.Core/Services/Impl/StatsService.cs b/NadekoBot.Core/Services/Impl/StatsService.cs index 044cda71..93269b62 100644 --- a/NadekoBot.Core/Services/Impl/StatsService.cs +++ b/NadekoBot.Core/Services/Impl/StatsService.cs @@ -21,7 +21,7 @@ namespace NadekoBot.Core.Services.Impl private readonly IBotCredentials _creds; private readonly DateTime _started; - public const string BotVersion = "2.4.4"; + public const string BotVersion = "2.5.0"; public string Author => "Kwoth#2560"; public string Library => "Discord.Net"; From e8fc244bb60486691ca384334a0dfeacba57ec40 Mon Sep 17 00:00:00 2001 From: xsftk Date: Wed, 15 Nov 2017 13:51:00 +0700 Subject: [PATCH 12/22] some renaming and removed comment --- .../CustomReactions/Extensions/Extensions.cs | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs index 1711b95c..b88fd3c0 100644 --- a/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs +++ b/NadekoBot.Core/Modules/CustomReactions/Extensions/Extensions.cs @@ -127,32 +127,32 @@ namespace NadekoBot.Modules.CustomReactions.Extensions public static WordPosition GetWordPosition(this string str, string word) { - var indexOfWord = str.IndexOf(word); - if (indexOfWord == -1) + var wordIndex = str.IndexOf(word); + if (wordIndex == -1) return WordPosition.None; - if (indexOfWord == 0) // on start + if (wordIndex == 0) { - if (word.Length < str.Length && str.isInvalidWordChar(word.Length)) // filter char after word index + if (word.Length < str.Length && str.isValidWordDivider(word.Length)) return WordPosition.Start; } - else if ((indexOfWord + word.Length) == str.Length) // on end + else if ((wordIndex + word.Length) == str.Length) { - if (str.isInvalidWordChar(indexOfWord - 1)) // filter char before word index + if (str.isValidWordDivider(wordIndex - 1)) return WordPosition.End; } - else if (str.isInvalidWordChar(indexOfWord - 1) && str.isInvalidWordChar(indexOfWord + word.Length)) // on middle + else if (str.isValidWordDivider(wordIndex - 1) && str.isValidWordDivider(wordIndex + word.Length)) return WordPosition.Middle; return WordPosition.None; } - private static bool isInvalidWordChar(this string str, int index) + private static bool isValidWordDivider(this string str, int index) { - var ch = (ushort)str[index]; - if (ch >= 65 && ch <= 90) // must be A-Z + var ch = str[index]; + if (ch >= 'a' && ch <= 'z') return false; - if (ch >= 97 && ch <= 122) // a-z + if (ch >= 'A' && ch <= 'Z') return false; return true; From 43ed332f847bf9c822a062acba0f754cdab805eb Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 14:01:40 +0100 Subject: [PATCH 13/22] Currency level up rewards (.xpcr) Bot owner only. --- ...40313_currency level up reward.Designer.cs | 2022 +++++++++++++++++ ...20171115040313_currency level up reward.cs | 45 + .../NadekoSqliteContextModelSnapshot.cs | 28 + .../Modules/Xp/Services/XpService.cs | 49 +- NadekoBot.Core/Modules/Xp/Xp.cs | 43 +- .../_strings/ResponseStrings.en-US.json | 5 +- .../_strings/cmd/command_strings.json | 15 +- 7 files changed, 2170 insertions(+), 37 deletions(-) create mode 100644 NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs create mode 100644 NadekoBot.Core/Migrations/20171115040313_currency level up reward.cs diff --git a/NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs b/NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs new file mode 100644 index 00000000..53ee737a --- /dev/null +++ b/NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs @@ -0,0 +1,2022 @@ +// +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage; +using Microsoft.EntityFrameworkCore.Storage.Internal; +using NadekoBot.Core.Services.Database; +using NadekoBot.Core.Services.Database.Models; +using System; + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoContext))] + [Migration("20171115040313_currency level up reward")] + partial class currencylevelupreward + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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("TimelyCurrency"); + + b.Property("TimelyCurrencyPeriod"); + + b.Property("TriviaCurrencyReward"); + + b.Property("XpMinutesTimeout") + .ValueGeneratedOnAdd() + .HasDefaultValue(5); + + b.Property("XpPerMessage") + .ValueGeneratedOnAdd() + .HasDefaultValue(3); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ClubApplicants", b => + { + b.Property("ClubId"); + + b.Property("UserId"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ClubBans", b => + { + b.Property("ClubId"); + + b.Property("UserId"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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, 21, 20, 53, 13, 305, 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.Core.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.Core.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.Core.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.Core.Services.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("DateAdded"); + + b.Property("GuildConfigId"); + + b.Property("Url") + .IsRequired(); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDcFromVc"); + + 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.Core.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.Core.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.Core.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.Core.Services.Database.Models.LoadedPackage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("DateAdded"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("LoadedPackages"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.Services.Database.Models.Poll", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("DateAdded"); + + b.Property("GuildId"); + + b.Property("Question"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("Poll"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PollAnswer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("Index"); + + b.Property("PollId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollAnswer"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("PollId"); + + b.Property("UserId"); + + b.Property("VoteIndex"); + + b.HasKey("Id"); + + b.HasIndex("PollId"); + + b.ToTable("PollVote"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("DateAdded"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasDefaultValue(0); + + b.Property("GuildId"); + + b.Property("LevelRequirement"); + + b.Property("RoleId"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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, 21, 20, 53, 13, 307, 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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.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.Core.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("DateAdded"); + + b.Property("Level"); + + b.Property("XpSettingsId"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("NadekoBot.Core.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.Core.Services.Database.Models.AntiRaidSetting", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiRaidSetting") + .HasForeignKey("NadekoBot.Core.Services.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.AntiSpamSetting") + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.AntiSpamSetting", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("AntiSpamSetting") + .HasForeignKey("NadekoBot.Core.Services.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.BlacklistItem", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("Blacklist") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.BlockedCmdOrMdl", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("BlockedCommands") + .HasForeignKey("BotConfigId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("BlockedModules") + .HasForeignKey("BotConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ClubApplicants", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ClubBans", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ClubInfo", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("NadekoBot.Core.Services.Database.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.CommandAlias", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.CommandPrice", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("CommandPrices") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.DiscordUser", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.ClubInfo", "Club") + .WithMany("Users") + .HasForeignKey("ClubId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.EightBallResponse", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("EightBallResponses") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ExcludedItem", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.FeedSub", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.GuildConfig", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.Permission", "RootPermission") + .WithMany() + .HasForeignKey("RootPermissionId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.GuildRepeater", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("GuildRepeaters") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.IgnoredLogChannel", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredChannels") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredVoicePresenceChannelIds") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.LoadedPackage", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("LoadedPackages") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.MutedUserId", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.NsfwBlacklitedTag", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("NsfwBlacklistedTags") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.Permission", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.Permission", "Next") + .WithOne("Previous") + .HasForeignKey("NadekoBot.Core.Services.Database.Models.Permission", "NextId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.Permissionv2", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("Permissions") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PlayingStatus", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("RotatingStatusMessages") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.MusicPlaylist") + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PollAnswer", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.Poll") + .WithMany("Answers") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.PollVote", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.Poll") + .WithMany("Votes") + .HasForeignKey("PollId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.RaceAnimal", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("RaceAnimals") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ShopEntry", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.ShopEntryItem", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.ShopEntry") + .WithMany("Items") + .HasForeignKey("ShopEntryId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.StartupCommand", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.BotConfig") + .WithMany("StartupCommands") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.StreamRoleSettings", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("NadekoBot.Core.Services.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.UnmuteTimer", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.VcRoleInfo", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.WaifuInfo", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("NadekoBot.Core.Services.Database.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.WaifuItem", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.WaifuUpdate", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("NadekoBot.Core.Services.Database.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.WarningPunishment", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig") + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpRoleReward", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpSettings", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("NadekoBot.Core.Services.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/NadekoBot.Core/Migrations/20171115040313_currency level up reward.cs b/NadekoBot.Core/Migrations/20171115040313_currency level up reward.cs new file mode 100644 index 00000000..98deb186 --- /dev/null +++ b/NadekoBot.Core/Migrations/20171115040313_currency level up reward.cs @@ -0,0 +1,45 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using System; +using System.Collections.Generic; + +namespace NadekoBot.Migrations +{ + public partial class currencylevelupreward : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "XpCurrencyReward", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Amount = table.Column(type: "INTEGER", nullable: false), + DateAdded = table.Column(type: "TEXT", nullable: true), + Level = table.Column(type: "INTEGER", nullable: false), + XpSettingsId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_XpCurrencyReward", x => x.Id); + table.ForeignKey( + name: "FK_XpCurrencyReward_XpSettings_XpSettingsId", + column: x => x.XpSettingsId, + principalTable: "XpSettings", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_XpCurrencyReward_XpSettingsId", + table: "XpCurrencyReward", + column: "XpSettingsId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "XpCurrencyReward"); + } + } +} diff --git a/NadekoBot.Core/Migrations/NadekoSqliteContextModelSnapshot.cs b/NadekoBot.Core/Migrations/NadekoSqliteContextModelSnapshot.cs index e1462543..ed80cf0e 100644 --- a/NadekoBot.Core/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/NadekoBot.Core/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -1551,6 +1551,26 @@ namespace NadekoBot.Migrations b.ToTable("WarningPunishment"); }); + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("DateAdded"); + + b.Property("Level"); + + b.Property("XpSettingsId"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpRoleReward", b => { b.Property("Id") @@ -1972,6 +1992,14 @@ namespace NadekoBot.Migrations .HasForeignKey("GuildConfigId"); }); + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpCurrencyReward", b => + { + b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + }); + modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpRoleReward", b => { b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings") diff --git a/NadekoBot.Core/Modules/Xp/Services/XpService.cs b/NadekoBot.Core/Modules/Xp/Services/XpService.cs index 5125ec42..705b108a 100644 --- a/NadekoBot.Core/Modules/Xp/Services/XpService.cs +++ b/NadekoBot.Core/Modules/Xp/Services/XpService.cs @@ -36,6 +36,8 @@ namespace NadekoBot.Modules.Xp.Services private readonly NadekoStrings _strings; private readonly IDataCache _cache; private readonly FontProvider _fonts; + private readonly IBotCredentials _creds; + private readonly CurrencyService _cs; public const int XP_REQUIRED_LVL_1 = 36; private readonly ConcurrentDictionary> _excludedRoles @@ -60,7 +62,7 @@ namespace NadekoBot.Modules.Xp.Services public XpService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache, - FontProvider fonts) + FontProvider fonts, IBotCredentials creds, CurrencyService cs) { _db = db; _cmd = cmd; @@ -70,6 +72,8 @@ namespace NadekoBot.Modules.Xp.Services _strings = strings; _cache = cache; _fonts = fonts; + _creds = creds; + _cs = cs; //load settings var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); @@ -105,6 +109,7 @@ namespace NadekoBot.Modules.Xp.Services { var toNotify = new List<(IMessageChannel MessageChannel, IUser User, int Level, XpNotificationType NotifyType, NotifOf NotifOf)>(); var roleRewards = new Dictionary>(); + var curRewards = new Dictionary>(); var toAddTo = new List(); while (_addMessageXp.TryDequeue(out var usr)) @@ -120,14 +125,13 @@ namespace NadekoBot.Modules.Xp.Services { var xp = item.Select(x => bc.BotConfig.XpPerMessage).Sum(); + //1. Mass query discord users and userxpstats and get them from local dict + //2. (better but much harder) Move everything to the database, and get old and new xp + // amounts for every user (in order to give rewards) + var usr = uow.Xp.GetOrCreateUser(item.Key.GuildId, item.Key.User.Id); var du = uow.DiscordUsers.GetOrCreate(item.Key.User); - if (du.LastXpGain + TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout) > DateTime.UtcNow) - continue; - - du.LastXpGain = DateTime.UtcNow; - var globalXp = du.TotalXp; var oldGlobalLevelData = new LevelStats(globalXp); var newGlobalLevelData = new LevelStats(globalXp + xp); @@ -156,21 +160,34 @@ namespace NadekoBot.Modules.Xp.Services toNotify.Add((first.Channel, first.User, newGuildLevelData.Level, usr.NotifyOnLevelUp, NotifOf.Server)); //give role - if (!roleRewards.TryGetValue(usr.GuildId, out var rewards)) + if (!roleRewards.TryGetValue(usr.GuildId, out var rrews)) { - rewards = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList(); - roleRewards.Add(usr.GuildId, rewards); + rrews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList(); + roleRewards.Add(usr.GuildId, rrews); } - var rew = rewards.FirstOrDefault(x => x.Level == newGuildLevelData.Level); - if (rew != null) + if (!curRewards.TryGetValue(usr.GuildId, out var crews)) { - var role = first.User.Guild.GetRole(rew.RoleId); + crews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).CurrencyRewards.ToList(); + curRewards.Add(usr.GuildId, crews); + } + + var rrew = rrews.FirstOrDefault(x => x.Level == newGuildLevelData.Level); + if (rrew != null) + { + var role = first.User.Guild.GetRole(rrew.RoleId); if (role != null) { var __ = first.User.AddRoleAsync(role); } } + //get currency reward for this level + var crew = crews.FirstOrDefault(x => x.Level == newGuildLevelData.Level); + if (crew != null) + { + //give the user the reward if it exists + await _cs.AddAsync(item.Key.User.Id, "Level-up Reward", crew.Amount, uow); + } } } @@ -429,7 +446,13 @@ namespace NadekoBot.Modules.Xp.Services private bool SetUserRewarded(ulong userId) { - return _rewardedUsers.Add(userId); + var r = _cache.Redis.GetDatabase(); + var key = $"{_creds.RedisKey()}_user_xp_gain_{userId}"; + + return r.StringSet(key, + true, + TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout), + StackExchange.Redis.When.NotExists); } public FullUserStats GetUserStats(IGuildUser user) diff --git a/NadekoBot.Core/Modules/Xp/Xp.cs b/NadekoBot.Core/Modules/Xp/Xp.cs index 0e2a7a6e..0493466c 100644 --- a/NadekoBot.Core/Modules/Xp/Xp.cs +++ b/NadekoBot.Core/Modules/Xp/Xp.cs @@ -17,11 +17,13 @@ namespace NadekoBot.Modules.Xp { private readonly DiscordSocketClient _client; private readonly DbService _db; + private readonly IBotConfigProvider _bc; - public Xp(DiscordSocketClient client,DbService db) + public Xp(DiscordSocketClient client,DbService db, IBotConfigProvider bc) { _client = client; _db = db; + _bc = bc; } [NadekoCommand, Usage, Description, Aliases] @@ -45,34 +47,39 @@ namespace NadekoBot.Modules.Xp [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public Task XpRoleRewards(int page = 1) + public Task XpLevelUpRewards(int page = 1) { page--; if (page < 0 || page > 100) return Task.CompletedTask; - var roles = _service.GetRoleRewards(Context.Guild.Id) - .OrderBy(x => x.Level) - .Skip(page * 9) - .Take(9); - var embed = new EmbedBuilder() .WithTitle(GetText("level_up_rewards")) .WithOkColor(); - if (!roles.Any()) - return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_role_rewards"))); + var rewards = _service.GetRoleRewards(Context.Guild.Id) + .OrderBy(x => x.Level) + .Select(x => + { + var str = Context.Guild.GetRole(x.RoleId)?.ToString(); + if (str != null) + str = GetText("role_reward", Format.Bold(str)); + return (x.Level, RoleStr: str); + }) + .Where(x => x.RoleStr != null) + .Concat(_service.GetCurrencyRewards(Context.Guild.Id) + .OrderBy(x => x.Level) + .Select(x => (x.Level, Format.Bold(x.Amount + _bc.BotConfig.CurrencySign)))) + .GroupBy(x => x.Level) + .OrderBy(x => x.Key) + .Skip(page * 9) + .Take(9) + .ForEach(x => embed.AddField(GetText("level_x", x.Key), string.Join("\n", x.Select(y => y.Item2)))); - foreach (var rolerew in roles) - { - var role = Context.Guild.GetRole(rolerew.RoleId); + if (!rewards.Any()) + return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_level_up_rewards"))); - if (role == null) - continue; - - embed.AddField(GetText("level_x", Format.Bold(rolerew.Level.ToString())), role.ToString()); - } return Context.Channel.EmbedAsync(embed); } @@ -104,7 +111,7 @@ namespace NadekoBot.Modules.Xp if (amount == 0) await ReplyConfirmLocalized("cur_reward_cleared", level).ConfigureAwait(false); else - await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount.ToString())).ConfigureAwait(false); + await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount + _bc.BotConfig.CurrencySign)).ConfigureAwait(false); } public enum NotifyPlace diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index aaefa2a4..ef002890 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -845,9 +845,10 @@ "xp_role_reward_added": "Users who reach level {0} will receive {1} role.", "xp_cur_reward_cleared": "Reaching level {0} will no longer reward any {1}.", "xp_cur_reward_added": "Users who reach level {0} will receive {1}.", - "xp_role_rewards": "Role Rewards", + "xp_level_up_rewards": "Level Up Rewards", "xp_level_x": "Level {0}", - "xp_no_role_rewards": "No role reward on this page.", + "xp_role_reward": "{0} role", + "xp_no_level_up_rewards": "No level up reward on this page.", "xp_server_leaderboard": "Server XP Leaderboard", "xp_global_leaderboard": "Global XP Leaderboard", "xp_modified": "Modified server XP of the user {0} by {1}", diff --git a/src/NadekoBot/_strings/cmd/command_strings.json b/src/NadekoBot/_strings/cmd/command_strings.json index c38b05b1..34eb5eb9 100644 --- a/src/NadekoBot/_strings/cmd/command_strings.json +++ b/src/NadekoBot/_strings/cmd/command_strings.json @@ -2815,11 +2815,11 @@ "{0}xpn server channel" ] }, - "xprolerewards": { - "Cmd": "xprolerewards xprrs", - "Desc": "Shows currently set role rewards.", + "xpleveluprewards": { + "Cmd": "xplvluprewards xprews xpcrs xprrs xprolerewards xpcurrewards", + "Desc": "Shows currently set level up rewards.", "Usage": [ - "{0}xprrs" + "{0}xprews" ] }, "xprolereward": { @@ -2829,6 +2829,13 @@ "{0}xprr 3 Social" ] }, + "xpcurrencyreward": { + "Cmd": "xpcurreward xpcr", + "Desc": "Sets a currency reward on a specified level. Provide no amount in order to remove the reward.", + "Usage": [ + "{0}xpcr 3 50" + ] + }, "xpleaderboard": { "Cmd": "xpleaderboard xplb", "Desc": "Shows current server's xp leaderboard.", From 62a2c7689f107cb3f292aea6f9d1bec72b681820 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 14:06:33 +0100 Subject: [PATCH 14/22] Fixed format error when removing currenc level up reward --- NadekoBot.Core/Modules/Xp/Xp.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Xp/Xp.cs b/NadekoBot.Core/Modules/Xp/Xp.cs index 0493466c..c7d4ad8e 100644 --- a/NadekoBot.Core/Modules/Xp/Xp.cs +++ b/NadekoBot.Core/Modules/Xp/Xp.cs @@ -109,7 +109,7 @@ namespace NadekoBot.Modules.Xp _service.SetCurrencyReward(Context.Guild.Id, level, amount); if (amount == 0) - await ReplyConfirmLocalized("cur_reward_cleared", level).ConfigureAwait(false); + await ReplyConfirmLocalized("cur_reward_cleared", level, _bc.BotConfig.CurrencySign).ConfigureAwait(false); else await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount + _bc.BotConfig.CurrencySign)).ConfigureAwait(false); } From 96b86e83b9f97090e76772c6e8fce122e779e5dd Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 14:27:38 +0100 Subject: [PATCH 15/22] .xpcr is owner only --- NadekoBot.Core/Modules/Xp/Xp.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NadekoBot.Core/Modules/Xp/Xp.cs b/NadekoBot.Core/Modules/Xp/Xp.cs index c7d4ad8e..886ae8c2 100644 --- a/NadekoBot.Core/Modules/Xp/Xp.cs +++ b/NadekoBot.Core/Modules/Xp/Xp.cs @@ -101,6 +101,7 @@ namespace NadekoBot.Modules.Xp [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] + [OwnerOnly] public async Task XpCurrencyReward(int level, int amount=0) { if (level < 1 || amount < 0) From 8c278fd1bd650b3583461e355afca30efaacf786 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 17:55:27 +0100 Subject: [PATCH 16/22] .logevents now shows where are you logging the event, if you are --- .../Modules/Administration/LogCommands.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Administration/LogCommands.cs b/NadekoBot.Core/Modules/Administration/LogCommands.cs index 26e311d8..b1fe07df 100644 --- a/NadekoBot.Core/Modules/Administration/LogCommands.cs +++ b/NadekoBot.Core/Modules/Administration/LogCommands.cs @@ -106,11 +106,60 @@ namespace NadekoBot.Modules.Administration [OwnerOnly] public async Task LogEvents() { + _service.GuildLogSettings.TryGetValue(Context.Guild.Id, out LogSetting l); + var str = string.Join("\n", Enum.GetNames(typeof(LogType)) + .Select(x => + { + var val = l == null ? null : GetLogProperty(l, Enum.Parse(x)); + if (val != null) + return $"{Format.Bold(x)} <#{val}>"; + return Format.Bold(x); + })); + await Context.Channel.SendConfirmAsync(Format.Bold(GetText("log_events")) + "\n" + - $"```fix\n{string.Join(", ", Enum.GetNames(typeof(LogType)).Cast())}```") + str) .ConfigureAwait(false); } + private ulong? GetLogProperty(LogSetting l, LogType type) + { + switch (type) + { + case LogType.Other: + return l.LogOtherId; + case LogType.MessageUpdated: + return l.MessageUpdatedId; + case LogType.MessageDeleted: + return l.MessageDeletedId; + case LogType.UserJoined: + return l.UserJoinedId; + case LogType.UserLeft: + return l.UserLeftId; + case LogType.UserBanned: + return l.UserBannedId; + case LogType.UserUnbanned: + return l.UserUnbannedId; + case LogType.UserUpdated: + return l.UserUpdatedId; + case LogType.ChannelCreated: + return l.ChannelCreatedId; + case LogType.ChannelDestroyed: + return l.ChannelDestroyedId; + case LogType.ChannelUpdated: + return l.ChannelUpdatedId; + case LogType.UserPresence: + return l.LogUserPresenceId; + case LogType.VoicePresence: + return l.LogVoicePresenceId; + case LogType.VoicePresenceTTS: + return l.LogVoicePresenceTTSId; + case LogType.UserMuted: + return l.UserMutedId; + default: + return null; + } + } + [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequireUserPermission(GuildPermission.Administrator)] From 2a411a00a6ca9279909d0a070fd91021a1e054ae Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 18:21:36 +0100 Subject: [PATCH 17/22] You can now specify 'allin' instead of the amount when playing .wheel, .br and .bf --- .../Modules/Gambling/FlipCoinCommands.cs | 19 +++++++++++--- NadekoBot.Core/Modules/Gambling/Gambling.cs | 25 +++++++++++++++---- .../Gambling/WheelOfFortuneCommands.cs | 21 +++++++++++++--- 3 files changed, 54 insertions(+), 11 deletions(-) diff --git a/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs b/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs index 1658022e..3bb6c01b 100644 --- a/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs @@ -20,14 +20,16 @@ namespace NadekoBot.Modules.Gambling private readonly IImageCache _images; private readonly IBotConfigProvider _bc; private readonly CurrencyService _cs; - + private readonly DbService _db; private static readonly NadekoRandom rng = new NadekoRandom(); - public FlipCoinCommands(IDataCache data, CurrencyService cs, IBotConfigProvider bc) + public FlipCoinCommands(IDataCache data, CurrencyService cs, + IBotConfigProvider bc, DbService db) { _images = data.LocalImages; _bc = bc; _cs = cs; + _db = db; } [NadekoCommand, Usage, Description, Aliases] @@ -86,7 +88,18 @@ namespace NadekoBot.Modules.Gambling } [NadekoCommand, Usage, Description, Aliases] - public async Task Betflip(int amount, BetFlipGuess guess) + public Task Betflip(Allin _, BetFlipGuess guess) + { + long cur; + using (var uow = _db.UnitOfWork) + { + cur = uow.Currency.GetUserCurrency(Context.User.Id); + } + return Betflip(cur, guess); + } + + [NadekoCommand, Usage, Description, Aliases] + public async Task Betflip(long amount, BetFlipGuess guess) { if (amount < _bc.BotConfig.MinimumBetAmount) { diff --git a/NadekoBot.Core/Modules/Gambling/Gambling.cs b/NadekoBot.Core/Modules/Gambling/Gambling.cs index 9defa74f..c6a05aa0 100644 --- a/NadekoBot.Core/Modules/Gambling/Gambling.cs +++ b/NadekoBot.Core/Modules/Gambling/Gambling.cs @@ -278,9 +278,9 @@ namespace NadekoBot.Modules.Gambling // }); // return Task.CompletedTask; //} + public enum Allin { Allin, All } - [NadekoCommand, Usage, Description, Aliases] - public async Task BetRoll(long amount) + private async Task InternallBetroll(long amount) { if (amount < 1) return; @@ -303,24 +303,39 @@ namespace NadekoBot.Modules.Gambling { str += GetText("br_win", (amount * _bc.BotConfig.Betroll67Multiplier) + CurrencySign, 66); await _cs.AddAsync(Context.User, "Betroll Gamble", - (int) (amount * _bc.BotConfig.Betroll67Multiplier), false).ConfigureAwait(false); + (int)(amount * _bc.BotConfig.Betroll67Multiplier), false).ConfigureAwait(false); } else if (rnd < 100) { str += GetText("br_win", (amount * _bc.BotConfig.Betroll91Multiplier) + CurrencySign, 90); await _cs.AddAsync(Context.User, "Betroll Gamble", - (int) (amount * _bc.BotConfig.Betroll91Multiplier), false).ConfigureAwait(false); + (int)(amount * _bc.BotConfig.Betroll91Multiplier), false).ConfigureAwait(false); } else { str += GetText("br_win", (amount * _bc.BotConfig.Betroll100Multiplier) + CurrencySign, 99) + " 👑"; await _cs.AddAsync(Context.User, "Betroll Gamble", - (int) (amount * _bc.BotConfig.Betroll100Multiplier), false).ConfigureAwait(false); + (int)(amount * _bc.BotConfig.Betroll100Multiplier), false).ConfigureAwait(false); } } await Context.Channel.SendConfirmAsync(str).ConfigureAwait(false); } + [NadekoCommand, Usage, Description, Aliases] + public Task BetRoll(long amount) + => InternallBetroll(amount); + + [NadekoCommand, Usage, Description, Aliases] + public Task BetRoll(Allin _) + { + long cur; + using (var uow = _db.UnitOfWork) + { + cur = uow.Currency.GetUserCurrency(Context.User.Id); + } + return InternallBetroll(cur); + } + [NadekoCommand, Usage, Description, Aliases] public async Task Leaderboard(int page = 1) { diff --git a/NadekoBot.Core/Modules/Gambling/WheelOfFortuneCommands.cs b/NadekoBot.Core/Modules/Gambling/WheelOfFortuneCommands.cs index ecbf4489..e8047008 100644 --- a/NadekoBot.Core/Modules/Gambling/WheelOfFortuneCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/WheelOfFortuneCommands.cs @@ -15,16 +15,31 @@ namespace NadekoBot.Modules.Gambling { private readonly CurrencyService _cs; private readonly IBotConfigProvider _bc; + private readonly DbService _db; - public WheelOfFortuneCommands(CurrencyService cs, IBotConfigProvider bc) + public WheelOfFortuneCommands(CurrencyService cs, IBotConfigProvider bc, + DbService db) { _cs = cs; _bc = bc; + _db = db; + } + + public enum Allin { Allin, All } + + [NadekoCommand, Usage, Description, Aliases] + public Task WheelOfFortune(Allin _) + { + long cur; + using (var uow = _db.UnitOfWork) + { + cur = uow.Currency.GetUserCurrency(Context.User.Id); + } + return WheelOfFortune(cur); } [NadekoCommand, Usage, Description, Aliases] - [RequireContext(ContextType.Guild)] - public async Task WheelOfFortune(int bet) + public async Task WheelOfFortune(long bet) { const int minBet = 10; if (bet < minBet) From dc3af0630b2d58b48a0328ff66bc199cc32f680e Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 20:07:01 +0100 Subject: [PATCH 18/22] removed duplicate string, close #1822 --- src/NadekoBot/_strings/ResponseStrings.en-US.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index ef002890..0e02a505 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -228,9 +228,6 @@ "gambling_flipped": "flipped {0}.", "gambling_flip_guess": "You guessed it! You won {0}", "gambling_flip_invalid": "Invalid number specified. You can flip 1 to {0} coins.", - "gambling_flowerreaction_desc": "Add {0} reaction to this message to get {1} ", - "gambling_flowerreaction_footer": "This event is active for up to {0} hours.", - "gambling_flowerreaction_title": "Flower reaction event started!", "gambling_gifted": "has gifted {0} to {1}", "gambling_has": "{0} has {1}", "gambling_heads": "Head", From 5d4fdea620219e86fd25987af50d260496f9045a Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 20:12:14 +0100 Subject: [PATCH 19/22] Disabling .cfi will now have immediate effect, instead of requiring a restart. closes #1791 --- NadekoBot.Core/Modules/Permissions/FilterCommands.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/NadekoBot.Core/Modules/Permissions/FilterCommands.cs b/NadekoBot.Core/Modules/Permissions/FilterCommands.cs index 7332c6ad..f241098b 100644 --- a/NadekoBot.Core/Modules/Permissions/FilterCommands.cs +++ b/NadekoBot.Core/Modules/Permissions/FilterCommands.cs @@ -89,6 +89,7 @@ namespace NadekoBot.Modules.Permissions } else { + _service.InviteFilteringChannels.TryRemove(channel.Id); await ReplyConfirmLocalized("invite_filter_channel_off").ConfigureAwait(false); } } From b6a1e9a420afe24aab14d2bba7f0b9856425d0f4 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 20:39:51 +0100 Subject: [PATCH 20/22] Dm help string now allows usage of embed strings --- NadekoBot.Core/Modules/Help/Help.cs | 1 - .../Modules/Help/Services/HelpService.cs | 20 ++++++++++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/NadekoBot.Core/Modules/Help/Help.cs b/NadekoBot.Core/Modules/Help/Help.cs index b07ea5be..c6c0dfe4 100644 --- a/NadekoBot.Core/Modules/Help/Help.cs +++ b/NadekoBot.Core/Modules/Help/Help.cs @@ -24,7 +24,6 @@ namespace NadekoBot.Modules.Help private readonly GlobalPermissionService _perms; public string HelpString => String.Format(_config.BotConfig.HelpString, _creds.ClientId, Prefix); - public string DMHelpString => _config.BotConfig.DMHelpString; public Help(IBotCredentials creds, GlobalPermissionService perms, IBotConfigProvider config, CommandService cmds) { diff --git a/NadekoBot.Core/Modules/Help/Services/HelpService.cs b/NadekoBot.Core/Modules/Help/Services/HelpService.cs index 2de4ccfb..23416b1a 100644 --- a/NadekoBot.Core/Modules/Help/Services/HelpService.cs +++ b/NadekoBot.Core/Modules/Help/Services/HelpService.cs @@ -9,6 +9,8 @@ using NadekoBot.Common.Attributes; using NadekoBot.Common.ModuleBehaviors; using NadekoBot.Core.Services; using NadekoBot.Core.Services.Impl; +using NadekoBot.Common; +using NLog; namespace NadekoBot.Modules.Help.Services { @@ -17,25 +19,33 @@ namespace NadekoBot.Modules.Help.Services private readonly IBotConfigProvider _bc; private readonly CommandHandler _ch; private readonly NadekoStrings _strings; + private readonly Logger _log; public HelpService(IBotConfigProvider bc, CommandHandler ch, NadekoStrings strings) { _bc = bc; _ch = ch; _strings = strings; + _log = LogManager.GetCurrentClassLogger(); } - public async Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg) + public Task LateExecute(DiscordSocketClient client, IGuild guild, IUserMessage msg) { try { - if(guild == null) - await msg.Channel.SendMessageAsync(_bc.BotConfig.DMHelpString).ConfigureAwait(false); + if (guild == null) + { + if (CREmbed.TryParse(_bc.BotConfig.DMHelpString, out var embed)) + return msg.Channel.EmbedAsync(embed.ToEmbed(), embed.PlainText?.SanitizeMentions() ?? ""); + + return msg.Channel.SendMessageAsync(_bc.BotConfig.DMHelpString); + } } - catch (Exception) + catch (Exception ex) { - //ignore + _log.Warn(ex); } + return Task.CompletedTask; } public EmbedBuilder GetCommandHelp(CommandInfo com, IGuild guild) From 366f6de9dd30d598c13ecf42d1dc061979cf93aa Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 20:52:34 +0100 Subject: [PATCH 21/22] You can now use embedbuilder in HelpString and DMHelpString --- NadekoBot.Core/Modules/Help/Help.cs | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/NadekoBot.Core/Modules/Help/Help.cs b/NadekoBot.Core/Modules/Help/Help.cs index c6c0dfe4..4f5efac3 100644 --- a/NadekoBot.Core/Modules/Help/Help.cs +++ b/NadekoBot.Core/Modules/Help/Help.cs @@ -11,6 +11,8 @@ using System.Collections.Generic; using NadekoBot.Common.Attributes; using NadekoBot.Modules.Help.Services; using NadekoBot.Modules.Permissions.Services; +using NadekoBot.Common; +using NadekoBot.Common.Replacements; namespace NadekoBot.Modules.Help { @@ -23,7 +25,23 @@ namespace NadekoBot.Modules.Help private readonly CommandService _cmds; private readonly GlobalPermissionService _perms; - public string HelpString => String.Format(_config.BotConfig.HelpString, _creds.ClientId, Prefix); + public EmbedBuilder GetHelpStringEmbed() + { + var r = new ReplacementBuilder() + .WithDefault(Context) + .WithOverride("{0}", () => _creds.ClientId.ToString()) + .WithOverride("{1}", () => Prefix) + .Build(); + + + if (!CREmbed.TryParse(_config.BotConfig.HelpString, out var embed)) + return new EmbedBuilder().WithOkColor() + .WithDescription(String.Format(_config.BotConfig.HelpString, _creds.ClientId, Prefix)); + + r.Replace(embed); + + return embed.ToEmbed(); + } public Help(IBotCredentials creds, GlobalPermissionService perms, IBotConfigProvider config, CommandService cmds) { @@ -93,16 +111,10 @@ namespace NadekoBot.Modules.Help if (com == null) { IMessageChannel ch = channel is ITextChannel ? await ((IGuildUser)Context.User).GetOrCreateDMChannelAsync() : channel; - await ch.SendMessageAsync(HelpString).ConfigureAwait(false); + await ch.EmbedAsync(GetHelpStringEmbed()).ConfigureAwait(false); return; } - //if (com == null) - //{ - // await ReplyErrorLocalized("command_not_found").ConfigureAwait(false); - // return; - //} - var embed = _service.GetCommandHelp(com, Context.Guild); await channel.EmbedAsync(embed).ConfigureAwait(false); } From 8738a693dbadda2e02500f6ea71f3233419fd62d Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 15 Nov 2017 20:55:02 +0100 Subject: [PATCH 22/22] Version upped --- NadekoBot.Core/Services/Impl/StatsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NadekoBot.Core/Services/Impl/StatsService.cs b/NadekoBot.Core/Services/Impl/StatsService.cs index 93269b62..ad5d5af9 100644 --- a/NadekoBot.Core/Services/Impl/StatsService.cs +++ b/NadekoBot.Core/Services/Impl/StatsService.cs @@ -21,7 +21,7 @@ namespace NadekoBot.Core.Services.Impl private readonly IBotCredentials _creds; private readonly DateTime _started; - public const string BotVersion = "2.5.0"; + public const string BotVersion = "2.5.1"; public string Author => "Kwoth#2560"; public string Library => "Discord.Net";