176 lines
7.5 KiB
C#
176 lines
7.5 KiB
C#
using Discord;
|
|
using Discord.Commands;
|
|
using Discord.Commands.Permissions;
|
|
using NadekoBot.Classes.JSONModels;
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace NadekoBot.Modules.Permissions.Classes
|
|
{
|
|
|
|
internal class PermissionChecker : IPermissionChecker
|
|
{
|
|
public static PermissionChecker Instance { get; } = new PermissionChecker();
|
|
|
|
//key - sid:command
|
|
//value - userid
|
|
private ConcurrentDictionary<string, ulong> commandCooldowns = new ConcurrentDictionary<string, ulong>();
|
|
private HashSet<ulong> timeBlackList { get; } = new HashSet<ulong>();
|
|
|
|
static PermissionChecker() { }
|
|
private PermissionChecker()
|
|
{
|
|
Task.Run(async () =>
|
|
{
|
|
while (true)
|
|
{
|
|
//blacklist is cleared every 1.00 seconds. That is the most time anyone will be blocked
|
|
await Task.Delay(1000).ConfigureAwait(false);
|
|
timeBlackList.Clear();
|
|
}
|
|
});
|
|
}
|
|
|
|
public bool CanRun(Command command, User user, Channel channel, out string error)
|
|
{
|
|
error = String.Empty;
|
|
|
|
if (!NadekoBot.Ready)
|
|
return false;
|
|
|
|
if (channel.IsPrivate || channel.Server == null)
|
|
return command.Category == "Help";
|
|
|
|
if (ConfigHandler.IsUserBlacklisted(user.Id) ||
|
|
(!channel.IsPrivate &&
|
|
(ConfigHandler.IsServerBlacklisted(channel.Server.Id) || ConfigHandler.IsChannelBlacklisted(channel.Id))))
|
|
{
|
|
return false;
|
|
}
|
|
if (timeBlackList.Contains(user.Id))
|
|
return false;
|
|
|
|
if (!channel.IsPrivate && !channel.Server.CurrentUser.GetPermissions(channel).SendMessages)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
timeBlackList.Add(user.Id);
|
|
|
|
ServerPermissions perms;
|
|
PermissionsHandler.PermissionsDict.TryGetValue(user.Server.Id, out perms);
|
|
|
|
AddUserCooldown(user.Server.Id, user.Id, command.Text.ToLower());
|
|
if (commandCooldowns.Keys.Contains(user.Server.Id + ":" + command.Text.ToLower()))
|
|
{
|
|
if (perms?.Verbose == true)
|
|
error = $"{user.Mention} You have a cooldown on that command.";
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
//is it a permission command?
|
|
// if it is, check if the user has the correct role
|
|
// if yes return true, if no return false
|
|
if (command.Category == "Permissions")
|
|
{
|
|
Discord.Role role = null;
|
|
try
|
|
{
|
|
role = PermissionHelper.ValidateRole(user.Server,
|
|
PermissionsHandler.GetServerPermissionsRoleName(user.Server));
|
|
}
|
|
catch { }
|
|
if (user.Server.Owner.Id == user.Id || (role != null && user.HasRole(role)))
|
|
return true;
|
|
throw new Exception($"You don't have the necessary role (**{(perms?.PermissionsControllerRole ?? "Nadeko")}**) to change permissions.");
|
|
}
|
|
|
|
var permissionType = PermissionsHandler.GetPermissionBanType(command, user, channel);
|
|
|
|
string msg;
|
|
|
|
if (permissionType == PermissionsHandler.PermissionBanType.ServerBanModule &&
|
|
command.Category.ToLower() == "nsfw")
|
|
msg = $"**{command.Category}** module has been banned from use on this **server**.\nNSFW module is disabled by default. Server owner can type `;sm nsfw enable` to enable it.";
|
|
else
|
|
switch (permissionType)
|
|
{
|
|
case PermissionsHandler.PermissionBanType.None:
|
|
return true;
|
|
case PermissionsHandler.PermissionBanType.ServerBanCommand:
|
|
msg = $"**{command.Text}** command has been banned from use on this **server**.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanType.ServerBanModule:
|
|
msg = $"**{command.Category}** module has been banned from use on this **server**.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanType.ChannelBanCommand:
|
|
msg = $"**{command.Text}** command has been banned from use on this **channel**.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanType.ChannelBanModule:
|
|
msg = $"**{command.Category}** module has been banned from use on this **channel**.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanType.RoleBanCommand:
|
|
msg = $"You do not have a **role** which permits you the usage of **{command.Text}** command.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanType.RoleBanModule:
|
|
msg = $"You do not have a **role** which permits you the usage of **{command.Category}** module.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanTypimsg.AuthorBanCommand:
|
|
msg = $"{user.Mention}, You have been banned from using **{command.Text}** command.";
|
|
break;
|
|
case PermissionsHandler.PermissionBanTypimsg.AuthorBanModule:
|
|
msg = $"{user.Mention}, You have been banned from using **{command.Category}** module.";
|
|
break;
|
|
default:
|
|
return true;
|
|
}
|
|
if (PermissionsHandler.PermissionsDict[user.Server.Id].Verbose) //if verbose - print errors
|
|
error = msg;
|
|
return false;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"Exception in canrun: {ex}");
|
|
try
|
|
{
|
|
if (perms != null && perms.Verbose)
|
|
//if verbose - print errors
|
|
error = ex.Message;
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
Console.WriteLine($"SERIOUS PERMISSION ERROR {ex2}\n\nUser:{user} Server: {user?.Server?.Name}/{user?.Server?.Id}");
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public void AddUserCooldown(ulong serverId, ulong userId, string commandName)
|
|
{
|
|
commandCooldowns.TryAdd(commandName, userId);
|
|
var tosave = serverId + ":" + commandName;
|
|
Task.Run(async () =>
|
|
{
|
|
ServerPermissions perms;
|
|
PermissionsHandler.PermissionsDict.TryGetValue(serverId, out perms);
|
|
int cd;
|
|
if (!perms.CommandCooldowns.TryGetValue(commandName, out cd))
|
|
{
|
|
return;
|
|
}
|
|
if (commandCooldowns.TryAdd(tosave, userId))
|
|
{
|
|
await Task.Delay(cd * 1000);
|
|
ulong throwaway;
|
|
commandCooldowns.TryRemove(tosave, out throwaway);
|
|
}
|
|
|
|
});
|
|
}
|
|
}
|
|
}
|