mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Global usings and file scoped namespaces
This commit is contained in:
@@ -1,157 +1,153 @@
|
||||
using System;
|
||||
using Discord;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Common.TypeReaders;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Extensions;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions
|
||||
namespace NadekoBot.Modules.Permissions;
|
||||
|
||||
public partial class Permissions
|
||||
{
|
||||
public partial class Permissions
|
||||
[Group]
|
||||
public class BlacklistCommands : NadekoSubmodule<BlacklistService>
|
||||
{
|
||||
[Group]
|
||||
public class BlacklistCommands : NadekoSubmodule<BlacklistService>
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public BlacklistCommands(DiscordSocketClient client)
|
||||
{
|
||||
private readonly DiscordSocketClient _client;
|
||||
|
||||
public BlacklistCommands(DiscordSocketClient client)
|
||||
{
|
||||
_client = client;
|
||||
}
|
||||
_client = client;
|
||||
}
|
||||
|
||||
private async Task ListBlacklistInternal(string title, BlacklistType type, int page = 0)
|
||||
{
|
||||
if (page < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(page));
|
||||
private async Task ListBlacklistInternal(string title, BlacklistType type, int page = 0)
|
||||
{
|
||||
if (page < 0)
|
||||
throw new ArgumentOutOfRangeException(nameof(page));
|
||||
|
||||
var list = _service.GetBlacklist();
|
||||
var items = await list
|
||||
.Where(x => x.Type == type)
|
||||
.Select(async i =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return i.Type switch
|
||||
{
|
||||
BlacklistType.Channel => Format.Code(i.ItemId.ToString())
|
||||
+ " " + (_client.GetChannel(i.ItemId)?.ToString() ?? ""),
|
||||
BlacklistType.User => Format.Code(i.ItemId.ToString())
|
||||
+ " " +
|
||||
((await _client.Rest.GetUserAsync(i.ItemId))?.ToString() ?? ""),
|
||||
BlacklistType.Server => Format.Code(i.ItemId.ToString())
|
||||
+ " " + (_client.GetGuild(i.ItemId)?.ToString() ?? ""),
|
||||
_ => Format.Code(i.ItemId.ToString())
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warning("Can't get {BlacklistType} [{BlacklistItemId}]", i.Type, i.ItemId);
|
||||
return Format.Code(i.ItemId.ToString());
|
||||
}
|
||||
})
|
||||
.WhenAll();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page, (int curPage) =>
|
||||
var list = _service.GetBlacklist();
|
||||
var items = await list
|
||||
.Where(x => x.Type == type)
|
||||
.Select(async i =>
|
||||
{
|
||||
var pageItems = items
|
||||
.Skip(10 * curPage)
|
||||
.Take(10)
|
||||
.ToList();
|
||||
|
||||
if (pageItems.Count == 0)
|
||||
try
|
||||
{
|
||||
return _eb.Create()
|
||||
.WithOkColor()
|
||||
.WithTitle(title)
|
||||
.WithDescription(GetText(strs.empty_page));
|
||||
return i.Type switch
|
||||
{
|
||||
BlacklistType.Channel => Format.Code(i.ItemId.ToString())
|
||||
+ " " + (_client.GetChannel(i.ItemId)?.ToString() ?? ""),
|
||||
BlacklistType.User => Format.Code(i.ItemId.ToString())
|
||||
+ " " +
|
||||
((await _client.Rest.GetUserAsync(i.ItemId))?.ToString() ?? ""),
|
||||
BlacklistType.Server => Format.Code(i.ItemId.ToString())
|
||||
+ " " + (_client.GetGuild(i.ItemId)?.ToString() ?? ""),
|
||||
_ => Format.Code(i.ItemId.ToString())
|
||||
};
|
||||
}
|
||||
catch
|
||||
{
|
||||
Log.Warning("Can't get {BlacklistType} [{BlacklistItemId}]", i.Type, i.ItemId);
|
||||
return Format.Code(i.ItemId.ToString());
|
||||
}
|
||||
})
|
||||
.WhenAll();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page, (int curPage) =>
|
||||
{
|
||||
var pageItems = items
|
||||
.Skip(10 * curPage)
|
||||
.Take(10)
|
||||
.ToList();
|
||||
|
||||
if (pageItems.Count == 0)
|
||||
{
|
||||
return _eb.Create()
|
||||
.WithOkColor()
|
||||
.WithTitle(title)
|
||||
.WithDescription(pageItems.JoinWith('\n'))
|
||||
.WithOkColor();
|
||||
}, items.Length, 10);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_users), BlacklistType.User, page);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ChannelBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_channels), BlacklistType.Channel, page);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_servers), BlacklistType.Server, page);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.User);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(AddRemove action, IUser usr)
|
||||
=> Blacklist(action, usr.Id, BlacklistType.User);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ChannelBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.Channel);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.Server);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(AddRemove action, IGuild guild)
|
||||
=> Blacklist(action, guild.Id, BlacklistType.Server);
|
||||
|
||||
private async Task Blacklist(AddRemove action, ulong id, BlacklistType type)
|
||||
{
|
||||
if (action == AddRemove.Add)
|
||||
{
|
||||
_service.Blacklist(type, id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.UnBlacklist(type, id);
|
||||
.WithDescription(GetText(strs.empty_page));
|
||||
}
|
||||
|
||||
return _eb.Create()
|
||||
.WithTitle(title)
|
||||
.WithDescription(pageItems.JoinWith('\n'))
|
||||
.WithOkColor();
|
||||
}, items.Length, 10);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_users), BlacklistType.User, page);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ChannelBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_channels), BlacklistType.Channel, page);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(int page = 1)
|
||||
{
|
||||
if (--page < 0)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return ListBlacklistInternal(GetText(strs.blacklisted_servers), BlacklistType.Server, page);
|
||||
}
|
||||
|
||||
if (action == AddRemove.Add)
|
||||
await ReplyConfirmLocalizedAsync(strs.blacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())));
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.unblacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())));
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.User);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task UserBlacklist(AddRemove action, IUser usr)
|
||||
=> Blacklist(action, usr.Id, BlacklistType.User);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ChannelBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.Channel);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(AddRemove action, ulong id)
|
||||
=> Blacklist(action, id, BlacklistType.Server);
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public Task ServerBlacklist(AddRemove action, IGuild guild)
|
||||
=> Blacklist(action, guild.Id, BlacklistType.Server);
|
||||
|
||||
private async Task Blacklist(AddRemove action, ulong id, BlacklistType type)
|
||||
{
|
||||
if (action == AddRemove.Add)
|
||||
{
|
||||
_service.Blacklist(type, id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.UnBlacklist(type, id);
|
||||
}
|
||||
|
||||
if (action == AddRemove.Add)
|
||||
await ReplyConfirmLocalizedAsync(strs.blacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())));
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.unblacklisted(Format.Code(type.ToString()),
|
||||
Format.Code(id.ToString())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,95 +5,92 @@ using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Common.TypeReaders;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions
|
||||
namespace NadekoBot.Modules.Permissions;
|
||||
|
||||
public partial class Permissions
|
||||
{
|
||||
public partial class Permissions
|
||||
[Group]
|
||||
public class CmdCdsCommands : NadekoSubmodule
|
||||
{
|
||||
[Group]
|
||||
public class CmdCdsCommands : NadekoSubmodule
|
||||
private readonly DbService _db;
|
||||
private readonly CmdCdService _service;
|
||||
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns
|
||||
=> _service.CommandCooldowns;
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns
|
||||
=> _service.ActiveCooldowns;
|
||||
|
||||
public CmdCdsCommands(CmdCdService service, DbService db)
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly CmdCdService _service;
|
||||
_service = service;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns
|
||||
=> _service.CommandCooldowns;
|
||||
private ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns
|
||||
=> _service.ActiveCooldowns;
|
||||
|
||||
public CmdCdsCommands(CmdCdService service, DbService db)
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task CmdCooldown(CommandOrCrInfo command, int secs)
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
if (secs < 0 || secs > 3600)
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
await ReplyErrorLocalizedAsync(strs.invalid_second_param_between(0, 3600));
|
||||
return;
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task CmdCooldown(CommandOrCrInfo command, int secs)
|
||||
var name = command.Name.ToLowerInvariant();
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
if (secs < 0 || secs > 3600)
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.invalid_second_param_between(0, 3600));
|
||||
return;
|
||||
}
|
||||
|
||||
var name = command.Name.ToLowerInvariant();
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.CommandCooldowns));
|
||||
var localSet = CommandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||
|
||||
var toDelete = config.CommandCooldowns.FirstOrDefault(cc => cc.CommandName == name);
|
||||
if (toDelete != null)
|
||||
uow.Set<CommandCooldown>().Remove(toDelete);
|
||||
localSet.RemoveWhere(cc => cc.CommandName == name);
|
||||
if (secs != 0)
|
||||
{
|
||||
var cc = new CommandCooldown()
|
||||
{
|
||||
CommandName = name,
|
||||
Seconds = secs,
|
||||
};
|
||||
config.CommandCooldowns.Add(cc);
|
||||
localSet.Add(cc);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
if (secs == 0)
|
||||
{
|
||||
var activeCds = ActiveCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||
activeCds.RemoveWhere(ac => ac.Command == name);
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_cleared(Format.Bold(name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_add(
|
||||
Format.Bold(name),
|
||||
Format.Bold(secs.ToString())));
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task AllCmdCooldowns()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.CommandCooldowns));
|
||||
var localSet = CommandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||
|
||||
if (!localSet.Any())
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_none).ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText(strs.sec)), s => $"{s,-30}", 2).ConfigureAwait(false);
|
||||
var toDelete = config.CommandCooldowns.FirstOrDefault(cc => cc.CommandName == name);
|
||||
if (toDelete != null)
|
||||
uow.Set<CommandCooldown>().Remove(toDelete);
|
||||
localSet.RemoveWhere(cc => cc.CommandName == name);
|
||||
if (secs != 0)
|
||||
{
|
||||
var cc = new CommandCooldown()
|
||||
{
|
||||
CommandName = name,
|
||||
Seconds = secs,
|
||||
};
|
||||
config.CommandCooldowns.Add(cc);
|
||||
localSet.Add(cc);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
if (secs == 0)
|
||||
{
|
||||
var activeCds = ActiveCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||
activeCds.RemoveWhere(ac => ac.Command == name);
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_cleared(Format.Bold(name)));
|
||||
}
|
||||
else
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_add(
|
||||
Format.Bold(name),
|
||||
Format.Bold(secs.ToString())));
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task AllCmdCooldowns()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
var localSet = CommandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||
|
||||
if (!localSet.Any())
|
||||
await ReplyConfirmLocalizedAsync(strs.cmdcd_none).ConfigureAwait(false);
|
||||
else
|
||||
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + GetText(strs.sec)), s => $"{s,-30}", 2).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,11 +1,10 @@
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Common
|
||||
namespace NadekoBot.Modules.Permissions.Common;
|
||||
|
||||
public class PermissionCache
|
||||
{
|
||||
public class PermissionCache
|
||||
{
|
||||
public string PermRole { get; set; }
|
||||
public bool Verbose { get; set; } = true;
|
||||
public PermissionsCollection<Permissionv2> Permissions { get; set; }
|
||||
}
|
||||
}
|
||||
public string PermRole { get; set; }
|
||||
public bool Verbose { get; set; } = true;
|
||||
public PermissionsCollection<Permissionv2> Permissions { get; set; }
|
||||
}
|
@@ -1,125 +1,122 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Common
|
||||
namespace NadekoBot.Modules.Permissions.Common;
|
||||
|
||||
public static class PermissionExtensions
|
||||
{
|
||||
public static class PermissionExtensions
|
||||
public static bool CheckPermissions(this IEnumerable<Permissionv2> permsEnumerable, IUserMessage message,
|
||||
string commandName, string moduleName, out int permIndex)
|
||||
{
|
||||
public static bool CheckPermissions(this IEnumerable<Permissionv2> permsEnumerable, IUserMessage message,
|
||||
string commandName, string moduleName, out int permIndex)
|
||||
var perms = permsEnumerable as List<Permissionv2> ?? permsEnumerable.ToList();
|
||||
|
||||
for (int i = perms.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var perms = permsEnumerable as List<Permissionv2> ?? permsEnumerable.ToList();
|
||||
var perm = perms[i];
|
||||
|
||||
for (int i = perms.Count - 1; i >= 0; i--)
|
||||
var result = perm.CheckPermission(message, commandName, moduleName);
|
||||
|
||||
if (result is null)
|
||||
{
|
||||
var perm = perms[i];
|
||||
|
||||
var result = perm.CheckPermission(message, commandName, moduleName);
|
||||
|
||||
if (result is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
permIndex = i;
|
||||
return result.Value;
|
||||
continue;
|
||||
}
|
||||
permIndex = -1; //defaut behaviour
|
||||
return true;
|
||||
}
|
||||
|
||||
//null = not applicable
|
||||
//true = applicable, allowed
|
||||
//false = applicable, not allowed
|
||||
public static bool? CheckPermission(this Permissionv2 perm, IUserMessage message, string commandName, string moduleName)
|
||||
{
|
||||
if (!((perm.SecondaryTarget == SecondaryPermissionType.Command &&
|
||||
perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) ||
|
||||
(perm.SecondaryTarget == SecondaryPermissionType.Module &&
|
||||
perm.SecondaryTargetName.ToLowerInvariant() == moduleName.ToLowerInvariant()) ||
|
||||
perm.SecondaryTarget == SecondaryPermissionType.AllModules))
|
||||
return null;
|
||||
|
||||
var guildUser = message.Author as IGuildUser;
|
||||
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
if (perm.PrimaryTargetId == message.Author.Id)
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
if (perm.PrimaryTargetId == message.Channel.Id)
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
if (guildUser is null)
|
||||
break;
|
||||
if (guildUser.RoleIds.Contains(perm.PrimaryTargetId))
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
if (guildUser is null)
|
||||
break;
|
||||
return perm.State;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetCommand(this Permissionv2 perm, string prefix, SocketGuild guild = null)
|
||||
{
|
||||
var com = "";
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
com += "u";
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
com += "c";
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
com += "r";
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
com += "s";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (perm.SecondaryTarget)
|
||||
{
|
||||
case SecondaryPermissionType.Module:
|
||||
com += "m";
|
||||
break;
|
||||
case SecondaryPermissionType.Command:
|
||||
com += "c";
|
||||
break;
|
||||
case SecondaryPermissionType.AllModules:
|
||||
com = "a" + com + "m";
|
||||
break;
|
||||
}
|
||||
|
||||
var secName = perm.SecondaryTarget == SecondaryPermissionType.Command && !perm.IsCustomCommand ?
|
||||
prefix + perm.SecondaryTargetName : perm.SecondaryTargetName;
|
||||
com += " " + (perm.SecondaryTargetName != "*" ? secName + " " : "") + (perm.State ? "enable" : "disable") + " ";
|
||||
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
com += guild?.GetUser(perm.PrimaryTargetId)?.ToString() ?? $"<@{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
com += $"<#{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
com += guild?.GetRole(perm.PrimaryTargetId)?.ToString() ?? $"<@&{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
break;
|
||||
}
|
||||
|
||||
return prefix + com;
|
||||
permIndex = i;
|
||||
return result.Value;
|
||||
}
|
||||
permIndex = -1; //defaut behaviour
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//null = not applicable
|
||||
//true = applicable, allowed
|
||||
//false = applicable, not allowed
|
||||
public static bool? CheckPermission(this Permissionv2 perm, IUserMessage message, string commandName, string moduleName)
|
||||
{
|
||||
if (!((perm.SecondaryTarget == SecondaryPermissionType.Command &&
|
||||
perm.SecondaryTargetName.ToLowerInvariant() == commandName.ToLowerInvariant()) ||
|
||||
(perm.SecondaryTarget == SecondaryPermissionType.Module &&
|
||||
perm.SecondaryTargetName.ToLowerInvariant() == moduleName.ToLowerInvariant()) ||
|
||||
perm.SecondaryTarget == SecondaryPermissionType.AllModules))
|
||||
return null;
|
||||
|
||||
var guildUser = message.Author as IGuildUser;
|
||||
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
if (perm.PrimaryTargetId == message.Author.Id)
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
if (perm.PrimaryTargetId == message.Channel.Id)
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
if (guildUser is null)
|
||||
break;
|
||||
if (guildUser.RoleIds.Contains(perm.PrimaryTargetId))
|
||||
return perm.State;
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
if (guildUser is null)
|
||||
break;
|
||||
return perm.State;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetCommand(this Permissionv2 perm, string prefix, SocketGuild guild = null)
|
||||
{
|
||||
var com = "";
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
com += "u";
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
com += "c";
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
com += "r";
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
com += "s";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (perm.SecondaryTarget)
|
||||
{
|
||||
case SecondaryPermissionType.Module:
|
||||
com += "m";
|
||||
break;
|
||||
case SecondaryPermissionType.Command:
|
||||
com += "c";
|
||||
break;
|
||||
case SecondaryPermissionType.AllModules:
|
||||
com = "a" + com + "m";
|
||||
break;
|
||||
}
|
||||
|
||||
var secName = perm.SecondaryTarget == SecondaryPermissionType.Command && !perm.IsCustomCommand ?
|
||||
prefix + perm.SecondaryTargetName : perm.SecondaryTargetName;
|
||||
com += " " + (perm.SecondaryTargetName != "*" ? secName + " " : "") + (perm.State ? "enable" : "disable") + " ";
|
||||
|
||||
switch (perm.PrimaryTarget)
|
||||
{
|
||||
case PrimaryPermissionType.User:
|
||||
com += guild?.GetUser(perm.PrimaryTargetId)?.ToString() ?? $"<@{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Channel:
|
||||
com += $"<#{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Role:
|
||||
com += guild?.GetRole(perm.PrimaryTargetId)?.ToString() ?? $"<@&{perm.PrimaryTargetId}>";
|
||||
break;
|
||||
case PrimaryPermissionType.Server:
|
||||
break;
|
||||
}
|
||||
|
||||
return prefix + com;
|
||||
}
|
||||
}
|
@@ -1,74 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Common
|
||||
namespace NadekoBot.Modules.Permissions.Common;
|
||||
|
||||
public class PermissionsCollection<T> : IndexedCollection<T> where T : class, IIndexed
|
||||
{
|
||||
public class PermissionsCollection<T> : IndexedCollection<T> where T : class, IIndexed
|
||||
private readonly object _localLocker = new object();
|
||||
public PermissionsCollection(IEnumerable<T> source) : base(source)
|
||||
{
|
||||
private readonly object _localLocker = new object();
|
||||
public PermissionsCollection(IEnumerable<T> source) : base(source)
|
||||
}
|
||||
|
||||
public static implicit operator List<T>(PermissionsCollection<T> x) =>
|
||||
x.Source;
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
}
|
||||
|
||||
public static implicit operator List<T>(PermissionsCollection<T> x) =>
|
||||
x.Source;
|
||||
|
||||
public override void Clear()
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
var first = Source[0];
|
||||
base.Clear();
|
||||
Source[0] = first;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Remove(T item)
|
||||
{
|
||||
bool removed;
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(Source.IndexOf(item) == 0)
|
||||
throw new ArgumentException("You can't remove first permsission (allow all)");
|
||||
removed = base.Remove(item);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
public override void Insert(int index, T item)
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // can't insert on first place. Last item is always allow all.
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
base.Insert(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveAt(int index)
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // you can't remove first permission (allow all)
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
|
||||
base.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public override T this[int index] {
|
||||
get => Source[index];
|
||||
set {
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // can't set first element. It's always allow all
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
base[index] = value;
|
||||
}
|
||||
}
|
||||
var first = Source[0];
|
||||
base.Clear();
|
||||
Source[0] = first;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public override bool Remove(T item)
|
||||
{
|
||||
bool removed;
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(Source.IndexOf(item) == 0)
|
||||
throw new ArgumentException("You can't remove first permsission (allow all)");
|
||||
removed = base.Remove(item);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
public override void Insert(int index, T item)
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // can't insert on first place. Last item is always allow all.
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
base.Insert(index, item);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RemoveAt(int index)
|
||||
{
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // you can't remove first permission (allow all)
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
|
||||
base.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
public override T this[int index] {
|
||||
get => Source[index];
|
||||
set {
|
||||
lock (_localLocker)
|
||||
{
|
||||
if(index == 0) // can't set first element. It's always allow all
|
||||
throw new IndexOutOfRangeException(nameof(index));
|
||||
base[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,296 +3,293 @@ using Discord.Commands;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions
|
||||
namespace NadekoBot.Modules.Permissions;
|
||||
|
||||
public partial class Permissions
|
||||
{
|
||||
public partial class Permissions
|
||||
[Group]
|
||||
public class FilterCommands : NadekoSubmodule<FilterService>
|
||||
{
|
||||
[Group]
|
||||
public class FilterCommands : NadekoSubmodule<FilterService>
|
||||
private readonly DbService _db;
|
||||
|
||||
public FilterCommands(DbService db)
|
||||
{
|
||||
private readonly DbService _db;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public FilterCommands(DbService db)
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task FwClear()
|
||||
{
|
||||
_service.ClearFilteredWords(ctx.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.fw_cleared).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterInv()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
_db = db;
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterInvites = !config.FilterInvites;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task FwClear()
|
||||
if (enabled)
|
||||
{
|
||||
_service.ClearFilteredWords(ctx.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.fw_cleared).ConfigureAwait(false);
|
||||
_service.InviteFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterInv()
|
||||
else
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterInvites = !config.FilterInvites;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_service.InviteFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.InviteFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterInv()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterInvitesChannelIds));
|
||||
var match = new FilterChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterInvitesChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterInvitesChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.InviteFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.InviteFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterLin()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterLinks = !config.FilterLinks;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_service.LinkFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.LinkFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterLin()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterLinksChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterLinksChannelIds));
|
||||
var match = new FilterLinksChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterLinksChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterLinksChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.LinkFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.LinkFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterWords()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterWords = !config.FilterWords;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_service.WordFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.WordFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterWords()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterWordsChannelIds));
|
||||
|
||||
var match = new FilterChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterWordsChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterWordsChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.WordFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.WordFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task FilterWord([Leftover] string word)
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
word = word?.Trim().ToLowerInvariant();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(word))
|
||||
return;
|
||||
|
||||
FilteredWord removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilteredWords));
|
||||
|
||||
removed = config.FilteredWords.FirstOrDefault(fw => fw.Word.Trim().ToLowerInvariant() == word);
|
||||
|
||||
if (removed is null)
|
||||
config.FilteredWords.Add(new FilteredWord() { Word = word });
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var filteredWords = _service.ServerFilteredWords.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<string>());
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
filteredWords.Add(word);
|
||||
await ReplyConfirmLocalizedAsync(strs.filter_word_add(Format.Code(word))).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredWords.TryRemove(word);
|
||||
await ReplyConfirmLocalizedAsync(strs.filter_word_remove(Format.Code(word))).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task LstFilterWords(int page = 1)
|
||||
{
|
||||
page--;
|
||||
if (page < 0)
|
||||
return;
|
||||
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
_service.ServerFilteredWords.TryGetValue(channel.Guild.Id, out var fwHash);
|
||||
|
||||
var fws = fwHash.ToArray();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
(curPage) => _eb.Create()
|
||||
.WithTitle(GetText(strs.filter_word_list))
|
||||
.WithDescription(string.Join("\n", fws.Skip(curPage * 10).Take(10)))
|
||||
.WithOkColor()
|
||||
, fws.Length, 10).ConfigureAwait(false);
|
||||
_service.InviteFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterInv()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterInvitesChannelIds));
|
||||
var match = new FilterChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterInvitesChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterInvitesChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.InviteFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.InviteFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.invite_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterLin()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterLinks = !config.FilterLinks;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_service.LinkFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.LinkFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterLin()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterLinksChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterLinksChannelIds));
|
||||
var match = new FilterLinksChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterLinksChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterLinksChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.LinkFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.LinkFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.link_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task SrvrFilterWords()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
bool enabled;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set);
|
||||
enabled = config.FilterWords = !config.FilterWords;
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
_service.WordFilteringServers.Add(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_server_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.WordFilteringServers.TryRemove(channel.Guild.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_server_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChnlFilterWords()
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
FilterChannelId removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilterWordsChannelIds));
|
||||
|
||||
var match = new FilterChannelId()
|
||||
{
|
||||
ChannelId = channel.Id
|
||||
};
|
||||
removed = config.FilterWordsChannelIds.FirstOrDefault(fc => fc.Equals(match));
|
||||
if (removed is null)
|
||||
{
|
||||
config.FilterWordsChannelIds.Add(match);
|
||||
}
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
_service.WordFilteringChannels.Add(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_channel_on).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_service.WordFilteringChannels.TryRemove(channel.Id);
|
||||
await ReplyConfirmLocalizedAsync(strs.word_filter_channel_off).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task FilterWord([Leftover] string word)
|
||||
{
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
word = word?.Trim().ToLowerInvariant();
|
||||
|
||||
if (string.IsNullOrWhiteSpace(word))
|
||||
return;
|
||||
|
||||
FilteredWord removed;
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(channel.Guild.Id, set => set.Include(gc => gc.FilteredWords));
|
||||
|
||||
removed = config.FilteredWords.FirstOrDefault(fw => fw.Word.Trim().ToLowerInvariant() == word);
|
||||
|
||||
if (removed is null)
|
||||
config.FilteredWords.Add(new FilteredWord() { Word = word });
|
||||
else
|
||||
{
|
||||
uow.Remove(removed);
|
||||
}
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
var filteredWords = _service.ServerFilteredWords.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<string>());
|
||||
|
||||
if (removed is null)
|
||||
{
|
||||
filteredWords.Add(word);
|
||||
await ReplyConfirmLocalizedAsync(strs.filter_word_add(Format.Code(word))).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredWords.TryRemove(word);
|
||||
await ReplyConfirmLocalizedAsync(strs.filter_word_remove(Format.Code(word))).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task LstFilterWords(int page = 1)
|
||||
{
|
||||
page--;
|
||||
if (page < 0)
|
||||
return;
|
||||
|
||||
var channel = (ITextChannel)ctx.Channel;
|
||||
|
||||
_service.ServerFilteredWords.TryGetValue(channel.Guild.Id, out var fwHash);
|
||||
|
||||
var fws = fwHash.ToArray();
|
||||
|
||||
await ctx.SendPaginatedConfirmAsync(page,
|
||||
(curPage) => _eb.Create()
|
||||
.WithTitle(GetText(strs.filter_word_list))
|
||||
.WithDescription(string.Join("\n", fws.Skip(curPage * 10).Take(10)))
|
||||
.WithOkColor()
|
||||
, fws.Length, 10).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -5,84 +5,82 @@ using NadekoBot.Common.TypeReaders;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions
|
||||
namespace NadekoBot.Modules.Permissions;
|
||||
|
||||
public partial class Permissions
|
||||
{
|
||||
public partial class Permissions
|
||||
[Group]
|
||||
public class GlobalPermissionCommands : NadekoSubmodule
|
||||
{
|
||||
[Group]
|
||||
public class GlobalPermissionCommands : NadekoSubmodule
|
||||
private GlobalPermissionService _service;
|
||||
private readonly DbService _db;
|
||||
|
||||
public GlobalPermissionCommands(GlobalPermissionService service, DbService db)
|
||||
{
|
||||
private GlobalPermissionService _service;
|
||||
private readonly DbService _db;
|
||||
_service = service;
|
||||
_db = db;
|
||||
}
|
||||
|
||||
public GlobalPermissionCommands(GlobalPermissionService service, DbService db)
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalPermList()
|
||||
{
|
||||
var blockedModule = _service.BlockedModules;
|
||||
var blockedCommands = _service.BlockedCommands;
|
||||
if (!blockedModule.Any() && !blockedCommands.Any())
|
||||
{
|
||||
_service = service;
|
||||
_db = db;
|
||||
await ReplyErrorLocalizedAsync(strs.lgp_none).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalPermList()
|
||||
var embed = _eb.Create().WithOkColor();
|
||||
|
||||
if (blockedModule.Any())
|
||||
embed.AddField(GetText(strs.blocked_modules)
|
||||
, string.Join("\n", _service.BlockedModules)
|
||||
, false);
|
||||
|
||||
if (blockedCommands.Any())
|
||||
embed.AddField(GetText(strs.blocked_commands)
|
||||
, string.Join("\n", _service.BlockedCommands)
|
||||
, false);
|
||||
|
||||
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalModule(ModuleOrCrInfo module)
|
||||
{
|
||||
var moduleName = module.Name.ToLowerInvariant();
|
||||
|
||||
var added = _service.ToggleModule(moduleName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
var blockedModule = _service.BlockedModules;
|
||||
var blockedCommands = _service.BlockedCommands;
|
||||
if (!blockedModule.Any() && !blockedCommands.Any())
|
||||
{
|
||||
await ReplyErrorLocalizedAsync(strs.lgp_none).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
var embed = _eb.Create().WithOkColor();
|
||||
|
||||
if (blockedModule.Any())
|
||||
embed.AddField(GetText(strs.blocked_modules)
|
||||
, string.Join("\n", _service.BlockedModules)
|
||||
, false);
|
||||
|
||||
if (blockedCommands.Any())
|
||||
embed.AddField(GetText(strs.blocked_commands)
|
||||
, string.Join("\n", _service.BlockedCommands)
|
||||
, false);
|
||||
|
||||
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.gmod_add(Format.Bold(module.Name))).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.gmod_remove(Format.Bold(module.Name))).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalModule(ModuleOrCrInfo module)
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalCommand(CommandOrCrInfo cmd)
|
||||
{
|
||||
var commandName = cmd.Name.ToLowerInvariant();
|
||||
var added = _service.ToggleCommand(commandName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
var moduleName = module.Name.ToLowerInvariant();
|
||||
|
||||
var added = _service.ToggleModule(moduleName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.gmod_add(Format.Bold(module.Name))).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.gmod_remove(Format.Bold(module.Name))).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.gcmd_add(Format.Bold(cmd.Name))).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task GlobalCommand(CommandOrCrInfo cmd)
|
||||
{
|
||||
var commandName = cmd.Name.ToLowerInvariant();
|
||||
var added = _service.ToggleCommand(commandName);
|
||||
|
||||
if (added)
|
||||
{
|
||||
await ReplyConfirmLocalizedAsync(strs.gcmd_add(Format.Bold(cmd.Name))).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
await ReplyConfirmLocalizedAsync(strs.gcmd_remove(Format.Bold(cmd.Name))).ConfigureAwait(false);
|
||||
}
|
||||
await ReplyConfirmLocalizedAsync(strs.gcmd_remove(Format.Bold(cmd.Name))).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -4,38 +4,37 @@ using System.Threading.Tasks;
|
||||
using NadekoBot.Common.Attributes;
|
||||
using NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions
|
||||
namespace NadekoBot.Modules.Permissions;
|
||||
|
||||
public partial class Permissions
|
||||
{
|
||||
public partial class Permissions
|
||||
[Group]
|
||||
public class ResetPermissionsCommands : NadekoSubmodule
|
||||
{
|
||||
[Group]
|
||||
public class ResetPermissionsCommands : NadekoSubmodule
|
||||
private readonly GlobalPermissionService _gps;
|
||||
private readonly PermissionService _perms;
|
||||
|
||||
public ResetPermissionsCommands(GlobalPermissionService gps, PermissionService perms)
|
||||
{
|
||||
private readonly GlobalPermissionService _gps;
|
||||
private readonly PermissionService _perms;
|
||||
_gps = gps;
|
||||
_perms = perms;
|
||||
}
|
||||
|
||||
public ResetPermissionsCommands(GlobalPermissionService gps, PermissionService perms)
|
||||
{
|
||||
_gps = gps;
|
||||
_perms = perms;
|
||||
}
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task ResetPerms()
|
||||
{
|
||||
await _perms.Reset(ctx.Guild.Id).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.perms_reset).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task ResetPerms()
|
||||
{
|
||||
await _perms.Reset(ctx.Guild.Id).ConfigureAwait(false);
|
||||
await ReplyConfirmLocalizedAsync(strs.perms_reset).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task ResetGlobalPerms()
|
||||
{
|
||||
await _gps.Reset();
|
||||
await ReplyConfirmLocalizedAsync(strs.global_perms_reset).ConfigureAwait(false);
|
||||
}
|
||||
[NadekoCommand, Aliases]
|
||||
[OwnerOnly]
|
||||
public async Task ResetGlobalPerms()
|
||||
{
|
||||
await _gps.Reset();
|
||||
await ReplyConfirmLocalizedAsync(strs.global_perms_reset).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Discord;
|
||||
using Discord;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
@@ -8,130 +6,128 @@ using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Common;
|
||||
using NadekoBot.Db;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Services
|
||||
namespace NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
public sealed class BlacklistService : IEarlyBehavior
|
||||
{
|
||||
public sealed class BlacklistService : IEarlyBehavior
|
||||
private readonly DbService _db;
|
||||
private readonly IPubSub _pubSub;
|
||||
private readonly IBotCredentials _creds;
|
||||
private IReadOnlyList<BlacklistEntry> _blacklist;
|
||||
public int Priority => int.MaxValue;
|
||||
|
||||
private readonly TypedKey<BlacklistEntry[]> blPubKey = new TypedKey<BlacklistEntry[]>("blacklist.reload");
|
||||
public BlacklistService(DbService db, IPubSub pubSub, IBotCredentials creds)
|
||||
{
|
||||
private readonly DbService _db;
|
||||
private readonly IPubSub _pubSub;
|
||||
private readonly IBotCredentials _creds;
|
||||
private IReadOnlyList<BlacklistEntry> _blacklist;
|
||||
public int Priority => int.MaxValue;
|
||||
_db = db;
|
||||
_pubSub = pubSub;
|
||||
_creds = creds;
|
||||
|
||||
private readonly TypedKey<BlacklistEntry[]> blPubKey = new TypedKey<BlacklistEntry[]>("blacklist.reload");
|
||||
public BlacklistService(DbService db, IPubSub pubSub, IBotCredentials creds)
|
||||
Reload(false);
|
||||
_pubSub.Sub(blPubKey, OnReload);
|
||||
}
|
||||
|
||||
private ValueTask OnReload(BlacklistEntry[] blacklist)
|
||||
{
|
||||
_blacklist = blacklist;
|
||||
return default;
|
||||
}
|
||||
|
||||
public Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
foreach (var bl in _blacklist)
|
||||
{
|
||||
_db = db;
|
||||
_pubSub = pubSub;
|
||||
_creds = creds;
|
||||
|
||||
Reload(false);
|
||||
_pubSub.Sub(blPubKey, OnReload);
|
||||
}
|
||||
|
||||
private ValueTask OnReload(BlacklistEntry[] blacklist)
|
||||
{
|
||||
_blacklist = blacklist;
|
||||
return default;
|
||||
}
|
||||
|
||||
public Task<bool> RunBehavior(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
foreach (var bl in _blacklist)
|
||||
if (guild != null && bl.Type == BlacklistType.Server && bl.ItemId == guild.Id)
|
||||
{
|
||||
if (guild != null && bl.Type == BlacklistType.Server && bl.ItemId == guild.Id)
|
||||
{
|
||||
Log.Information("Blocked input from blacklisted guild: {GuildName} [{GuildId}]",
|
||||
guild.Name,
|
||||
guild.Id);
|
||||
Log.Information("Blocked input from blacklisted guild: {GuildName} [{GuildId}]",
|
||||
guild.Name,
|
||||
guild.Id);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
if (bl.Type == BlacklistType.Channel && bl.ItemId == usrMsg.Channel.Id)
|
||||
{
|
||||
Log.Information("Blocked input from blacklisted channel: {ChannelName} [{ChannelId}]",
|
||||
usrMsg.Channel.Name,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
if (bl.Type == BlacklistType.User && bl.ItemId == usrMsg.Author.Id)
|
||||
{
|
||||
Log.Information("Blocked input from blacklisted user: {UserName} [{UserId}]",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public IReadOnlyList<BlacklistEntry> GetBlacklist()
|
||||
=> _blacklist;
|
||||
|
||||
public void Reload(bool publish = true)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var toPublish = uow.Blacklist.AsNoTracking().ToArray();
|
||||
_blacklist = toPublish;
|
||||
if (publish)
|
||||
if (bl.Type == BlacklistType.Channel && bl.ItemId == usrMsg.Channel.Id)
|
||||
{
|
||||
_pubSub.Pub(blPubKey, toPublish);
|
||||
Log.Information("Blocked input from blacklisted channel: {ChannelName} [{ChannelId}]",
|
||||
usrMsg.Channel.Name,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
if (bl.Type == BlacklistType.User && bl.ItemId == usrMsg.Author.Id)
|
||||
{
|
||||
Log.Information("Blocked input from blacklisted user: {UserName} [{UserId}]",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id);
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void Blacklist(BlacklistType type, ulong id)
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public IReadOnlyList<BlacklistEntry> GetBlacklist()
|
||||
=> _blacklist;
|
||||
|
||||
public void Reload(bool publish = true)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var toPublish = uow.Blacklist.AsNoTracking().ToArray();
|
||||
_blacklist = toPublish;
|
||||
if (publish)
|
||||
{
|
||||
if (_creds.OwnerIds.Contains(id))
|
||||
return;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var item = new BlacklistEntry { ItemId = id, Type = type };
|
||||
uow.Blacklist.Add(item);
|
||||
uow.SaveChanges();
|
||||
|
||||
Reload(true);
|
||||
}
|
||||
|
||||
public void UnBlacklist(BlacklistType type, ulong id)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var toRemove = uow.Blacklist
|
||||
.FirstOrDefault(bi => bi.ItemId == id && bi.Type == type);
|
||||
|
||||
if (toRemove is not null)
|
||||
uow.Blacklist.Remove(toRemove);
|
||||
|
||||
uow.SaveChanges();
|
||||
|
||||
Reload(true);
|
||||
}
|
||||
|
||||
public void BlacklistUsers(IReadOnlyCollection<ulong> toBlacklist)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var bc = uow.Blacklist;
|
||||
//blacklist the users
|
||||
bc.AddRange(toBlacklist.Select(x =>
|
||||
new BlacklistEntry
|
||||
{
|
||||
ItemId = x,
|
||||
Type = BlacklistType.User,
|
||||
}));
|
||||
|
||||
//clear their currencies
|
||||
uow.DiscordUser.RemoveFromMany(toBlacklist);
|
||||
uow.SaveChanges();
|
||||
}
|
||||
|
||||
Reload(true);
|
||||
_pubSub.Pub(blPubKey, toPublish);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Blacklist(BlacklistType type, ulong id)
|
||||
{
|
||||
if (_creds.OwnerIds.Contains(id))
|
||||
return;
|
||||
|
||||
using var uow = _db.GetDbContext();
|
||||
var item = new BlacklistEntry { ItemId = id, Type = type };
|
||||
uow.Blacklist.Add(item);
|
||||
uow.SaveChanges();
|
||||
|
||||
Reload(true);
|
||||
}
|
||||
|
||||
public void UnBlacklist(BlacklistType type, ulong id)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var toRemove = uow.Blacklist
|
||||
.FirstOrDefault(bi => bi.ItemId == id && bi.Type == type);
|
||||
|
||||
if (toRemove is not null)
|
||||
uow.Blacklist.Remove(toRemove);
|
||||
|
||||
uow.SaveChanges();
|
||||
|
||||
Reload(true);
|
||||
}
|
||||
|
||||
public void BlacklistUsers(IReadOnlyCollection<ulong> toBlacklist)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var bc = uow.Blacklist;
|
||||
//blacklist the users
|
||||
bc.AddRange(toBlacklist.Select(x =>
|
||||
new BlacklistEntry
|
||||
{
|
||||
ItemId = x,
|
||||
Type = BlacklistType.User,
|
||||
}));
|
||||
|
||||
//clear their currencies
|
||||
uow.DiscordUser.RemoveFromMany(toBlacklist);
|
||||
uow.SaveChanges();
|
||||
}
|
||||
|
||||
Reload(true);
|
||||
}
|
||||
}
|
@@ -1,81 +1,78 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.Collections;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Services
|
||||
namespace NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
public class CmdCdService : ILateBlocker, INService
|
||||
{
|
||||
public class CmdCdService : ILateBlocker, INService
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns { get; }
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
||||
|
||||
public int Priority { get; } = 0;
|
||||
|
||||
public CmdCdService(Bot bot)
|
||||
{
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> CommandCooldowns { get; }
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> ActiveCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
|
||||
|
||||
public int Priority { get; } = 0;
|
||||
|
||||
public CmdCdService(Bot bot)
|
||||
{
|
||||
CommandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(
|
||||
bot.AllGuildConfigs.ToDictionary(k => k.GuildId,
|
||||
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
||||
}
|
||||
|
||||
public Task<bool> TryBlock(IGuild guild, IUser user, string commandName)
|
||||
{
|
||||
if (guild is null)
|
||||
return Task.FromResult(false);
|
||||
|
||||
var cmdcds = CommandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||
CommandCooldown cdRule;
|
||||
if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == commandName)) != null)
|
||||
{
|
||||
var activeCdsForGuild = ActiveCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||
if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == commandName) != null)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
activeCdsForGuild.Add(new ActiveCooldown()
|
||||
{
|
||||
UserId = user.Id,
|
||||
Command = commandName,
|
||||
});
|
||||
|
||||
var _ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(cdRule.Seconds * 1000).ConfigureAwait(false);
|
||||
activeCdsForGuild.RemoveWhere(ac => ac.Command == commandName && ac.UserId == user.Id);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var guild = ctx.Guild;
|
||||
var user = ctx.User;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
return TryBlock(guild, user, commandName);
|
||||
}
|
||||
CommandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(
|
||||
bot.AllGuildConfigs.ToDictionary(k => k.GuildId,
|
||||
v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
|
||||
}
|
||||
|
||||
public class ActiveCooldown
|
||||
public Task<bool> TryBlock(IGuild guild, IUser user, string commandName)
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
if (guild is null)
|
||||
return Task.FromResult(false);
|
||||
|
||||
var cmdcds = CommandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>());
|
||||
CommandCooldown cdRule;
|
||||
if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == commandName)) != null)
|
||||
{
|
||||
var activeCdsForGuild = ActiveCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>());
|
||||
if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == commandName) != null)
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
activeCdsForGuild.Add(new ActiveCooldown()
|
||||
{
|
||||
UserId = user.Id,
|
||||
Command = commandName,
|
||||
});
|
||||
|
||||
var _ = Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(cdRule.Seconds * 1000).ConfigureAwait(false);
|
||||
activeCdsForGuild.RemoveWhere(ac => ac.Command == commandName && ac.UserId == user.Id);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var guild = ctx.Guild;
|
||||
var user = ctx.User;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
return TryBlock(guild, user, commandName);
|
||||
}
|
||||
}
|
||||
|
||||
public class ActiveCooldown
|
||||
{
|
||||
public string Command { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
}
|
@@ -1,5 +1,4 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Net;
|
||||
@@ -9,227 +8,223 @@ using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Extensions;
|
||||
using NadekoBot.Services;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Internal;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Db;
|
||||
using NadekoBot.Modules.Administration;
|
||||
using Serilog;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Services
|
||||
namespace NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
public sealed class FilterService : IEarlyBehavior
|
||||
{
|
||||
public sealed class FilterService : IEarlyBehavior
|
||||
private readonly DbService _db;
|
||||
|
||||
public ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
||||
|
||||
//serverid, filteredwords
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<string>> ServerFilteredWords { get; }
|
||||
|
||||
public ConcurrentHashSet<ulong> WordFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> WordFilteringServers { get; }
|
||||
|
||||
public ConcurrentHashSet<ulong> LinkFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> LinkFilteringServers { get; }
|
||||
|
||||
public int Priority => int.MaxValue - 1;
|
||||
|
||||
public ConcurrentHashSet<string> FilteredWordsForChannel(ulong channelId, ulong guildId)
|
||||
{
|
||||
private readonly DbService _db;
|
||||
ConcurrentHashSet<string> words = new ConcurrentHashSet<string>();
|
||||
if (WordFilteringChannels.Contains(channelId))
|
||||
ServerFilteredWords.TryGetValue(guildId, out words);
|
||||
return words;
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> InviteFilteringServers { get; }
|
||||
|
||||
//serverid, filteredwords
|
||||
public ConcurrentDictionary<ulong, ConcurrentHashSet<string>> ServerFilteredWords { get; }
|
||||
|
||||
public ConcurrentHashSet<ulong> WordFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> WordFilteringServers { get; }
|
||||
|
||||
public ConcurrentHashSet<ulong> LinkFilteringChannels { get; }
|
||||
public ConcurrentHashSet<ulong> LinkFilteringServers { get; }
|
||||
|
||||
public int Priority => int.MaxValue - 1;
|
||||
|
||||
public ConcurrentHashSet<string> FilteredWordsForChannel(ulong channelId, ulong guildId)
|
||||
public void ClearFilteredWords(ulong guildId)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
ConcurrentHashSet<string> words = new ConcurrentHashSet<string>();
|
||||
if (WordFilteringChannels.Contains(channelId))
|
||||
ServerFilteredWords.TryGetValue(guildId, out words);
|
||||
return words;
|
||||
}
|
||||
var gc = uow.GuildConfigsForId(guildId,
|
||||
set => set.Include(x => x.FilteredWords)
|
||||
.Include(x => x.FilterWordsChannelIds));
|
||||
|
||||
public void ClearFilteredWords(ulong guildId)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
WordFilteringServers.TryRemove(guildId);
|
||||
ServerFilteredWords.TryRemove(guildId, out _);
|
||||
|
||||
foreach (var c in gc.FilterWordsChannelIds)
|
||||
{
|
||||
var gc = uow.GuildConfigsForId(guildId,
|
||||
set => set.Include(x => x.FilteredWords)
|
||||
.Include(x => x.FilterWordsChannelIds));
|
||||
|
||||
WordFilteringServers.TryRemove(guildId);
|
||||
ServerFilteredWords.TryRemove(guildId, out _);
|
||||
|
||||
foreach (var c in gc.FilterWordsChannelIds)
|
||||
{
|
||||
WordFilteringChannels.TryRemove(c.ChannelId);
|
||||
}
|
||||
|
||||
gc.FilterWords = false;
|
||||
gc.FilteredWords.Clear();
|
||||
gc.FilterWordsChannelIds.Clear();
|
||||
|
||||
uow.SaveChanges();
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<string> FilteredWordsForServer(ulong guildId)
|
||||
{
|
||||
var words = new ConcurrentHashSet<string>();
|
||||
if (WordFilteringServers.Contains(guildId))
|
||||
ServerFilteredWords.TryGetValue(guildId, out words);
|
||||
return words;
|
||||
}
|
||||
|
||||
public FilterService(DiscordSocketClient client, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
|
||||
using(var uow = db.GetDbContext())
|
||||
{
|
||||
var ids = client.GetGuildIds();
|
||||
var configs = uow.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Include(x => x.FilteredWords)
|
||||
.Include(x => x.FilterLinksChannelIds)
|
||||
.Include(x => x.FilterWordsChannelIds)
|
||||
.Include(x => x.FilterInvitesChannelIds)
|
||||
.Where(gc => ids.Contains(gc.GuildId))
|
||||
.ToList();
|
||||
|
||||
InviteFilteringServers = new ConcurrentHashSet<ulong>(configs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
|
||||
InviteFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));
|
||||
|
||||
LinkFilteringServers = new ConcurrentHashSet<ulong>(configs.Where(gc => gc.FilterLinks).Select(gc => gc.GuildId));
|
||||
LinkFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterLinksChannelIds.Select(fci => fci.ChannelId)));
|
||||
|
||||
var dict = configs.ToDictionary(gc => gc.GuildId, gc => new ConcurrentHashSet<string>(gc.FilteredWords.Select(fw => fw.Word)));
|
||||
|
||||
ServerFilteredWords = new ConcurrentDictionary<ulong, ConcurrentHashSet<string>>(dict);
|
||||
|
||||
var serverFiltering = configs.Where(gc => gc.FilterWords);
|
||||
WordFilteringServers = new ConcurrentHashSet<ulong>(serverFiltering.Select(gc => gc.GuildId));
|
||||
WordFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId)));
|
||||
WordFilteringChannels.TryRemove(c.ChannelId);
|
||||
}
|
||||
|
||||
client.MessageUpdated += (oldData, newMsg, channel) =>
|
||||
{
|
||||
var _ = Task.Run(() =>
|
||||
{
|
||||
var guild = (channel as ITextChannel)?.Guild;
|
||||
var usrMsg = newMsg as IUserMessage;
|
||||
gc.FilterWords = false;
|
||||
gc.FilteredWords.Clear();
|
||||
gc.FilterWordsChannelIds.Clear();
|
||||
|
||||
if (guild is null || usrMsg is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return RunBehavior(guild, usrMsg);
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<bool> RunBehavior(IGuild guild, IUserMessage msg)
|
||||
{
|
||||
if (!(msg.Author is IGuildUser gu) || gu.GuildPermissions.Administrator)
|
||||
return false;
|
||||
|
||||
var results = await Task.WhenAll(
|
||||
FilterInvites(guild, msg),
|
||||
FilterWords(guild, msg),
|
||||
FilterLinks(guild, msg));
|
||||
|
||||
return results.Any(x => x);
|
||||
}
|
||||
|
||||
private async Task<bool> FilterWords(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
var filteredChannelWords = FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
|
||||
var filteredServerWords = FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
|
||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
||||
{
|
||||
foreach (var word in wordsInMessage)
|
||||
{
|
||||
if (filteredChannelWords.Contains(word) ||
|
||||
filteredServerWords.Contains(word))
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] used a filtered word in {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> FilterInvites(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
if ((InviteFilteringChannels.Contains(usrMsg.Channel.Id)
|
||||
|| InviteFilteringServers.Contains(guild.Id))
|
||||
&& usrMsg.Content.IsDiscordInvite())
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] sent a filtered invite to {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> FilterLinks(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
if ((LinkFilteringChannels.Contains(usrMsg.Channel.Id)
|
||||
|| LinkFilteringServers.Contains(guild.Id))
|
||||
&& usrMsg.Content.TryGetUrlPath(out _))
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] sent a filtered link to {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter links in channel with id " + usrMsg.Channel.Id, ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
uow.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ConcurrentHashSet<string> FilteredWordsForServer(ulong guildId)
|
||||
{
|
||||
var words = new ConcurrentHashSet<string>();
|
||||
if (WordFilteringServers.Contains(guildId))
|
||||
ServerFilteredWords.TryGetValue(guildId, out words);
|
||||
return words;
|
||||
}
|
||||
|
||||
public FilterService(DiscordSocketClient client, DbService db)
|
||||
{
|
||||
_db = db;
|
||||
|
||||
using(var uow = db.GetDbContext())
|
||||
{
|
||||
var ids = client.GetGuildIds();
|
||||
var configs = uow.Set<GuildConfig>()
|
||||
.AsQueryable()
|
||||
.Include(x => x.FilteredWords)
|
||||
.Include(x => x.FilterLinksChannelIds)
|
||||
.Include(x => x.FilterWordsChannelIds)
|
||||
.Include(x => x.FilterInvitesChannelIds)
|
||||
.Where(gc => ids.Contains(gc.GuildId))
|
||||
.ToList();
|
||||
|
||||
InviteFilteringServers = new ConcurrentHashSet<ulong>(configs.Where(gc => gc.FilterInvites).Select(gc => gc.GuildId));
|
||||
InviteFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterInvitesChannelIds.Select(fci => fci.ChannelId)));
|
||||
|
||||
LinkFilteringServers = new ConcurrentHashSet<ulong>(configs.Where(gc => gc.FilterLinks).Select(gc => gc.GuildId));
|
||||
LinkFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterLinksChannelIds.Select(fci => fci.ChannelId)));
|
||||
|
||||
var dict = configs.ToDictionary(gc => gc.GuildId, gc => new ConcurrentHashSet<string>(gc.FilteredWords.Select(fw => fw.Word)));
|
||||
|
||||
ServerFilteredWords = new ConcurrentDictionary<ulong, ConcurrentHashSet<string>>(dict);
|
||||
|
||||
var serverFiltering = configs.Where(gc => gc.FilterWords);
|
||||
WordFilteringServers = new ConcurrentHashSet<ulong>(serverFiltering.Select(gc => gc.GuildId));
|
||||
WordFilteringChannels = new ConcurrentHashSet<ulong>(configs.SelectMany(gc => gc.FilterWordsChannelIds.Select(fwci => fwci.ChannelId)));
|
||||
}
|
||||
|
||||
client.MessageUpdated += (oldData, newMsg, channel) =>
|
||||
{
|
||||
var _ = Task.Run(() =>
|
||||
{
|
||||
var guild = (channel as ITextChannel)?.Guild;
|
||||
var usrMsg = newMsg as IUserMessage;
|
||||
|
||||
if (guild is null || usrMsg is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return RunBehavior(guild, usrMsg);
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
};
|
||||
}
|
||||
|
||||
public async Task<bool> RunBehavior(IGuild guild, IUserMessage msg)
|
||||
{
|
||||
if (!(msg.Author is IGuildUser gu) || gu.GuildPermissions.Administrator)
|
||||
return false;
|
||||
|
||||
var results = await Task.WhenAll(
|
||||
FilterInvites(guild, msg),
|
||||
FilterWords(guild, msg),
|
||||
FilterLinks(guild, msg));
|
||||
|
||||
return results.Any(x => x);
|
||||
}
|
||||
|
||||
private async Task<bool> FilterWords(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
var filteredChannelWords = FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id) ?? new ConcurrentHashSet<string>();
|
||||
var filteredServerWords = FilteredWordsForServer(guild.Id) ?? new ConcurrentHashSet<string>();
|
||||
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
|
||||
if (filteredChannelWords.Count != 0 || filteredServerWords.Count != 0)
|
||||
{
|
||||
foreach (var word in wordsInMessage)
|
||||
{
|
||||
if (filteredChannelWords.Contains(word) ||
|
||||
filteredServerWords.Contains(word))
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] used a filtered word in {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> FilterInvites(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
if ((InviteFilteringChannels.Contains(usrMsg.Channel.Id)
|
||||
|| InviteFilteringServers.Contains(guild.Id))
|
||||
&& usrMsg.Content.IsDiscordInvite())
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] sent a filtered invite to {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async Task<bool> FilterLinks(IGuild guild, IUserMessage usrMsg)
|
||||
{
|
||||
if (guild is null)
|
||||
return false;
|
||||
if (usrMsg is null)
|
||||
return false;
|
||||
|
||||
if ((LinkFilteringChannels.Contains(usrMsg.Channel.Id)
|
||||
|| LinkFilteringServers.Contains(guild.Id))
|
||||
&& usrMsg.Content.TryGetUrlPath(out _))
|
||||
{
|
||||
Log.Information("User {UserName} [{UserId}] sent a filtered link to {ChannelId} channel",
|
||||
usrMsg.Author.ToString(),
|
||||
usrMsg.Author.Id,
|
||||
usrMsg.Channel.Id);
|
||||
|
||||
try
|
||||
{
|
||||
await usrMsg.DeleteAsync().ConfigureAwait(false);
|
||||
return true;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
{
|
||||
Log.Warning("I do not have permission to filter links in channel with id " + usrMsg.Channel.Id, ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -1,101 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading.Tasks;
|
||||
using Discord.Commands;
|
||||
using Discord.WebSocket;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Services;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Services
|
||||
namespace NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
public class GlobalPermissionService : ILateBlocker, INService
|
||||
{
|
||||
public class GlobalPermissionService : ILateBlocker, INService
|
||||
private readonly BotConfigService _bss;
|
||||
public int Priority { get; } = 0;
|
||||
|
||||
public HashSet<string> BlockedCommands => _bss.Data.Blocked.Commands;
|
||||
public HashSet<string> BlockedModules => _bss.Data.Blocked.Modules;
|
||||
|
||||
public GlobalPermissionService(BotConfigService bss)
|
||||
{
|
||||
private readonly BotConfigService _bss;
|
||||
public int Priority { get; } = 0;
|
||||
|
||||
public HashSet<string> BlockedCommands => _bss.Data.Blocked.Commands;
|
||||
public HashSet<string> BlockedModules => _bss.Data.Blocked.Modules;
|
||||
|
||||
public GlobalPermissionService(BotConfigService bss)
|
||||
{
|
||||
_bss = bss;
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var settings = _bss.Data;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
if (commandName != "resetglobalperms" &&
|
||||
(settings.Blocked.Commands.Contains(commandName) ||
|
||||
settings.Blocked.Modules.Contains(moduleName.ToLowerInvariant())))
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles module blacklist
|
||||
/// </summary>
|
||||
/// <param name="moduleName">Lowercase module name</param>
|
||||
/// <returns>Whether the module is added</returns>
|
||||
public bool ToggleModule(string moduleName)
|
||||
{
|
||||
var added = false;
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
if (bs.Blocked.Modules.Add(moduleName))
|
||||
{
|
||||
added = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs.Blocked.Modules.Remove(moduleName);
|
||||
added = false;
|
||||
}
|
||||
});
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles command blacklist
|
||||
/// </summary>
|
||||
/// <param name="commandName">Lowercase command name</param>
|
||||
/// <returns>Whether the command is added</returns>
|
||||
public bool ToggleCommand(string commandName)
|
||||
{
|
||||
var added = false;
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
if (bs.Blocked.Commands.Add(commandName))
|
||||
{
|
||||
added = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs.Blocked.Commands.Remove(commandName);
|
||||
added = false;
|
||||
}
|
||||
});
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets all global permissions
|
||||
/// </summary>
|
||||
public Task Reset()
|
||||
{
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
bs.Blocked.Commands.Clear();
|
||||
bs.Blocked.Modules.Clear();
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
_bss = bss;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var settings = _bss.Data;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
if (commandName != "resetglobalperms" &&
|
||||
(settings.Blocked.Commands.Contains(commandName) ||
|
||||
settings.Blocked.Modules.Contains(moduleName.ToLowerInvariant())))
|
||||
{
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles module blacklist
|
||||
/// </summary>
|
||||
/// <param name="moduleName">Lowercase module name</param>
|
||||
/// <returns>Whether the module is added</returns>
|
||||
public bool ToggleModule(string moduleName)
|
||||
{
|
||||
var added = false;
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
if (bs.Blocked.Modules.Add(moduleName))
|
||||
{
|
||||
added = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs.Blocked.Modules.Remove(moduleName);
|
||||
added = false;
|
||||
}
|
||||
});
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggles command blacklist
|
||||
/// </summary>
|
||||
/// <param name="commandName">Lowercase command name</param>
|
||||
/// <returns>Whether the command is added</returns>
|
||||
public bool ToggleCommand(string commandName)
|
||||
{
|
||||
var added = false;
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
if (bs.Blocked.Commands.Add(commandName))
|
||||
{
|
||||
added = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs.Blocked.Commands.Remove(commandName);
|
||||
added = false;
|
||||
}
|
||||
});
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets all global permissions
|
||||
/// </summary>
|
||||
public Task Reset()
|
||||
{
|
||||
_bss.ModifyConfig(bs =>
|
||||
{
|
||||
bs.Blocked.Commands.Clear();
|
||||
bs.Blocked.Modules.Clear();
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading.Tasks;
|
||||
using Discord;
|
||||
using Discord.Commands;
|
||||
@@ -13,180 +11,179 @@ using NadekoBot.Services;
|
||||
using NadekoBot.Services.Database.Models;
|
||||
using NadekoBot.Db;
|
||||
|
||||
namespace NadekoBot.Modules.Permissions.Services
|
||||
namespace NadekoBot.Modules.Permissions.Services;
|
||||
|
||||
public class PermissionService : ILateBlocker, INService
|
||||
{
|
||||
public class PermissionService : ILateBlocker, INService
|
||||
{
|
||||
public int Priority { get; } = 0;
|
||||
public int Priority { get; } = 0;
|
||||
|
||||
private readonly DbService _db;
|
||||
private readonly CommandHandler _cmd;
|
||||
private readonly IBotStrings _strings;
|
||||
private readonly IEmbedBuilderService _eb;
|
||||
private readonly DbService _db;
|
||||
private readonly CommandHandler _cmd;
|
||||
private readonly IBotStrings _strings;
|
||||
private readonly IEmbedBuilderService _eb;
|
||||
|
||||
//guildid, root permission
|
||||
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
||||
new ConcurrentDictionary<ulong, PermissionCache>();
|
||||
//guildid, root permission
|
||||
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
|
||||
new ConcurrentDictionary<ulong, PermissionCache>();
|
||||
|
||||
public PermissionService(DiscordSocketClient client,
|
||||
DbService db,
|
||||
CommandHandler cmd,
|
||||
IBotStrings strings,
|
||||
IEmbedBuilderService eb)
|
||||
public PermissionService(DiscordSocketClient client,
|
||||
DbService db,
|
||||
CommandHandler cmd,
|
||||
IBotStrings strings,
|
||||
IEmbedBuilderService eb)
|
||||
{
|
||||
_db = db;
|
||||
_cmd = cmd;
|
||||
_strings = strings;
|
||||
_eb = eb;
|
||||
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
_db = db;
|
||||
_cmd = cmd;
|
||||
_strings = strings;
|
||||
_eb = eb;
|
||||
|
||||
using (var uow = _db.GetDbContext())
|
||||
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => x.Id)
|
||||
.ToList()))
|
||||
{
|
||||
foreach (var x in uow.GuildConfigs.Permissionsv2ForAll(client.Guilds.ToArray().Select(x => x.Id)
|
||||
.ToList()))
|
||||
Cache.TryAdd(x.GuildId, new PermissionCache()
|
||||
{
|
||||
Cache.TryAdd(x.GuildId, new PermissionCache()
|
||||
{
|
||||
Verbose = x.VerbosePermissions,
|
||||
PermRole = x.PermissionRole,
|
||||
Permissions = new PermissionsCollection<Permissionv2>(x.Permissions)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PermissionCache GetCacheFor(ulong guildId)
|
||||
{
|
||||
if (!Cache.TryGetValue(guildId, out var pc))
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(guildId,
|
||||
set => set.Include(x => x.Permissions));
|
||||
UpdateCache(config);
|
||||
}
|
||||
Cache.TryGetValue(guildId, out pc);
|
||||
if (pc is null)
|
||||
throw new Exception("Cache is null.");
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
||||
public async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GcWithPermissionsv2For(guildId);
|
||||
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
|
||||
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
|
||||
foreach (var perm in perms)
|
||||
{
|
||||
perm.Index = ++max;
|
||||
config.Permissions.Add(perm);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
UpdateCache(config);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateCache(GuildConfig config)
|
||||
{
|
||||
Cache.AddOrUpdate(config.GuildId, new PermissionCache()
|
||||
{
|
||||
Permissions = new PermissionsCollection<Permissionv2>(config.Permissions),
|
||||
PermRole = config.PermissionRole,
|
||||
Verbose = config.VerbosePermissions
|
||||
}, (id, old) =>
|
||||
{
|
||||
old.Permissions = new PermissionsCollection<Permissionv2>(config.Permissions);
|
||||
old.PermRole = config.PermissionRole;
|
||||
old.Verbose = config.VerbosePermissions;
|
||||
return old;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var guild = ctx.Guild;
|
||||
var msg = ctx.Message;
|
||||
var user = ctx.User;
|
||||
var channel = ctx.Channel;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
await Task.Yield();
|
||||
if (guild is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resetCommand = commandName == "resetperms";
|
||||
|
||||
PermissionCache pc = GetCacheFor(guild.Id);
|
||||
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
|
||||
{
|
||||
if (pc.Verbose)
|
||||
{
|
||||
try
|
||||
{
|
||||
await channel.SendErrorAsync(_eb,
|
||||
_strings.GetText(strs.perm_prevent(index + 1,
|
||||
Format.Bold(pc.Permissions[index]
|
||||
.GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild))), guild.Id));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (moduleName == nameof(Permissions))
|
||||
{
|
||||
if (!(user is IGuildUser guildUser))
|
||||
return true;
|
||||
|
||||
if (guildUser.GuildPermissions.Administrator)
|
||||
return false;
|
||||
|
||||
var permRole = pc.PermRole;
|
||||
if (!ulong.TryParse(permRole, out var rid))
|
||||
rid = 0;
|
||||
string returnMsg;
|
||||
IRole role;
|
||||
if (string.IsNullOrWhiteSpace(permRole) || (role = guild.GetRole(rid)) is null)
|
||||
{
|
||||
returnMsg = $"You need Admin permissions in order to use permission commands.";
|
||||
if (pc.Verbose)
|
||||
try { await channel.SendErrorAsync(_eb, returnMsg).ConfigureAwait(false); } catch { }
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (!guildUser.RoleIds.Contains(rid))
|
||||
{
|
||||
returnMsg = $"You need the {Format.Bold(role.Name)} role in order to use permission commands.";
|
||||
if (pc.Verbose)
|
||||
try { await channel.SendErrorAsync(_eb, returnMsg).ConfigureAwait(false); } catch { }
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task Reset(ulong guildId)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GcWithPermissionsv2For(guildId);
|
||||
config.Permissions = Permissionv2.GetDefaultPermlist;
|
||||
await uow.SaveChangesAsync();
|
||||
UpdateCache(config);
|
||||
Verbose = x.VerbosePermissions,
|
||||
PermRole = x.PermissionRole,
|
||||
Permissions = new PermissionsCollection<Permissionv2>(x.Permissions)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PermissionCache GetCacheFor(ulong guildId)
|
||||
{
|
||||
if (!Cache.TryGetValue(guildId, out var pc))
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GuildConfigsForId(guildId,
|
||||
set => set.Include(x => x.Permissions));
|
||||
UpdateCache(config);
|
||||
}
|
||||
Cache.TryGetValue(guildId, out pc);
|
||||
if (pc is null)
|
||||
throw new Exception("Cache is null.");
|
||||
}
|
||||
return pc;
|
||||
}
|
||||
|
||||
public async Task AddPermissions(ulong guildId, params Permissionv2[] perms)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GcWithPermissionsv2For(guildId);
|
||||
//var orderedPerms = new PermissionsCollection<Permissionv2>(config.Permissions);
|
||||
var max = config.Permissions.Max(x => x.Index); //have to set its index to be the highest
|
||||
foreach (var perm in perms)
|
||||
{
|
||||
perm.Index = ++max;
|
||||
config.Permissions.Add(perm);
|
||||
}
|
||||
await uow.SaveChangesAsync();
|
||||
UpdateCache(config);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateCache(GuildConfig config)
|
||||
{
|
||||
Cache.AddOrUpdate(config.GuildId, new PermissionCache()
|
||||
{
|
||||
Permissions = new PermissionsCollection<Permissionv2>(config.Permissions),
|
||||
PermRole = config.PermissionRole,
|
||||
Verbose = config.VerbosePermissions
|
||||
}, (id, old) =>
|
||||
{
|
||||
old.Permissions = new PermissionsCollection<Permissionv2>(config.Permissions);
|
||||
old.PermRole = config.PermissionRole;
|
||||
old.Verbose = config.VerbosePermissions;
|
||||
return old;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<bool> TryBlockLate(ICommandContext ctx, string moduleName, CommandInfo command)
|
||||
{
|
||||
var guild = ctx.Guild;
|
||||
var msg = ctx.Message;
|
||||
var user = ctx.User;
|
||||
var channel = ctx.Channel;
|
||||
var commandName = command.Name.ToLowerInvariant();
|
||||
|
||||
await Task.Yield();
|
||||
if (guild is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
var resetCommand = commandName == "resetperms";
|
||||
|
||||
PermissionCache pc = GetCacheFor(guild.Id);
|
||||
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
|
||||
{
|
||||
if (pc.Verbose)
|
||||
{
|
||||
try
|
||||
{
|
||||
await channel.SendErrorAsync(_eb,
|
||||
_strings.GetText(strs.perm_prevent(index + 1,
|
||||
Format.Bold(pc.Permissions[index]
|
||||
.GetCommand(_cmd.GetPrefix(guild), (SocketGuild)guild))), guild.Id));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
if (moduleName == nameof(Permissions))
|
||||
{
|
||||
if (!(user is IGuildUser guildUser))
|
||||
return true;
|
||||
|
||||
if (guildUser.GuildPermissions.Administrator)
|
||||
return false;
|
||||
|
||||
var permRole = pc.PermRole;
|
||||
if (!ulong.TryParse(permRole, out var rid))
|
||||
rid = 0;
|
||||
string returnMsg;
|
||||
IRole role;
|
||||
if (string.IsNullOrWhiteSpace(permRole) || (role = guild.GetRole(rid)) is null)
|
||||
{
|
||||
returnMsg = $"You need Admin permissions in order to use permission commands.";
|
||||
if (pc.Verbose)
|
||||
try { await channel.SendErrorAsync(_eb, returnMsg).ConfigureAwait(false); } catch { }
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (!guildUser.RoleIds.Contains(rid))
|
||||
{
|
||||
returnMsg = $"You need the {Format.Bold(role.Name)} role in order to use permission commands.";
|
||||
if (pc.Verbose)
|
||||
try { await channel.SendErrorAsync(_eb, returnMsg).ConfigureAwait(false); } catch { }
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task Reset(ulong guildId)
|
||||
{
|
||||
using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var config = uow.GcWithPermissionsv2For(guildId);
|
||||
config.Permissions = Permissionv2.GetDefaultPermlist;
|
||||
await uow.SaveChangesAsync();
|
||||
UpdateCache(config);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user