Changed all locks to SemaphoreSlims, Slight musicbuffer changes.
This commit is contained in:
		| @@ -6,6 +6,8 @@ using System.Collections.ObjectModel; | |||||||
| using System.ComponentModel; | using System.ComponentModel; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Runtime.CompilerServices; | using System.Runtime.CompilerServices; | ||||||
|  | using System.Threading; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace NadekoBot.Classes | namespace NadekoBot.Classes | ||||||
| { | { | ||||||
| @@ -27,9 +29,12 @@ namespace NadekoBot.Classes | |||||||
|                 { |                 { | ||||||
|                     configs = JsonConvert |                     configs = JsonConvert | ||||||
|                         .DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>( |                         .DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>( | ||||||
|                             File.ReadAllText(filePath), new JsonSerializerSettings() { |                             File.ReadAllText(filePath), new JsonSerializerSettings() | ||||||
|                                 Error = (s,e) => { |                             { | ||||||
|                                     if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") { |                                 Error = (s, e) => | ||||||
|  |                                 { | ||||||
|  |                                     if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") | ||||||
|  |                                     { | ||||||
|                                         e.ErrorContext.Handled = true; |                                         e.ErrorContext.Handled = true; | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
| @@ -52,14 +57,19 @@ namespace NadekoBot.Classes | |||||||
|         public ServerSpecificConfig Of(ulong id) => |         public ServerSpecificConfig Of(ulong id) => | ||||||
|             configs.GetOrAdd(id, _ => new ServerSpecificConfig()); |             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)); |                 File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented)); | ||||||
|             } |             } | ||||||
|  |             finally | ||||||
|  |             { | ||||||
|  |                 saveLock.Release(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -245,7 +255,7 @@ namespace NadekoBot.Classes | |||||||
|             LogserverIgnoreChannels = new ObservableCollection<ulong>(); |             LogserverIgnoreChannels = new ObservableCollection<ulong>(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         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) |         private void OnPropertyChanged([CallerMemberName] string propertyName = null) | ||||||
|         { |         { | ||||||
|   | |||||||
| @@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Administration | |||||||
|                     { |                     { | ||||||
|                         var conf = SpecificConfigurations.Default.Of(e.Server.Id); |                         var conf = SpecificConfigurations.Default.Of(e.Server.Id); | ||||||
|                         conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; |                         conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; | ||||||
|                         Classes.JSONModels.ConfigHandler.SaveConfig(); |                         await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|                         if (conf.AutoDeleteMessagesOnCommand) |                         if (conf.AutoDeleteMessagesOnCommand) | ||||||
|                             await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`"); |                             await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`"); | ||||||
|                         else |                         else | ||||||
|   | |||||||
| @@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|                         NadekoBot.Config.CustomReactions[name].Add(message); |                         NadekoBot.Config.CustomReactions[name].Add(message); | ||||||
|                     else |                     else | ||||||
|                         NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<string>() { message }); |                         NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<string>() { 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); |                     await e.Channel.SendMessage($"Added {name} : {message}").ConfigureAwait(false); | ||||||
|  |  | ||||||
|                 }); |                 }); | ||||||
| @@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|                     index = index - 1; |                     index = index - 1; | ||||||
|                     NadekoBot.Config.CustomReactions[name][index] = msg; |                     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); |                     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); |                         NadekoBot.Config.CustomReactions.Remove(name); | ||||||
|                         message = $"Deleted custom reaction: `{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); |                     await e.Channel.SendMessage(message).ConfigureAwait(false); | ||||||
|                 }); |                 }); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -7,8 +7,10 @@ using System; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using System.Threading; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Timers; | using System.Timers; | ||||||
|  | using Timer = System.Timers.Timer; | ||||||
|  |  | ||||||
| namespace NadekoBot.Modules.Administration.Commands | namespace NadekoBot.Modules.Administration.Commands | ||||||
| { | { | ||||||
| @@ -36,7 +38,7 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|                 {"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()} |                 {"%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) |         public PlayingRotate(DiscordModule module) : base(module) | ||||||
|         { |         { | ||||||
| @@ -47,7 +49,9 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|                 { |                 { | ||||||
|                     i++; |                     i++; | ||||||
|                     var status = ""; |                     var status = ""; | ||||||
|                     lock (playingPlaceholderLock) |                     //wtf am i doing, just use a queue ffs | ||||||
|  |                     await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); | ||||||
|  |                     try | ||||||
|                     { |                     { | ||||||
|                         if (PlayingPlaceholders.Count == 0 |                         if (PlayingPlaceholders.Count == 0 | ||||||
|                             || NadekoBot.Config.RotatingStatuses.Count == 0 |                             || NadekoBot.Config.RotatingStatuses.Count == 0 | ||||||
| @@ -59,6 +63,7 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|                         status = PlayingPlaceholders.Aggregate(status, |                         status = PlayingPlaceholders.Aggregate(status, | ||||||
|                             (current, kvp) => current.Replace(kvp.Key, kvp.Value())); |                             (current, kvp) => current.Replace(kvp.Key, kvp.Value())); | ||||||
|                     } |                     } | ||||||
|  |                     finally { playingPlaceholderLock.Release(); } | ||||||
|                     if (string.IsNullOrWhiteSpace(status)) |                     if (string.IsNullOrWhiteSpace(status)) | ||||||
|                         return; |                         return; | ||||||
|                     await Task.Run(() => { NadekoBot.Client.SetGame(status); }); |                     await Task.Run(() => { NadekoBot.Client.SetGame(status); }); | ||||||
| @@ -71,14 +76,18 @@ namespace NadekoBot.Modules.Administration.Commands | |||||||
|  |  | ||||||
|         public Func<CommandEventArgs, Task> DoFunc() => async e => |         public Func<CommandEventArgs, Task> DoFunc() => async e => | ||||||
|         { |         { | ||||||
|             lock (playingPlaceholderLock) |             await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); | ||||||
|  |             try | ||||||
|             { |             { | ||||||
|                 if (timer.Enabled) |                 if (timer.Enabled) | ||||||
|                     timer.Stop(); |                     timer.Stop(); | ||||||
|                 else |                 else | ||||||
|                     timer.Start(); |                     timer.Start(); | ||||||
|                 NadekoBot.Config.IsRotatingStatus = timer.Enabled; |                 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); |             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"); |                     var arg = e.GetArg("text"); | ||||||
|                     if (string.IsNullOrWhiteSpace(arg)) |                     if (string.IsNullOrWhiteSpace(arg)) | ||||||
|                         return; |                         return; | ||||||
|                     lock (playingPlaceholderLock) |                     await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); | ||||||
|  |                     try | ||||||
|                     { |                     { | ||||||
|                         NadekoBot.Config.RotatingStatuses.Add(arg); |                         NadekoBot.Config.RotatingStatuses.Add(arg); | ||||||
|                         ConfigHandler.SaveConfig(); |                         await ConfigHandler.SaveConfig(); | ||||||
|  |                     } | ||||||
|  |                     finally | ||||||
|  |                     { | ||||||
|  |                         playingPlaceholderLock.Release(); | ||||||
|                     } |                     } | ||||||
|                     await e.Channel.SendMessage("🆗 `Added a new playing string.`").ConfigureAwait(false); |                     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"); |                     var arg = e.GetArg("number"); | ||||||
|                     int num; |                     int num; | ||||||
|                     string str; |                     string str; | ||||||
|                     lock (playingPlaceholderLock) |                     await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); | ||||||
|                     { |                     try { | ||||||
|                         if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count) |                         if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count) | ||||||
|                             return; |                             return; | ||||||
|                         str = NadekoBot.Config.RotatingStatuses[num - 1]; |                         str = NadekoBot.Config.RotatingStatuses[num - 1]; | ||||||
|                         NadekoBot.Config.RotatingStatuses.RemoveAt(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); |                     await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false); | ||||||
|                 }); |                 }); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ using System.Collections.Generic; | |||||||
| using System.Text; | using System.Text; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using NadekoBot.Modules.Permissions.Classes; | using NadekoBot.Modules.Permissions.Classes; | ||||||
|  | using System.Threading; | ||||||
|  |  | ||||||
| namespace NadekoBot.Modules.ClashOfClans | namespace NadekoBot.Modules.ClashOfClans | ||||||
| { | { | ||||||
| @@ -16,8 +17,6 @@ namespace NadekoBot.Modules.ClashOfClans | |||||||
|  |  | ||||||
|         public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>(); |         public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>(); | ||||||
|  |  | ||||||
|         private readonly object writeLock = new object(); |  | ||||||
|  |  | ||||||
|         public override void Install(ModuleManager manager) |         public override void Install(ModuleManager manager) | ||||||
|         { |         { | ||||||
|             manager.CreateCommands("", cgb => |             manager.CreateCommands("", cgb => | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ using System.Collections.Generic; | |||||||
| using System.IO; | using System.IO; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Security.Cryptography; | using System.Security.Cryptography; | ||||||
|  | using System.Threading; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace NadekoBot.Modules.Games.Commands | namespace NadekoBot.Modules.Games.Commands | ||||||
| @@ -59,7 +60,7 @@ namespace NadekoBot.Modules.Games.Commands | |||||||
|         //channelid/messageid pair |         //channelid/messageid pair | ||||||
|         ConcurrentDictionary<ulong, IEnumerable<Message>> plantedFlowerChannels = new ConcurrentDictionary<ulong, IEnumerable<Message>>(); |         ConcurrentDictionary<ulong, IEnumerable<Message>> plantedFlowerChannels = new ConcurrentDictionary<ulong, IEnumerable<Message>>(); | ||||||
|  |  | ||||||
|         private object locker = new object(); |         private SemaphoreSlim locker = new SemaphoreSlim(1,1); | ||||||
|  |  | ||||||
|         internal override void Init(CommandGroupBuilder cgb) |         internal override void Init(CommandGroupBuilder cgb) | ||||||
|         { |         { | ||||||
| @@ -84,32 +85,34 @@ namespace NadekoBot.Modules.Games.Commands | |||||||
|  |  | ||||||
|             cgb.CreateCommand(Module.Prefix + "plant") |             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)") |                 .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)) |                         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; |                             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) |                         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; |                             return; | ||||||
|                         } |                         } | ||||||
|  |  | ||||||
|                         var file = GetRandomCurrencyImagePath(); |                         var file = GetRandomCurrencyImagePath(); | ||||||
|                         Message msg; |                         Message msg; | ||||||
|                         if (file == null) |                         if (file == null) | ||||||
|                             msg = e.Channel.SendMessage(NadekoBot.Config.CurrencySign).GetAwaiter().GetResult(); |                             msg = await e.Channel.SendMessage(NadekoBot.Config.CurrencySign).ConfigureAwait(false); | ||||||
|                         else |                         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 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 }); |                         plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 }); | ||||||
|                     } |                     } | ||||||
|  |                     finally { locker.Release();  } | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|             cgb.CreateCommand(Prefix + "gencurrency") |             cgb.CreateCommand(Prefix + "gencurrency") | ||||||
| @@ -129,12 +132,12 @@ namespace NadekoBot.Modules.Games.Commands | |||||||
|                     int throwaway; |                     int throwaway; | ||||||
|                     if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out 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 |                     else | ||||||
|                     { |                     { | ||||||
|                         if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd)) |                         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); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia | |||||||
| { | { | ||||||
|     internal class TriviaGame |     internal class TriviaGame | ||||||
|     { |     { | ||||||
|         private readonly object _guessLock = new object(); |         private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1,1); | ||||||
|  |  | ||||||
|         private Server server { get; } |         private Server server { get; } | ||||||
|         private Channel channel { get; } |         private Channel channel { get; } | ||||||
| @@ -113,7 +113,8 @@ namespace NadekoBot.Modules.Games.Commands.Trivia | |||||||
|                 if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; |                 if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; | ||||||
|  |  | ||||||
|                 var guess = false; |                 var guess = false; | ||||||
|                 lock (_guessLock) |                 await _guessLock.WaitAsync().ConfigureAwait(false); | ||||||
|  |                 try | ||||||
|                 { |                 { | ||||||
|                     if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested) |                     if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested) | ||||||
|                     { |                     { | ||||||
| @@ -122,6 +123,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia | |||||||
|                         guess = true; |                         guess = true; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |                 catch { _guessLock.Release(); } | ||||||
|                 if (!guess) return; |                 if (!guess) return; | ||||||
|                 triviaCancelSource.Cancel(); |                 triviaCancelSource.Cancel(); | ||||||
|                 await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); |                 await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false); | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Music.Classes | |||||||
|  |  | ||||||
|         public int BufferSize { get; } |         public int BufferSize { get; } | ||||||
|  |  | ||||||
|         private readonly object readWriteLock = new object(); |         private readonly SemaphoreSlim readWriteLock = new SemaphoreSlim(1, 1); | ||||||
|  |  | ||||||
|         public PoopyBuffer(int size) |         public PoopyBuffer(int size) | ||||||
|         { |         { | ||||||
| @@ -32,51 +32,57 @@ namespace NadekoBot.Modules.Music.Classes | |||||||
|             ringBuffer = new byte[size]; |             ringBuffer = new byte[size]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public int Read(byte[] buffer, int count) |         public Task<int> ReadAsync(byte[] buffer, int count) | ||||||
|         { |         { | ||||||
|             if (buffer.Length < count) |             return Task.Run(async () => | ||||||
|                 throw new ArgumentException(); |  | ||||||
|             //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***"); |  | ||||||
|             lock (readWriteLock) |  | ||||||
|             { |             { | ||||||
|                 //read as much as you can if you're reading too much |                 if (buffer.Length < count) | ||||||
|                 if (count > ContentLength) |                     throw new ArgumentException(); | ||||||
|                     count = ContentLength; |                 //Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***"); | ||||||
|                 //if nothing to read, return 0 |                 await readWriteLock.WaitAsync().ConfigureAwait(false); | ||||||
|                 if (WritePosition == ReadPosition) |                 try | ||||||
|                     return 0; |  | ||||||
|                 // if buffer is in the "normal" state, just read |  | ||||||
|                 if (WritePosition > ReadPosition) |  | ||||||
|                 { |                 { | ||||||
|                     Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); |                     //read as much as you can if you're reading too much | ||||||
|                     ReadPosition += count; |                     if (count > ContentLength) | ||||||
|                     //Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]"); |                         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 <Writepos | ||||||
|  |                     // buffer is in its inverted state | ||||||
|  |                     // A: if i can read as much as possible without hitting the buffer.length, read that | ||||||
|  |  | ||||||
|  |                     if (count + ReadPosition <= BufferSize) | ||||||
|  |                     { | ||||||
|  |                         Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); | ||||||
|  |                         ReadPosition += count; | ||||||
|  |                         //Console.WriteLine($"Read only normally2 {count}[{ReadPosition - count} to {ReadPosition}]"); | ||||||
|  |                         return count; | ||||||
|  |                     } | ||||||
|  |                     // B: if i can't read as much, read to the end, | ||||||
|  |                     var readNormaly = BufferSize - ReadPosition; | ||||||
|  |                     Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, readNormaly); | ||||||
|  |  | ||||||
|  |                     //Console.WriteLine($"Read normaly {count}[{ReadPosition} to {ReadPosition + readNormaly}]"); | ||||||
|  |                     //then read the remaining amount from the start | ||||||
|  |  | ||||||
|  |                     var readFromStart = count - readNormaly; | ||||||
|  |                     Buffer.BlockCopy(ringBuffer, 0, buffer, readNormaly, readFromStart); | ||||||
|  |                     //Console.WriteLine($"Read From start {readFromStart}[{0} to {readFromStart}]"); | ||||||
|  |                     ReadPosition = readFromStart; | ||||||
|                     return count; |                     return count; | ||||||
|                 } |                 } | ||||||
|                 //else ReadPos <Writepos |                 finally { readWriteLock.Release(); } | ||||||
|                 // buffer is in its inverted state |             }); | ||||||
|                 // A: if i can read as much as possible without hitting the buffer.length, read that |  | ||||||
|  |  | ||||||
|                 if (count + ReadPosition <= BufferSize) |  | ||||||
|                 { |  | ||||||
|                     Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count); |  | ||||||
|                     ReadPosition += count; |  | ||||||
|                     //Console.WriteLine($"Read only normally2 {count}[{ReadPosition - count} to {ReadPosition}]"); |  | ||||||
|                     return count; |  | ||||||
|                 } |  | ||||||
|                 // B: if i can't read as much, read to the end, |  | ||||||
|                 var readNormaly = BufferSize - ReadPosition; |  | ||||||
|                 Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, readNormaly); |  | ||||||
|  |  | ||||||
|                 //Console.WriteLine($"Read normaly {count}[{ReadPosition} to {ReadPosition + readNormaly}]"); |  | ||||||
|                 //then read the remaining amount from the start |  | ||||||
|  |  | ||||||
|                 var readFromStart = count - readNormaly; |  | ||||||
|                 Buffer.BlockCopy(ringBuffer, 0, buffer, readNormaly, readFromStart); |  | ||||||
|                 //Console.WriteLine($"Read From start {readFromStart}[{0} to {readFromStart}]"); |  | ||||||
|                 ReadPosition = readFromStart; |  | ||||||
|                 return count; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task WriteAsync(byte[] buffer, int count, CancellationToken cancelToken) |         public async Task WriteAsync(byte[] buffer, int count, CancellationToken cancelToken) | ||||||
| @@ -89,32 +95,37 @@ namespace NadekoBot.Modules.Music.Classes | |||||||
|                 if (cancelToken.IsCancellationRequested) |                 if (cancelToken.IsCancellationRequested) | ||||||
|                     return; |                     return; | ||||||
|             } |             } | ||||||
|             //the while above assures that i cannot write past readposition with my write, so i don't have to check |             await Task.Run(async () => | ||||||
|             // *unless its multithreaded or task is not awaited |  | ||||||
|             lock (readWriteLock) |  | ||||||
|             { |             { | ||||||
|                 // if i can just write without hitting buffer.length, do it |                 //the while above assures that i cannot write past readposition with my write, so i don't have to check | ||||||
|                 if (WritePosition + count < BufferSize) |                 // *unless its multithreaded or task is not awaited | ||||||
|  |                 await readWriteLock.WaitAsync().ConfigureAwait(false); | ||||||
|  |                 try | ||||||
|                 { |                 { | ||||||
|                     Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count); |                     // if i can just write without hitting buffer.length, do it | ||||||
|                     WritePosition += count; |                     if (WritePosition + count < BufferSize) | ||||||
|                     //Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]"); |                     { | ||||||
|                     return; |                         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 |                 finally { readWriteLock.Release(); } | ||||||
|  |             }); | ||||||
|                 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; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -155,7 +155,7 @@ namespace NadekoBot.Modules.Music.Classes | |||||||
|             { |             { | ||||||
|                 //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); |                 //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); | ||||||
|                 byte[] buffer = new byte[blockSize]; |                 byte[] buffer = new byte[blockSize]; | ||||||
|                 var read = songBuffer.Read(buffer, blockSize); |                 var read = await songBuffer.ReadAsync(buffer, blockSize).ConfigureAwait(false); | ||||||
|                 unchecked |                 unchecked | ||||||
|                 { |                 { | ||||||
|                     bytesSent += (ulong)read; |                     bytesSent += (ulong)read; | ||||||
|   | |||||||
| @@ -689,7 +689,7 @@ namespace NadekoBot.Modules.Permissions | |||||||
|                             if (!e.Message.MentionedUsers.Any()) return; |                             if (!e.Message.MentionedUsers.Any()) return; | ||||||
|                             var usr = e.Message.MentionedUsers.First(); |                             var usr = e.Message.MentionedUsers.First(); | ||||||
|                             NadekoBot.Config.UserBlacklist.Add(usr.Id); |                             NadekoBot.Config.UserBlacklist.Add(usr.Id); | ||||||
|                             ConfigHandler.SaveConfig(); |                             await ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|                             await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false); |                             await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false); | ||||||
|                         }).ConfigureAwait(false); |                         }).ConfigureAwait(false); | ||||||
|                     }); |                     }); | ||||||
| @@ -707,7 +707,7 @@ namespace NadekoBot.Modules.Permissions | |||||||
|                            if (NadekoBot.Config.UserBlacklist.Contains(usr.Id)) |                            if (NadekoBot.Config.UserBlacklist.Contains(usr.Id)) | ||||||
|                            { |                            { | ||||||
|                                NadekoBot.Config.UserBlacklist.Remove(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); |                                await e.Channel.SendMessage($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false); | ||||||
|                            } |                            } | ||||||
|                            else |                            else | ||||||
| @@ -727,7 +727,7 @@ namespace NadekoBot.Modules.Permissions | |||||||
|                             if (!e.Message.MentionedChannels.Any()) return; |                             if (!e.Message.MentionedChannels.Any()) return; | ||||||
|                             var ch = e.Message.MentionedChannels.First(); |                             var ch = e.Message.MentionedChannels.First(); | ||||||
|                             NadekoBot.Config.UserBlacklist.Add(ch.Id); |                             NadekoBot.Config.UserBlacklist.Add(ch.Id); | ||||||
|                             ConfigHandler.SaveConfig(); |                             await ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|                             await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); |                             await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); | ||||||
|                         }).ConfigureAwait(false); |                         }).ConfigureAwait(false); | ||||||
|                     }); |                     }); | ||||||
| @@ -742,7 +742,7 @@ namespace NadekoBot.Modules.Permissions | |||||||
|                             if (!e.Message.MentionedChannels.Any()) return; |                             if (!e.Message.MentionedChannels.Any()) return; | ||||||
|                             var ch = e.Message.MentionedChannels.First(); |                             var ch = e.Message.MentionedChannels.First(); | ||||||
|                             NadekoBot.Config.UserBlacklist.Remove(ch.Id); |                             NadekoBot.Config.UserBlacklist.Remove(ch.Id); | ||||||
|                             ConfigHandler.SaveConfig(); |                             await ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|                             await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); |                             await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); | ||||||
|                         }).ConfigureAwait(false); |                         }).ConfigureAwait(false); | ||||||
|                     }); |                     }); | ||||||
| @@ -767,7 +767,7 @@ namespace NadekoBot.Modules.Permissions | |||||||
|                             } |                             } | ||||||
|                             var serverId = server.Id; |                             var serverId = server.Id; | ||||||
|                             NadekoBot.Config.ServerBlacklist.Add(serverId); |                             NadekoBot.Config.ServerBlacklist.Add(serverId); | ||||||
|                             ConfigHandler.SaveConfig(); |                             await ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|                             //cleanup trivias and typeracing |                             //cleanup trivias and typeracing | ||||||
|                             Modules.Games.Commands.Trivia.TriviaGame trivia; |                             Modules.Games.Commands.Trivia.TriviaGame trivia; | ||||||
|                             TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia); |                             TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia); | ||||||
|   | |||||||
| @@ -30,8 +30,6 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static Dictionary<string, CachedChampion> CachedChampionImages = new Dictionary<string, CachedChampion>(); |         private static Dictionary<string, CachedChampion> CachedChampionImages = new Dictionary<string, CachedChampion>(); | ||||||
|         private readonly object cacheLock = new object(); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|         private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer(); |         private System.Timers.Timer clearTimer { get; } = new System.Timers.Timer(); | ||||||
|         public LoLCommands(DiscordModule module) : base(module) |         public LoLCommands(DiscordModule module) : base(module) | ||||||
| @@ -42,7 +40,6 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|             { |             { | ||||||
|                 try |                 try | ||||||
|                 { |                 { | ||||||
|                     lock (cacheLock) |  | ||||||
|                         CachedChampionImages = CachedChampionImages |                         CachedChampionImages = CachedChampionImages | ||||||
|                             .Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0)) |                             .Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0)) | ||||||
|                             .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); |                             .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); | ||||||
| @@ -87,16 +84,14 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|                           var resolvedRole = role; |                           var resolvedRole = role; | ||||||
|                           var name = e.GetArg("champ").Replace(" ", "").ToLower(); |                           var name = e.GetArg("champ").Replace(" ", "").ToLower(); | ||||||
|                           CachedChampion champ = null; |                           CachedChampion champ = null; | ||||||
|                           lock (cacheLock) |  | ||||||
|                           { |                           if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ)) | ||||||
|                               CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); |                               if (champ != null) | ||||||
|                           } |                               { | ||||||
|                           if (champ != null) |                                   champ.ImageStream.Position = 0; | ||||||
|                           { |                                   await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); | ||||||
|                               champ.ImageStream.Position = 0; |                                   return; | ||||||
|                               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)); |                           var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false)); | ||||||
|                           JToken data = null; |                           JToken data = null; | ||||||
|                           if (role != null) |                           if (role != null) | ||||||
| @@ -121,17 +116,13 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|                               role = allData[0]["role"].ToString(); |                               role = allData[0]["role"].ToString(); | ||||||
|                               resolvedRole = ResolvePos(role); |                               resolvedRole = ResolvePos(role); | ||||||
|                           } |                           } | ||||||
|                           lock (cacheLock) |                           if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ)) | ||||||
|                           { |                               if (champ != null) | ||||||
|                               CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ); |                               { | ||||||
|                           } |                                   champ.ImageStream.Position = 0; | ||||||
|                           if (champ != null) |                                   await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); | ||||||
|                           { |                                   return; | ||||||
|                               Console.WriteLine("Sending lol image from cache."); |                               } | ||||||
|                               champ.ImageStream.Position = 0; |  | ||||||
|                               await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false); |  | ||||||
|                               return; |  | ||||||
|                           } |  | ||||||
|                           //name = data["title"].ToString(); |                           //name = data["title"].ToString(); | ||||||
|                           // get all possible roles, and "select" the shown one |                           // get all possible roles, and "select" the shown one | ||||||
|                           var roles = new string[allData.Count]; |                           var roles = new string[allData.Count]; | ||||||
|   | |||||||
| @@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 catch { } |                 catch { } | ||||||
|                 ConfigHandler.SaveConfig(); |                 await ConfigHandler.SaveConfig().ConfigureAwait(false); | ||||||
|             }; |             }; | ||||||
|             checkTimer.Start(); |             checkTimer.Start(); | ||||||
|         } |         } | ||||||
| @@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Searches.Commands | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     config.ObservingStreams.Remove(toRemove); |                     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); |                     await e.Channel.SendMessage($":ok: Removed `{toRemove.Username}`'s stream from notifications.").ConfigureAwait(false); | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -197,7 +197,7 @@ namespace NadekoBot | |||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
| #if NADEKO_RELEASE | #if NADEKO_RELEASE | ||||||
|                 await Task.Delay(90000).ConfigureAwait(false); |                 await Task.Delay(100000).ConfigureAwait(false); | ||||||
| #else | #else | ||||||
|                 await Task.Delay(1000).ConfigureAwait(false); |                 await Task.Delay(1000).ConfigureAwait(false); | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -78,13 +78,14 @@ | |||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> |   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> | ||||||
|     <DebugSymbols>true</DebugSymbols> |     <DebugSymbols>true</DebugSymbols> | ||||||
|     <OutputPath>bin\x64\Debug\</OutputPath> |     <OutputPath>bin\Debug\</OutputPath> | ||||||
|     <DefineConstants>TRACE;DEBUG</DefineConstants> |     <DefineConstants>TRACE;DEBUG</DefineConstants> | ||||||
|     <DebugType>full</DebugType> |     <DebugType>full</DebugType> | ||||||
|     <PlatformTarget>x64</PlatformTarget> |     <PlatformTarget>x64</PlatformTarget> | ||||||
|     <ErrorReport>prompt</ErrorReport> |     <ErrorReport>prompt</ErrorReport> | ||||||
|     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> |     <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet> | ||||||
|     <Prefer32Bit>true</Prefer32Bit> |     <Prefer32Bit>true</Prefer32Bit> | ||||||
|  |     <Optimize>false</Optimize> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> |   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> | ||||||
|     <OutputPath>bin\x64\Release\</OutputPath> |     <OutputPath>bin\x64\Release\</OutputPath> | ||||||
|   | |||||||
| @@ -4,6 +4,8 @@ using Newtonsoft.Json; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
| using System.Runtime.Serialization; | using System.Runtime.Serialization; | ||||||
|  | using System.Threading; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace NadekoBot.Classes.JSONModels | namespace NadekoBot.Classes.JSONModels | ||||||
| { | { | ||||||
| @@ -187,13 +189,17 @@ Nadeko Support Server: <https://discord.gg/0ehQwTK2RBjAxzEY>"; | |||||||
|  |  | ||||||
|     public static class ConfigHandler |     public static class ConfigHandler | ||||||
|     { |     { | ||||||
|         private static readonly object configLock = new object(); |         private static readonly SemaphoreSlim configLock = new SemaphoreSlim(1, 1); | ||||||
|         public static void SaveConfig() |         public static async Task SaveConfig() | ||||||
|         { |         { | ||||||
|             lock (configLock) |             await configLock.WaitAsync(); | ||||||
|  |             try | ||||||
|             { |             { | ||||||
|                 File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented)); |                 File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented)); | ||||||
|             } |             } | ||||||
|  |             finally { | ||||||
|  |                 configLock.Release(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) || |         public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) || | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user