diff --git a/LinuxSetup.md b/LinuxSetup.md index 48704088..39acd7be 100644 --- a/LinuxSetup.md +++ b/LinuxSetup.md @@ -48,7 +48,7 @@ Note if the command is not being initiated, hit **Enter** **2.6)** *ONLY CentOS 7, Fedora 19 (and later)* -`yum install yum-util` +`yum install yum-utils` `rpm --import "http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF"` diff --git a/NadekoBot.sln b/NadekoBot.sln index eb9860d0..d41210c6 100644 --- a/NadekoBot.sln +++ b/NadekoBot.sln @@ -49,68 +49,68 @@ Global {27A886F5-CDDA-4F4A-81EE-6DAFCCE9DE46}.Release|x64.Build.0 = Release|x64 {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|x64.ActiveCfg = Debug|x64 - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|x64.Build.0 = Debug|x64 + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|x64.ActiveCfg = Debug|Any CPU + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Debug|x64.Build.0 = Debug|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|Any CPU.Build.0 = Debug|Any CPU - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|x64.ActiveCfg = Debug|x64 - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|x64.Build.0 = Debug|x64 + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|x64.ActiveCfg = Debug|Any CPU + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.FullDebug|x64.Build.0 = Debug|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|x64.ActiveCfg = Release|x64 - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|x64.Build.0 = Release|x64 + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|x64.ActiveCfg = Release|Any CPU + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.NadekoRelease|x64.Build.0 = Release|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.ActiveCfg = Release|Any CPU {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|Any CPU.Build.0 = Release|Any CPU - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|x64.ActiveCfg = Release|x64 - {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|x64.Build.0 = Release|x64 + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|x64.ActiveCfg = Release|Any CPU + {7BFEF748-B934-4621-9B11-6302E3A9F6B3}.Release|x64.Build.0 = Release|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|x64.ActiveCfg = Debug|x64 - {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|x64.Build.0 = Debug|x64 + {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|x64.ActiveCfg = Debug|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Debug|x64.Build.0 = Debug|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|Any CPU.Build.0 = Debug|Any CPU - {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|x64.ActiveCfg = Debug|x64 - {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|x64.Build.0 = Debug|x64 + {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|x64.ActiveCfg = Debug|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.FullDebug|x64.Build.0 = Debug|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU - {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|x64.ActiveCfg = Release|x64 - {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|x64.Build.0 = Release|x64 + {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|x64.ActiveCfg = Release|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.NadekoRelease|x64.Build.0 = Release|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|Any CPU.Build.0 = Release|Any CPU - {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|x64.ActiveCfg = Release|x64 - {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|x64.Build.0 = Release|x64 + {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|x64.ActiveCfg = Release|Any CPU + {8D71A857-879A-4A10-859E-5FF824ED6688}.Release|x64.Build.0 = Release|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3091164F-66AE-4543-A63D-167C1116241D}.Debug|x64.ActiveCfg = Debug|x64 - {3091164F-66AE-4543-A63D-167C1116241D}.Debug|x64.Build.0 = Debug|x64 + {3091164F-66AE-4543-A63D-167C1116241D}.Debug|x64.ActiveCfg = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Debug|x64.Build.0 = Debug|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|Any CPU.Build.0 = Debug|Any CPU - {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|x64.ActiveCfg = Debug|x64 - {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|x64.Build.0 = Debug|x64 + {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|x64.ActiveCfg = Debug|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.FullDebug|x64.Build.0 = Debug|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU - {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|x64.ActiveCfg = Release|x64 - {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|x64.Build.0 = Release|x64 + {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|x64.ActiveCfg = Release|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.NadekoRelease|x64.Build.0 = Release|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.ActiveCfg = Release|Any CPU {3091164F-66AE-4543-A63D-167C1116241D}.Release|Any CPU.Build.0 = Release|Any CPU - {3091164F-66AE-4543-A63D-167C1116241D}.Release|x64.ActiveCfg = Release|x64 - {3091164F-66AE-4543-A63D-167C1116241D}.Release|x64.Build.0 = Release|x64 + {3091164F-66AE-4543-A63D-167C1116241D}.Release|x64.ActiveCfg = Release|Any CPU + {3091164F-66AE-4543-A63D-167C1116241D}.Release|x64.Build.0 = Release|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|x64.ActiveCfg = Debug|x64 - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|x64.Build.0 = Debug|x64 + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|x64.ActiveCfg = Debug|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Debug|x64.Build.0 = Debug|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.ActiveCfg = Debug|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|Any CPU.Build.0 = Debug|Any CPU - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|x64.ActiveCfg = Debug|x64 - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|x64.Build.0 = Debug|x64 + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|x64.ActiveCfg = Debug|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.FullDebug|x64.Build.0 = Debug|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.ActiveCfg = Release|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|Any CPU.Build.0 = Release|Any CPU - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|x64.ActiveCfg = Release|x64 - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|x64.Build.0 = Release|x64 + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|x64.ActiveCfg = Release|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.NadekoRelease|x64.Build.0 = Release|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.ActiveCfg = Release|Any CPU {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|Any CPU.Build.0 = Release|Any CPU - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|x64.ActiveCfg = Release|x64 - {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|x64.Build.0 = Release|x64 + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|x64.ActiveCfg = Release|Any CPU + {1B5603B4-6F8F-4289-B945-7BAAE523D740}.Release|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NadekoBot/Classes/NadekoStats.cs b/NadekoBot/Classes/NadekoStats.cs index 8161348a..57d730d4 100644 --- a/NadekoBot/Classes/NadekoStats.cs +++ b/NadekoBot/Classes/NadekoStats.cs @@ -7,7 +7,9 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +#if NADEKO_RELEASE using System.IO; +#endif using System.Linq; using System.Net.Http; using System.Reflection; @@ -227,6 +229,7 @@ namespace NadekoBot DateTime dt; if (!commandTracker.TryGetValue(e.Message.Id, out dt)) return; +#if NADEKO_RELEASE try { if (e is CommandErrorEventArgs) @@ -248,18 +251,19 @@ namespace NadekoBot } } catch { } +#endif } private async void StatsCollector_RanCommand(object sender, CommandEventArgs e) { 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-----"); + commandsRan++; #if !NADEKO_RELEASE await Task.Run(() => { try { - commandsRan++; Classes.DbHandler.Instance.Connection.Insert(new DataModels.Command { ServerId = (long)(e.Server?.Id ?? 0), diff --git a/NadekoBot/Classes/SearchHelper.cs b/NadekoBot/Classes/SearchHelper.cs index a0a59e9b..e5bbcc2e 100644 --- a/NadekoBot/Classes/SearchHelper.cs +++ b/NadekoBot/Classes/SearchHelper.cs @@ -61,10 +61,31 @@ namespace NadekoBot.Classes IEnumerable> headers = null, RequestHttpMethod method = RequestHttpMethod.Get) { - - using (var streamReader = new StreamReader(await GetResponseStreamAsync(url, headers, method).ConfigureAwait(false))) + if (string.IsNullOrWhiteSpace(url)) + throw new ArgumentNullException(nameof(url)); + var cl = new HttpClient(); + cl.DefaultRequestHeaders.Clear(); + switch (method) { - return await streamReader.ReadToEndAsync().ConfigureAwait(false); + case RequestHttpMethod.Get: + if (headers != null) + { + foreach (var header in headers) + { + cl.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value); + } + } + return await cl.GetStringAsync(url).ConfigureAwait(false); + case RequestHttpMethod.Post: + FormUrlEncodedContent formContent = null; + if (headers != null) + { + formContent = new FormUrlEncodedContent(headers); + } + var message = await cl.PostAsync(url, formContent).ConfigureAwait(false); + return await message.Content.ReadAsStringAsync().ConfigureAwait(false); + default: + throw new NotImplementedException("That type of request is unsupported."); } } diff --git a/NadekoBot/Classes/ServerSpecificConfig.cs b/NadekoBot/Classes/ServerSpecificConfig.cs index 9142e574..1642f75e 100644 --- a/NadekoBot/Classes/ServerSpecificConfig.cs +++ b/NadekoBot/Classes/ServerSpecificConfig.cs @@ -64,7 +64,7 @@ namespace NadekoBot.Classes await saveLock.WaitAsync(); try { - File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented)); + await Task.Run(() => File.WriteAllText(filePath, JsonConvert.SerializeObject(configs, Formatting.Indented))); } finally { @@ -208,11 +208,9 @@ namespace NadekoBot.Classes [JsonIgnore] private bool exclusiveSelfAssignedRoles = false; - public bool ExclusiveSelfAssignedRoles - { + public bool ExclusiveSelfAssignedRoles { get { return exclusiveSelfAssignedRoles; } - set - { + set { exclusiveSelfAssignedRoles = value; if (!SpecificConfigurations.Instantiated) return; OnPropertyChanged(); @@ -280,7 +278,7 @@ namespace NadekoBot.Classes } public bool Equals(StreamNotificationConfig other) => - this.Username.ToLower().Trim() == other.Username.ToLower().Trim() && + this.Username.ToUpperInvariant().Trim() == other.Username.ToUpperInvariant().Trim() && this.Type == other.Type && this.ServerId == other.ServerId; diff --git a/NadekoBot/Classes/lib/sqlite3.dll b/NadekoBot/Classes/lib/sqlite3.dll new file mode 100644 index 00000000..c68c1f14 Binary files /dev/null and b/NadekoBot/Classes/lib/sqlite3.dll differ diff --git a/NadekoBot/Modules/Administration/AdministrationModule.cs b/NadekoBot/Modules/Administration/AdministrationModule.cs index 23402c81..24effe3a 100644 --- a/NadekoBot/Modules/Administration/AdministrationModule.cs +++ b/NadekoBot/Modules/Administration/AdministrationModule.cs @@ -72,9 +72,9 @@ namespace NadekoBot.Modules.Administration conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand; await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false); if (conf.AutoDeleteMessagesOnCommand) - await e.Channel.SendMessage("❗`Now automatically deleting successfull command invokations.`"); + await e.Channel.SendMessage("❗`Now automatically deleting successful command invokations.`"); else - await e.Channel.SendMessage("❗`Stopped automatic deletion of successfull command invokations.`"); + await e.Channel.SendMessage("❗`Stopped automatic deletion of successful command invokations.`"); }); @@ -628,7 +628,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "prune") .Alias(Prefix + "clr") .Description( - "`.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` 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. **Needs Manage Messages Permissions**" + $"| `{Prefix}prune` or `{Prefix}prune 5` or `{Prefix}prune @Someone` or `{Prefix}prune @Someone X`") .Parameter("user_or_num", ParameterType.Optional) .Parameter("num", ParameterType.Optional) @@ -685,7 +685,7 @@ namespace NadekoBot.Modules.Administration cgb.CreateCommand(Prefix + "setname") .Alias(Prefix + "newnm") - .Description($"Give the bot a new name. **Bot Owner Only!** | {Prefix}newnm BotName") + .Description($"Give the bot a new name. **Bot Owner Only!** | `{Prefix}newnm BotName`") .Parameter("new_name", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -697,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!** | `{Prefix}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 http://i.imgur.com/xTG3a1I.jpg`") .Parameter("img", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -728,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!** | `{Prefix}send serverid|u:user_id Send this to a user!` or `{Prefix}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 sid|u:uid Hello user!` or `{Prefix}send sid|c:cid Message to channel!` (cid = channel id, sid = server id)") .Parameter("ids", ParameterType.Required) .Parameter("msg", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) diff --git a/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs b/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs index 38084dfa..373840cb 100644 --- a/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs +++ b/NadekoBot/Modules/Administration/Commands/AutoAssignRole.cs @@ -10,7 +10,7 @@ namespace NadekoBot.Modules.Administration.Commands { public AutoAssignRole(DiscordModule module) : base(module) { - NadekoBot.Client.UserJoined += (s, e) => + NadekoBot.OnReady += () => NadekoBot.Client.UserJoined += (s, e) => { try { diff --git a/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs b/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs index c08c34ef..88f6cd40 100644 --- a/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs +++ b/NadekoBot/Modules/Administration/Commands/CrossServerTextChannel.cs @@ -13,46 +13,49 @@ namespace NadekoBot.Modules.Administration.Commands { public CrossServerTextChannel(DiscordModule module) : base(module) { - NadekoBot.Client.MessageReceived += async (s, e) => + NadekoBot.OnReady += () => { - try + NadekoBot.Client.MessageReceived += async (s, e) => { - if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; - foreach (var subscriber in Subscribers) + try { - var set = subscriber.Value; - if (!set.Contains(e.Channel)) - continue; - foreach (var chan in set.Except(new[] { e.Channel })) + if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return; + foreach (var subscriber in Subscribers) { - await chan.SendMessage(GetText(e.Server, e.Channel, e.User, e.Message)).ConfigureAwait(false); + var set = subscriber.Value; + if (!set.Contains(e.Channel)) + continue; + foreach (var chan in set.Except(new[] { e.Channel })) + { + await chan.SendMessage(GetText(e.Server, e.Channel, e.User, e.Message)).ConfigureAwait(false); + } } } - } - catch { } - }; - NadekoBot.Client.MessageUpdated += async (s, e) => - { - try + catch { } + }; + NadekoBot.Client.MessageUpdated += async (s, e) => { - if (e.After?.User?.Id == null || e.After.User.Id == NadekoBot.Client.CurrentUser.Id) return; - foreach (var subscriber in Subscribers) + try { - var set = subscriber.Value; - if (!set.Contains(e.Channel)) - continue; - foreach (var chan in set.Except(new[] { e.Channel })) + if (e.After?.User?.Id == null || e.After.User.Id == NadekoBot.Client.CurrentUser.Id) return; + foreach (var subscriber in Subscribers) { - var msg = chan.Messages - .FirstOrDefault(m => - m.RawText == GetText(e.Server, e.Channel, e.User, e.Before)); - if (msg != default(Message)) - await msg.Edit(GetText(e.Server, e.Channel, e.User, e.After)).ConfigureAwait(false); + var set = subscriber.Value; + if (!set.Contains(e.Channel)) + continue; + foreach (var chan in set.Except(new[] { e.Channel })) + { + var msg = chan.Messages + .FirstOrDefault(m => + m.RawText == GetText(e.Server, e.Channel, e.User, e.Before)); + if (msg != default(Message)) + await msg.Edit(GetText(e.Server, e.Channel, e.User, e.After)).ConfigureAwait(false); + } } - } - } - catch { } + } + catch { } + }; }; } diff --git a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs index 2725e196..575e2493 100644 --- a/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs +++ b/NadekoBot/Modules/Administration/Commands/CustomReactionsCommands.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace NadekoBot.Modules.Administration.Commands { @@ -23,7 +22,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Prefix + "addcustreact") .Alias(Prefix + "acr") - .Description($"Add a custom reaction. Guide here: **Bot Owner Only!** | `{Prefix}acr \"hello\" I love saying hello to %user%`") + .Description($"Add a custom reaction. Guide here: **Bot Owner Only!** | `{Prefix}acr \"hello\" Hi there %user%`") .AddCheck(SimpleCheckers.OwnerOnly()) .Parameter("name", ParameterType.Required) .Parameter("message", ParameterType.Unparsed) diff --git a/NadekoBot/Modules/Administration/Commands/LogCommand.cs b/NadekoBot/Modules/Administration/Commands/LogCommand.cs index b5f19eb1..87a0723e 100644 --- a/NadekoBot/Modules/Administration/Commands/LogCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/LogCommand.cs @@ -19,67 +19,73 @@ namespace NadekoBot.Modules.Administration.Commands public LogCommand(DiscordModule module) : base(module) { - NadekoBot.Client.MessageReceived += MsgRecivd; - NadekoBot.Client.MessageDeleted += MsgDltd; - NadekoBot.Client.MessageUpdated += MsgUpdtd; - NadekoBot.Client.UserUpdated += UsrUpdtd; - NadekoBot.Client.UserBanned += UsrBanned; - NadekoBot.Client.UserLeft += UsrLeft; - NadekoBot.Client.UserJoined += UsrJoined; - NadekoBot.Client.UserUnbanned += UsrUnbanned; - NadekoBot.Client.ChannelCreated += ChannelCreated; - NadekoBot.Client.ChannelDestroyed += ChannelDestroyed; - NadekoBot.Client.ChannelUpdated += ChannelUpdated; - - - NadekoBot.Client.MessageReceived += async (s, e) => + NadekoBot.OnReady += () => { - if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id) - return; - if (!SpecificConfigurations.Default.Of(e.Server.Id).SendPrivateMessageOnMention) return; - try + NadekoBot.Client.MessageReceived += MsgRecivd; + NadekoBot.Client.MessageDeleted += MsgDltd; + NadekoBot.Client.MessageUpdated += MsgUpdtd; + NadekoBot.Client.UserUpdated += UsrUpdtd; + NadekoBot.Client.UserBanned += UsrBanned; + NadekoBot.Client.UserLeft += UsrLeft; + NadekoBot.Client.UserJoined += UsrJoined; + NadekoBot.Client.UserUnbanned += UsrUnbanned; + NadekoBot.Client.ChannelCreated += ChannelCreated; + NadekoBot.Client.ChannelDestroyed += ChannelDestroyed; + NadekoBot.Client.ChannelUpdated += ChannelUpdated; + + + NadekoBot.Client.MessageReceived += async (s, e) => { - var usr = e.Message.MentionedUsers.FirstOrDefault(u => u != e.User); - if (usr?.Status != UserStatus.Offline) + if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id) return; - await e.Channel.SendMessage($"User `{usr.Name}` is offline. PM sent.").ConfigureAwait(false); - await usr.SendMessage( - $"User `{e.User.Name}` mentioned you on " + - $"`{e.Server.Name}` server while you were offline.\n" + - $"`Message:` {e.Message.Text}").ConfigureAwait(false); - } - catch { } + if (!SpecificConfigurations.Default.Of(e.Server.Id).SendPrivateMessageOnMention) return; + try + { + var usr = e.Message.MentionedUsers.FirstOrDefault(u => u != e.User); + if (usr?.Status != UserStatus.Offline) + return; + await e.Channel.SendMessage($"User `{usr.Name}` is offline. PM sent.").ConfigureAwait(false); + await usr.SendMessage( + $"User `{e.User.Name}` mentioned you on " + + $"`{e.Server.Name}` server while you were offline.\n" + + $"`Message:` {e.Message.Text}").ConfigureAwait(false); + } + catch { } + }; }; // start the userpresence queue - NadekoBot.OnReady += () => Task.Run(async () => - { - while (true) - { - var toSend = new Dictionary(); - //take everything from the queue and merge the messages which are going to the same channel - KeyValuePair item; - while (voicePresenceUpdates.TryTake(out item)) - { - if (toSend.ContainsKey(item.Key)) - { - toSend[item.Key] = toSend[item.Key] + Environment.NewLine + item.Value; - } - else - { - toSend.Add(item.Key, item.Value); - } - } - //send merged messages to each channel - foreach (var k in toSend) - { - try { await k.Key.SendMessage(Environment.NewLine + k.Value).ConfigureAwait(false); } catch { } - } + NadekoBot.OnReady += () => + { + Task.Run(async () => + { + while (true) + { + var toSend = new Dictionary(); + //take everything from the queue and merge the messages which are going to the same channel + KeyValuePair item; + while (voicePresenceUpdates.TryTake(out item)) + { + if (toSend.ContainsKey(item.Key)) + { + toSend[item.Key] = toSend[item.Key] + Environment.NewLine + item.Value; + } + else + { + toSend.Add(item.Key, item.Value); + } + } + //send merged messages to each channel + foreach (var k in toSend) + { + try { await k.Key.SendMessage(Environment.NewLine + k.Value).ConfigureAwait(false); } catch { } + } - await Task.Delay(5000); - } - }); + await Task.Delay(5000); + } + }); + }; } private async void ChannelUpdated(object sender, ChannelUpdatedEventArgs e) diff --git a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs index c1caa0bc..3eff2ff2 100644 --- a/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs +++ b/NadekoBot/Modules/Administration/Commands/PlayingRotate.cs @@ -9,7 +9,6 @@ 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 @@ -38,7 +37,7 @@ namespace NadekoBot.Modules.Administration.Commands {"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()} }; - private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1,1); + private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1, 1); public PlayingRotate(DiscordModule module) : base(module) { @@ -70,8 +69,7 @@ namespace NadekoBot.Modules.Administration.Commands } catch { } }; - - timer.Enabled = NadekoBot.Config.IsRotatingStatus; + NadekoBot.OnReady += () => timer.Enabled = NadekoBot.Config.IsRotatingStatus; } public Func DoFunc() => async e => @@ -86,7 +84,8 @@ namespace NadekoBot.Modules.Administration.Commands NadekoBot.Config.IsRotatingStatus = timer.Enabled; await ConfigHandler.SaveConfig().ConfigureAwait(false); } - finally { + finally + { playingPlaceholderLock.Release(); } await e.Channel.SendMessage($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false); @@ -103,7 +102,7 @@ namespace NadekoBot.Modules.Administration.Commands cgb.CreateCommand(Module.Prefix + "addplaying") .Alias(Module.Prefix + "adpl") .Description("Adds a specified string to the list of playing strings to rotate. " + - "Supported placeholders: " + string.Join(", ", PlayingPlaceholders.Keys)+ $" **Bot Owner Only!**| `{Prefix}adpl`") + "Supported placeholders: " + string.Join(", ", PlayingPlaceholders.Keys) + $" **Bot Owner Only!**| `{Prefix}adpl`") .Parameter("text", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -152,7 +151,8 @@ namespace NadekoBot.Modules.Administration.Commands int num; string str; await playingPlaceholderLock.WaitAsync().ConfigureAwait(false); - try { + try + { if (!int.TryParse(arg.Trim(), out num) || num <= 0 || num > NadekoBot.Config.RotatingStatuses.Count) return; str = NadekoBot.Config.RotatingStatuses[num - 1]; diff --git a/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs b/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs index d1f62bd9..38c30d07 100644 --- a/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/RatelimitCommand.cs @@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Administration.Commands public RatelimitCommand(DiscordModule module) : base(module) { - NadekoBot.Client.MessageReceived += async (s, e) => + NadekoBot.OnReady += () => NadekoBot.Client.MessageReceived += async (s, e) => { if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id) return; diff --git a/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs b/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs index b2cdf3b4..c4ebf22c 100644 --- a/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/ServerGreetCommand.cs @@ -31,8 +31,12 @@ namespace NadekoBot.Modules.Administration.Commands { AnnouncementsDictionary = new ConcurrentDictionary(); - NadekoBot.Client.UserJoined += UserJoined; - NadekoBot.Client.UserLeft += UserLeft; + //gotta subscribe after ready, to prevent trying to send these before all guilds are initialized + NadekoBot.OnReady += () => + { + NadekoBot.Client.UserJoined += UserJoined; + NadekoBot.Client.UserLeft += UserLeft; + }; var data = Classes.DbHandler.Instance.GetAllRows(); @@ -245,7 +249,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "greetmsg") - .Description($"Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. **Needs Manage Server Permissions.**| `{Prefix}greetmsg Welcome to the server, %user%.`") + .Description($"Sets a new join announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. **Needs Manage Server Permissions.**| `{Prefix}greetmsg Welcome, %user%.`") .Parameter("msg", ParameterType.Unparsed) .Do(async e => { @@ -278,7 +282,7 @@ namespace NadekoBot.Modules.Administration.Commands }); cgb.CreateCommand(Module.Prefix + "byemsg") - .Description($"Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. **Needs Manage Server Permissions.**| `{Prefix}byemsg %user% has left the server.`") + .Description($"Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. **Needs Manage Server Permissions.**| `{Prefix}byemsg %user% has left.`") .Parameter("msg", ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs b/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs index 4c6a948c..af220059 100644 --- a/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs +++ b/NadekoBot/Modules/Administration/Commands/VoicePlusTextCommand.cs @@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Administration.Commands public VoicePlusTextCommand(DiscordModule module) : base(module) { // changing servers may cause bugs - NadekoBot.Client.UserUpdated += async (sender, e) => + NadekoBot.OnReady += () => NadekoBot.Client.UserUpdated += async (sender, e) => { try { @@ -88,7 +88,7 @@ namespace NadekoBot.Modules.Administration.Commands { cgb.CreateCommand(Module.Prefix + "cleanv+t") .Alias(Module.Prefix + "cv+t") - .Description($"Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk.\nNeeds Manage Roles and Manage Channels Permissions.** | `{Prefix}cleanv+t`") + .Description($"Deletes all text channels ending in `-voice` for which voicechannels are not found. **Use at your own risk. Needs Manage Roles and Manage Channels Permissions.** | `{Prefix}cleanv+t`") .AddCheck(SimpleCheckers.CanManageRoles) .AddCheck(SimpleCheckers.ManageChannels()) .Do(async e => diff --git a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs index e14e48b4..07db4f98 100644 --- a/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs +++ b/NadekoBot/Modules/ClashOfClans/ClashOfClansModule.cs @@ -23,7 +23,9 @@ namespace NadekoBot.Modules.ClashOfClans public ClashOfClansModule() { - NadekoBot.OnReady += () => Task.Run(async () => + NadekoBot.OnReady += () => + { + Task.Run(async () => { if (File.Exists("data/clashofclans/wars.json")) { @@ -109,6 +111,7 @@ namespace NadekoBot.Modules.ClashOfClans await Task.Delay(5000); } }); + }; } private static void Save() diff --git a/NadekoBot/Modules/Gambling/DiceRollCommand.cs b/NadekoBot/Modules/Gambling/DiceRollCommand.cs index 55bb5ee1..326d85c4 100644 --- a/NadekoBot/Modules/Gambling/DiceRollCommand.cs +++ b/NadekoBot/Modules/Gambling/DiceRollCommand.cs @@ -27,7 +27,7 @@ namespace NadekoBot.Modules.Gambling cgb.CreateCommand(Module.Prefix + "rolluo") .Description("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. | `{Prefix}roll` or `{Prefix}roll` 7 or `{Prefix}roll 3d5`") + $" If you split 2 numbers with letter d (xdy) it will roll x dice from 1 to y. | `{Prefix}rolluo` or `{Prefix}rolluo 7` or `{Prefix}rolluo 3d5`") .Parameter("num", ParameterType.Optional) .Do(RollFunc(false)); @@ -161,4 +161,4 @@ namespace NadekoBot.Modules.Gambling } }; } -} \ No newline at end of file +} diff --git a/NadekoBot/Modules/Games/Commands/PollCommand.cs b/NadekoBot/Modules/Games/Commands/PollCommand.cs index 785d5c5f..b7082803 100644 --- a/NadekoBot/Modules/Games/Commands/PollCommand.cs +++ b/NadekoBot/Modules/Games/Commands/PollCommand.cs @@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Games.Commands internal override void Init(CommandGroupBuilder cgb) { cgb.CreateCommand(Module.Prefix + "poll") - .Description($"Creates a poll, only person who has manage server permission can do it. | `{Prefix}poll Question?;Answer1;Answ 2;A_3`") + .Description($"Creates a poll, only person who has manage server permission can do it. **Needs Manage Server Permissions**| `{Prefix}poll Question?;Answer1;Answ 2;A_3`") .Parameter("allargs", ParameterType.Unparsed) .Do(async e => { @@ -138,4 +138,4 @@ namespace NadekoBot.Modules.Games.Commands catch { } } } -} \ No newline at end of file +} diff --git a/NadekoBot/Modules/Help/Commands/HelpCommand.cs b/NadekoBot/Modules/Help/Commands/HelpCommand.cs index d0ba292b..9d41d7bd 100644 --- a/NadekoBot/Modules/Help/Commands/HelpCommand.cs +++ b/NadekoBot/Modules/Help/Commands/HelpCommand.cs @@ -1,10 +1,37 @@ -using Discord.Commands; +// +// _oo0oo_ +// o8888888o +// 88" . "88 +// (| -_- |) +// 0\ = /0 +// ___/`---'\___ +// .' \\| |// '. +// / \\||| : |||// \ +// / _||||| -:- |||||- \ +// | | \\\ - /// | | +// | \_| ''\---/'' |_/ | +// \ .-\__ '-' ___/-. / +// ___'. .' /--.--\ `. .'___ +// ."" '< `.___\_<|>_/___.' >' "". +// | | : `- \`.;`\ _ /`;.`/ - ` : | | +// \ \ `_. \_ __\ /__ _/ .-` / / +// =====`-.____`.___ \_____/___.-`___.-'===== +// `=---=' +// +// +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// 佛祖保佑 永无BUG +// +// +using Discord.Commands; using NadekoBot.Extensions; using NadekoBot.Modules; using NadekoBot.Modules.Permissions.Classes; using System; using System.IO; using System.Linq; +using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -47,32 +74,25 @@ namespace NadekoBot.Classes.Help.Commands public Action DoGitFunc() => e => { - string helpstr = -$@"######For more information and how to setup your own NadekoBot, go to: -######You can donate on patreon: -######or paypal: `nadekodiscordbot@gmail.com` + var helpstr = new StringBuilder(); -#NadekoBot List Of Commands "; - - - string lastCategory = ""; + var lastCategory = ""; foreach (var com in NadekoBot.Client.GetService().AllCommands) { if (com.Category != lastCategory) { - helpstr += "\n### " + com.Category + " \n"; - helpstr += "Command and aliases | Description | Usage\n"; - helpstr += "----------------|--------------|-------\n"; + helpstr.AppendLine("\n### " + com.Category + " "); + helpstr.AppendLine("Command and aliases | Description | Usage"); + helpstr.AppendLine("----------------|--------------|-------"); lastCategory = com.Category; } - helpstr += PrintCommandHelp(com); + helpstr.AppendLine($"`{com.Text}`{string.Concat(com.Aliases.Select(a => $", `{a}`"))} | {com.Description}"); } helpstr = helpstr.Replace(NadekoBot.BotMention, "@BotName"); - helpstr = helpstr.Replace(" |", " | ").Replace("**Usage**:", " | ").Replace("**Description:**", " | ").Replace("\n|", " | \n"); #if DEBUG - File.WriteAllText("../../../commandlist.md", helpstr); + File.WriteAllText("../../../docs/Commands List.md", helpstr.ToString()); #else - File.WriteAllText("commandlist.md", helpstr); + File.WriteAllText("commandlist.md", helpstr.ToString()); #endif }; @@ -92,13 +112,8 @@ $@"######For more information and how to setup your own NadekoBot, go to: await e.Channel.SendMessage( -@"**Wiki with all info**: - -**WINDOWS SETUP GUIDE**: - -**LINUX SETUP GUIDE**: - -**LIST OF COMMANDS**: ").ConfigureAwait(false)); +@"**LIST OF COMMANDS**: +**Hosting Guides and docs can be found here**: ").ConfigureAwait(false)); cgb.CreateCommand(Module.Prefix + "donate") .Alias("~donate") diff --git a/NadekoBot/Modules/Music/Classes/Song.cs b/NadekoBot/Modules/Music/Classes/Song.cs index d235776a..0b0a479a 100644 --- a/NadekoBot/Modules/Music/Classes/Song.cs +++ b/NadekoBot/Modules/Music/Classes/Song.cs @@ -297,10 +297,22 @@ namespace NadekoBot.Modules.Music.Classes if (video == null) // do something with this error throw new Exception("Could not load any video elements based on the query."); - var m = Regex.Match(query, @"\?t=(?\d*)"); + + var m = Regex.Match(query, @"\?t=((?\d*)h)?((?\d*)m)?((?\d*)s?)?"); int gotoTime = 0; if (m.Captures.Count > 0) - int.TryParse(m.Groups["t"].ToString(), out gotoTime); + { + int hours; + int minutes; + int seconds; + + int.TryParse(m.Groups["h"].ToString(), out hours); + int.TryParse(m.Groups["m"].ToString(), out minutes); + int.TryParse(m.Groups["s"].ToString(), out seconds); + + gotoTime = hours * 60 * 60 + minutes * 60 + seconds; + } + var song = new Song(new SongInfo { Title = video.Title.Substring(0, video.Title.Length - 10), // removing trailing "- You Tube" diff --git a/NadekoBot/Modules/Music/MusicModule.cs b/NadekoBot/Modules/Music/MusicModule.cs index 3c4aa351..a4c40bd3 100644 --- a/NadekoBot/Modules/Music/MusicModule.cs +++ b/NadekoBot/Modules/Music/MusicModule.cs @@ -324,7 +324,7 @@ namespace NadekoBot.Modules.Music cgb.CreateCommand(Prefix + "soundcloudpl") .Alias(Prefix + "scpl") - .Description($"Queue a soundcloud playlist using a link. | `{Prefix}scpl https://soundcloud.com/saratology/sets/symphony`") + .Description($"Queue a soundcloud playlist using a link. | `{Prefix}scpl soundcloudseturl`") .Parameter("pl", ParameterType.Unparsed) .Do(async e => { @@ -466,7 +466,7 @@ namespace NadekoBot.Modules.Music //var msRegex = new Regex(@"(?\d+)>(?\d+)", RegexOptions.Compiled); cgb.CreateCommand(Prefix + "movesong") .Alias(Prefix + "ms") - .Description($"Moves a song from one position to another. | `{Prefix} ms` 5>3") + .Description($"Moves a song from one position to another. | `{Prefix} ms 5>3`") .Parameter("fromto") .Do(async e => { @@ -502,7 +502,7 @@ namespace NadekoBot.Modules.Music cgb.CreateCommand(Prefix + "setmaxqueue") .Alias(Prefix + "smq") - .Description($"Sets a maximum queue size. Supply 0 or no argument to have no limit. | `{Prefix}smq` 50 or `{Prefix}smq`") + .Description($"Sets a maximum queue size. Supply 0 or no argument to have no limit. | `{Prefix}smq 50` or `{Prefix}smq`") .Parameter("size", ParameterType.Unparsed) .Do(async e => { diff --git a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs index 0c6aa79b..53c874c1 100644 --- a/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs +++ b/NadekoBot/Modules/Permissions/Classes/PermissionChecker.cs @@ -4,7 +4,6 @@ using Discord.Commands.Permissions; using NadekoBot.Classes.JSONModels; using System; using System.Collections.Concurrent; -using System.Collections.Generic; using System.Threading.Tasks; namespace NadekoBot.Modules.Permissions.Classes @@ -14,10 +13,8 @@ namespace NadekoBot.Modules.Permissions.Classes { public static PermissionChecker Instance { get; } = new PermissionChecker(); - //key - sid:command - //value - userid private ConcurrentDictionary commandCooldowns = new ConcurrentDictionary(); - private HashSet timeBlackList { get; } = new HashSet(); + private ConcurrentDictionary timeBlackList { get; } = new ConcurrentDictionary(); static PermissionChecker() { } private PermissionChecker() @@ -26,7 +23,6 @@ namespace NadekoBot.Modules.Permissions.Classes { while (true) { - //blacklist is cleared every 1.00 seconds. That is the most time anyone will be blocked await Task.Delay(1000).ConfigureAwait(false); timeBlackList.Clear(); } @@ -43,21 +39,28 @@ namespace NadekoBot.Modules.Permissions.Classes if (channel.IsPrivate || channel.Server == null) return command.Category == "Help"; + if (user == null) + return false; + if (ConfigHandler.IsUserBlacklisted(user.Id) || (!channel.IsPrivate && (ConfigHandler.IsServerBlacklisted(channel.Server.Id) || ConfigHandler.IsChannelBlacklisted(channel.Id)))) { return false; } - if (timeBlackList.Contains(user.Id)) - return false; + try + { + if (timeBlackList.ContainsKey(user.Id)) + return false; + } + catch { return false; } if (!channel.IsPrivate && !channel.Server.CurrentUser.GetPermissions(channel).SendMessages) { return false; } - timeBlackList.Add(user.Id); + timeBlackList.TryAdd(user.Id, true); ServerPermissions perms; PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms); diff --git a/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs b/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs index d7c9e784..9c00c7c6 100644 --- a/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs +++ b/NadekoBot/Modules/Permissions/Classes/PermissionsHandler.cs @@ -22,7 +22,7 @@ namespace NadekoBot.Modules.Permissions.Classes } - public static void Initialize() + public static Task Initialize() => Task.Run(() => { Console.WriteLine("Reading from the permission files."); Directory.CreateDirectory("data/permissions"); @@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Permissions.Classes catch { } } Console.WriteLine("Permission initialization complete."); - } + }); internal static Permissions GetRolePermissionsById(Server server, ulong id) { @@ -157,7 +157,7 @@ namespace NadekoBot.Modules.Permissions.Classes Newtonsoft.Json.JsonConvert.SerializeObject(serverPerms, Newtonsoft.Json.Formatting.Indented)); }); - public static Task WriteToJson() => Task.Run(() => + public static Task WriteToJson() => Task.Run(() => { Directory.CreateDirectory("data/permissions/"); foreach (var kvp in PermissionsDict) @@ -428,11 +428,13 @@ namespace NadekoBot.Modules.Permissions.Classes { var serverPerms = PermissionsDict.GetOrAdd(server.Id, new ServerPermissions(server.Id, server.Name)); - if (value == 0) { + if (value == 0) + { int throwaway; serverPerms.CommandCooldowns.TryRemove(commandName, out throwaway); } - else { + else + { serverPerms.CommandCooldowns.AddOrUpdate(commandName, value, (str, v) => value); } diff --git a/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs b/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs index 445558c3..29458c7a 100644 --- a/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs +++ b/NadekoBot/Modules/Permissions/Commands/FilterInvitesCommand.cs @@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Permissions.Commands public FilterInvitesCommand(DiscordModule module) : base(module) { - NadekoBot.Client.MessageReceived += async (sender, args) => + NadekoBot.OnReady += () => NadekoBot.Client.MessageReceived += async (sender, args) => { if (args.Channel.IsPrivate || args.User.Id == NadekoBot.Client.CurrentUser.Id) return; try diff --git a/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs b/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs index b574ef23..5b3c77e3 100644 --- a/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs +++ b/NadekoBot/Modules/Permissions/Commands/FilterWordsCommand.cs @@ -11,7 +11,7 @@ namespace NadekoBot.Modules.Permissions.Commands { public FilterWords(DiscordModule module) : base(module) { - NadekoBot.Client.MessageReceived += async (sender, args) => + NadekoBot.OnReady += () => NadekoBot.Client.MessageReceived += async (sender, args) => { if (args.Channel.IsPrivate || args.User.Id == NadekoBot.Client.CurrentUser.Id) return; try diff --git a/NadekoBot/Modules/Permissions/PermissionsModule.cs b/NadekoBot/Modules/Permissions/PermissionsModule.cs index a024341f..bf717094 100644 --- a/NadekoBot/Modules/Permissions/PermissionsModule.cs +++ b/NadekoBot/Modules/Permissions/PermissionsModule.cs @@ -679,7 +679,7 @@ namespace NadekoBot.Modules.Permissions }); cgb.CreateCommand(Prefix + "ubl") - .Description($"Blacklists a mentioned user. | `{Prefix}ubl [user_mention]`") + .Description($"Blacklists a mentioned user. **Bot Owner Only!**| `{Prefix}ubl [user_mention]`") .Parameter("user", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -695,7 +695,7 @@ namespace NadekoBot.Modules.Permissions }); cgb.CreateCommand(Prefix + "uubl") - .Description($"Unblacklists a mentioned user. | `{Prefix}uubl [user_mention]`") + .Description($"Unblacklists a mentioned user. **Bot Owner Only!** | `{Prefix}uubl [user_mention]`") .Parameter("user", ParameterType.Unparsed) .AddCheck(SimpleCheckers.OwnerOnly()) .Do(async e => @@ -726,7 +726,7 @@ namespace NadekoBot.Modules.Permissions { if (!e.Message.MentionedChannels.Any()) return; var ch = e.Message.MentionedChannels.First(); - NadekoBot.Config.UserBlacklist.Add(ch.Id); + NadekoBot.Config.ChannelBlacklist.Add(ch.Id); await ConfigHandler.SaveConfig().ConfigureAwait(false); await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); }).ConfigureAwait(false); @@ -741,9 +741,14 @@ namespace NadekoBot.Modules.Permissions { if (!e.Message.MentionedChannels.Any()) return; var ch = e.Message.MentionedChannels.First(); - NadekoBot.Config.UserBlacklist.Remove(ch.Id); - await ConfigHandler.SaveConfig().ConfigureAwait(false); - await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`").ConfigureAwait(false); + if (NadekoBot.Config.ChannelBlacklist.Contains(ch.Id)) + { + NadekoBot.Config.ChannelBlacklist.Remove(ch.Id); + await ConfigHandler.SaveConfig().ConfigureAwait(false); + await e.Channel.SendMessage($"`Sucessfully unblacklisted channel {ch.Name}`").ConfigureAwait(false); + } + else + await e.Channel.SendMessage($"`{ch.Name} was not in blacklist`").ConfigureAwait(false); }).ConfigureAwait(false); }); @@ -780,7 +785,7 @@ namespace NadekoBot.Modules.Permissions cgb.CreateCommand(Prefix + "cmdcooldown") .Alias(Prefix+ "cmdcd") - .Description($"Sets a cooldown per user for a command. Set 0 to clear. | `{Prefix}cmdcd \"some cmd\" 5`") + .Description($"Sets a cooldown per user for a command. Set 0 to clear. **Needs Manager Messages Permissions**| `{Prefix}cmdcd \"some cmd\" 5`") .Parameter("command", ParameterType.Required) .Parameter("secs",ParameterType.Required) .AddCheck(SimpleCheckers.ManageMessages()) diff --git a/NadekoBot/Modules/Searches/Commands/OsuCommands.cs b/NadekoBot/Modules/Searches/Commands/OsuCommands.cs index 8ead137d..6d95b72e 100644 --- a/NadekoBot/Modules/Searches/Commands/OsuCommands.cs +++ b/NadekoBot/Modules/Searches/Commands/OsuCommands.cs @@ -2,6 +2,7 @@ using NadekoBot.Classes; using Newtonsoft.Json.Linq; using System; +using System.Globalization; using System.IO; using System.Net; using System.Text.RegularExpressions; @@ -56,7 +57,7 @@ namespace NadekoBot.Modules.Searches.Commands }); cgb.CreateCommand(Module.Prefix + "osu b") - .Description($"Shows information about an osu beatmap. |`{Prefix}osu b` https://osu.ppy.sh/s/127712") + .Description($"Shows information about an osu beatmap. |`{Prefix}osu b https://osu.ppy.sh/s/127712`") .Parameter("map", ParameterType.Unparsed) .Do(async e => { @@ -75,7 +76,7 @@ namespace NadekoBot.Modules.Searches.Commands var reqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&{mapId}"; var obj = JArray.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false))[0]; var sb = new System.Text.StringBuilder(); - var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}"), 2); + var starRating = Math.Round(Double.Parse($"{obj["difficultyrating"]}", CultureInfo.InvariantCulture), 2); var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss"); sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}"); sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}"); @@ -120,7 +121,7 @@ namespace NadekoBot.Modules.Searches.Commands { var mapReqString = $"https://osu.ppy.sh/api/get_beatmaps?k={NadekoBot.Creds.OsuAPIKey}&b={item["beatmap_id"]}"; var map = JArray.Parse(await SearchHelper.GetResponseStringAsync(mapReqString).ConfigureAwait(false))[0]; - var pp = Math.Round(Double.Parse($"{item["pp"]}"), 2); + var pp = Math.Round(Double.Parse($"{item["pp"]}", CultureInfo.InvariantCulture), 2); var acc = CalculateAcc(item, m); var mods = ResolveMods(Int32.Parse($"{item["enabled_mods"]}")); if (mods != "+") diff --git a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs index f8720324..1513d0e7 100644 --- a/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs +++ b/NadekoBot/Modules/Searches/Commands/StreamNotifications.cs @@ -7,72 +7,89 @@ using System; using System.Collections.Concurrent; using System.Linq; using System.Threading.Tasks; -using System.Timers; namespace NadekoBot.Modules.Searches.Commands { internal class StreamNotifications : DiscordCommand { - - private readonly Timer checkTimer = new Timer - { - Interval = new TimeSpan(0, 0, 15).TotalMilliseconds, - }; - private ConcurrentDictionary> cachedStatuses = new ConcurrentDictionary>(); + private bool FirstPass { get; set; } = true; public StreamNotifications(DiscordModule module) : base(module) { - - checkTimer.Elapsed += async (s, e) => + //start checking only after ready, because we need all servers to be initialized + NadekoBot.OnReady += () => { - cachedStatuses.Clear(); - try + Task.Run(async () => + { + await Task.Delay(60000); + while (true) { - var streams = SpecificConfigurations.Default.AllConfigs.SelectMany(c => c.ObservingStreams); - if (!streams.Any()) return; - - foreach (var stream in streams) + cachedStatuses.Clear(); + try { - Tuple data; - try + var streams = SpecificConfigurations.Default.AllConfigs.SelectMany(c => c.ObservingStreams); + if (!streams.Any()) return; +#if NADEKO_RELEASE + var clr = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine($"Getting {streams.Count()} streams."); + Console.ForegroundColor = clr; +#endif + foreach (var stream in streams) { - data = await GetStreamStatus(stream).ConfigureAwait(false); - } - catch - { - continue; - } - - if (data.Item1 != stream.LastStatus) - { - stream.LastStatus = data.Item1; - var server = NadekoBot.Client.GetServer(stream.ServerId); - var channel = server?.GetChannel(stream.ChannelId); - if (channel == null) + Tuple data; + try + { + data = await GetStreamStatus(stream).ConfigureAwait(false); + } + catch + { continue; - var msg = $"`{stream.Username}`'s stream is now " + - $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " + - $"**{data.Item2}** viewers."; - if (stream.LastStatus) - if (stream.Type == StreamNotificationConfig.StreamType.Hitbox) - msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; - else if (stream.Type == StreamNotificationConfig.StreamType.Twitch) - msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; - else if (stream.Type == StreamNotificationConfig.StreamType.Beam) - msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】"; - else if (stream.Type == StreamNotificationConfig.StreamType.YoutubeGaming) - msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】"; - await channel.SendMessage(msg).ConfigureAwait(false); + } + + if (data.Item1 != stream.LastStatus) + { + stream.LastStatus = data.Item1; + if (FirstPass) + continue; + var server = NadekoBot.Client.GetServer(stream.ServerId); + var channel = server?.GetChannel(stream.ChannelId); + if (channel == null) + continue; + var msg = $"`{stream.Username}`'s stream is now " + + $"**{(data.Item1 ? "ONLINE" : "OFFLINE")}** with " + + $"**{data.Item2}** viewers."; + if (stream.LastStatus) + if (stream.Type == StreamNotificationConfig.StreamType.Hitbox) + msg += $"\n`Here is the Link:`【 http://www.hitbox.tv/{stream.Username}/ 】"; + else if (stream.Type == StreamNotificationConfig.StreamType.Twitch) + msg += $"\n`Here is the Link:`【 http://www.twitch.tv/{stream.Username}/ 】"; + else if (stream.Type == StreamNotificationConfig.StreamType.Beam) + msg += $"\n`Here is the Link:`【 http://www.beam.pro/{stream.Username}/ 】"; + else if (stream.Type == StreamNotificationConfig.StreamType.YoutubeGaming) + msg += $"\n`Here is the Link:`【 not implemented yet - {stream.Username} 】"; + await channel.SendMessage(msg).ConfigureAwait(false); + } } + FirstPass = false; +#if NADEKO_RELEASE + clr = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Blue; + Console.WriteLine($"Done getting streams."); + Console.ForegroundColor = clr; +#endif + } + catch { } + finally + { + await Task.Delay(TimeSpan.FromSeconds(60)); } } - catch { } - await ConfigHandler.SaveConfig().ConfigureAwait(false); - }; - checkTimer.Start(); - } + }); + }; + } private async Task> GetStreamStatus(StreamNotificationConfig stream, bool checkCache = true) { bool isLive; diff --git a/NadekoBot/Modules/Searches/SearchesModule.cs b/NadekoBot/Modules/Searches/SearchesModule.cs index 2662107a..4caa708b 100644 --- a/NadekoBot/Modules/Searches/SearchesModule.cs +++ b/NadekoBot/Modules/Searches/SearchesModule.cs @@ -300,10 +300,11 @@ $@"🌍 **Weather for** 【{obj["target"]}】 { var items = JObject.Parse(res); var sb = new System.Text.StringBuilder(); - sb.AppendLine($"`Term:` {items["list"][0]["word"].ToString()}"); - sb.AppendLine($"`Definition:` {items["list"][0]["definition"].ToString()}"); - sb.Append($"`Link:` <{await items["list"][0]["permalink"].ToString().ShortenUrl().ConfigureAwait(false)}>"); - await e.Channel.SendMessage(sb.ToString()); + var item = items["list"][0]; + sb.AppendLine($"`Term:` {item["word"].ToString()}"); + sb.AppendLine($"`Definition:` {item["definition"].ToString()}"); + sb.Append($"`Link:` <{item["permalink"].ToString()}>"); + await e.Channel.SendMessage(sb.ToString()).ConfigureAwait(false); } catch { diff --git a/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs b/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs index b1a10a8c..4bc8f384 100644 --- a/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs +++ b/NadekoBot/Modules/Translator/Helpers/GoogleTranslator.cs @@ -99,6 +99,8 @@ namespace NadekoBot.Modules.Translator.Helpers { "bengali", "bn"}, { "bulgarian", "bg"}, { "catalan", "ca"}, + { "chinese-traditional", "zh-TW"}, + { "chinese-simplified", "zh-CN"}, { "chinese", "zh-CN"}, { "croatian", "hr"}, { "czech", "cs"}, @@ -163,6 +165,7 @@ namespace NadekoBot.Modules.Translator.Helpers { "bn", "bn"}, { "bg", "bg"}, { "ca", "ca"}, + { "zh-TW", "zh-TW"}, { "zh-CN", "zh-CN"}, { "hr", "hr"}, { "cs", "cs"}, diff --git a/NadekoBot/Modules/Utility/Commands/InfoCommands.cs b/NadekoBot/Modules/Utility/Commands/InfoCommands.cs index da1bcd0c..4a19b990 100644 --- a/NadekoBot/Modules/Utility/Commands/InfoCommands.cs +++ b/NadekoBot/Modules/Utility/Commands/InfoCommands.cs @@ -39,7 +39,7 @@ namespace NadekoBot.Modules.Utility.Commands sb.AppendLine($"`Roles:` **{server.Roles.Count()}**"); sb.AppendLine($"`Created At:` **{createdAt}**"); if (server.CustomEmojis.Count() > 0) - sb.AppendLine($"`Custom Emojis:` **{string.Join(", ", server.CustomEmojis)}**"); + sb.AppendLine($"`Custom Emojis:` **{string.Join(", ", server.CustomEmojis.Select(em => em.Name))}**"); if (server.Features.Count() > 0) sb.AppendLine($"`Features:` **{string.Join(", ", server.Features)}**"); if (!string.IsNullOrWhiteSpace(server.SplashId)) diff --git a/NadekoBot/Modules/Utility/Commands/Remind.cs b/NadekoBot/Modules/Utility/Commands/Remind.cs index 808f4b11..07054394 100644 --- a/NadekoBot/Modules/Utility/Commands/Remind.cs +++ b/NadekoBot/Modules/Utility/Commands/Remind.cs @@ -30,7 +30,7 @@ namespace NadekoBot.Modules.Utility.Commands { var remList = DbHandler.Instance.GetAllRows(); - reminders = remList.Select(StartNewReminder).ToList(); + NadekoBot.OnReady += () => reminders = remList.Select(StartNewReminder).ToList(); } private Timer StartNewReminder(Reminder r) diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index b706b95d..a66de25d 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -2,6 +2,7 @@ using Discord.Audio; using Discord.Commands; using Discord.Modules; +using NadekoBot.Classes; using NadekoBot.Classes.Help.Commands; using NadekoBot.Classes.JSONModels; using NadekoBot.Modules.Administration; @@ -117,7 +118,7 @@ namespace NadekoBot Client = new DiscordClient(new DiscordConfigBuilder() { MessageCacheSize = 10, - ConnectionTimeout = 180000, + ConnectionTimeout = int.MaxValue, LogLevel = LogSeverity.Warning, LogHandler = (s, e) => Console.WriteLine($"Severity: {e.Severity}" + @@ -145,9 +146,6 @@ namespace NadekoBot } }); - //reply to personal messages and forward if enabled. - Client.MessageReceived += Client_MessageReceived; - //add command service Client.AddService(commandService); @@ -185,9 +183,18 @@ namespace NadekoBot //run the bot Client.ExecuteAndWait(async () => { + await Task.Run(() => + { + Console.WriteLine("Specific config started initializing."); + var x = SpecificConfigurations.Default; + Console.WriteLine("Specific config done initializing."); + }); + + await PermissionsHandler.Initialize(); + try { - await Client.Connect(Creds.Token).ConfigureAwait(false); + await Client.Connect(Creds.Token, TokenType.Bot).ConfigureAwait(false); } catch (Exception ex) { @@ -197,7 +204,7 @@ namespace NadekoBot return; } #if NADEKO_RELEASE - await Task.Delay(150000).ConfigureAwait(false); + await Task.Delay(220000).ConfigureAwait(false); #else await Task.Delay(1000).ConfigureAwait(false); #endif @@ -228,9 +235,22 @@ namespace NadekoBot if (string.IsNullOrWhiteSpace(request.Content)) e.Cancel = true; }; - PermissionsHandler.Initialize(); +#if NADEKO_RELEASE + Client.ClientAPI.SentRequest += (s, e) => + { + Console.WriteLine($"[Request of type {e.Request.GetType()} sent in {e.Milliseconds}]"); + + var request = e.Request as Discord.API.Client.Rest.SendMessageRequest; + if (request == null) return; + + Console.WriteLine($"[Content: { request.Content }"); + }; +#endif NadekoBot.Ready = true; NadekoBot.OnReady(); + Console.WriteLine("Ready!"); + //reply to personal messages and forward if enabled. + Client.MessageReceived += Client_MessageReceived; }); Console.WriteLine("Exiting..."); Console.ReadKey(); diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index 341f1850..223f778f 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -13,6 +13,9 @@ 512 true false + + + C:\Users\Master\Desktop\NadekoBot\ true Disk @@ -30,9 +33,6 @@ false true true - - - AnyCPU @@ -161,6 +161,9 @@ False lib\ScaredFingers.UnitsConversion.dll + + Classes\lib\sqlite3.dll + @@ -299,8 +302,12 @@ - - + + Designer + + + Designer + @@ -553,9 +560,7 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - -