A lot of work on administration module

This commit is contained in:
Kwoth
2016-08-16 18:00:52 +02:00
parent d7f8126fe4
commit d6477b9d90
15 changed files with 765 additions and 968 deletions

View File

@@ -0,0 +1,765 @@
using Discord;
using Discord.Commands;
using Discord.Modules;
using NadekoBot.Classes;
using NadekoBot.DataModels;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Commands;
using NadekoBot.Modules.Permissions.Classes;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NadekoBot.Services;
using NadekoBot.Attributes;
//todo fix delmsgoncmd
//todo DB
namespace NadekoBot.Modules.Administration
{
[Module(".", AppendSpace = false)]
public partial class AdministrationModule : DiscordModule
{
public AdministrationModule(ILocalization loc, CommandService cmds, IBotConfiguration config, IDiscordClient client) : base(loc, cmds, config, client)
{
}
//todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Restart(IMessage imsg)
//{
// var channel = imsg.Channel as IGuildChannel;
// await imsg.Channel.SendMessageAsync("`Restarting in 2 seconds...`");
// await Task.Delay(2000);
// System.Diagnostics.Process.Start(System.Reflection.Assembly.GetEntryAssembly().Location);
// Environment.Exit(0);
//}
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//[RequirePermission(GuildPermission.ManageGuild)]
//public async Task Delmsgoncmd(IMessage imsg)
//{
// var channel = imsg.Channel as IGuildChannel;
// var conf = SpecificConfigurations.Default.Of(channel.Guild.Id);
// conf.AutoDeleteMessagesOnCommand = !conf.AutoDeleteMessagesOnCommand;
// await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
// if (conf.AutoDeleteMessagesOnCommand)
// await imsg.Channel.SendMessageAsync("❗`Now automatically deleting successfull command invokations.`");
// else
// await imsg.Channel.SendMessageAsync("❗`Stopped automatic deletion of successfull command invokations.`");
//}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task Setrole(IMessage imsg, IUser userName, [Remainder] string roleName)
{
var channel = imsg.Channel as IGuildChannel;
if (string.IsNullOrWhiteSpace(roleName)) return;
var usr = channel.Guild.FindUsers(userName).FirstOrDefault();
if (usr == null)
{
await imsg.Channel.SendMessageAsync("You failed to supply a valid username").ConfigureAwait(false);
return;
}
var role = channel.Guild.FindRoles(roleName).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync("You failed to supply a valid role").ConfigureAwait(false);
return;
}
try
{
await usr.AddRoles(role).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Successfully added role **{role.Name}** to user **{usr.Name}**").ConfigureAwait(false);
}
catch (Exception ex)
{
await imsg.Channel.SendMessageAsync("Failed to add roles. Bot has insufficient permissions.\n").ConfigureAwait(false);
Console.WriteLine(ex.ToString());
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task Removerole(IMessage imsg, IUser userName, [Remainder] string roleName)
{
var channel = imsg.Channel as IGuildChannel;
if (string.IsNullOrWhiteSpace(roleName)) return;
var usr = channel.Guild.FindUsers(userName).FirstOrDefault();
if (usr == null)
{
await imsg.Channel.SendMessageAsync("You failed to supply a valid username").ConfigureAwait(false);
return;
}
var role = channel.Guild.FindRoles(roleName).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync("You failed to supply a valid role").ConfigureAwait(false);
return;
}
try
{
await usr.RemoveRoles(role).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Successfully removed role **{role.Name}** from user **{usr.Name}**").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("Failed to remove roles. Most likely reason: Insufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task RenameRole(IMessage imsg, string r1, string r2)
{
var channel = imsg.Channel as IGuildChannel;
var roleToEdit = channel.Guild.FindRoles(r1).FirstOrDefault();
if (roleToEdit == null)
{
await imsg.Channel.SendMessageAsync("Can't find that role.").ConfigureAwait(false);
return;
}
try
{
if (roleToEdit.Position > channel.Guild.CurrentUser.Roles.Max(r => r.Position))
{
await imsg.Channel.SendMessageAsync("I can't edit roles higher than my highest role.").ConfigureAwait(false);
return;
}
await roleToEdit.Edit(r2);
await imsg.Channel.SendMessageAsync("Role renamed.").ConfigureAwait(false);
}
catch (Exception)
{
await imsg.Channel.SendMessageAsync("Failed to rename role. Probably insufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task RemoveAllRoles(IMessage imsg, [Remainder] string userName)
{
var channel = imsg.Channel as IGuildChannel;
var usr = channel.Guild.FindUsers(userName).FirstOrDefault();
if (usr == null)
{
await imsg.Channel.SendMessageAsync("You failed to supply a valid username").ConfigureAwait(false);
return;
}
try
{
await usr.RemoveRoles(usr.Roles.ToArray()).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Successfully removed **all** roles from user **{usr.Name}**").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("Failed to remove roles. Most likely reason: Insufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task CreateRole(IMessage imsg, [Remainder] string roleName)
{
var channel = imsg.Channel as IGuildChannel;
if (string.IsNullOrWhiteSpace(e.GetArg("role_name")))
return;
try
{
var r = await channel.Guild.CreateRole(e.GetArg("role_name")).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Successfully created role **{r.Name}**.").ConfigureAwait(false);
}
catch (Exception)
{
await imsg.Channel.SendMessageAsync(":warning: Unspecified error.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)]
public async Task RoleColor(IMessage imsg, string roleName, string r="", string g="", string b="")
{
var channel = imsg.Channel as IGuildChannel;
var args = e.Args.Where(s => s != string.Empty);
if (args.Count() != 2 && args.Count() != 4)
{
await imsg.Channel.SendMessageAsync("The parameters are invalid.").ConfigureAwait(false);
return;
}
var role = channel.Guild.FindRoles(e.Args[0]).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync("That role does not exist.").ConfigureAwait(false);
return;
}
try
{
var rgb = args.Count() == 4;
var arg1 = e.Args[1].Replace("#", "");
var red = Convert.ToByte(rgb ? int.Parse(arg1) : Convert.ToInt32(arg1.Substring(0, 2), 16));
var green = Convert.ToByte(rgb ? int.Parse(e.Args[2]) : Convert.ToInt32(arg1.Substring(2, 2), 16));
var blue = Convert.ToByte(rgb ? int.Parse(e.Args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16));
await role.Edit(color: new Color(red, green, blue)).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Role {role.Name}'s color has been changed.").ConfigureAwait(false);
}
catch (Exception)
{
await imsg.Channel.SendMessageAsync("Error occured, most likely invalid parameters or insufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.BanMembers)]
public async Task Ban(IMessage imsg, IUser user, [Remainder] string msg)
{
var channel = imsg.Channel as IGuildChannel;
if (user == null)
{
await imsg.Channel.SendMessageAsync("User not found.").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
await user.SendMessage($"**You have been BANNED from `{channel.Guild.Name}` server.**\n" +
$"Reason: {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); // temp solution; give time for a message to be send, fu volt
}
try
{
await channel.Guild.Ban(user, 7).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync("Banned user " + user.Name + " Id: " + user.Id).ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.BanMembers)]
public async Task Softban(IMessage imsg, IUser user, [Remainder] string msg)
{
var channel = imsg.Channel as IGuildChannel;
if (user == null)
{
await imsg.Channel.SendMessageAsync("User not found.").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
await user.SendMessage($"**You have been SOFT-BANNED from `{channel.Guild.Name}` server.**\n" +
$"Reason: {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); // temp solution; give time for a message to be send, fu volt
}
try
{
await channel.Guild.Ban(user, 7).ConfigureAwait(false);
await channel.Guild.Unban(user).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync("Soft-Banned user " + user.Username + " Id: " + user.Id).ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Kick(IMessage imsg, IUser user, [Remainder] string msg)
{
var channel = imsg.Channel as IGuildChannel;
var usr = channel.Guild.FindUsers(user).FirstOrDefault();
if (usr == null)
{
await imsg.Channel.SendMessageAsync("User not found.").ConfigureAwait(false);
return;
}
if (!string.IsNullOrWhiteSpace(msg))
{
await usr.SendMessage($"**You have been KICKED from `{channel.Guild.Name}` server.**\n" +
$"Reason: {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); // temp solution; give time for a message to be send, fu volt
}
try
{
await usr.Kick().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync("Kicked user " + usr.Name + " Id: " + usr.Id).ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.MuteMembers)]
public async Task Mute(IMessage imsg, [Remainder] string throwaway)
{
var channel = imsg.Channel as IGuildChannel;
if (!e.Message.MentionedUsers.Any())
return;
try
{
foreach (var u in e.Message.MentionedUsers)
{
await u.Edit(isMuted: true).ConfigureAwait(false);
}
await imsg.Channel.SendMessageAsync("Mute successful").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("I most likely don't have the permission necessary for that.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Unmute(IMessage imsg, [Remainder] string throwaway)
{
var channel = imsg.Channel as IGuildChannel;
if (!e.Message.MentionedUsers.Any())
return;
try
{
foreach (var u in e.Message.MentionedUsers)
{
await u.Edit(isMuted: false).ConfigureAwait(false);
}
await imsg.Channel.SendMessageAsync("Unmute successful").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("I most likely don't have the permission necessary for that.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.DeafenMembers)]
public async Task Deafen(IMessage imsg, [Remainder] string throwaway)
{
var channel = imsg.Channel as IGuildChannel;
if (!e.Message.MentionedUsers.Any())
return;
try
{
foreach (var u in e.Message.MentionedUsers)
{
await u.Edit(isDeafened: true).ConfigureAwait(false);
}
await imsg.Channel.SendMessageAsync("Deafen successful").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("I most likely don't have the permission necessary for that.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.DeafenMembers)]
public async Task UnDeafen(IMessage imsg, [Remainder] string throwaway)
{
var channel = imsg.Channel as IGuildChannel;
if (!e.Message.MentionedUsers.Any())
return;
try
{
foreach (var u in e.Message.MentionedUsers)
{
await u.Edit(isDeafened: false).ConfigureAwait(false);
}
await imsg.Channel.SendMessageAsync("Undeafen successful").ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync("I most likely don't have the permission necessary for that.").ConfigureAwait(false);
}
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task DelVoiChanl(IMessage imsg, [Remainder] channelName)
{
var channel = imsg.Channel as IGuildChannel;
var ch = channel.Guild.FindChannels(channelName, ChannelType.Voice).FirstOrDefault();
if (ch == null)
return;
await ch.Delete().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Removed channel **{channelName}**.").ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task CreatVoiChanl(IMessage imsg, [Remainder] string channelName)
{
var channel = imsg.Channel as IGuildChannel;
await channel.Guild.CreateChannel(e.GetArg("channel_name"), ChannelType.Voice).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Created voice channel **{e.GetArg("channel_name")}**.").ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task DelTxtChanl(IMessage imsg, [Remainder] string channelName)
{
var channel = imsg.Channel as IGuildChannel;
var channel = channel.Guild.FindChannels(e.GetArg("channel_name"), ChannelType.Text).FirstOrDefault();
if (channel == null) return;
await channel.Delete().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Removed text channel **{e.GetArg("channel_name")}**.").ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)]
public async Task CreaTxtChanl(IMessage imsg, [Remainder] string arg)
{
var channel = imsg.Channel as IGuildChannel;
await channel.Guild.CreateChannel(e.GetArg("channel_name"), ChannelType.Text).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Added text channel **{e.GetArg("channel_name")}**.").ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)]
public async Task SetTopic(IMessage imsg, [Remainder] string arg)
{
var topic = e.GetArg("topic")?.Trim() ?? "";
await e.Channel.Edit(topic: topic).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync(":ok: **New channel topic set.**").ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)]
public async Task SetChanlName(IMessage imsg, [Remainder] string arg)
{
var channel = imsg.Channel as IGuildChannel;
var name = e.GetArg("name");
if (string.IsNullOrWhiteSpace(name))
return;
await e.Channel.Edit(name: name).ConfigureAwait(false);
await imsg.Channel.SendMessageAsync(":ok: **New channel name set.**").ConfigureAwait(false);
}
//todo maybe split into 3/4 different commands with the same name
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Prune(IMessage msg, [Remainder] string target = null)
{
var channel = msg.Channel as IGuildChannel;
var user = await channel.Guild.GetCurrentUserAsync();
if (string.IsNullOrWhiteSpace(target))
{
var enumerable = (await msg.Channel.GetMessagesAsync()).Where(x => x.Author.Id == user.Id);
await msg.Channel.DeleteMessagesAsync(enumerable);
return;
}
target = target.Trim();
if (!user.GetPermissions(channel).ManageMessages)
{
await msg.Reply("Don't have permissions to manage messages in channel");
return;
}
int count;
if (int.TryParse(target, out count))
{
while (count > 0)
{
int limit = (count < 100) ? count : 100;
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit));
await msg.Channel.DeleteMessagesAsync(enumerable);
await Task.Delay(1000); // there is a 1 per second per guild ratelimit for deletemessages
if (enumerable.Count < limit) break;
count -= limit;
}
}
else if (msg.MentionedUsers.Count > 0)
{
var toDel = new List<IMessage>();
var match = Regex.Match(target, @"\s(\d+)\s");
if (match.Success)
{
int.TryParse(match.Groups[1].Value, out count);
var messages = new List<IMessage>(count);
while (count > 0)
{
var toAdd = await msg.Channel.GetMessagesAsync(limit: count < 100 ? count : 100);
messages.AddRange(toAdd);
count -= toAdd.Count;
}
foreach (var mention in msg.MentionedUsers)
{
toDel.AddRange(messages.Where(m => m.Author.Id == mention.Id));
}
var messagesEnum = messages.AsEnumerable();
while (messagesEnum.Count() > 0)
{
await msg.Channel.DeleteMessagesAsync(messagesEnum.Take(100));
await Task.Delay(1000); // 1 second ratelimit
messagesEnum = messagesEnum.Skip(100);
}
}
}
}
//todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Die(IMessage imsg)
//{
// var channel = imsg.Channel as IGuildChannel;
// await imsg.Channel.SendMessageAsync("`Shutting down.`").ConfigureAwait(false);
// await Task.Delay(2000).ConfigureAwait(false);
// Environment.Exit(0);
//}
////todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Setname(IMessage imsg, [Remainder] string newName)
//{
// var channel = imsg.Channel as IGuildChannel;
//}
////todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task NewAvatar(IMessage imsg, [Remainder] string img)
//{
// var channel = imsg.Channel as IGuildChannel;
// if (string.IsNullOrWhiteSpace(e.GetArg("img")))
// return;
// // Gather user provided URL.
// var avatarAddress = e.GetArg("img");
// var imageStream = await SearchHelper.GetResponseStreamAsync(avatarAddress).ConfigureAwait(false);
// var image = System.Drawing.Image.FromStream(imageStream);
// await client.CurrentUser.Edit("", avatar: image.ToStream()).ConfigureAwait(false);
// // Send confirm.
// await imsg.Channel.SendMessageAsync("New avatar set.").ConfigureAwait(false);
//}
////todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task SetGame(IMessage imsg, [Remainder] string game)
//{
// var channel = imsg.Channel as IGuildChannel;
// game = game ?? "";
// client.SetGame(e.GetArg("set_game"));
//}
////todo owner only
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Send(IMessage imsg, string where, [Remainder] string msg)
//{
// var channel = imsg.Channel as IGuildChannel;
// if (string.IsNullOrWhiteSpace(msg))
// return;
// var ids = where.Split('|');
// if (ids.Length != 2)
// return;
// var sid = ulong.Parse(ids[0]);
// var server = NadekoBot.Client.Servers.Where(s => s.Id == sid).FirstOrDefault();
// if (server == null)
// return;
// if (ids[1].ToUpperInvariant().StartsWith("C:"))
// {
// var cid = ulong.Parse(ids[1].Substring(2));
// var channel = server.TextChannels.Where(c => c.Id == cid).FirstOrDefault();
// if (channel == null)
// {
// return;
// }
// await channel.SendMessage(msg);
// }
// else if (ids[1].ToUpperInvariant().StartsWith("U:"))
// {
// var uid = ulong.Parse(ids[1].Substring(2));
// var user = server.Users.Where(u => u.Id == uid).FirstOrDefault();
// if (user == null)
// {
// return;
// }
// await user.SendMessage(msg);
// }
// else
// {
// await imsg.Channel.SendMessageAsync("`Invalid format.`");
// }
//}
////todo owner only
////todo DB
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Donadd(IMessage imsg, IUser donator, int amount)
//{
// var channel = imsg.Channel as IGuildChannel;
// var donator = channel.Guild.FindUsers(e.GetArg("donator")).FirstOrDefault();
// var amount = int.Parse(e.GetArg("amount"));
// if (donator == null) return;
// try
// {
// DbHandler.Instance.Connection.Insert(new Donator
// {
// Amount = amount,
// UserName = donator.Name,
// UserId = (long)donator.Id
// });
// imsg.Channel.SendMessageAsync("Successfuly added a new donator. 👑").ConfigureAwait(false);
// }
// catch { }
//}
//todo owner only
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Announce(IMessage imsg, [Remainder] string message)
{
var channel = imsg.Channel as IGuildChannel;
foreach (var ch in NadekoBot.Client.Servers.Select(s => s.DefaultChannel))
{
await ch.SendMessage(e.GetArg("msg")).ConfigureAwait(false);
}
await imsg.Channel.SendMessageAsync(":ok:").ConfigureAwait(false);
}
//todo owner only
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task SaveChat(IMessage imsg, int cnt)
{
var channel = imsg.Channel as IGuildChannel;
ulong? lastmsgId = null;
var sb = new StringBuilder();
var msgs = new List<IMessage>(cnt);
while (cnt > 0)
{
var dlcnt = cnt < 100 ? cnt : 100;
var dledMsgs = await e.Channel.DownloadMessages(dlcnt, lastmsgId);
if (!dledMsgs.Any())
break;
msgs.AddRange(dledMsgs);
lastmsgId = msgs[msgs.Count - 1].Id;
cnt -= 100;
}
await e.User.SendFile($"Chatlog-{channel.Guild.Name}/#{e.Channel.Name}-{DateTime.Now}.txt",
JsonConvert.SerializeObject(new { Messages = msgs.Select(s => s.ToString()) }, Formatting.Indented).ToStream()).ConfigureAwait(false);
}
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.MentionEveryone)]
public async Task MentionRole(IMessage imsg, [Remainder] string roles)
{
var channel = imsg.Channel as IGuildChannel;
var arg = e.GetArg("roles").Split(',').Select(r => r.Trim());
string send = $"--{e.User.Mention} has invoked a mention on the following roles--";
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str)))
{
var role = channel.Guild.FindRoles(roleStr).FirstOrDefault();
if (role == null) continue;
send += $"\n`{role.Name}`\n";
send += string.Join(", ", role.Members.Select(r => r.Mention));
}
while (send.Length > 2000)
{
var curstr = send.Substring(0, 2000);
await
e.Channel.Send(curstr.Substring(0,
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
send.Substring(2000);
}
await e.Channel.Send(send).ConfigureAwait(false);
}
//todo DB
//[LocalizedCommand, LocalizedDescription, LocalizedSummary]
//[RequireContext(ContextType.Guild)]
//public async Task Donators(IMessage imsg)
//{
// var channel = imsg.Channel as IGuildChannel;
// var rows = DbHandler.Instance.GetAllRows<Donator>();
// var donatorsOrdered = rows.OrderByDescending(d => d.Amount);
// string str = $"**Thanks to the people listed below for making this project happen!**\n";
// await imsg.Channel.SendMessageAsync(str + string.Join("⭐", donatorsOrdered.Select(d => d.UserName))).ConfigureAwait(false);
//}
}
}

View File

@@ -0,0 +1,72 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Linq;
namespace NadekoBot.Modules.Administration.Commands
{
class AutoAssignRole : DiscordCommand
{
public AutoAssignRole(DiscordModule module) : base(module)
{
NadekoBot.Client.UserJoined += (s, e) =>
{
try
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var role = e.Server.Roles.Where(r => r.Id == config.AutoAssignedRole).FirstOrDefault();
if (role == null)
return;
e.User.AddRoles(role);
}
catch (Exception ex)
{
Console.WriteLine($"aar exception. {ex}");
}
};
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "autoassignrole")
.Alias(Module.Prefix + "aar")
.Description($"Automaticaly assigns a specified role to every user who joins the server. **Needs Manage Roles Permissions.** |`{Prefix}aar` to disable, `{Prefix}aar Role Name` to enable")
.Parameter("role", ParameterType.Unparsed)
.AddCheck(new SimpleCheckers.ManageRoles())
.Do(async e =>
{
if (!e.Server.CurrentUser.ServerPermissions.ManageRoles)
{
await imsg.Channel.SendMessageAsync("I do not have the permission to manage roles.").ConfigureAwait(false);
return;
}
var r = e.GetArg("role")?.Trim();
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (string.IsNullOrWhiteSpace(r)) //if role is not specified, disable
{
config.AutoAssignedRole = 0;
await imsg.Channel.SendMessageAsync("`Auto assign role on user join is now disabled.`").ConfigureAwait(false);
return;
}
var role = e.Server.FindRoles(r).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync("💢 `Role not found.`").ConfigureAwait(false);
return;
}
config.AutoAssignedRole = role.Id;
await imsg.Channel.SendMessageAsync("`Auto assigned role is set.`").ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,110 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
namespace NadekoBot.Modules.Administration.Commands
{
class CrossServerTextChannel : DiscordCommand
{
public CrossServerTextChannel(DiscordModule module) : base(module)
{
NadekoBot.Client.MessageReceived += async (s, e) =>
{
try
{
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
foreach (var subscriber in Subscribers)
{
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
{
if (e.After?.User?.Id == null || e.After.User.Id == NadekoBot.Client.CurrentUser.Id) return;
foreach (var subscriber in Subscribers)
{
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 { }
};
}
private string GetText(Server server, Channel channel, User user, Message message) =>
$"**{server.Name} | {channel.Name}** `{user.Name}`: " + message.RawText;
public static readonly ConcurrentDictionary<int, HashSet<Channel>> Subscribers = new ConcurrentDictionary<int, HashSet<Channel>>();
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "scsc")
.Description("Starts an instance of cross server channel. You will get a token as a DM " +
$"that other people will use to tune in to the same instance. **Bot Owner Only.** | `{Prefix}scsc`")
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var token = new Random().Next();
var set = new HashSet<Channel>();
if (Subscribers.TryAdd(token, set))
{
set.Add(e.Channel);
await e.User.SendMessage("This is your CSC token:" + token.ToString()).ConfigureAwait(false);
}
});
cgb.CreateCommand(Module.Prefix + "jcsc")
.Description($"Joins current channel to an instance of cross server channel using the token. **Needs Manage Server Permissions.**| `{Prefix}jcsc`")
.Parameter("token")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
int token;
if (!int.TryParse(e.GetArg("token"), out token))
return;
HashSet<Channel> set;
if (!Subscribers.TryGetValue(token, out set))
return;
set.Add(e.Channel);
await imsg.Channel.SendMessageAsync(":ok:").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "lcsc")
.Description($"Leaves Cross server channel instance from this channel. **Needs Manage Server Permissions.**| `{Prefix}lcsc`")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
foreach (var subscriber in Subscribers)
{
subscriber.Value.Remove(e.Channel);
}
await imsg.Channel.SendMessageAsync(":ok:").ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,225 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration.Commands
{
class CustomReactionsCommands : DiscordCommand
{
public CustomReactionsCommands(DiscordModule module) : base(module)
{
}
internal override void Init(CommandGroupBuilder cgb)
{
var Prefix = Module.Prefix;
cgb.CreateCommand(Prefix + "addcustreact")
.Alias(Prefix + "acr")
.Description($"Add a custom reaction. Guide here: <https://github.com/Kwoth/NadekoBot/wiki/Custom-Reactions> **Bot Owner Only!** | `{Prefix}acr \"hello\" I love saying hello to %user%`")
.AddCheck(SimpleCheckers.OwnerOnly())
.Parameter("name", ParameterType.Required)
.Parameter("message", ParameterType.Unparsed)
.Do(async e =>
{
var name = e.GetArg("name");
var message = e.GetArg("message")?.Trim();
if (string.IsNullOrWhiteSpace(message))
{
await imsg.Channel.SendMessageAsync($"Incorrect command usage. See -h {Prefix}acr for correct formatting").ConfigureAwait(false);
return;
}
if (NadekoBot.Config.CustomReactions.ContainsKey(name))
NadekoBot.Config.CustomReactions[name].Add(message);
else
NadekoBot.Config.CustomReactions.Add(name, new System.Collections.Generic.List<string>() { message });
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Added {name} : {message}").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "listcustreact")
.Alias(Prefix + "lcr")
.Description($"Lists custom reactions (paginated with 30 commands per page). Use 'all' instead of page number to get all custom reactions DM-ed to you. |`{Prefix}lcr 1`")
.Parameter("num", ParameterType.Required)
.Do(async e =>
{
var numStr = e.GetArg("num");
if (numStr.ToUpperInvariant() == "ALL")
{
var fullstr = String.Join("\n", NadekoBot.Config.CustomReactions.Select(kvp => kvp.Key));
do
{
var str = string.Concat(fullstr.Take(1900));
fullstr = new string(fullstr.Skip(1900).ToArray());
await e.User.SendMessage("```xl\n" + str + "```");
} while (fullstr.Length != 0);
return;
}
int num;
if (!int.TryParse(numStr, out num) || num <= 0) num = 1;
var cmds = GetCustomsOnPage(num - 1);
if (!cmds.Any())
{
await imsg.Channel.SendMessageAsync("`There are no custom reactions.`");
}
else
{
string result = SearchHelper.ShowInPrettyCode<string>(cmds, s => $"{s,-25}"); //People prefer starting with 1
await imsg.Channel.SendMessageAsync($"`Showing page {num}:`\n" + result).ConfigureAwait(false);
}
});
cgb.CreateCommand(Prefix + "showcustreact")
.Alias(Prefix + "scr")
.Description($"Shows all possible responses from a single custom reaction. |`{Prefix}scr %mention% bb`")
.Parameter("name", ParameterType.Unparsed)
.Do(async e =>
{
var name = e.GetArg("name")?.Trim();
if (string.IsNullOrWhiteSpace(name))
return;
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
{
await imsg.Channel.SendMessageAsync("`Can't find that custom reaction.`").ConfigureAwait(false);
return;
}
var items = NadekoBot.Config.CustomReactions[name];
var message = new StringBuilder($"Responses for {Format.Bold(name)}:\n");
var last = items.Last();
int i = 1;
foreach (var reaction in items)
{
message.AppendLine($"[{i++}] " + Format.Code(Format.Escape(reaction)));
}
await imsg.Channel.SendMessageAsync(message.ToString());
});
cgb.CreateCommand(Prefix + "editcustreact")
.Alias(Prefix + "ecr")
.Description($"Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `{Prefix}ecr \"%mention% disguise\" 2 Test 123`")
.Parameter("name", ParameterType.Required)
.Parameter("index", ParameterType.Required)
.Parameter("message", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var name = e.GetArg("name")?.Trim();
if (string.IsNullOrWhiteSpace(name))
return;
var indexstr = e.GetArg("index")?.Trim();
if (string.IsNullOrWhiteSpace(indexstr))
return;
var msg = e.GetArg("message")?.Trim();
if (string.IsNullOrWhiteSpace(msg))
return;
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
{
await imsg.Channel.SendMessageAsync("`Could not find given commandname`").ConfigureAwait(false);
return;
}
int index;
if (!int.TryParse(indexstr, out index) || index < 1 || index > NadekoBot.Config.CustomReactions[name].Count)
{
await imsg.Channel.SendMessageAsync("`Invalid index.`").ConfigureAwait(false);
return;
}
index = index - 1;
NadekoBot.Config.CustomReactions[name][index] = msg;
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "delcustreact")
.Alias(Prefix + "dcr")
.Description($"Deletes a custom reaction with given name (and index). **Bot Owner Only.**| `{Prefix}dcr index`")
.Parameter("name", ParameterType.Required)
.Parameter("index", ParameterType.Optional)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var name = e.GetArg("name")?.Trim();
if (string.IsNullOrWhiteSpace(name))
return;
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
{
await imsg.Channel.SendMessageAsync("Could not find given commandname").ConfigureAwait(false);
return;
}
string message = "";
int index;
if (int.TryParse(e.GetArg("index")?.Trim() ?? "", out index))
{
index = index - 1;
if (index < 0 || index > NadekoBot.Config.CustomReactions[name].Count)
{
await imsg.Channel.SendMessageAsync("Given index was out of range").ConfigureAwait(false);
return;
}
NadekoBot.Config.CustomReactions[name].RemoveAt(index);
if (!NadekoBot.Config.CustomReactions[name].Any())
{
NadekoBot.Config.CustomReactions.Remove(name);
}
message = $"Deleted response #{index + 1} from `{name}`";
}
else
{
NadekoBot.Config.CustomReactions.Remove(name);
message = $"Deleted custom reaction: `{name}`";
}
await Classes.JSONModels.ConfigHandler.SaveConfig().ConfigureAwait(false);
await imsg.Channel.SendMessageAsync(message).ConfigureAwait(false);
});
}
private readonly int ItemsPerPage = 30;
private IEnumerable<string> GetCustomsOnPage(int page)
{
var items = NadekoBot.Config.CustomReactions.Skip(page * ItemsPerPage).Take(ItemsPerPage);
if (!items.Any())
{
return Enumerable.Empty<string>();
}
return items.Select(kvp => kvp.Key);
/*
var message = new StringBuilder($"--- Custom reactions - page {page + 1} ---\n");
foreach (var cr in items)
{
message.Append($"{Format.Code(cr.Key)}\n");
int i = 1;
var last = cr.Value.Last();
foreach (var reaction in cr.Value)
{
if (last != reaction)
message.AppendLine(" `├" + i++ + "─`" + Format.Bold(reaction));
else
message.AppendLine(" `└" + i++ + "─`" + Format.Bold(reaction));
}
}
return message.ToString() + "\n";
*/
}
}
}
// zeta is a god
//├
//─
//│
//└

View File

@@ -0,0 +1,47 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.DataModels;
using NadekoBot.Modules.Permissions.Classes;
using System.IO;
using System.Linq;
namespace NadekoBot.Modules.Administration.Commands
{
internal class IncidentsCommands : DiscordCommand
{
public IncidentsCommands(DiscordModule module) : base(module) { }
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "listincidents")
.Alias(Prefix + "lin")
.Description($"List all UNREAD incidents and flags them as read. **Needs Manage Server Permissions.**| `{Prefix}lin`")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var sid = (long)e.Server.Id;
var incs = DbHandler.Instance.FindAll<Incident>(i => i.ServerId == sid && i.Read == false);
DbHandler.Instance.Connection.UpdateAll(incs.Select(i => { i.Read = true; return i; }));
await e.User.SendMessage(string.Join("\n----------------------", incs.Select(i => i.Text)));
});
cgb.CreateCommand(Module.Prefix + "listallincidents")
.Alias(Prefix + "lain")
.Description($"Sends you a file containing all incidents and flags them as read. **Needs Manage Server Permissions.**| `{Prefix}lain`")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var sid = (long)e.Server.Id;
var incs = DbHandler.Instance.FindAll<Incident>(i => i.ServerId == sid);
DbHandler.Instance.Connection.UpdateAll(incs.Select(i => { i.Read = true; return i; }));
var data = string.Join("\n----------------------\n", incs.Select(i => i.Text));
MemoryStream ms = new MemoryStream();
var sw = new StreamWriter(ms);
sw.WriteLine(data);
sw.Flush();
sw.BaseStream.Position = 0;
await e.User.SendFile("incidents.txt", sw.BaseStream);
});
}
}
}

View File

@@ -0,0 +1,483 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration.Commands
{
internal class LogCommand : DiscordCommand
{
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
private ConcurrentBag<KeyValuePair<Channel, string>> voicePresenceUpdates = new ConcurrentBag<KeyValuePair<Channel, string>>();
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) =>
{
if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
return;
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 imsg.Channel.SendMessageAsync($"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<Channel, string>();
//take everything from the queue and merge the messages which are going to the same channel
KeyValuePair<Channel, string> 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);
}
});
}
private async void ChannelUpdated(object sender, ChannelUpdatedEventArgs e)
{
try
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || config.LogserverIgnoreChannels.Contains(e.After.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (e.Before.Name != e.After.Name)
await ch.SendMessage($@"`{prettyCurrentTime}` **Channel Name Changed** `#{e.Before.Name}` (*{e.After.Id}*)
`New:` {e.After.Name}").ConfigureAwait(false);
else if (e.Before.Topic != e.After.Topic)
await ch.SendMessage($@"`{prettyCurrentTime}` **Channel Topic Changed** `#{e.After.Name}` (*{e.After.Id}*)
`Old:` {e.Before.Topic}
`New:` {e.After.Topic}").ConfigureAwait(false);
}
catch { }
}
private async void ChannelDestroyed(object sender, ChannelEventArgs e)
{
try
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || config.LogserverIgnoreChannels.Contains(e.Channel.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"❗`{prettyCurrentTime}`❗`Channel Deleted:` #{e.Channel.Name} (*{e.Channel.Id}*)").ConfigureAwait(false);
}
catch { }
}
private async void ChannelCreated(object sender, ChannelEventArgs e)
{
try
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || config.LogserverIgnoreChannels.Contains(e.Channel.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`🆕`Channel Created:` #{e.Channel.Mention} (*{e.Channel.Id}*)").ConfigureAwait(false);
}
catch { }
}
private async void UsrUnbanned(object sender, UserEventArgs e)
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`♻`User was unbanned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
catch { }
}
private async void UsrJoined(object sender, UserEventArgs e)
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`✅`User joined:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
catch { }
}
private async void UsrLeft(object sender, UserEventArgs e)
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`❗`User left:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
catch { }
}
private async void UsrBanned(object sender, UserEventArgs e)
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"❗`{prettyCurrentTime}`❌`User banned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
catch { }
}
private async void MsgRecivd(object sender, MessageEventArgs e)
{
try
{
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
return;
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || e.Channel.Id == chId || config.LogserverIgnoreChannels.Contains(e.Channel.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (!string.IsNullOrWhiteSpace(e.Message.Text))
{
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **New Message** `#{e.Channel.Name}`
👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Text.Unmention()}").ConfigureAwait(false);
}
else
{
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **File Uploaded** `#{e.Channel.Name}`
👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Attachments.FirstOrDefault()?.ProxyUrl}").ConfigureAwait(false);
}
}
catch { }
}
private async void MsgDltd(object sender, MessageEventArgs e)
{
try
{
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
return;
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || e.Channel.Id == chId || config.LogserverIgnoreChannels.Contains(e.Channel.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (!string.IsNullOrWhiteSpace(e.Message.Text))
{
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **Message** 🚮 `#{e.Channel.Name}`
👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Text.Unmention()}").ConfigureAwait(false);
}
else
{
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **File Deleted** `#{e.Channel.Name}`
👤`{e.User?.ToString() ?? ("NULL")}` {e.Message.Attachments.FirstOrDefault()?.ProxyUrl}").ConfigureAwait(false);
}
}
catch { }
}
private async void MsgUpdtd(object sender, MessageUpdatedEventArgs e)
{
try
{
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
return;
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var chId = config.LogServerChannel;
if (chId == null || e.Channel.Id == chId || config.LogserverIgnoreChannels.Contains(e.Channel.Id))
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
👤`{e.User?.ToString() ?? ("NULL")}`
`Old:` {e.Before.Text.Unmention()}
`New:` {e.After.Text.Unmention()}").ConfigureAwait(false);
}
catch { }
}
private async void UsrUpdtd(object sender, UserUpdatedEventArgs e)
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
try
{
var chId = config.LogPresenceChannel;
if (chId != null)
{
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) != null)
{
if (e.Before.Status != e.After.Status)
{
voicePresenceUpdates.Add(new KeyValuePair<Channel, string>(ch, $"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**."));
}
}
}
}
catch { }
try
{
ulong notifyChBeforeId;
ulong notifyChAfterId;
Channel notifyChBefore = null;
Channel notifyChAfter = null;
var beforeVch = e.Before.VoiceChannel;
var afterVch = e.After.VoiceChannel;
var notifyLeave = false;
var notifyJoin = false;
if ((beforeVch != null || afterVch != null) && (beforeVch != afterVch)) // this means we need to notify for sure.
{
if (beforeVch != null && config.VoiceChannelLog.TryGetValue(beforeVch.Id, out notifyChBeforeId) && (notifyChBefore = e.Before.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChBeforeId)) != null)
{
notifyLeave = true;
}
if (afterVch != null && config.VoiceChannelLog.TryGetValue(afterVch.Id, out notifyChAfterId) && (notifyChAfter = e.After.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChAfterId)) != null)
{
notifyJoin = true;
}
if ((notifyLeave && notifyJoin) && (notifyChAfter == notifyChBefore))
{
await notifyChAfter.SendMessage($"🎼`{prettyCurrentTime}` {e.Before.Name} moved from **{beforeVch.Mention}** to **{afterVch.Mention}** voice channel.").ConfigureAwait(false);
}
else if (notifyJoin)
{
await notifyChAfter.SendMessage($"🎼`{prettyCurrentTime}` {e.Before.Name} has joined **{afterVch.Mention}** voice channel.").ConfigureAwait(false);
}
else if (notifyLeave)
{
await notifyChBefore.SendMessage($"🎼`{prettyCurrentTime}` {e.Before.Name} has left **{beforeVch.Mention}** voice channel.").ConfigureAwait(false);
}
}
}
catch { }
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
string str = $"🕔`{prettyCurrentTime}`";
if (e.Before.Name != e.After.Name)
str += $"**Name Changed**👤`{e.Before?.ToString()}`\n\t\t`New:`{e.After.ToString()}`";
else if (e.Before.Nickname != e.After.Nickname)
str += $"**Nickname Changed**👤`{e.Before?.ToString()}`\n\t\t`Old:` {e.Before.Nickname}#{e.Before.Discriminator}\n\t\t`New:` {e.After.Nickname}#{e.After.Discriminator}";
else if (e.Before.AvatarUrl != e.After.AvatarUrl)
str += $"**Avatar Changed**👤`{e.Before?.ToString()}`\n\t {await e.Before.AvatarUrl.ShortenUrl()} `=>` {await e.After.AvatarUrl.ShortenUrl()}";
else if (!e.Before.Roles.SequenceEqual(e.After.Roles))
{
if (e.Before.Roles.Count() < e.After.Roles.Count())
{
var diffRoles = e.After.Roles.Where(r => !e.Before.Roles.Contains(r)).Select(r => "`" + r.Name + "`");
str += $"**User's Roles changed ⚔➕**👤`{e.Before?.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role.";
}
else if (e.Before.Roles.Count() > e.After.Roles.Count())
{
var diffRoles = e.Before.Roles.Where(r => !e.After.Roles.Contains(r)).Select(r => "`" + r.Name + "`");
str += $"**User's Roles changed ⚔➖**👤`{e.Before?.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role.";
}
else
{
Console.WriteLine("SEQUENCE NOT EQUAL BUT NO DIFF ROLES - REPORT TO KWOTH on #NADEKOLOG server");
return;
}
}
else
return;
await ch.SendMessage(str).ConfigureAwait(false);
}
catch { }
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "spmom")
.Description($"Toggles whether mentions of other offline users on your server will send a pm to them. **Needs Manage Server Permissions.**| `{Prefix}spmom`")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var specificConfig = SpecificConfigurations.Default.Of(e.Server.Id);
specificConfig.SendPrivateMessageOnMention =
!specificConfig.SendPrivateMessageOnMention;
if (specificConfig.SendPrivateMessageOnMention)
await imsg.Channel.SendMessageAsync(":ok: I will send private messages " +
"to mentioned offline users.").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync(":ok: I won't send private messages " +
"to mentioned offline users anymore.").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "logserver")
.Description($"Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!** | `{Prefix}logserver`")
.AddCheck(SimpleCheckers.OwnerOnly())
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
{
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = e.Channel.Id;
await imsg.Channel.SendMessageAsync($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false);
return;
}
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = null;
await imsg.Channel.SendMessageAsync($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "logignore")
.Description($"Toggles whether the {Prefix}logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Bot Owner Only!**| `{Prefix}logignore`")
.AddCheck(SimpleCheckers.OwnerOnly())
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (config.LogserverIgnoreChannels.Remove(e.Channel.Id))
{
await imsg.Channel.SendMessageAsync($"`{Prefix}logserver will stop ignoring this channel.`");
}
else
{
config.LogserverIgnoreChannels.Add(e.Channel.Id);
await imsg.Channel.SendMessageAsync($"`{Prefix}logserver will ignore this channel.`");
}
});
cgb.CreateCommand(Module.Prefix + "userpresence")
.Description($"Starts logging to this channel when someone from the server goes online/offline/idle. **Needs Manage Server Permissions.**| `{Prefix}userpresence`")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel;
if (chId == null)
{
SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = e.Channel.Id;
await imsg.Channel.SendMessageAsync($"**User presence notifications enabled.**").ConfigureAwait(false);
return;
}
SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = null;
await imsg.Channel.SendMessageAsync($"**User presence notifications disabled.**").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "voicepresence")
.Description($"Toggles logging to this channel whenever someone joins or leaves a voice channel you are in right now. **Needs Manage Server Permissions.**| `{Prefix}voicerpresence`")
.Parameter("all", ParameterType.Optional)
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (e.GetArg("all")?.ToLower() == "all")
{
foreach (var voiceChannel in e.Server.VoiceChannels)
{
config.VoiceChannelLog.TryAdd(voiceChannel.Id, e.Channel.Id);
}
await imsg.Channel.SendMessageAsync("Started logging user presence for **ALL** voice channels!").ConfigureAwait(false);
return;
}
if (e.User.VoiceChannel == null)
{
await imsg.Channel.SendMessageAsync("💢 You are not in a voice channel right now. If you are, please rejoin it.").ConfigureAwait(false);
return;
}
ulong throwaway;
if (!config.VoiceChannelLog.TryRemove(e.User.VoiceChannel.Id, out throwaway))
{
config.VoiceChannelLog.TryAdd(e.User.VoiceChannel.Id, e.Channel.Id);
await imsg.Channel.SendMessageAsync($"`Logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false);
}
else
await imsg.Channel.SendMessageAsync($"`Stopped logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,129 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Timers;
namespace NadekoBot.Modules.Administration.Commands
{
class MessageRepeater : DiscordCommand
{
private readonly ConcurrentDictionary<Server, Repeater> repeaters = new ConcurrentDictionary<Server, Repeater>();
private class Repeater
{
[Newtonsoft.Json.JsonIgnore]
public Timer MessageTimer { get; set; }
[Newtonsoft.Json.JsonIgnore]
public Channel RepeatingChannel { get; set; }
public ulong RepeatingServerId { get; set; }
public ulong RepeatingChannelId { get; set; }
public Message lastMessage { get; set; } = null;
public string RepeatingMessage { get; set; }
public int Interval { get; set; }
public Repeater Start()
{
MessageTimer = new Timer { Interval = Interval };
MessageTimer.Elapsed += async (s, e) => await Invoke();
return this;
}
public async Task Invoke()
{
var ch = RepeatingChannel;
var msg = RepeatingMessage;
if (ch != null && !string.IsNullOrWhiteSpace(msg))
{
try
{
if (lastMessage != null)
await lastMessage.Delete().ConfigureAwait(false);
}
catch { }
try
{
lastMessage = await ch.SendMessage(msg).ConfigureAwait(false);
}
catch { }
}
}
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "repeatinvoke")
.Alias(Module.Prefix + "repinv")
.Description($"Immediately shows the repeat message and restarts the timer. **Needs Manage Messages Permissions.**| `{Prefix}repinv`")
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e =>
{
Repeater rep;
if (!repeaters.TryGetValue(e.Server, out rep))
{
await imsg.Channel.SendMessageAsync("`No repeating message found on this server.`");
return;
}
await rep.Invoke();
});
cgb.CreateCommand(Module.Prefix + "repeat")
.Description("Repeat a message every X minutes. If no parameters are specified, " +
$"repeat is disabled. **Needs Manage Messages Permissions.** |`{Prefix}repeat 5 Hello there`")
.Parameter("minutes", ParameterType.Optional)
.Parameter("msg", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e =>
{
var minutesStr = e.GetArg("minutes");
var msg = e.GetArg("msg");
// if both null, disable
if (string.IsNullOrWhiteSpace(msg) && string.IsNullOrWhiteSpace(minutesStr))
{
Repeater rep;
if (!repeaters.TryRemove(e.Server, out rep))
return;
rep.MessageTimer.Stop();
await imsg.Channel.SendMessageAsync("Repeating disabled").ConfigureAwait(false);
return;
}
int minutes;
if (!int.TryParse(minutesStr, out minutes) || minutes < 1 || minutes > 1440)
{
await imsg.Channel.SendMessageAsync("Invalid value").ConfigureAwait(false);
return;
}
var repeater = repeaters.GetOrAdd(
e.Server,
s => new Repeater
{
Interval = minutes * 60 * 1000,
RepeatingChannel = e.Channel,
RepeatingChannelId = e.Channel.Id,
RepeatingServerId = e.Server.Id,
}.Start()
);
if (!string.IsNullOrWhiteSpace(msg))
repeater.RepeatingMessage = msg;
repeater.MessageTimer.Stop();
repeater.MessageTimer.Start();
await imsg.Channel.SendMessageAsync(String.Format("👌 Repeating `{0}` every " +
"**{1}** minutes on {2} channel.",
repeater.RepeatingMessage, minutes, repeater.RepeatingChannel))
.ConfigureAwait(false);
});
}
public MessageRepeater(DiscordModule module) : base(module) { }
}
}

View File

@@ -0,0 +1,167 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Classes.JSONModels;
using NadekoBot.Modules.Music;
using NadekoBot.Modules.Permissions.Classes;
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
{
internal class PlayingRotate : DiscordCommand
{
private static readonly Timer timer = new Timer(20000);
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
new Dictionary<string, Func<string>> {
{"%servers%", () => NadekoBot.Client.Servers.Count().ToString()},
{"%users%", () => NadekoBot.Client.Servers.SelectMany(s => s.Users).Count().ToString()},
{"%playing%", () => {
var cnt = MusicModule.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
if (cnt != 1) return cnt.ToString();
try {
var mp = MusicModule.MusicPlayers.FirstOrDefault();
return mp.Value.CurrentSong.SongInfo.Title;
}
catch {
return "No songs";
}
}
},
{"%queued%", () => MusicModule.MusicPlayers.Sum(kvp => kvp.Value.Playlist.Count).ToString()},
{"%trivia%", () => Games.Commands.TriviaCommands.RunningTrivias.Count.ToString()}
};
private readonly SemaphoreSlim playingPlaceholderLock = new SemaphoreSlim(1,1);
public PlayingRotate(DiscordModule module) : base(module)
{
var i = -1;
timer.Elapsed += async (s, e) =>
{
try
{
i++;
var status = "";
//wtf am i doing, just use a queue ffs
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{
if (PlayingPlaceholders.Count == 0
|| NadekoBot.Config.RotatingStatuses.Count == 0
|| i >= NadekoBot.Config.RotatingStatuses.Count)
{
i = 0;
}
status = NadekoBot.Config.RotatingStatuses[i];
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); });
}
catch { }
};
timer.Enabled = NadekoBot.Config.IsRotatingStatus;
}
public Func<CommandEventArgs, Task> DoFunc() => async e =>
{
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{
if (timer.Enabled)
timer.Stop();
else
timer.Start();
NadekoBot.Config.IsRotatingStatus = timer.Enabled;
await ConfigHandler.SaveConfig().ConfigureAwait(false);
}
finally {
playingPlaceholderLock.Release();
}
await imsg.Channel.SendMessageAsync($"❗`Rotating playing status has been {(timer.Enabled ? "enabled" : "disabled")}.`").ConfigureAwait(false);
};
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "rotateplaying")
.Alias(Module.Prefix + "ropl")
.Description($"Toggles rotation of playing status of the dynamic strings you specified earlier. **Bot Owner Only!** | `{Prefix}ropl`")
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(DoFunc());
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`")
.Parameter("text", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var arg = e.GetArg("text");
if (string.IsNullOrWhiteSpace(arg))
return;
await playingPlaceholderLock.WaitAsync().ConfigureAwait(false);
try
{
NadekoBot.Config.RotatingStatuses.Add(arg);
await ConfigHandler.SaveConfig();
}
finally
{
playingPlaceholderLock.Release();
}
await imsg.Channel.SendMessageAsync("🆗 `Added a new playing string.`").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "listplaying")
.Alias(Module.Prefix + "lipl")
.Description($"Lists all playing statuses with their corresponding number. **Bot Owner Only!**| `{Prefix}lipl`")
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
if (NadekoBot.Config.RotatingStatuses.Count == 0)
await imsg.Channel.SendMessageAsync("`There are no playing strings. " +
"Add some with .addplaying [text] command.`").ConfigureAwait(false);
var sb = new StringBuilder();
for (var i = 0; i < NadekoBot.Config.RotatingStatuses.Count; i++)
{
sb.AppendLine($"`{i + 1}.` {NadekoBot.Config.RotatingStatuses[i]}");
}
await imsg.Channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "removeplaying")
.Alias(Module.Prefix + "repl", Module.Prefix + "rmpl")
.Description($"Removes a playing string on a given number. **Bot Owner Only!**| `{Prefix}rmpl`")
.Parameter("number", ParameterType.Required)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var arg = e.GetArg("number");
int num;
string str;
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);
await ConfigHandler.SaveConfig().ConfigureAwait(false);
}
finally { playingPlaceholderLock.Release(); }
await imsg.Channel.SendMessageAsync($"🆗 `Removed playing string #{num}`({str})").ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,63 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
namespace NadekoBot.Modules.Administration.Commands
{
internal class RatelimitCommand : DiscordCommand
{
public static ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>> RatelimitingChannels = new ConcurrentDictionary<ulong, ConcurrentDictionary<ulong, DateTime>>();
private static readonly TimeSpan ratelimitTime = new TimeSpan(0, 0, 0, 5);
public RatelimitCommand(DiscordModule module) : base(module)
{
NadekoBot.Client.MessageReceived += async (s, e) =>
{
if (e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
return;
ConcurrentDictionary<ulong, DateTime> userTimePair;
if (!RatelimitingChannels.TryGetValue(e.Channel.Id, out userTimePair)) return;
DateTime lastMessageTime;
if (userTimePair.TryGetValue(e.User.Id, out lastMessageTime))
{
if (DateTime.Now - lastMessageTime < ratelimitTime)
{
try
{
await e.Message.Delete().ConfigureAwait(false);
}
catch { }
return;
}
}
userTimePair.AddOrUpdate(e.User.Id, id => DateTime.Now, (id, dt) => DateTime.Now);
};
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "slowmode")
.Description($"Toggles slow mode. When ON, users will be able to send only 1 message every 5 seconds. **Needs Manage Messages Permissions.**| `{Prefix}slowmode`")
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e =>
{
ConcurrentDictionary<ulong, DateTime> throwaway;
if (RatelimitingChannels.TryRemove(e.Channel.Id, out throwaway))
{
await imsg.Channel.SendMessageAsync("Slow mode disabled.").ConfigureAwait(false);
return;
}
if (RatelimitingChannels.TryAdd(e.Channel.Id, new ConcurrentDictionary<ulong, DateTime>()))
{
await imsg.Channel.SendMessageAsync("Slow mode initiated. " +
"Users can't send more than 1 message every 5 seconds.")
.ConfigureAwait(false);
}
});
}
}
}

View File

@@ -0,0 +1,207 @@
using Discord.Commands;
using Discord.Net;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration.Commands
{
internal class SelfAssignedRolesCommand : DiscordCommand
{
public SelfAssignedRolesCommand(DiscordModule module) : base(module) { }
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "asar")
.Description("Adds a role, or list of roles separated by whitespace" +
$"(use quotations for multiword roles) to the list of self-assignable roles. **Needs Manage Roles Permissions.**| `{Prefix}asar Gamer`")
.Parameter("roles", ParameterType.Multiple)
.AddCheck(SimpleCheckers.CanManageRoles)
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var msg = new StringBuilder();
foreach (var arg in e.Args)
{
var role = e.Server.FindRoles(arg.Trim()).FirstOrDefault();
if (role == null)
msg.AppendLine($":anger:Role **{arg}** not found.");
else
{
if (config.ListOfSelfAssignableRoles.Contains(role.Id))
{
msg.AppendLine($":anger:Role **{role.Name}** is already in the list.");
continue;
}
config.ListOfSelfAssignableRoles.Add(role.Id);
msg.AppendLine($":ok:Role **{role.Name}** added to the list.");
}
}
await imsg.Channel.SendMessageAsync(msg.ToString()).ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "rsar")
.Description($"Removes a specified role from the list of self-assignable roles. | `{Prefix}rsar`")
.Parameter("role", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.CanManageRoles)
.Do(async e =>
{
var roleName = e.GetArg("role")?.Trim();
if (string.IsNullOrWhiteSpace(roleName))
return;
var role = e.Server.FindRoles(roleName).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync(":anger:That role does not exist.").ConfigureAwait(false);
return;
}
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
{
await imsg.Channel.SendMessageAsync(":anger:That role is not self-assignable.").ConfigureAwait(false);
return;
}
config.ListOfSelfAssignableRoles.Remove(role.Id);
await imsg.Channel.SendMessageAsync($":ok:**{role.Name}** has been removed from the list of self-assignable roles").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "lsar")
.Description($"Lists all self-assignable roles. | `{Prefix}lsar`")
.Parameter("roles", ParameterType.Multiple)
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
var msg = new StringBuilder($"There are `{config.ListOfSelfAssignableRoles.Count}` self assignable roles:\n");
var toRemove = new HashSet<ulong>();
foreach (var roleId in config.ListOfSelfAssignableRoles.OrderBy(r => r.ToString()))
{
var role = e.Server.GetRole(roleId);
if (role == null)
{
msg.Append($"`{roleId} not found. Cleaned up.`, ");
toRemove.Add(roleId);
}
else
{
msg.Append($"**{role.Name}**, ");
}
}
foreach (var id in toRemove)
{
config.ListOfSelfAssignableRoles.Remove(id);
}
await imsg.Channel.SendMessageAsync(msg.ToString()).ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "togglexclsar").Alias(Module.Prefix + "tesar")
.Description($"toggle whether the self-assigned roles should be exclusive | `{Prefix}tesar`")
.AddCheck(SimpleCheckers.CanManageRoles)
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
string exl = config.ExclusiveSelfAssignedRoles ? "exclusive" : "not exclusive";
await imsg.Channel.SendMessageAsync("Self assigned roles are now " + exl);
});
cgb.CreateCommand(Module.Prefix + "iam")
.Description("Adds a role to you that you choose. " +
"Role must be on a list of self-assignable roles." +
$" | `{Prefix}iam Gamer`")
.Parameter("role", ParameterType.Unparsed)
.Do(async e =>
{
var roleName = e.GetArg("role")?.Trim();
if (string.IsNullOrWhiteSpace(roleName))
return;
var role = e.Server.FindRoles(roleName).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync(":anger:That role does not exist.").ConfigureAwait(false);
return;
}
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
{
await imsg.Channel.SendMessageAsync(":anger:That role is not self-assignable.").ConfigureAwait(false);
return;
}
if (e.User.HasRole(role))
{
await imsg.Channel.SendMessageAsync($":anger:You already have {role.Name} role.").ConfigureAwait(false);
return;
}
var sameRoles = e.User.Roles.Where(r => config.ListOfSelfAssignableRoles.Contains(r.Id));
if (config.ExclusiveSelfAssignedRoles && sameRoles.Any())
{
await imsg.Channel.SendMessageAsync($":anger:You already have {sameRoles.FirstOrDefault().Name} role.").ConfigureAwait(false);
return;
}
try
{
await e.User.AddRoles(role).ConfigureAwait(false);
}
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.InternalServerError)
{
}
catch (Exception ex)
{
await imsg.Channel.SendMessageAsync($":anger:`I am unable to add that role to you. I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
return;
}
var msg = await imsg.Channel.SendMessageAsync($":ok:You now have {role.Name} role.").ConfigureAwait(false);
await Task.Delay(3000).ConfigureAwait(false);
await msg.Delete().ConfigureAwait(false);
try
{
await e.Message.Delete().ConfigureAwait(false);
}
catch { }
});
cgb.CreateCommand(Module.Prefix + "iamnot")
.Alias(Module.Prefix + "iamn")
.Description("Removes a role to you that you choose. " +
"Role must be on a list of self-assignable roles." +
$" | `{Prefix}iamn Gamer`")
.Parameter("role", ParameterType.Unparsed)
.Do(async e =>
{
var roleName = e.GetArg("role")?.Trim();
if (string.IsNullOrWhiteSpace(roleName))
return;
var role = e.Server.FindRoles(roleName).FirstOrDefault();
if (role == null)
{
await imsg.Channel.SendMessageAsync(":anger:That role does not exist.").ConfigureAwait(false);
return;
}
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (!config.ListOfSelfAssignableRoles.Contains(role.Id))
{
await imsg.Channel.SendMessageAsync(":anger:That role is not self-assignable.").ConfigureAwait(false);
return;
}
if (!e.User.HasRole(role))
{
await imsg.Channel.SendMessageAsync($":anger:You don't have {role.Name} role.").ConfigureAwait(false);
return;
}
await e.User.RemoveRoles(role).ConfigureAwait(false);
var msg = await imsg.Channel.SendMessageAsync($":ok:Successfuly removed {role.Name} role from you.").ConfigureAwait(false);
await Task.Delay(3000).ConfigureAwait(false);
await msg.Delete().ConfigureAwait(false);
try
{
await e.Message.Delete().ConfigureAwait(false);
}
catch { }
});
}
}
}

