From a39d136826dd9c28f7958c0f1c476f3b233cba47 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Thu, 9 Nov 2017 08:49:24 +0100 Subject: [PATCH 1/3] Added .raffleany - it will include users who are not online, too --- NadekoBot.Core/Modules/Gambling/Gambling.cs | 16 ++++++++++++++++ src/NadekoBot/data/command_strings.json | 10 +++++++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Gambling/Gambling.cs b/NadekoBot.Core/Modules/Gambling/Gambling.cs index 11e79fef..9defa74f 100644 --- a/NadekoBot.Core/Modules/Gambling/Gambling.cs +++ b/NadekoBot.Core/Modules/Gambling/Gambling.cs @@ -107,6 +107,22 @@ namespace NadekoBot.Modules.Gambling await Context.Channel.SendConfirmAsync("🎟 "+ GetText("raffled_user"), $"**{usr.Username}#{usr.Discriminator}**", footer: $"ID: {usr.Id}").ConfigureAwait(false); } + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task RaffleAny([Remainder] IRole role = null) + { + role = role ?? Context.Guild.EveryoneRole; + + var members = (await role.GetMembersAsync()); + var membersArray = members as IUser[] ?? members.ToArray(); + if (membersArray.Length == 0) + { + return; + } + var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; + await Context.Channel.SendConfirmAsync("🎟 " + GetText("raffled_user"), $"**{usr.Username}#{usr.Discriminator}**", footer: $"ID: {usr.Id}").ConfigureAwait(false); + } + [NadekoCommand, Usage, Description, Aliases] [Priority(1)] public async Task Cash([Remainder] IUser user = null) diff --git a/src/NadekoBot/data/command_strings.json b/src/NadekoBot/data/command_strings.json index eff19a26..3b44ba3c 100644 --- a/src/NadekoBot/data/command_strings.json +++ b/src/NadekoBot/data/command_strings.json @@ -940,12 +940,20 @@ }, "raffle": { "Cmd": "raffle", - "Desc": "Prints a name and ID of a random user from the online list from the (optional) role.", + "Desc": "Prints a name and ID of a random online user from the server, or from the online user in the specified role.", "Usage": [ "{0}raffle", "{0}raffle RoleName" ] }, + "raffleany": { + "Cmd": "raffleany", + "Desc": "Prints a name and ID of a random user from the server, or from the specified role.", + "Usage": [ + "{0}raffleany", + "{0}raffleany RoleName" + ] + }, "give": { "Cmd": "give", "Desc": "Give someone a certain amount of currency.", From ae3c4561943f5396d595dae2dd0ddc5c2118de4f Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Thu, 9 Nov 2017 13:44:36 +0100 Subject: [PATCH 2/3] .masskill command added (bot owner only) --- .../Modules/Administration/Administration.cs | 4 +- .../Administration/UserPunishCommands.cs | 99 ++++++++++++++++++- .../Repositories/ICurrencyRepository.cs | 1 + .../Repositories/Impl/CurrencyRepository.cs | 5 + .../Services/Impl/BotConfigProvider.cs | 5 +- NadekoBot.Core/Services/NadekoBot.cs | 2 +- .../_strings/ResponseStrings.en-US.json | 5 +- src/NadekoBot/data/command_strings.json | 7 ++ 8 files changed, 119 insertions(+), 9 deletions(-) diff --git a/NadekoBot.Core/Modules/Administration/Administration.cs b/NadekoBot.Core/Modules/Administration/Administration.cs index 9f3c92c9..bafd390a 100644 --- a/NadekoBot.Core/Modules/Administration/Administration.cs +++ b/NadekoBot.Core/Modules/Administration/Administration.cs @@ -261,7 +261,7 @@ namespace NadekoBot.Modules.Administration public async Task CreatVoiChanl([Remainder] string channelName) { var ch = await Context.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false); - await ReplyConfirmLocalized("createvoich",Format.Bold(ch.Name)).ConfigureAwait(false); + await ReplyConfirmLocalized("createvoich", Format.Bold(ch.Name)).ConfigureAwait(false); } [NadekoCommand, Usage, Description, Aliases] @@ -312,7 +312,7 @@ namespace NadekoBot.Modules.Administration [RequireUserPermission(GuildPermission.MentionEveryone)] public async Task MentionRole(params IRole[] roles) { - string send = "❕" +GetText("menrole",Context.User.Mention); + string send = "❕" + GetText("menrole", Context.User.Mention); foreach (var role in roles) { send += $"\n**{role.Name}**\n"; diff --git a/NadekoBot.Core/Modules/Administration/UserPunishCommands.cs b/NadekoBot.Core/Modules/Administration/UserPunishCommands.cs index 1303e4e2..35f5629f 100644 --- a/NadekoBot.Core/Modules/Administration/UserPunishCommands.cs +++ b/NadekoBot.Core/Modules/Administration/UserPunishCommands.cs @@ -18,10 +18,15 @@ namespace NadekoBot.Modules.Administration public class UserPunishCommands : NadekoSubmodule { private readonly DbService _db; + private readonly CurrencyService _cs; + private readonly IBotConfigProvider _bc; - public UserPunishCommands(DbService db, MuteService muteService) + public UserPunishCommands(DbService db, MuteService muteService, + CurrencyService cs, IBotConfigProvider bc) { _db = db; + _cs = cs; + _bc = bc; } [NadekoCommand, Usage, Description, Aliases] @@ -101,7 +106,7 @@ namespace NadekoBot.Modules.Administration var embed = new EmbedBuilder().WithOkColor() .WithTitle(GetText("warnlog_for", (Context.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString())) - .WithFooter(efb => efb.WithText(GetText("page", page + 1))); + .WithFooter(efb => efb.WithText(GetText("page", page + 1))); if (!warnings.Any()) { @@ -202,8 +207,8 @@ namespace NadekoBot.Modules.Administration uow.Complete(); } - await ReplyConfirmLocalized("warn_punish_set", - Format.Bold(punish.ToString()), + await ReplyConfirmLocalized("warn_punish_set", + Format.Bold(punish.ToString()), Format.Bold(number.ToString())).ConfigureAwait(false); } @@ -397,6 +402,92 @@ namespace NadekoBot.Modules.Administration .AddField(efb => efb.WithName("ID").WithValue(user.Id.ToString()).WithIsInline(true))) .ConfigureAwait(false); } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + [RequireUserPermission(GuildPermission.BanMembers)] + [RequireBotPermission(GuildPermission.BanMembers)] + [OwnerOnly] + public async Task MassKill([Remainder] string people) + { + if (string.IsNullOrWhiteSpace(people)) + return; + + var gusers = ((SocketGuild)Context.Guild).Users; + //get user objects and reasons + var bans = people.Split("\n") + .Select(x => + { + var split = x.Trim().Split(" "); + + var reason = string.Join(" ", split.Skip(1)); + + if (ulong.TryParse(split[0], out var id)) + return (Original: split[0], Id: id, Reason: reason); + + return (Original: split[0], + Id: gusers + .FirstOrDefault(u => u.ToString().ToLowerInvariant() == x) + ?.Id, + Reason: reason); + }) + .ToArray(); + + //if user is null, means that person couldn't be found + var missing = bans + .Where(x => !x.Id.HasValue) + .ToArray(); + + //get only data for found users + var found = bans + .Where(x => x.Id.HasValue) + .Select(x => x.Id.Value) + .ToArray(); + + var missStr = string.Join("\n", missing); + if (string.IsNullOrWhiteSpace(missStr)) + missStr = "-"; + + //send a message but don't wait for it + var banningMessageTask = Context.Channel.EmbedAsync(new EmbedBuilder() + .WithDescription(GetText("mass_kill_in_progress", bans.Length)) + .AddField(GetText("invalid", missing.Length), missStr) + .WithOkColor()); + + using (var uow = _db.UnitOfWork) + { + var bc = uow.BotConfig.GetOrCreate(set => set.Include(x => x.Blacklist)); + //blacklist the users + bc.Blacklist.AddRange(found.Select(x => + new BlacklistItem + { + ItemId = x, + Type = BlacklistType.User, + })); + //clear their currencies + uow.Currency.RemoveFromMany(found.Select(x => (long)x).ToList()); + uow.Complete(); + } + + _bc.Reload(); + + //do the banning + await Task.WhenAll(bans + .Where(x => x.Id.HasValue) + .Select(x => Context.Guild.AddBanAsync(x.Id.Value, 7, x.Reason, new RequestOptions() { + RetryMode = RetryMode.AlwaysRetry, + }))) + .ConfigureAwait(false); + + //wait for the message and edit it + var banningMessage = await banningMessageTask.ConfigureAwait(false); + + await banningMessage.ModifyAsync(x => x.Embed = new EmbedBuilder() + .WithDescription(GetText("mass_kill_completed", bans.Length)) + .AddField(GetText("invalid", missing.Length), missStr) + .WithOkColor() + .Build()).ConfigureAwait(false); + } } } } diff --git a/NadekoBot.Core/Services/Database/Repositories/ICurrencyRepository.cs b/NadekoBot.Core/Services/Database/Repositories/ICurrencyRepository.cs index 51f35cf0..0a1f484b 100644 --- a/NadekoBot.Core/Services/Database/Repositories/ICurrencyRepository.cs +++ b/NadekoBot.Core/Services/Database/Repositories/ICurrencyRepository.cs @@ -9,5 +9,6 @@ namespace NadekoBot.Core.Services.Database.Repositories long GetUserCurrency(ulong userId); bool TryUpdateState(ulong userId, long change); IEnumerable GetTopRichest(int count, int skip); + void RemoveFromMany(List ids); } } diff --git a/NadekoBot.Core/Services/Database/Repositories/Impl/CurrencyRepository.cs b/NadekoBot.Core/Services/Database/Repositories/Impl/CurrencyRepository.cs index e21c63a1..bbc0e8f1 100644 --- a/NadekoBot.Core/Services/Database/Repositories/Impl/CurrencyRepository.cs +++ b/NadekoBot.Core/Services/Database/Repositories/Impl/CurrencyRepository.cs @@ -33,6 +33,11 @@ namespace NadekoBot.Core.Services.Database.Repositories.Impl public long GetUserCurrency(ulong userId) => GetOrCreate(userId).Amount; + public void RemoveFromMany(List ids) + { + _set.RemoveRange(_set.Where(x => ids.Contains((long)x.UserId))); + } + public bool TryUpdateState(ulong userId, long change) { var cur = GetOrCreate(userId); diff --git a/NadekoBot.Core/Services/Impl/BotConfigProvider.cs b/NadekoBot.Core/Services/Impl/BotConfigProvider.cs index c9152299..cdbc4d36 100644 --- a/NadekoBot.Core/Services/Impl/BotConfigProvider.cs +++ b/NadekoBot.Core/Services/Impl/BotConfigProvider.cs @@ -6,11 +6,14 @@ namespace NadekoBot.Core.Services.Impl public class BotConfigProvider : IBotConfigProvider { private readonly DbService _db; + private readonly IDataCache _cache; + public BotConfig BotConfig { get; private set; } - public BotConfigProvider(DbService db, BotConfig bc) + public BotConfigProvider(DbService db, BotConfig bc, IDataCache cache) { _db = db; + _cache = cache; BotConfig = bc; } diff --git a/NadekoBot.Core/Services/NadekoBot.cs b/NadekoBot.Core/Services/NadekoBot.cs index e4ee216d..af42ae0a 100644 --- a/NadekoBot.Core/Services/NadekoBot.cs +++ b/NadekoBot.Core/Services/NadekoBot.cs @@ -129,7 +129,7 @@ namespace NadekoBot { AllGuildConfigs = uow.GuildConfigs.GetAllGuildConfigs(startingGuildIdList).ToImmutableArray(); - IBotConfigProvider botConfigProvider = new BotConfigProvider(_db, _botConfig); + IBotConfigProvider botConfigProvider = new BotConfigProvider(_db, _botConfig, Cache); //initialize Services Services = new NServiceProvider() diff --git a/src/NadekoBot/_strings/ResponseStrings.en-US.json b/src/NadekoBot/_strings/ResponseStrings.en-US.json index 6cca1fea..c92aaf75 100644 --- a/src/NadekoBot/_strings/ResponseStrings.en-US.json +++ b/src/NadekoBot/_strings/ResponseStrings.en-US.json @@ -919,5 +919,8 @@ "searches_crypto_not_found": "Cryptocurrency with that name was not found.", "searches_did_you_mean": "Did you mean {0}?", "administration_self_assign_level_req": "Self assignable role {0} now requires at least server level {1}.", - "administration_self_assign_not_level": "That self-assignable role requires at least server level {0}." + "administration_self_assign_not_level": "That self-assignable role requires at least server level {0}.", + "administration_invalid": "Invalid / Can't be found ({0})", + "administration_mass_kill_in_progress": "Mass Banning and Blacklisting of {0} users is in progress...", + "administration_mass_kill_completed": "Mass Banning and Blacklisting of {0} users is complete." } \ No newline at end of file diff --git a/src/NadekoBot/data/command_strings.json b/src/NadekoBot/data/command_strings.json index 3b44ba3c..c38b05b1 100644 --- a/src/NadekoBot/data/command_strings.json +++ b/src/NadekoBot/data/command_strings.json @@ -3113,5 +3113,12 @@ "usage": [ "{0}rlr 5 SomeRole" ] + }, + "masskill": { + "cmd": "masskill", + "desc": "Specify a new-line separated list of `userid reason`. You can use Username#discrim instead of UserId. Specified users will be banned from the current server, blacklisted from the bot, and have all of their flowers taken away.", + "usage": [ + "{0}masskill BadPerson#1234 Toxic person" + ] } } From 86805bafa9b5d846784554bdcd0de6195ae79f1c Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 10 Nov 2017 13:35:39 +0100 Subject: [PATCH 3/3] Fixed .crypto errors? Closes #1816 --- .../Searches/Services/SearchesService.cs | 31 +++++++++++++------ 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs index 6876dfea..2755cfb1 100644 --- a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs +++ b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs @@ -53,10 +53,28 @@ namespace NadekoBot.Modules.Searches.Services private readonly ConcurrentDictionary> _blacklistedTags = new ConcurrentDictionary>(); private readonly Timer _t; + private readonly SemaphoreSlim _cryptoLock = new SemaphoreSlim(1, 1); public async Task CryptoData() { - var data = await _cache.Redis.GetDatabase() - .StringGetAsync("crypto_data").ConfigureAwait(false); + string data; + var r = _cache.Redis.GetDatabase(); + await _cryptoLock.WaitAsync().ConfigureAwait(false); + try + { + data = await r.StringGetAsync("crypto_data").ConfigureAwait(false); + + if (data == null) + { + data = await Http.GetStringAsync("https://api.coinmarketcap.com/v1/ticker/") + .ConfigureAwait(false); + + await r.StringSetAsync("crypto_data", data, TimeSpan.FromHours(6)).ConfigureAwait(false); + } + } + finally + { + _cryptoLock.Release(); + } return JsonConvert.DeserializeObject(data); } @@ -121,14 +139,7 @@ namespace NadekoBot.Modules.Searches.Services var r = _cache.Redis.GetDatabase(); try { - var data = (string)(await r.StringGetAsync("crypto_data").ConfigureAwait(false)); - if (data == null) - { - data = await Http.GetStringAsync("https://api.coinmarketcap.com/v1/ticker/") - .ConfigureAwait(false); - - await r.StringSetAsync("crypto_data", data, TimeSpan.FromHours(6)).ConfigureAwait(false); - } + } catch (Exception ex) {