Changed all locks to SemaphoreSlims, Slight musicbuffer changes.
This commit is contained in:
parent
106a779552
commit
e66615b056
@ -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) ||
|
||||||
|
Loading…
Reference in New Issue
Block a user