diff --git a/NadekoBot/Classes/ServerSpecificConfig.cs b/NadekoBot/Classes/ServerSpecificConfig.cs index ff42f0fd..9142e574 100644 --- a/NadekoBot/Classes/ServerSpecificConfig.cs +++ b/NadekoBot/Classes/ServerSpecificConfig.cs @@ -6,6 +6,8 @@ using System.Collections.ObjectModel; using System.ComponentModel; using System.IO; using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; namespace NadekoBot.Classes { @@ -27,9 +29,12 @@ namespace NadekoBot.Classes { configs = JsonConvert .DeserializeObject>( - File.ReadAllText(filePath), new JsonSerializerSettings() { - Error = (s,e) => { - if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") { + File.ReadAllText(filePath), new JsonSerializerSettings() + { + Error = (s, e) => + { + if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") + { e.ErrorContext.Handled = true; } } @@ -52,14 +57,19 @@ namespace NadekoBot.Classes public ServerSpecificConfig Of(ulong id) => configs.GetOrAdd(id, _ => new ServerSpecificConfig()); - private readonly object saveLock = new object(); + private readonly SemaphoreSlim saveLock = new SemaphoreSlim(1, 1); - public void Save() + public async Task Save() { - lock (saveLock) + await saveLock.WaitAsync(); + try { File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented)); } + finally + { + saveLock.Release(); + } } } @@ -245,7 +255,7 @@ namespace NadekoBot.Classes LogserverIgnoreChannels = new ObservableCollection(); } - public event PropertyChangedEventHandler PropertyChanged = delegate { SpecificConfigurations.Default.Save(); }; + public event PropertyChangedEventHandler PropertyChanged = async delegate { await SpecificConfigurations.Default.Save().ConfigureAwait(false); }; private void OnPropertyChanged([CallerMemberName] string propertyName = null) { diff --git a/NadekoBot/Modules/Administration/AdministrationModule.cs b/NadekoBot/Modules/Administration/AdministrationModule.cs index ab6dafae..ad28d083 100644 --- a/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Administration { var conf = SpecificConfigurations.Default.Of(e.Server.Id); conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; - Classes.JSONModels.ConfigHandler.SaveConfig(); + await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); if (conf.AutoDeleteMessagesOnCommand) await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`"); else diff --git a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs index fcd970a7..a01f9a8d 100644 --- a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs +++ b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs @@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Administration.Commands NadekoBot.Config.CustomReactions[name].Add(message); else NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List() { message }); - await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); + await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"Added {name} : {message}").ConfigureAwait(false); }); @@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration.Commands index = index - 1; NadekoBot.Config.CustomReactions[name][index] = msg; - await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); + await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false); }); @@ -183,7 +183,7 @@ namespace NadekoBot.Modules.Administration.Commands NadekoBot.Config.CustomReactions.Remove(name); message = $"Deleted custom reaction: `{name}`"; } - await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false); + await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage(message).ConfigureAwait(false); }); } diff --git a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs index aa7570cb..2d22d870 100644 --- a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs +++ b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs @@ -7,8 +7,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using System.Timers; +using Timer = System.Timers.Timer; namespace NadekoBot.Modules.Administration.Commands { @@ -36,7 +38,7 @@ namespace NadekoBot.Modules.Administration.Commands {"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()} }; - private readonly object playingPlaceholderLock = new object(); + private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1,1); public PlayingRotate(DiscordModule module) : base(module) { @@ -47,7 +49,9 @@ namespace NadekoBot.Modules.Administration.Commands { i++; var status = ""; - lock (playingPlaceholderLock) + //wtf am i doing, just use a queue ffs + await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); + try { if (PlayingPlaceholders.Count == 0 || NadekoBot.Config.RotatingStatuses.Count == 0 @@ -59,6 +63,7 @@ namespace NadekoBot.Modules.Administration.Commands status = PlayingPlaceholders.Aggregate(status, (current, kvp) => current.Replace(kvp.Key, kvp.Value())); } + finally { playingPlaceholderLock.Release(); } if (string.IsNullOrWhiteSpace(status)) return; await Task.Run(() => { NadekoBot.Client.SetGame(status); }); @@ -71,14 +76,18 @@ namespace NadekoBot.Modules.Administration.Commands public Func DoFunc() => async e => { - lock (playingPlaceholderLock) + await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); + try { if (timer.Enabled) timer.Stop(); else timer.Start(); NadekoBot.Config.IsRotatingStatus = timer.Enabled; - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); + } + finally { + playingPlaceholderLock.Release(); } await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false); }; @@ -102,10 +111,15 @@ namespace NadekoBot.Modules.Administration.Commands var arg = e.GetArg("text"); if (string.IsNullOrWhiteSpace(arg)) return; - lock (playingPlaceholderLock) + await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); + try { NadekoBot.Config.RotatingStatuses.Add(arg); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig(); + } + finally + { + playingPlaceholderLock.Release(); } await e.Channel.SendMessage("🆗 `Added a new playing string.`").ConfigureAwait(false); }); @@ -137,14 +151,15 @@ namespace NadekoBot.Modules.Administration.Commands var arg = e.GetArg("number"); int num; string str; - lock (playingPlaceholderLock) - { + await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); + try { if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count) return; str = NadekoBot.Config.RotatingStatuses[num - 1]; NadekoBot.Config.RotatingStatuses.RemoveAt(num - 1); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); } + finally { playingPlaceholderLock.Release(); } await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false); }); } diff --git a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs index 9c383509..c5ba20fc 100644 --- a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs +++ b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using NadekoBot.Modules.Permissions.Classes; +using System.Threading; namespace NadekoBot.Modules.ClashOfClans { @@ -16,8 +17,6 @@ namespace NadekoBot.Modules.ClashOfClans public static ConcurrentDictionary> ClashWars { get; } = new ConcurrentDictionary>(); - private readonly object writeLock = new object(); - public override void Install(ModuleManager manager) { manager.CreateCommands("", cgb => diff --git a/NadekoBot/Modules/Games/Commands/PlantPick.cs b/NadekoBot/Modules/Games/Commands/PlantPick.cs index 6af69857..e2bce2ec 100644 --- a/NadekoBot/Modules/Games/Commands/PlantPick.cs +++ b/NadekoBot/Modules/Games/Commands/PlantPick.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; +using System.Threading; using System.Threading.Tasks; namespace NadekoBot.Modules.Games.Commands @@ -59,7 +60,7 @@ namespace NadekoBot.Modules.Games.Commands //channelid/messageid pair ConcurrentDictionary> plantedFlowerChannels = new ConcurrentDictionary>(); - private object locker = new object(); + private SemaphoreSlim locker = new SemaphoreSlim(1,1); internal override void Init(CommandGroupBuilder cgb) { @@ -84,32 +85,34 @@ namespace NadekoBot.Modules.Games.Commands cgb.CreateCommand(Module.Prefix + "plant") .Description("Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)") - .Do(e => + .Do(async e => { - lock (locker) + await locker.WaitAsync().ConfigureAwait(false); + try { if (plantedFlowerChannels.ContainsKey(e.Channel.Id)) { - e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel."); + await e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel.").ConfigureAwait(false); return; } - var removed = FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).GetAwaiter().GetResult(); + var removed = await FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).ConfigureAwait(false); if (!removed) { - e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").Wait(); + await e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").ConfigureAwait(false); return; } var file = GetRandomCurrencyImagePath(); Message msg; if (file == null) - msg = e.Channel.SendMessage(NadekoBot.Config.CurrencySign).GetAwaiter().GetResult(); + msg = await e.Channel.SendMessage(NadekoBot.Config.CurrencySign).ConfigureAwait(false); else - msg = e.Channel.SendFile(file).GetAwaiter().GetResult(); + msg = await e.Channel.SendFile(file).ConfigureAwait(false); var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]); - var msg2 = e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").GetAwaiter().GetResult(); + var msg2 = await e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false); plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 }); } + finally { locker.Release(); } }); cgb.CreateCommand(Prefix + "gencurrency") @@ -129,12 +132,12 @@ namespace NadekoBot.Modules.Games.Commands int throwaway; if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out throwaway)) { - await e.Channel.SendMessage("`Currency generation disabled on this channel.`"); + await e.Channel.SendMessage("`Currency generation disabled on this channel.`").ConfigureAwait(false); } else { if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd)) - await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`"); + await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`").ConfigureAwait(false); } }); } diff --git a/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs b/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs index 683eb3d0..fc5dd361 100644 --- a/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs +++ b/NadekoBot/Modules/Games/Commands/Trivia/TriviaGame.cs @@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia { internal class TriviaGame { - private readonly object _guessLock = new object(); + private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1,1); private Server server { get; } private Channel channel { get; } @@ -113,7 +113,8 @@ namespace NadekoBot.Modules.Games.Commands.Trivia if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; var guess = false; - lock (_guessLock) + await _guessLock.WaitAsync().ConfigureAwait(false); + try { if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested) { @@ -122,6 +123,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia guess = true; } } + catch { _guessLock.Release(); } if (!guess) return; triviaCancelSource.Cancel(); await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); diff --git a/NadekoBot/Modules/Music/Classes/PoopyBuffer.cs b/NadekoBot/Modules/Music/Classes/PoopyBuffer.cs index 15dc4977..c4a95daa 100644 --- a/NadekoBot/Modules/Music/Classes/PoopyBuffer.cs +++ b/NadekoBot/Modules/Music/Classes/PoopyBuffer.cs @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Music.Classes public int BufferSize { get; } - private readonly object readWriteLock = new object(); + private readonly SemaphoreSlim readWriteLock = new SemaphoreSlim(1, 1); public PoopyBuffer(int size) { @@ -32,51 +32,57 @@ namespace NadekoBot.Modules.Music.Classes ringBuffer = new byte[size]; } - public int Read(byte[] buffer, int count) + public Task ReadAsync(byte[] buffer, int count) { - if (buffer.Length < count) - throw new ArgumentException(); - //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***"); - lock (readWriteLock) + return Task.Run(async () => { - //read as much as you can if you're reading too much - if (count > ContentLength) - count = ContentLength; - //if nothing to read, return 0 - if (WritePosition == ReadPosition) - return 0; - // if buffer is in the "normal" state, just read - if (WritePosition > ReadPosition) + if (buffer.Length < count) + throw new ArgumentException(); + //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***"); + await readWriteLock.WaitAsync().ConfigureAwait(false); + try { - Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); - ReadPosition += count; - //Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]"); + //read as much as you can if you're reading too much + if (count > ContentLength) + count = ContentLength; + //if nothing to read, return 0 + if (WritePosition == ReadPosition) + return 0; + // if buffer is in the "normal" state, just read + if (WritePosition > ReadPosition) + { + Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); + ReadPosition += count; + //Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]"); + return count; + } + //else ReadPos { - // if i can just write without hitting buffer.length, do it - if (WritePosition + count < BufferSize) + //the while above assures that i cannot write past readposition with my write, so i don't have to check + // *unless its multithreaded or task is not awaited + await readWriteLock.WaitAsync().ConfigureAwait(false); + try { - Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count); - WritePosition += count; - //Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]"); - return; + // if i can just write without hitting buffer.length, do it + if (WritePosition + count < BufferSize) + { + Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count); + WritePosition += count; + //Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]"); + return; + } + // otherwise, i have to write to the end, then write the rest from the start + + var wroteNormaly = BufferSize - WritePosition; + Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly); + + //Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]"); + + var wroteFromStart = count - wroteNormaly; + Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart); + + //Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}"); + + WritePosition = wroteFromStart; } - // otherwise, i have to write to the end, then write the rest from the start - - var wroteNormaly = BufferSize - WritePosition; - Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly); - - //Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]"); - - var wroteFromStart = count - wroteNormaly; - Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart); - - //Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}"); - - WritePosition = wroteFromStart; - } + finally { readWriteLock.Release(); } + }); } } } diff --git a/NadekoBot/Modules/Music/Classes/Song.cs b/NadekoBot/Modules/Music/Classes/Song.cs index 025863e0..9f2fb382 100644 --- a/NadekoBot/Modules/Music/Classes/Song.cs +++ b/NadekoBot/Modules/Music/Classes/Song.cs @@ -155,7 +155,7 @@ namespace NadekoBot.Modules.Music.Classes { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); byte[] buffer = new byte[blockSize]; - var read = songBuffer.Read(buffer, blockSize); + var read = await songBuffer.ReadAsync(buffer, blockSize).ConfigureAwait(false); unchecked { bytesSent += (ulong)read; diff --git a/NadekoBot/Modules/Permissions/PermissionsModule.cs b/NadekoBot/Modules/Permissions/PermissionsModule.cs index 4c13b9ff..8ca83e48 100644 --- a/NadekoBot/Modules/Permissions/PermissionsModule.cs +++ b/NadekoBot/Modules/Permissions/PermissionsModule.cs @@ -689,7 +689,7 @@ namespace NadekoBot.Modules.Permissions if (!e.Message.MentionedUsers.Any()) return; var usr = e.Message.MentionedUsers.First(); NadekoBot.Config.UserBlacklist.Add(usr.Id); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false); }).ConfigureAwait(false); }); @@ -707,7 +707,7 @@ namespace NadekoBot.Modules.Permissions if (NadekoBot.Config.UserBlacklist.Contains(usr.Id)) { NadekoBot.Config.UserBlacklist.Remove(usr.Id); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false); } else @@ -727,7 +727,7 @@ namespace NadekoBot.Modules.Permissions if (!e.Message.MentionedChannels.Any()) return; var ch = e.Message.MentionedChannels.First(); NadekoBot.Config.UserBlacklist.Add(ch.Id); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); }).ConfigureAwait(false); }); @@ -742,7 +742,7 @@ namespace NadekoBot.Modules.Permissions if (!e.Message.MentionedChannels.Any()) return; var ch = e.Message.MentionedChannels.First(); NadekoBot.Config.UserBlacklist.Remove(ch.Id); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); }).ConfigureAwait(false); }); @@ -767,7 +767,7 @@ namespace NadekoBot.Modules.Permissions } var serverId = server.Id; NadekoBot.Config.ServerBlacklist.Add(serverId); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); //cleanup trivias and typeracing Modules.Games.Commands.Trivia.TriviaGame trivia; TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia); diff --git a/NadekoBot/Modules/Searches/Commands/LoLCommands.cs b/NadekoBot/Modules/Searches/Commands/LoLCommands.cs index bbe2eca9..8826beaf 100644 --- a/NadekoBot/Modules/Searches/Commands/LoLCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/LoLCommands.cs @@ -30,8 +30,6 @@ namespace NadekoBot.Modules.Searches.Commands } private static Dictionary CachedChampionImages = new Dictionary(); - private readonly object cacheLock = new object(); - private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer(); public LoLCommands(DiscordModule module) : base(module) @@ -42,7 +40,6 @@ namespace NadekoBot.Modules.Searches.Commands { try { - lock (cacheLock) CachedChampionImages = CachedChampionImages .Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); @@ -87,16 +84,14 @@ namespace NadekoBot.Modules.Searches.Commands var resolvedRole = role; var name = e.GetArg("champ").Replace(" ", "").ToLower(); CachedChampion champ = null; - lock (cacheLock) - { - CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); - } - if (champ != null) - { - champ.ImageStream.Position = 0; - await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); - return; - } + + if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ)) + if (champ != null) + { + champ.ImageStream.Position = 0; + await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); + return; + } var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false)); JToken data = null; if (role != null) @@ -121,17 +116,13 @@ namespace NadekoBot.Modules.Searches.Commands role = allData[0]["role"].ToString(); resolvedRole = ResolvePos(role); } - lock (cacheLock) - { - CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); - } - if (champ != null) - { - Console.WriteLine("Sending lol image from cache."); - champ.ImageStream.Position = 0; - await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); - return; - } + if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ)) + if (champ != null) + { + champ.ImageStream.Position = 0; + await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); + return; + } //name = data["title"].ToString(); // get all possible roles, and "select" the shown one var roles = new string[allData.Count]; diff --git a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs index d5c6c755..efe521ff 100644 --- a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs +++ b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs @@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Searches.Commands } } catch { } - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); }; checkTimer.Start(); } @@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Searches.Commands } config.ObservingStreams.Remove(toRemove); - ConfigHandler.SaveConfig(); + await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($":ok: Removed `{toRemove.Username}`'s stream from notifications.").ConfigureAwait(false); }); diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index 4a091e3e..ad68beca 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -197,7 +197,7 @@ namespace NadekoBot return; } #if NADEKO_RELEASE - await Task.Delay(90000).ConfigureAwait(false); + await Task.Delay(100000).ConfigureAwait(false); #else await Task.Delay(1000).ConfigureAwait(false); #endif diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index cd467b7f..4e16fee4 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -78,13 +78,14 @@ true - bin\x64\Debug\ + bin\Debug\ TRACE;DEBUG full x64 prompt MinimumRecommendedRules.ruleset true + false bin\x64\Release\ diff --git a/NadekoBot/_Models/JSONModels/Configuration.cs b/NadekoBot/_Models/JSONModels/Configuration.cs index 295134fe..d39c6e00 100644 --- a/NadekoBot/_Models/JSONModels/Configuration.cs +++ b/NadekoBot/_Models/JSONModels/Configuration.cs @@ -4,6 +4,8 @@ using Newtonsoft.Json; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; +using System.Threading; +using System.Threading.Tasks; namespace NadekoBot.Classes.JSONModels { @@ -187,13 +189,17 @@ Nadeko Support Server: "; public static class ConfigHandler { - private static readonly object configLock = new object(); - public static void SaveConfig() + private static readonly SemaphoreSlim configLock = new SemaphoreSlim(1, 1); + public static async Task SaveConfig() { - lock (configLock) + await configLock.WaitAsync(); + try { File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented)); } + finally { + configLock.Release(); + } } public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) ||