View File

@@ -0,0 +1,42 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System.Linq;
namespace NadekoBot.Modules.Administration.Commands
{
class SelfCommands : DiscordCommand
{
public SelfCommands(DiscordModule module) : base(module)
{
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "leave")
.Description($"Makes Nadeko leave the server. Either name or id required. **Bot Owner Only!**| `{Prefix}leave 123123123331`")
.Parameter("arg", ParameterType.Required)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var arg = e.GetArg("arg").Trim();
var server = NadekoBot.Client.Servers.FirstOrDefault(s => s.Id.ToString() == arg) ??
NadekoBot.Client.FindServers(arg).FirstOrDefault();
if (server == null)
{
await imsg.Channel.SendMessageAsync("Cannot find that server").ConfigureAwait(false);
return;
}
if (!server.IsOwner)
{
await server.Leave().ConfigureAwait(false);
}
else
{
await server.Delete().ConfigureAwait(false);
}
await NadekoBot.SendMessageToOwner("Left server " + server.Name).ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,332 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
/* Voltana's legacy
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Factory.StartNew(valueFactory)) { }
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Factory.StartNew(() => taskFactory()).Unwrap()) { }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}
*/
namespace NadekoBot.Modules.Administration.Commands
{
internal class ServerGreetCommand : DiscordCommand
{
public static ConcurrentDictionary<ulong, AnnounceControls> AnnouncementsDictionary;
public static long Greeted = 0;
public ServerGreetCommand(DiscordModule module) : base(module)
{
AnnouncementsDictionary = new ConcurrentDictionary<ulong, AnnounceControls>();
NadekoBot.Client.UserJoined += UserJoined;
NadekoBot.Client.UserLeft += UserLeft;
var data = Classes.DbHandler.Instance.GetAllRows<DataModels.Announcement>();
if (!data.Any()) return;
foreach (var obj in data)
AnnouncementsDictionary.TryAdd((ulong)obj.ServerId, new AnnounceControls(obj));
}
private async void UserLeft(object sender, UserEventArgs e)
{
try
{
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) ||
!AnnouncementsDictionary[e.Server.Id].Bye) return;
var controls = AnnouncementsDictionary[e.Server.Id];
var channel = NadekoBot.Client.GetChannel(controls.ByeChannel);
var msg = controls.ByeText.Replace("%user%", "**" + e.User.Name + "**").Trim();
if (string.IsNullOrEmpty(msg))
return;
if (controls.ByePM)
{
Greeted++;
try
{
await e.User.SendMessage($"`Farewell Message From {e.Server?.Name}`\n" + msg).ConfigureAwait(false);
}
catch { }
}
else
{
if (channel == null) return;
Greeted++;
var toDelete = await channel.SendMessage(msg).ConfigureAwait(false);
if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages)
{
await Task.Delay(30000).ConfigureAwait(false); // 5 minutes
await toDelete.Delete().ConfigureAwait(false);
}
}
}
catch { }
}
private async void UserJoined(object sender, Discord.UserEventArgs e)
{
try
{
if (!AnnouncementsDictionary.ContainsKey(e.Server.Id) ||
!AnnouncementsDictionary[e.Server.Id].Greet) return;
var controls = AnnouncementsDictionary[e.Server.Id];
var channel = NadekoBot.Client.GetChannel(controls.GreetChannel);
var msg = controls.GreetText.Replace("%user%", e.User.Mention).Trim();
if (string.IsNullOrEmpty(msg))
return;
if (controls.GreetPM)
{
Greeted++;
await e.User.SendMessage($"`Welcome Message From {e.Server.Name}`\n" + msg).ConfigureAwait(false);
}
else
{
if (channel == null) return;
Greeted++;
var toDelete = await channel.SendMessage(msg).ConfigureAwait(false);
if (e.Server.CurrentUser.GetPermissions(channel).ManageMessages && controls.DeleteGreetMessages)
{
await Task.Delay(30000).ConfigureAwait(false); // 5 minutes
await toDelete.Delete().ConfigureAwait(false);
}
}
}
catch { }
}
public class AnnounceControls
{
private DataModels.Announcement _model { get; }
public bool Greet {
get { return _model.Greet; }
set { _model.Greet = value; Save(); }
}
public ulong GreetChannel {
get { return (ulong)_model.GreetChannelId; }
set { _model.GreetChannelId = (long)value; Save(); }
}
public bool GreetPM {
get { return _model.GreetPM; }
set { _model.GreetPM = value; Save(); }
}
public bool ByePM {
get { return _model.ByePM; }
set { _model.ByePM = value; Save(); }
}
public string GreetText {
get { return _model.GreetText; }
set { _model.GreetText = value; Save(); }
}
public bool Bye {
get { return _model.Bye; }
set { _model.Bye = value; Save(); }
}
public ulong ByeChannel {
get { return (ulong)_model.ByeChannelId; }
set { _model.ByeChannelId = (long)value; Save(); }
}
public string ByeText {
get { return _model.ByeText; }
set { _model.ByeText = value; Save(); }
}
public ulong ServerId {
get { return (ulong)_model.ServerId; }
set { _model.ServerId = (long)value; }
}
public bool DeleteGreetMessages {
get {
return _model.DeleteGreetMessages;
}
set {
_model.DeleteGreetMessages = value; Save();
}
}
public AnnounceControls(DataModels.Announcement model)
{
this._model = model;
}
public AnnounceControls(ulong serverId)
{
this._model = new DataModels.Announcement();
ServerId = serverId;
}
internal bool ToggleBye(ulong id)
{
if (Bye)
{
return Bye = false;
}
else
{
ByeChannel = id;
return Bye = true;
}
}
internal bool ToggleGreet(ulong id)
{
if (Greet)
{
return Greet = false;
}
else
{
GreetChannel = id;
return Greet = true;
}
}
internal bool ToggleDelete() => DeleteGreetMessages = !DeleteGreetMessages;
internal bool ToggleGreetPM() => GreetPM = !GreetPM;
internal bool ToggleByePM() => ByePM = !ByePM;
private void Save()
{
Classes.DbHandler.Instance.Save(_model);
}
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "grdel")
.Description($"Toggles automatic deletion of greet and bye messages. **Needs Manage Server Permissions.**| `{Prefix}grdel`")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleDelete())
await imsg.Channel.SendMessageAsync("`Automatic deletion of greet and bye messages has been enabled.`").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("`Automatic deletion of greet and bye messages has been disabled.`").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "greet")
.Description($"Toggles anouncements on the current channel when someone joins the server. **Needs Manage Server Permissions.**| `{Prefix}greet`")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleGreet(e.Channel.Id))
await imsg.Channel.SendMessageAsync("Greet announcements enabled on this channel.").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("Greet announcements disabled.").ConfigureAwait(false);
});
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%.`")
.Parameter("msg", ParameterType.Unparsed)
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (string.IsNullOrWhiteSpace(e.GetArg("msg")))
{
await imsg.Channel.SendMessageAsync("`Current greet message:` " + ann.GreetText);
return;
}
ann.GreetText = e.GetArg("msg");
await imsg.Channel.SendMessageAsync("New greet message set.").ConfigureAwait(false);
if (!ann.Greet)
await imsg.Channel.SendMessageAsync("Enable greet messsages by typing `.greet`").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "bye")
.Description($"Toggles anouncements on the current channel when someone leaves the server. | `{Prefix}bye`")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleBye(e.Channel.Id))
await imsg.Channel.SendMessageAsync("Bye announcements enabled on this channel.").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("Bye announcements disabled.").ConfigureAwait(false);
});
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.`")
.Parameter("msg", ParameterType.Unparsed)
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (string.IsNullOrWhiteSpace(e.GetArg("msg")))
{
await imsg.Channel.SendMessageAsync("`Current bye message:` " + ann.ByeText);
return;
}
ann.ByeText = e.GetArg("msg");
await imsg.Channel.SendMessageAsync("New bye message set.").ConfigureAwait(false);
if (!ann.Bye)
await imsg.Channel.SendMessageAsync("Enable bye messsages by typing `.bye`.").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "byepm")
.Description($"Toggles whether the good bye messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}byepm`")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleByePM())
await imsg.Channel.SendMessageAsync("Bye messages will be sent in a PM from now on.\n ⚠ Keep in mind this might fail if the user and the bot have no common servers after the user leaves.").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("Bye messages will be sent in a bound channel from now on.").ConfigureAwait(false);
if (!ann.Bye)
await imsg.Channel.SendMessageAsync("Enable bye messsages by typing `.bye`, and set the bye message using `.byemsg`").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "greetpm")
.Description($"Toggles whether the greet messages will be sent in a PM or in the text channel. **Needs Manage Server Permissions.**| `{Prefix}greetpm`")
.Do(async e =>
{
if (!e.User.ServerPermissions.ManageServer) return;
var ann = AnnouncementsDictionary.GetOrAdd(e.Server.Id, new AnnounceControls(e.Server.Id));
if (ann.ToggleGreetPM())
await imsg.Channel.SendMessageAsync("Greet messages will be sent in a PM from now on.").ConfigureAwait(false);
else
await imsg.Channel.SendMessageAsync("Greet messages will be sent in a bound channel from now on.").ConfigureAwait(false);
if (!ann.Greet)
await imsg.Channel.SendMessageAsync("Enable greet messsages by typing `.greet`, and set the greet message using `.greetmsg`").ConfigureAwait(false);
});
}
}
}

