From fcb6da8dcae2992a95ce64fa6b7a83d5061a1619 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 3 Nov 2017 11:29:15 +0100 Subject: [PATCH 1/5] wip cooldowns --- NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs index ef59635e..a47f54b9 100644 --- a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs @@ -59,12 +59,14 @@ namespace NadekoBot.Modules.Gambling private readonly IBotConfigProvider _bc; private readonly CurrencyService _cs; private readonly DbService _db; + private readonly IDataCache _cache; - public WaifuClaimCommands(IBotConfigProvider bc, CurrencyService cs, DbService db) + public WaifuClaimCommands(IDataCache cache, IBotConfigProvider bc, CurrencyService cs, DbService db) { _bc = bc; _cs = cs; _db = db; + _cache = cache; } [NadekoCommand, Usage, Description, Aliases] @@ -317,6 +319,10 @@ namespace NadekoBot.Modules.Gambling if (w?.Affinity?.UserId == u?.Id) { //todo don't let people change affinity on different shards + } + else if (_cache.Redis.TryAddAffinityCooldown(Context.User.Id)) + { + } else if (_service.AffinityCooldowns.AddOrUpdate(Context.User.Id, now, From 0dbd60b5ac530ef1133305e1f80551f1e531a20b Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 3 Nov 2017 12:35:27 +0100 Subject: [PATCH 2/5] .affinity cooldown will now work properly on multiple shards --- .../Modules/Gambling/WaifuClaimCommands.cs | 21 +++++-------------- NadekoBot.Core/Services/IDataCache.cs | 1 + NadekoBot.Core/Services/Impl/RedisCache.cs | 13 ++++++++++++ 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs index a47f54b9..caceb4f5 100644 --- a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs @@ -54,8 +54,6 @@ namespace NadekoBot.Modules.Gambling NotEnoughFunds, InsufficientAmount } - - private static readonly TimeSpan _affinityLimit = TimeSpan.FromMinutes(30); private readonly IBotConfigProvider _bc; private readonly CurrencyService _cs; private readonly DbService _db; @@ -309,8 +307,7 @@ namespace NadekoBot.Modules.Gambling } DiscordUser oldAff = null; var sucess = false; - var cooldown = false; - var difference = TimeSpan.Zero; + TimeSpan? remaining = null; using (var uow = _db.UnitOfWork) { var w = uow.Waifus.ByWaifuUserId(Context.User.Id); @@ -320,15 +317,8 @@ namespace NadekoBot.Modules.Gambling { //todo don't let people change affinity on different shards } - else if (_cache.Redis.TryAddAffinityCooldown(Context.User.Id)) + else if (!_cache.TryAddAffinityCooldown(Context.User.Id, out remaining)) { - - } - else if (_service.AffinityCooldowns.AddOrUpdate(Context.User.Id, - now, - (key, old) => ((difference = now.Subtract(old)) > _affinityLimit) ? now : old) != now) - { - cooldown = true; } else if (w == null) { @@ -370,12 +360,11 @@ namespace NadekoBot.Modules.Gambling } if (!sucess) { - if (cooldown) + if (remaining != null) { - var remaining = _affinityLimit.Subtract(difference); await ReplyErrorLocalized("waifu_affinity_cooldown", - Format.Bold(((int)remaining.TotalHours).ToString()), - Format.Bold(remaining.Minutes.ToString())).ConfigureAwait(false); + Format.Bold(((int)remaining?.TotalHours).ToString()), + Format.Bold(remaining?.Minutes.ToString())).ConfigureAwait(false); } else { diff --git a/NadekoBot.Core/Services/IDataCache.cs b/NadekoBot.Core/Services/IDataCache.cs index 20215b20..157f1e7f 100644 --- a/NadekoBot.Core/Services/IDataCache.cs +++ b/NadekoBot.Core/Services/IDataCache.cs @@ -15,5 +15,6 @@ namespace NadekoBot.Core.Services Task SetNovelDataAsync(string link, string data); TimeSpan? AddTimelyClaim(ulong id, int period); void RemoveAllTimelyClaims(); + bool TryAddAffinityCooldown(ulong userId, out TimeSpan? time); } } diff --git a/NadekoBot.Core/Services/Impl/RedisCache.cs b/NadekoBot.Core/Services/Impl/RedisCache.cs index 97a097cd..493bd0b0 100644 --- a/NadekoBot.Core/Services/Impl/RedisCache.cs +++ b/NadekoBot.Core/Services/Impl/RedisCache.cs @@ -83,5 +83,18 @@ namespace NadekoBot.Core.Services.Impl _db.KeyDelete(k, CommandFlags.FireAndForget); } } + + public bool TryAddAffinityCooldown(ulong userId, out TimeSpan? time) + { + time = _db.KeyTimeToLive($"{_redisKey}_affinity_{userId}"); + if (time == null) + { + time = TimeSpan.FromMinutes(30); + _db.StringSet($"{_redisKey}_affinity_{userId}", true); + _db.KeyExpire($"{_redisKey}_affinity_{userId}", time); + return true; + } + return false; + } } } From 1c157ddfc1345644622839a6290657161574bb5a Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 3 Nov 2017 12:46:51 +0100 Subject: [PATCH 3/5] .divorce cooldown now properly works on multiple shards --- .../Modules/Gambling/Services/WaifuService.cs | 5 ----- .../Modules/Gambling/WaifuClaimCommands.cs | 13 ++++--------- NadekoBot.Core/Services/IDataCache.cs | 1 + NadekoBot.Core/Services/Impl/RedisCache.cs | 13 +++++++++++++ 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/NadekoBot.Core/Modules/Gambling/Services/WaifuService.cs b/NadekoBot.Core/Modules/Gambling/Services/WaifuService.cs index f9274c52..d2fbdcef 100644 --- a/NadekoBot.Core/Modules/Gambling/Services/WaifuService.cs +++ b/NadekoBot.Core/Modules/Gambling/Services/WaifuService.cs @@ -1,7 +1,5 @@ using Discord; using NadekoBot.Core.Services; -using System; -using System.Collections.Concurrent; using System.Threading.Tasks; namespace NadekoBot.Modules.Gambling.Services @@ -11,9 +9,6 @@ namespace NadekoBot.Modules.Gambling.Services private readonly DbService _db; private readonly CurrencyService _cs; - public ConcurrentDictionary DivorceCooldowns { get; } = new ConcurrentDictionary(); - public ConcurrentDictionary AffinityCooldowns { get; } = new ConcurrentDictionary(); - public WaifuService(DbService db, CurrencyService cs) { _db = db; diff --git a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs index caceb4f5..272719f0 100644 --- a/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/WaifuClaimCommands.cs @@ -213,8 +213,6 @@ namespace NadekoBot.Modules.Gambling Cooldown } - - private static readonly TimeSpan _divorceLimit = TimeSpan.FromHours(6); [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [Priority(0)] @@ -229,7 +227,7 @@ namespace NadekoBot.Modules.Gambling return; DivorceResult result; - var difference = TimeSpan.Zero; + TimeSpan? remaining = null; var amount = 0; WaifuInfo w = null; using (var uow = _db.UnitOfWork) @@ -238,9 +236,7 @@ namespace NadekoBot.Modules.Gambling var now = DateTime.UtcNow; if (w?.Claimer == null || w.Claimer.UserId != Context.User.Id) result = DivorceResult.NotYourWife; - else if (_service.DivorceCooldowns.AddOrUpdate(Context.User.Id, - now, - (key, old) => ((difference = now.Subtract(old)) > _divorceLimit) ? now : old) != now) + else if (!_cache.TryAddDivorceCooldown(Context.User.Id, out remaining)) { result = DivorceResult.Cooldown; } @@ -289,10 +285,9 @@ namespace NadekoBot.Modules.Gambling } else { - var remaining = _divorceLimit.Subtract(difference); await ReplyErrorLocalized("waifu_recent_divorce", - Format.Bold(((int)remaining.TotalHours).ToString()), - Format.Bold(remaining.Minutes.ToString())).ConfigureAwait(false); + Format.Bold(((int)remaining?.TotalHours).ToString()), + Format.Bold(remaining?.Minutes.ToString())).ConfigureAwait(false); } } diff --git a/NadekoBot.Core/Services/IDataCache.cs b/NadekoBot.Core/Services/IDataCache.cs index 157f1e7f..5c114dc7 100644 --- a/NadekoBot.Core/Services/IDataCache.cs +++ b/NadekoBot.Core/Services/IDataCache.cs @@ -16,5 +16,6 @@ namespace NadekoBot.Core.Services TimeSpan? AddTimelyClaim(ulong id, int period); void RemoveAllTimelyClaims(); bool TryAddAffinityCooldown(ulong userId, out TimeSpan? time); + bool TryAddDivorceCooldown(ulong userId, out TimeSpan? time); } } diff --git a/NadekoBot.Core/Services/Impl/RedisCache.cs b/NadekoBot.Core/Services/Impl/RedisCache.cs index 493bd0b0..f5f5cc98 100644 --- a/NadekoBot.Core/Services/Impl/RedisCache.cs +++ b/NadekoBot.Core/Services/Impl/RedisCache.cs @@ -96,5 +96,18 @@ namespace NadekoBot.Core.Services.Impl } return false; } + + public bool TryAddDivorceCooldown(ulong userId, out TimeSpan? time) + { + time = _db.KeyTimeToLive($"{_redisKey}_divorce_{userId}"); + if (time == null) + { + time = TimeSpan.FromHours(6); + _db.StringSet($"{_redisKey}_divorce_{userId}", true); + _db.KeyExpire($"{_redisKey}_divorce_{userId}", time); + return true; + } + return false; + } } } From 4b7b44f0d42b9344a1c57fa0f75b65f34a7890d7 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Fri, 3 Nov 2017 13:21:35 +0100 Subject: [PATCH 4/5] wip images service --- NadekoBot.Core/Services/Impl/ImagesService.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/NadekoBot.Core/Services/Impl/ImagesService.cs b/NadekoBot.Core/Services/Impl/ImagesService.cs index 50d432a8..8c8c0128 100644 --- a/NadekoBot.Core/Services/Impl/ImagesService.cs +++ b/NadekoBot.Core/Services/Impl/ImagesService.cs @@ -9,6 +9,7 @@ namespace NadekoBot.Core.Services.Impl //todo move everything to redis public class ImagesService : IImagesService { + private readonly IDataCache _cache; private readonly Logger _log; private const string _basePath = "data/images/"; @@ -51,10 +52,14 @@ namespace NadekoBot.Core.Services.Impl public ImmutableArray Rip { get; private set; } public ImmutableArray FlowerCircle { get; private set; } - public ImagesService() + public ImagesService(IDataCache cache, int shardId) { + _cache = cache; _log = LogManager.GetCurrentClassLogger(); - this.Reload(); + if (shardId == 0) + { + this.Reload(); + } } public void Reload() From 607decfbcc45b216f2ffdcc2b8d0d8f4ba0a6859 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sun, 5 Nov 2017 13:28:08 +0100 Subject: [PATCH 5/5] local image caching to redis done? --- .../Modules/Administration/SelfCommands.cs | 7 +- .../Administration/Services/SelfService.cs | 6 +- .../Modules/Gambling/DiceRollCommands.cs | 23 +- .../Modules/Gambling/FlipCoinCommands.cs | 6 +- .../Modules/Gambling/SlotCommands.cs | 6 +- .../Modules/Games/Common/GirlRating.cs | 6 +- NadekoBot.Core/Modules/Games/Games.cs | 6 +- .../Modules/Games/PlantAndPickCommands.cs | 13 +- .../Modules/Games/Services/GamesService.cs | 15 +- .../Searches/Services/SearchesService.cs | 6 +- .../Modules/Xp/Services/XpService.cs | 9 +- NadekoBot.Core/Services/IDataCache.cs | 2 + NadekoBot.Core/Services/IImageCache.cs | 27 +++ NadekoBot.Core/Services/IImagesService.cs | 27 --- NadekoBot.Core/Services/Impl/ImagesService.cs | 223 ++++++++++++++---- NadekoBot.Core/Services/Impl/RedisCache.cs | 4 + NadekoBot.Core/Services/ShardsCoordinator.cs | 2 + 17 files changed, 267 insertions(+), 121 deletions(-) create mode 100644 NadekoBot.Core/Services/IImageCache.cs delete mode 100644 NadekoBot.Core/Services/IImagesService.cs diff --git a/NadekoBot.Core/Modules/Administration/SelfCommands.cs b/NadekoBot.Core/Modules/Administration/SelfCommands.cs index 1a83a454..38fe17de 100644 --- a/NadekoBot.Core/Modules/Administration/SelfCommands.cs +++ b/NadekoBot.Core/Modules/Administration/SelfCommands.cs @@ -29,19 +29,18 @@ namespace NadekoBot.Modules.Administration private static readonly object _locker = new object(); private readonly DiscordSocketClient _client; - private readonly IImagesService _images; + private readonly IImageCache _images; private readonly IBotConfigProvider _bc; private readonly NadekoBot _bot; private readonly IBotCredentials _creds; private readonly IDataCache _cache; public SelfCommands(DbService db, NadekoBot bot, DiscordSocketClient client, - IImagesService images, IBotConfigProvider bc, - IBotCredentials creds, IDataCache cache) + IBotConfigProvider bc, IBotCredentials creds, IDataCache cache) { _db = db; _client = client; - _images = images; + _images = cache.LocalImages; _bc = bc; _bot = bot; _creds = creds; diff --git a/NadekoBot.Core/Modules/Administration/Services/SelfService.cs b/NadekoBot.Core/Modules/Administration/Services/SelfService.cs index b6efd5ee..157c35e4 100644 --- a/NadekoBot.Core/Modules/Administration/Services/SelfService.cs +++ b/NadekoBot.Core/Modules/Administration/Services/SelfService.cs @@ -30,11 +30,11 @@ namespace NadekoBot.Modules.Administration.Services private readonly IBotCredentials _creds; private ImmutableArray> ownerChannels = new ImmutableArray>(); private readonly IBotConfigProvider _bc; - private readonly IImagesService _imgs; + private readonly IImageCache _imgs; public SelfService(DiscordSocketClient client, NadekoBot bot, CommandHandler cmdHandler, DbService db, IBotConfigProvider bc, ILocalization localization, NadekoStrings strings, IBotCredentials creds, - IDataCache cache, IImagesService imgs) + IDataCache cache) { _redis = cache.Redis; _bot = bot; @@ -46,7 +46,7 @@ namespace NadekoBot.Modules.Administration.Services _client = client; _creds = creds; _bc = bc; - _imgs = imgs; + _imgs = cache.LocalImages; var sub = _redis.GetSubscriber(); sub.Subscribe(_creds.RedisKey() + "_reload_images", diff --git a/NadekoBot.Core/Modules/Gambling/DiceRollCommands.cs b/NadekoBot.Core/Modules/Gambling/DiceRollCommands.cs index 08fd7f4f..5458768b 100644 --- a/NadekoBot.Core/Modules/Gambling/DiceRollCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/DiceRollCommands.cs @@ -24,11 +24,11 @@ namespace NadekoBot.Modules.Gambling private static readonly Regex fudgeRegex = new Regex(@"^(?\d+)d(?:F|f)$", RegexOptions.Compiled); private static readonly char[] _fateRolls = { '-', ' ', '+' }; - private readonly IImagesService _images; + private readonly IImageCache _images; - public DriceRollCommands(IImagesService images) + public DriceRollCommands(IDataCache data) { - _images = images; + _images = data.LocalImages; } @@ -141,10 +141,8 @@ namespace NadekoBot.Modules.Gambling private async Task InternallDndRoll(string arg, bool ordered) { Match match; - int n1; - int n2; if ((match = fudgeRegex.Match(arg)).Length != 0 && - int.TryParse(match.Groups["n1"].ToString(), out n1) && + int.TryParse(match.Groups["n1"].ToString(), out int n1) && n1 > 0 && n1 < 500) { var rng = new NadekoRandom(); @@ -164,13 +162,14 @@ namespace NadekoBot.Modules.Gambling { var rng = new NadekoRandom(); if (int.TryParse(match.Groups["n1"].ToString(), out n1) && - int.TryParse(match.Groups["n2"].ToString(), out n2) && + int.TryParse(match.Groups["n2"].ToString(), out int n2) && n1 <= 50 && n2 <= 100000 && n1 > 0 && n2 > 0) { - var add = 0; - var sub = 0; - int.TryParse(match.Groups["add"].Value, out add); - int.TryParse(match.Groups["sub"].Value, out sub); + if (!int.TryParse(match.Groups["add"].Value, out int add) || + !int.TryParse(match.Groups["sub"].Value, out int sub)) + { + return; + } var arr = new int[n1]; for (int i = 0; i < n1; i++) @@ -179,7 +178,7 @@ namespace NadekoBot.Modules.Gambling } var sum = arr.Sum(); - var embed = new EmbedBuilder().WithOkColor().WithDescription(Context.User.Mention + " " +GetText("dice_rolled_num", n1) + $"`1 - {n2}`") + var embed = new EmbedBuilder().WithOkColor().WithDescription(Context.User.Mention + " " + GetText("dice_rolled_num", n1) + $"`1 - {n2}`") .AddField(efb => efb.WithName(Format.Bold("Rolls")) .WithValue(string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString()))))) .AddField(efb => efb.WithName(Format.Bold("Sum")) diff --git a/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs b/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs index 94eb2d17..1658022e 100644 --- a/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/FlipCoinCommands.cs @@ -17,15 +17,15 @@ namespace NadekoBot.Modules.Gambling [Group] public class FlipCoinCommands : NadekoSubmodule { - private readonly IImagesService _images; + private readonly IImageCache _images; private readonly IBotConfigProvider _bc; private readonly CurrencyService _cs; private static readonly NadekoRandom rng = new NadekoRandom(); - public FlipCoinCommands(IImagesService images, CurrencyService cs, IBotConfigProvider bc) + public FlipCoinCommands(IDataCache data, CurrencyService cs, IBotConfigProvider bc) { - _images = images; + _images = data.LocalImages; _bc = bc; _cs = cs; } diff --git a/NadekoBot.Core/Modules/Gambling/SlotCommands.cs b/NadekoBot.Core/Modules/Gambling/SlotCommands.cs index 39f3cf9e..dd31dbe3 100644 --- a/NadekoBot.Core/Modules/Gambling/SlotCommands.cs +++ b/NadekoBot.Core/Modules/Gambling/SlotCommands.cs @@ -32,12 +32,12 @@ namespace NadekoBot.Modules.Gambling //https://lh6.googleusercontent.com/-i1hjAJy_kN4/UswKxmhrbPI/AAAAAAAAB1U/82wq_4ZZc-Y/DE6B0895-6FC1-48BE-AC4F-14D1B91AB75B.jpg //thanks to judge for helping me with this - private readonly IImagesService _images; + private readonly IImageCache _images; private readonly CurrencyService _cs; - public SlotCommands(IImagesService images, IBotConfigProvider bc, CurrencyService cs) + public SlotCommands(IDataCache data, IBotConfigProvider bc, CurrencyService cs) { - _images = images; + _images = data.LocalImages; _bc = bc; _cs = cs; } diff --git a/NadekoBot.Core/Modules/Games/Common/GirlRating.cs b/NadekoBot.Core/Modules/Games/Common/GirlRating.cs index 6b7354f3..98ad9cd4 100644 --- a/NadekoBot.Core/Modules/Games/Common/GirlRating.cs +++ b/NadekoBot.Core/Modules/Games/Common/GirlRating.cs @@ -14,6 +14,7 @@ namespace NadekoBot.Modules.Games.Common public class GirlRating { private static readonly Logger _log = LogManager.GetCurrentClassLogger(); + private readonly IImageCache _images; public double Crazy { get; } public double Hot { get; } @@ -21,8 +22,9 @@ namespace NadekoBot.Modules.Games.Common public string Advice { get; } public AsyncLazy Url { get; } - public GirlRating(IImagesService _images, double crazy, double hot, int roll, string advice) + public GirlRating(IImageCache images, double crazy, double hot, int roll, string advice) { + _images = images; Crazy = crazy; Hot = hot; Roll = roll; @@ -45,7 +47,7 @@ namespace NadekoBot.Modules.Games.Common using (var pointMs = new MemoryStream(_images.RategirlDot.ToArray(), false)) using (var pointImg = Image.Load(pointMs)) { - img.DrawImage(pointImg, 100, default(Size), new Point(pointx - 10, pointy - 10)); + img.DrawImage(pointImg, 100, default, new Point(pointx - 10, pointy - 10)); } string url; diff --git a/NadekoBot.Core/Modules/Games/Games.cs b/NadekoBot.Core/Modules/Games/Games.cs index 55979b6f..e5f9c0fa 100644 --- a/NadekoBot.Core/Modules/Games/Games.cs +++ b/NadekoBot.Core/Modules/Games/Games.cs @@ -19,11 +19,11 @@ namespace NadekoBot.Modules.Games //todo update docs public partial class Games : NadekoTopLevelModule { - private readonly IImagesService _images; + private readonly IImageCache _images; - public Games(IImagesService images) + public Games(IDataCache data) { - _images = images; + _images = data.LocalImages; } //#if GLOBAL_NADEKO // [NadekoCommand, Usage, Description, Aliases] diff --git a/NadekoBot.Core/Modules/Games/PlantAndPickCommands.cs b/NadekoBot.Core/Modules/Games/PlantAndPickCommands.cs index 1cb1e388..e726cad3 100644 --- a/NadekoBot.Core/Modules/Games/PlantAndPickCommands.cs +++ b/NadekoBot.Core/Modules/Games/PlantAndPickCommands.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Threading.Tasks; using NadekoBot.Common.Attributes; using NadekoBot.Modules.Games.Services; +using System; namespace NadekoBot.Modules.Games { @@ -88,12 +89,18 @@ namespace NadekoBot.Modules.Games else msgToSend += " " + GetText("pick_sn", Prefix); - using (var toSend = imgData.Data.ToStream()) + using (var toSend = imgData.ToStream()) { - msg = await Context.Channel.SendFileAsync(toSend, imgData.Name, msgToSend).ConfigureAwait(false); + msg = await Context.Channel.SendFileAsync(toSend, "plant.png", msgToSend, options: new RequestOptions() + { + RetryMode = RetryMode.AlwaysRetry + }).ConfigureAwait(false); } } - catch { } + catch (Exception ex) + { + _log.Warn(ex); + } var msgs = new IUserMessage[amount]; msgs[0] = msg; diff --git a/NadekoBot.Core/Modules/Games/Services/GamesService.cs b/NadekoBot.Core/Modules/Games/Services/GamesService.cs index ccb40b1f..c8a7dc85 100644 --- a/NadekoBot.Core/Modules/Games/Services/GamesService.cs +++ b/NadekoBot.Core/Modules/Games/Services/GamesService.cs @@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Games.Services private readonly Timer _t; private readonly CommandHandler _cmd; private readonly NadekoStrings _strings; - private readonly IImagesService _images; + private readonly IImageCache _images; private readonly Logger _log; private readonly NadekoRandom _rng; private readonly CurrencyService _cs; @@ -57,13 +57,13 @@ namespace NadekoBot.Modules.Games.Services public ConcurrentDictionary NunchiGames { get; } = new ConcurrentDictionary(); public GamesService(CommandHandler cmd, IBotConfigProvider bc, NadekoBot bot, - NadekoStrings strings, IImagesService images, CommandHandler cmdHandler, + NadekoStrings strings, IDataCache data, CommandHandler cmdHandler, CurrencyService cs) { _bc = bc; _cmd = cmd; _strings = strings; - _images = images; + _images = data.LocalImages; _cmdHandler = cmdHandler; _log = LogManager.GetCurrentClassLogger(); _rng = new NadekoRandom(); @@ -144,10 +144,11 @@ namespace NadekoBot.Modules.Games.Services private ConcurrentDictionary _locks { get; } = new ConcurrentDictionary(); public ConcurrentHashSet HalloweenAwardedUsers { get; } = new ConcurrentHashSet(); - public (string Name, ImmutableArray Data) GetRandomCurrencyImage() + public byte[] GetRandomCurrencyImage() { var rng = new NadekoRandom(); - return _images.Currency[rng.Next(0, _images.Currency.Length)]; + var cur = _images.Currency; + return cur[rng.Next(0, cur.Length)]; } private string GetText(ITextChannel ch, string key, params object[] rep) @@ -195,11 +196,11 @@ namespace NadekoBot.Modules.Games.Services : GetText(channel, "curgen_pl", dropAmount, _bc.BotConfig.CurrencySign) + " " + GetText(channel, "pick_pl", prefix); var file = GetRandomCurrencyImage(); - using (var fileStream = file.Data.ToStream()) + using (var fileStream = file.ToStream()) { var sent = await channel.SendFileAsync( fileStream, - file.Name, + "drop.png", toSend).ConfigureAwait(false); msgs[0] = sent; diff --git a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs index d982b720..74e501d7 100644 --- a/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs +++ b/NadekoBot.Core/Modules/Searches/Services/SearchesService.cs @@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Searches.Services private readonly IGoogleApiService _google; private readonly DbService _db; private readonly Logger _log; - private readonly IImagesService _imgs; + private readonly IImageCache _imgs; private readonly IDataCache _cache; private readonly FontProvider _fonts; private readonly HttpClient http; @@ -60,7 +60,7 @@ namespace NadekoBot.Modules.Searches.Services private readonly ConcurrentDictionary> _blacklistedTags = new ConcurrentDictionary>(); public SearchesService(DiscordSocketClient client, IGoogleApiService google, - DbService db, NadekoBot bot, IImagesService imgs, IDataCache cache, + DbService db, NadekoBot bot, IDataCache cache, FontProvider fonts) { Http = new HttpClient(); @@ -69,7 +69,7 @@ namespace NadekoBot.Modules.Searches.Services _google = google; _db = db; _log = LogManager.GetCurrentClassLogger(); - _imgs = imgs; + _imgs = cache.LocalImages; _cache = cache; _fonts = fonts; http = new HttpClient(); diff --git a/NadekoBot.Core/Modules/Xp/Services/XpService.cs b/NadekoBot.Core/Modules/Xp/Services/XpService.cs index ef3bdbcc..65d9c818 100644 --- a/NadekoBot.Core/Modules/Xp/Services/XpService.cs +++ b/NadekoBot.Core/Modules/Xp/Services/XpService.cs @@ -19,8 +19,6 @@ using SixLabors.Fonts; using System.IO; using SixLabors.Primitives; using System.Net.Http; -using SixLabors.Shapes; -using System.Numerics; using ImageSharp.Drawing.Pens; using ImageSharp.Drawing.Brushes; @@ -33,7 +31,7 @@ namespace NadekoBot.Modules.Xp.Services private readonly DbService _db; private readonly CommandHandler _cmd; private readonly IBotConfigProvider _bc; - private readonly IImagesService _images; + private readonly IImageCache _images; private readonly Logger _log; private readonly NadekoStrings _strings; private readonly IDataCache _cache; @@ -61,14 +59,13 @@ namespace NadekoBot.Modules.Xp.Services private readonly HttpClient http = new HttpClient(); public XpService(CommandHandler cmd, IBotConfigProvider bc, - NadekoBot bot, IImagesService images, - DbService db, NadekoStrings strings, IDataCache cache, + NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache, FontProvider fonts) { _db = db; _cmd = cmd; _bc = bc; - _images = images; + _images = cache.LocalImages; _log = LogManager.GetCurrentClassLogger(); _strings = strings; _cache = cache; diff --git a/NadekoBot.Core/Services/IDataCache.cs b/NadekoBot.Core/Services/IDataCache.cs index 5c114dc7..d1256529 100644 --- a/NadekoBot.Core/Services/IDataCache.cs +++ b/NadekoBot.Core/Services/IDataCache.cs @@ -7,6 +7,8 @@ namespace NadekoBot.Core.Services public interface IDataCache { ConnectionMultiplexer Redis { get; } + IImageCache LocalImages { get; } + Task<(bool Success, byte[] Data)> TryGetImageDataAsync(string key); Task<(bool Success, string Data)> TryGetAnimeDataAsync(string key); Task<(bool Success, string Data)> TryGetNovelDataAsync(string key); diff --git a/NadekoBot.Core/Services/IImageCache.cs b/NadekoBot.Core/Services/IImageCache.cs new file mode 100644 index 00000000..5e1e6fea --- /dev/null +++ b/NadekoBot.Core/Services/IImageCache.cs @@ -0,0 +1,27 @@ +using System.Collections.Immutable; + +namespace NadekoBot.Core.Services +{ + public interface IImageCache + { + byte[] Heads { get; } + byte[] Tails { get; } + + byte[][] Currency { get; } + byte[][] Dice { get; } + + byte[] SlotBackground { get; } + byte[][] SlotEmojis { get; } + byte[][] SlotNumbers { get; } + + byte[] WifeMatrix { get; } + byte[] RategirlDot { get; } + + byte[] XpCard { get; } + + byte[] Rip { get; } + byte[] FlowerCircle { get; } + + void Reload(); + } +} diff --git a/NadekoBot.Core/Services/IImagesService.cs b/NadekoBot.Core/Services/IImagesService.cs deleted file mode 100644 index 0d700c42..00000000 --- a/NadekoBot.Core/Services/IImagesService.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Collections.Immutable; - -namespace NadekoBot.Core.Services -{ - public interface IImagesService : INService - { - ImmutableArray Heads { get; } - ImmutableArray Tails { get; } - - ImmutableArray<(string, ImmutableArray)> Currency { get; } - ImmutableArray> Dice { get; } - - ImmutableArray SlotBackground { get; } - ImmutableArray> SlotEmojis { get; } - ImmutableArray> SlotNumbers { get; } - - ImmutableArray WifeMatrix { get; } - ImmutableArray RategirlDot { get; } - - ImmutableArray XpCard { get; } - - ImmutableArray Rip { get; } - ImmutableArray FlowerCircle { get; } - - void Reload(); - } -} diff --git a/NadekoBot.Core/Services/Impl/ImagesService.cs b/NadekoBot.Core/Services/Impl/ImagesService.cs index 8c8c0128..89594cf3 100644 --- a/NadekoBot.Core/Services/Impl/ImagesService.cs +++ b/NadekoBot.Core/Services/Impl/ImagesService.cs @@ -1,17 +1,22 @@ -using NLog; +using NadekoBot.Extensions; +using Newtonsoft.Json; +using NLog; +using StackExchange.Redis; using System; -using System.Collections.Immutable; using System.IO; using System.Linq; namespace NadekoBot.Core.Services.Impl { //todo move everything to redis - public class ImagesService : IImagesService + public class RedisImagesCache : IImageCache { - private readonly IDataCache _cache; + private readonly ConnectionMultiplexer _con; + private readonly IBotCredentials _creds; private readonly Logger _log; + private IDatabase _db => _con.GetDatabase(); + private const string _basePath = "data/images/"; private const string _headsPath = _basePath + "coins/heads.png"; @@ -32,71 +37,189 @@ namespace NadekoBot.Core.Services.Impl private const string _ripPath = _basePath + "rip/rip.png"; private const string _ripFlowersPath = _basePath + "rip/rose_overlay.png"; - - public ImmutableArray Heads { get; private set; } - public ImmutableArray Tails { get; private set; } - - public ImmutableArray<(string, ImmutableArray)> Currency { get; private set; } - - public ImmutableArray> Dice { get; private set; } - - public ImmutableArray SlotBackground { get; private set; } - public ImmutableArray> SlotNumbers { get; private set; } - public ImmutableArray> SlotEmojis { get; private set; } - - public ImmutableArray WifeMatrix { get; private set; } - public ImmutableArray RategirlDot { get; private set; } - - public ImmutableArray XpCard { get; private set; } - - public ImmutableArray Rip { get; private set; } - public ImmutableArray FlowerCircle { get; private set; } - - public ImagesService(IDataCache cache, int shardId) + public byte[] Heads { - _cache = cache; - _log = LogManager.GetCurrentClassLogger(); - if (shardId == 0) + get { - this.Reload(); + return Get("heads"); } + set + { + Set("heads", value); + } + } + + public byte[] Tails + { + get + { + return Get("tails"); + } + set + { + Set("tails", value); + } + } + + public byte[][] Currency + { + get + { + return Get("currency"); + } + set + { + Set("currency", value); + } + } + + public byte[][] Dice + { + get + { + return Get("dice"); + } + set + { + Set("dice", value); + } + } + + public byte[] SlotBackground + { + get + { + return Get("slot_background"); + } + set + { + Set("slot_background", value); + } + } + + public byte[][] SlotNumbers + { + get + { + return Get("slotnumbers"); + } + set + { + Set("slotnumbers", value); + } + } + public byte[][] SlotEmojis + { + get + { + return Get("slotemojis"); + } + set + { + Set("slotemojis", value); + } + } + + public byte[] WifeMatrix + { + get + { + return Get("wife_matrix"); + } + set + { + Set("wife_matrix", value); + } + } + public byte[] RategirlDot + { + get + { + return Get("rategirl_dot"); + } + set + { + Set("rategirl_dot", value); + } + } + + public byte[] XpCard + { + get + { + return Get("xp_card"); + } + set + { + Set("xp_card", value); + } + } + + public byte[] Rip + { + get + { + return Get("rip"); + } + set + { + Set("rip", value); + } + } + public byte[] FlowerCircle + { + get + { + return Get("flower_circle"); + } + set + { + Set("flower_circle", value); + } + } + + public RedisImagesCache(ConnectionMultiplexer con, IBotCredentials creds) + { + _con = con; + _creds = creds; + _log = LogManager.GetCurrentClassLogger(); } public void Reload() { try { - Heads = File.ReadAllBytes(_headsPath).ToImmutableArray(); - Tails = File.ReadAllBytes(_tailsPath).ToImmutableArray(); + Heads = File.ReadAllBytes(_headsPath); + Tails = File.ReadAllBytes(_tailsPath); Currency = Directory.GetFiles(_currencyImagesPath) - .Select(x => (Path.GetFileName(x), File.ReadAllBytes(x).ToImmutableArray())) - .ToImmutableArray(); + .Select(x => File.ReadAllBytes(x)) + .ToArray(); Dice = Directory.GetFiles(_diceImagesPath) .OrderBy(x => int.Parse(Path.GetFileNameWithoutExtension(x))) - .Select(x => File.ReadAllBytes(x).ToImmutableArray()) - .ToImmutableArray(); + .Select(x => File.ReadAllBytes(x)) + .ToArray(); - SlotBackground = File.ReadAllBytes(_slotBackgroundPath).ToImmutableArray(); + SlotBackground = File.ReadAllBytes(_slotBackgroundPath); SlotNumbers = Directory.GetFiles(_slotNumbersPath) .OrderBy(f => int.Parse(Path.GetFileNameWithoutExtension(f))) - .Select(x => File.ReadAllBytes(x).ToImmutableArray()) - .ToImmutableArray(); + .Select(x => File.ReadAllBytes(x)) + .ToArray(); SlotEmojis = Directory.GetFiles(_slotEmojisPath) .OrderBy(f => int.Parse(Path.GetFileNameWithoutExtension(f))) - .Select(x => File.ReadAllBytes(x).ToImmutableArray()) - .ToImmutableArray(); + .Select(x => File.ReadAllBytes(x)) + .ToArray(); - WifeMatrix = File.ReadAllBytes(_wifeMatrixPath).ToImmutableArray(); - RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray(); + WifeMatrix = File.ReadAllBytes(_wifeMatrixPath); + RategirlDot = File.ReadAllBytes(_rategirlDot); - XpCard = File.ReadAllBytes(_xpCardPath).ToImmutableArray(); + XpCard = File.ReadAllBytes(_xpCardPath); - Rip = File.ReadAllBytes(_ripPath).ToImmutableArray(); - FlowerCircle = File.ReadAllBytes(_ripFlowersPath).ToImmutableArray(); + Rip = File.ReadAllBytes(_ripPath); + FlowerCircle = File.ReadAllBytes(_ripFlowersPath); } catch (Exception ex) { @@ -104,5 +227,15 @@ namespace NadekoBot.Core.Services.Impl throw; } } + + private T Get(string key) where T : class + { + return JsonConvert.DeserializeObject(_db.StringGet($"{_creds.RedisKey()}_localimg_{key}")); + } + + private void Set(string key, object obj) + { + _db.StringSet($"{_creds.RedisKey()}_localimg_{key}", JsonConvert.SerializeObject(obj)); + } } } \ No newline at end of file diff --git a/NadekoBot.Core/Services/Impl/RedisCache.cs b/NadekoBot.Core/Services/Impl/RedisCache.cs index f5f5cc98..69334cd1 100644 --- a/NadekoBot.Core/Services/Impl/RedisCache.cs +++ b/NadekoBot.Core/Services/Impl/RedisCache.cs @@ -9,6 +9,9 @@ namespace NadekoBot.Core.Services.Impl public class RedisCache : IDataCache { public ConnectionMultiplexer Redis { get; } + + public IImageCache LocalImages { get; } + private readonly IDatabase _db; private readonly string _redisKey; @@ -16,6 +19,7 @@ namespace NadekoBot.Core.Services.Impl { Redis = ConnectionMultiplexer.Connect("127.0.0.1"); Redis.PreserveAsyncOrder = false; + LocalImages = new RedisImagesCache(Redis, creds); _db = Redis.GetDatabase(); _redisKey = creds.RedisKey(); } diff --git a/NadekoBot.Core/Services/ShardsCoordinator.cs b/NadekoBot.Core/Services/ShardsCoordinator.cs index d312f697..68255e9f 100644 --- a/NadekoBot.Core/Services/ShardsCoordinator.cs +++ b/NadekoBot.Core/Services/ShardsCoordinator.cs @@ -72,6 +72,8 @@ namespace NadekoBot.Core.Services _key = _creds.RedisKey(); _redis = ConnectionMultiplexer.Connect("127.0.0.1"); + new RedisImagesCache(_redis, _creds).Reload(); //reload images into redis + //setup initial shard statuses _defaultShardState = new ShardComMessage() {