diff --git a/.gitignore b/.gitignore index 31a88a35..e9eea17a 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ Tests/ # Uncomment if necessary however generally it will be regenerated when needed #!**/packages/repositories.config NadekoBot/bin/Debug/data/nadekobot.sqlite +NadekoBot/bin/Debug/data/config.json diff --git a/NadekoBot/Classes/JSONModels/Config.cs b/NadekoBot/Classes/JSONModels/Config.cs deleted file mode 100644 index 2b643ebf..00000000 --- a/NadekoBot/Classes/JSONModels/Config.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System; - -namespace NadekoBot.Classes.JSONModels { - internal class LocalizedStrings { - public string[] _8BallAnswers { get; set; } - } -} diff --git a/NadekoBot/Classes/JSONModels/Configuration.cs b/NadekoBot/Classes/JSONModels/Configuration.cs new file mode 100644 index 00000000..aff5fbdd --- /dev/null +++ b/NadekoBot/Classes/JSONModels/Configuration.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace NadekoBot.Classes.JSONModels { + public class Configuration { + public bool DontJoinServers = false; + public bool ForwardMessages = true; + public HashSet ServerBlacklist = new HashSet(); + public HashSet ChannelBlacklist = new HashSet(); + public HashSet UserBlacklist = new HashSet(); + } +} diff --git a/NadekoBot/Classes/JSONModels/_JSONModels.cs b/NadekoBot/Classes/JSONModels/_JSONModels.cs index d967a62a..df806861 100644 --- a/NadekoBot/Classes/JSONModels/_JSONModels.cs +++ b/NadekoBot/Classes/JSONModels/_JSONModels.cs @@ -3,16 +3,14 @@ namespace NadekoBot.Classes.JSONModels { public class Credentials { - public string Username; - public string Password; - public string BotId; - public string GoogleAPIKey; - public ulong[] OwnerIds; - public string TrelloAppKey; - public bool? ForwardMessages; - public string SoundCloudClientID; - public string MashapeKey; - public string LOLAPIKey; - public bool DontJoinServers = false; + public string Username = "myemail@email.com"; + public string Password = "xxxxxxx"; + public ulong BotId = 1231231231231; + public string GoogleAPIKey = ""; + public ulong[] OwnerIds = {123123123123, 5675675679845}; + public string TrelloAppKey = ""; + public string SoundCloudClientID = ""; + public string MashapeKey = ""; + public string LOLAPIKey = ""; } } \ No newline at end of file diff --git a/NadekoBot/Classes/Music/MusicControls.cs b/NadekoBot/Classes/Music/MusicControls.cs index cd67113e..fe17576e 100644 --- a/NadekoBot/Classes/Music/MusicControls.cs +++ b/NadekoBot/Classes/Music/MusicControls.cs @@ -102,6 +102,7 @@ namespace NadekoBot.Classes.Music { try { if (!SongCancelSource.IsCancellationRequested) SongCancelSource.Cancel(); + audioClient.Disconnect(); } catch { Console.WriteLine("STOP"); diff --git a/NadekoBot/Classes/Permissions/PermissionChecker.cs b/NadekoBot/Classes/Permissions/PermissionChecker.cs index f3d7b04d..837d74de 100644 --- a/NadekoBot/Classes/Permissions/PermissionChecker.cs +++ b/NadekoBot/Classes/Permissions/PermissionChecker.cs @@ -7,17 +7,17 @@ using System.Collections.Concurrent; using System.Collections.Generic; namespace NadekoBot.Classes.Permissions { + internal class PermissionChecker : IPermissionChecker { public static PermissionChecker Instance { get; } = new PermissionChecker(); private ConcurrentDictionary timeBlackList { get; } = new ConcurrentDictionary(); - private HashSet serverBlacklist { get; } = new HashSet(); static PermissionChecker() { } public PermissionChecker() { Task.Run(async () => { while (true) { - //blacklist is cleared every 1.75 seconds. That is the most time anyone will be blocked for ever + //blacklist is cleared every 1.75 seconds. That is the most time anyone will be blocked await Task.Delay(1750); timeBlackList.Clear(); } @@ -27,6 +27,12 @@ namespace NadekoBot.Classes.Permissions { public bool CanRun(Command command, User user, Channel channel, out string error) { error = String.Empty; + if (NadekoBot.IsUserBlacklisted(user.Id) || + (!channel.IsPrivate && + (NadekoBot.IsServerBlacklisted(channel.Server.Id) || NadekoBot.IsChannelBlacklisted(channel.Id)))) { + return false; + } + if (timeBlackList.ContainsKey(user)) return false; diff --git a/NadekoBot/Classes/Permissions/PermissionHelper.cs b/NadekoBot/Classes/Permissions/PermissionHelper.cs index 107e061e..f8991a7d 100644 --- a/NadekoBot/Classes/Permissions/PermissionHelper.cs +++ b/NadekoBot/Classes/Permissions/PermissionHelper.cs @@ -1,10 +1,10 @@ -using Discord.Commands; -using Discord.Modules; -using System; +using System; using System.Linq; using Discord; +using Discord.Commands; +using Discord.Modules; -namespace NadekoBot.Classes { +namespace NadekoBot.Classes.Permissions { internal static class PermissionHelper { public static bool ValidateBool(string passedArg) { if (string.IsNullOrWhiteSpace(passedArg)) { diff --git a/NadekoBot/Modules/Conversations.cs b/NadekoBot/Modules/Conversations.cs index 4ef2f7d2..7532c568 100644 --- a/NadekoBot/Modules/Conversations.cs +++ b/NadekoBot/Modules/Conversations.cs @@ -248,7 +248,7 @@ namespace NadekoBot.Modules { e.Channel.SendFile("ripzor_m8.png", RipName(text, string.IsNullOrWhiteSpace(e.GetArg("year")) ? null : e.GetArg("year"))); }); - if (!NadekoBot.Creds.DontJoinServers) { + if (!NadekoBot.Config.DontJoinServers) { cgb.CreateCommand("j") .Description("Joins a server using a code.") .Parameter("id", ParameterType.Required) diff --git a/NadekoBot/Modules/Permissions.cs b/NadekoBot/Modules/Permissions.cs index 3aef9e3d..660b586a 100644 --- a/NadekoBot/Modules/Permissions.cs +++ b/NadekoBot/Modules/Permissions.cs @@ -1,23 +1,24 @@ using System; using Discord.Modules; using Discord.Commands; -using NadekoBot.Classes; using PermsHandler = NadekoBot.Classes.Permissions.PermissionsHandler; using System.Linq; +using System.Threading.Tasks; +using NadekoBot.Classes.Permissions; using NadekoBot.Extensions; namespace NadekoBot.Modules { internal class PermissionModule : DiscordModule { private const string prefix = ";"; - public PermissionModule() { + public PermissionModule() { //Empty for now } //todo word filtering/invite bans (?:discord(?:\.gg|app\.com\/invite)\/(?([\w]{16}|(?:[\w]+-?){3}))) public override void Install(ModuleManager manager) { manager.CreateCommands("", cgb => { - cgb.AddCheck(Classes.Permissions.PermissionChecker.Instance); + cgb.AddCheck(PermissionChecker.Instance); commands.ForEach(cmd => cmd.Init(cgb)); @@ -35,8 +36,7 @@ namespace NadekoBot.Modules { Discord.Role role = null; try { role = PermissionHelper.ValidateRole(e.Server, arg); - } - catch (Exception ex) { + } catch (Exception ex) { Console.WriteLine(ex.Message); await e.Channel.SendMessage($"Role `{arg}` probably doesn't exist. Create the role with that name first."); return; @@ -76,8 +76,7 @@ namespace NadekoBot.Modules { if (!string.IsNullOrWhiteSpace(arg)) try { role = PermissionHelper.ValidateRole(e.Server, arg); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("💢 Error: " + ex.Message); return; } @@ -99,8 +98,7 @@ namespace NadekoBot.Modules { if (!string.IsNullOrWhiteSpace(arg)) try { channel = PermissionHelper.ValidateChannel(e.Server, arg); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("💢 Error: " + ex.Message); return; } @@ -120,8 +118,7 @@ namespace NadekoBot.Modules { if (!string.IsNullOrWhiteSpace(e.GetArg("user"))) try { user = PermissionHelper.ValidateUser(e.Server, e.GetArg("user")); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("💢 Error: " + ex.Message); return; } @@ -143,11 +140,9 @@ namespace NadekoBot.Modules { PermsHandler.SetServerModulePermission(e.Server, module, state); await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on this server."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -163,11 +158,9 @@ namespace NadekoBot.Modules { PermsHandler.SetServerCommandPermission(e.Server, command, state); await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on this server."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -187,18 +180,15 @@ namespace NadekoBot.Modules { PermsHandler.SetRoleModulePermission(role, module, state); } await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles."); - } - else { + } else { var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); PermsHandler.SetRoleModulePermission(role, module, state); await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role."); } - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -218,18 +208,15 @@ namespace NadekoBot.Modules { PermsHandler.SetRoleCommandPermission(role, command, state); } await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **ALL** roles."); - } - else { + } else { var role = PermissionHelper.ValidateRole(e.Server, e.GetArg("role")); PermsHandler.SetRoleCommandPermission(role, command, state); await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role."); } - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -249,18 +236,15 @@ namespace NadekoBot.Modules { PermsHandler.SetChannelModulePermission(channel, module, state); } await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels."); - } - else { + } else { var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel")); PermsHandler.SetChannelModulePermission(channel, module, state); await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel."); } - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -280,18 +264,15 @@ namespace NadekoBot.Modules { PermsHandler.SetChannelCommandPermission(channel, command, state); } await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** on **ALL** channels."); - } - else { + } else { var channel = PermissionHelper.ValidateChannel(e.Server, e.GetArg("channel")); PermsHandler.SetChannelCommandPermission(channel, command, state); await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel."); } - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -309,11 +290,9 @@ namespace NadekoBot.Modules { PermsHandler.SetUserModulePermission(user, module, state); await e.Channel.SendMessage($"Module **{module}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -331,11 +310,9 @@ namespace NadekoBot.Modules { PermsHandler.SetUserCommandPermission(user, command, state); await e.Channel.SendMessage($"Command **{command}** has been **{(state ? "enabled" : "disabled")}** for user **{user.Name}**."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -351,11 +328,9 @@ namespace NadekoBot.Modules { PermsHandler.SetServerModulePermission(e.Server, module.Name, state); } await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** on this server."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -373,11 +348,9 @@ namespace NadekoBot.Modules { PermsHandler.SetServerCommandPermission(e.Server, command.Text, state); } await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** on this server."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -395,11 +368,9 @@ namespace NadekoBot.Modules { } await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -418,11 +389,9 @@ namespace NadekoBot.Modules { PermsHandler.SetChannelCommandPermission(channel, command.Text, state); } await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{channel.Name}** channel."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -440,11 +409,9 @@ namespace NadekoBot.Modules { } await e.Channel.SendMessage($"All modules have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); @@ -463,14 +430,57 @@ namespace NadekoBot.Modules { PermsHandler.SetRoleCommandPermission(role, command.Text, state); } await e.Channel.SendMessage($"All commands from the **{module}** module have been **{(state ? "enabled" : "disabled")}** for **{role.Name}** role."); - } - catch (ArgumentException exArg) { + } catch (ArgumentException exArg) { await e.Channel.SendMessage(exArg.Message); - } - catch (Exception ex) { + } catch (Exception ex) { await e.Channel.SendMessage("Something went terribly wrong - " + ex.Message); } }); + + cgb.CreateCommand(prefix + "ubl") + .Description("Blacklists a mentioned user.\n**Usage**: ;ubl [user_mention]") + .Parameter("user", ParameterType.Unparsed) + .Do(async e => { + await Task.Run(async () => { + if (!e.Message.MentionedUsers.Any()) return; + var usr = e.Message.MentionedUsers.First(); + NadekoBot.Config.UserBlacklist.Add(usr.Id); + NadekoBot.SaveConfig(); + await e.Channel.SendMessage($"`Sucessfully blacklisted user {usr.Name}`"); + }); + }); + + cgb.CreateCommand(prefix + "ucl") + .Description("Blacklists a mentioned channel (#general for example).\n**Usage**: ;ubl [channel_mention]") + .Parameter("user", ParameterType.Unparsed) + .Do(async e => { + await Task.Run(async () => { + if (!e.Message.MentionedChannels.Any()) return; + var ch = e.Message.MentionedChannels.First(); + NadekoBot.Config.UserBlacklist.Add(ch.Id); + NadekoBot.SaveConfig(); + await e.Channel.SendMessage($"`Sucessfully blacklisted channel {ch.Name}`"); + }); + }); + + cgb.CreateCommand(prefix + "usl") + .Description("Blacklists a server by a name or id (#general for example).\n**Usage**: ;usl [servername/serverid]") + .Parameter("user", ParameterType.Unparsed) + .Do(async e => { + await Task.Run(async () => { + var arg = e.GetArg("user"); + if (string.IsNullOrWhiteSpace(arg)) + return; + var server = NadekoBot.Client.FindServers(arg.Trim()).FirstOrDefault(); + if (server == null) { + await e.Channel.SendMessage("Cannot find that server"); + return; + } + NadekoBot.Config.ServerBlacklist.Add(server.Id); + NadekoBot.SaveConfig(); + await e.Channel.SendMessage($"`Sucessfully blacklisted server {server.Name}`"); + }); + }); }); } } diff --git a/NadekoBot/NadekoBot.cs b/NadekoBot/NadekoBot.cs index 55e7d0ad..896f8c61 100644 --- a/NadekoBot/NadekoBot.cs +++ b/NadekoBot/NadekoBot.cs @@ -18,12 +18,30 @@ namespace NadekoBot { public static DiscordClient Client; public static bool ForwardMessages = false; public static Credentials Creds { get; set; } + public static Configuration Config { get; set; } public static string BotMention { get; set; } = ""; private static Channel OwnerPrivateChannel { get; set; } private static void Main() { Console.OutputEncoding = Encoding.Unicode; + + // generate credentials example so people can know about the changes i make + try { + File.WriteAllText("credentials_example.json", JsonConvert.SerializeObject(new Credentials(), Formatting.Indented)); + File.WriteAllText("data/config_example.json", JsonConvert.SerializeObject(new Configuration(), Formatting.Indented)); + } + catch { + Console.WriteLine("Failed writing credentials_example.json or data/config_example.json"); + } + + try { + Config = JsonConvert.DeserializeObject(File.ReadAllText("data/config.json")); + } + catch { + Console.WriteLine("Failed loading configuration."); + } + try { //load credentials from credentials.json Creds = JsonConvert.DeserializeObject(File.ReadAllText("credentials.json")); @@ -39,7 +57,7 @@ namespace NadekoBot { Console.WriteLine(string.IsNullOrWhiteSpace(Creds.TrelloAppKey) ? "No trello appkey found. You will not be able to use trello commands." : "Trello app key provided."); - Console.WriteLine(Creds.ForwardMessages != true + Console.WriteLine(Config.ForwardMessages != true ? "Not forwarding messages." : "Forwarding private messages to owner."); Console.WriteLine(string.IsNullOrWhiteSpace(Creds.SoundCloudClientID) @@ -149,7 +167,6 @@ namespace NadekoBot { } private static bool repliedRecently = false; - private static async void Client_MessageReceived(object sender, MessageEventArgs e) { try { if (e.Server != null || e.User.Id == Client.CurrentUser.Id) return; @@ -157,12 +174,14 @@ namespace NadekoBot { // just ban this trash AutoModerator // and cancer christmass spirit // and crappy shotaslave + if (IsBlackListed(e)) + return; if (e.User.Id == 105309315895693312 || e.User.Id == 119174277298782216 || e.User.Id == 143515953525817344) return; // FU - if (!NadekoBot.Creds.DontJoinServers) { + if (!NadekoBot.Config.DontJoinServers) { try { await (await Client.GetInvite(e.Message.Text)).Accept(); await e.Channel.SendMessage("I got in!"); @@ -188,6 +207,23 @@ namespace NadekoBot { }); } catch { } } + + private static readonly object configLock = new object(); + public static void SaveConfig() { + lock (configLock) { + File.WriteAllText("data/config.json", JsonConvert.SerializeObject(NadekoBot.Config, Formatting.Indented)); + } + } + + public static bool IsBlackListed(MessageEventArgs evArgs) => IsUserBlacklisted(evArgs.User.Id) || + (!evArgs.Channel.IsPrivate && + (IsChannelBlacklisted(evArgs.Channel.Id) || IsServerBlacklisted(evArgs.Server.Id))); + + public static bool IsServerBlacklisted(ulong id) => NadekoBot.Config.ServerBlacklist.Contains(id); + + public static bool IsChannelBlacklisted(ulong id) => NadekoBot.Config.ChannelBlacklist.Contains(id); + + public static bool IsUserBlacklisted(ulong id) => NadekoBot.Config.UserBlacklist.Contains(id); } } diff --git a/NadekoBot/NadekoBot.csproj b/NadekoBot/NadekoBot.csproj index b2d3f0c5..943365cf 100644 --- a/NadekoBot/NadekoBot.csproj +++ b/NadekoBot/NadekoBot.csproj @@ -118,7 +118,7 @@ - + diff --git a/NadekoBot/bin/Debug/Discord.Net.Audio.dll b/NadekoBot/bin/Debug/Discord.Net.Audio.dll index d69a079d..be483770 100644 Binary files a/NadekoBot/bin/Debug/Discord.Net.Audio.dll and b/NadekoBot/bin/Debug/Discord.Net.Audio.dll differ diff --git a/NadekoBot/bin/Debug/Discord.Net.Commands.dll b/NadekoBot/bin/Debug/Discord.Net.Commands.dll index d610b8cc..9cd45af7 100644 Binary files a/NadekoBot/bin/Debug/Discord.Net.Commands.dll and b/NadekoBot/bin/Debug/Discord.Net.Commands.dll differ diff --git a/NadekoBot/bin/Debug/Discord.Net.Modules.dll b/NadekoBot/bin/Debug/Discord.Net.Modules.dll index 50944c6c..db0020d7 100644 Binary files a/NadekoBot/bin/Debug/Discord.Net.Modules.dll and b/NadekoBot/bin/Debug/Discord.Net.Modules.dll differ diff --git a/NadekoBot/bin/Debug/Discord.Net.dll b/NadekoBot/bin/Debug/Discord.Net.dll index 372ad73e..aba79794 100644 Binary files a/NadekoBot/bin/Debug/Discord.Net.dll and b/NadekoBot/bin/Debug/Discord.Net.dll differ diff --git a/NadekoBot/bin/Debug/data/config_example.json b/NadekoBot/bin/Debug/data/config_example.json new file mode 100644 index 00000000..9d035085 --- /dev/null +++ b/NadekoBot/bin/Debug/data/config_example.json @@ -0,0 +1,7 @@ +{ + "DontJoinServers": false, + "ForwardMessages": true, + "ServerBlacklist": [], + "ChannelBlacklist": [], + "UserBlacklist": [] +} \ No newline at end of file