From 4c75c7e598919bb3431eacf79cc60af7eaddc7a5 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 13 Oct 2016 23:09:59 +0200 Subject: [PATCH 01/28] Fixed rotating status placeholders, permission mentioning --- NadekoBot.sln | 9 --------- .../Administration/Commands/PlayingRotateCommands.cs | 8 ++++++-- .../Modules/Permissions/PermissionExtensions.cs | 5 ++++- src/NadekoBot/_Extensions/Extensions.cs | 9 +++++++++ 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/NadekoBot.sln b/NadekoBot.sln index e844576d..7b8981b8 100644 --- a/NadekoBot.sln +++ b/NadekoBot.sln @@ -16,8 +16,6 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "discord.net\ EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "discord.net\src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "tests", "src\tests\tests.xproj", "{14CBADA0-971C-44E3-B331-C7D01DD74F0B}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,18 +41,11 @@ Global {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.GlobalNadeko|Any CPU.ActiveCfg = GlobalNadeko|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {14CBADA0-971C-44E3-B331-C7D01DD74F0B}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {45EC1473-C678-4857-A544-07DFE0D0B478} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} - {14CBADA0-971C-44E3-B331-C7D01DD74F0B} = {04929013-5BAB-42B0-B9B2-8F2BB8F16AF2} EndGlobalSection EndGlobal diff --git a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs index ab8721e8..5b6e2654 100644 --- a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs @@ -2,6 +2,7 @@ using Discord.Commands; using Discord.WebSocket; using NadekoBot.Attributes; +using NadekoBot.Extensions; using NadekoBot.Services; using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; @@ -47,10 +48,13 @@ namespace NadekoBot.Modules.Administration if (!conf.RotatingStatusMessages.Any()) continue; - + var status = conf.RotatingStatusMessages[index++].Status; + if (string.IsNullOrWhiteSpace(status)) + continue; + PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value())); await NadekoBot.Client .GetCurrentUser() - .ModifyStatusAsync(mpp => mpp.Game = new Game(conf.RotatingStatusMessages[index++].Status)) + .ModifyStatusAsync(mpp => mpp.Game = new Game(status)) .ConfigureAwait(false); } } diff --git a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs index 783e2b90..991f25cd 100644 --- a/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs +++ b/src/NadekoBot/Modules/Permissions/PermissionExtensions.cs @@ -136,7 +136,10 @@ namespace NadekoBot.Modules.Permissions com += $"<#{perm.PrimaryTargetId}>"; break; case PrimaryPermissionType.Role: - com += $"<@&{perm.PrimaryTargetId}>"; + if(guild == null) + com += $"<@&{perm.PrimaryTargetId}>"; + else + com += guild.GetRole(perm.PrimaryTargetId).ToString() ?? $"<@{perm.PrimaryTargetId}>"; break; case PrimaryPermissionType.Server: break; diff --git a/src/NadekoBot/_Extensions/Extensions.cs b/src/NadekoBot/_Extensions/Extensions.cs index 43283a64..6fe6b13c 100644 --- a/src/NadekoBot/_Extensions/Extensions.cs +++ b/src/NadekoBot/_Extensions/Extensions.cs @@ -24,6 +24,15 @@ namespace NadekoBot.Extensions http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); } + public static IEnumerable ForEach(this IEnumerable elems, Action exec) + { + foreach (var elem in elems) + { + exec(elem); + } + return elems; + } + public static void AddRange(this HashSet target, IEnumerable elements) where T : class { foreach (var item in elements) From ff663c4331ec0fb6eeb918363faad47757cab23e Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 00:59:02 +0200 Subject: [PATCH 02/28] Fixed .donadd description --- src/NadekoBot/Resources/CommandStrings.Designer.cs | 2 +- src/NadekoBot/Resources/CommandStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index aa85279f..d4e09b34 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -2067,7 +2067,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Add a donator to the database. **Kwoth Only**. + /// Looks up a localized string similar to Add a donator to the database.. /// public static string donadd_desc { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 3072d75f..1314fa26 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -796,7 +796,7 @@ donadd - Add a donator to the database. **Kwoth Only** + Add a donator to the database. `.donadd Donate Amount` From 889050b8ae576789243906827f7cc2a3e75aa37d Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 08:21:45 +0200 Subject: [PATCH 03/28] Fixed .setgame on sharded bots --- src/NadekoBot/Modules/Administration/Administration.cs | 4 ++-- .../Administration/Commands/PlayingRotateCommands.cs | 7 +++---- src/NadekoBot/Modules/CustomReactions/Extensions.cs | 2 +- src/NadekoBot/Services/Impl/BotCredentials.cs | 4 ++-- src/NadekoBot/Services/Impl/StatsService.cs | 2 +- src/NadekoBot/ShardedDiscordClient.cs | 9 ++++++--- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index de1c466f..eaeb163a 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -531,7 +531,7 @@ namespace NadekoBot.Modules.Administration if (string.IsNullOrWhiteSpace(newName)) return; - await NadekoBot.Client.GetCurrentUser().ModifyAsync(u => u.Username = newName).ConfigureAwait(false); + await (await NadekoBot.Client.GetCurrentUserAsync()).ModifyAsync(u => u.Username = newName).ConfigureAwait(false); await channel.SendMessageAsync($"Successfully changed name to {newName}").ConfigureAwait(false); } @@ -554,7 +554,7 @@ namespace NadekoBot.Modules.Administration await sr.CopyToAsync(imgStream); imgStream.Position = 0; - await NadekoBot.Client.GetCurrentUser().ModifyAsync(u => u.Avatar = imgStream).ConfigureAwait(false); + await (await NadekoBot.Client.GetCurrentUserAsync().ConfigureAwait(false)).ModifyAsync(u => u.Avatar = imgStream).ConfigureAwait(false); } } diff --git a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs index 5b6e2654..68007791 100644 --- a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs @@ -52,10 +52,9 @@ namespace NadekoBot.Modules.Administration if (string.IsNullOrWhiteSpace(status)) continue; PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value())); - await NadekoBot.Client - .GetCurrentUser() - .ModifyStatusAsync(mpp => mpp.Game = new Game(status)) - .ConfigureAwait(false); + await (await NadekoBot.Client.GetCurrentUserAsync()) + .ModifyStatusAsync(mpp => mpp.Game = new Game(status)) + .ConfigureAwait(false); } } catch (Exception ex) diff --git a/src/NadekoBot/Modules/CustomReactions/Extensions.cs b/src/NadekoBot/Modules/CustomReactions/Extensions.cs index 147d6dcf..b2bb133f 100644 --- a/src/NadekoBot/Modules/CustomReactions/Extensions.cs +++ b/src/NadekoBot/Modules/CustomReactions/Extensions.cs @@ -14,7 +14,7 @@ namespace NadekoBot.Modules.CustomReactions { public static Dictionary> placeholders = new Dictionary>() { - {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } }, + {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUserAsync().Id}>"; } }, {"%user%", (ctx) => { return ctx.Author.Mention; } }, {"%target%", (ctx) => { return ctx.MentionedUsers.Shuffle().FirstOrDefault()?.Mention ?? "Nobody"; } }, {"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } } diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index 9343efd9..6632857f 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -62,8 +62,8 @@ namespace NadekoBot.Services.Impl { public ulong ClientId { get; set; } public ulong? BotId { get; set; } - public string Token { get; set; } - public ulong[] OwnerIds { get; set; } + public string Token { get; set; } = ""; + public ulong[] OwnerIds { get; set; } = new ulong[1]; public string LoLApiKey { get; set; } public string GoogleApiKey { get; set; } public string MashapeKey { get; set; } diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index a2ec5b65..6523b3cf 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -35,7 +35,7 @@ namespace NadekoBot.Services.Impl } public Task Print() { - var curUser = client.GetCurrentUser(); + var curUser = client.GetCurrentUserAsync(); return Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net` `Bot Version: {BotVersion}` `Bot id: {curUser.Id}` diff --git a/src/NadekoBot/ShardedDiscordClient.cs b/src/NadekoBot/ShardedDiscordClient.cs index 30bc3139..b119df42 100644 --- a/src/NadekoBot/ShardedDiscordClient.cs +++ b/src/NadekoBot/ShardedDiscordClient.cs @@ -64,8 +64,11 @@ namespace NadekoBot Clients = clientList.AsReadOnly(); } - public ISelfUser GetCurrentUser() => - Clients.Select(c => c.GetCurrentUser()).FirstOrDefault(u => u != null); + public ISelfUser GetCurrentUser() => + Clients[0].GetCurrentUser(); + + public Task GetCurrentUserAsync() => + Clients[0].GetCurrentUserAsync(); public IReadOnlyCollection GetGuilds() => Clients.SelectMany(c => c.GetGuilds()).ToArray(); @@ -74,7 +77,7 @@ namespace NadekoBot Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null); public Task GetDMChannelAsync(ulong channelId) => - Clients.Select(async c => await c.GetDMChannelAsync(channelId).ConfigureAwait(false)).FirstOrDefault(c => c != null); + Clients[0].GetDMChannelAsync(channelId); internal Task LoginAsync(TokenType tokenType, string token) => Task.WhenAll(Clients.Select(async c => { await c.LoginAsync(tokenType, token); _log.Info($"Shard #{c.ShardId} logged in."); })); From 10b3aa9ad3052284a144ac7b174151448a30da54 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 10:50:04 +0200 Subject: [PATCH 04/28] Fixed some plural currency forms, added .scr, .lcr now shows only triggers --- .../CustomReactions/CustomReactions.cs | 24 ++++++++++++++++++- src/NadekoBot/Modules/Gambling/Gambling.cs | 12 +++++----- .../Resources/CommandStrings.Designer.cs | 4 ++-- src/NadekoBot/Resources/CommandStrings.resx | 4 ++-- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index a8c71001..e5ace4d2 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -124,10 +124,32 @@ namespace NadekoBot.Modules.CustomReactions if (customReactions == null || !customReactions.Any()) await imsg.Channel.SendMessageAsync("`No custom reactions found`").ConfigureAwait(false); else - await imsg.Channel.SendMessageAsync(string.Join("\n", customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 10).Take(10))) + await imsg.Channel.SendMessageAsync($"`Page {page} of custom reactions:`\n" + string.Join("\n", customReactions.OrderBy(cr => cr.Trigger).Skip((page - 1) * 15).Take(15).Select(cr => $"`#{cr.Id}` `Trigger:` {cr.Trigger}"))) .ConfigureAwait(false); } + [NadekoCommand, Usage, Description, Aliases] + public async Task ShowCustReact(IUserMessage imsg, int id) + { + var channel = imsg.Channel as ITextChannel; + + ConcurrentHashSet customReactions; + if (channel == null) + customReactions = GlobalReactions; + else + customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()); + + var found = customReactions.FirstOrDefault(cr => cr.Id == id); + + if (found == null) + await imsg.Channel.SendMessageAsync("`No custom reaction found with that id.`").ConfigureAwait(false); + else + { + await imsg.Channel.SendMessageAsync($"`Custom reaction #{id}`\n`Trigger:` {found.Trigger}\n`Response:` {found.Response}") + .ConfigureAwait(false); + } + } + [NadekoCommand, Usage, Description, Aliases] public async Task DelCustReact(IUserMessage imsg, int id) { diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 6335295f..41cb7d77 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -96,7 +96,7 @@ namespace NadekoBot.Modules.Gambling return; } await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {umsg.Author.Username} ({umsg.Author.Id}).", amount, true).ConfigureAwait(false); - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {Gambling.CurrencyPluralName}s to {receiver.Mention}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -117,7 +117,7 @@ namespace NadekoBot.Modules.Gambling await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", (int)amount).ConfigureAwait(false); - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {Gambling.CurrencyName}s to <@{usrId}>!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -130,9 +130,9 @@ namespace NadekoBot.Modules.Gambling return; if(await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount, true).ConfigureAwait(false)) - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyPluralName} from {user}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false); else - await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {Gambling.CurrencyPluralName} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); } @@ -146,9 +146,9 @@ namespace NadekoBot.Modules.Gambling return; if(await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false)) - await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {Gambling.CurrencyName}s from <@{usrId}>!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false); else - await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {Gambling.CurrencyPluralName} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); + await channel.SendMessageAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index d4e09b34..7e72bcb8 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -6171,7 +6171,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Shows all possible responses from a single custom reaction.. + /// Looks up a localized string similar to Shows a custom reaction's response on a given ID.. /// public static string showcustreact_desc { get { @@ -6180,7 +6180,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `.scr %mention% bb`. + /// Looks up a localized string similar to `.scr 1`. /// public static string showcustreact_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 1314fa26..2e58df86 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -454,10 +454,10 @@ showcustreact scr - Shows all possible responses from a single custom reaction. + Shows a custom reaction's response on a given ID. - `.scr %mention% bb` + `.scr 1` editcustreact ecr From 0e627ba9e3c8c39220950e019d4e15b79e367356 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 12:34:56 +0200 Subject: [PATCH 05/28] Fixed prefixes in commandlist --- docs/Commands List.md | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/docs/Commands List.md b/docs/Commands List.md index 70dd28a0..609ca5ed 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -34,7 +34,7 @@ Command and aliases | Description | Usage `.savechat` | Saves a number of messages to a text file and sends it to you. | `.savechat 150` **Bot owner only.** `.mentionrole` `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission. | `.menro RoleName` **Requires MentionEveryone server permission.** `.donators` | List of lovely people who donated to keep this project alive. | `.donators` -`.donadd` | Add a donator to the database. **Kwoth Only** | `.donadd Donate Amount` **Bot owner only.** +`.donadd` | Add a donator to the database. | `.donadd Donate Amount` **Bot owner only.** `.autoassignrole` `.aar` | Automaticaly assigns a specified role to every user who joins the server. | `.aar` to disable, `.aar Role Name` to enable **Requires ManageRoles server permission.** `.scsc` | Starts an instance of cross server channel. You will get a token as a DM that other people will use to tune in to the same instance. | `.scsc` **Bot owner only.** `.jcsc` | Joins current channel to an instance of cross server channel using the token. | `.jcsc TokenHere` **Requires ManageServer server permission.** @@ -87,29 +87,30 @@ Command and aliases | Description | Usage ### CustomReactions Command and aliases | Description | Usage ----------------|--------------|------- -`#addcustreact` `#acr` | Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: | `.acr "hello" Hi there %user%` -`#listcustreact` `#lcr` | Lists global or server custom reactions (15 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcr 1` -`#delcustreact` `#dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction. | `.dcr 5` +`.addcustreact` `.acr` | Add a custom reaction with a trigger and a response. Running this command in server requires Administration permission. Running this command in DM is Bot Owner only and adds a new global custom reaction. Guide here: | `.acr "hello" Hi there %user%` +`.listcustreact` `.lcr` | Lists global or server custom reactions (15 commands per page). Running the command in DM will list global custom reactions, while running it in server will list that server's custom reactions. | `.lcr 1` +`.showcustreact` `.scr` | Shows a custom reaction's response on a given ID. | `.scr 1` +`.delcustreact` `.dcr` | Deletes a custom reaction on a specific index. If ran in DM, it is bot owner only and deletes a global custom reaction. If ran in a server, it requires Administration priviledges and removes server custom reaction. | `.dcr 5` ### Gambling Command and aliases | Description | Usage ----------------|--------------|------- -`xraffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` -`xcash` `x$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy` -`xgive` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"` -`xaward` | Awards someone a certain amount of currency. | `$award 100 @person` **Bot owner only.** -`xtake` | Takes a certain amount of flowers from someone. | `$take 1 "@someguy"` **Bot owner only.** -`xbetroll` `xbr` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `$br 5` -`xleaderboard` `xlb` | Displays bot currency leaderboard. | `$lb` -`xrace` | Starts a new animal race. | `$race` -`xjoinrace` `xjr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5` -`xroll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5` -`xrolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5` -`xnroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15` -`xdraw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5` -`xshuffle` `xsh` | Reshuffles all cards back into the deck. | `$sh` -`xflip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3` -`xbetflip` `xbf` | Bet to guess will the result be heads or tails. Guessing awards you double flowers you've bet. | `$bf 5 heads` or `$bf 3 t` +`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName` +`$cash` `$$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @SomeGuy` +`$give` | Give someone a certain amount of currency. | `$give 1 "@SomeGuy"` +`$award` | Awards someone a certain amount of currency. | `$award 100 @person` **Bot owner only.** +`$take` | Takes a certain amount of flowers from someone. | `$take 1 "@someguy"` **Bot owner only.** +`$betroll` `$br` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | `$br 5` +`$leaderboard` `$lb` | Displays bot currency leaderboard. | `$lb` +`$race` | Starts a new animal race. | `$race` +`$joinrace` `$jr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5` +`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$roll` or `$roll 7` or `$roll 3d5` +`$rolluo` | Rolls X normal dice (up to 30) unordered. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `$rolluo` or `$rolluo 7` or `$rolluo 3d5` +`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15` +`$draw` | Draws a card from the deck.If you supply number X, she draws up to 5 cards from the deck. | `$draw` or `$draw 5` +`$shuffle` `$sh` | Reshuffles all cards back into the deck. | `$sh` +`$flip` | Flips coin(s) - heads or tails, and shows an image. | `$flip` or `$flip 3` +`$betflip` `$bf` | Bet to guess will the result be heads or tails. Guessing awards you double flowers you've bet. | `$bf 5 heads` or `$bf 3 t` ### Games Command and aliases | Description | Usage From 2e046b9fe92354aac5284425fc5aa640986eb913 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 19:44:19 +0200 Subject: [PATCH 06/28] fixed pokeab usage --- src/NadekoBot/Resources/CommandStrings.Designer.cs | 2 +- src/NadekoBot/Resources/CommandStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 7e72bcb8..73f71499 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -4641,7 +4641,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `~pokeab "water gun"`. + /// Looks up a localized string similar to `~pokeab overgrow`. /// public static string pokemonability_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 2e58df86..42cce386 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -1996,7 +1996,7 @@ Searches for a pokemon ability. - `~pokeab "water gun"` + `~pokeab overgrow` memelist From c46fd50c12da844266898818b566e5453060ea50 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 21:54:26 +0200 Subject: [PATCH 07/28] Fixed custom reactions self-trigger, fixed bot credentials example --- .../Modules/CustomReactions/CustomReactions.cs | 2 +- src/NadekoBot/Services/Impl/BotCredentials.cs | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index e5ace4d2..60f342b0 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -33,7 +33,7 @@ namespace NadekoBot.Modules.CustomReactions client.MessageReceived += (imsg) => { var umsg = imsg as IUserMessage; - if (umsg == null) + if (umsg == null || imsg.Author.IsBot) return Task.CompletedTask; var channel = umsg.Channel as ITextChannel; diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index 6632857f..52af1934 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -33,6 +33,8 @@ namespace NadekoBot.Services.Impl public BotCredentials() { _log = LogManager.GetCurrentClassLogger(); + + try { File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); } catch { } if (File.Exists("./credentials.json")) { var cm = JsonConvert.DeserializeObject(File.ReadAllText("./credentials.json")); @@ -52,23 +54,23 @@ namespace NadekoBot.Services.Impl } else { - File.WriteAllText("./credentials_example.json", JsonConvert.SerializeObject(new CredentialsModel(), Formatting.Indented)); - _log.Fatal($"credentials.json is missing. Failed to start. Example written to {Path.GetFullPath("./credentials_example.json")}"); + _log.Fatal($"credentials.json is missing. Failed to start. Example is in {Path.GetFullPath("./credentials_example.json")}"); throw new FileNotFoundException(); } + } private class CredentialsModel { - public ulong ClientId { get; set; } + public ulong ClientId { get; set; } = 123123123; public ulong? BotId { get; set; } public string Token { get; set; } = ""; public ulong[] OwnerIds { get; set; } = new ulong[1]; - public string LoLApiKey { get; set; } - public string GoogleApiKey { get; set; } - public string MashapeKey { get; set; } - public string OsuApiKey { get; set; } - public string SoundCloudClientId { get; set; } + public string LoLApiKey { get; set; } = ""; + public string GoogleApiKey { get; set; } = ""; + public string MashapeKey { get; set; } = ""; + public string OsuApiKey { get; set; } = ""; + public string SoundCloudClientId { get; set; } = ""; public DB Db { get; set; } public int TotalShards { get; set; } = 1; } From dacfc1f8eacb98933e96c5625c7d05ee9d115943 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Fri, 14 Oct 2016 23:18:07 +0200 Subject: [PATCH 08/28] Fixed crash --- .../Utility/Commands/UnitConversion.cs | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs index 0f86bcbc..d4f9df0c 100644 --- a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs +++ b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs @@ -66,35 +66,40 @@ namespace NadekoBot.Modules.Utility } public async Task UpdateCurrency() - { - var currencyRates = await UpdateCurrencyRates(); - var unitTypeString = "currency"; - var range = currencyRates.ConversionRates.Select(u => new ConvertUnit() + {try { - InternalTrigger = u.Key, - Modifier = u.Value, - UnitType = unitTypeString - }).ToArray(); - var baseType = new ConvertUnit() - { - Triggers = new[] { currencyRates.Base }, - Modifier = decimal.One, - UnitType = unitTypeString - }; - var toRemove = Units.Where(u => u.UnitType == unitTypeString); + var currencyRates = await UpdateCurrencyRates(); + var unitTypeString = "currency"; + var range = currencyRates.ConversionRates.Select(u => new ConvertUnit() + { + InternalTrigger = u.Key, + Modifier = u.Value, + UnitType = unitTypeString + }).ToArray(); + var baseType = new ConvertUnit() + { + Triggers = new[] { currencyRates.Base }, + Modifier = decimal.One, + UnitType = unitTypeString + }; + var toRemove = Units.Where(u => u.UnitType == unitTypeString); - using (var uow = DbHandler.UnitOfWork()) - { - uow.ConverterUnits.RemoveRange(toRemove.ToArray()); - uow.ConverterUnits.Add(baseType); - uow.ConverterUnits.AddRange(range); + using (var uow = DbHandler.UnitOfWork()) + { + uow.ConverterUnits.RemoveRange(toRemove.ToArray()); + uow.ConverterUnits.Add(baseType); + uow.ConverterUnits.AddRange(range); - await uow.CompleteAsync().ConfigureAwait(false); + await uow.CompleteAsync().ConfigureAwait(false); + } + Units.RemoveAll(u => u.UnitType == unitTypeString); + Units.Add(baseType); + Units.AddRange(range); + _log.Info("Updated Currency"); + } + catch { + _log.Warn("Failed updating currency."); } - Units.RemoveAll(u => u.UnitType == unitTypeString); - Units.Add(baseType); - Units.AddRange(range); - _log.Info("Updated Currency"); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] From 9cc0af1666ff69b09f466cf7716be9f88f1e878c Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 00:03:52 +0200 Subject: [PATCH 09/28] Fixed botid, %mention% in custom reactions --- .../Modules/CustomReactions/Extensions.cs | 2 +- .../Modules/Permissions/Permissions.cs | 148 ++++++++++++++++-- src/NadekoBot/Services/CommandHandler.cs | 60 +++---- .../Repositories/IGuildConfigRepository.cs | 3 +- .../Impl/GuildConfigRepository.cs | 19 ++- src/NadekoBot/Services/Impl/StatsService.cs | 8 +- src/NadekoBot/credentials_example.json | 15 ++ 7 files changed, 206 insertions(+), 49 deletions(-) create mode 100644 src/NadekoBot/credentials_example.json diff --git a/src/NadekoBot/Modules/CustomReactions/Extensions.cs b/src/NadekoBot/Modules/CustomReactions/Extensions.cs index b2bb133f..147d6dcf 100644 --- a/src/NadekoBot/Modules/CustomReactions/Extensions.cs +++ b/src/NadekoBot/Modules/CustomReactions/Extensions.cs @@ -14,7 +14,7 @@ namespace NadekoBot.Modules.CustomReactions { public static Dictionary> placeholders = new Dictionary>() { - {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUserAsync().Id}>"; } }, + {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } }, {"%user%", (ctx) => { return ctx.Author.Mention; } }, {"%target%", (ctx) => { return ctx.MentionedUsers.Shuffle().FirstOrDefault()?.Mention ?? "Nobody"; } }, {"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } } diff --git a/src/NadekoBot/Modules/Permissions/Permissions.cs b/src/NadekoBot/Modules/Permissions/Permissions.cs index d8e2d167..1ebb4433 100644 --- a/src/NadekoBot/Modules/Permissions/Permissions.cs +++ b/src/NadekoBot/Modules/Permissions/Permissions.cs @@ -11,12 +11,39 @@ using Discord; using NadekoBot.Services.Database; using NadekoBot.Services.Database.Models; using Discord.API; +using System.Collections.Concurrent; namespace NadekoBot.Modules.Permissions { [NadekoModule("Permissions", ";")] public partial class Permissions : DiscordModule { + public class PermissionCache + { + public string PermRole { get; set; } + public bool Verbose { get; set; } = true; + public Permission RootPermission { get; set; } + } + + //guildid, root permission + public static ConcurrentDictionary Cache; + + static Permissions() + { + using (var uow = DbHandler.UnitOfWork()) + { + Cache = new ConcurrentDictionary(uow.GuildConfigs + .PermissionsForAll() + .ToDictionary(k => k.GuildId, + v => new PermissionCache() + { + RootPermission = v.RootPermission, + Verbose = v.VerbosePermissions, + PermRole = v.PermissionRole + })); + } + } + public Permissions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) { } @@ -31,6 +58,12 @@ namespace NadekoBot.Modules.Permissions { var config = uow.GuildConfigs.For(channel.Guild.Id); config.VerbosePermissions = action.Value; + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = Permission.GetDefaultRoot(), + Verbose = config.VerbosePermissions + }, (id, old) => { old.Verbose = config.VerbosePermissions; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -52,6 +85,12 @@ namespace NadekoBot.Modules.Permissions } else { config.PermissionRole = role.Name.Trim(); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = Permission.GetDefaultRoot(), + Verbose = config.VerbosePermissions + }, (id, old) => { old.PermRole = role.Name.Trim(); return old; }); await uow.CompleteAsync().ConfigureAwait(false); } } @@ -107,6 +146,12 @@ namespace NadekoBot.Modules.Permissions { p = perms.RemoveAt(index); } + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -216,6 +261,12 @@ namespace NadekoBot.Modules.Permissions } config.RootPermission = fromPerm.GetRoot(); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"`Moved permission:` \"{fromPerm.GetCommand(channel.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false); @@ -244,7 +295,14 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); + await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command on this server.").ConfigureAwait(false); @@ -266,7 +324,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module on this server.").ConfigureAwait(false); @@ -288,7 +352,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command for `{user}` user.").ConfigureAwait(false); @@ -310,7 +380,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false); @@ -332,7 +408,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{command.Text}` command for `{role}` role.").ConfigureAwait(false); @@ -354,7 +436,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false); @@ -377,7 +465,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = command.Text.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } } @@ -403,7 +497,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = module.Name.ToLowerInvariant(), State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false); @@ -425,7 +525,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false); @@ -447,7 +553,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false); @@ -469,7 +581,13 @@ namespace NadekoBot.Modules.Permissions SecondaryTargetName = "*", State = action.Value, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false); @@ -502,7 +620,13 @@ namespace NadekoBot.Modules.Permissions State = true, }; - uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, allowUser); + var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, allowUser); + Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() + { + PermRole = config.PermissionRole, + RootPermission = config.RootPermission, + Verbose = config.VerbosePermissions + }, (id, old) => { old.RootPermission = config.RootPermission; return old; }); await uow.CompleteAsync().ConfigureAwait(false); } await channel.SendMessageAsync($"{(action.Value ? "Allowed" : "Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false); diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index 21bce20e..628e883a 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -129,7 +129,7 @@ namespace NadekoBot.Services { var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrMsg.Author, MultiMatchHandling.Best); var command = t.Item1; - var verbose = t.Item2; + var permCache = t.Item2; var result = t.Item3; sw.Stop(); var channel = (usrMsg.Channel as ITextChannel); @@ -165,7 +165,7 @@ namespace NadekoBot.Services ); if (guild != null && command != null && result.Error == CommandError.Exception) { - if (verbose) + if (permCache != null && permCache.Verbose) try { await msg.Channel.SendMessageAsync(":warning: " + result.ErrorReason).ConfigureAwait(false); } catch { } } } @@ -189,10 +189,10 @@ namespace NadekoBot.Services return; } - public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { + public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { var searchResult = _commandService.Search(message, input); if (!searchResult.IsSuccess) - return new Tuple(null, false, searchResult); + return new Tuple(null, null, searchResult); var commands = searchResult.Commands; for (int i = commands.Count - 1; i >= 0; i--) @@ -201,7 +201,7 @@ namespace NadekoBot.Services if (!preconditionResult.IsSuccess) { if (commands.Count == 1) - return new Tuple(null, false, searchResult); + return new Tuple(null, null, searchResult); else continue; } @@ -225,55 +225,55 @@ namespace NadekoBot.Services if (!parseResult.IsSuccess) { if (commands.Count == 1) - return new Tuple(null, false, parseResult); + return new Tuple(null, null, parseResult); else continue; } } - bool verbose = false; - Permission rootPerm = null; - string permRole = ""; - if (guild != null) - { - using (var uow = DbHandler.UnitOfWork()) - { - var config = uow.GuildConfigs.PermissionsFor(guild.Id); - verbose = config.VerbosePermissions; - rootPerm = config.RootPermission; - permRole = config.PermissionRole.Trim().ToLowerInvariant(); - } - } - _log.Info("Permissions retrieved"); + var cmd = commands[i]; bool resetCommand = cmd.Name == "ResetPermissions"; - //check permissions + PermissionCache pc; if (guild != null) { - int index; - if (!resetCommand && !rootPerm.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index)) + pc = Permissions.Cache.GetOrAdd(guild.Id, (id) => { - var returnMsg = $"Permission number #{index + 1} **{rootPerm.GetAt(index).GetCommand()}** is preventing this action."; - return new Tuple(cmd, verbose, SearchResult.FromError(CommandError.Exception, returnMsg)); + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.GuildConfigs.PermissionsFor(guild.Id); + return new PermissionCache() + { + Verbose = config.VerbosePermissions, + RootPermission = config.RootPermission, + PermRole = config.PermissionRole.Trim().ToLowerInvariant(), + }; + } + }); + int index; + if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index)) + { + var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand()}** is preventing this action."; + return new Tuple(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); } if (cmd.Module.Source.Name == typeof(Permissions).Name) //permissions, you must have special role { - if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == permRole)) + if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant())) { - return new Tuple(cmd, false, SearchResult.FromError(CommandError.Exception, $"You need the **{permRole}** role in order to use permission commands.")); + return new Tuple(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands.")); } } } if (CmdCdsCommands.HasCooldown(cmd, guild, user)) - return new Tuple(cmd, false, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you.")); + return new Tuple(cmd, null, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you.")); - return new Tuple(commands[i], false, await commands[i].Execute(message, parseResult)); + return new Tuple(commands[i], null, await commands[i].Execute(message, parseResult)); } - return new Tuple(null, false, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.")); + return new Tuple(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.")); } } diff --git a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs index e6797de1..7a780380 100644 --- a/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/IGuildConfigRepository.cs @@ -12,7 +12,8 @@ namespace NadekoBot.Services.Database.Repositories { GuildConfig For(ulong guildId); GuildConfig PermissionsFor(ulong guildId); - void SetNewRootPermission(ulong guildId, Permission p); + IEnumerable PermissionsForAll(); + GuildConfig SetNewRootPermission(ulong guildId, Permission p); IEnumerable GetAllFollowedStreams(); } } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs index 0e9151bb..1b3c1501 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/GuildConfigRepository.cs @@ -90,12 +90,28 @@ namespace NadekoBot.Services.Database.Repositories.Impl return config; } + public IEnumerable PermissionsForAll() + { + var query = _set.Include(gc => gc.RootPermission); + + //todo this is possibly a disaster for performance + //What i could do instead is count the number of permissions in the permission table for this guild + // and make a for loop with those. + // or just select permissions for this guild and manually chain them + for (int i = 0; i < 60; i++) + { + query = query.ThenInclude(gc => gc.Next); + } + + return query.ToList(); + } + public IEnumerable GetAllFollowedStreams() => _set.Include(gc => gc.FollowedStreams) .SelectMany(gc => gc.FollowedStreams) .ToList(); - public void SetNewRootPermission(ulong guildId, Permission p) + public GuildConfig SetNewRootPermission(ulong guildId, Permission p) { var data = _set .Include(gc => gc.RootPermission) @@ -103,6 +119,7 @@ namespace NadekoBot.Services.Database.Repositories.Impl data.RootPermission.Prepend(p); data.RootPermission = p; + return data; } } } diff --git a/src/NadekoBot/Services/Impl/StatsService.cs b/src/NadekoBot/Services/Impl/StatsService.cs index 6523b3cf..1c84cf63 100644 --- a/src/NadekoBot/Services/Impl/StatsService.cs +++ b/src/NadekoBot/Services/Impl/StatsService.cs @@ -33,17 +33,17 @@ namespace NadekoBot.Services.Impl this.client.Disconnected += _ => Reset(); } - public Task Print() + public async Task Print() { - var curUser = client.GetCurrentUserAsync(); - return Task.FromResult($@"`Author: Kwoth` `Library: Discord.Net` + var curUser = await client.GetCurrentUserAsync(); + return $@"`Author: Kwoth` `Library: Discord.Net` `Bot Version: {BotVersion}` `Bot id: {curUser.Id}` `Owners' Ids: {string.Join(", ", NadekoBot.Credentials.OwnerIds)}` `Uptime: {GetUptimeString()}` `Servers: {client.GetGuilds().Count} | TextChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count()} | VoiceChannels: {client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count()}` `Commands Ran this session: {commandsRan}` -`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`"); +`Messages: {messageCounter} ({messageCounter / (double)GetUptime().TotalSeconds:F2}/sec)` `Heap: {Heap} MB`"; } public Task Reset() diff --git a/src/NadekoBot/credentials_example.json b/src/NadekoBot/credentials_example.json new file mode 100644 index 00000000..31a9414f --- /dev/null +++ b/src/NadekoBot/credentials_example.json @@ -0,0 +1,15 @@ +{ + "ClientId": 123123123, + "BotId": null, + "Token": "", + "OwnerIds": [ + 0 + ], + "LoLApiKey": "", + "GoogleApiKey": "", + "MashapeKey": "", + "OsuApiKey": "", + "SoundCloudClientId": "", + "Db": null, + "TotalShards": 1 +} \ No newline at end of file From fd56e14fd3032908b8ceb6aba93a2998b5ed0da6 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 00:56:29 +0200 Subject: [PATCH 10/28] Fixed merged global custom reactions --- src/NadekoBot/Modules/CustomReactions/CustomReactions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index 60f342b0..c26e2a2b 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -24,8 +24,8 @@ namespace NadekoBot.Modules.CustomReactions using (var uow = DbHandler.UnitOfWork()) { var items = uow.CustomReactions.GetAll(); - GuildReactions = new ConcurrentDictionary>(items.Where(g => g.GuildId != null).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet(g))); - GlobalReactions = new ConcurrentHashSet(items.Where(g => g.GuildId == null)); + GuildReactions = new ConcurrentDictionary>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet(g))); + GlobalReactions = new ConcurrentHashSet(items.Where(g => g.GuildId == null || g.GuildId == 0)); } } public CustomReactions(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) From 4001cf2e41b0b600a27d436b81eb8d562490b09c Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 01:20:06 +0200 Subject: [PATCH 11/28] Fixed some stuff in rotating statuses, more optimal too --- .../Commands/PlayingRotateCommands.cs | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs index 68007791..bf6030bb 100644 --- a/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/PlayingRotateCommands.cs @@ -22,6 +22,18 @@ namespace NadekoBot.Modules.Administration public class PlayingRotateCommands { private Logger _log { get; } + public static List RotatingStatusMessages { get; } + public static bool RotatingStatuses { get; private set; } = false; + + static PlayingRotateCommands() + { + using (var uow = DbHandler.UnitOfWork()) + { + var conf = uow.BotConfig.GetOrCreate(); + RotatingStatusMessages = conf.RotatingStatusMessages; + RotatingStatuses = conf.RotatingStatuses; + } + } public PlayingRotateCommands() { @@ -33,22 +45,16 @@ namespace NadekoBot.Modules.Administration { try { - BotConfig conf; - using (var uow = DbHandler.UnitOfWork()) - { - conf = uow.BotConfig.GetOrCreate(); - } - - if (!conf.RotatingStatuses) + if (!RotatingStatuses) continue; else { - if (index >= conf.RotatingStatusMessages.Count) + if (index >= RotatingStatusMessages.Count) index = 0; - if (!conf.RotatingStatusMessages.Any()) + if (!RotatingStatusMessages.Any()) continue; - var status = conf.RotatingStatusMessages[index++].Status; + var status = RotatingStatusMessages[index++].Status; if (string.IsNullOrWhiteSpace(status)) continue; PlayingPlaceholders.ForEach(e => status = status.Replace(e.Key, e.Value())); @@ -94,16 +100,15 @@ namespace NadekoBot.Modules.Administration public async Task RotatePlaying(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; - - bool status; + using (var uow = DbHandler.UnitOfWork()) { var config = uow.BotConfig.GetOrCreate(); - status = config.RotatingStatuses = !config.RotatingStatuses; + RotatingStatuses = config.RotatingStatuses = !config.RotatingStatuses; await uow.CompleteAsync(); } - if (status) + if (RotatingStatuses) await channel.SendMessageAsync("`Rotating playing status enabled.`"); else await channel.SendMessageAsync("`Rotating playing status disabled.`"); @@ -119,7 +124,9 @@ namespace NadekoBot.Modules.Administration using (var uow = DbHandler.UnitOfWork()) { var config = uow.BotConfig.GetOrCreate(); - config.RotatingStatusMessages.Add(new PlayingStatus { Status = status }); + var toAdd = new PlayingStatus { Status = status }; + config.RotatingStatusMessages.Add(toAdd); + RotatingStatusMessages.Add(toAdd); await uow.CompleteAsync(); } @@ -132,19 +139,14 @@ namespace NadekoBot.Modules.Administration public async Task ListPlaying(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; + - List statuses; - using (var uow = DbHandler.UnitOfWork()) - { - statuses = uow.BotConfig.GetOrCreate().RotatingStatusMessages; - } - - if (!statuses.Any()) + if (!RotatingStatusMessages.Any()) await channel.SendMessageAsync("`No rotating playing statuses set.`"); else { var i = 1; - await channel.SendMessageAsync($"{umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", statuses.Select(rs => $"`{i++}.` {rs.Status}"))); + await channel.SendMessageAsync($"{umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}"))); } } @@ -166,6 +168,7 @@ namespace NadekoBot.Modules.Administration return; msg = config.RotatingStatusMessages[index].Status; config.RotatingStatusMessages.RemoveAt(index); + RotatingStatusMessages.RemoveAt(index); await uow.CompleteAsync(); } await channel.SendMessageAsync($"`Removed the the playing message:` {msg}").ConfigureAwait(false); From a7ac590e9d8d2e40a8949ed27a6ac41551ba538a Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 02:58:15 +0200 Subject: [PATCH 12/28] Currency Transactions readded. You can't gift yourself money anymore. --- ...1015005020_CurrencyTransaction.Designer.cs | 775 ++++++++++++++++++ .../20161015005020_CurrencyTransaction.cs | 33 + .../NadekoSqliteContextModelSnapshot.cs | 16 + src/NadekoBot/Modules/Gambling/Gambling.cs | 2 +- src/NadekoBot/Services/CurrencyHandler.cs | 13 + .../Services/Database/IUnitOfWork.cs | 1 + .../Database/Models/CurrencyTransaction.cs | 15 + .../Services/Database/NadekoContext.cs | 1 + .../ICurrencyTransactionsRepository.cs | 13 + .../Impl/CurrencyTransactionsRepository.cs | 17 + src/NadekoBot/Services/Database/UnitOfWork.cs | 3 + 11 files changed, 888 insertions(+), 1 deletion(-) create mode 100644 src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs create mode 100644 src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs create mode 100644 src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs create mode 100644 src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs create mode 100644 src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs diff --git a/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs new file mode 100644 index 00000000..09af6235 --- /dev/null +++ b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.Designer.cs @@ -0,0 +1,775 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NadekoBot.Services.Database.Impl; + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoSqliteContext))] + [Migration("20161015005020_CurrencyTransaction")] + partial class CurrencyTransaction + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rtm-21431"); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ItemId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("BlacklistItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BufferSize"); + + b.Property("CurrencyGenerationChance"); + + b.Property("CurrencyGenerationCooldown"); + + b.Property("CurrencyName"); + + b.Property("CurrencyPluralName"); + + b.Property("CurrencySign"); + + b.Property("DMHelpString"); + + b.Property("ForwardMessages"); + + b.Property("ForwardToAllOwners"); + + b.Property("HelpString"); + + b.Property("MigrationVersion"); + + b.Property("RemindMessageFormat"); + + b.Property("RotatingStatuses"); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BaseDestroyed"); + + b.Property("CallUser"); + + b.Property("ClashWarId"); + + b.Property("Stars"); + + b.Property("TimeAdded"); + + b.HasKey("Id"); + + b.HasIndex("ClashWarId"); + + b.ToTable("ClashCallers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("EnemyClan"); + + b.Property("GuildId"); + + b.Property("Size"); + + b.Property("StartedAt"); + + b.Property("WarState"); + + b.HasKey("Id"); + + b.ToTable("ClashOfClans"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CommandName"); + + b.Property("GuildConfigId"); + + b.Property("Seconds"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("InternalTrigger"); + + b.Property("Modifier"); + + b.Property("UnitType"); + + b.HasKey("Id"); + + b.ToTable("ConversionUnits"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Currency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("IsRegex"); + + b.Property("OwnerOnly"); + + b.Property("Response"); + + b.Property("Trigger"); + + b.HasKey("Id"); + + b.ToTable("CustomReactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Name"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Donators"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("EightBallResponses"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildConfigId1"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("Word"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildId"); + + b.Property("Type"); + + b.Property("Username"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDeleteByeMessages"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("DefaultMusicVolume"); + + b.Property("DeleteMessageOnCommand"); + + b.Property("DmGreetMessageText"); + + b.Property("ExclusiveSelfAssignedRoles"); + + b.Property("FilterInvites"); + + b.Property("FilterWords"); + + b.Property("GreetMessageChannelId"); + + b.Property("GuildId"); + + b.Property("LogSettingId"); + + b.Property("PermissionRole"); + + b.Property("RootPermissionId"); + + b.Property("SendChannelByeMessage"); + + b.Property("SendChannelGreetMessage"); + + b.Property("SendDmGreetMessage"); + + b.Property("VerbosePermissions"); + + b.Property("VoicePlusTextEnabled"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("LogSettingId"); + + b.HasIndex("RootPermissionId"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelCreated"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("IsLogging"); + + b.Property("LogUserPresence"); + + b.Property("LogVoicePresence"); + + b.Property("MessageDeleted"); + + b.Property("MessageUpdated"); + + b.Property("UserBanned"); + + b.Property("UserJoined"); + + b.Property("UserLeft"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUpdated"); + + b.Property("VoicePresenceChannelId"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ModuleName"); + + b.Property("Prefix"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("ModulePrefixes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Author"); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("NextId"); + + b.Property("PrimaryTarget"); + + b.Property("PrimaryTargetId"); + + b.Property("SecondaryTarget"); + + b.Property("SecondaryTargetName"); + + b.Property("State"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Status"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("PlayingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("MusicPlaylistId"); + + b.Property("Provider"); + + b.Property("ProviderType"); + + b.Property("Query"); + + b.Property("Title"); + + b.Property("Uri"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("AuthorName") + .IsRequired(); + + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); + + b.HasKey("Id"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Icon"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("RaceAnimals"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("IsPrivate"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("UserId"); + + b.Property("When"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildId"); + + b.Property("Interval"); + + b.Property("Message"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("RoleId"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("Blacklist") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar") + .WithMany("Bases") + .HasForeignKey("ClashWarId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("EightBallResponses") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission") + .WithMany() + .HasForeignKey("RootPermissionId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredChannels") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredVoicePresenceChannelIds") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("ModulePrefixes") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") + .WithOne("Previous") + .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RotatingStatusMessages") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist") + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RaceAnimals") + .HasForeignKey("BotConfigId"); + }); + } + } +} diff --git a/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs new file mode 100644 index 00000000..5d0b61d4 --- /dev/null +++ b/src/NadekoBot/Migrations/20161015005020_CurrencyTransaction.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class CurrencyTransaction : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "CurrencyTransactions", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Autoincrement", true), + Amount = table.Column(nullable: false), + Reason = table.Column(nullable: true), + UserId = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CurrencyTransactions", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CurrencyTransactions"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index ee91013c..148c0cdc 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -164,6 +164,22 @@ namespace NadekoBot.Migrations b.ToTable("Currency"); }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => { b.Property("Id") diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index 41cb7d77..33278f2d 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -87,7 +87,7 @@ namespace NadekoBot.Modules.Gambling public async Task Give(IUserMessage umsg, long amount, [Remainder] IGuildUser receiver) { var channel = (ITextChannel)umsg.Channel; - if (amount <= 0) + if (amount <= 0 || umsg.Author.Id == receiver.Id) return; var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false); if (!success) diff --git a/src/NadekoBot/Services/CurrencyHandler.cs b/src/NadekoBot/Services/CurrencyHandler.cs index 2c0128b3..6b9f26f7 100644 --- a/src/NadekoBot/Services/CurrencyHandler.cs +++ b/src/NadekoBot/Services/CurrencyHandler.cs @@ -7,6 +7,7 @@ using Discord; using NadekoBot.Services.Database; using NadekoBot.Extensions; using NadekoBot.Modules.Gambling; +using NadekoBot.Services.Database.Models; namespace NadekoBot.Services { @@ -33,6 +34,12 @@ namespace NadekoBot.Services var success = uow.Currency.TryUpdateState(authorId, -amount); if (!success) return false; + uow.CurrencyTransactions.Add(new CurrencyTransaction() + { + UserId = authorId, + Reason = reason, + Amount = amount, + }); await uow.CompleteAsync().ConfigureAwait(false); } @@ -56,6 +63,12 @@ namespace NadekoBot.Services using (var uow = DbHandler.UnitOfWork()) { uow.Currency.TryUpdateState(receiverId, amount); + uow.CurrencyTransactions.Add(new CurrencyTransaction() + { + UserId = receiverId, + Reason = reason, + Amount = amount, + }); await uow.CompleteAsync(); } } diff --git a/src/NadekoBot/Services/Database/IUnitOfWork.cs b/src/NadekoBot/Services/Database/IUnitOfWork.cs index a56fafdb..3704bf2f 100644 --- a/src/NadekoBot/Services/Database/IUnitOfWork.cs +++ b/src/NadekoBot/Services/Database/IUnitOfWork.cs @@ -22,6 +22,7 @@ namespace NadekoBot.Services.Database IUnitConverterRepository ConverterUnits { get; } ICustomReactionRepository CustomReactions { get; } ICurrencyRepository Currency { get; } + ICurrencyTransactionsRepository CurrencyTransactions { get; } IMusicPlaylistRepository MusicPlaylists { get; } int Complete(); diff --git a/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs b/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs new file mode 100644 index 00000000..be36ca5f --- /dev/null +++ b/src/NadekoBot/Services/Database/Models/CurrencyTransaction.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Models +{ + public class CurrencyTransaction : DbEntity + { + public long Amount { get; set; } + public string Reason { get; set; } + public ulong UserId { get; set; } + } +} diff --git a/src/NadekoBot/Services/Database/NadekoContext.cs b/src/NadekoBot/Services/Database/NadekoContext.cs index 0f0b5325..156df04a 100644 --- a/src/NadekoBot/Services/Database/NadekoContext.cs +++ b/src/NadekoBot/Services/Database/NadekoContext.cs @@ -24,6 +24,7 @@ namespace NadekoBot.Services.Database public DbSet ConversionUnits { get; set; } public DbSet MusicPlaylists { get; set; } public DbSet CustomReactions { get; set; } + public DbSet CurrencyTransactions { get; set; } //logging public DbSet LogSettings { get; set; } diff --git a/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs b/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs new file mode 100644 index 00000000..9cada99b --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/ICurrencyTransactionsRepository.cs @@ -0,0 +1,13 @@ +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Services.Database.Repositories +{ + public interface ICurrencyTransactionsRepository : IRepository + { + } +} diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs new file mode 100644 index 00000000..8a8bffe8 --- /dev/null +++ b/src/NadekoBot/Services/Database/Repositories/Impl/CurrencyTransactionsRepository.cs @@ -0,0 +1,17 @@ +using NadekoBot.Services.Database.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; + +namespace NadekoBot.Services.Database.Repositories.Impl +{ + public class CurrencyTransactionsRepository : Repository, ICurrencyTransactionsRepository + { + public CurrencyTransactionsRepository(DbContext context) : base(context) + { + } + } +} diff --git a/src/NadekoBot/Services/Database/UnitOfWork.cs b/src/NadekoBot/Services/Database/UnitOfWork.cs index 43cc5f6d..b4dd1e8b 100644 --- a/src/NadekoBot/Services/Database/UnitOfWork.cs +++ b/src/NadekoBot/Services/Database/UnitOfWork.cs @@ -39,6 +39,9 @@ namespace NadekoBot.Services.Database private ICurrencyRepository _currency; public ICurrencyRepository Currency => _currency ?? (_currency = new CurrencyRepository(_context)); + private ICurrencyTransactionsRepository _currencyTransactions; + public ICurrencyTransactionsRepository CurrencyTransactions => _currencyTransactions ?? (_currencyTransactions = new CurrencyTransactionsRepository(_context)); + private IUnitConverterRepository _conUnits; public IUnitConverterRepository ConverterUnits => _conUnits ?? (_conUnits = new UnitConverterRepository(_context)); From 1e87e4cf7f9e7be3d932084cc7a53f55dbac84c2 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 08:25:52 +0200 Subject: [PATCH 13/28] Fixed crash, fixed imdb --- .../Modules/Administration/Administration.cs | 15 +++++++++++++++ .../Commands/AutoAssignRoleCommands.cs | 1 - .../Searches/Commands/IMDB/ImdbScraper.cs | 17 +++++------------ .../Searches/Commands/Models/ImdbMovie.cs | 2 +- src/NadekoBot/Modules/Searches/Searches.cs | 4 ++++ src/NadekoBot/Services/Impl/GoogleApiService.cs | 17 ++++++++++++++--- 6 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index eaeb163a..b3a7cd36 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -35,6 +35,7 @@ namespace NadekoBot.Modules.Administration if (channel == null) return; + //todo cache this bool shouldDelete; using (var uow = DbHandler.UnitOfWork()) { @@ -695,12 +696,14 @@ namespace NadekoBot.Modules.Administration await channel.SendMessageAsync(send).ConfigureAwait(false); } + IGuild nadekoSupportServer; [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] public async Task Donators(IUserMessage umsg) { var channel = (ITextChannel)umsg.Channel; IEnumerable donatorsOrdered; + using (var uow = DbHandler.UnitOfWork()) { donatorsOrdered = uow.Donators.GetDonatorsOrdered(); @@ -708,6 +711,18 @@ namespace NadekoBot.Modules.Administration string str = $"**Thanks to the people listed below for making this project happen!**\n"; await channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false); + + nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850); + + if (nadekoSupportServer == null) + return; + + var patreonRole = nadekoSupportServer.GetRole(236667642088259585); + if (patreonRole == null) + return; + + var usrs = nadekoSupportServer.GetUsers().Where(u => u.Roles.Contains(patreonRole)); + await channel.SendMessageAsync("\n`Patreon supporters:`\n" + string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false); } diff --git a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs index 968f9dd9..dd35927c 100644 --- a/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/AutoAssignRoleCommands.cs @@ -28,7 +28,6 @@ namespace NadekoBot.Modules.Administration { conf = uow.GuildConfigs.For(user.Guild.Id); } - var aarType = conf.AutoAssignRoleId.GetType(); if (conf.AutoAssignRoleId == 0) return; diff --git a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs index ce8f8a37..3f635099 100644 --- a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs +++ b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs @@ -74,17 +74,9 @@ namespace NadekoBot.Modules.Searches.IMDB mov.OriginalTitle = Match(@"title-extra"">(.*?)<", html); mov.Year = Match(@".*?\(.*?(\d{4}).*?\).*?", Match(@"(.*?)", html)); mov.Rating = Match(@"(\d.\d)/10", html); - mov.Genres = MatchAll(@"(.*?)", Match(@"Genre.?:(.*?)(|See more)", html)).Cast().ToList(); - mov.Plot = Match(@"Plot:.*?
(.*?)(.*?", html); - if (!string.IsNullOrEmpty(mov.Poster) && mov.Poster.IndexOf("media-imdb.com") > 0) - { - mov.Poster = Regex.Replace(mov.Poster, @"_V1.*?.jpg", "_V1._SY200.jpg"); - } - else - { - mov.Poster = string.Empty; - } + mov.Genres = MatchAll(@"(.*?)", Match(@"Genre.?:((.|\n)*?)(<\/div>|See more)", html)).Cast().ToList(); + mov.Plot = Match(@"Plot:\n
\n((.|\n)*?)( private static List MatchAll(string regex, string html, int i = 1) diff --git a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs index f4fa1770..318eb6dc 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Models/ImdbMovie.cs @@ -26,7 +26,7 @@ $@"`Title:` {WebUtility.HtmlDecode(Title)} {(string.IsNullOrEmpty(OriginalTitle) `Genre:` {GenresAsString} `Link:` <{ImdbURL}> `Plot:` {System.Net.WebUtility.HtmlDecode(Plot.TrimTo(500))} -`img:` " + Poster; +`Poster:` " + NadekoBot.Google.ShortenUrl(Poster).GetAwaiter().GetResult(); public string GenresAsString => string.Join(", ", Genres); } diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index 5f676709..d18d94a9 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -66,6 +66,10 @@ $@"🌍 **Weather for** 【{obj["target"]}】 await channel.SendMessageAsync(result).ConfigureAwait(false); } + //todo move to omdb + // | + // v + //{"Title":"Shutter Island","Year":"2010","Rated":"R","Released":"19 Feb 2010","Runtime":"138 min","Genre":"Mystery, Thriller","Director":"Martin Scorsese","Writer":"Laeta Kalogridis (screenplay), Dennis Lehane (novel)","Actors":"Leonardo DiCaprio, Mark Ruffalo, Ben Kingsley, Max von Sydow","Plot":"In 1954, a U.S. marshal investigates the disappearance of a murderess who escaped from a hospital for the criminally insane.","Language":"English, German","Country":"USA","Awards":"8 wins & 59 nominations.","Poster":"https://images-na.ssl-images-amazon.com/images/M/MV5BMTMxMTIyNzMxMV5BMl5BanBnXkFtZTcwOTc4OTI3Mg@@._V1_SX300.jpg","Metascore":"63","imdbRating":"8.1","imdbVotes":"798,447","imdbID":"tt1130884","Type":"movie","Response":"True"} [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] public async Task Imdb(IUserMessage umsg, [Remainder] string query = null) diff --git a/src/NadekoBot/Services/Impl/GoogleApiService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs index 4d74e290..c1df1513 100644 --- a/src/NadekoBot/Services/Impl/GoogleApiService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -7,6 +7,7 @@ using Google.Apis.Services; using System.Text.RegularExpressions; using Google.Apis.Urlshortener.v1; using Google.Apis.Urlshortener.v1.Data; +using NLog; namespace NadekoBot.Services.Impl { @@ -14,6 +15,7 @@ namespace NadekoBot.Services.Impl { private YouTubeService yt; private UrlshortenerService sh; + private Logger _log { get; } public GoogleApiService() { @@ -23,6 +25,8 @@ namespace NadekoBot.Services.Impl ApiKey = NadekoBot.Credentials.GoogleApiKey }; + _log = LogManager.GetCurrentClassLogger(); + yt = new YouTubeService(bcs); sh = new UrlshortenerService(bcs); } @@ -85,9 +89,16 @@ namespace NadekoBot.Services.Impl { if (string.IsNullOrWhiteSpace(url)) throw new ArgumentNullException(nameof(url)); - - var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); - return response.Id; + try + { + var response = await sh.Url.Insert(new Url { LongUrl = url }).ExecuteAsync(); + return response.Id; + } + catch (Exception ex) + { + _log.Warn(ex); + return url; + } } public async Task> GetPlaylistTracksAsync(string playlistId, int count = 50) From 40978c123d7849bd1756fa849339d708c1cde085 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 14:12:35 +0200 Subject: [PATCH 14/28] Clash of clans works perfectly now, updated some strings and usages for it too --- .../Migrations/20161015102407_coc.Designer.cs | 777 ++++++++++++++++++ .../Migrations/20161015102407_coc.cs | 24 + .../NadekoSqliteContextModelSnapshot.cs | 2 + .../Modules/ClashOfClans/ClashOfClans.cs | 79 +- .../Modules/ClashOfClans/Extensions.cs | 38 +- .../Resources/CommandStrings.Designer.cs | 12 +- src/NadekoBot/Resources/CommandStrings.resx | 12 +- .../Services/Database/Models/ClashCaller.cs | 1 + .../Impl/ClashOfClansRepository.cs | 4 +- 9 files changed, 887 insertions(+), 62 deletions(-) create mode 100644 src/NadekoBot/Migrations/20161015102407_coc.Designer.cs create mode 100644 src/NadekoBot/Migrations/20161015102407_coc.cs diff --git a/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs b/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs new file mode 100644 index 00000000..f05d500c --- /dev/null +++ b/src/NadekoBot/Migrations/20161015102407_coc.Designer.cs @@ -0,0 +1,777 @@ +ο»Ώusing System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using NadekoBot.Services.Database.Impl; + +namespace NadekoBot.Migrations +{ + [DbContext(typeof(NadekoSqliteContext))] + [Migration("20161015102407_coc")] + partial class coc + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { + modelBuilder + .HasAnnotation("ProductVersion", "1.0.0-rtm-21431"); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ItemId"); + + b.Property("Type"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("BlacklistItem"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BotConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BufferSize"); + + b.Property("CurrencyGenerationChance"); + + b.Property("CurrencyGenerationCooldown"); + + b.Property("CurrencyName"); + + b.Property("CurrencyPluralName"); + + b.Property("CurrencySign"); + + b.Property("DMHelpString"); + + b.Property("ForwardMessages"); + + b.Property("ForwardToAllOwners"); + + b.Property("HelpString"); + + b.Property("MigrationVersion"); + + b.Property("RemindMessageFormat"); + + b.Property("RotatingStatuses"); + + b.HasKey("Id"); + + b.ToTable("BotConfig"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BaseDestroyed"); + + b.Property("CallUser"); + + b.Property("ClashWarId"); + + b.Property("SequenceNumber"); + + b.Property("Stars"); + + b.Property("TimeAdded"); + + b.HasKey("Id"); + + b.HasIndex("ClashWarId"); + + b.ToTable("ClashCallers"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashWar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("EnemyClan"); + + b.Property("GuildId"); + + b.Property("Size"); + + b.Property("StartedAt"); + + b.Property("WarState"); + + b.HasKey("Id"); + + b.ToTable("ClashOfClans"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("CommandName"); + + b.Property("GuildConfigId"); + + b.Property("Seconds"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ConvertUnit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("InternalTrigger"); + + b.Property("Modifier"); + + b.Property("UnitType"); + + b.HasKey("Id"); + + b.ToTable("ConversionUnits"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Currency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Currency"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Reason"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CustomReaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("IsRegex"); + + b.Property("OwnerOnly"); + + b.Property("Response"); + + b.Property("Trigger"); + + b.HasKey("Id"); + + b.ToTable("CustomReactions"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Donator", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Amount"); + + b.Property("Name"); + + b.Property("UserId"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("Donators"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Text"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("EightBallResponses"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildConfigId1"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.HasIndex("GuildConfigId1"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildConfigId"); + + b.Property("Word"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.Property("GuildId"); + + b.Property("Type"); + + b.Property("Username"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildConfigId"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AutoAssignRoleId"); + + b.Property("AutoDeleteByeMessages"); + + b.Property("AutoDeleteGreetMessages"); + + b.Property("AutoDeleteGreetMessagesTimer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages"); + + b.Property("ByeMessageChannelId"); + + b.Property("ChannelByeMessageText"); + + b.Property("ChannelGreetMessageText"); + + b.Property("DefaultMusicVolume"); + + b.Property("DeleteMessageOnCommand"); + + b.Property("DmGreetMessageText"); + + b.Property("ExclusiveSelfAssignedRoles"); + + b.Property("FilterInvites"); + + b.Property("FilterWords"); + + b.Property("GreetMessageChannelId"); + + b.Property("GuildId"); + + b.Property("LogSettingId"); + + b.Property("PermissionRole"); + + b.Property("RootPermissionId"); + + b.Property("SendChannelByeMessage"); + + b.Property("SendChannelGreetMessage"); + + b.Property("SendDmGreetMessage"); + + b.Property("VerbosePermissions"); + + b.Property("VoicePlusTextEnabled"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("LogSettingId"); + + b.HasIndex("RootPermissionId"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("LogSettingId"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredVoicePresenceCHannels"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelCreated"); + + b.Property("ChannelDestroyed"); + + b.Property("ChannelId"); + + b.Property("ChannelUpdated"); + + b.Property("IsLogging"); + + b.Property("LogUserPresence"); + + b.Property("LogVoicePresence"); + + b.Property("MessageDeleted"); + + b.Property("MessageUpdated"); + + b.Property("UserBanned"); + + b.Property("UserJoined"); + + b.Property("UserLeft"); + + b.Property("UserPresenceChannelId"); + + b.Property("UserUnbanned"); + + b.Property("UserUpdated"); + + b.Property("VoicePresenceChannelId"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("ModuleName"); + + b.Property("Prefix"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("ModulePrefixes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("Author"); + + b.Property("AuthorId"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("NextId"); + + b.Property("PrimaryTarget"); + + b.Property("PrimaryTargetId"); + + b.Property("SecondaryTarget"); + + b.Property("SecondaryTargetName"); + + b.Property("State"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Status"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("PlayingStatus"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("MusicPlaylistId"); + + b.Property("Provider"); + + b.Property("ProviderType"); + + b.Property("Query"); + + b.Property("Title"); + + b.Property("Uri"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AuthorId"); + + b.Property("AuthorName") + .IsRequired(); + + b.Property("GuildId"); + + b.Property("Keyword") + .IsRequired(); + + b.Property("Text") + .IsRequired(); + + b.HasKey("Id"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("BotConfigId"); + + b.Property("Icon"); + + b.Property("Name"); + + b.HasKey("Id"); + + b.HasIndex("BotConfigId"); + + b.ToTable("RaceAnimals"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("IsPrivate"); + + b.Property("Message"); + + b.Property("ServerId"); + + b.Property("UserId"); + + b.Property("When"); + + b.HasKey("Id"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ChannelId"); + + b.Property("GuildId"); + + b.Property("Interval"); + + b.Property("Message"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("GuildId"); + + b.Property("RoleId"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.BlacklistItem", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("Blacklist") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ClashCaller", b => + { + b.HasOne("NadekoBot.Services.Database.Models.ClashWar", "ClashWar") + .WithMany("Bases") + .HasForeignKey("ClashWarId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.CommandCooldown", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.EightBallResponse", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("EightBallResponses") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId"); + + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId1"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FilteredWord", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.FollowedStream", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GCChannelId", b => + { + b.HasOne("NadekoBot.Services.Database.Models.GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.GuildConfig", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.HasOne("NadekoBot.Services.Database.Models.Permission", "RootPermission") + .WithMany() + .HasForeignKey("RootPermissionId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredLogChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredChannels") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.IgnoredVoicePresenceChannel", b => + { + b.HasOne("NadekoBot.Services.Database.Models.LogSetting", "LogSetting") + .WithMany("IgnoredVoicePresenceChannelIds") + .HasForeignKey("LogSettingId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.ModulePrefix", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("ModulePrefixes") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.Permission", b => + { + b.HasOne("NadekoBot.Services.Database.Models.Permission", "Next") + .WithOne("Previous") + .HasForeignKey("NadekoBot.Services.Database.Models.Permission", "NextId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlayingStatus", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RotatingStatusMessages") + .HasForeignKey("BotConfigId"); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.PlaylistSong", b => + { + b.HasOne("NadekoBot.Services.Database.Models.MusicPlaylist") + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("NadekoBot.Services.Database.Models.RaceAnimal", b => + { + b.HasOne("NadekoBot.Services.Database.Models.BotConfig") + .WithMany("RaceAnimals") + .HasForeignKey("BotConfigId"); + }); + } + } +} diff --git a/src/NadekoBot/Migrations/20161015102407_coc.cs b/src/NadekoBot/Migrations/20161015102407_coc.cs new file mode 100644 index 00000000..e1d42e8c --- /dev/null +++ b/src/NadekoBot/Migrations/20161015102407_coc.cs @@ -0,0 +1,24 @@ +ο»Ώusing System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace NadekoBot.Migrations +{ + public partial class coc : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "SequenceNumber", + table: "ClashCallers", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "SequenceNumber", + table: "ClashCallers"); + } + } +} diff --git a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs index 148c0cdc..be1f7786 100644 --- a/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs +++ b/src/NadekoBot/Migrations/NadekoSqliteContextModelSnapshot.cs @@ -80,6 +80,8 @@ namespace NadekoBot.Migrations b.Property("ClashWarId"); + b.Property("SequenceNumber"); + b.Property("Stars"); b.Property("TimeAdded"); diff --git a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs index ae5fc69a..1f084c4c 100644 --- a/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs +++ b/src/NadekoBot/Modules/ClashOfClans/ClashOfClans.cs @@ -21,23 +21,21 @@ namespace NadekoBot.Modules.ClashOfClans static ClashOfClans() { - //using (var uow = DbHandler.UnitOfWork()) - //{ - // ClashWars = new ConcurrentDictionary>( - // uow.ClashOfClans - // .GetAllWars() - // .Select(cw => { - // if (cw == null || cw.Bases == null) - // return null; - // cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId) - // ?.GetTextChannel(cw.ChannelId); - // cw.Bases.Capacity = cw.Size; - // return cw; - // }) - // .Where(cw => cw?.Channel != null) - // .GroupBy(cw => cw.GuildId) - // .ToDictionary(g => g.Key, g => g.ToList())); - //} + using (var uow = DbHandler.UnitOfWork()) + { + ClashWars = new ConcurrentDictionary>( + uow.ClashOfClans + .GetAllWars() + .Select(cw => + { + cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId) + ?.GetTextChannel(cw.ChannelId); + return cw; + }) + .Where(cw => cw?.Channel != null) + .GroupBy(cw => cw.GuildId) + .ToDictionary(g => g.Key, g => g.ToList())); + } } public ClashOfClans(ILocalization loc, CommandService cmds, ShardedDiscordClient client) : base(loc, cmds, client) { @@ -46,9 +44,9 @@ namespace NadekoBot.Modules.ClashOfClans private static async Task CheckWar(TimeSpan callExpire, ClashWar war) { var Bases = war.Bases; - for (var i = 0; i < Bases.Capacity; i++) + for (var i = 0; i < Bases.Count; i++) { - if (Bases[i] == null) continue; + if (Bases[i].CallUser == null) continue; if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire) { Bases[i] = null; @@ -84,7 +82,6 @@ namespace NadekoBot.Modules.ClashOfClans var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id); - //cw.Start(); wars.Add(cw); await channel.SendMessageAsync($"β—πŸ”°**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false); @@ -191,26 +188,26 @@ namespace NadekoBot.Modules.ClashOfClans [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name, 1); + await FinishClaim(umsg, number, baseNumber - 1, 1); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name, 2); + await FinishClaim(umsg, number, baseNumber - 1, 2); } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) + public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber = 0) { var channel = (ITextChannel)umsg.Channel; - await FinishClaim(umsg, number, baseNumber, other_name); + await FinishClaim(umsg, number, baseNumber - 1); } [NadekoCommand, Usage, Description, Aliases] @@ -263,7 +260,7 @@ namespace NadekoBot.Modules.ClashOfClans } } - private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name, int stars = 3) + private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, int stars = 3) { var channel = (ITextChannel)umsg.Channel; var warInfo = GetWarInfo(umsg, number); @@ -272,17 +269,19 @@ namespace NadekoBot.Modules.ClashOfClans await channel.SendMessageAsync("πŸ’’πŸ”° **That war does not exist.**").ConfigureAwait(false); return; } - var usr = - string.IsNullOrWhiteSpace(other_name) ? - umsg.Author.Username : - other_name; - var war = warInfo.Item1[warInfo.Item2]; try { - var baseNum = war.FinishClaim(usr, stars); - SaveWar(war); - await channel.SendMessageAsync($"β—πŸ”°{umsg.Author.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false); + if (baseNumber == -1) + { + baseNumber = war.FinishClaim(umsg.Author.Username, stars); + SaveWar(war); + } + else + { + war.FinishClaim(baseNumber, stars); + } + await channel.SendMessageAsync($"β—πŸ”°{umsg.Author.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false); } catch (Exception ex) { @@ -324,6 +323,16 @@ namespace NadekoBot.Modules.ClashOfClans Channel = NadekoBot.Client.GetGuild(serverId) ?.GetTextChannel(channelId) }; + cw.Bases.Capacity = size; + for (int i = 0; i < size; i++) + { + cw.Bases.Add(new ClashCaller() + { + CallUser = null, + SequenceNumber = i, + }); + } + Console.WriteLine(cw.Bases.Capacity); uow.ClashOfClans.Add(cw); await uow.CompleteAsync(); return cw; diff --git a/src/NadekoBot/Modules/ClashOfClans/Extensions.cs b/src/NadekoBot/Modules/ClashOfClans/Extensions.cs index b367f0a6..d2103edd 100644 --- a/src/NadekoBot/Modules/ClashOfClans/Extensions.cs +++ b/src/NadekoBot/Modules/ClashOfClans/Extensions.cs @@ -30,21 +30,20 @@ namespace NadekoBot.Modules.ClashOfClans public static void Call(this ClashWar cw, string u, int baseNumber) { - if (baseNumber < 0 || baseNumber >= cw.Bases.Capacity) + if (baseNumber < 0 || baseNumber >= cw.Bases.Count) throw new ArgumentException("Invalid base number"); - if (cw.Bases[baseNumber] != null) + if (cw.Bases[baseNumber].CallUser != null) throw new ArgumentException("That base is already claimed."); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.BaseDestroyed == false && cw.Bases[i]?.CallUser == u) throw new ArgumentException($"@{u} You already claimed base #{i + 1}. You can't claim a new one."); } - cw.Bases[baseNumber] = new ClashCaller() { - CallUser = u.Trim(), - TimeAdded = DateTime.UtcNow, - BaseDestroyed = false - }; + var cc = cw.Bases[baseNumber]; + cc.CallUser = u.Trim(); + cc.TimeAdded = DateTime.UtcNow; + cc.BaseDestroyed = false; } public static void Start(this ClashWar cw) @@ -56,7 +55,7 @@ namespace NadekoBot.Modules.ClashOfClans //Started = true; cw.WarState = StateOfWar.Started; cw.StartedAt = DateTime.UtcNow; - foreach (var b in cw.Bases.Where(b => b != null)) + foreach (var b in cw.Bases.Where(b => b.CallUser != null)) { b.ResetTime(); } @@ -65,10 +64,10 @@ namespace NadekoBot.Modules.ClashOfClans public static int Uncall(this ClashWar cw, string user) { user = user.Trim(); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.CallUser != user) continue; - cw.Bases[i] = null; + cw.Bases[i].CallUser = null; return i; } throw new InvalidOperationException("You are not participating in that war."); @@ -85,9 +84,9 @@ namespace NadekoBot.Modules.ClashOfClans if (cw.WarState == StateOfWar.Created) sb.AppendLine("`not started`"); var twoHours = new TimeSpan(2, 0, 0); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { - if (cw.Bases[i] == null) + if (cw.Bases[i].CallUser == null) { sb.AppendLine($"`{i + 1}.` ❌*unclaimed*"); } @@ -111,7 +110,7 @@ namespace NadekoBot.Modules.ClashOfClans public static int FinishClaim(this ClashWar cw, string user, int stars = 3) { user = user.Trim(); - for (var i = 0; i < cw.Bases.Capacity; i++) + for (var i = 0; i < cw.Bases.Count; i++) { if (cw.Bases[i]?.BaseDestroyed != false || cw.Bases[i]?.CallUser != user) continue; cw.Bases[i].BaseDestroyed = true; @@ -120,5 +119,16 @@ namespace NadekoBot.Modules.ClashOfClans } throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base."); } + + public static void FinishClaim(this ClashWar cw, int index, int stars = 3) + { + if (index < 0 || index > cw.Bases.Count) + throw new ArgumentOutOfRangeException(nameof(index)); + var toFinish = cw.Bases[index]; + if (toFinish.BaseDestroyed != false) throw new InvalidOperationException("That base is already destroyed."); + if (toFinish.CallUser == null) throw new InvalidOperationException("That base is unclaimed."); + toFinish.BaseDestroyed = true; + toFinish.Stars = stars; + } } } \ No newline at end of file diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 73f71499..787a437f 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -1338,7 +1338,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish_desc { get { @@ -1347,7 +1347,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf 1 Someone`. + /// Looks up a localized string similar to `,cf 1` or `,cf 1 5`. /// public static string claimfinish_usage { get { @@ -1365,7 +1365,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish1_desc { get { @@ -1374,7 +1374,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf1 2 SomeGirl`. + /// Looks up a localized string similar to `,cf1 1` or `,cf1 1 5`. /// public static string claimfinish1_usage { get { @@ -1392,7 +1392,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else.. + /// Looks up a localized string similar to Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else.. /// public static string claimfinish2_desc { get { @@ -1401,7 +1401,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `,cf2 1 SomeGuy`. + /// Looks up a localized string similar to `,cf2 1` or `,cf2 1 5`. /// public static string claimfinish2_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 42cce386..55d78219 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2362,28 +2362,28 @@ claimfinish cf - Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf 1 Someone` + `,cf 1` or `,cf 1 5` claimfinish2 cf2 - Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf2 1 SomeGuy` + `,cf2 1` or `,cf2 1 5` claimfinish1 cf1 - Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. + Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. - `,cf1 2 SomeGirl` + `,cf1 1` or `,cf1 1 5` unclaim ucall uc diff --git a/src/NadekoBot/Services/Database/Models/ClashCaller.cs b/src/NadekoBot/Services/Database/Models/ClashCaller.cs index 2f875049..719ef9ee 100644 --- a/src/NadekoBot/Services/Database/Models/ClashCaller.cs +++ b/src/NadekoBot/Services/Database/Models/ClashCaller.cs @@ -9,6 +9,7 @@ namespace NadekoBot.Services.Database.Models { public class ClashCaller : DbEntity { + public int? SequenceNumber { get; set; } = null; public string CallUser { get; set; } public DateTime TimeAdded { get; set; } diff --git a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs index 78b2aaf3..bbe12205 100644 --- a/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs +++ b/src/NadekoBot/Services/Database/Repositories/Impl/ClashOfClansRepository.cs @@ -16,8 +16,10 @@ namespace NadekoBot.Services.Database.Repositories.Impl public IEnumerable GetAllWars() { - return _set.Include(cw => cw.Bases) + var toReturn = _set.Include(cw => cw.Bases) .ToList(); + toReturn.ForEach(cw => cw.Bases = cw.Bases.Where(w => w.SequenceNumber != null).OrderBy(w => w.SequenceNumber).ToList()); + return toReturn; } } } From 384e83f07f6b7319b2d7f60a6d7ccc7c91607e1e Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 14:40:01 +0200 Subject: [PATCH 15/28] Small fix to custom reactions --- src/NadekoBot/Modules/Administration/Commands/Migration.cs | 2 +- .../Modules/Administration/Commands/ServerGreetCommands.cs | 4 ++-- src/NadekoBot/Modules/CustomReactions/CustomReactions.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/Migration.cs b/src/NadekoBot/Modules/Administration/Commands/Migration.cs index cd7ae2f8..b434bb1d 100644 --- a/src/NadekoBot/Modules/Administration/Commands/Migration.cs +++ b/src/NadekoBot/Modules/Administration/Commands/Migration.cs @@ -411,7 +411,7 @@ namespace NadekoBot.Modules.Administration { return cr.Value.Select(res => new CustomReaction() { - GuildId = 0, + GuildId = null, IsRegex = false, OwnerOnly = false, Response = res, diff --git a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs index fba659ff..8d6e7f16 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ServerGreetCommands.cs @@ -43,7 +43,7 @@ namespace NadekoBot.Modules.Administration if (channel == null) //maybe warn the server owner that the channel is missing return; - var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username + $" ({user.Id})").Replace("%server%", user.Guild.Name); + var msg = conf.ChannelByeMessageText.Replace("%user%", user.Username).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); if (string.IsNullOrWhiteSpace(msg)) return; try @@ -78,7 +78,7 @@ namespace NadekoBot.Modules.Administration var channel = (await user.Guild.GetTextChannelsAsync()).SingleOrDefault(c => c.Id == conf.GreetMessageChannelId); if (channel != null) //maybe warn the server owner that the channel is missing { - var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%server%", user.Guild.Name); + var msg = conf.ChannelGreetMessageText.Replace("%user%", user.Mention).Replace("%id%", user.Id.ToString()).Replace("%server%", user.Guild.Name); if (!string.IsNullOrWhiteSpace(msg)) { try diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index c26e2a2b..a10f8f13 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -169,16 +169,16 @@ namespace NadekoBot.Modules.CustomReactions if (toDelete == null) //not found return; - if (toDelete.GuildId == null && channel == null) + if ((toDelete.GuildId == null || toDelete.GuildId == 0) && channel == null) { uow.CustomReactions.Remove(toDelete); GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id); success = true; } - else if (toDelete.GuildId != null && channel?.Guild.Id == toDelete.GuildId) + else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && channel?.Guild.Id == toDelete.GuildId) { uow.CustomReactions.Remove(toDelete); - GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()).RemoveWhere(cr=>cr.Id == toDelete.Id); + GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet()).RemoveWhere(cr => cr.Id == toDelete.Id); success = true; } if(success) From 1dd8f9b5eacf3db432b7c525bf63e73f6e17e587 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 14:59:51 +0200 Subject: [PATCH 16/28] Fixes to custom reactions case insensitivty --- src/NadekoBot/Modules/Administration/Commands/Migration.cs | 2 +- src/NadekoBot/Modules/CustomReactions/CustomReactions.cs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/Migration.cs b/src/NadekoBot/Modules/Administration/Commands/Migration.cs index b434bb1d..feb3aab0 100644 --- a/src/NadekoBot/Modules/Administration/Commands/Migration.cs +++ b/src/NadekoBot/Modules/Administration/Commands/Migration.cs @@ -415,7 +415,7 @@ namespace NadekoBot.Modules.Administration IsRegex = false, OwnerOnly = false, Response = res, - Trigger = cr.Key, + Trigger = cr.Key.ToLowerInvariant(), }); }).ToArray()); diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index a10f8f13..2e72533e 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -42,19 +42,19 @@ namespace NadekoBot.Modules.CustomReactions var t = Task.Run(async () => { - var content = umsg.Content.ToLowerInvariant(); + var content = umsg.Content.Trim().ToLowerInvariant(); ConcurrentHashSet reactions; GuildReactions.TryGetValue(channel.Guild.Id, out reactions); if (reactions != null && reactions.Any()) { - var reaction = reactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault(); + var reaction = reactions.Where(cr => cr.TriggerWithContext(umsg).Trim().ToLowerInvariant() == content).Shuffle().FirstOrDefault(); if (reaction != null) { try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } return; } } - var greaction = GlobalReactions.Where(cr => cr.TriggerWithContext(umsg) == content).Shuffle().FirstOrDefault(); + var greaction = GlobalReactions.Where(cr => cr.TriggerWithContext(umsg).Trim().ToLowerInvariant() == content).Shuffle().FirstOrDefault(); if (greaction != null) { try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } From 17f76da220573f4a68c9450d749822e0297a21ad Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 23:11:45 +0200 Subject: [PATCH 17/28] Moved from imdb to omdb --- .../Searches/Commands/IMDB/ImdbScraper.cs | 168 ------------------ src/NadekoBot/Modules/Searches/Searches.cs | 21 +-- .../Resources/CommandStrings.Designer.cs | 4 +- src/NadekoBot/Resources/CommandStrings.resx | 4 +- 4 files changed, 9 insertions(+), 188 deletions(-) delete mode 100644 src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs diff --git a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs b/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs deleted file mode 100644 index 3f635099..00000000 --- a/src/NadekoBot/Modules/Searches/Commands/IMDB/ImdbScraper.cs +++ /dev/null @@ -1,168 +0,0 @@ -ο»Ώusing NadekoBot.Extensions; -using NadekoBot.Modules.Searches.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -/******************************************************************************* -* Free ASP.net IMDb Scraper API for the new IMDb Template. -* Author: Abhinay Rathore -* Website: http://www.AbhinayRathore.com -* Blog: http://web3o.blogspot.com -* More Info: http://web3o.blogspot.com/2010/11/aspnetc-imdb-scraping-api.html - -* Updated By: Gergo Torcsvari -* Last Updated: Feb, 2016 -*******************************************************************************/ - -namespace NadekoBot.Modules.Searches.IMDB -{ - public static class ImdbScraper - { - //Search Engine URLs - private static string GoogleSearch = "https://www.google.com/search?q=imdb+"; - //Constructor - public static async Task ImdbScrape(string MovieName, bool GetExtraInfo = true) - { - ImdbMovie mov = new ImdbMovie(); - string imdbUrl = await GetIMDbUrlAsync(System.Uri.EscapeUriString(MovieName)); - mov.Status = false; - if (!string.IsNullOrWhiteSpace(imdbUrl)) - { - await ParseIMDbPage(imdbUrl, GetExtraInfo, mov); - } - - return mov; - } - - public static async Task ImdbScrapeFromId(string imdbId, bool GetExtraInfo = true) - { - ImdbMovie mov = new ImdbMovie(); - string imdbUrl = "http://www.imdb.com/title/" + imdbId + "/"; - mov.Status = false; - await ParseIMDbPage(imdbUrl, GetExtraInfo, mov); - return mov; - } - - public static async Task GetIMDBId(string MovieName) - { - string imdbUrl = await GetIMDbUrlAsync(System.Uri.EscapeUriString(MovieName)); - return Match(@"http://www.imdb.com/title/(tt\d{7})", imdbUrl); - } - //Get IMDb URL from search results - private static async Task GetIMDbUrlAsync(string MovieName) - { - string url = GoogleSearch + MovieName; - string html = await GetUrlDataAsync(url); - List imdbUrls = MatchAll(@".*?", html); - if (imdbUrls.Count > 0) - return (string)imdbUrls[0]; - else return String.Empty; - } - //Parse IMDb page data - private static async Task ParseIMDbPage(string imdbUrl, bool GetExtraInfo, ImdbMovie mov) - { - string html = await GetUrlDataAsync(imdbUrl + "combined"); - mov.Id = Match(@"", html); - if (!string.IsNullOrEmpty(mov.Id)) - { - mov.Status = true; - mov.Title = Match(@"(IMDb \- )*(.*?) \(.*?", html, 2); - mov.OriginalTitle = Match(@"title-extra"">(.*?)<", html); - mov.Year = Match(@".*?\(.*?(\d{4}).*?\).*?", Match(@"(.*?)", html)); - mov.Rating = Match(@"(\d.\d)/10", html); - mov.Genres = MatchAll(@"(.*?)", Match(@"Genre.?:((.|\n)*?)(<\/div>|See more)", html)).Cast().ToList(); - mov.Plot = Match(@"Plot:\n
\n((.|\n)*?)( release = new Dictionary(); - string releasehtml = await GetUrlDataAsync("http://www.imdb.com/title/" + mov.Id + "/releaseinfo"); - foreach (string r in MatchAll(@"(.*?)", Match(@"\n*?(.*?)
", releasehtml))) - { - Match rd = new Regex(@"(.*?)\n*?.*?(.*?)", RegexOptions.Multiline).Match(r); - release[StripHTML(rd.Groups[1].Value.Trim())] = StripHTML(rd.Groups[2].Value.Trim()); - } - //mov.ReleaseDates = release; - - Dictionary aka = new Dictionary(); - List list = MatchAll(@".*?(.*?)", Match(@"\n*?(.*?)
", releasehtml)); - foreach (string r in list) - { - Match rd = new Regex(@"\n*?.*?(.*?)\n*?.*?(.*?)", RegexOptions.Multiline).Match(r); - aka[StripHTML(rd.Groups[1].Value.Trim())] = StripHTML(rd.Groups[2].Value.Trim()); - } - mov.Aka = aka; - - - - } - //Get all media images - private static async Task> GetMediaImages(ImdbMovie mov) - { - List list = new List(); - string mediaurl = "http://www.imdb.com/title/" + mov.Id + "/mediaindex"; - string mediahtml = await GetUrlDataAsync(mediaurl); - int pagecount = MatchAll(@"", Match(@"(.*?)", mediahtml)).Count; - for (int p = 1; p <= pagecount + 1; p++) - { - mediahtml = await GetUrlDataAsync(mediaurl + "?page=" + p); - foreach (Match m in new Regex(@"src=""(.*?)""", RegexOptions.Multiline).Matches(Match(@"
(.*?)
", mediahtml))) - { - String image = m.Groups[1].Value; - list.Add(Regex.Replace(image, @"_V1\..*?.jpg", "_V1._SY0.jpg")); - } - } - return list; - } - //Get Recommended Titles - private static async Task> GetRecommendedTitlesAsync(ImdbMovie mov) - { - List list = new List(); - string recUrl = "http://www.imdb.com/widget/recommendations/_ajax/get_more_recs?specs=p13nsims%3A" + mov.Id; - string json = await GetUrlDataAsync(recUrl); - return MatchAll(@"title=\\""(.*?)\\""", json); - } - /*******************************[ Helper Methods ]********************************/ - //Match single instance - private static string Match(string regex, string html, int i = 1) - { - var m = new Regex(regex, RegexOptions.Multiline).Match(html); - return m.Groups[i].Value.Trim(); - } - //Match all instances and return as List - private static List MatchAll(string regex, string html, int i = 1) - { - List list = new List(); - foreach (Match m in new Regex(regex, RegexOptions.Multiline).Matches(html)) - list.Add(m.Groups[i].Value.Trim()); - return list; - } - //Strip HTML Tags - private static string StripHTML(string inputString) - { - return Regex.Replace(inputString, @"<.*?>", string.Empty); - } - //Get URL Data - private static async Task GetUrlDataAsync(string url) - { - using (var http = new HttpClient()) - { - http.AddFakeHeaders(); - return await http.GetStringAsync(url); - } - } - } -} \ No newline at end of file diff --git a/src/NadekoBot/Modules/Searches/Searches.cs b/src/NadekoBot/Modules/Searches/Searches.cs index d18d94a9..8118e011 100644 --- a/src/NadekoBot/Modules/Searches/Searches.cs +++ b/src/NadekoBot/Modules/Searches/Searches.cs @@ -12,11 +12,11 @@ using System.Text.RegularExpressions; using System.Net; using Discord.WebSocket; using NadekoBot.Modules.Searches.Models; -using NadekoBot.Modules.Searches.IMDB; using System.Collections.Generic; using ImageProcessorCore; using NadekoBot.Extensions; using System.IO; +using NadekoBot.Modules.Searches.Commands.OMDB; namespace NadekoBot.Modules.Searches { @@ -66,10 +66,6 @@ $@"🌍 **Weather for** 【{obj["target"]}】 await channel.SendMessageAsync(result).ConfigureAwait(false); } - //todo move to omdb - // | - // v - //{"Title":"Shutter Island","Year":"2010","Rated":"R","Released":"19 Feb 2010","Runtime":"138 min","Genre":"Mystery, Thriller","Director":"Martin Scorsese","Writer":"Laeta Kalogridis (screenplay), Dennis Lehane (novel)","Actors":"Leonardo DiCaprio, Mark Ruffalo, Ben Kingsley, Max von Sydow","Plot":"In 1954, a U.S. marshal investigates the disappearance of a murderess who escaped from a hospital for the criminally insane.","Language":"English, German","Country":"USA","Awards":"8 wins & 59 nominations.","Poster":"https://images-na.ssl-images-amazon.com/images/M/MV5BMTMxMTIyNzMxMV5BMl5BanBnXkFtZTcwOTc4OTI3Mg@@._V1_SX300.jpg","Metascore":"63","imdbRating":"8.1","imdbVotes":"798,447","imdbID":"tt1130884","Type":"movie","Response":"True"} [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] public async Task Imdb(IUserMessage umsg, [Remainder] string query = null) @@ -78,21 +74,14 @@ $@"🌍 **Weather for** 【{obj["target"]}】 if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return; await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); - string result; - try - { - var movie = await ImdbScraper.ImdbScrape(query, true); - if (movie.Status) result = movie.ToString(); - else result = "Failed to find that movie."; - } - catch (Exception ex) + + var movie = await OmdbProvider.FindMovie(query); + if (movie == null) { await channel.SendMessageAsync("Failed to find that movie.").ConfigureAwait(false); - _log.Warn(ex); return; } - - await channel.SendMessageAsync(result.ToString()).ConfigureAwait(false); + await channel.SendMessageAsync(movie.ToString()).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 787a437f..0dfd896a 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -3111,7 +3111,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to imdb. + /// Looks up a localized string similar to imdb omdb. /// public static string imdb_cmd { get { @@ -3120,7 +3120,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Queries imdb for movies or series, show first result.. + /// Looks up a localized string similar to Queries omdb for movies or series, show first result.. /// public static string imdb_desc { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 55d78219..753dea51 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2044,10 +2044,10 @@ `~ani aquarion evol` - imdb + imdb omdb - Queries imdb for movies or series, show first result. + Queries omdb for movies or series, show first result. `~imdb Batman vs Superman` From 799b6cfae2dae267ee090e7e12e16e978719afc2 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 23:14:28 +0200 Subject: [PATCH 18/28] .roles updated string, missed af ile --- .../Searches/Commands/OMDB/OmdbProvider.cs | 46 +++++++++++++++++++ .../Resources/CommandStrings.Designer.cs | 4 +- src/NadekoBot/Resources/CommandStrings.resx | 4 +- 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs diff --git a/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs b/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs new file mode 100644 index 00000000..12032805 --- /dev/null +++ b/src/NadekoBot/Modules/Searches/Commands/OMDB/OmdbProvider.cs @@ -0,0 +1,46 @@ +ο»Ώusing Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Searches.Commands.OMDB +{ + public static class OmdbProvider + { + private const string queryUrl = "http://www.omdbapi.com/?t={0}&y=&plot=full&r=json"; + + public static async Task FindMovie(string name) + { + using (var http = new HttpClient()) + { + var res = await http.GetStringAsync(String.Format(queryUrl,name.Trim().Replace(' ','+'))).ConfigureAwait(false); + var movie = JsonConvert.DeserializeObject(res); + + movie.Poster = await NadekoBot.Google.ShortenUrl(movie.Poster); + return movie; + } + } + } + + public class OmdbMovie + { + public string Title { get; set; } + public string Year { get; set; } + public string ImdbRating { get; set; } + public string ImdbId { get; set; } + public string Genre { get; set; } + public string Plot { get; set; } + public string Poster { get; set; } + + public override string ToString() => +$@"`Title:` {Title} +`Year:` {Year} +`Rating:` {ImdbRating} +`Genre:` {Genre} +`Link:` http://www.imdb.com/title/{ImdbId}/ +`Plot:` {Plot}"; + } +} diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 0dfd896a..b2e6fb09 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -5550,7 +5550,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to List all roles on this server or a single user if specified.. + /// Looks up a localized string similar to List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page.. /// public static string roles_desc { get { @@ -5559,7 +5559,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to `.roles`. + /// Looks up a localized string similar to `.roles 2` or `.roles @Someone`. /// public static string roles_usage { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 753dea51..26a09eb1 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -940,10 +940,10 @@ roles - List all roles on this server or a single user if specified. + List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page. - `.roles` + `.roles 2` or `.roles @Someone` channeltopic ct From 13e8fe7caa2a79f2678d9c709d6cb9265c10f542 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sat, 15 Oct 2016 23:48:08 +0200 Subject: [PATCH 19/28] Fixed !!pl --- src/NadekoBot/Services/Impl/GoogleApiService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Services/Impl/GoogleApiService.cs b/src/NadekoBot/Services/Impl/GoogleApiService.cs index c1df1513..712dc4a9 100644 --- a/src/NadekoBot/Services/Impl/GoogleApiService.cs +++ b/src/NadekoBot/Services/Impl/GoogleApiService.cs @@ -119,7 +119,7 @@ namespace NadekoBot.Services.Impl count -= toGet; var query = yt.PlaylistItems.List("contentDetails"); - query.MaxResults = count; + query.MaxResults = toGet; query.PlaylistId = playlistId; query.PageToken = nextPageToken; From 00cb7621b58983dfb56c850f033c5624ad8310cf Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 00:15:30 +0200 Subject: [PATCH 20/28] asar description fix --- src/NadekoBot/Resources/CommandStrings.Designer.cs | 2 +- src/NadekoBot/Resources/CommandStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index b2e6fb09..48332af8 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -366,7 +366,7 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles.. + /// Looks up a localized string similar to Adds a role to the list of self-assignable roles.. /// public static string asar_desc { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 26a09eb1..426ab5f7 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -382,7 +382,7 @@ asar - Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles. + Adds a role to the list of self-assignable roles. `.asar Gamer` From bd3caa8407c27a6cfb87c1e8cc6265fee3672513 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 00:51:41 +0200 Subject: [PATCH 21/28] Fixed .convert f -> c --- src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs index d4f9df0c..12a4b8f3 100644 --- a/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs +++ b/src/NadekoBot/Modules/Utility/Commands/UnitConversion.cs @@ -148,10 +148,10 @@ namespace NadekoBot.Modules.Utility break; } //from Kelvin to target - switch (targetUnit.Triggers.First()) + switch (targetUnit.Triggers.First().ToUpperInvariant()) { case "C": - res = value - 273.15m; //celcius! + res = res - 273.15m; //celcius! break; case "F": res = res * (9m / 5m) - 459.67m; From 70e5337d9767453c72780daa7107fc295007f20b Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 01:11:20 +0200 Subject: [PATCH 22/28] Fixed music crash on !!n !!s and !!d? --- src/NadekoBot/Modules/Music/Classes/MusicControls.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs index fa4e2302..a11b63a5 100644 --- a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs +++ b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -111,7 +111,7 @@ namespace NadekoBot.Modules.Music.Classes if (CurrentSong == null) continue; - + OnStarted(this, CurrentSong); await CurrentSong.Play(audioClient, cancelToken); @@ -122,8 +122,9 @@ namespace NadekoBot.Modules.Music.Classes if (RepeatSong) AddSong(CurrentSong, 0); - + } + catch (OperationCanceledException) { } finally { if (!cancelToken.IsCancellationRequested) From 966b091c957467c6d9493609f8fd548c3c6e6461 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 01:37:29 +0200 Subject: [PATCH 23/28] !!d fix? --- src/NadekoBot/Modules/Music/Classes/MusicControls.cs | 3 ++- src/NadekoBot/Modules/Music/Music.cs | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs index a11b63a5..941a89b9 100644 --- a/src/NadekoBot/Modules/Music/Classes/MusicControls.cs +++ b/src/NadekoBot/Modules/Music/Classes/MusicControls.cs @@ -251,9 +251,10 @@ namespace NadekoBot.Modules.Music.Classes RepeatSong = false; Destroyed = true; playlist.Clear(); + + try { await audioClient.DisconnectAsync(); } catch { } if (!SongCancelSource.IsCancellationRequested) SongCancelSource.Cancel(); - await audioClient.DisconnectAsync(); }); } diff --git a/src/NadekoBot/Modules/Music/Music.cs b/src/NadekoBot/Modules/Music/Music.cs index 3e45fd48..61f04fba 100644 --- a/src/NadekoBot/Modules/Music/Music.cs +++ b/src/NadekoBot/Modules/Music/Music.cs @@ -72,9 +72,10 @@ namespace NadekoBot.Modules.Music var channel = (ITextChannel)umsg.Channel; MusicPlayer musicPlayer; - if (!MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; + if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) - musicPlayer.Destroy(); + if(MusicPlayers.TryRemove(channel.Guild.Id, out musicPlayer)) + musicPlayer.Destroy(); return Task.CompletedTask; } From 1e056e853db3fd3d734b062b6a9a617e471e915b Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 05:22:54 +0200 Subject: [PATCH 24/28] custom reaction now support %target% --- .../CustomReactions/CustomReactions.cs | 14 ++++++++-- .../Modules/CustomReactions/Extensions.cs | 28 +++++++++++++++---- 2 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs index 2e72533e..efbf1217 100644 --- a/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs +++ b/src/NadekoBot/Modules/CustomReactions/CustomReactions.cs @@ -47,14 +47,24 @@ namespace NadekoBot.Modules.CustomReactions GuildReactions.TryGetValue(channel.Guild.Id, out reactions); if (reactions != null && reactions.Any()) { - var reaction = reactions.Where(cr => cr.TriggerWithContext(umsg).Trim().ToLowerInvariant() == content).Shuffle().FirstOrDefault(); + var reaction = reactions.Where(cr => { + var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%"); + var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant(); + return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger); + }).Shuffle().FirstOrDefault(); if (reaction != null) { try { await channel.SendMessageAsync(reaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } return; } } - var greaction = GlobalReactions.Where(cr => cr.TriggerWithContext(umsg).Trim().ToLowerInvariant() == content).Shuffle().FirstOrDefault(); + var greaction = GlobalReactions.Where(cr => + { + var hasTarget = cr.Response.ToLowerInvariant().Contains("%target%"); + var trigger = cr.TriggerWithContext(umsg).Trim().ToLowerInvariant(); + return ((hasTarget && content.StartsWith(trigger + " ")) || content == trigger); + }).Shuffle().FirstOrDefault(); + if (greaction != null) { try { await channel.SendMessageAsync(greaction.ResponseWithContext(umsg)).ConfigureAwait(false); } catch { } diff --git a/src/NadekoBot/Modules/CustomReactions/Extensions.cs b/src/NadekoBot/Modules/CustomReactions/Extensions.cs index 147d6dcf..91c3db20 100644 --- a/src/NadekoBot/Modules/CustomReactions/Extensions.cs +++ b/src/NadekoBot/Modules/CustomReactions/Extensions.cs @@ -12,27 +12,45 @@ namespace NadekoBot.Modules.CustomReactions { public static class Extensions { + public static Dictionary> responsePlaceholders = new Dictionary>() + { + {"%target%", (ctx, trigger) => { return ctx.Content.ToLowerInvariant().Substring(trigger.Length); } } + }; + public static Dictionary> placeholders = new Dictionary>() { {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } }, {"%user%", (ctx) => { return ctx.Author.Mention; } }, - {"%target%", (ctx) => { return ctx.MentionedUsers.Shuffle().FirstOrDefault()?.Mention ?? "Nobody"; } }, {"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } } }; - private static string ResolveCRString(this string str, IUserMessage ctx) + private static string ResolveTriggerString(this string str, IUserMessage ctx) { foreach (var ph in placeholders) { - str = str.Replace(ph.Key, ph.Value(ctx)); + str = str.ToLowerInvariant().Replace(ph.Key, ph.Value(ctx)); + } + return str; + } + + private static string ResolveResponseString(this string str, IUserMessage ctx, string resolvedTrigger) + { + foreach (var ph in placeholders) + { + str = str.ToLowerInvariant().Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx)); + } + + foreach (var ph in responsePlaceholders) + { + str = str.ToLowerInvariant().Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, resolvedTrigger)); } return str; } public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx) - => cr.Trigger.ResolveCRString(ctx); + => cr.Trigger.ResolveTriggerString(ctx); public static string ResponseWithContext(this CustomReaction cr, IUserMessage ctx) - => cr.Response.ResolveCRString(ctx); + => cr.Response.ResolveResponseString(ctx, cr.Trigger.ResolveTriggerString(ctx)); } } From 83c5d9815c4c00be7d35ffecd709720229e08ac9 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 05:24:46 +0200 Subject: [PATCH 25/28] Commandlist updated --- docs/Commands List.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/Commands List.md b/docs/Commands List.md index 609ca5ed..e889dcac 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -53,7 +53,7 @@ Command and aliases | Description | Usage `.listplaying` `.lipl` | Lists all playing statuses with their corresponding number. | `.lipl` **Bot owner only.** `.removeplaying` `.rmpl` `.repl` | Removes a playing string on a given number. | `.rmpl` **Bot owner only.** `.slowmode` | Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. | `.slowmode` **Requires ManageMessages server permission.** -`.asar` | Adds a role, or list of roles separated by whitespace(use quotations for multiword roles) to the list of self-assignable roles. | `.asar Gamer` **Requires ManageRoles server permission.** +`.asar` | Adds a role to the list of self-assignable roles. | `.asar Gamer` **Requires ManageRoles server permission.** `.rsar` | Removes a specified role from the list of self-assignable roles. | `.rsar` **Requires ManageRoles server permission.** `.lsar` | Lists all self-assignable roles. | `.lsar` `.togglexclsar` `.tesar` | Toggles whether the self-assigned roles are exclusive. (So that any person can have only one of the self assignable roles) | `.tesar` **Requires ManageRoles server permission.** @@ -78,9 +78,9 @@ Command and aliases | Description | Usage `,startwar` `,sw` | Starts a war with a given number. | `,sw 15` `,listwar` `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | `,lw [war_number] or ,lw` `,claim` `,call` `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | `,call [war_number] [base_number] [optional_other_name]` -`,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf1 2 SomeGirl` -`,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf2 1 SomeGuy` -`,claimfinish` `,cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument finishes for someone else. | `,cf 1 Someone` +`,claimfinish1` `,cf1` | Finish your claim with 1 star if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf1 1` or `,cf1 1 5` +`,claimfinish2` `,cf2` | Finish your claim with 2 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf2 1` or `,cf2 1 5` +`,claimfinish` `,cf` | Finish your claim with 3 stars if you destroyed a base. First argument is the war number, optional second argument is a base number if you want to finish for someone else. | `,cf 1` or `,cf 1 5` `,endwar` `,ew` | Ends the war with a given index. | `,ew [war_number]` `,unclaim` `,ucall` `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | `,uc [war_number] [optional_other_name]` @@ -224,7 +224,7 @@ Command and aliases | Description | Usage ----------------|--------------|------- `~weather` `~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `~we Moscow RF` `~youtube` `~yt` | Searches youtubes and shows the first result | `~yt query` -`~imdb` | Queries imdb for movies or series, show first result. | `~imdb Batman vs Superman` +`~imdb` `~omdb` | Queries omdb for movies or series, show first result. | `~imdb Batman vs Superman` `~randomcat` `~meow` | Shows a random cat image. | `~meow` `~randomdog` `~woof` | Shows a random dog image. | `~woof` `~img` `~i` | Pulls the first image found using a search parameter. Use ~ir for different results. | `~i cute kitten` @@ -258,7 +258,7 @@ Command and aliases | Description | Usage `~osub` | Shows information about an osu beatmap. | `~osub https://osu.ppy.sh/s/127712` `~osu5` | Displays a user's top 5 plays. | `~osu5 Name` `~pokemon` `~poke` | Searches for a pokemon. | `~poke Sylveon` -`~pokemonability` `~pokeab` | Searches for a pokemon ability. | `~pokeab "water gun"` +`~pokemonability` `~pokeab` | Searches for a pokemon ability. | `~pokeab overgrow` `~hitbox` `~hb` | Notifies this channel when a certain user starts streaming. | `~hitbox SomeStreamer` **Requires ManageMessages server permission.** `~twitch` `~tw` | Notifies this channel when a certain user starts streaming. | `~twitch SomeStreamer` **Requires ManageMessages server permission.** `~beam` `~bm` | Notifies this channel when a certain user starts streaming. | `~beam SomeStreamer` **Requires ManageMessages server permission.** @@ -275,7 +275,7 @@ Command and aliases | Description | Usage `.userid` `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"` `.channelid` `.cid` | Shows current channel ID. | `.cid` `.serverid` `.sid` | Shows current server ID. | `.sid` -`.roles` | List all roles on this server or a single user if specified. | `.roles` +`.roles` | List roles on this server or a roles of a specific user if specified. Paginated. 20 roles per page. | `.roles 2` or `.roles @Someone` `.channeltopic` `.ct` | Sends current channel's topic as a message. | `.ct` `.stats` | Shows some basic stats for Nadeko. | `.stats` `.showemojis` `.se` | Shows a name and a link to every SPECIAL emoji in the message. | `.se A message full of SPECIALemojis` From 251730387d6796de89f60abb2d48375287e3d440 Mon Sep 17 00:00:00 2001 From: Jordan Fearnley Date: Sun, 16 Oct 2016 05:14:42 +0100 Subject: [PATCH 26/28] Custom Reactions update Updated to account for the re-introduction of `%target%` --- docs/Custom Reactions.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/Custom Reactions.md b/docs/Custom Reactions.md index d2e6f40d..1f2d4600 100644 --- a/docs/Custom Reactions.md +++ b/docs/Custom Reactions.md @@ -35,7 +35,6 @@ There are currently three different placeholders which we will look at, with mor |`%mention`|The `%mention%` placeholder is triggered when you type `@BotName` - It's important to note that if you've given the bot a custom nickname, this trigger won't work!|```.acr "Hello %mention%" I, %mention%, also say hello!```|Input: "Hello @BotName" Output: "I, @BotName, also say hello!"| |`%user%`|The `%user%` placeholder mentions the person who said the command|`.acr "Who am I?" You are %user%!`|Input: "Who am I?" Output: "You are @Username!"| |`%rng%`|The `%rng%` placeholder generates a random number between 0 and 10|`.acr "Random number" %rng%`|Input: "Random number" Output: "2"| - -[//]: # (|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase|`.acr "Say this: " %target%|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".|) +|`%target%`|The `%target%` placeholder is used to make Nadeko Mention another person or phrase, it is only supported as part of the response|`.acr "Say this: " %target%`|Input: "Say this: I, @BotName, am a parrot!". Output: "I, @BotName, am a parrot!".| Thanks to Nekai for being creative. <3 From d1219feddd3fc469ca1a812f7652cbba43e786a0 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 19:08:49 +0200 Subject: [PATCH 27/28] Slight mistake in poll commands --- src/NadekoBot/Modules/Games/Commands/PollCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs index 5daf7add..c31fc654 100644 --- a/src/NadekoBot/Modules/Games/Commands/PollCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PollCommands.cs @@ -128,7 +128,7 @@ namespace NadekoBot.Modules.Games return; if (participants.TryAdd(msg.Author, vote)) { - try { await (ch as ITextChannel).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); } catch { } + try { await ((IMessageChannel)ch).SendMessageAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); } catch { } } }); return Task.CompletedTask; From 2fad6487438311ed7cbc7c90ef85bdc4e3b237ac Mon Sep 17 00:00:00 2001 From: Kwoth Date: Sun, 16 Oct 2016 23:33:29 +0200 Subject: [PATCH 28/28] Fixed a typo, thanks to jvitkauskas --- src/NadekoBot/Modules/Music/Classes/Song.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Music/Classes/Song.cs b/src/NadekoBot/Modules/Music/Classes/Song.cs index 00757f92..db2c72f8 100644 --- a/src/NadekoBot/Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/Modules/Music/Classes/Song.cs @@ -53,7 +53,7 @@ namespace NadekoBot.Modules.Music.Classes private Logger _log; public int SkipTo { - get { return SkipTo; } + get { return skipTo; } set { skipTo = value; bytesSent = (ulong)skipTo * 3840 * 50;