View File

@@ -0,0 +1,164 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ChPermOverride = Discord.ChannelPermissionOverrides;
namespace NadekoBot.Modules.Administration.Commands
{
internal class VoicePlusTextCommand : DiscordCommand
{
Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
public VoicePlusTextCommand(DiscordModule module) : base(module)
{
// changing servers may cause bugs
NadekoBot.Client.UserUpdated += async (sender, e) =>
{
try
{
if (e.Server == null)
return;
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (e.Before.VoiceChannel == e.After.VoiceChannel) return;
if (!config.VoicePlusTextEnabled)
return;
var serverPerms = e.Server.GetUser(NadekoBot.Client.CurrentUser.Id)?.ServerPermissions;
if (serverPerms == null)
return;
if (!serverPerms.Value.ManageChannels || !serverPerms.Value.ManageRoles)
{
try
{
await e.Server.Owner.SendMessage(
"I don't have manage server and/or Manage Channels permission," +
$" so I cannot run voice+text on **{e.Server.Name}** server.").ConfigureAwait(false);
}
catch { } // meh
config.VoicePlusTextEnabled = false;
return;
}
var beforeVch = e.Before.VoiceChannel;
if (beforeVch != null)
{
var textChannel =
e.Server.FindChannels(GetChannelName(beforeVch.Name), ChannelType.Text).FirstOrDefault();
if (textChannel != null)
await textChannel.AddPermissionsRule(e.Before,
new ChPermOverride(readMessages: PermValue.Deny,
sendMessages: PermValue.Deny)).ConfigureAwait(false);
}
var afterVch = e.After.VoiceChannel;
if (afterVch != null && e.Server.AFKChannel != afterVch)
{
var textChannel = e.Server.FindChannels(
GetChannelName(afterVch.Name),
ChannelType.Text)
.FirstOrDefault();
if (textChannel == null)
{
textChannel = (await e.Server.CreateChannel(GetChannelName(afterVch.Name), ChannelType.Text).ConfigureAwait(false));
await textChannel.AddPermissionsRule(e.Server.EveryoneRole,
new ChPermOverride(readMessages: PermValue.Deny,
sendMessages: PermValue.Deny)).ConfigureAwait(false);
}
await textChannel.AddPermissionsRule(e.After,
new ChPermOverride(readMessages: PermValue.Allow,
sendMessages: PermValue.Allow)).ConfigureAwait(false);
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
};
}
private string GetChannelName(string voiceName) =>
channelNameRegex.Replace(voiceName, "").Trim().Replace(" ", "-").TrimTo(90, true) + "-voice";
internal override void Init(CommandGroupBuilder cgb)
{
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`")
.AddCheck(SimpleCheckers.CanManageRoles)
.AddCheck(SimpleCheckers.ManageChannels())
.Do(async e =>
{
if (!e.Server.CurrentUser.ServerPermissions.ManageChannels)
{
await imsg.Channel.SendMessageAsync("`I have insufficient permission to do that.`");
return;
}
var allTxtChannels = e.Server.TextChannels.Where(c => c.Name.EndsWith("-voice"));
var validTxtChannelNames = e.Server.VoiceChannels.Select(c => GetChannelName(c.Name));
var invalidTxtChannels = allTxtChannels.Where(c => !validTxtChannelNames.Contains(c.Name));
foreach (var c in invalidTxtChannels)
{
try
{
await c.Delete();
}
catch { }
await Task.Delay(500);
}
await imsg.Channel.SendMessageAsync("`Done.`");
});
cgb.CreateCommand(Module.Prefix + "voice+text")
.Alias(Module.Prefix + "v+t")
.Description("Creates a text channel for each voice channel only users in that voice channel can see." +
$"If you are server owner, keep in mind you will see them all the time regardless. **Needs Manage Roles and Manage Channels Permissions.**| `{Prefix}voice+text`")
.AddCheck(SimpleCheckers.ManageChannels())
.AddCheck(SimpleCheckers.CanManageRoles)
.Do(async e =>
{
try
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (config.VoicePlusTextEnabled == true)
{
config.VoicePlusTextEnabled = false;
foreach (var textChannel in e.Server.TextChannels.Where(c => c.Name.EndsWith("-voice")))
{
try
{
await textChannel.Delete().ConfigureAwait(false);
}
catch
{
await imsg.Channel.SendMessageAsync(
":anger: Error: Most likely i don't have permissions to do this.")
.ConfigureAwait(false);
return;
}
}
await imsg.Channel.SendMessageAsync("Successfuly removed voice + text feature.").ConfigureAwait(false);
return;
}
config.VoicePlusTextEnabled = true;
await imsg.Channel.SendMessageAsync("Successfuly enabled voice + text feature. " +
"**Make sure the bot has manage roles and manage channels permissions**")
.ConfigureAwait(false);
}
catch (Exception ex)
{
await imsg.Channel.SendMessageAsync(ex.ToString()).ConfigureAwait(false);
}
});
}
}
}

View File

@@ -127,73 +127,6 @@ namespace NadekoBot.Modules.Utility
await msg.Reply("`List of roles:` \n• " + string.Join("\n• ", (msg.Channel as IGuildChannel).Guild.Roles.Except(new[] { guild.EveryoneRole })));
}
}
//todo maybe split into 3/4 different commands with the same name
[LocalizedCommand, LocalizedDescription, LocalizedSummary]
[RequireContext(ContextType.Guild)]
public async Task Prune(IMessage msg, [Remainder] string target = null)
{
var channel = msg.Channel as IGuildChannel;
var user = await channel.Guild.GetCurrentUserAsync();
if (string.IsNullOrWhiteSpace(target))
{
var enumerable = (await msg.Channel.GetMessagesAsync()).Where(x => x.Author.Id == user.Id);
await msg.Channel.DeleteMessagesAsync(enumerable);
return;
}
target = target.Trim();
if (!user.GetPermissions(channel).ManageMessages)
{
await msg.Reply("Don't have permissions to manage messages in channel");
return;
}
int count;
if (int.TryParse(target, out count))
{
while (count > 0)
{
int limit = (count < 100) ? count : 100;
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit));
await msg.Channel.DeleteMessagesAsync(enumerable);
await Task.Delay(1000); // there is a 1 per second per guild ratelimit for deletemessages
if (enumerable.Count < limit) break;
count -= limit;
}
}
else if (msg.MentionedUsers.Count > 0)
{
var toDel = new List<IMessage>();
var match = Regex.Match(target, @"\s(\d+)\s");
if (match.Success)
{
int.TryParse(match.Groups[1].Value, out count);
var messages = new List<IMessage>(count);
while (count > 0)
{
var toAdd = await msg.Channel.GetMessagesAsync(limit: count < 100 ? count : 100);
messages.AddRange(toAdd);
count -= toAdd.Count;
}
foreach (var mention in msg.MentionedUsers)
{
toDel.AddRange(messages.Where(m => m.Author.Id == mention.Id));
}
var messagesEnum = messages.AsEnumerable();
while (messagesEnum.Count() > 0)
{
await msg.Channel.DeleteMessagesAsync(messagesEnum.Take(100));
await Task.Delay(1000); // 1 second ratelimit
messagesEnum = messagesEnum.Skip(100);
}
}
}
}
}
}