From 6a90b0a406d4f548a5d7e51a5a018e2575caacf8 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Mon, 15 May 2017 14:32:40 +0200 Subject: [PATCH 01/22] >gc is bot owner only on public nadeko now --- .../Modules/Games/Commands/PlantAndPickCommands.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs index 44eb474a..bffa5624 100644 --- a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs @@ -181,10 +181,13 @@ namespace NadekoBot.Modules.Games return old; }); } -#if !GLOBAL_NADEKO + [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequireUserPermission(GuildPermission.ManageMessages)] +#if GLOBAL_NADEKO + [OwnerOnly] +#endif public async Task GenCurrency() { var channel = (ITextChannel)Context.Channel; @@ -218,7 +221,6 @@ namespace NadekoBot.Modules.Games await ReplyConfirmLocalized("curgen_disabled").ConfigureAwait(false); } } -#endif private static KeyValuePair> GetRandomCurrencyImage() { From d4be914cde3e9910a0b0fc746510c027c4d02683 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 15:08:30 +0200 Subject: [PATCH 02/22] few string fixes to docs --- docs/Commands List.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Commands List.md b/docs/Commands List.md index 513edd6a..f472c1a3 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -94,11 +94,11 @@ Commands and aliases | Description | Usage `.reloadimages` | Reloads images bot is using. Safe to use even when bot is being used heavily. **Bot owner only** | `.reloadimages` `.greetdel` `.grdel` | Sets the time it takes (in seconds) for greet messages to be auto-deleted. Set it to 0 to disable automatic deletion. **Requires ManageServer server permission.** | `.greetdel 0` or `.greetdel 30` `.greet` | Toggles anouncements on the current channel when someone joins the server. **Requires ManageServer server permission.** | `.greet` -`.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.` +`.greetmsg` | Sets a new join announcement message which will be shown in the server's channel. Type `%user%` if you want to mention the new member. Using it with no message will show the current greet message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetmsg Welcome, %user%.` `.greetdm` | Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). **Requires ManageServer server permission.** | `.greetdm` -`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`. +`.greetdmmsg` | Sets a new join announcement message which will be sent to the user who joined. Type `%user%` if you want to mention the new member. Using it with no message will show the current DM greet message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.greetdmmsg Welcome to the server, %user%`. `.bye` | Toggles anouncements on the current channel when someone leaves the server. **Requires ManageServer server permission.** | `.bye` -`.byemsg` | Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.` +`.byemsg` | Sets a new leave announcement message. Type `%user%` if you want to show the name the user who left. Type `%id%` to show id. Using this command with no message will show the current bye message. You can use embed json from instead of a regular text, if you want the message to be embedded. **Requires ManageServer server permission.** | `.byemsg %user% has left.` `.byedel` | Sets the time it takes (in seconds) for bye messages to be auto-deleted. Set it to `0` to disable automatic deletion. **Requires ManageServer server permission.** | `.byedel 0` or `.byedel 30` `.warn` | Warns a user. **Requires BanMembers server permission.** | `.warn @b1nzy Very rude person` `.warnlog` | See a list of warnings of a certain user. **Requires BanMembers server permission.** | `.warnlog @b1nzy` From cf9d58a7ebdce5e9b83049b94d4ad89333f2cfe8 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 16:46:03 +0200 Subject: [PATCH 03/22] .antispam is a bit smarter now, it will take messages from the last 30 minutes into consideration --- .../Commands/ProtectionCommands.cs | 59 +++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/ProtectionCommands.cs b/src/NadekoBot/Modules/Administration/Commands/ProtectionCommands.cs index 23f1eaf0..e89f14ba 100644 --- a/src/NadekoBot/Modules/Administration/Commands/ProtectionCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/ProtectionCommands.cs @@ -10,6 +10,8 @@ using System; using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; +using System.Threading; +using System.Collections.Generic; namespace NadekoBot.Modules.Administration { @@ -35,30 +37,51 @@ namespace NadekoBot.Modules.Administration = new ConcurrentDictionary(); } - public class UserSpamStats + public class UserSpamStats : IDisposable { - public int Count { get; set; } + public int Count => timers.Count; public string LastMessage { get; set; } - public UserSpamStats(string msg) - { - Count = 1; - LastMessage = msg.ToUpperInvariant(); - } + private ConcurrentQueue timers { get; } + public UserSpamStats(IUserMessage msg) + { + LastMessage = msg.Content.ToUpperInvariant(); + timers = new ConcurrentQueue(); + + ApplyNextMessage(msg); + } + + private readonly object applyLock = new object(); public void ApplyNextMessage(IUserMessage message) { - var upperMsg = message.Content.ToUpperInvariant(); - if (upperMsg != LastMessage || (string.IsNullOrWhiteSpace(upperMsg) && message.Attachments.Any())) - { - LastMessage = upperMsg; - Count = 0; - } - else - { - Count++; + lock(applyLock){ + var upperMsg = message.Content.ToUpperInvariant(); + if (upperMsg != LastMessage || (string.IsNullOrWhiteSpace(upperMsg) && message.Attachments.Any())) + { + LastMessage = upperMsg; + //todo c#7 + Timer old; + while(timers.TryDequeue(out old)) + old.Change(Timeout.Infinite, Timeout.Infinite); + } + var t = new Timer((_) => { + //todo c#7 + Timer __; + if(timers.TryDequeue(out __)) + __.Change(Timeout.Infinite, Timeout.Infinite); + }, null, TimeSpan.FromMinutes(30), TimeSpan.FromMinutes(30)); + timers.Enqueue(t); } } + + public void Dispose() + { + //todo c#7 + Timer old; + while(timers.TryDequeue(out old)) + old.Change(Timeout.Infinite, Timeout.Infinite); + } } [Group] @@ -112,7 +135,7 @@ namespace NadekoBot.Modules.Administration })) return; - var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, new UserSpamStats(msg.Content), + var stats = spamSettings.UserStats.AddOrUpdate(msg.Author.Id, (id) => new UserSpamStats(msg), (id, old) => { old.ApplyNextMessage(msg); return old; @@ -122,6 +145,7 @@ namespace NadekoBot.Modules.Administration { if (spamSettings.UserStats.TryRemove(msg.Author.Id, out stats)) { + stats.Dispose(); await PunishUsers(spamSettings.AntiSpamSettings.Action, ProtectionType.Spamming, (IGuildUser)msg.Author) .ConfigureAwait(false); } @@ -317,6 +341,7 @@ namespace NadekoBot.Modules.Administration AntiSpamStats throwaway; if (_antiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway)) { + throwaway.UserStats.ForEach(x => x.Value.Dispose()); using (var uow = DbHandler.UnitOfWork()) { var gc = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.AntiSpamSetting) From 749c63aec3e14ef6e225e1ef3130dc5c28b34a6a Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 18:53:10 +0200 Subject: [PATCH 04/22] you can now divorce people using their id --- .../Modules/Gambling/Commands/WaifuClaimCommands.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs b/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs index c1d16578..3822c8c5 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs @@ -188,9 +188,15 @@ namespace NadekoBot.Modules.Gambling private static readonly TimeSpan _divorceLimit = TimeSpan.FromHours(6); [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] - public async Task Divorce([Remainder]IUser target) + [Priority(1)] + public Task Divorce([Remainder]IUser target) => Divorce(target.Id); + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + [Priority(0)] + public async Task Divorce([Remainder]ulong targetId) { - if (target.Id == Context.User.Id) + if (targetId == Context.User.Id) return; DivorceResult result; @@ -199,7 +205,7 @@ namespace NadekoBot.Modules.Gambling WaifuInfo w = null; using (var uow = DbHandler.UnitOfWork()) { - w = uow.Waifus.ByWaifuUserId(target.Id); + w = uow.Waifus.ByWaifuUserId(targetId); var now = DateTime.UtcNow; if (w?.Claimer == null || w.Claimer.UserId != Context.User.Id) result = DivorceResult.NotYourWife; From fbbcd1ffc425cceae11b725b1f4f7c608aee8cd7 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 21:52:41 +0200 Subject: [PATCH 05/22] Grammar mistake --- src/NadekoBot/Resources/CommandStrings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index a201f829..532b8a2e 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -418,7 +418,7 @@ iamnot iamn - Removes a role to you that you choose. Role must be on a list of self-assignable roles. + Removes a specified role from you. Role must be on a list of self-assignable roles. `{0}iamn Gamer` From 7ac94e907f3b1d50154d296f0d1b659c6b7c7116 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 22:00:55 +0200 Subject: [PATCH 06/22] .warnp will now correctly overwrite old setting on the same number of warnings --- .../Commands/UserPunishCommands.cs | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs b/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs index f794d47a..ad28d5ae 100644 --- a/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs @@ -214,25 +214,15 @@ namespace NadekoBot.Modules.Administration using (var uow = DbHandler.UnitOfWork()) { - var ps = uow.GuildConfigs.For(Context.Guild.Id).WarnPunishments; - var p = ps.FirstOrDefault(x => x.Count == number); + var ps = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(x => x.WarnPunishments)).WarnPunishments; + ps.RemoveAll(x => x.Count == number); - if (p == null) + ps.Add(new WarningPunishment() { - ps.Add(new WarningPunishment() - { - Count = number, - Punishment = punish, - Time = time, - }); - } - else - { - p.Count = number; - p.Punishment = punish; - p.Time = time; - uow._context.Update(p); - } + Count = number, + Punishment = punish, + Time = time, + }); uow.Complete(); } From cad2834106bb313c530edca5980e1c4e204b73d2 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 22:03:09 +0200 Subject: [PATCH 07/22] softban punishment now correctly prunes messages from the last 7 days --- .../Modules/Administration/Commands/UserPunishCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs b/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs index ad28d5ae..f0189683 100644 --- a/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs +++ b/src/NadekoBot/Modules/Administration/Commands/UserPunishCommands.cs @@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Administration await guild.AddBanAsync(user).ConfigureAwait(false); break; case PunishmentAction.Softban: - await guild.AddBanAsync(user).ConfigureAwait(false); + await guild.AddBanAsync(user, 7).ConfigureAwait(false); try { await guild.RemoveBanAsync(user).ConfigureAwait(false); From 78c3fbf55abb04067a6faf3d4e9e2e2f18e820ba Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 22:06:50 +0200 Subject: [PATCH 08/22] Fixed descriptions --- src/NadekoBot/Resources/CommandStrings.resx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 532b8a2e..ffc84a59 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -3442,19 +3442,19 @@ globalcommand gcmd - Enables or disables a command from use on all servers. + Toggles whether a command can be used on any server. - `{0}gcmd ` + `{0}gcmd .stats` globalmodule gmod - Enable or disable a module from use on all servers. + Toggles whether a module can be used on any server. - `{0}gmod nsfw disable` + `{0}gmod nsfw` listglobalperms lgp From 515dfc1eb2142083f24e4cce69d22b0a6135592e Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 22:50:30 +0200 Subject: [PATCH 09/22] .lsar will now show if it cleans up some deleted roles, and show the proper count --- .../Administration/Commands/SelfAssignedRolesCommand.cs | 3 ++- src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs index e13a278f..160004d8 100644 --- a/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs +++ b/src/NadekoBot/Modules/Administration/Commands/SelfAssignedRolesCommand.cs @@ -108,7 +108,6 @@ namespace NadekoBot.Modules.Administration using (var uow = DbHandler.UnitOfWork()) { var roleModels = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id).ToList(); - roleCnt = roleModels.Count; msg.AppendLine(); foreach (var roleModel in roleModels) @@ -116,11 +115,13 @@ namespace NadekoBot.Modules.Administration var role = Context.Guild.Roles.FirstOrDefault(r => r.Id == roleModel.RoleId); if (role == null) { + toRemove.Add(roleModel); uow.SelfAssignedRoles.Remove(roleModel); } else { msg.Append($"**{role.Name}**, "); + roleCnt++; } } foreach (var role in toRemove) diff --git a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs index bffa5624..640422f7 100644 --- a/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/PlantAndPickCommands.cs @@ -82,9 +82,9 @@ namespace NadekoBot.Modules.Games var prefix = NadekoBot.ModulePrefixes[typeof(Games).Name]; var toSend = dropAmount == 1 ? GetLocalText(channel, "curgen_sn", NadekoBot.BotConfig.CurrencySign) - + GetLocalText(channel, "pick_sn", prefix) + + " " + GetLocalText(channel, "pick_sn", prefix) : GetLocalText(channel, "curgen_pl", dropAmount, NadekoBot.BotConfig.CurrencySign) - + GetLocalText(channel, "pick_pl", prefix); + + " " + GetLocalText(channel, "pick_pl", prefix); var file = GetRandomCurrencyImage(); using (var fileStream = file.Value.ToStream()) { From f26fa4dfcc96d5adb3140154fdbf0277521eac2a Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 22:57:56 +0200 Subject: [PATCH 10/22] fixed error message in the console when >pick is used while .delmsgoncmd is enabled --- src/NadekoBot/Modules/Administration/Administration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index 0e175083..70d8ca12 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -41,7 +41,7 @@ namespace NadekoBot.Modules.Administration var channel = msg.Channel as SocketTextChannel; if (channel == null) return; - if (deleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune") + if (deleteMessagesOnCommand.Contains(channel.Guild.Id) && cmd.Name != "prune" && cmd.Name != "pick") await msg.DeleteAsync().ConfigureAwait(false); } catch (Exception ex) From cd7f2cd63d633d7ba70d9082b652df547b0b9948 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:02:23 +0200 Subject: [PATCH 11/22] fixed an issue with ghost words in ;lfw --- src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs index 9eea8a50..fe2cf36d 100644 --- a/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs +++ b/src/NadekoBot/Modules/Permissions/Commands/FilterCommands.cs @@ -190,7 +190,7 @@ namespace NadekoBot.Modules.Permissions { var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FilteredWords)); - removed = config.FilteredWords.RemoveWhere(fw => fw.Word == word); + removed = config.FilteredWords.RemoveWhere(fw => fw.Word.Trim().ToLowerInvariant() == word); if (removed == 0) config.FilteredWords.Add(new Services.Database.Models.FilteredWord() { Word = word }); From c45f7bc9ab991cfff89c2ef3b4864c458c783335 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:22:32 +0200 Subject: [PATCH 12/22] Guild owners can now use .setrole on anyone --- src/NadekoBot/Modules/Administration/Administration.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index 70d8ca12..8fd0bf6c 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -118,7 +118,7 @@ namespace NadekoBot.Modules.Administration { var guser = (IGuildUser)Context.User; var maxRole = guser.GetRoles().Max(x => x.Position); - if (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position)) + if ((Context.User.Id != Context.Guild.OwnerId) && (maxRole < role.Position || maxRole <= usr.GetRoles().Max(x => x.Position))) return; try { From 12147da93bcaea05f93a8a7bac3abf15e723dea1 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:28:44 +0200 Subject: [PATCH 13/22] by its id, not by its color :facepalm: --- src/NadekoBot/Resources/CommandStrings.resx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index ffc84a59..94462d97 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -3388,7 +3388,7 @@ shoprem shoprm - Removes an item from the shop by its color. + Removes an item from the shop by its ID. shop From 1cd7852674358866c427377f43a1c8fdd3f6338e Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:37:41 +0200 Subject: [PATCH 14/22] sanitized queuer names in music --- src/NadekoBot/Modules/Music/Classes/Song.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Music/Classes/Song.cs b/src/NadekoBot/Modules/Music/Classes/Song.cs index c7e933eb..1f7fd67a 100644 --- a/src/NadekoBot/Modules/Music/Classes/Song.cs +++ b/src/NadekoBot/Modules/Music/Classes/Song.cs @@ -26,7 +26,11 @@ namespace NadekoBot.Modules.Music.Classes { public SongInfo SongInfo { get; } public MusicPlayer MusicPlayer { get; set; } - public string QueuerName { get; set; } + + private string _queuerName; + public string QueuerName { get{ + return Discord.Format.Sanitize(_queuerName); + } set { _queuerName = value; } } public TimeSpan TotalTime { get; set; } = TimeSpan.Zero; public TimeSpan CurrentTime => TimeSpan.FromSeconds(bytesSent / (float)_frameBytes / (1000 / (float)_milliseconds)); From 631e17a569fc145c6c34fa01cfe1738626e77b0f Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:57:25 +0200 Subject: [PATCH 15/22] Fixed an issue where using .prune wouldn't work if there was a message older than 2 weeks in the last 100 messages. Also some string fixes --- .../Modules/Administration/Administration.cs | 16 +++++++++++----- .../Gambling/Commands/WaifuClaimCommands.cs | 2 ++ src/NadekoBot/Resources/CommandStrings.resx | 4 ++-- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/NadekoBot/Modules/Administration/Administration.cs b/src/NadekoBot/Modules/Administration/Administration.cs index 8fd0bf6c..780fb29a 100644 --- a/src/NadekoBot/Modules/Administration/Administration.cs +++ b/src/NadekoBot/Modules/Administration/Administration.cs @@ -381,12 +381,14 @@ namespace NadekoBot.Modules.Administration { var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false); - var enumerable = (await Context.Channel.GetMessagesAsync().Flatten()).AsEnumerable(); - enumerable = enumerable.Where(x => x.Author.Id == user.Id); + var enumerable = (await Context.Channel.GetMessagesAsync().Flatten()) + .Where(x => x.Author.Id == user.Id && DateTime.Now - x.CreatedAt < twoWeeks); await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false); Context.Message.DeleteAfter(3); } + + private TimeSpan twoWeeks => TimeSpan.FromDays(14); // prune x [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] @@ -399,7 +401,8 @@ namespace NadekoBot.Modules.Administration return; await Context.Message.DeleteAsync().ConfigureAwait(false); int limit = (count < 100) ? count + 1 : 100; - var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false)); + var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false)) + .Where(x => DateTime.Now - x.CreatedAt < twoWeeks); if (enumerable.FirstOrDefault()?.Id == Context.Message.Id) enumerable = enumerable.Skip(1).ToArray(); else @@ -422,7 +425,8 @@ namespace NadekoBot.Modules.Administration count += 1; int limit = (count < 100) ? count : 100; - var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten()).Where(m => m.Author == user); + var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten()) + .Where(m => m.Author == user && DateTime.Now - m.CreatedAt < twoWeeks); await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false); Context.Message.DeleteAfter(3); @@ -437,7 +441,9 @@ namespace NadekoBot.Modules.Administration foreach (var role in roles) { send += $"\n**{role.Name}**\n"; - send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.GetRoles().Contains(role)).Take(50).Select(u => u.Mention)); + send += string.Join(", ", (await Context.Guild.GetUsersAsync()) + .Where(u => u.GetRoles().Contains(role)) + .Take(50).Select(u => u.Mention)); } while (send.Length > 2000) diff --git a/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs b/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs index 3822c8c5..a37ef8cf 100644 --- a/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Commands/WaifuClaimCommands.cs @@ -173,6 +173,8 @@ namespace NadekoBot.Modules.Gambling amount + CurrencySign); if (w.Affinity?.UserId == Context.User.Id) msg += "\n" + GetText("waifu_fulfilled", target, w.Price + CurrencySign); + else + msg = " " + msg; await Context.Channel.SendConfirmAsync(Context.User.Mention + msg).ConfigureAwait(false); } diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 94462d97..055e5207 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2038,7 +2038,7 @@ chucknorris cn - Shows a random Chuck Norris joke from <http://tambal.azurewebsites.net/joke/random> + Shows a random Chuck Norris joke from <http://api.icndb.com/jokes/random/> `{0}cn` @@ -3406,7 +3406,7 @@ Toggles if this role is displayed in the sidebar or not - `{0}rh Guests true` or `{0}rh "Space Wizards" true + `{0}rh Guests true` or `{0}rh "Space Wizards" true` buy From 69dc07b3fba94794e71cd29f9cfa229ddfd5284c Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Tue, 16 May 2017 23:58:21 +0200 Subject: [PATCH 16/22] ping now works in dms --- src/NadekoBot/Modules/Utility/Utility.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NadekoBot/Modules/Utility/Utility.cs b/src/NadekoBot/Modules/Utility/Utility.cs index 0e2eba1b..741fa006 100644 --- a/src/NadekoBot/Modules/Utility/Utility.cs +++ b/src/NadekoBot/Modules/Utility/Utility.cs @@ -503,7 +503,6 @@ namespace NadekoBot.Modules.Utility await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), title, title).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] - [RequireContext(ContextType.Guild)] public async Task Ping() { var sw = Stopwatch.StartNew(); From a08b2fb749af32c0c4fb3b89e28921b4655007bf Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 00:03:38 +0200 Subject: [PATCH 17/22] race_no_race string added --- src/NadekoBot/Resources/ResponseStrings.resx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/NadekoBot/Resources/ResponseStrings.resx b/src/NadekoBot/Resources/ResponseStrings.resx index 70142b88..1fb27df8 100644 --- a/src/NadekoBot/Resources/ResponseStrings.resx +++ b/src/NadekoBot/Resources/ResponseStrings.resx @@ -1220,6 +1220,9 @@ Don't forget to leave your discord name or id in the message. You've already joined this race! + + This Animal Race is full! + Total: {0} Average: {1} From 080ad1fd9d62f6707dbd61562fd99b0930527654 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 00:04:08 +0200 Subject: [PATCH 18/22] Commandlist update --- docs/Commands List.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/Commands List.md b/docs/Commands List.md index f472c1a3..0021e0cc 100644 --- a/docs/Commands List.md +++ b/docs/Commands List.md @@ -26,7 +26,7 @@ Commands and aliases | Description | Usage `.renamerole` `.renr` | Renames a role. The role you are renaming must be lower than bot's highest role. **Requires ManageRoles server permission.** | `.renr "First role" SecondRole` `.removeallroles` `.rar` | Removes all roles from a mentioned user. **Requires ManageRoles server permission.** | `.rar @User` `.createrole` `.cr` | Creates a role with a given name. **Requires ManageRoles server permission.** | `.cr Awesome Role` -`.rolehoist` `.rh` | Toggles if this role is displayed in the sidebar or not **Requires ManageRoles server permission.** | `.rh Guests true` or `.rh "Space Wizards" true +`.rolehoist` `.rh` | Toggles if this role is displayed in the sidebar or not **Requires ManageRoles server permission.** | `.rh Guests true` or `.rh "Space Wizards" true` `.rolecolor` `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. **Requires ManageRoles server permission.** | `.rc Admin 255 200 100` or `.rc Admin ffba55` `.deafen` `.deaf` | Deafens mentioned user or users. **Requires DeafenMembers server permission.** | `.deaf "@Someguy"` or `.deaf "@Someguy" "@Someguy"` `.undeafen` `.undef` | Undeafens mentioned user or users. **Requires DeafenMembers server permission.** | `.undef "@Someguy"` or `.undef "@Someguy" "@Someguy"` @@ -73,7 +73,7 @@ Commands and aliases | Description | Usage `.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) **Requires ManageRoles server permission.** | `.tesar` `.iam` | Adds a role to you that you choose. Role must be on a list of self-assignable roles. | `.iam Gamer` -`.iamnot` `.iamn` | Removes a role to you that you choose. Role must be on a list of self-assignable roles. | `.iamn Gamer` +`.iamnot` `.iamn` | Removes a specified role from you. Role must be on a list of self-assignable roles. | `.iamn Gamer` `.scadd` | Adds a command to the list of commands which will be executed automatically in the current channel, in the order they were added in, by the bot when it startups up. **Bot owner only** | `.scadd .stats` `.sclist` | Lists all startup commands in the order they will be executed in. **Bot owner only** | `.sclist` `.wait` | Used only as a startup command. Waits a certain number of miliseconds before continuing the execution of the following startup commands. **Bot owner only** | `.wait 3000` @@ -170,7 +170,7 @@ Commands and aliases | Description | Usage `$buy` | Buys an item from the shop on a given index. If buying items, make sure that the bot can DM you. | `$buy 2` `$shopadd` | Adds an item to the shop by specifying type price and name. Available types are role and list. **Requires Administrator server permission.** | `$shopadd role 1000 Rich` `$shoplistadd` | Adds an item to the list of items for sale in the shop entry given the index. You usually want to run this command in the secret channel, so that the unique items are not leaked. **Requires Administrator server permission.** | `$shoplistadd 1 Uni-que-Steam-Key` -`$shoprem` `$shoprm` | Removes an item from the shop by its color. **Requires Administrator server permission.** | `$shoprm 1` +`$shoprem` `$shoprm` | Removes an item from the shop by its ID. **Requires Administrator server permission.** | `$shoprm 1` `$slotstats` | Shows the total stats of the slot command for this bot's session. **Bot owner only** | `$slotstats` `$slottest` | Tests to see how much slots payout for X number of plays. **Bot owner only** | `$slottest 1000` `$slot` | Play Nadeko slots. Max bet is 9999. 1.5 second cooldown per user. | `$slot 5` @@ -311,8 +311,8 @@ Commands and aliases | Description | Usage `;fw` | Adds or removes (if it exists) a word from the list of filtered words. Use`;sfw` or `;cfw` to toggle filtering. | `;fw poop` `;lstfilterwords` `;lfw` | Shows a list of filtered words. | `;lfw` `;listglobalperms` `;lgp` | Lists global permissions set by the bot owner. **Bot owner only** | `;lgp` -`;globalmodule` `;gmod` | Enable or disable a module from use on all servers. **Bot owner only** | `;gmod nsfw disable` -`;globalcommand` `;gcmd` | Enables or disables a command from use on all servers. **Bot owner only** | `;gcmd ` +`;globalmodule` `;gmod` | Toggles whether a module can be used on any server. **Bot owner only** | `;gmod nsfw` +`;globalcommand` `;gcmd` | Toggles whether a command can be used on any server. **Bot owner only** | `;gcmd .stats` ###### [Back to ToC](#table-of-contents) @@ -362,7 +362,7 @@ Commands and aliases | Description | Usage `~manga` `~mang` `~mq` | Queries anilist for a manga and shows the first result. | `~mq Shingeki no kyojin` `~yomama` `~ym` | Shows a random joke from | `~ym` `~randjoke` `~rj` | Shows a random joke from | `~rj` -`~chucknorris` `~cn` | Shows a random Chuck Norris joke from | `~cn` +`~chucknorris` `~cn` | Shows a random Chuck Norris joke from | `~cn` `~wowjoke` | Get one of Kwoth's penultimate WoW jokes. | `~wowjoke` `~magicitem` `~mi` | Shows a random magic item from | `~mi` `~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/ | `~memelist` From bc78f70655c4d558125687e1e35932a65ce66d83 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 00:42:30 +0200 Subject: [PATCH 19/22] you can no longer remind channels you don't have access to --- src/NadekoBot/Modules/Utility/Commands/Remind.cs | 15 +++++++++++++-- src/NadekoBot/Resources/ResponseStrings.resx | 3 +++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/NadekoBot/Modules/Utility/Commands/Remind.cs b/src/NadekoBot/Modules/Utility/Commands/Remind.cs index 8da05b89..4ffd9469 100644 --- a/src/NadekoBot/Modules/Utility/Commands/Remind.cs +++ b/src/NadekoBot/Modules/Utility/Commands/Remind.cs @@ -123,8 +123,19 @@ namespace NadekoBot.Modules.Utility [RequireContext(ContextType.Guild)] [RequireUserPermission(GuildPermission.ManageMessages)] [Priority(0)] - public Task Remind(ITextChannel channel, string timeStr, [Remainder] string message) => - RemindInternal(channel.Id, false, timeStr, message); + public async Task Remind(ITextChannel channel, string timeStr, [Remainder] string message) + { + var perms = ((IGuildUser)Context.User).GetPermissions((ITextChannel)channel); + if (!perms.SendMessages || !perms.ReadMessages) + { + await ReplyErrorLocalized("cant_read_or_send").ConfigureAwait(false); + return; + } + else + { + var _ = RemindInternal(channel.Id, false, timeStr, message).ConfigureAwait(false); + } + } public async Task RemindInternal(ulong targetId, bool isPrivate, string timeStr, [Remainder] string message) { diff --git a/src/NadekoBot/Resources/ResponseStrings.resx b/src/NadekoBot/Resources/ResponseStrings.resx index 1fb27df8..ccb11a5e 100644 --- a/src/NadekoBot/Resources/ResponseStrings.resx +++ b/src/NadekoBot/Resources/ResponseStrings.resx @@ -2105,6 +2105,9 @@ Owner ID: {2} I will remind {0} to {1} in {2} `({3:d.M.yyyy.} at {4:HH:mm})` + + You can't read from or send messages to that channel. + Not a valid time format. Check the commandlist. From 3a96e272b4e077c6397f451ce4806a8f40b74b35 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 00:55:59 +0200 Subject: [PATCH 20/22] Bot owners can no longer blacklist other bot owners --- .../Modules/Permissions/Commands/BlacklistCommands.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/NadekoBot/Modules/Permissions/Commands/BlacklistCommands.cs b/src/NadekoBot/Modules/Permissions/Commands/BlacklistCommands.cs index 4278d5a4..7cc8e62f 100644 --- a/src/NadekoBot/Modules/Permissions/Commands/BlacklistCommands.cs +++ b/src/NadekoBot/Modules/Permissions/Commands/BlacklistCommands.cs @@ -65,6 +65,9 @@ namespace NadekoBot.Modules.Permissions private async Task Blacklist(AddRemove action, ulong id, BlacklistType type) { + if(action == AddRemove.Add && NadekoBot.Credentials.OwnerIds.Contains(id)) + return; + using (var uow = DbHandler.UnitOfWork()) { if (action == AddRemove.Add) From cbc527346ab5d32c6c6345f2a813ba8239c144de Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 00:57:10 +0200 Subject: [PATCH 21/22] string fix --- src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs b/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs index 96e06a4e..7e965fa8 100644 --- a/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs +++ b/src/NadekoBot/Modules/Utility/Commands/InfoCommands.cs @@ -126,7 +126,7 @@ namespace NadekoBot.Modules.Utility } await Context.Channel.EmbedAsync(new EmbedBuilder() - .WithTitle(GetText("activity_page", page)) + .WithTitle(GetText("activity_page", page + 1)) .WithOkColor() .WithFooter(efb => efb.WithText(GetText("activity_users_total", NadekoBot.CommandHandler.UserMessagesSent.Count))) From 6dd0cb281e479eb6c367378b141cf2daa730146d Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Wed, 17 May 2017 14:02:18 +0200 Subject: [PATCH 22/22] fixed hangman images, and some strings --- .../Games/Commands/Hangman/HangmanGame.cs | 2 +- src/NadekoBot/Resources/ResponseStrings.resx | 3 + .../data/{hangman2.json => hangman3.json} | 68 +++++++++---------- 3 files changed, 38 insertions(+), 35 deletions(-) rename src/NadekoBot/data/{hangman2.json => hangman3.json} (99%) diff --git a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs index 0f2f3bda..5c329925 100644 --- a/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs +++ b/src/NadekoBot/Modules/Games/Commands/Hangman/HangmanGame.cs @@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Games.Hangman { public class HangmanTermPool { - const string termsPath = "data/hangman2.json"; + const string termsPath = "data/hangman3.json"; public static IReadOnlyDictionary data { get; } static HangmanTermPool() { diff --git a/src/NadekoBot/Resources/ResponseStrings.resx b/src/NadekoBot/Resources/ResponseStrings.resx index ccb11a5e..17d7cfef 100644 --- a/src/NadekoBot/Resources/ResponseStrings.resx +++ b/src/NadekoBot/Resources/ResponseStrings.resx @@ -2085,6 +2085,9 @@ Owner ID: {2} Page {0} of quotes + No quotes found on that page. + + No quotes found matching the quote ID specified. diff --git a/src/NadekoBot/data/hangman2.json b/src/NadekoBot/data/hangman3.json similarity index 99% rename from src/NadekoBot/data/hangman2.json rename to src/NadekoBot/data/hangman3.json index b93e6aa5..a671657f 100644 --- a/src/NadekoBot/data/hangman2.json +++ b/src/NadekoBot/data/hangman3.json @@ -772,7 +772,7 @@ }, { "Word": "Antigua and Barbuda", - "ImageUrl": "https://www.randomlists.com/img/national-flags/antigua-and-barbuda.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/antigua_and_barbuda.gif" }, { "Word": "Argentina", @@ -836,7 +836,7 @@ }, { "Word": "Bosnia and Herzegovina", - "ImageUrl": "https://www.randomlists.com/img/national-flags/bosnia-and-herzegovina.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/bosnia_and_herzegovina.gif" }, { "Word": "Botswana", @@ -856,7 +856,7 @@ }, { "Word": "Burkina Faso", - "ImageUrl": "https://www.randomlists.com/img/national-flags/burkina-faso.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/burkina_faso.gif" }, { "Word": "Burma", @@ -880,11 +880,11 @@ }, { "Word": "Cape Verde", - "ImageUrl": "https://www.randomlists.com/img/national-flags/cape-verde.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/cape_verde.gif" }, { "Word": "Central African Republic", - "ImageUrl": "https://www.randomlists.com/img/national-flags/central-african-republic.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/central_african_republic.gif" }, { "Word": "Chad", @@ -912,7 +912,7 @@ }, { "Word": "Costa Rica", - "ImageUrl": "https://www.randomlists.com/img/national-flags/costa-rica.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/costa_rica.gif" }, { "Word": "Croatia", @@ -928,7 +928,7 @@ }, { "Word": "Czech Republic", - "ImageUrl": "https://www.randomlists.com/img/national-flags/czech-republic.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/czech_republic.gif" }, { "Word": "Denmark", @@ -944,11 +944,11 @@ }, { "Word": "Dominican Republic", - "ImageUrl": "https://www.randomlists.com/img/national-flags/dominican-republic.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/dominican_republic.gif" }, { "Word": "East Timor", - "ImageUrl": "https://www.randomlists.com/img/national-flags/east-timor.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/east_timor.gif" }, { "Word": "Ecuador", @@ -960,7 +960,7 @@ }, { "Word": "El Salvador", - "ImageUrl": "https://www.randomlists.com/img/national-flags/el-salvador.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/el_salvador.gif" }, { "Word": "England", @@ -968,7 +968,7 @@ }, { "Word": "Equatorial Guinea", - "ImageUrl": "https://www.randomlists.com/img/national-flags/equatorial-guinea.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/equatorial_guinea.gif" }, { "Word": "Eritrea", @@ -1032,7 +1032,7 @@ }, { "Word": "Guinea-Bissau", - "ImageUrl": "https://www.randomlists.com/img/national-flags/guinea-bissau.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/guinea_bissau.gif" }, { "Word": "Guyana", @@ -1048,7 +1048,7 @@ }, { "Word": "Hong Kong", - "ImageUrl": "https://www.randomlists.com/img/national-flags/hong-kong.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/hong_kong.gif" }, { "Word": "Hungary", @@ -1080,7 +1080,7 @@ }, { "Word": "Isle of Man", - "ImageUrl": "https://www.randomlists.com/img/national-flags/isle-of-man.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/isle_of_man.gif" }, { "Word": "Israel", @@ -1116,11 +1116,11 @@ }, { "Word": "North Korea", - "ImageUrl": "https://www.randomlists.com/img/national-flags/korea-north.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/korea_north.gif" }, { "Word": "South Korea", - "ImageUrl": "https://www.randomlists.com/img/national-flags/korea-south.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/korea_south.gif" }, { "Word": "Kosovo", @@ -1204,7 +1204,7 @@ }, { "Word": "Marshall Islands", - "ImageUrl": "https://www.randomlists.com/img/national-flags/marshall-islands.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/marshall_islands.gif" }, { "Word": "Mauritania", @@ -1264,7 +1264,7 @@ }, { "Word": "New Zealand", - "ImageUrl": "https://www.randomlists.com/img/national-flags/new-zealand.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/new_zealand.gif" }, { "Word": "Nicaragua", @@ -1300,7 +1300,7 @@ }, { "Word": "Papua New Guinea", - "ImageUrl": "https://www.randomlists.com/img/national-flags/papua-new-guinea.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/papua_new_guinea.gif" }, { "Word": "Paraguay", @@ -1324,7 +1324,7 @@ }, { "Word": "Puerto Rico", - "ImageUrl": "https://www.randomlists.com/img/national-flags/puerto-rico.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/puerto_rico.gif" }, { "Word": "Qatar", @@ -1344,15 +1344,15 @@ }, { "Word": "Saint Kitts and Nevis", - "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-kitts-and-nevis.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_kitts_and_nevis.gif" }, { "Word": "Saint Lucia", - "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-lucia.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_lucia.gif" }, { "Word": "Saint Vincent and the Grenadines", - "ImageUrl": "https://www.randomlists.com/img/national-flags/saint-vincent-and-the-grenadines.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/saint_vincent_and_the_grenadines.gif" }, { "Word": "Samoa", @@ -1360,11 +1360,11 @@ }, { "Word": "San Marino", - "ImageUrl": "https://www.randomlists.com/img/national-flags/san-marino.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/san_marino.gif" }, { "Word": "Saudi Arabia", - "ImageUrl": "https://www.randomlists.com/img/national-flags/saudi-arabia.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/saudi_arabia.gif" }, { "Word": "Scotland", @@ -1384,7 +1384,7 @@ }, { "Word": "Sierra Leone", - "ImageUrl": "https://www.randomlists.com/img/national-flags/sierra-leone.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/sierra_leone.gif" }, { "Word": "Singapore", @@ -1400,7 +1400,7 @@ }, { "Word": "Solomon Islands", - "ImageUrl": "https://www.randomlists.com/img/national-flags/solomon-islands.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/solomon_islands.gif" }, { "Word": "Somalia", @@ -1408,7 +1408,7 @@ }, { "Word": "South Africa", - "ImageUrl": "https://www.randomlists.com/img/national-flags/south-africa.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/south_africa.gif" }, { "Word": "Spain", @@ -1416,7 +1416,7 @@ }, { "Word": "Sri Lanka", - "ImageUrl": "https://www.randomlists.com/img/national-flags/sri-lanka.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/sri_lanka.gif" }, { "Word": "Sudan", @@ -1468,7 +1468,7 @@ }, { "Word": "Trinidad and Tobago", - "ImageUrl": "https://www.randomlists.com/img/national-flags/trinidad-and-tobago.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/trinidad_and_tobago.gif" }, { "Word": "Tunisia", @@ -1496,15 +1496,15 @@ }, { "Word": "United Arab Emirates", - "ImageUrl": "https://www.randomlists.com/img/national-flags/united-arab-emirates.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/united_arab_emirates.gif" }, { "Word": "United Kingdom", - "ImageUrl": "https://www.randomlists.com/img/national-flags/united-kingdom.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/united_kingdom.gif" }, { "Word": "United States of America", - "ImageUrl": "https://www.randomlists.com/img/national-flags/united-states-of-america.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/united_states_of_america.gif" }, { "Word": "Uruguay", @@ -1524,7 +1524,7 @@ }, { "Word": "Vatican City", - "ImageUrl": "https://www.randomlists.com/img/national-flags/vatican-city.gif" + "ImageUrl": "https://www.randomlists.com/img/national-flags/vatican_city.gif" }, { "Word": "Venezuela",