commit
54bed4ecc9
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +1,6 @@
|
||||
[submodule "discord.net"]
|
||||
path = discord.net
|
||||
url = git://github.com/kwoth/discord.net.git
|
||||
[submodule "ffmpeg-installer"]
|
||||
path = ffmpeg-installer
|
||||
url = https://github.com/kwoth/ffmpeg-installer
|
||||
|
@ -36,9 +36,7 @@ ________________________________________________________________________________
|
||||
###### Setting up `ffmpeg` with installer:
|
||||
1) Google Account
|
||||
2) Soundcloud Account (if you want soundcloud support)
|
||||
|
||||
3) Download installer here: http://luxcaeli.de/owncloud/s/fIxSgh4Nde3Td6e/download
|
||||
|
||||
3) Download installer here: https://goo.gl/lQZnsH (pick the one for your system, either 32 or 64bit and then click 'download')
|
||||
4) Run the installer
|
||||
|
||||
5) Follow these steps on how to setup API keys:
|
||||
|
@ -138,7 +138,7 @@ namespace NadekoBot.Extensions
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="list"></param>
|
||||
public static void Shuffle<T>(this IList<T> list)
|
||||
public static IList<T> Shuffle<T>(this IList<T> list)
|
||||
{
|
||||
|
||||
// Thanks to @Joe4Evr for finding a bug in the old version of the shuffle
|
||||
@ -160,6 +160,7 @@ namespace NadekoBot.Extensions
|
||||
list[k] = list[n];
|
||||
list[n] = value;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -303,6 +304,15 @@ namespace NadekoBot.Extensions
|
||||
public static int GiB(this int value) => value.MiB() * 1024;
|
||||
public static int GB(this int value) => value.MB() * 1000;
|
||||
|
||||
public static ulong KiB(this ulong value) => value * 1024;
|
||||
public static ulong KB(this ulong value) => value * 1000;
|
||||
|
||||
public static ulong MiB(this ulong value) => value.KiB() * 1024;
|
||||
public static ulong MB(this ulong value) => value.KB() * 1000;
|
||||
|
||||
public static ulong GiB(this ulong value) => value.MiB() * 1024;
|
||||
public static ulong GB(this ulong value) => value.MB() * 1000;
|
||||
|
||||
public static Stream ToStream(this Image img, System.Drawing.Imaging.ImageFormat format = null)
|
||||
{
|
||||
if (format == null)
|
||||
@ -362,5 +372,7 @@ namespace NadekoBot.Extensions
|
||||
return sw.BaseStream;
|
||||
}
|
||||
|
||||
public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,10 @@ using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Administration.Commands;
|
||||
using NadekoBot.Modules.Music;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
@ -41,7 +43,23 @@ namespace NadekoBot
|
||||
var commandService = NadekoBot.Client.GetService<CommandService>();
|
||||
|
||||
statsStopwatch.Start();
|
||||
|
||||
commandService.CommandExecuted += StatsCollector_RanCommand;
|
||||
commandService.CommandFinished += CommandService_CommandFinished;
|
||||
commandService.CommandErrored += (s, e) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (e.ErrorType == CommandErrorType.Exception)
|
||||
File.AppendAllText("errors.txt", $@"Command: {e.Command}
|
||||
{e.Exception}
|
||||
-------------------------------------
|
||||
");
|
||||
}
|
||||
catch {
|
||||
Console.WriteLine("Command errored errorring");
|
||||
}
|
||||
};
|
||||
|
||||
Task.Run(StartCollecting);
|
||||
|
||||
@ -97,7 +115,7 @@ namespace NadekoBot
|
||||
if (e.Channel.IsPrivate)
|
||||
return;
|
||||
if (e.Channel.Type == ChannelType.Text)
|
||||
VoiceChannelsCount++;
|
||||
TextChannelsCount--;
|
||||
else if (e.Channel.Type == ChannelType.Voice)
|
||||
VoiceChannelsCount--;
|
||||
}
|
||||
@ -106,6 +124,7 @@ namespace NadekoBot
|
||||
carbonStatusTimer.Elapsed += async (s, e) => await SendUpdateToCarbon().ConfigureAwait(false);
|
||||
carbonStatusTimer.Start();
|
||||
}
|
||||
|
||||
HttpClient carbonClient = new HttpClient();
|
||||
private async Task SendUpdateToCarbon()
|
||||
{
|
||||
@ -176,9 +195,11 @@ namespace NadekoBot
|
||||
|
||||
private async Task StartCollecting()
|
||||
{
|
||||
var statsSw = new Stopwatch();
|
||||
while (true)
|
||||
{
|
||||
await Task.Delay(new TimeSpan(0, 30, 0)).ConfigureAwait(false);
|
||||
statsSw.Start();
|
||||
try
|
||||
{
|
||||
var onlineUsers = await Task.Run(() => NadekoBot.Client.Servers.Sum(x => x.Users.Count())).ConfigureAwait(false);
|
||||
@ -195,6 +216,13 @@ namespace NadekoBot
|
||||
ConnectedServers = connectedServers,
|
||||
DateAdded = DateTime.Now
|
||||
});
|
||||
|
||||
statsSw.Stop();
|
||||
var clr = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
Console.WriteLine($"--------------\nCollecting stats finished in {statsSw.Elapsed.TotalSeconds}s\n-------------");
|
||||
Console.ForegroundColor = clr;
|
||||
statsSw.Reset();
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -204,9 +232,21 @@ namespace NadekoBot
|
||||
}
|
||||
}
|
||||
|
||||
private static ConcurrentDictionary<ulong, DateTime> commandTracker = new ConcurrentDictionary<ulong, DateTime>();
|
||||
|
||||
private void CommandService_CommandFinished(object sender, CommandEventArgs e)
|
||||
{
|
||||
DateTime dt;
|
||||
if (!commandTracker.TryGetValue(e.Message.Id, out dt))
|
||||
return;
|
||||
Console.WriteLine($">>COMMAND ENDED after *{(DateTime.UtcNow - dt).TotalSeconds}s*\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
|
||||
}
|
||||
|
||||
private async void StatsCollector_RanCommand(object sender, CommandEventArgs e)
|
||||
{
|
||||
Console.WriteLine($">> Cmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
|
||||
commandTracker.TryAdd(e.Message.Id, DateTime.UtcNow);
|
||||
Console.WriteLine($">>COMMAND STARTED\nCmd: {e.Command.Text}\nMsg: {e.Message.Text}\nUsr: {e.User.Name} [{e.User.Id}]\nSrvr: {e.Server?.Name ?? "PRIVATE"} [{e.Server?.Id}]\n-----");
|
||||
#if !NADEKO_RELEASE
|
||||
await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
@ -230,6 +270,7 @@ namespace NadekoBot
|
||||
Console.WriteLine(ex);
|
||||
}
|
||||
}).ConfigureAwait(false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -364,9 +364,7 @@ namespace NadekoBot.Classes
|
||||
}
|
||||
|
||||
var httpResponse = (await httpWebRequest.GetResponseAsync().ConfigureAwait(false)) as HttpWebResponse;
|
||||
if (httpResponse == null) return "HTTP_RESPONSE_ERROR";
|
||||
var responseStream = httpResponse.GetResponseStream();
|
||||
if (responseStream == null) return "RESPONSE_STREAM ERROR";
|
||||
using (var streamReader = new StreamReader(responseStream))
|
||||
{
|
||||
var responseText = await streamReader.ReadToEndAsync().ConfigureAwait(false);
|
||||
@ -375,6 +373,7 @@ namespace NadekoBot.Classes
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Shortening of this url failed: " + url);
|
||||
Console.WriteLine(ex.ToString());
|
||||
return url;
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Classes
|
||||
{
|
||||
@ -27,9 +29,12 @@ namespace NadekoBot.Classes
|
||||
{
|
||||
configs = JsonConvert
|
||||
.DeserializeObject<ConcurrentDictionary<ulong, ServerSpecificConfig>>(
|
||||
File.ReadAllText(filePath), new JsonSerializerSettings() {
|
||||
Error = (s,e) => {
|
||||
if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels") {
|
||||
File.ReadAllText(filePath), new JsonSerializerSettings()
|
||||
{
|
||||
Error = (s, e) =>
|
||||
{
|
||||
if (e.ErrorContext.Member.ToString() == "GenerateCurrencyChannels")
|
||||
{
|
||||
e.ErrorContext.Handled = true;
|
||||
}
|
||||
}
|
||||
@ -52,14 +57,19 @@ namespace NadekoBot.Classes
|
||||
public ServerSpecificConfig Of(ulong id) =>
|
||||
configs.GetOrAdd(id, _ => new ServerSpecificConfig());
|
||||
|
||||
private readonly object saveLock = new object();
|
||||
private readonly SemaphoreSlim saveLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
public void Save()
|
||||
public async Task Save()
|
||||
{
|
||||
lock (saveLock)
|
||||
await saveLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented));
|
||||
}
|
||||
finally
|
||||
{
|
||||
saveLock.Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +255,7 @@ namespace NadekoBot.Classes
|
||||
LogserverIgnoreChannels = new ObservableCollection<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)
|
||||
{
|
||||
|
@ -70,7 +70,7 @@ namespace NadekoBot.Modules.Administration
|
||||
{
|
||||
var conf = SpecificConfigurations.Default.Of(e.Server.Id);
|
||||
conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
|
||||
Classes.JSONModels.ConfigHandler.SaveConfig();
|
||||
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
if (conf.AutoDeleteMessagesOnCommand)
|
||||
await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`");
|
||||
else
|
||||
@ -90,7 +90,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "setrole").Alias(Prefix + "sr")
|
||||
.Description("Sets a role for a given user. | .sr @User Guest")
|
||||
.Description($"Sets a role for a given user. | `{Prefix}sr @User Guest`")
|
||||
.Parameter("user_name", ParameterType.Required)
|
||||
.Parameter("role_name", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
@ -133,7 +133,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "removerole").Alias(Prefix + "rr")
|
||||
.Description("Removes a role from a given user. | .rr @User Admin")
|
||||
.Description($"Removes a role from a given user. | `{Prefix}rr @User Admin`")
|
||||
.Parameter("user_name", ParameterType.Required)
|
||||
.Parameter("role_name", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
@ -204,7 +204,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "removeallroles").Alias(Prefix + "rar")
|
||||
.Description("Removes all roles from a mentioned user. | .rar @User")
|
||||
.Description($"Removes all roles from a mentioned user. | `{Prefix}rar @User`")
|
||||
.Parameter("user_name", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
.Do(async e =>
|
||||
@ -230,7 +230,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "createrole").Alias(Prefix + "cr")
|
||||
.Description("Creates a role with a given name.**Usage**: `.r Awesome Role`")
|
||||
.Description($"Creates a role with a given name. | `{Prefix}cr Awesome Role`")
|
||||
.Parameter("role_name", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.CanManageRoles)
|
||||
.Do(async e =>
|
||||
@ -253,7 +253,7 @@ namespace NadekoBot.Modules.Administration
|
||||
.Parameter("r", ParameterType.Optional)
|
||||
.Parameter("g", ParameterType.Optional)
|
||||
.Parameter("b", ParameterType.Optional)
|
||||
.Description("Set a role's color to the hex or 0-255 rgb color value provided. | `.color Admin 255 200 100` or `.color Admin ffba55`")
|
||||
.Description($"Set a role's color to the hex or 0-255 rgb color value provided. | `{Prefix}rc Admin 255 200 100` or `{Prefix}rc Admin ffba55`")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageRoles)
|
||||
@ -298,7 +298,7 @@ namespace NadekoBot.Modules.Administration
|
||||
cgb.CreateCommand(Prefix + "ban").Alias(Prefix + "b")
|
||||
.Parameter("user", ParameterType.Required)
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.Description("Bans a user by id or name with an optional message. | .b \"@some Guy\" Your behaviour is toxic.")
|
||||
.Description($"Bans a user by id or name with an optional message. | `{Prefix}b \"@some Guy\" Your behaviour is toxic.`")
|
||||
.Do(async e =>
|
||||
{
|
||||
var msg = e.GetArg("msg");
|
||||
@ -333,7 +333,7 @@ namespace NadekoBot.Modules.Administration
|
||||
cgb.CreateCommand(Prefix + "softban").Alias(Prefix + "sb")
|
||||
.Parameter("user", ParameterType.Required)
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.Description("Bans and then unbans a user by id or name with an optional message. | .sb \"@some Guy\" Your behaviour is toxic.")
|
||||
.Description($"Bans and then unbans a user by id or name with an optional message. | `{Prefix}sb \"@some Guy\" Your behaviour is toxic.`")
|
||||
.Do(async e =>
|
||||
{
|
||||
var msg = e.GetArg("msg");
|
||||
@ -369,7 +369,7 @@ namespace NadekoBot.Modules.Administration
|
||||
cgb.CreateCommand(Prefix + "kick").Alias(Prefix + "k")
|
||||
.Parameter("user")
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.Description("Kicks a mentioned user.")
|
||||
.Description($"Kicks a mentioned user. | `{Prefix}k \"@some Guy\" Your behaviour is toxic.`")
|
||||
.Do(async e =>
|
||||
{
|
||||
var msg = e.GetArg("msg");
|
||||
@ -400,7 +400,7 @@ namespace NadekoBot.Modules.Administration
|
||||
}
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "mute")
|
||||
.Description("Mutes mentioned user or users.")
|
||||
.Description($"Mutes mentioned user or users. | `{Prefix}mute \"@Someguy\"` or `{Prefix}mute \"@Someguy\" \"@Someguy\"`")
|
||||
.Parameter("throwaway", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -426,7 +426,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "unmute")
|
||||
.Description("Unmutes mentioned user or users.")
|
||||
.Description($"Unmutes mentioned user or users. | `{Prefix}unmute \"@Someguy\"` or `{Prefix}unmute \"@Someguy\" \"@Someguy\"`")
|
||||
.Parameter("throwaway", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -453,7 +453,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "deafen")
|
||||
.Alias(Prefix + "deaf")
|
||||
.Description("Deafens mentioned user or users")
|
||||
.Description($"Deafens mentioned user or users | `{Prefix}deaf \"@Someguy\"` or `{Prefix}deaf \"@Someguy\" \"@Someguy\"`")
|
||||
.Parameter("throwaway", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -480,7 +480,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "undeafen")
|
||||
.Alias(Prefix + "undef")
|
||||
.Description("Undeafens mentioned user or users")
|
||||
.Description($"Undeafens mentioned user or users | `{Prefix}undef \"@Someguy\"` or `{Prefix}undef \"@Someguy\" \"@Someguy\"`")
|
||||
.Parameter("throwaway", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -507,7 +507,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "delvoichanl")
|
||||
.Alias(Prefix + "dvch")
|
||||
.Description("Deletes a voice channel with a given name.")
|
||||
.Description($"Deletes a voice channel with a given name. | `{Prefix}dvch VoiceChannelName`")
|
||||
.Parameter("channel_name", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -530,7 +530,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "creatvoichanl")
|
||||
.Alias(Prefix + "cvch")
|
||||
.Description("Creates a new voice channel with a given name.")
|
||||
.Description($"Creates a new voice channel with a given name. | `{Prefix}cvch VoiceChannelName`")
|
||||
.Parameter("channel_name", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -550,7 +550,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "deltxtchanl")
|
||||
.Alias(Prefix + "dtch")
|
||||
.Description("Deletes a text channel with a given name.")
|
||||
.Description($"Deletes a text channel with a given name. | `{Prefix}dtch TextChannelName`")
|
||||
.Parameter("channel_name", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -572,7 +572,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "creatxtchanl")
|
||||
.Alias(Prefix + "ctch")
|
||||
.Description("Creates a new text channel with a given name.")
|
||||
.Description($"Creates a new text channel with a given name. | `{Prefix}ctch TextChannelName`")
|
||||
.Parameter("channel_name", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -604,7 +604,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "setchanlname")
|
||||
.Alias(Prefix + "schn")
|
||||
.Description("Changed the name of the current channel.")
|
||||
.Description($"Changed the name of the current channel.| `{Prefix}schn NewName`")
|
||||
.AddCheck(SimpleCheckers.ManageChannels())
|
||||
.Parameter("name", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
@ -636,7 +636,8 @@ namespace NadekoBot.Modules.Administration
|
||||
Message[] msgs;
|
||||
if (string.IsNullOrWhiteSpace(e.GetArg("user_or_num"))) // if nothing is set, clear nadeko's messages, no permissions required
|
||||
{
|
||||
msgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false)).Where(m => m.User.Id == e.Server.CurrentUser.Id).ToArray();
|
||||
msgs = (await e.Channel.DownloadMessages(100).ConfigureAwait(false));//.Where(m => m.User.Id == e.Server.CurrentUser.Id).ToArray();
|
||||
msgs = msgs.Where(m => m.User.Id == e.Server.CurrentUser.Id).ToArray();
|
||||
if (!msgs.Any())
|
||||
return;
|
||||
await e.Channel.DeleteMessages(msgs).ConfigureAwait(false);
|
||||
@ -684,7 +685,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "setname")
|
||||
.Alias(Prefix + "newnm")
|
||||
.Description("Give the bot a new name. **Bot Owner Only!**")
|
||||
.Description($"Give the bot a new name. **Bot Owner Only!** | {Prefix}newnm BotName")
|
||||
.Parameter("new_name", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -696,7 +697,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "newavatar")
|
||||
.Alias(Prefix + "setavatar")
|
||||
.Description("Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!** | `.setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg`")
|
||||
.Description($"Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!** | `{Prefix}setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg`")
|
||||
.Parameter("img", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -717,7 +718,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "setgame")
|
||||
.Description("Sets the bots game. **Bot Owner Only!**")
|
||||
.Description($"Sets the bots game. **Bot Owner Only!** | `{Prefix}setgame Playing with kwoth`")
|
||||
.Parameter("set_game", ParameterType.Unparsed)
|
||||
.Do(e =>
|
||||
{
|
||||
@ -727,7 +728,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "send")
|
||||
.Description("Send a message to someone on a different server through the bot. **Bot Owner Only!** | `.send serverid|u:user_id Send this to a user!` or `.send serverid|c:channel_id Send this to a channel!`")
|
||||
.Description($"Send a message to someone on a different server through the bot. **Bot Owner Only!** | `{Prefix}send serverid|u:user_id Send this to a user!` or `{Prefix}send serverid|c:channel_id Send this to a channel!`")
|
||||
.Parameter("ids", ParameterType.Required)
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
@ -775,7 +776,7 @@ namespace NadekoBot.Modules.Administration
|
||||
|
||||
cgb.CreateCommand(Prefix + "mentionrole")
|
||||
.Alias(Prefix + "menro")
|
||||
.Description("Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission.")
|
||||
.Description($"Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission. | `{Prefix}menro RoleName`")
|
||||
.Parameter("roles", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -828,7 +829,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "donadd")
|
||||
.Description("Add a donator to the database.")
|
||||
.Description($"Add a donator to the database. | `.donadd Donate Amount`")
|
||||
.Parameter("donator")
|
||||
.Parameter("amount")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
@ -854,7 +855,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "announce")
|
||||
.Description($"Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | {Prefix}announce Useless spam")
|
||||
.Description($"Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | `{Prefix}announce Useless spam`")
|
||||
.Parameter("msg", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -868,7 +869,7 @@ namespace NadekoBot.Modules.Administration
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "savechat")
|
||||
.Description("Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.chatsave 150`")
|
||||
.Description($"Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `{Prefix}savechat 150`")
|
||||
.Parameter("cnt", ParameterType.Required)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
|
@ -40,7 +40,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
NadekoBot.Config.CustomReactions[name].Add(message);
|
||||
else
|
||||
NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<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);
|
||||
|
||||
});
|
||||
@ -140,7 +140,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
index = index - 1;
|
||||
NadekoBot.Config.CustomReactions[name][index] = msg;
|
||||
|
||||
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false);
|
||||
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false);
|
||||
});
|
||||
|
||||
@ -183,7 +183,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
NadekoBot.Config.CustomReactions.Remove(name);
|
||||
message = $"Deleted custom reaction: `{name}`";
|
||||
}
|
||||
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false);
|
||||
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage(message).ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
@ -7,8 +7,10 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Timers;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
@ -36,7 +38,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
{"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()}
|
||||
};
|
||||
|
||||
private readonly object playingPlaceholderLock = new object();
|
||||
private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1,1);
|
||||
|
||||
public PlayingRotate(DiscordModule module) : base(module)
|
||||
{
|
||||
@ -47,7 +49,9 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
{
|
||||
i++;
|
||||
var status = "";
|
||||
lock (playingPlaceholderLock)
|
||||
//wtf am i doing, just use a queue ffs
|
||||
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (PlayingPlaceholders.Count == 0
|
||||
|| NadekoBot.Config.RotatingStatuses.Count == 0
|
||||
@ -59,6 +63,7 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
status = PlayingPlaceholders.Aggregate(status,
|
||||
(current, kvp) => current.Replace(kvp.Key, kvp.Value()));
|
||||
}
|
||||
finally { playingPlaceholderLock.Release(); }
|
||||
if (string.IsNullOrWhiteSpace(status))
|
||||
return;
|
||||
await Task.Run(() => { NadekoBot.Client.SetGame(status); });
|
||||
@ -71,14 +76,18 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
|
||||
public Func<CommandEventArgs, Task> DoFunc() => async e =>
|
||||
{
|
||||
lock (playingPlaceholderLock)
|
||||
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (timer.Enabled)
|
||||
timer.Stop();
|
||||
else
|
||||
timer.Start();
|
||||
NadekoBot.Config.IsRotatingStatus = timer.Enabled;
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
}
|
||||
finally {
|
||||
playingPlaceholderLock.Release();
|
||||
}
|
||||
await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false);
|
||||
};
|
||||
@ -102,10 +111,15 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
var arg = e.GetArg("text");
|
||||
if (string.IsNullOrWhiteSpace(arg))
|
||||
return;
|
||||
lock (playingPlaceholderLock)
|
||||
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
NadekoBot.Config.RotatingStatuses.Add(arg);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig();
|
||||
}
|
||||
finally
|
||||
{
|
||||
playingPlaceholderLock.Release();
|
||||
}
|
||||
await e.Channel.SendMessage("🆗 `Added a new playing string.`").ConfigureAwait(false);
|
||||
});
|
||||
@ -137,14 +151,15 @@ namespace NadekoBot.Modules.Administration.Commands
|
||||
var arg = e.GetArg("number");
|
||||
int num;
|
||||
string str;
|
||||
lock (playingPlaceholderLock)
|
||||
{
|
||||
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
|
||||
try {
|
||||
if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count)
|
||||
return;
|
||||
str = NadekoBot.Config.RotatingStatuses[num - 1];
|
||||
NadekoBot.Config.RotatingStatuses.RemoveAt(num - 1);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
}
|
||||
finally { playingPlaceholderLock.Release(); }
|
||||
await e.Channel.SendMessage($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false);
|
||||
});
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
using Discord.Commands;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
//using Manatee.Json.Serialization;
|
||||
|
||||
namespace NadekoBot.Classes.ClashOfClans
|
||||
{
|
||||
@ -11,16 +10,22 @@ namespace NadekoBot.Classes.ClashOfClans
|
||||
{
|
||||
One, Two, Three
|
||||
}
|
||||
public enum WarState
|
||||
{
|
||||
Started, Ended, Created
|
||||
}
|
||||
[System.Serializable]
|
||||
internal class Caller
|
||||
{
|
||||
public string CallUser { get; }
|
||||
public string CallUser { get; set; }
|
||||
|
||||
public DateTime TimeAdded { get; private set; }
|
||||
public DateTime TimeAdded { get; set; }
|
||||
|
||||
public bool BaseDestroyed { get; internal set; }
|
||||
public bool BaseDestroyed { get; set; }
|
||||
|
||||
public int Stars { get; set; } = 3;
|
||||
|
||||
public Caller() { }
|
||||
|
||||
public Caller(string callUser, DateTime timeAdded, bool baseDestroyed)
|
||||
{
|
||||
@ -31,7 +36,7 @@ namespace NadekoBot.Classes.ClashOfClans
|
||||
|
||||
public void ResetTime()
|
||||
{
|
||||
TimeAdded = DateTime.Now;
|
||||
TimeAdded = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
public void Destroy()
|
||||
@ -44,97 +49,84 @@ namespace NadekoBot.Classes.ClashOfClans
|
||||
{
|
||||
private static TimeSpan callExpire => new TimeSpan(2, 0, 0);
|
||||
|
||||
public string EnemyClan { get; }
|
||||
public int Size { get; }
|
||||
public string EnemyClan { get; set; }
|
||||
public int Size { get; set; }
|
||||
|
||||
private Caller[] bases { get; }
|
||||
private CancellationTokenSource[] baseCancelTokens;
|
||||
private CancellationTokenSource endTokenSource { get; } = new CancellationTokenSource();
|
||||
public event Action<string> OnUserTimeExpired = delegate { };
|
||||
public event Action OnWarEnded = delegate { };
|
||||
public bool Started { get; set; } = false;
|
||||
public Caller[] Bases { get; set; }
|
||||
public WarState WarState { get; set; } = WarState.Created;
|
||||
//public bool Started { get; set; } = false;
|
||||
public DateTime StartedAt { get; set; }
|
||||
//public bool Ended { get; private set; } = false;
|
||||
|
||||
public ClashWar(string enemyClan, int size, CommandEventArgs e)
|
||||
public ulong ServerId { get; set; }
|
||||
public ulong ChannelId { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public Discord.Channel Channel { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// This init is purely for the deserialization
|
||||
/// </summary>
|
||||
public ClashWar() { }
|
||||
|
||||
public ClashWar(string enemyClan, int size, ulong serverId, ulong channelId)
|
||||
{
|
||||
this.EnemyClan = enemyClan;
|
||||
this.Size = size;
|
||||
this.bases = new Caller[size];
|
||||
this.baseCancelTokens = new CancellationTokenSource[size];
|
||||
this.Bases = new Caller[size];
|
||||
this.ServerId = serverId;
|
||||
this.ChannelId = channelId;
|
||||
this.Channel = NadekoBot.Client.Servers.FirstOrDefault(s => s.Id == serverId)?.TextChannels.FirstOrDefault(c => c.Id == channelId);
|
||||
}
|
||||
|
||||
internal void End()
|
||||
{
|
||||
if (endTokenSource.Token.IsCancellationRequested) return;
|
||||
endTokenSource.Cancel();
|
||||
OnWarEnded();
|
||||
//Ended = true;
|
||||
WarState = WarState.Ended;
|
||||
}
|
||||
|
||||
internal void Call(string u, int baseNumber)
|
||||
{
|
||||
if (baseNumber < 0 || baseNumber >= bases.Length)
|
||||
if (baseNumber < 0 || baseNumber >= Bases.Length)
|
||||
throw new ArgumentException("Invalid base number");
|
||||
if (bases[baseNumber] != null)
|
||||
if (Bases[baseNumber] != null)
|
||||
throw new ArgumentException("That base is already claimed.");
|
||||
for (var i = 0; i < bases.Length; i++)
|
||||
for (var i = 0; i < Bases.Length; i++)
|
||||
{
|
||||
if (bases[i]?.BaseDestroyed == false && bases[i]?.CallUser == u)
|
||||
throw new ArgumentException($"@{u} You already claimed a base #{i + 1}. You can't claim a new one.");
|
||||
if (Bases[i]?.BaseDestroyed == false && Bases[i]?.CallUser == u)
|
||||
throw new ArgumentException($"@{u} You already claimed base #{i + 1}. You can't claim a new one.");
|
||||
}
|
||||
|
||||
bases[baseNumber] = new Caller(u.Trim(), DateTime.Now, false);
|
||||
Bases[baseNumber] = new Caller(u.Trim(), DateTime.UtcNow, false);
|
||||
}
|
||||
|
||||
internal async Task Start()
|
||||
internal void Start()
|
||||
{
|
||||
if (Started)
|
||||
throw new InvalidOperationException();
|
||||
try
|
||||
if (WarState == WarState.Started)
|
||||
throw new InvalidOperationException("War already started");
|
||||
//if (Started)
|
||||
// throw new InvalidOperationException();
|
||||
//Started = true;
|
||||
WarState = WarState.Started;
|
||||
StartedAt = DateTime.UtcNow;
|
||||
foreach (var b in Bases.Where(b => b != null))
|
||||
{
|
||||
Started = true;
|
||||
foreach (var b in bases.Where(b => b != null))
|
||||
{
|
||||
b.ResetTime();
|
||||
}
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(async () => await ClearArray()).ConfigureAwait(false);
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
await Task.Delay(new TimeSpan(24, 0, 0), endTokenSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
finally
|
||||
{
|
||||
End();
|
||||
b.ResetTime();
|
||||
}
|
||||
}
|
||||
|
||||
internal int Uncall(string user)
|
||||
{
|
||||
user = user.Trim();
|
||||
for (var i = 0; i < bases.Length; i++)
|
||||
for (var i = 0; i < Bases.Length; i++)
|
||||
{
|
||||
if (bases[i]?.CallUser != user) continue;
|
||||
bases[i] = null;
|
||||
if (Bases[i]?.CallUser != user) continue;
|
||||
Bases[i] = null;
|
||||
return i;
|
||||
}
|
||||
throw new InvalidOperationException("You are not participating in that war.");
|
||||
}
|
||||
|
||||
private async Task ClearArray()
|
||||
{
|
||||
while (!endTokenSource.IsCancellationRequested)
|
||||
{
|
||||
await Task.Delay(5000).ConfigureAwait(false);
|
||||
for (var i = 0; i < bases.Length; i++)
|
||||
{
|
||||
if (bases[i] == null) continue;
|
||||
if (!bases[i].BaseDestroyed && DateTime.Now - bases[i].TimeAdded >= callExpire)
|
||||
{
|
||||
OnUserTimeExpired(bases[i].CallUser);
|
||||
bases[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string ShortPrint() =>
|
||||
$"`{EnemyClan}` ({Size} v {Size})";
|
||||
|
||||
@ -143,24 +135,24 @@ namespace NadekoBot.Classes.ClashOfClans
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine($"🔰**WAR AGAINST `{EnemyClan}` ({Size} v {Size}) INFO:**");
|
||||
if (!Started)
|
||||
if (WarState == WarState.Created)
|
||||
sb.AppendLine("`not started`");
|
||||
for (var i = 0; i < bases.Length; i++)
|
||||
for (var i = 0; i < Bases.Length; i++)
|
||||
{
|
||||
if (bases[i] == null)
|
||||
if (Bases[i] == null)
|
||||
{
|
||||
sb.AppendLine($"`{i + 1}.` ❌*unclaimed*");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bases[i].BaseDestroyed)
|
||||
if (Bases[i].BaseDestroyed)
|
||||
{
|
||||
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` {new string('⭐', bases[i].Stars)}");
|
||||
sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {new string('⭐', Bases[i].Stars)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
var left = Started ? callExpire - (DateTime.Now - bases[i].TimeAdded) : callExpire;
|
||||
sb.AppendLine($"`{i + 1}.` ✅ `{bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
|
||||
var left = (WarState == WarState.Started) ? callExpire - (DateTime.UtcNow - Bases[i].TimeAdded) : callExpire;
|
||||
sb.AppendLine($"`{i + 1}.` ✅ `{Bases[i].CallUser}` {left.Hours}h {left.Minutes}m {left.Seconds}s left");
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,11 +163,11 @@ namespace NadekoBot.Classes.ClashOfClans
|
||||
internal int FinishClaim(string user, int stars = 3)
|
||||
{
|
||||
user = user.Trim();
|
||||
for (var i = 0; i < bases.Length; i++)
|
||||
for (var i = 0; i < Bases.Length; i++)
|
||||
{
|
||||
if (bases[i]?.BaseDestroyed != false || bases[i]?.CallUser != user) continue;
|
||||
bases[i].BaseDestroyed = true;
|
||||
bases[i].Stars = stars;
|
||||
if (Bases[i]?.BaseDestroyed != false || Bases[i]?.CallUser != user) continue;
|
||||
Bases[i].BaseDestroyed = true;
|
||||
Bases[i].Stars = stars;
|
||||
return i;
|
||||
}
|
||||
throw new InvalidOperationException($"@{user} You are either not participating in that war, or you already destroyed a base.");
|
||||
|
@ -1,12 +1,15 @@
|
||||
using Discord.Commands;
|
||||
using Discord.Modules;
|
||||
using NadekoBot.Classes.ClashOfClans;
|
||||
using NadekoBot.Modules.Permissions.Classes;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Modules.Permissions.Classes;
|
||||
|
||||
namespace NadekoBot.Modules.ClashOfClans
|
||||
{
|
||||
@ -14,69 +17,172 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
{
|
||||
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.ClashOfClans;
|
||||
|
||||
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
|
||||
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();
|
||||
|
||||
private readonly object writeLock = new object();
|
||||
|
||||
public ClashOfClansModule()
|
||||
{
|
||||
NadekoBot.OnReady += () => Task.Run(async () =>
|
||||
{
|
||||
if (File.Exists("data/clashofclans/wars.json"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var content = File.ReadAllText("data/clashofclans/wars.json");
|
||||
|
||||
var dict = JsonConvert.DeserializeObject<Dictionary<ulong, List<ClashWar>>>(content);
|
||||
|
||||
foreach (var cw in dict)
|
||||
{
|
||||
cw.Value.ForEach(war =>
|
||||
{
|
||||
war.Channel = NadekoBot.Client.GetServer(war.ServerId)?.GetChannel(war.ChannelId);
|
||||
if (war.Channel == null)
|
||||
{
|
||||
cw.Value.Remove(war);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
//urgh
|
||||
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(dict);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Could not load coc wars: " + e.Message);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//Can't this be disabled if the modules is disabled too :)
|
||||
var callExpire = new TimeSpan(2, 0, 0);
|
||||
var warExpire = new TimeSpan(23, 0, 0);
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
var hash = ClashWars.GetHashCode();
|
||||
foreach (var cw in ClashWars)
|
||||
{
|
||||
foreach (var war in cw.Value)
|
||||
{
|
||||
await CheckWar(callExpire, war);
|
||||
}
|
||||
List<ClashWar> newVal = new List<ClashWar>();
|
||||
foreach (var w in cw.Value)
|
||||
{
|
||||
//We add when A: the war is not ended
|
||||
if (w.WarState != WarState.Ended)
|
||||
{
|
||||
//and B: the war has not expired
|
||||
if ((w.WarState == WarState.Started && DateTime.UtcNow - w.StartedAt <= warExpire) || w.WarState == WarState.Created)
|
||||
{
|
||||
newVal.Add(w);
|
||||
}
|
||||
}
|
||||
}
|
||||
//var newVal = cw.Value.Where(w => !(w.Ended || DateTime.UtcNow - w.StartedAt >= warExpire)).ToList();
|
||||
foreach (var exWar in cw.Value.Except(newVal))
|
||||
{
|
||||
await exWar.Channel.SendMessage($"War against {exWar.EnemyClan} ({exWar.Size}v{exWar.Size}) has ended");
|
||||
}
|
||||
|
||||
if (newVal.Count == 0)
|
||||
{
|
||||
List<ClashWar> obj;
|
||||
ClashWars.TryRemove(cw.Key, out obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClashWars.AddOrUpdate(cw.Key, newVal, (x, s) => newVal);
|
||||
}
|
||||
}
|
||||
if (hash != ClashWars.GetHashCode()) //something changed
|
||||
{
|
||||
Save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch { }
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory("data/clashofclans");
|
||||
File.WriteAllText("data/clashofclans/wars.json", JsonConvert.SerializeObject(ClashWars, Formatting.Indented));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task CheckWar(TimeSpan callExpire, ClashWar war)
|
||||
{
|
||||
var Bases = war.Bases;
|
||||
for (var i = 0; i < Bases.Length; i++)
|
||||
{
|
||||
if (Bases[i] == null) continue;
|
||||
if (!Bases[i].BaseDestroyed && DateTime.UtcNow - Bases[i].TimeAdded >= callExpire)
|
||||
{
|
||||
await war.Channel.SendMessage($"❗🔰**Claim from @{Bases[i].CallUser} for a war against {war.ShortPrint()} has expired.**").ConfigureAwait(false);
|
||||
Bases[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region commands
|
||||
public override void Install(ModuleManager manager)
|
||||
{
|
||||
manager.CreateCommands("", cgb =>
|
||||
{
|
||||
|
||||
cgb.AddCheck(PermissionChecker.Instance);
|
||||
cgb.AddCheck(PermissionChecker.Instance);
|
||||
|
||||
cgb.CreateCommand(Prefix + "createwar")
|
||||
.Alias(Prefix + "cw")
|
||||
.Description($"Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. |{Prefix}cw 15 The Enemy Clan")
|
||||
.Parameter("size")
|
||||
.Parameter("enemy_clan", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageChannels)
|
||||
return;
|
||||
List<ClashWar> wars;
|
||||
if (!ClashWars.TryGetValue(e.Server.Id, out wars))
|
||||
{
|
||||
wars = new List<ClashWar>();
|
||||
if (!ClashWars.TryAdd(e.Server.Id, wars))
|
||||
return;
|
||||
}
|
||||
var enemyClan = e.GetArg("enemy_clan");
|
||||
if (string.IsNullOrWhiteSpace(enemyClan))
|
||||
{
|
||||
return;
|
||||
}
|
||||
int size;
|
||||
if (!int.TryParse(e.GetArg("size"), out size) || size < 10 || size > 50 || size % 5 != 0)
|
||||
{
|
||||
await e.Channel.SendMessage("💢🔰 Not a Valid war size").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var cw = new ClashWar(enemyClan, size, e);
|
||||
//cw.Start();
|
||||
wars.Add(cw);
|
||||
cw.OnUserTimeExpired += async (u) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await
|
||||
e.Channel.SendMessage(
|
||||
$"❗🔰**Claim from @{u} for a war against {cw.ShortPrint()} has expired.**")
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
cw.OnWarEnded += async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await e.Channel.SendMessage($"❗🔰**War against {cw.ShortPrint()} ended.**").ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
};
|
||||
await e.Channel.SendMessage($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
|
||||
//war with the index X started.
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "createwar")
|
||||
.Alias(Prefix + "cw")
|
||||
.Description($"Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. |{Prefix}cw 15 The Enemy Clan")
|
||||
.Parameter("size")
|
||||
.Parameter("enemy_clan", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageChannels)
|
||||
return;
|
||||
var enemyClan = e.GetArg("enemy_clan");
|
||||
if (string.IsNullOrWhiteSpace(enemyClan))
|
||||
{
|
||||
return;
|
||||
}
|
||||
int size;
|
||||
if (!int.TryParse(e.GetArg("size"), out size) || size < 10 || size > 50 || size % 5 != 0)
|
||||
{
|
||||
await e.Channel.SendMessage("💢🔰 Not a Valid war size").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
List<ClashWar> wars;
|
||||
if (!ClashWars.TryGetValue(e.Server.Id, out wars))
|
||||
{
|
||||
wars = new List<ClashWar>();
|
||||
if (!ClashWars.TryAdd(e.Server.Id, wars))
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var cw = new ClashWar(enemyClan, size, e.Server.Id, e.Channel.Id);
|
||||
//cw.Start();
|
||||
|
||||
wars.Add(cw);
|
||||
await e.Channel.SendMessage($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
|
||||
Save();
|
||||
//war with the index X started.
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "startwar")
|
||||
.Alias(Prefix + "sw")
|
||||
@ -93,14 +199,14 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
var war = warsInfo.Item1[warsInfo.Item2];
|
||||
try
|
||||
{
|
||||
var startTask = war.Start();
|
||||
war.Start();
|
||||
await e.Channel.SendMessage($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
|
||||
await startTask.ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
await e.Channel.SendMessage($"🔰**WAR AGAINST {war.ShortPrint()} IS ALREADY STARTED**").ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
|
||||
}
|
||||
Save();
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "listwar")
|
||||
@ -132,6 +238,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
}
|
||||
await e.Channel.SendMessage(sb.ToString()).ConfigureAwait(false);
|
||||
return;
|
||||
|
||||
}
|
||||
//if number is not null, print the war needed
|
||||
var warsInfo = GetInfo(e);
|
||||
@ -173,6 +280,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
var war = warsInfo.Item1[warsInfo.Item2];
|
||||
war.Call(usr, baseNum - 1);
|
||||
await e.Channel.SendMessage($"🔰**{usr}** claimed a base #{baseNum} for a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||
Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -206,7 +314,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
cgb.CreateCommand(Prefix + "unclaim")
|
||||
.Alias(Prefix + "uncall")
|
||||
.Alias(Prefix + "uc")
|
||||
.Description($"Removes your claim from a certain war. Optional second argument denotes a person in whos place to unclaim | {Prefix}uc [war_number] [optional_other_name]")
|
||||
.Description($"Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | {Prefix}uc [war_number] [optional_other_name]")
|
||||
.Parameter("number", ParameterType.Required)
|
||||
.Parameter("other_name", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
@ -226,6 +334,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
var war = warsInfo.Item1[warsInfo.Item2];
|
||||
var baseNumber = war.Uncall(usr);
|
||||
await e.Channel.SendMessage($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||
Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -246,12 +355,17 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
return;
|
||||
}
|
||||
warsInfo.Item1[warsInfo.Item2].End();
|
||||
await e.Channel.SendMessage($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
|
||||
|
||||
var size = warsInfo.Item1[warsInfo.Item2].Size;
|
||||
warsInfo.Item1.RemoveAt(warsInfo.Item2);
|
||||
Save();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
private async Task FinishClaim(CommandEventArgs e, int stars = 3)
|
||||
{
|
||||
@ -271,6 +385,7 @@ namespace NadekoBot.Modules.ClashOfClans
|
||||
{
|
||||
var baseNum = war.FinishClaim(usr, stars);
|
||||
await e.Channel.SendMessage($"❗🔰{e.User.Mention} **DESTROYED** a base #{baseNum + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
|
||||
Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -33,7 +33,7 @@ namespace NadekoBot.Modules.Conversations
|
||||
cgb.AddCheck(PermissionChecker.Instance);
|
||||
|
||||
cgb.CreateCommand("..")
|
||||
.Description("Adds a new quote with the specified name (single word) and message (no limit). | .. abc My message")
|
||||
.Description("Adds a new quote with the specified name (single word) and message (no limit). | `.. abc My message`")
|
||||
.Parameter("keyword", ParameterType.Required)
|
||||
.Parameter("text", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Conversations
|
||||
});
|
||||
|
||||
cgb.CreateCommand("...")
|
||||
.Description("Shows a random quote with a specified name. | .. abc")
|
||||
.Description("Shows a random quote with a specified name. | `... abc`")
|
||||
.Parameter("keyword", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
|
289
NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
289
NadekoBot/Modules/Gambling/Commands/AnimalRacing.cs
Normal file
@ -0,0 +1,289 @@
|
||||
using NadekoBot.Classes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using System.Collections.Concurrent;
|
||||
using Discord;
|
||||
using NadekoBot.Extensions;
|
||||
using System.Threading;
|
||||
|
||||
namespace NadekoBot.Modules.Gambling.Commands
|
||||
{
|
||||
class AnimalRacing : DiscordCommand
|
||||
{
|
||||
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces = new ConcurrentDictionary<ulong, AnimalRace>();
|
||||
|
||||
public AnimalRacing(DiscordModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Prefix + "race")
|
||||
.Description("Starts a new animal race.")
|
||||
.Do(e => {
|
||||
var ar = new AnimalRace(e.Server.Id, e.Channel);
|
||||
if (ar.Fail)
|
||||
{
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
cgb.CreateCommand(Prefix + "joinrace")
|
||||
.Alias(Prefix + "jr")
|
||||
.Description("Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`")
|
||||
.Parameter("amount", ParameterType.Optional)
|
||||
.Do(async e => {
|
||||
|
||||
int amount;
|
||||
if (!int.TryParse(e.GetArg("amount"), out amount) || amount < 0)
|
||||
amount = 0;
|
||||
|
||||
var userFlowers = GamblingModule.GetUserFlowers(e.User.Id);
|
||||
|
||||
if (userFlowers < amount)
|
||||
{
|
||||
await e.Channel.SendMessage($"{e.User.Mention} You don't have enough {NadekoBot.Config.CurrencyName}s. You only have {userFlowers}{NadekoBot.Config.CurrencySign}.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (amount > 0)
|
||||
await FlowersHandler.RemoveFlowers(e.User, "BetRace", (int)amount, true).ConfigureAwait(false);
|
||||
|
||||
AnimalRace ar;
|
||||
if (!AnimalRaces.TryGetValue(e.Server.Id, out ar)) {
|
||||
await e.Channel.SendMessage("No race exists on this server");
|
||||
}
|
||||
await ar.JoinRace(e.User, amount);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public class AnimalRace
|
||||
{
|
||||
|
||||
private ConcurrentQueue<string> animals = new ConcurrentQueue<string>(NadekoBot.Config.RaceAnimals.Shuffle());
|
||||
|
||||
public bool Fail { get; internal set; }
|
||||
|
||||
public List<Participant> participants = new List<Participant>();
|
||||
private ulong serverId;
|
||||
private int messagesSinceGameStarted = 0;
|
||||
|
||||
public Channel raceChannel { get; set; }
|
||||
public bool Started { get; private set; } = false;
|
||||
|
||||
public AnimalRace(ulong serverId, Channel ch)
|
||||
{
|
||||
this.serverId = serverId;
|
||||
this.raceChannel = ch;
|
||||
if (!AnimalRaces.TryAdd(serverId, this))
|
||||
{
|
||||
Fail = true;
|
||||
return;
|
||||
}
|
||||
var cancelSource = new CancellationTokenSource();
|
||||
var token = cancelSource.Token;
|
||||
var fullgame = CheckForFullGameAsync(token);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await raceChannel.SendMessage($"🏁`Race is starting in 20 seconds or when the room is full. Type $jr to join the race.`");
|
||||
var t = await Task.WhenAny(Task.Delay(20000, token), fullgame);
|
||||
Started = true;
|
||||
cancelSource.Cancel();
|
||||
if (t == fullgame)
|
||||
{
|
||||
await raceChannel.SendMessage("🏁`Race full, starting right now!`");
|
||||
}
|
||||
else if (participants.Count > 1)
|
||||
{
|
||||
await raceChannel.SendMessage("🏁`Game starting with " + participants.Count + " praticipants.`");
|
||||
}
|
||||
else
|
||||
{
|
||||
await raceChannel.SendMessage("🏁`Race failed to start since there was not enough participants.`");
|
||||
var p = participants.FirstOrDefault();
|
||||
if (p != null)
|
||||
await FlowersHandler.AddFlowersAsync(p.User, "BetRace", p.AmountBet, true).ConfigureAwait(false);
|
||||
End();
|
||||
return;
|
||||
}
|
||||
await Task.Run(StartRace);
|
||||
End();
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
|
||||
private void End()
|
||||
{
|
||||
AnimalRace throwaway;
|
||||
AnimalRaces.TryRemove(serverId, out throwaway);
|
||||
}
|
||||
|
||||
private async Task StartRace() {
|
||||
var rng = new Random();
|
||||
Participant winner = null;
|
||||
Message msg = null;
|
||||
int place = 1;
|
||||
try
|
||||
{
|
||||
NadekoBot.Client.MessageReceived += Client_MessageReceived;
|
||||
|
||||
while (!participants.All(p => p.Total >= 60))
|
||||
{
|
||||
//update the state
|
||||
participants.ForEach(p =>
|
||||
{
|
||||
|
||||
p.Total += 1 + rng.Next(0, 10);
|
||||
if (p.Total > 60)
|
||||
{
|
||||
p.Total = 60;
|
||||
if (winner == null)
|
||||
{
|
||||
winner = p;
|
||||
}
|
||||
if (p.Place == 0)
|
||||
p.Place = place++;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//draw the state
|
||||
|
||||
var text = $@"|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|
|
||||
{String.Join("\n", participants.Select(p => $"{(int)(p.Total / 60f * 100),-2}%|{p.ToString()}"))}
|
||||
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
|
||||
if (msg == null || messagesSinceGameStarted >= 10) // also resend the message if channel was spammed
|
||||
{
|
||||
if(msg != null)
|
||||
try { await msg.Delete(); } catch { }
|
||||
msg = await raceChannel.SendMessage(text);
|
||||
messagesSinceGameStarted = 0;
|
||||
}
|
||||
else
|
||||
await msg.Edit(text);
|
||||
|
||||
await Task.Delay(2500);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
NadekoBot.Client.MessageReceived -= Client_MessageReceived;
|
||||
}
|
||||
|
||||
if (winner.AmountBet > 0)
|
||||
{
|
||||
var wonAmount = winner.AmountBet * (participants.Count - 1);
|
||||
await FlowersHandler.AddFlowersAsync(winner.User, "Won a Race", wonAmount).ConfigureAwait(false);
|
||||
await raceChannel.SendMessage($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race and {wonAmount}{NadekoBot.Config.CurrencySign}!**");
|
||||
}
|
||||
else
|
||||
{
|
||||
await raceChannel.SendMessage($"🏁 {winner.User.Mention} as {winner.Animal} **Won the race!**");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void Client_MessageReceived(object sender, MessageEventArgs e)
|
||||
{
|
||||
if (e.Message.IsAuthor || e.Channel.IsPrivate || e.Channel != raceChannel)
|
||||
return;
|
||||
messagesSinceGameStarted++;
|
||||
}
|
||||
|
||||
private async Task CheckForFullGameAsync(CancellationToken cancelToken) {
|
||||
while (animals.Count > 0)
|
||||
{
|
||||
await Task.Delay(100,cancelToken);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> JoinRace(User u, int amount = 0)
|
||||
{
|
||||
var animal = "";
|
||||
if (!animals.TryDequeue(out animal))
|
||||
{
|
||||
await raceChannel.SendMessage($"{u.Mention} `There is no running race on this server.`");
|
||||
return false;
|
||||
}
|
||||
var p = new Participant(u, animal, amount);
|
||||
if (participants.Contains(p))
|
||||
{
|
||||
await raceChannel.SendMessage($"{u.Mention} `You already joined this race.`");
|
||||
return false;
|
||||
}
|
||||
if (Started)
|
||||
{
|
||||
await raceChannel.SendMessage($"{u.Mention} `Race is already started`");
|
||||
return false;
|
||||
}
|
||||
participants.Add(p);
|
||||
await raceChannel.SendMessage($"{u.Mention} **joined the race as a {p.Animal}" + (amount > 0 ? $" and bet {amount} {NadekoBot.Config.CurrencyName.SnPl(amount)}!**" : "**"));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class Participant
|
||||
{
|
||||
public User User { get; set; }
|
||||
public string Animal { get; set; }
|
||||
public int AmountBet { get; set; }
|
||||
|
||||
public float Coeff { get; set; }
|
||||
public int Total { get; set; }
|
||||
|
||||
public int Place { get; set; } = 0;
|
||||
|
||||
public Participant(User u, string a, int amount)
|
||||
{
|
||||
this.User = u;
|
||||
this.Animal = a;
|
||||
this.AmountBet = amount;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return User.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var p = obj as Participant;
|
||||
return p == null?
|
||||
false:
|
||||
p.User == User;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var str = new string('‣', Total) + Animal;
|
||||
if (Place == 0)
|
||||
return str;
|
||||
if (Place == 1)
|
||||
{
|
||||
return str + "🏆";
|
||||
}
|
||||
else if (Place == 2)
|
||||
{
|
||||
return str + "`2nd`";
|
||||
}
|
||||
else if (Place == 3)
|
||||
{
|
||||
return str + "`3rd`";
|
||||
}
|
||||
else {
|
||||
return str + $"`{Place}th`";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ using Discord.Modules;
|
||||
using NadekoBot.Classes;
|
||||
using NadekoBot.DataModels;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Gambling.Commands;
|
||||
using NadekoBot.Modules.Permissions.Classes;
|
||||
using System;
|
||||
using System.Linq;
|
||||
@ -18,6 +19,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
commands.Add(new DrawCommand(this));
|
||||
commands.Add(new FlipCoinCommand(this));
|
||||
commands.Add(new DiceRollCommand(this));
|
||||
commands.Add(new AnimalRacing(this));
|
||||
}
|
||||
|
||||
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Gambling;
|
||||
@ -31,7 +33,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
commands.ForEach(com => com.Init(cgb));
|
||||
|
||||
cgb.CreateCommand(Prefix + "raffle")
|
||||
.Description("Prints a name and ID of a random user from the online list from the (optional) role.")
|
||||
.Description($"Prints a name and ID of a random user from the online list from the (optional) role. | `{Prefix}raffle` or `{Prefix}raffle RoleName")
|
||||
.Parameter("role", ParameterType.Optional)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -93,7 +95,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "award")
|
||||
.Description("Gives someone a certain amount of flowers. **Bot Owner Only!** | `$award 100 @person`")
|
||||
.Description($"Gives someone a certain amount of flowers. **Bot Owner Only!** | `{Prefix}award 100 @person`")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Parameter("amount", ParameterType.Required)
|
||||
.Parameter("receiver", ParameterType.Unparsed)
|
||||
@ -115,7 +117,7 @@ namespace NadekoBot.Modules.Gambling
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "take")
|
||||
.Description("Takes a certain amount of flowers from someone. **Bot Owner Only!**")
|
||||
.Description($"Takes a certain amount of flowers from someone. **Bot Owner Only!** | `{Prefix}take 1 \"@someguy\"`")
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Parameter("amount", ParameterType.Required)
|
||||
.Parameter("rektperson", ParameterType.Unparsed)
|
||||
|
@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Games.Commands
|
||||
@ -59,7 +60,7 @@ namespace NadekoBot.Modules.Games.Commands
|
||||
//channelid/messageid pair
|
||||
ConcurrentDictionary<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)
|
||||
{
|
||||
@ -78,38 +79,47 @@ namespace NadekoBot.Modules.Games.Commands
|
||||
|
||||
await FlowersHandler.AddFlowersAsync(e.User, "Picked a flower.", 1, true).ConfigureAwait(false);
|
||||
var msg = await e.Channel.SendMessage($"**{e.User.Name}** picked a {NadekoBot.Config.CurrencyName}!").ConfigureAwait(false);
|
||||
await Task.Delay(10000).ConfigureAwait(false);
|
||||
await msg.Delete().ConfigureAwait(false);
|
||||
ThreadPool.QueueUserWorkItem(async (state) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(10000).ConfigureAwait(false);
|
||||
await msg.Delete().ConfigureAwait(false);
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Module.Prefix + "plant")
|
||||
.Description("Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)")
|
||||
.Do(e =>
|
||||
.Do(async e =>
|
||||
{
|
||||
lock (locker)
|
||||
await locker.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (plantedFlowerChannels.ContainsKey(e.Channel.Id))
|
||||
{
|
||||
e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel.");
|
||||
await e.Channel.SendMessage($"There is already a {NadekoBot.Config.CurrencyName} in this channel.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var removed = FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).GetAwaiter().GetResult();
|
||||
var removed = await FlowersHandler.RemoveFlowers(e.User, "Planted a flower.", 1, true).ConfigureAwait(false);
|
||||
if (!removed)
|
||||
{
|
||||
e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").Wait();
|
||||
await e.Channel.SendMessage($"You don't have any {NadekoBot.Config.CurrencyName}s.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var file = GetRandomCurrencyImagePath();
|
||||
Message msg;
|
||||
if (file == null)
|
||||
msg = e.Channel.SendMessage(NadekoBot.Config.CurrencySign).GetAwaiter().GetResult();
|
||||
msg = await e.Channel.SendMessage(NadekoBot.Config.CurrencySign).ConfigureAwait(false);
|
||||
else
|
||||
msg = e.Channel.SendFile(file).GetAwaiter().GetResult();
|
||||
msg = await e.Channel.SendFile(file).ConfigureAwait(false);
|
||||
var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(NadekoBot.Config.CurrencyName[0]);
|
||||
var msg2 = e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").GetAwaiter().GetResult();
|
||||
var msg2 = await e.Channel.SendMessage($"Oh how Nice! **{e.User.Name}** planted {(vowelFirst ? "an" : "a")} {NadekoBot.Config.CurrencyName}. Pick it using {Module.Prefix}pick").ConfigureAwait(false);
|
||||
plantedFlowerChannels.TryAdd(e.Channel.Id, new[] { msg, msg2 });
|
||||
}
|
||||
finally { locker.Release(); }
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "gencurrency")
|
||||
@ -129,12 +139,12 @@ namespace NadekoBot.Modules.Games.Commands
|
||||
int throwaway;
|
||||
if (config.GenerateCurrencyChannels.TryRemove(e.Channel.Id, out throwaway))
|
||||
{
|
||||
await e.Channel.SendMessage("`Currency generation disabled on this channel.`");
|
||||
await e.Channel.SendMessage("`Currency generation disabled on this channel.`").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config.GenerateCurrencyChannels.TryAdd(e.Channel.Id, cd))
|
||||
await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`");
|
||||
await e.Channel.SendMessage($"`Currency generation enabled on this channel. Cooldown is {cd} minutes.`").ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -15,11 +15,6 @@ namespace NadekoBot.Modules.Games.Commands
|
||||
|
||||
public static ConcurrentDictionary<Server, Poll> ActivePolls = new ConcurrentDictionary<Server, Poll>();
|
||||
|
||||
public Func<CommandEventArgs, Task> DoFunc()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
internal override void Init(CommandGroupBuilder cgb)
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "poll")
|
||||
|
@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
||||
{
|
||||
internal class TriviaGame
|
||||
{
|
||||
private readonly object _guessLock = new object();
|
||||
private readonly SemaphoreSlim _guessLock = new SemaphoreSlim(1,1);
|
||||
|
||||
private Server server { get; }
|
||||
private Channel channel { get; }
|
||||
@ -113,7 +113,8 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
||||
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
|
||||
|
||||
var guess = false;
|
||||
lock (_guessLock)
|
||||
await _guessLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (GameActive && CurrentQuestion.IsAnswerCorrect(e.Message.Text) && !triviaCancelSource.IsCancellationRequested)
|
||||
{
|
||||
@ -122,6 +123,7 @@ namespace NadekoBot.Modules.Games.Commands.Trivia
|
||||
guess = true;
|
||||
}
|
||||
}
|
||||
finally { _guessLock.Release(); }
|
||||
if (!guess) return;
|
||||
triviaCancelSource.Cancel();
|
||||
await channel.SendMessage($"☑️ {e.User.Mention} guessed it! The answer was: **{CurrentQuestion.Answer}**").ConfigureAwait(false);
|
||||
|
@ -36,7 +36,7 @@ namespace NadekoBot.Modules.Games
|
||||
commands.ForEach(cmd => cmd.Init(cgb));
|
||||
|
||||
cgb.CreateCommand(Prefix + "choose")
|
||||
.Description("Chooses a thing from a list of things | >choose Get up;Sleep;Sleep more")
|
||||
.Description($"Chooses a thing from a list of things | `{Prefix}choose Get up;Sleep;Sleep more`")
|
||||
.Parameter("list", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Games
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "8ball")
|
||||
.Description("Ask the 8ball a yes/no question.")
|
||||
.Description($"Ask the 8ball a yes/no question. | `{Prefix}8ball should i do something`")
|
||||
.Parameter("question", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Games
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "rps")
|
||||
.Description("Play a game of rocket paperclip scissors with Nadeko. | >rps scissors")
|
||||
.Description($"Play a game of rocket paperclip scissors with Nadeko. | `{Prefix}rps scissors`")
|
||||
.Parameter("input", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
|
@ -113,17 +113,10 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
if (CurrentSong == null)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
OnStarted(this, CurrentSong);
|
||||
await CurrentSong.Play(audioClient, cancelToken);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Console.WriteLine("Song canceled");
|
||||
SongCancelSource = new CancellationTokenSource();
|
||||
cancelToken = SongCancelSource.Token;
|
||||
}
|
||||
|
||||
OnStarted(this, CurrentSong);
|
||||
await CurrentSong.Play(audioClient, cancelToken);
|
||||
|
||||
OnCompleted(this, CurrentSong);
|
||||
|
||||
if (RepeatPlaylist)
|
||||
@ -135,8 +128,14 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
}
|
||||
finally
|
||||
{
|
||||
await Task.Delay(300).ConfigureAwait(false);
|
||||
if (!cancelToken.IsCancellationRequested)
|
||||
{
|
||||
SongCancelSource.Cancel();
|
||||
}
|
||||
SongCancelSource = new CancellationTokenSource();
|
||||
cancelToken = SongCancelSource.Token;
|
||||
CurrentSong = null;
|
||||
await Task.Delay(300).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
|
||||
public int BufferSize { get; }
|
||||
|
||||
private readonly object readWriteLock = new object();
|
||||
private readonly SemaphoreSlim readWriteLock = new SemaphoreSlim(1, 1);
|
||||
|
||||
public PoopyBuffer(int size)
|
||||
{
|
||||
@ -32,51 +32,57 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
ringBuffer = new byte[size];
|
||||
}
|
||||
|
||||
public int Read(byte[] buffer, int count)
|
||||
public Task<int> ReadAsync(byte[] buffer, int count)
|
||||
{
|
||||
if (buffer.Length < count)
|
||||
throw new ArgumentException();
|
||||
//Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***");
|
||||
lock (readWriteLock)
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
//read as much as you can if you're reading too much
|
||||
if (count > ContentLength)
|
||||
count = ContentLength;
|
||||
//if nothing to read, return 0
|
||||
if (WritePosition == ReadPosition)
|
||||
return 0;
|
||||
// if buffer is in the "normal" state, just read
|
||||
if (WritePosition > ReadPosition)
|
||||
if (buffer.Length < count)
|
||||
throw new ArgumentException();
|
||||
//Console.WriteLine($"***\nRead: {ReadPosition}\nWrite: {WritePosition}\nContentLength:{ContentLength}\n***");
|
||||
await readWriteLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count);
|
||||
ReadPosition += count;
|
||||
//Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]");
|
||||
//read as much as you can if you're reading too much
|
||||
if (count > ContentLength)
|
||||
count = ContentLength;
|
||||
//if nothing to read, return 0
|
||||
if (WritePosition == ReadPosition)
|
||||
return 0;
|
||||
// if buffer is in the "normal" state, just read
|
||||
if (WritePosition > ReadPosition)
|
||||
{
|
||||
Buffer.BlockCopy(ringBuffer, ReadPosition, buffer, 0, count);
|
||||
ReadPosition += count;
|
||||
//Console.WriteLine($"Read only normally1 {count}[{ReadPosition - count} to {ReadPosition}]");
|
||||
return count;
|
||||
}
|
||||
//else ReadPos <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;
|
||||
}
|
||||
//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
|
||||
finally { readWriteLock.Release(); }
|
||||
});
|
||||
|
||||
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)
|
||||
@ -89,32 +95,37 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
if (cancelToken.IsCancellationRequested)
|
||||
return;
|
||||
}
|
||||
//the while above assures that i cannot write past readposition with my write, so i don't have to check
|
||||
// *unless its multithreaded or task is not awaited
|
||||
lock (readWriteLock)
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
// if i can just write without hitting buffer.length, do it
|
||||
if (WritePosition + count < BufferSize)
|
||||
//the while above assures that i cannot write past readposition with my write, so i don't have to check
|
||||
// *unless its multithreaded or task is not awaited
|
||||
await readWriteLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count);
|
||||
WritePosition += count;
|
||||
//Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]");
|
||||
return;
|
||||
// if i can just write without hitting buffer.length, do it
|
||||
if (WritePosition + count < BufferSize)
|
||||
{
|
||||
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, count);
|
||||
WritePosition += count;
|
||||
//Console.WriteLine($"Wrote only normally {count}[{WritePosition - count} to {WritePosition}]");
|
||||
return;
|
||||
}
|
||||
// otherwise, i have to write to the end, then write the rest from the start
|
||||
|
||||
var wroteNormaly = BufferSize - WritePosition;
|
||||
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly);
|
||||
|
||||
//Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]");
|
||||
|
||||
var wroteFromStart = count - wroteNormaly;
|
||||
Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart);
|
||||
|
||||
//Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}");
|
||||
|
||||
WritePosition = wroteFromStart;
|
||||
}
|
||||
// otherwise, i have to write to the end, then write the rest from the start
|
||||
|
||||
var wroteNormaly = BufferSize - WritePosition;
|
||||
Buffer.BlockCopy(buffer, 0, ringBuffer, WritePosition, wroteNormaly);
|
||||
|
||||
//Console.WriteLine($"Wrote normally {wroteNormaly}[{WritePosition} to {BufferSize}]");
|
||||
|
||||
var wroteFromStart = count - wroteNormaly;
|
||||
Buffer.BlockCopy(buffer, wroteNormaly, ringBuffer, 0, wroteFromStart);
|
||||
|
||||
//Console.WriteLine($"and from start {wroteFromStart} [0 to {wroteFromStart}");
|
||||
|
||||
WritePosition = wroteFromStart;
|
||||
}
|
||||
finally { readWriteLock.Release(); }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ using NadekoBot.Classes;
|
||||
using NadekoBot.Extensions;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
@ -31,9 +32,7 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
public SongInfo SongInfo { get; }
|
||||
public string QueuerName { get; set; }
|
||||
|
||||
private PoopyBuffer songBuffer { get; set; }
|
||||
|
||||
private bool prebufferingComplete { get; set; } = false;
|
||||
private bool bufferingCompleted { get; set; } = false;
|
||||
public MusicPlayer MusicPlayer { get; set; }
|
||||
|
||||
public string PrettyCurrentTime()
|
||||
@ -74,7 +73,7 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
return this;
|
||||
}
|
||||
|
||||
private Task BufferSong(CancellationToken cancelToken) =>
|
||||
private Task BufferSong(string filename, CancellationToken cancelToken) =>
|
||||
Task.Factory.StartNew(async () =>
|
||||
{
|
||||
Process p = null;
|
||||
@ -89,40 +88,38 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
RedirectStandardError = false,
|
||||
CreateNoWindow = true,
|
||||
});
|
||||
const int blockSize = 3840;
|
||||
var buffer = new byte[blockSize];
|
||||
var attempt = 0;
|
||||
while (!cancelToken.IsCancellationRequested)
|
||||
var prebufferSize = 100ul.MiB();
|
||||
using (var outStream = new FileStream(filename, FileMode.Append, FileAccess.Write, FileShare.Read))
|
||||
{
|
||||
var read = 0;
|
||||
try
|
||||
byte[] buffer = new byte[81920];
|
||||
int bytesRead;
|
||||
while ((bytesRead = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) != 0)
|
||||
{
|
||||
read = await p.StandardOutput.BaseStream.ReadAsync(buffer, 0, blockSize, cancelToken)
|
||||
.ConfigureAwait(false);
|
||||
await outStream.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false);
|
||||
while ((ulong)outStream.Length - bytesSent > prebufferSize)
|
||||
await Task.Delay(100, cancelToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (read == 0)
|
||||
if (attempt++ == 50)
|
||||
break;
|
||||
else
|
||||
await Task.Delay(100, cancelToken).ConfigureAwait(false);
|
||||
else
|
||||
attempt = 0;
|
||||
await songBuffer.WriteAsync(buffer, read, cancelToken).ConfigureAwait(false);
|
||||
if (songBuffer.ContentLength > 2.MB())
|
||||
prebufferingComplete = true;
|
||||
}
|
||||
|
||||
bufferingCompleted = true;
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception) {
|
||||
var oldclr = Console.ForegroundColor;
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine(@"You have not properly installed or configured FFMPEG.
|
||||
Please install and configure FFMPEG to play music.
|
||||
Check the guides for your platform on how to setup ffmpeg correctly:
|
||||
Windows Guide: https://goo.gl/SCv72y
|
||||
Linux Guide: https://goo.gl/rRhjCp");
|
||||
Console.ForegroundColor = oldclr;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"Buffering errored: {ex.Message}");
|
||||
Console.WriteLine($"Buffering stopped: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.WriteLine($"Buffering done." + $" [{songBuffer.ContentLength}]");
|
||||
Console.WriteLine($"Buffering done.");
|
||||
if (p != null)
|
||||
{
|
||||
try
|
||||
@ -137,53 +134,82 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
|
||||
internal async Task Play(IAudioClient voiceClient, CancellationToken cancelToken)
|
||||
{
|
||||
// initialize the buffer here because if this song was playing before (requeued), we must delete old buffer data
|
||||
songBuffer = new PoopyBuffer(NadekoBot.Config.BufferSize);
|
||||
var filename = Path.Combine(MusicModule.MusicDataPath, DateTime.Now.UnixTimestamp().ToString());
|
||||
|
||||
var bufferTask = BufferSong(cancelToken).ConfigureAwait(false);
|
||||
var bufferAttempts = 0;
|
||||
const int waitPerAttempt = 500;
|
||||
var toAttemptTimes = SongInfo.ProviderType != MusicType.Normal ? 5 : 9;
|
||||
while (!prebufferingComplete && bufferAttempts++ < toAttemptTimes)
|
||||
var bufferTask = BufferSong(filename, cancelToken).ConfigureAwait(false);
|
||||
|
||||
var inStream = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Write);
|
||||
|
||||
bytesSent = 0;
|
||||
|
||||
try
|
||||
{
|
||||
await Task.Delay(waitPerAttempt, cancelToken).ConfigureAwait(false);
|
||||
}
|
||||
Console.WriteLine($"Prebuffering done? in {waitPerAttempt * bufferAttempts}");
|
||||
const int blockSize = 3840;
|
||||
var attempt = 0;
|
||||
while (!cancelToken.IsCancellationRequested)
|
||||
{
|
||||
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
|
||||
byte[] buffer = new byte[blockSize];
|
||||
var read = songBuffer.Read(buffer, blockSize);
|
||||
unchecked
|
||||
var prebufferingTask = CheckPrebufferingAsync(inStream, cancelToken);
|
||||
var sw = new Stopwatch();
|
||||
sw.Start();
|
||||
var t = await Task.WhenAny(prebufferingTask, Task.Delay(5000, cancelToken));
|
||||
if (t != prebufferingTask)
|
||||
{
|
||||
bytesSent += (ulong)read;
|
||||
Console.WriteLine("Prebuffering timed out or canceled. Cannot get any data from the stream.");
|
||||
return;
|
||||
}
|
||||
if (read == 0)
|
||||
if (attempt++ == 20)
|
||||
{
|
||||
voiceClient.Wait();
|
||||
Console.WriteLine($"Song finished. [{songBuffer.ContentLength}]");
|
||||
break;
|
||||
}
|
||||
else
|
||||
await Task.Delay(100, cancelToken).ConfigureAwait(false);
|
||||
else
|
||||
attempt = 0;
|
||||
else if(prebufferingTask.IsCanceled)
|
||||
{
|
||||
Console.WriteLine("Prebuffering timed out. Cannot get any data from the stream.");
|
||||
return;
|
||||
}
|
||||
sw.Stop();
|
||||
Console.WriteLine("Prebuffering successfully completed in "+ sw.Elapsed);
|
||||
|
||||
while (this.MusicPlayer.Paused)
|
||||
await Task.Delay(200, cancelToken).ConfigureAwait(false);
|
||||
buffer = AdjustVolume(buffer, MusicPlayer.Volume);
|
||||
voiceClient.Send(buffer, 0, read);
|
||||
const int blockSize = 3840;
|
||||
var attempt = 0;
|
||||
byte[] buffer = new byte[blockSize];
|
||||
while (!cancelToken.IsCancellationRequested)
|
||||
{
|
||||
//Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------");
|
||||
var read = inStream.Read(buffer, 0, buffer.Length);
|
||||
//await inStream.CopyToAsync(voiceClient.OutputStream);
|
||||
unchecked
|
||||
{
|
||||
bytesSent += (ulong)read;
|
||||
}
|
||||
if (read == 0)
|
||||
if (attempt++ == 20)
|
||||
{
|
||||
voiceClient.Wait();
|
||||
break;
|
||||
}
|
||||
else
|
||||
await Task.Delay(100, cancelToken).ConfigureAwait(false);
|
||||
else
|
||||
attempt = 0;
|
||||
|
||||
while (this.MusicPlayer.Paused)
|
||||
await Task.Delay(200, cancelToken).ConfigureAwait(false);
|
||||
|
||||
buffer = AdjustVolume(buffer, MusicPlayer.Volume);
|
||||
voiceClient.Send(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await bufferTask;
|
||||
await Task.Run(() => voiceClient.Clear());
|
||||
inStream.Dispose();
|
||||
try { File.Delete(filename); } catch { }
|
||||
}
|
||||
Console.WriteLine("Awiting buffer task");
|
||||
await bufferTask;
|
||||
Console.WriteLine("Buffer task done.");
|
||||
voiceClient.Clear();
|
||||
cancelToken.ThrowIfCancellationRequested();
|
||||
}
|
||||
|
||||
private async Task CheckPrebufferingAsync(Stream inStream, CancellationToken cancelToken)
|
||||
{
|
||||
while (!bufferingCompleted && inStream.Length < 2.MiB())
|
||||
{
|
||||
await Task.Delay(100, cancelToken);
|
||||
}
|
||||
Console.WriteLine("Buffering successfull");
|
||||
}
|
||||
|
||||
/*
|
||||
//stackoverflow ftw
|
||||
private static byte[] AdjustVolume(byte[] audioSamples, float volume)
|
||||
{
|
||||
@ -210,6 +236,33 @@ namespace NadekoBot.Modules.Music.Classes
|
||||
}
|
||||
return array;
|
||||
}
|
||||
*/
|
||||
|
||||
//aidiakapi ftw
|
||||
public unsafe static byte[] AdjustVolume(byte[] audioSamples, float volume)
|
||||
{
|
||||
Contract.Requires(audioSamples != null);
|
||||
Contract.Requires(audioSamples.Length % 2 == 0);
|
||||
Contract.Requires(volume >= 0f && volume <= 1f);
|
||||
Contract.Assert(BitConverter.IsLittleEndian);
|
||||
|
||||
if (Math.Abs(volume - 1f) < 0.0001f) return audioSamples;
|
||||
|
||||
// 16-bit precision for the multiplication
|
||||
int volumeFixed = (int)Math.Round(volume * 65536d);
|
||||
|
||||
int count = audioSamples.Length / 2;
|
||||
|
||||
fixed (byte* srcBytes = audioSamples)
|
||||
{
|
||||
short* src = (short*)srcBytes;
|
||||
|
||||
for (int i = count; i != 0; i--, src++)
|
||||
*src = (short)(((*src) * volumeFixed) >> 16);
|
||||
}
|
||||
|
||||
return audioSamples;
|
||||
}
|
||||
|
||||
public static async Task<Song> ResolveSong(string query, MusicType musicType = MusicType.Normal)
|
||||
{
|
||||
|
@ -18,11 +18,16 @@ namespace NadekoBot.Modules.Music
|
||||
{
|
||||
internal class MusicModule : DiscordModule
|
||||
{
|
||||
|
||||
public static ConcurrentDictionary<Server, MusicPlayer> MusicPlayers = new ConcurrentDictionary<Server, MusicPlayer>();
|
||||
|
||||
public const string MusicDataPath = "data/musicdata";
|
||||
|
||||
public MusicModule()
|
||||
{
|
||||
//it can fail if its currenctly opened or doesn't exist. Either way i don't care
|
||||
try { Directory.Delete(MusicDataPath, true); } catch { }
|
||||
|
||||
Directory.CreateDirectory(MusicDataPath);
|
||||
}
|
||||
|
||||
public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Music;
|
||||
@ -713,7 +718,7 @@ namespace NadekoBot.Modules.Music
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "goto")
|
||||
.Description("Goes to a specific time in seconds in a song.")
|
||||
.Description($"Goes to a specific time in seconds in a song. | {Prefix}goto 30")
|
||||
.Parameter("time")
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -856,7 +861,7 @@ namespace NadekoBot.Modules.Music
|
||||
}
|
||||
if (!silent)
|
||||
{
|
||||
var queuedMessage = await textCh.SendMessage($"🎵`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count}`").ConfigureAwait(false);
|
||||
var queuedMessage = await textCh.SendMessage($"🎵`Queued`{resolvedSong.PrettyName} **at** `#{musicPlayer.Playlist.Count + 1}`").ConfigureAwait(false);
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
Task.Run(async () =>
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
cgb.AddCheck(PermissionChecker.Instance);
|
||||
|
||||
cgb.CreateCommand(Prefix + "hentai")
|
||||
.Description("Shows a random NSFW hentai image from gelbooru and danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~hentai yuri+kissing")
|
||||
.Description($"Shows a random NSFW hentai image from gelbooru and danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}hentai yuri+kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -39,7 +39,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
await e.Channel.SendMessage("`No results.`");
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "danbooru")
|
||||
.Description("Shows a random hentai image from danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~danbooru yuri+kissing")
|
||||
.Description($"Shows a random hentai image from danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}danbooru yuri+kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -51,7 +51,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
await e.Channel.SendMessage(link).ConfigureAwait(false);
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "gelbooru")
|
||||
.Description("Shows a random hentai image from gelbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~gelbooru yuri+kissing")
|
||||
.Description($"Shows a random hentai image from gelbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}gelbooru yuri+kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -64,7 +64,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "rule34")
|
||||
.Description("Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~rule34 yuri+kissing")
|
||||
.Description($"Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}rule34 yuri+kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -76,7 +76,7 @@ namespace NadekoBot.Modules.NSFW
|
||||
await e.Channel.SendMessage(link).ConfigureAwait(false);
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "e621")
|
||||
.Description("Shows a random hentai image from e621.net with a given tag. Tag is optional but preffered. Use spaces for multiple tags. | ~e621 yuri kissing")
|
||||
.Description($"Shows a random hentai image from e621.net with a given tag. Tag is optional but preffered. Use spaces for multiple tags. | `{Prefix}e621 yuri kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
|
@ -150,21 +150,21 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
return PermissionBanType.None;
|
||||
}
|
||||
|
||||
private static void WriteServerToJson(ServerPermissions serverPerms)
|
||||
private static Task WriteServerToJson(ServerPermissions serverPerms) => Task.Run(() =>
|
||||
{
|
||||
string pathToFile = $"data/permissions/{serverPerms.Id}.json";
|
||||
File.WriteAllText(pathToFile,
|
||||
Newtonsoft.Json.JsonConvert.SerializeObject(serverPerms, Newtonsoft.Json.Formatting.Indented));
|
||||
}
|
||||
});
|
||||
|
||||
public static void WriteToJson()
|
||||
public static Task WriteToJson() => Task.Run(() =>
|
||||
{
|
||||
Directory.CreateDirectory("data/permissions/");
|
||||
foreach (var kvp in PermissionsDict)
|
||||
{
|
||||
WriteServerToJson(kvp.Value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
public static string GetServerPermissionsRoleName(Server server)
|
||||
{
|
||||
@ -174,25 +174,25 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
return serverPerms.PermissionsControllerRole;
|
||||
}
|
||||
|
||||
internal static void SetPermissionsRole(Server server, string roleName)
|
||||
internal static async Task SetPermissionsRole(Server server, string roleName)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
|
||||
serverPerms.PermissionsControllerRole = roleName;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static void SetVerbosity(Server server, bool val)
|
||||
internal static async Task SetVerbosity(Server server, bool val)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
|
||||
serverPerms.Verbose = val;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static void CopyRolePermissions(Role fromRole, Role toRole)
|
||||
internal static async Task CopyRolePermissions(Role fromRole, Role toRole)
|
||||
{
|
||||
var server = fromRole.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -207,10 +207,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
|
||||
to.CopyFrom(from);
|
||||
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static void CopyChannelPermissions(Channel fromChannel, Channel toChannel)
|
||||
internal static async Task CopyChannelPermissions(Channel fromChannel, Channel toChannel)
|
||||
{
|
||||
var server = fromChannel.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -225,10 +225,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
|
||||
to.CopyFrom(from);
|
||||
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal static void CopyUserPermissions(User fromUser, User toUser)
|
||||
internal static async Task CopyUserPermissions(User fromUser, User toUser)
|
||||
{
|
||||
var server = fromUser.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -243,10 +243,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
|
||||
to.CopyFrom(from);
|
||||
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetServerModulePermission(Server server, string moduleName, bool value)
|
||||
public static async Task SetServerModulePermission(Server server, string moduleName, bool value)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
@ -256,10 +256,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
modules[moduleName] = value;
|
||||
else
|
||||
modules.TryAdd(moduleName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetServerCommandPermission(Server server, string commandName, bool value)
|
||||
public static async Task SetServerCommandPermission(Server server, string commandName, bool value)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
@ -269,10 +269,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
commands[commandName] = value;
|
||||
else
|
||||
commands.TryAdd(commandName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetChannelModulePermission(Channel channel, string moduleName, bool value)
|
||||
public static async Task SetChannelModulePermission(Channel channel, string moduleName, bool value)
|
||||
{
|
||||
var server = channel.Server;
|
||||
|
||||
@ -288,10 +288,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
modules[moduleName] = value;
|
||||
else
|
||||
modules.TryAdd(moduleName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetChannelCommandPermission(Channel channel, string commandName, bool value)
|
||||
public static async Task SetChannelCommandPermission(Channel channel, string commandName, bool value)
|
||||
{
|
||||
var server = channel.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -306,10 +306,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
commands[commandName] = value;
|
||||
else
|
||||
commands.TryAdd(commandName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetRoleModulePermission(Role role, string moduleName, bool value)
|
||||
public static async Task SetRoleModulePermission(Role role, string moduleName, bool value)
|
||||
{
|
||||
var server = role.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -324,10 +324,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
modules[moduleName] = value;
|
||||
else
|
||||
modules.TryAdd(moduleName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetRoleCommandPermission(Role role, string commandName, bool value)
|
||||
public static async Task SetRoleCommandPermission(Role role, string commandName, bool value)
|
||||
{
|
||||
var server = role.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -342,10 +342,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
commands[commandName] = value;
|
||||
else
|
||||
commands.TryAdd(commandName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetUserModulePermission(User user, string moduleName, bool value)
|
||||
public static async Task SetUserModulePermission(User user, string moduleName, bool value)
|
||||
{
|
||||
var server = user.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -360,10 +360,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
modules[moduleName] = value;
|
||||
else
|
||||
modules.TryAdd(moduleName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetUserCommandPermission(User user, string commandName, bool value)
|
||||
public static async Task SetUserCommandPermission(User user, string commandName, bool value)
|
||||
{
|
||||
var server = user.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -377,19 +377,19 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
commands[commandName] = value;
|
||||
else
|
||||
commands.TryAdd(commandName, value);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetServerWordPermission(Server server, bool value)
|
||||
public static async Task SetServerWordPermission(Server server, bool value)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
|
||||
serverPerms.Permissions.FilterWords = value;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetChannelWordPermission(Channel channel, bool value)
|
||||
public static async Task SetChannelWordPermission(Channel channel, bool value)
|
||||
{
|
||||
var server = channel.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -399,19 +399,19 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
|
||||
|
||||
serverPerms.ChannelPermissions[channel.Id].FilterWords = value;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetServerFilterInvitesPermission(Server server, bool value)
|
||||
public static async Task SetServerFilterInvitesPermission(Server server, bool value)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
|
||||
serverPerms.Permissions.FilterInvites = value;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetChannelFilterInvitesPermission(Channel channel, bool value)
|
||||
public static async Task SetChannelFilterInvitesPermission(Channel channel, bool value)
|
||||
{
|
||||
var server = channel.Server;
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
@ -421,10 +421,10 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
serverPerms.ChannelPermissions.Add(channel.Id, new Permissions(channel.Name));
|
||||
|
||||
serverPerms.ChannelPermissions[channel.Id].FilterInvites = value;
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void SetCommandCooldown(Server server, string commandName, int value)
|
||||
public static async Task SetCommandCooldown(Server server, string commandName, int value)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
@ -436,26 +436,26 @@ namespace NadekoBot.Modules.Permissions.Classes
|
||||
serverPerms.CommandCooldowns.AddOrUpdate(commandName, value, (str, v) => value);
|
||||
}
|
||||
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public static void AddFilteredWord(Server server, string word)
|
||||
public static async Task AddFilteredWord(Server server, string word)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
if (serverPerms.Words.Contains(word))
|
||||
throw new InvalidOperationException("That word is already banned.");
|
||||
serverPerms.Words.Add(word);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
public static void RemoveFilteredWord(Server server, string word)
|
||||
public static async Task RemoveFilteredWord(Server server, string word)
|
||||
{
|
||||
var serverPerms = PermissionsDict.GetOrAdd(server.Id,
|
||||
new ServerPermissions(server.Id, server.Name));
|
||||
if (!serverPerms.Words.Contains(word))
|
||||
throw new InvalidOperationException("That word is not banned.");
|
||||
serverPerms.Words.Remove(word);
|
||||
Task.Run(() => WriteServerToJson(serverPerms));
|
||||
await WriteServerToJson(serverPerms).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
|
@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
var chan = string.IsNullOrWhiteSpace(chanStr)
|
||||
? e.Channel
|
||||
: PermissionHelper.ValidateChannel(e.Server, chanStr);
|
||||
PermissionsHandler.SetChannelFilterInvitesPermission(chan, state);
|
||||
await PermissionsHandler.SetChannelFilterInvitesPermission(chan, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for **{chan.Name}** channel.")
|
||||
.ConfigureAwait(false);
|
||||
return;
|
||||
@ -80,7 +80,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
|
||||
foreach (var curChannel in e.Server.TextChannels)
|
||||
{
|
||||
PermissionsHandler.SetChannelFilterInvitesPermission(curChannel, state);
|
||||
await PermissionsHandler.SetChannelFilterInvitesPermission(curChannel, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for **ALL** channels.")
|
||||
.ConfigureAwait(false);
|
||||
@ -102,7 +102,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
try
|
||||
{
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
PermissionsHandler.SetServerFilterInvitesPermission(e.Server, state);
|
||||
await PermissionsHandler.SetServerFilterInvitesPermission(e.Server, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Invite Filter has been **{(state ? "enabled" : "disabled")}** for this server.")
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
var chan = string.IsNullOrWhiteSpace(chanStr)
|
||||
? e.Channel
|
||||
: PermissionHelper.ValidateChannel(e.Server, chanStr);
|
||||
PermissionsHandler.SetChannelWordPermission(chan, state);
|
||||
await PermissionsHandler.SetChannelWordPermission(chan, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Word filtering has been **{(state ? "enabled" : "disabled")}** for **{chan.Name}** channel.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
@ -76,7 +76,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
|
||||
foreach (var curChannel in e.Server.TextChannels)
|
||||
{
|
||||
PermissionsHandler.SetChannelWordPermission(curChannel, state);
|
||||
await PermissionsHandler.SetChannelWordPermission(curChannel, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Word filtering has been **{(state ? "enabled" : "disabled")}** for **ALL** channels.").ConfigureAwait(false);
|
||||
}
|
||||
@ -98,7 +98,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
var word = e.GetArg("word");
|
||||
if (string.IsNullOrWhiteSpace(word))
|
||||
return;
|
||||
PermissionsHandler.AddFilteredWord(e.Server, word.ToLowerInvariant().Trim());
|
||||
await PermissionsHandler.AddFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Successfully added new filtered word.").ConfigureAwait(false);
|
||||
|
||||
}
|
||||
@ -120,7 +120,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
var word = e.GetArg("word");
|
||||
if (string.IsNullOrWhiteSpace(word))
|
||||
return;
|
||||
PermissionsHandler.RemoveFilteredWord(e.Server, word.ToLowerInvariant().Trim());
|
||||
await PermissionsHandler.RemoveFilteredWord(e.Server, word.ToLowerInvariant().Trim()).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Successfully removed filtered word.").ConfigureAwait(false);
|
||||
|
||||
}
|
||||
@ -159,7 +159,7 @@ namespace NadekoBot.Modules.Permissions.Commands
|
||||
try
|
||||
{
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
PermissionsHandler.SetServerWordPermission(e.Server, state);
|
||||
await PermissionsHandler.SetServerWordPermission(e.Server, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Word filtering has been **{(state ? "enabled" : "disabled")}** on this server.")
|
||||
.ConfigureAwait(false);
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
await e.Channel.SendMessage($"Role `{arg}` probably doesn't exist. Create the role with that name first.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
PermissionsHandler.SetPermissionsRole(e.Server, role.Name);
|
||||
await PermissionsHandler.SetPermissionsRole(e.Server, role.Name).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Role `{role.Name}` is now required in order to change permissions.").ConfigureAwait(false);
|
||||
});
|
||||
|
||||
@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var args = arg.Split('~').Select(a => a.Trim()).ToArray();
|
||||
if (args.Length > 2)
|
||||
{
|
||||
await e.Channel.SendMessage("💢Invalid number of '~'s in the argument.");
|
||||
await e.Channel.SendMessage("💢Invalid number of '~'s in the argument.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
try
|
||||
@ -79,12 +79,12 @@ namespace NadekoBot.Modules.Permissions
|
||||
var fromRole = PermissionHelper.ValidateRole(e.Server, args[0]);
|
||||
var toRole = PermissionHelper.ValidateRole(e.Server, args[1]);
|
||||
|
||||
PermissionsHandler.CopyRolePermissions(fromRole, toRole);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromRole.Name}** to **{toRole.Name}**.");
|
||||
await PermissionsHandler.CopyRolePermissions(fromRole, toRole).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromRole.Name}** to **{toRole.Name}**.").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await e.Channel.SendMessage($"💢{ex.Message}");
|
||||
await e.Channel.SendMessage($"💢{ex.Message}").ConfigureAwait(false);
|
||||
}
|
||||
});
|
||||
cgb.CreateCommand(Prefix + "chnlpermscopy")
|
||||
@ -107,8 +107,8 @@ namespace NadekoBot.Modules.Permissions
|
||||
var fromChannel = PermissionHelper.ValidateChannel(e.Server, args[0]);
|
||||
var toChannel = PermissionHelper.ValidateChannel(e.Server, args[1]);
|
||||
|
||||
PermissionsHandler.CopyChannelPermissions(fromChannel, toChannel);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromChannel.Name}** to **{toChannel.Name}**.");
|
||||
await PermissionsHandler.CopyChannelPermissions(fromChannel, toChannel).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromChannel.Name}** to **{toChannel.Name}**.").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -127,7 +127,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var args = arg.Split('~').Select(a => a.Trim()).ToArray();
|
||||
if (args.Length > 2)
|
||||
{
|
||||
await e.Channel.SendMessage("💢Invalid number of '~'s in the argument.");
|
||||
await e.Channel.SendMessage("💢Invalid number of '~'s in the argument.").ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
try
|
||||
@ -135,8 +135,8 @@ namespace NadekoBot.Modules.Permissions
|
||||
var fromUser = PermissionHelper.ValidateUser(e.Server, args[0]);
|
||||
var toUser = PermissionHelper.ValidateUser(e.Server, args[1]);
|
||||
|
||||
PermissionsHandler.CopyUserPermissions(fromUser, toUser);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromUser.ToString()}**to * *{toUser.ToString()}**.");
|
||||
await PermissionsHandler.CopyUserPermissions(fromUser, toUser).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Copied permission settings from **{fromUser.ToString()}**to * *{toUser.ToString()}**.").ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@ -146,13 +146,13 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
cgb.CreateCommand(Prefix + "verbose")
|
||||
.Alias(Prefix + "v")
|
||||
.Description("Sets whether to show when a command/module is blocked. | ;verbose true")
|
||||
.Description($"Sets whether to show when a command/module is blocked. | `{Prefix}verbose true`")
|
||||
.Parameter("arg", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
var arg = e.GetArg("arg");
|
||||
var val = PermissionHelper.ValidateBool(arg);
|
||||
PermissionsHandler.SetVerbosity(e.Server, val);
|
||||
await PermissionsHandler.SetVerbosity(e.Server, val).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Verbosity set to {val}.").ConfigureAwait(false);
|
||||
});
|
||||
|
||||
@ -169,7 +169,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
cgb.CreateCommand(Prefix + "roleperms")
|
||||
.Alias(Prefix + "rp")
|
||||
.Description("Shows banned permissions for a certain role. No argument means for everyone. | ;rp AwesomeRole")
|
||||
.Description($"Shows banned permissions for a certain role. No argument means for everyone. | `{Prefix}rp AwesomeRole`")
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -195,7 +195,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
cgb.CreateCommand(Prefix + "chnlperms")
|
||||
.Alias(Prefix + "cp")
|
||||
.Description("Shows banned permissions for a certain channel. No argument means for this channel. | ;cp #dev")
|
||||
.Description($"Shows banned permissions for a certain channel. No argument means for this channel. | `{Prefix}cp #dev`")
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -220,7 +220,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
cgb.CreateCommand(Prefix + "userperms")
|
||||
.Alias(Prefix + "up")
|
||||
.Description("Shows banned permissions for a certain user. No argument means for yourself. | ;up Kwoth")
|
||||
.Description($"Shows banned permissions for a certain user. No argument means for yourself. | `{Prefix}up Kwoth`")
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -246,7 +246,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Alias(Prefix + "sm")
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Description("Sets a module's permission at the server level. | ;sm \"module name\" enable")
|
||||
.Description($"Sets a module's permission at the server level. | `{Prefix}sm \"module name\" enable`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var module = PermissionHelper.ValidateModule(e.GetArg("module"));
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
|
||||
PermissionsHandler.SetServerModulePermission(e.Server, module, state);
|
||||
await PermissionsHandler.SetServerModulePermission(e.Server, module, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException exArg)
|
||||
@ -270,7 +270,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
cgb.CreateCommand(Prefix + "srvrcmd").Alias(Prefix + "sc")
|
||||
.Parameter("command", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Description("Sets a command's permission at the server level. | ;sc \"command name\" disable")
|
||||
.Description($"Sets a command's permission at the server level. | `{Prefix}sc \"command name\" disable`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -278,7 +278,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var command = PermissionHelper.ValidateCommand(e.GetArg("command"));
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
|
||||
PermissionsHandler.SetServerCommandPermission(e.Server, command, state);
|
||||
await PermissionsHandler.SetServerCommandPermission(e.Server, command, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException exArg)
|
||||
@ -295,7 +295,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Description("Sets a module's permission at the role level. | ;rm \"module name\" enable MyRole")
|
||||
.Description($"Sets a module's permission at the role level. | `{Prefix}rm \"module name\" enable MyRole`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -307,7 +307,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
foreach (var role in e.Server.Roles)
|
||||
{
|
||||
PermissionsHandler.SetRoleModulePermission(role, module, state);
|
||||
await PermissionsHandler.SetRoleModulePermission(role, module, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles.").ConfigureAwait(false);
|
||||
}
|
||||
@ -315,7 +315,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role"));
|
||||
|
||||
PermissionsHandler.SetRoleModulePermission(role, module, state);
|
||||
await PermissionsHandler.SetRoleModulePermission(role, module, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@ -333,7 +333,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("command", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Description("Sets a command's permission at the role level. | ;rc \"command name\" disable MyRole")
|
||||
.Description($"Sets a command's permission at the role level. | `{Prefix}rc \"command name\" disable MyRole`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -345,7 +345,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
foreach (var role in e.Server.Roles)
|
||||
{
|
||||
PermissionsHandler.SetRoleCommandPermission(role, command, state);
|
||||
await PermissionsHandler.SetRoleCommandPermission(role, command, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles.").ConfigureAwait(false);
|
||||
}
|
||||
@ -353,7 +353,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role"));
|
||||
|
||||
PermissionsHandler.SetRoleCommandPermission(role, command, state);
|
||||
await PermissionsHandler.SetRoleCommandPermission(role, command, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@ -371,7 +371,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Description("Sets a module's permission at the channel level. | ;cm \"module name\" enable SomeChannel")
|
||||
.Description($"Sets a module's permission at the channel level. | `{Prefix}cm \"module name\" enable SomeChannel`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -383,20 +383,20 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
foreach (var channel in e.Server.TextChannels)
|
||||
{
|
||||
PermissionsHandler.SetChannelModulePermission(channel, module, state);
|
||||
await PermissionsHandler.SetChannelModulePermission(channel, module, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels.").ConfigureAwait(false);
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(channelArg))
|
||||
{
|
||||
PermissionsHandler.SetChannelModulePermission(e.Channel, module, state);
|
||||
await PermissionsHandler.SetChannelModulePermission(e.Channel, module, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{e.Channel.Name}** channel.").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
var channel = PermissionHelper.ValidateChannel(e.Server, channelArg);
|
||||
|
||||
PermissionsHandler.SetChannelModulePermission(channel, module, state);
|
||||
await PermissionsHandler.SetChannelModulePermission(channel, module, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@ -414,7 +414,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("command", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Description("Sets a command's permission at the channel level. | ;cc \"command name\" enable SomeChannel")
|
||||
.Description($"Sets a command's permission at the channel level. | `{Prefix}cc \"command name\" enable SomeChannel`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -426,7 +426,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
foreach (var channel in e.Server.TextChannels)
|
||||
{
|
||||
PermissionsHandler.SetChannelCommandPermission(channel, command, state);
|
||||
await PermissionsHandler.SetChannelCommandPermission(channel, command, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels.").ConfigureAwait(false);
|
||||
}
|
||||
@ -434,7 +434,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel"));
|
||||
|
||||
PermissionsHandler.SetChannelCommandPermission(channel, command, state);
|
||||
await PermissionsHandler.SetChannelCommandPermission(channel, command, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
@ -452,7 +452,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.Description("Sets a module's permission at the user level. | ;um \"module name\" enable SomeUsername")
|
||||
.Description($"Sets a module's permission at the user level. | `{Prefix}um \"module name\" enable SomeUsername`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -461,7 +461,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
var user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user"));
|
||||
|
||||
PermissionsHandler.SetUserModulePermission(user, module, state);
|
||||
await PermissionsHandler.SetUserModulePermission(user, module, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException exArg)
|
||||
@ -478,7 +478,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("command", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.Description("Sets a command's permission at the user level. | ;uc \"command name\" enable SomeUsername")
|
||||
.Description($"Sets a command's permission at the user level. | `{Prefix}uc \"command name\" enable SomeUsername`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -487,7 +487,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var state = PermissionHelper.ValidateBool(e.GetArg("bool"));
|
||||
var user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user"));
|
||||
|
||||
PermissionsHandler.SetUserCommandPermission(user, command, state);
|
||||
await PermissionsHandler.SetUserCommandPermission(user, command, state).ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**.").ConfigureAwait(false);
|
||||
}
|
||||
catch (ArgumentException exArg)
|
||||
@ -502,7 +502,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
cgb.CreateCommand(Prefix + "allsrvrmdls").Alias(Prefix + "asm")
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Description("Sets permissions for all modules at the server level. | ;asm [enable/disable]")
|
||||
.Description($"Sets permissions for all modules at the server level. | `{Prefix}asm [enable/disable]`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -511,7 +511,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
|
||||
{
|
||||
PermissionsHandler.SetServerModulePermission(e.Server, module.Name, state);
|
||||
await PermissionsHandler.SetServerModulePermission(e.Server, module.Name, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
|
||||
}
|
||||
@ -528,7 +528,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
cgb.CreateCommand(Prefix + "allsrvrcmds").Alias(Prefix + "asc")
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Description("Sets permissions for all commands from a certain module at the server level. | ;asc \"module name\" [enable/disable]")
|
||||
.Description($"Sets permissions for all commands from a certain module at the server level. | `{Prefix}asc \"module name\" [enable/disable]`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -538,7 +538,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
|
||||
{
|
||||
PermissionsHandler.SetServerCommandPermission(e.Server, command.Text, state);
|
||||
await PermissionsHandler.SetServerCommandPermission(e.Server, command.Text, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** on this server.").ConfigureAwait(false);
|
||||
}
|
||||
@ -555,7 +555,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
cgb.CreateCommand(Prefix + "allchnlmdls").Alias(Prefix + "acm")
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Description("Sets permissions for all modules at the channel level. | ;acm [enable/disable] SomeChannel")
|
||||
.Description($"Sets permissions for all modules at the channel level. | `{Prefix}acm [enable/disable] SomeChannel`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -565,7 +565,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var channel = string.IsNullOrWhiteSpace(chArg) ? e.Channel : PermissionHelper.ValidateChannel(e.Server, chArg);
|
||||
foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
|
||||
{
|
||||
PermissionsHandler.SetChannelModulePermission(channel, module.Name, state);
|
||||
await PermissionsHandler.SetChannelModulePermission(channel, module.Name, state).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
|
||||
@ -584,7 +584,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Description("Sets permissions for all commands from a certain module at the channel level. | ;acc \"module name\" [enable/disable] SomeChannel")
|
||||
.Description($"Sets permissions for all commands from a certain module at the channel level. | `{Prefix}acc \"module name\" [enable/disable] SomeChannel`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -594,7 +594,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel"));
|
||||
foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
|
||||
{
|
||||
PermissionsHandler.SetChannelCommandPermission(channel, command.Text, state);
|
||||
await PermissionsHandler.SetChannelCommandPermission(channel, command.Text, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel.").ConfigureAwait(false);
|
||||
}
|
||||
@ -611,7 +611,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
cgb.CreateCommand(Prefix + "allrolemdls").Alias(Prefix + "arm")
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Description("Sets permissions for all modules at the role level. | ;arm [enable/disable] MyRole")
|
||||
.Description($"Sets permissions for all modules at the role level. | `{Prefix}arm [enable/disable] MyRole`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -620,7 +620,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role"));
|
||||
foreach (var module in NadekoBot.Client.GetService<ModuleService>().Modules)
|
||||
{
|
||||
PermissionsHandler.SetRoleModulePermission(role, module.Name, state);
|
||||
await PermissionsHandler.SetRoleModulePermission(role, module.Name, state).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
|
||||
@ -639,7 +639,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
.Parameter("module", ParameterType.Required)
|
||||
.Parameter("bool", ParameterType.Required)
|
||||
.Parameter("role", ParameterType.Unparsed)
|
||||
.Description("Sets permissions for all commands from a certain module at the role level. | ;arc \"module name\" [enable/disable] MyRole")
|
||||
.Description($"Sets permissions for all commands from a certain module at the role level. | `{Prefix}arc \"module name\" [enable/disable] MyRole`")
|
||||
.Do(async e =>
|
||||
{
|
||||
try
|
||||
@ -652,7 +652,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
{
|
||||
foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
|
||||
{
|
||||
PermissionsHandler.SetRoleCommandPermission(role, command.Text, state);
|
||||
await PermissionsHandler.SetRoleCommandPermission(role, command.Text, state).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **all roles** role.").ConfigureAwait(false);
|
||||
@ -663,7 +663,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
|
||||
foreach (var command in NadekoBot.Client.GetService<CommandService>().AllCommands.Where(c => c.Category == module))
|
||||
{
|
||||
PermissionsHandler.SetRoleCommandPermission(role, command.Text, state);
|
||||
await PermissionsHandler.SetRoleCommandPermission(role, command.Text, state).ConfigureAwait(false);
|
||||
}
|
||||
await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role.").ConfigureAwait(false);
|
||||
}
|
||||
@ -679,7 +679,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "ubl")
|
||||
.Description("Blacklists a mentioned user. | ;ubl [user_mention]")
|
||||
.Description($"Blacklists a mentioned user. | `{Prefix}ubl [user_mention]`")
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -689,13 +689,13 @@ namespace NadekoBot.Modules.Permissions
|
||||
if (!e.Message.MentionedUsers.Any()) return;
|
||||
var usr = e.Message.MentionedUsers.First();
|
||||
NadekoBot.Config.UserBlacklist.Add(usr.Id);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`").ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "uubl")
|
||||
.Description($"Unblacklists a mentioned user. | {Prefix}uubl [user_mention]")
|
||||
.Description($"Unblacklists a mentioned user. | `{Prefix}uubl [user_mention]`")
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -707,7 +707,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
if (NadekoBot.Config.UserBlacklist.Contains(usr.Id))
|
||||
{
|
||||
NadekoBot.Config.UserBlacklist.Remove(usr.Id);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"`Sucessfully unblacklisted user {usr.Name}`").ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
@ -718,7 +718,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "cbl")
|
||||
.Description("Blacklists a mentioned channel (#general for example). | ;cbl #some_channel")
|
||||
.Description($"Blacklists a mentioned channel (#general for example). | `{Prefix}cbl #some_channel`")
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -727,13 +727,13 @@ namespace NadekoBot.Modules.Permissions
|
||||
if (!e.Message.MentionedChannels.Any()) return;
|
||||
var ch = e.Message.MentionedChannels.First();
|
||||
NadekoBot.Config.UserBlacklist.Add(ch.Id);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "cubl")
|
||||
.Description("Unblacklists a mentioned channel (#general for example). | ;cubl #some_channel")
|
||||
.Description($"Unblacklists a mentioned channel (#general for example). | `{Prefix}cubl #some_channel`")
|
||||
.Parameter("channel", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -742,13 +742,13 @@ namespace NadekoBot.Modules.Permissions
|
||||
if (!e.Message.MentionedChannels.Any()) return;
|
||||
var ch = e.Message.MentionedChannels.First();
|
||||
NadekoBot.Config.UserBlacklist.Remove(ch.Id);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false);
|
||||
}).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "sbl")
|
||||
.Description("Blacklists a server by a name or id (#general for example). **BOT OWNER ONLY** | ;sbl [servername/serverid]")
|
||||
.Description($"Blacklists a server by a name or id (#general for example). **BOT OWNER ONLY** | `{Prefix}sbl [servername/serverid]`")
|
||||
.Parameter("server", ParameterType.Unparsed)
|
||||
.AddCheck(SimpleCheckers.OwnerOnly())
|
||||
.Do(async e =>
|
||||
@ -767,7 +767,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
}
|
||||
var serverId = server.Id;
|
||||
NadekoBot.Config.ServerBlacklist.Add(serverId);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
//cleanup trivias and typeracing
|
||||
Modules.Games.Commands.Trivia.TriviaGame trivia;
|
||||
TriviaCommands.RunningTrivias.TryRemove(serverId, out trivia);
|
||||
@ -795,7 +795,7 @@ namespace NadekoBot.Modules.Permissions
|
||||
throw new ArgumentOutOfRangeException("secs", "Invalid second parameter. (Must be a number between 0 and 3600)");
|
||||
|
||||
|
||||
PermissionsHandler.SetCommandCooldown(e.Server, command, secs);
|
||||
await PermissionsHandler.SetCommandCooldown(e.Server, command, secs).ConfigureAwait(false);
|
||||
if(secs == 0)
|
||||
await e.Channel.SendMessage($"Command **{command}** has no coooldown now.").ConfigureAwait(false);
|
||||
else
|
||||
|
@ -30,8 +30,6 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
}
|
||||
|
||||
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();
|
||||
public LoLCommands(DiscordModule module) : base(module)
|
||||
@ -42,7 +40,6 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (cacheLock)
|
||||
CachedChampionImages = CachedChampionImages
|
||||
.Where(kvp => DateTime.Now - kvp.Value.AddedAt > new TimeSpan(1, 0, 0))
|
||||
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
@ -87,16 +84,14 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
var resolvedRole = role;
|
||||
var name = e.GetArg("champ").Replace(" ", "").ToLower();
|
||||
CachedChampion champ = null;
|
||||
lock (cacheLock)
|
||||
{
|
||||
CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ);
|
||||
}
|
||||
if (champ != null)
|
||||
{
|
||||
champ.ImageStream.Position = 0;
|
||||
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ))
|
||||
if (champ != null)
|
||||
{
|
||||
champ.ImageStream.Position = 0;
|
||||
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
var allData = JArray.Parse(await Classes.SearchHelper.GetResponseStringAsync($"http://api.champion.gg/champion/{name}?api_key={NadekoBot.Creds.LOLAPIKey}").ConfigureAwait(false));
|
||||
JToken data = null;
|
||||
if (role != null)
|
||||
@ -121,17 +116,13 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
role = allData[0]["role"].ToString();
|
||||
resolvedRole = ResolvePos(role);
|
||||
}
|
||||
lock (cacheLock)
|
||||
{
|
||||
CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ);
|
||||
}
|
||||
if (champ != null)
|
||||
{
|
||||
Console.WriteLine("Sending lol image from cache.");
|
||||
champ.ImageStream.Position = 0;
|
||||
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
if(CachedChampionImages.TryGetValue(name + "_" + resolvedRole, out champ))
|
||||
if (champ != null)
|
||||
{
|
||||
champ.ImageStream.Position = 0;
|
||||
await e.Channel.SendFile("champ.png", champ.ImageStream).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
//name = data["title"].ToString();
|
||||
// get all possible roles, and "select" the shown one
|
||||
var roles = new string[allData.Count];
|
||||
|
@ -68,7 +68,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
};
|
||||
checkTimer.Start();
|
||||
}
|
||||
@ -254,7 +254,7 @@ namespace NadekoBot.Modules.Searches.Commands
|
||||
}
|
||||
|
||||
config.ObservingStreams.Remove(toRemove);
|
||||
ConfigHandler.SaveConfig();
|
||||
await ConfigHandler.SaveConfig().ConfigureAwait(false);
|
||||
await e.Channel.SendMessage($":ok: Removed `{toRemove.Username}`'s stream from notifications.").ConfigureAwait(false);
|
||||
});
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace NadekoBot.Modules.Searches
|
||||
commands.ForEach(cmd => cmd.Init(cgb));
|
||||
|
||||
cgb.CreateCommand(Prefix + "we")
|
||||
.Description($"Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | {Prefix}we Moscow RF")
|
||||
.Description($"Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `{Prefix}we Moscow RF`")
|
||||
.Parameter("city", ParameterType.Required)
|
||||
.Parameter("country", ParameterType.Required)
|
||||
.Do(async e =>
|
||||
@ -69,7 +69,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
|
||||
cgb.CreateCommand(Prefix + "yt")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Description("Searches youtubes and shows the first result")
|
||||
.Description($"Searches youtubes and shows the first result | `{Prefix}yt query`")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return;
|
||||
@ -106,7 +106,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
|
||||
cgb.CreateCommand(Prefix + "imdb")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Description("Queries imdb for movies or series, show first result.")
|
||||
.Description($"Queries imdb for movies or series, show first result. | `{Prefix}imdb query`")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return;
|
||||
@ -130,7 +130,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
cgb.CreateCommand(Prefix + "mang")
|
||||
.Alias(Prefix + "manga").Alias(Prefix + "mq")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Description("Queries anilist for a manga and shows the first result.")
|
||||
.Description($"Queries anilist for a manga and shows the first result. | `{Prefix}mq query`")
|
||||
.Do(async e =>
|
||||
{
|
||||
if (!(await SearchHelper.ValidateQuery(e.Channel, e.GetArg("query")).ConfigureAwait(false))) return;
|
||||
@ -157,8 +157,16 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
.ConfigureAwait(false);
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "randomdog")
|
||||
.Alias(Prefix + "woof")
|
||||
.Description("Shows a random dog image.")
|
||||
.Do(async e =>
|
||||
{
|
||||
await e.Channel.SendMessage("http://random.dog/" + await SearchHelper.GetResponseStringAsync("http://random.dog/woof").ConfigureAwait(false)).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "i")
|
||||
.Description("Pulls the first image found using a search parameter. Use ~ir for different results. | ~i cute kitten")
|
||||
.Description($"Pulls the first image found using a search parameter. Use ~ir for different results. | `{Prefix}i cute kitten`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -184,7 +192,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "ir")
|
||||
.Description("Pulls a random image using a search parameter. | ~ir cute kitten")
|
||||
.Description($"Pulls a random image using a search parameter. | `{Prefix}ir cute kitten`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -211,7 +219,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "lmgtfy")
|
||||
.Description("Google something for an idiot.")
|
||||
.Description($"Google something for an idiot. | `{Prefix}lmgtfy query`")
|
||||
.Parameter("ffs", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -222,7 +230,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
|
||||
cgb.CreateCommand(Prefix + "google")
|
||||
.Alias(Prefix + "g")
|
||||
.Description("Get a google search link for some terms.")
|
||||
.Description($"Get a google search link for some terms. | `{Prefix}google query`")
|
||||
.Parameter("terms", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -234,7 +242,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "hs")
|
||||
.Description("Searches for a Hearthstone card and shows its image. Takes a while to complete. |~hs Ysera")
|
||||
.Description($"Searches for a Hearthstone card and shows its image. Takes a while to complete. | `{Prefix}hs Ysera`")
|
||||
.Parameter("name", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -275,7 +283,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "ud")
|
||||
.Description("Searches Urban Dictionary for a word. |~ud Pineapple")
|
||||
.Description($"Searches Urban Dictionary for a word. | `{Prefix}ud Pineapple`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -304,7 +312,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
// thanks to Blaubeerwald
|
||||
cgb.CreateCommand(Prefix + "#")
|
||||
.Description("Searches Tagdef.com for a hashtag. |~# ff")
|
||||
.Description($"Searches Tagdef.com for a hashtag. | `{Prefix}# ff`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -389,7 +397,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "revav")
|
||||
.Description("Returns a google reverse image search for someone's avatar.")
|
||||
.Description($"Returns a google reverse image search for someone's avatar. | `{Prefix}revav \"@SomeGuy\"")
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -406,7 +414,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "revimg")
|
||||
.Description("Returns a google reverse image search for an image from a link.")
|
||||
.Description($"Returns a google reverse image search for an image from a link. | `{Prefix}revav Image link`")
|
||||
.Parameter("image", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -418,7 +426,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "safebooru")
|
||||
.Description("Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~safebooru yuri+kissing")
|
||||
.Description($"Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `{Prefix}safebooru yuri+kissing`")
|
||||
.Parameter("tag", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -431,7 +439,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "wiki")
|
||||
.Description("Gives you back a wikipedia link")
|
||||
.Description($"Gives you back a wikipedia link | `{Prefix}wiki query`")
|
||||
.Parameter("query", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -445,7 +453,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "clr")
|
||||
.Description("Shows you what color corresponds to that hex. | `~clr 00ff00`")
|
||||
.Description($"Shows you what color corresponds to that hex. | `{Prefix}clr 00ff00`")
|
||||
.Parameter("color", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -470,7 +478,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
|
||||
|
||||
cgb.CreateCommand(Prefix + "videocall")
|
||||
.Description("Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message.")
|
||||
.Description($"Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `{Prefix}videocall \"@SomeGuy\"`")
|
||||
.Parameter("arg", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -494,7 +502,7 @@ $@"🌍 **Weather for** 【{obj["target"]}】
|
||||
cgb.CreateCommand(Prefix + "av")
|
||||
.Alias(Prefix + "avatar")
|
||||
.Parameter("mention", ParameterType.Required)
|
||||
.Description("Shows a mentioned person's avatar. | ~av @X")
|
||||
.Description($"Shows a mentioned person's avatar. | `{Prefix}av @X`")
|
||||
.Do(async e =>
|
||||
{
|
||||
var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
|
||||
|
@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Translator
|
||||
{
|
||||
cgb.CreateCommand(Module.Prefix + "translate")
|
||||
.Alias(Module.Prefix + "trans")
|
||||
.Description($"Translates from>to text. From the given language to the destiation language. | {Module.Prefix}trans en>fr Hello")
|
||||
.Description($"Translates from>to text. From the given language to the destiation language. | `{Module.Prefix}trans en>fr Hello`")
|
||||
.Parameter("langs", ParameterType.Required)
|
||||
.Parameter("text", ParameterType.Unparsed)
|
||||
.Do(TranslateFunc());
|
||||
|
@ -71,7 +71,7 @@ namespace NadekoBot.Modules.Trello
|
||||
cgb.CreateCommand(Prefix + "bind")
|
||||
.Description("Bind a trello bot to a single channel. " +
|
||||
"You will receive notifications from your board when something is added or edited." +
|
||||
" | bind [board_id]")
|
||||
$" | `{Prefix}bind [board_id]`")
|
||||
.Parameter("board_id", Discord.Commands.ParameterType.Required)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -116,7 +116,7 @@ namespace NadekoBot.Modules.Trello
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "cards")
|
||||
.Description("Lists all cards from the supplied list. You can supply either a name or an index.")
|
||||
.Description($"Lists all cards from the supplied list. You can supply either a name or an index. | `{Prefix}cards index`")
|
||||
.Parameter("list_name", Discord.Commands.ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ namespace NadekoBot.Modules.Utility
|
||||
commands.ForEach(cmd => cmd.Init(cgb));
|
||||
|
||||
cgb.CreateCommand(Prefix + "whoplays")
|
||||
.Description("Shows a list of users who are playing the specified game.")
|
||||
.Description($"Shows a list of users who are playing the specified game. | `{Prefix}whoplays Overwatch`")
|
||||
.Parameter("game", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -52,16 +52,15 @@ namespace NadekoBot.Modules.Utility
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "inrole")
|
||||
.Description("Lists every person from the provided role or roles (separated by a ',') on this server.")
|
||||
.Description($"Lists every person from the provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `{Prefix}inrole Role`")
|
||||
.Parameter("roles", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
if (!e.User.ServerPermissions.MentionEveryone) return;
|
||||
var arg = e.GetArg("roles").Split(',').Select(r => r.Trim());
|
||||
string send = $"`Here is a list of users in a specfic role:`";
|
||||
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str)))
|
||||
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@everyone" && str != "everyone"))
|
||||
{
|
||||
var role = e.Server.FindRoles(roleStr).FirstOrDefault();
|
||||
if (role == null) continue;
|
||||
@ -71,6 +70,11 @@ namespace NadekoBot.Modules.Utility
|
||||
|
||||
while (send.Length > 2000)
|
||||
{
|
||||
if (!e.User.ServerPermissions.ManageMessages)
|
||||
{
|
||||
await e.Channel.SendMessage($"{e.User.Mention} you are not allowed to use this command on roles with a lot of users in them to prevent abuse.");
|
||||
return;
|
||||
}
|
||||
var curstr = send.Substring(0, 2000);
|
||||
await
|
||||
e.Channel.Send(curstr.Substring(0,
|
||||
@ -110,7 +114,7 @@ namespace NadekoBot.Modules.Utility
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "userid").Alias(Prefix + "uid")
|
||||
.Description("Shows user ID.")
|
||||
.Description($"Shows user ID. | `{Prefix}uid` or `{Prefix}uid \"@SomeGuy\"")
|
||||
.Parameter("user", ParameterType.Unparsed)
|
||||
.Do(async e =>
|
||||
{
|
||||
@ -122,11 +126,11 @@ namespace NadekoBot.Modules.Utility
|
||||
});
|
||||
|
||||
cgb.CreateCommand(Prefix + "channelid").Alias(Prefix + "cid")
|
||||
.Description("Shows current channel ID.")
|
||||
.Description($"Shows current channel ID. | `{Prefix}cid`")
|
||||
.Do(async e => await e.Channel.SendMessage("This channel's ID is " + e.Channel.Id).ConfigureAwait(false));
|
||||
|
||||
cgb.CreateCommand(Prefix + "serverid").Alias(Prefix + "sid")
|
||||
.Description("Shows current server ID.")
|
||||
.Description($"Shows current server ID. | `{Prefix}sid`")
|
||||
.Do(async e => await e.Channel.SendMessage("This server's ID is " + e.Server.Id).ConfigureAwait(false));
|
||||
|
||||
cgb.CreateCommand(Prefix + "roles")
|
||||
@ -144,6 +148,18 @@ namespace NadekoBot.Modules.Utility
|
||||
}
|
||||
await e.Channel.SendMessage("`List of roles:` \n• " + string.Join("\n• ", e.Server.Roles)).ConfigureAwait(false);
|
||||
});
|
||||
|
||||
|
||||
cgb.CreateCommand(Prefix + "channeltopic")
|
||||
.Alias(Prefix + "ct")
|
||||
.Description($"Sends current channel's topic as a message. | `{Prefix}ct`")
|
||||
.Do(async e =>
|
||||
{
|
||||
var topic = e.Channel.Topic;
|
||||
if (string.IsNullOrWhiteSpace(topic))
|
||||
return;
|
||||
await e.Channel.SendMessage(topic).ConfigureAwait(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +197,7 @@ namespace NadekoBot
|
||||
return;
|
||||
}
|
||||
#if NADEKO_RELEASE
|
||||
await Task.Delay(90000).ConfigureAwait(false);
|
||||
await Task.Delay(100000).ConfigureAwait(false);
|
||||
#else
|
||||
await Task.Delay(1000).ConfigureAwait(false);
|
||||
#endif
|
||||
|
@ -46,6 +46,7 @@
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<NoWarn>
|
||||
</NoWarn>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
@ -55,6 +56,7 @@
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'PRIVATE|AnyCPU'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@ -78,13 +80,14 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>TRACE;DEBUG</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
@ -115,6 +118,7 @@
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="libvideo, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
@ -186,6 +190,7 @@
|
||||
<Compile Include="Classes\FlowersHandler.cs" />
|
||||
<Compile Include="Modules\Conversations\Commands\RipCommand.cs" />
|
||||
<Compile Include="Modules\CustomReactions\CustomReactions.cs" />
|
||||
<Compile Include="Modules\Gambling\Commands\AnimalRacing.cs" />
|
||||
<Compile Include="Modules\Music\Classes\PlaylistFullException.cs" />
|
||||
<Compile Include="Modules\Programming\Commands\HaskellRepl.cs" />
|
||||
<Compile Include="Modules\Programming\ProgrammingModule.cs" />
|
||||
|
@ -4,6 +4,8 @@ using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Classes.JSONModels
|
||||
{
|
||||
@ -88,6 +90,17 @@ namespace NadekoBot.Classes.JSONModels
|
||||
public bool IsRotatingStatus { get; set; } = false;
|
||||
public int BufferSize { get; set; } = 4.MiB();
|
||||
|
||||
public string[] RaceAnimals { get; internal set; } = {
|
||||
"🐼",
|
||||
"🐻",
|
||||
"🐧",
|
||||
"🐨",
|
||||
"🐬",
|
||||
"🐞",
|
||||
"🦀",
|
||||
"🦄" };
|
||||
|
||||
[JsonIgnore]
|
||||
public List<Quote> Quotes { get; set; } = new List<Quote>();
|
||||
|
||||
[JsonIgnore]
|
||||
@ -187,13 +200,17 @@ Nadeko Support Server: <https://discord.gg/0ehQwTK2RBjAxzEY>";
|
||||
|
||||
public static class ConfigHandler
|
||||
{
|
||||
private static readonly object configLock = new object();
|
||||
public static void SaveConfig()
|
||||
private static readonly SemaphoreSlim configLock = new SemaphoreSlim(1, 1);
|
||||
public static async Task SaveConfig()
|
||||
{
|
||||
lock (configLock)
|
||||
await configLock.WaitAsync();
|
||||
try
|
||||
{
|
||||
File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented));
|
||||
}
|
||||
finally {
|
||||
configLock.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) ||
|
||||
|
@ -4,7 +4,16 @@
|
||||
"ForwardToAllOwners": false,
|
||||
"IsRotatingStatus": false,
|
||||
"BufferSize": 4194304,
|
||||
"Quotes": [],
|
||||
"RaceAnimals": [
|
||||
"🐼",
|
||||
"🐻",
|
||||
"🐧",
|
||||
"🐨",
|
||||
"🐬",
|
||||
"🐞",
|
||||
"🦀",
|
||||
"🦄"
|
||||
],
|
||||
"RemindMessageFormat": "❗⏰**I've been told to remind you to '%message%' now by %user%.**⏰❗",
|
||||
"CustomReactions": {
|
||||
"\\o\\": [
|
||||
|
178
commandlist.md
178
commandlist.md
@ -2,7 +2,7 @@
|
||||
######You can donate on paypal: `nadekodiscordbot@gmail.com`
|
||||
|
||||
#NadekoBot List Of Commands
|
||||
Version: `NadekoBot v0.9.6048.2992`
|
||||
Version: `NadekoBot v0.9.6051.26856`
|
||||
### Help
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
@ -57,38 +57,38 @@ Command and aliases | Description | Usage
|
||||
`.listallincidents`, `.lain` | Sends you a file containing all incidents and flags them as read.
|
||||
`.delmsgoncmd` | Toggles the automatic deletion of user's successful command message to prevent chat flood. Server Manager Only.
|
||||
`.restart` | Restarts the bot. Might not work. **Bot Owner Only**
|
||||
`.setrole`, `.sr` | Sets a role for a given user. | .sr @User Guest
|
||||
`.removerole`, `.rr` | Removes a role from a given user. | .rr @User Admin
|
||||
`.setrole`, `.sr` | Sets a role for a given user. | `.sr @User Guest`
|
||||
`.removerole`, `.rr` | Removes a role from a given user. | `.rr @User Admin`
|
||||
`.renamerole`, `.renr` | Renames a role. Role you are renaming must be lower than bot's highest role. | `.renr "First role" SecondRole`
|
||||
`.removeallroles`, `.rar` | Removes all roles from a mentioned user. | .rar @User
|
||||
`.createrole`, `.cr` | Creates a role with a given name. | `.r Awesome Role`
|
||||
`.rolecolor`, `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. | `.color Admin 255 200 100` or `.color Admin ffba55`
|
||||
`.ban`, `.b` | Bans a user by id or name with an optional message. | .b "@some Guy" Your behaviour is toxic.
|
||||
`.softban`, `.sb` | Bans and then unbans a user by id or name with an optional message. | .sb "@some Guy" Your behaviour is toxic.
|
||||
`.kick`, `.k` | Kicks a mentioned user.
|
||||
`.mute` | Mutes mentioned user or users.
|
||||
`.unmute` | Unmutes mentioned user or users.
|
||||
`.deafen`, `.deaf` | Deafens mentioned user or users
|
||||
`.undeafen`, `.undef` | Undeafens mentioned user or users
|
||||
`.delvoichanl`, `.dvch` | Deletes a voice channel with a given name.
|
||||
`.creatvoichanl`, `.cvch` | Creates a new voice channel with a given name.
|
||||
`.deltxtchanl`, `.dtch` | Deletes a text channel with a given name.
|
||||
`.creatxtchanl`, `.ctch` | Creates a new text channel with a given name.
|
||||
`.removeallroles`, `.rar` | Removes all roles from a mentioned user. | `.rar @User`
|
||||
`.createrole`, `.cr` | Creates a role with a given name. | `.cr Awesome Role`
|
||||
`.rolecolor`, `.rc` | Set a role's color to the hex or 0-255 rgb color value provided. | `.rc Admin 255 200 100` or `.rc Admin ffba55`
|
||||
`.ban`, `.b` | Bans a user by id or name with an optional message. | `.b "@some Guy" Your behaviour is toxic.`
|
||||
`.softban`, `.sb` | Bans and then unbans a user by id or name with an optional message. | `.sb "@some Guy" Your behaviour is toxic.`
|
||||
`.kick`, `.k` | Kicks a mentioned user. | `.k "@some Guy" Your behaviour is toxic.`
|
||||
`.mute` | Mutes mentioned user or users. | `.mute "@Someguy"` or `.mute "@Someguy" "@Someguy"`
|
||||
`.unmute` | Unmutes mentioned user or users. | `.unmute "@Someguy"` or `.unmute "@Someguy" "@Someguy"`
|
||||
`.deafen`, `.deaf` | Deafens mentioned user or users | `.deaf "@Someguy"` or `.deaf "@Someguy" "@Someguy"`
|
||||
`.undeafen`, `.undef` | Undeafens mentioned user or users | `.undef "@Someguy"` or `.undef "@Someguy" "@Someguy"`
|
||||
`.delvoichanl`, `.dvch` | Deletes a voice channel with a given name. | `.dvch VoiceChannelName`
|
||||
`.creatvoichanl`, `.cvch` | Creates a new voice channel with a given name. | `.cvch VoiceChannelName`
|
||||
`.deltxtchanl`, `.dtch` | Deletes a text channel with a given name. | `.dtch TextChannelName`
|
||||
`.creatxtchanl`, `.ctch` | Creates a new text channel with a given name. | `.ctch TextChannelName`
|
||||
`.settopic`, `.st` | Sets a topic on the current channel. | `.st My new topic`
|
||||
`.setchanlname`, `.schn` | Changed the name of the current channel.
|
||||
`.setchanlname`, `.schn` | Changed the name of the current channel.| `.schn NewName`
|
||||
`.heap` | Shows allocated memory - **Bot Owner Only!**
|
||||
`.prune`, `.clr` | `.prune` removes all nadeko's messages in the last 100 messages.`.prune X` removes last X messages from the channel (up to 100)`.prune @Someone` removes all Someone's messages in the last 100 messages.`.prune @Someone X` removes last X 'Someone's' messages in the channel. | `.prune` or `.prune 5` or `.prune @Someone` or `.prune @Someone X`
|
||||
`.die` | Shuts the bot down and notifies users about the restart. **Bot Owner Only!**
|
||||
`.setname`, `.newnm` | Give the bot a new name. **Bot Owner Only!**
|
||||
`.setname`, `.newnm` | Give the bot a new name. **Bot Owner Only!** | .newnm BotName
|
||||
`.newavatar`, `.setavatar` | Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. **Bot Owner Only!** | `.setavatar https://i.ytimg.com/vi/WDudkR1eTMM/maxresdefault.jpg`
|
||||
`.setgame` | Sets the bots game. **Bot Owner Only!**
|
||||
`.setgame` | Sets the bots game. **Bot Owner Only!** | `.setgame Playing with kwoth`
|
||||
`.send` | Send a message to someone on a different server through the bot. **Bot Owner Only!** | `.send serverid|u:user_id Send this to a user!` or `.send serverid|c:channel_id Send this to a channel!`
|
||||
`.mentionrole`, `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission.
|
||||
`.mentionrole`, `.menro` | Mentions every person from the provided role or roles (separated by a ',') on this server. Requires you to have mention everyone permission. | `.menro RoleName`
|
||||
`.unstuck` | Clears the message queue. **Bot Owner Only!**
|
||||
`.donators` | List of lovely people who donated to keep this project alive.
|
||||
`.donadd` | Add a donator to the database.
|
||||
`.announce` | Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | .announce Useless spam
|
||||
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.chatsave 150`
|
||||
`.donadd` | Add a donator to the database. | `.donadd Donate Amount`
|
||||
`.announce` | Sends a message to all servers' general channel bot is connected to.**Bot Owner Only!** | `.announce Useless spam`
|
||||
`.savechat` | Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.savechat 150`
|
||||
|
||||
### Utility
|
||||
Command and aliases | Description | Usage
|
||||
@ -98,15 +98,16 @@ Command and aliases | Description | Usage
|
||||
`.serverinfo`, `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | .sinfo Some Server
|
||||
`.channelinfo`, `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | .cinfo #some-channel
|
||||
`.userinfo`, `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | .uinfo @SomeUser
|
||||
`.whoplays` | Shows a list of users who are playing the specified game.
|
||||
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server.
|
||||
`.whoplays` | Shows a list of users who are playing the specified game. | `.whoplays Overwatch`
|
||||
`.inrole` | Lists every person from the provided role or roles (separated by a ',') on this server. If the list is too long for 1 message, you must have Manage Messages permission. | `.inrole Role`
|
||||
`.checkmyperms` | Checks your userspecific permissions on this channel.
|
||||
`.stats` | Shows some basic stats for Nadeko.
|
||||
`.dysyd` | Shows some basic stats for Nadeko.
|
||||
`.userid`, `.uid` | Shows user ID.
|
||||
`.channelid`, `.cid` | Shows current channel ID.
|
||||
`.serverid`, `.sid` | Shows current server ID.
|
||||
`.userid`, `.uid` | Shows user ID. | `.uid` or `.uid "@SomeGuy"
|
||||
`.channelid`, `.cid` | Shows current channel ID. | `.cid`
|
||||
`.serverid`, `.sid` | Shows current server ID. | `.sid`
|
||||
`.roles` | List all roles on this server or a single user if specified.
|
||||
`.channeltopic`, `.ct` | Sends current channel's topic as a message. | `.ct`
|
||||
|
||||
### Permissions
|
||||
Command and aliases | Description | Usage
|
||||
@ -122,38 +123,38 @@ Command and aliases | Description | Usage
|
||||
`;rolepermscopy`, `;rpc` | Copies BOT PERMISSIONS (not discord permissions) from one role to another. | `;rpc Some Role ~ Some other role`
|
||||
`;chnlpermscopy`, `;cpc` | Copies BOT PERMISSIONS (not discord permissions) from one channel to another. | `;cpc Some Channel ~ Some other channel`
|
||||
`;usrpermscopy`, `;upc` | Copies BOT PERMISSIONS (not discord permissions) from one role to another. | `;upc @SomeUser ~ @SomeOtherUser`
|
||||
`;verbose`, `;v` | Sets whether to show when a command/module is blocked. | ;verbose true
|
||||
`;verbose`, `;v` | Sets whether to show when a command/module is blocked. | `;verbose true`
|
||||
`;srvrperms`, `;sp` | Shows banned permissions for this server.
|
||||
`;roleperms`, `;rp` | Shows banned permissions for a certain role. No argument means for everyone. | ;rp AwesomeRole
|
||||
`;chnlperms`, `;cp` | Shows banned permissions for a certain channel. No argument means for this channel. | ;cp #dev
|
||||
`;userperms`, `;up` | Shows banned permissions for a certain user. No argument means for yourself. | ;up Kwoth
|
||||
`;srvrmdl`, `;sm` | Sets a module's permission at the server level. | ;sm "module name" enable
|
||||
`;srvrcmd`, `;sc` | Sets a command's permission at the server level. | ;sc "command name" disable
|
||||
`;rolemdl`, `;rm` | Sets a module's permission at the role level. | ;rm "module name" enable MyRole
|
||||
`;rolecmd`, `;rc` | Sets a command's permission at the role level. | ;rc "command name" disable MyRole
|
||||
`;chnlmdl`, `;cm` | Sets a module's permission at the channel level. | ;cm "module name" enable SomeChannel
|
||||
`;chnlcmd`, `;cc` | Sets a command's permission at the channel level. | ;cc "command name" enable SomeChannel
|
||||
`;usrmdl`, `;um` | Sets a module's permission at the user level. | ;um "module name" enable SomeUsername
|
||||
`;usrcmd`, `;uc` | Sets a command's permission at the user level. | ;uc "command name" enable SomeUsername
|
||||
`;allsrvrmdls`, `;asm` | Sets permissions for all modules at the server level. | ;asm [enable/disable]
|
||||
`;allsrvrcmds`, `;asc` | Sets permissions for all commands from a certain module at the server level. | ;asc "module name" [enable/disable]
|
||||
`;allchnlmdls`, `;acm` | Sets permissions for all modules at the channel level. | ;acm [enable/disable] SomeChannel
|
||||
`;allchnlcmds`, `;acc` | Sets permissions for all commands from a certain module at the channel level. | ;acc "module name" [enable/disable] SomeChannel
|
||||
`;allrolemdls`, `;arm` | Sets permissions for all modules at the role level. | ;arm [enable/disable] MyRole
|
||||
`;allrolecmds`, `;arc` | Sets permissions for all commands from a certain module at the role level. | ;arc "module name" [enable/disable] MyRole
|
||||
`;ubl` | Blacklists a mentioned user. | ;ubl [user_mention]
|
||||
`;uubl` | Unblacklists a mentioned user. | ;uubl [user_mention]
|
||||
`;cbl` | Blacklists a mentioned channel (#general for example). | ;cbl #some_channel
|
||||
`;cubl` | Unblacklists a mentioned channel (#general for example). | ;cubl #some_channel
|
||||
`;sbl` | Blacklists a server by a name or id (#general for example). **BOT OWNER ONLY** | ;sbl [servername/serverid]
|
||||
`;roleperms`, `;rp` | Shows banned permissions for a certain role. No argument means for everyone. | `;rp AwesomeRole`
|
||||
`;chnlperms`, `;cp` | Shows banned permissions for a certain channel. No argument means for this channel. | `;cp #dev`
|
||||
`;userperms`, `;up` | Shows banned permissions for a certain user. No argument means for yourself. | `;up Kwoth`
|
||||
`;srvrmdl`, `;sm` | Sets a module's permission at the server level. | `;sm "module name" enable`
|
||||
`;srvrcmd`, `;sc` | Sets a command's permission at the server level. | `;sc "command name" disable`
|
||||
`;rolemdl`, `;rm` | Sets a module's permission at the role level. | `;rm "module name" enable MyRole`
|
||||
`;rolecmd`, `;rc` | Sets a command's permission at the role level. | `;rc "command name" disable MyRole`
|
||||
`;chnlmdl`, `;cm` | Sets a module's permission at the channel level. | `;cm "module name" enable SomeChannel`
|
||||
`;chnlcmd`, `;cc` | Sets a command's permission at the channel level. | `;cc "command name" enable SomeChannel`
|
||||
`;usrmdl`, `;um` | Sets a module's permission at the user level. | `;um "module name" enable SomeUsername`
|
||||
`;usrcmd`, `;uc` | Sets a command's permission at the user level. | `;uc "command name" enable SomeUsername`
|
||||
`;allsrvrmdls`, `;asm` | Sets permissions for all modules at the server level. | `;asm [enable/disable]`
|
||||
`;allsrvrcmds`, `;asc` | Sets permissions for all commands from a certain module at the server level. | `;asc "module name" [enable/disable]`
|
||||
`;allchnlmdls`, `;acm` | Sets permissions for all modules at the channel level. | `;acm [enable/disable] SomeChannel`
|
||||
`;allchnlcmds`, `;acc` | Sets permissions for all commands from a certain module at the channel level. | `;acc "module name" [enable/disable] SomeChannel`
|
||||
`;allrolemdls`, `;arm` | Sets permissions for all modules at the role level. | `;arm [enable/disable] MyRole`
|
||||
`;allrolecmds`, `;arc` | Sets permissions for all commands from a certain module at the role level. | `;arc "module name" [enable/disable] MyRole`
|
||||
`;ubl` | Blacklists a mentioned user. | `;ubl [user_mention]`
|
||||
`;uubl` | Unblacklists a mentioned user. | `;uubl [user_mention]`
|
||||
`;cbl` | Blacklists a mentioned channel (#general for example). | `;cbl #some_channel`
|
||||
`;cubl` | Unblacklists a mentioned channel (#general for example). | `;cubl #some_channel`
|
||||
`;sbl` | Blacklists a server by a name or id (#general for example). **BOT OWNER ONLY** | `;sbl [servername/serverid]`
|
||||
`;cmdcooldown`, `;cmdcd` | Sets a cooldown per user for a command. Set 0 to clear. | `;cmdcd "some cmd" 5`
|
||||
`;allcmdcooldowns`, `;acmdcds` | Shows a list of all commands and their respective cooldowns.
|
||||
|
||||
### Conversations
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`..` | Adds a new quote with the specified name (single word) and message (no limit). | .. abc My message
|
||||
`...` | Shows a random quote with a specified name. | .. abc
|
||||
`..` | Adds a new quote with the specified name (single word) and message (no limit). | `.. abc My message`
|
||||
`...` | Shows a random quote with a specified name. | `... abc`
|
||||
`..qdel`, `..quotedelete` | Deletes all quotes with the specified keyword. You have to either be bot owner or the creator of the quote to delete it. | `..qdel abc`
|
||||
`@BotName rip` | Shows a grave image of someone with a start year | @NadekoBot rip @Someone 2000
|
||||
`@BotName die` | Works only for the owner. Shuts the bot down.
|
||||
@ -173,11 +174,13 @@ Command and aliases | Description | Usage
|
||||
`$roll` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice. If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5
|
||||
`$rolluo` | Rolls 0-100. If you supply a number [x] it rolls up to 30 normal dice (unordered). If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | $roll or $roll 7 or $roll 3d5
|
||||
`$nroll` | Rolls in a given range. | `$nroll 5` (rolls 0-5) or `$nroll 5-15`
|
||||
`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role.
|
||||
`$race` | Starts a new animal race.
|
||||
`$joinrace`, `$jr` | Joins a new race. You can specify an amount of flowers for betting (optional). You will get YourBet*(participants-1) back if you win. | `$jr` or `$jr 5`
|
||||
`$raffle` | Prints a name and ID of a random user from the online list from the (optional) role. | `$raffle` or `$raffle RoleName
|
||||
`$$$` | Check how much NadekoFlowers a person has. (Defaults to yourself) | `$$$` or `$$$ @Someone`
|
||||
`$give` | Give someone a certain amount of NadekoFlowers
|
||||
`$award` | Gives someone a certain amount of flowers. **Bot Owner Only!** | `$award 100 @person`
|
||||
`$take` | Takes a certain amount of flowers from someone. **Bot Owner Only!**
|
||||
`$take` | Takes a certain amount of flowers from someone. **Bot Owner Only!** | `$take 1 "@someguy"`
|
||||
`$betroll`, `$br` | Bets a certain amount of NadekoFlowers and rolls a dice. Rolling over 66 yields x2 flowers, over 90 - x3 and 100 x10. | $br 5
|
||||
`$leaderboard`, `$lb` |
|
||||
|
||||
@ -196,9 +199,9 @@ Command and aliases | Description | Usage
|
||||
`>plant` | Spend a flower to plant it in this channel. (If bot is restarted or crashes, flower will be lost)
|
||||
`>gencurrency`, `>gc` | Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a NadekoFlower. Optional parameter cooldown time in minutes, 5 minutes by default. Requires Manage Messages permission. | `>gc` or `>gc 60`
|
||||
`>leet` | Converts a text to leetspeak with 6 (1-6) severity levels | >leet 3 Hello
|
||||
`>choose` | Chooses a thing from a list of things | >choose Get up;Sleep;Sleep more
|
||||
`>8ball` | Ask the 8ball a yes/no question.
|
||||
`>rps` | Play a game of rocket paperclip scissors with Nadeko. | >rps scissors
|
||||
`>choose` | Chooses a thing from a list of things | `>choose Get up;Sleep;Sleep more`
|
||||
`>8ball` | Ask the 8ball a yes/no question. | `>8ball should i do something`
|
||||
`>rps` | Play a game of rocket paperclip scissors with Nadeko. | `>rps scissors`
|
||||
`>linux` | Prints a customizable Linux interjection | `>linux Spyware Windows`
|
||||
|
||||
### Music
|
||||
@ -234,7 +237,7 @@ Command and aliases | Description | Usage
|
||||
`!!load` | Loads a playlist under a certain name. | `!!load classical-1`
|
||||
`!!playlists`, `!!pls` | Lists all playlists. Paginated. 20 per page. Default page is 0. | `!!pls 1`
|
||||
`!!deleteplaylist`, `!!delpls` | Deletes a saved playlist. Only if you made it or if you are the bot owner. | `!!delpls animu-5`
|
||||
`!!goto` | Goes to a specific time in seconds in a song.
|
||||
`!!goto` | Goes to a specific time in seconds in a song. | !!goto 30
|
||||
`!!getlink`, `!!gl` | Shows a link to the currently playing song.
|
||||
`!!autoplay`, `!!ap` | Toggles autoplay - When the song is finished, automatically queue a related youtube song. (Works only for youtube songs and when queue is empty)
|
||||
|
||||
@ -262,41 +265,42 @@ Command and aliases | Description | Usage
|
||||
`~pokemonability`, `~pokeab` | Searches for a pokemon ability.
|
||||
`~memelist` | Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/
|
||||
`~memegen` | Generates a meme from memelist with top and bottom text. | `~memegen biw "gets iced coffee" "in the winter"`
|
||||
`~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | ~we Moscow RF
|
||||
`~yt` | Searches youtubes and shows the first result
|
||||
`~we` | Shows weather data for a specified city and a country. BOTH ARE REQUIRED. Use country abbrevations. | `~we Moscow RF`
|
||||
`~yt` | Searches youtubes and shows the first result | `~yt query`
|
||||
`~ani`, `~anime`, `~aq` | Queries anilist for an anime and shows the first result.
|
||||
`~imdb` | Queries imdb for movies or series, show first result.
|
||||
`~mang`, `~manga`, `~mq` | Queries anilist for a manga and shows the first result.
|
||||
`~imdb` | Queries imdb for movies or series, show first result. | `~imdb query`
|
||||
`~mang`, `~manga`, `~mq` | Queries anilist for a manga and shows the first result. | `~mq query`
|
||||
`~randomcat`, `~meow` | Shows a random cat image.
|
||||
`~i` | Pulls the first image found using a search parameter. Use ~ir for different results. | ~i cute kitten
|
||||
`~ir` | Pulls a random image using a search parameter. | ~ir cute kitten
|
||||
`~lmgtfy` | Google something for an idiot.
|
||||
`~google`, `~g` | Get a google search link for some terms.
|
||||
`~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | ~hs Ysera
|
||||
`~ud` | Searches Urban Dictionary for a word. | ~ud Pineapple
|
||||
`~#` | Searches Tagdef.com for a hashtag. | ~# ff
|
||||
`~randomdog`, `~woof` | Shows a random dog image.
|
||||
`~i` | Pulls the first image found using a search parameter. Use ~ir for different results. | `~i cute kitten`
|
||||
`~ir` | Pulls a random image using a search parameter. | `~ir cute kitten`
|
||||
`~lmgtfy` | Google something for an idiot. | `~lmgtfy query`
|
||||
`~google`, `~g` | Get a google search link for some terms. | `~google query`
|
||||
`~hs` | Searches for a Hearthstone card and shows its image. Takes a while to complete. | `~hs Ysera`
|
||||
`~ud` | Searches Urban Dictionary for a word. | `~ud Pineapple`
|
||||
`~#` | Searches Tagdef.com for a hashtag. | `~# ff`
|
||||
`~quote` | Shows a random quote.
|
||||
`~catfact` | Shows a random catfact from <http://catfacts-api.appspot.com/api/facts>
|
||||
`~yomama`, `~ym` | Shows a random joke from <http://api.yomomma.info/>
|
||||
`~randjoke`, `~rj` | Shows a random joke from <http://tambal.azurewebsites.net/joke/random>
|
||||
`~chucknorris`, `~cn` | Shows a random chucknorris joke from <http://tambal.azurewebsites.net/joke/random>
|
||||
`~magicitem`, `~mi` | Shows a random magicitem from <https://1d4chan.org/wiki/List_of_/tg/%27s_magic_items>
|
||||
`~revav` | Returns a google reverse image search for someone's avatar.
|
||||
`~revimg` | Returns a google reverse image search for an image from a link.
|
||||
`~safebooru` | Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~safebooru yuri+kissing
|
||||
`~wiki` | Gives you back a wikipedia link
|
||||
`~revav` | Returns a google reverse image search for someone's avatar. | `~revav "@SomeGuy"
|
||||
`~revimg` | Returns a google reverse image search for an image from a link. | `~revav Image link`
|
||||
`~safebooru` | Shows a random image from safebooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~safebooru yuri+kissing`
|
||||
`~wiki` | Gives you back a wikipedia link | `~wiki query`
|
||||
`~clr` | Shows you what color corresponds to that hex. | `~clr 00ff00`
|
||||
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message.
|
||||
`~av`, `~avatar` | Shows a mentioned person's avatar. | ~av @X
|
||||
`~videocall` | Creates a private <http://www.appear.in> video call link for you and other mentioned people. The link is sent to mentioned people via a private message. | `~videocall "@SomeGuy"`
|
||||
`~av`, `~avatar` | Shows a mentioned person's avatar. | `~av @X`
|
||||
|
||||
### NSFW
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`~hentai` | Shows a random NSFW hentai image from gelbooru and danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~hentai yuri+kissing
|
||||
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~danbooru yuri+kissing
|
||||
`~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~gelbooru yuri+kissing
|
||||
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | ~rule34 yuri+kissing
|
||||
`~e621` | Shows a random hentai image from e621.net with a given tag. Tag is optional but preffered. Use spaces for multiple tags. | ~e621 yuri kissing
|
||||
`~hentai` | Shows a random NSFW hentai image from gelbooru and danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~hentai yuri+kissing`
|
||||
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~danbooru yuri+kissing`
|
||||
`~gelbooru` | Shows a random hentai image from gelbooru with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~gelbooru yuri+kissing`
|
||||
`~rule34` | Shows a random image from rule34.xx with a given tag. Tag is optional but preffered. (multiple tags are appended with +) | `~rule34 yuri+kissing`
|
||||
`~e621` | Shows a random hentai image from e621.net with a given tag. Tag is optional but preffered. Use spaces for multiple tags. | `~e621 yuri kissing`
|
||||
`~cp` | We all know where this will lead you to.
|
||||
`~boobs` | Real adult content.
|
||||
`~butts`, `~ass`, `~butt` | Real adult content.
|
||||
@ -305,13 +309,13 @@ Command and aliases | Description | Usage
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`,createwar`, `,cw` | Creates a new war by specifying a size (>10 and multiple of 5) and enemy clan name. | ,cw 15 The Enemy Clan
|
||||
`,startwar`, `,sw` | Starts a war with a given number.
|
||||
`,startwar`, `,sw` | Starts a war with a given number. | `,sw 1`
|
||||
`,listwar`, `,lw` | Shows the active war claims by a number. Shows all wars in a short way if no number is specified. | ,lw [war_number] or ,lw
|
||||
`,claim`, `,call`, `,c` | Claims a certain base from a certain war. You can supply a name in the third optional argument to claim in someone else's place. | ,call [war_number] [base_number] [optional_other_name]
|
||||
`,claimfinish`, `,cf`, `,cf3`, `,claimfinish3` | Finish your claim with 3 stars if you destroyed a base. Optional second argument finishes for someone else. | ,cf [war_number] [optional_other_name]
|
||||
`,claimfinish2`, `,cf2` | Finish your claim with 2 stars if you destroyed a base. Optional second argument finishes for someone else. | ,cf [war_number] [optional_other_name]
|
||||
`,claimfinish1`, `,cf1` | Finish your claim with 1 stars if you destroyed a base. Optional second argument finishes for someone else. | ,cf [war_number] [optional_other_name]
|
||||
`,unclaim`, `,uncall`, `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whos place to unclaim | ,uc [war_number] [optional_other_name]
|
||||
`,unclaim`, `,uncall`, `,uc` | Removes your claim from a certain war. Optional second argument denotes a person in whose place to unclaim | ,uc [war_number] [optional_other_name]
|
||||
`,endwar`, `,ew` | Ends the war with a given index. | ,ew [war_number]
|
||||
|
||||
### Pokegame
|
||||
@ -326,7 +330,7 @@ Command and aliases | Description | Usage
|
||||
### Translator
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`~translate`, `~trans` | Translates from>to text. From the given language to the destiation language. | ~trans en>fr Hello
|
||||
`~translate`, `~trans` | Translates from>to text. From the given language to the destiation language. | `~trans en>fr Hello`
|
||||
`~translangs` | List the valid languages for translation.
|
||||
|
||||
### Customreactions
|
||||
@ -352,7 +356,7 @@ Command and aliases | Description | Usage
|
||||
### Trello
|
||||
Command and aliases | Description | Usage
|
||||
----------------|--------------|-------
|
||||
`trello bind` | Bind a trello bot to a single channel. You will receive notifications from your board when something is added or edited. | bind [board_id]
|
||||
`trello bind` | Bind a trello bot to a single channel. You will receive notifications from your board when something is added or edited. | `trello bind [board_id]`
|
||||
`trello unbind` | Unbinds a bot from the channel and board.
|
||||
`trello lists`, `trello list` | Lists all lists yo ;)
|
||||
`trello cards` | Lists all cards from the supplied list. You can supply either a name or an index.
|
||||
`trello cards` | Lists all cards from the supplied list. You can supply either a name or an index. | `trello cards index`
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3e519b5e0b33175e5a5ca247322b7082de484e15
|
||||
Subproject commit 3a33731135f1b7dd2efdb51b16158c84bb22da66
|
1
ffmpeg-installer
Submodule
1
ffmpeg-installer
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit d593fe3a86be7da9e4177865446f2f5ca58b6be4
|
Loading…
Reference in New Issue
Block a user