Prefix stuff almost complete, and i just realized permissions are getting screwed because of this

This commit is contained in:
Master Kwoth 2017-05-30 06:54:59 +02:00
parent 7704569c36
commit 6dd002002d
29 changed files with 1887 additions and 132 deletions

View File

@ -1,4 +1,5 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Services;
using NadekoBot.Services.CustomReactions; using NadekoBot.Services.CustomReactions;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -8,18 +9,22 @@ namespace NadekoBot.TypeReaders
public class CommandTypeReader : TypeReader public class CommandTypeReader : TypeReader
{ {
private readonly CommandService _cmds; private readonly CommandService _cmds;
private readonly CommandHandler _cmdHandler;
public CommandTypeReader(CommandService cmds) public CommandTypeReader(CommandService cmds, CommandHandler cmdHandler)
{ {
_cmds = cmds; _cmds = cmds;
_cmdHandler = cmdHandler;
} }
public override Task<TypeReaderResult> Read(ICommandContext context, string input) public override Task<TypeReaderResult> Read(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
if (!input.StartsWith(NadekoBot.Prefix.ToUpperInvariant())) var prefix = _cmdHandler.GetPrefix(context.Guild);
if (!input.StartsWith(prefix.ToUpperInvariant()))
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found."));
input = input.Substring(NadekoBot.Prefix.Length); input = input.Substring(prefix.Length);
var cmd = _cmds.Commands.FirstOrDefault(c => var cmd = _cmds.Commands.FirstOrDefault(c =>
c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input)); c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input));
@ -34,7 +39,7 @@ namespace NadekoBot.TypeReaders
{ {
private readonly CustomReactionsService _crs; private readonly CustomReactionsService _crs;
public CommandOrCrTypeReader(CustomReactionsService crs, CommandService cmds) : base(cmds) public CommandOrCrTypeReader(CustomReactionsService crs, CommandService cmds, CommandHandler cmdHandler) : base(cmds, cmdHandler)
{ {
_crs = crs; _crs = crs;
} }
@ -62,7 +67,7 @@ namespace NadekoBot.TypeReaders
var cmd = await base.Read(context, input); var cmd = await base.Read(context, input);
if (cmd.IsSuccess) if (cmd.IsSuccess)
{ {
return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Aliases.First())); return TypeReaderResult.FromSuccess(new CommandOrCrInfo(((CommandInfo)cmd.Values.First().Value).Name));
} }
return TypeReaderResult.FromError(CommandError.ParseFailed, "No such command or cr found."); return TypeReaderResult.FromError(CommandError.ParseFailed, "No such command or cr found.");
} }

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations
{
public partial class guildprefixes : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Prefix",
table: "GuildConfigs",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "DefaultPrefix",
table: "BotConfig",
nullable: true,
defaultValue: ".");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Prefix",
table: "GuildConfigs");
migrationBuilder.DropColumn(
name: "DefaultPrefix",
table: "BotConfig");
}
}
}

View File

@ -2,7 +2,9 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using NadekoBot.Services.Database; using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {
@ -149,6 +151,8 @@ namespace NadekoBot.Migrations
b.Property<DateTime?>("DateAdded"); b.Property<DateTime?>("DateAdded");
b.Property<string>("DefaultPrefix");
b.Property<string>("ErrorColor"); b.Property<string>("ErrorColor");
b.Property<bool>("ForwardMessages"); b.Property<bool>("ForwardMessages");
@ -568,6 +572,8 @@ namespace NadekoBot.Migrations
b.Property<string>("PermissionRole"); b.Property<string>("PermissionRole");
b.Property<string>("Prefix");
b.Property<int?>("RootPermissionId"); b.Property<int?>("RootPermissionId");
b.Property<bool>("SendChannelByeMessage"); b.Property<bool>("SendChannelByeMessage");

View File

@ -0,0 +1,55 @@
using Discord;
using Discord.Commands;
using NadekoBot.Attributes;
using NadekoBot.Services;
using NadekoBot.Services.Administration;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
{
public partial class Administration
{
[Group]
public class PrefixCommands : NadekoSubmodule
{
[NadekoCommand, Usage, Description, Aliases]
[Priority(0)]
public new async Task Prefix()
{
await ReplyConfirmLocalized("prefix_current", Format.Code(_cmdHandler.GetPrefix(Context.Guild))).ConfigureAwait(false);
return;
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)]
[Priority(1)]
public new async Task Prefix([Remainder]string prefix)
{
if (string.IsNullOrWhiteSpace(prefix))
return;
var oldPrefix = base.Prefix;
var newPrefix = _cmdHandler.SetPrefix(Context.Guild, prefix);
await ReplyConfirmLocalized("prefix_new", Format.Code(oldPrefix), Format.Code(newPrefix)).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task DefPrefix([Remainder]string prefix)
{
if (string.IsNullOrWhiteSpace(prefix))
{
await ReplyConfirmLocalized("defprefix_current", _cmdHandler.DefaultPrefix).ConfigureAwait(false);
return;
}
var oldPrefix = _cmdHandler.DefaultPrefix;
var newPrefix = _cmdHandler.SetDefaultPrefix(prefix);
await ReplyConfirmLocalized("defprefix_new", Format.Code(oldPrefix), Format.Code(newPrefix)).ConfigureAwait(false);
}
}
}
}

View File

@ -22,14 +22,16 @@ namespace NadekoBot.Modules.Games.Models
private readonly List<ulong> finishedUserIds; private readonly List<ulong> finishedUserIds;
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly GamesService _games; private readonly GamesService _games;
private readonly string _prefix;
private Logger _log { get; } private Logger _log { get; }
public TypingGame(GamesService games, DiscordShardedClient client, ITextChannel channel) public TypingGame(GamesService games, DiscordShardedClient client, ITextChannel channel, string prefix) //kek@prefix
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_games = games; _games = games;
_client = client; _client = client;
_prefix = prefix;
this.Channel = channel; this.Channel = channel;
IsActive = false; IsActive = false;
@ -96,7 +98,7 @@ namespace NadekoBot.Modules.Games.Models
if (_games.TypingArticles.Any()) if (_games.TypingArticles.Any())
return _games.TypingArticles[new NadekoRandom().Next(0, _games.TypingArticles.Count)].Text; return _games.TypingArticles[new NadekoRandom().Next(0, _games.TypingArticles.Count)].Text;
else else
return $"No typing articles found. Use {NadekoBot.Prefix}typeadd command to add a new article for typing."; return $"No typing articles found. Use {_prefix}typeadd command to add a new article for typing.";
} }

View File

@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Games
{ {
var channel = (ITextChannel)Context.Channel; var channel = (ITextChannel)Context.Channel;
var game = RunningContests.GetOrAdd(channel.Guild.Id, id => new TypingGame(_games, _client, channel)); var game = RunningContests.GetOrAdd(channel.Guild.Id, id => new TypingGame(_games, _client, channel, Prefix));
if (game.IsActive) if (game.IsActive)
{ {

View File

@ -10,6 +10,7 @@ using System.IO;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Permissions;
namespace NadekoBot.Modules.Help namespace NadekoBot.Modules.Help
{ {
@ -20,15 +21,17 @@ namespace NadekoBot.Modules.Help
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private readonly BotConfig _config; private readonly BotConfig _config;
private readonly CommandService _cmds; private readonly CommandService _cmds;
private readonly GlobalPermissionService _perms;
public string HelpString => String.Format(_config.HelpString, _creds.ClientId, NadekoBot.Prefix); public string HelpString => String.Format(_config.HelpString, _creds.ClientId, Prefix);
public string DMHelpString => _config.DMHelpString; public string DMHelpString => _config.DMHelpString;
public Help(IBotCredentials creds, BotConfig config, CommandService cmds) public Help(IBotCredentials creds, GlobalPermissionService perms, BotConfig config, CommandService cmds)
{ {
_creds = creds; _creds = creds;
_config = config; _config = config;
_cmds = cmds; _cmds = cmds;
_perms = perms;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -39,8 +42,7 @@ namespace NadekoBot.Modules.Help
.WithTitle(GetText("list_of_modules")) .WithTitle(GetText("list_of_modules"))
.WithDescription(string.Join("\n", .WithDescription(string.Join("\n",
_cmds.Modules.GroupBy(m => m.GetTopLevelModule()) _cmds.Modules.GroupBy(m => m.GetTopLevelModule())
//todo perms .Where(m => !_perms.BlockedModules.Contains(m.Key.Name.ToLowerInvariant()))
//.Where(m => !Permissions.Permissions.GlobalPermissionCommands.BlockedModules.Contains(m.Key.Name.ToLowerInvariant()))
.Select(m => "• " + m.Key.Name) .Select(m => "• " + m.Key.Name)
.OrderBy(s => s))); .OrderBy(s => s)));
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
@ -55,8 +57,7 @@ namespace NadekoBot.Modules.Help
if (string.IsNullOrWhiteSpace(module)) if (string.IsNullOrWhiteSpace(module))
return; return;
var cmds = _cmds.Commands.Where(c => c.Module.GetTopLevelModule().Name.ToUpperInvariant().StartsWith(module)) var cmds = _cmds.Commands.Where(c => c.Module.GetTopLevelModule().Name.ToUpperInvariant().StartsWith(module))
//todo perms .Where(c => !_perms.BlockedCommands.Contains(c.Aliases.First().ToLowerInvariant()))
//.Where(c => !Permissions.Permissions.GlobalPermissionCommands.BlockedCommands.Contains(c.Aliases.First().ToLowerInvariant()))
.OrderBy(c => c.Aliases.First()) .OrderBy(c => c.Aliases.First())
.Distinct(new CommandTextEqualityComparer()) .Distinct(new CommandTextEqualityComparer())
.AsEnumerable(); .AsEnumerable();
@ -154,8 +155,8 @@ namespace NadekoBot.Modules.Help
lastModule = module.Name; lastModule = module.Name;
} }
helpstr.AppendLine($"{string.Join(" ", com.Aliases.Select(a => "`" + a + "`"))} |" + helpstr.AppendLine($"{string.Join(" ", com.Aliases.Select(a => "`" + a + "`"))} |" +
$" {string.Format(com.Summary, NadekoBot.Prefix)} {GetCommandRequirements(com)} |" + $" {string.Format(com.Summary, Prefix)} {GetCommandRequirements(com)} |" +
$" {string.Format(com.Remarks, NadekoBot.Prefix)}"); $" {string.Format(com.Remarks, Prefix)}");
} }
File.WriteAllText("../../docs/Commands List.md", helpstr.ToString()); File.WriteAllText("../../docs/Commands List.md", helpstr.ToString());
await ReplyConfirmLocalized("commandlist_regen").ConfigureAwait(false); await ReplyConfirmLocalized("commandlist_regen").ConfigureAwait(false);

View File

@ -2,6 +2,7 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Administration;
using NLog; using NLog;
using System.Globalization; using System.Globalization;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,19 +13,21 @@ namespace NadekoBot.Modules
{ {
protected readonly Logger _log; protected readonly Logger _log;
protected CultureInfo _cultureInfo; protected CultureInfo _cultureInfo;
public readonly string Prefix;
public readonly string ModuleTypeName; public readonly string ModuleTypeName;
public readonly string LowerModuleTypeName; public readonly string LowerModuleTypeName;
public NadekoStrings _strings { get; set; } public NadekoStrings _strings { get; set; }
public CommandHandler _cmdHandler { get; set; }
public ILocalization _localization { get; set; } public ILocalization _localization { get; set; }
public string Prefix => _cmdHandler.GetPrefix(Context.Guild);
protected NadekoTopLevelModule(bool isTopLevelModule = true) protected NadekoTopLevelModule(bool isTopLevelModule = true)
{ {
//if it's top level module //if it's top level module
ModuleTypeName = isTopLevelModule ? this.GetType().Name : this.GetType().DeclaringType.Name; ModuleTypeName = isTopLevelModule ? this.GetType().Name : this.GetType().DeclaringType.Name;
LowerModuleTypeName = ModuleTypeName.ToLowerInvariant(); LowerModuleTypeName = ModuleTypeName.ToLowerInvariant();
Prefix = NadekoBot.Prefix;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
} }

View File

@ -13,11 +13,11 @@ namespace NadekoBot.Modules.Permissions.Commands
[Group] [Group]
public class ResetPermissionsCommands : NadekoSubmodule public class ResetPermissionsCommands : NadekoSubmodule
{ {
private readonly PermissionsService _service; private readonly PermissionService _service;
private readonly DbService _db; private readonly DbService _db;
private readonly GlobalPermissionService _globalPerms; private readonly GlobalPermissionService _globalPerms;
public ResetPermissionsCommands(PermissionsService service, GlobalPermissionService globalPerms, DbService db) public ResetPermissionsCommands(PermissionService service, GlobalPermissionService globalPerms, DbService db)
{ {
_service = service; _service = service;
_db = db; _db = db;

View File

@ -16,9 +16,9 @@ namespace NadekoBot.Modules.Permissions
public partial class Permissions : NadekoTopLevelModule public partial class Permissions : NadekoTopLevelModule
{ {
private readonly DbService _db; private readonly DbService _db;
private readonly PermissionsService _service; private readonly PermissionService _service;
public Permissions(PermissionsService service, DbService db) public Permissions(PermissionService service, DbService db)
{ {
_db = db; _db = db;
_service = service; _service = service;

View File

@ -29,7 +29,7 @@ namespace NadekoBot.Modules.Searches
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Placelist() public async Task Placelist()
{ {
await Context.Channel.SendConfirmAsync(GetText("list_of_place_tags", NadekoBot.Prefix), await Context.Channel.SendConfirmAsync(GetText("list_of_place_tags", Prefix),
typesStr) typesStr)
.ConfigureAwait(false); .ConfigureAwait(false);
} }

View File

@ -65,7 +65,7 @@ namespace NadekoBot.Modules.Utility
return; return;
} }
var rem = (_patreon.Interval - (DateTime.UtcNow - _patreon.LastUpdate)); var rem = (_patreon.Interval - (DateTime.UtcNow - _patreon.LastUpdate));
var helpcmd = Format.Code(NadekoBot.Prefix + "donate"); var helpcmd = Format.Code(Prefix + "donate");
await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(GetText("clpa_fail")) .WithDescription(GetText("clpa_fail"))
.AddField(efb => efb.WithName(GetText("clpa_fail_already_title")).WithValue(GetText("clpa_fail_already"))) .AddField(efb => efb.WithName(GetText("clpa_fail_already_title")).WithValue(GetText("clpa_fail_already")))

View File

@ -41,9 +41,6 @@ namespace NadekoBot
public static Color OkColor { get; private set; } public static Color OkColor { get; private set; }
public static Color ErrorColor { get; private set; } public static Color ErrorColor { get; private set; }
//todo placeholder, will be guild-based
public static string Prefix { get; } = ".";
public ImmutableArray<GuildConfig> AllGuildConfigs { get; } public ImmutableArray<GuildConfig> AllGuildConfigs { get; }
public BotConfig BotConfig { get; } public BotConfig BotConfig { get; }
public DbService Db { get; } public DbService Db { get; }
@ -97,7 +94,7 @@ namespace NadekoBot
var soundcloudApiService = new SoundCloudApiService(Credentials); var soundcloudApiService = new SoundCloudApiService(Credentials);
var localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db); var localization = new Localization(BotConfig.Locale, AllGuildConfigs.ToDictionary(x => x.GuildId, x => x.Locale), Db);
var strings = new NadekoStrings(localization); var strings = new NadekoStrings(localization);
var commandHandler = new CommandHandler(Client, CommandService, Credentials, this); var commandHandler = new CommandHandler(Client, Db, BotConfig, AllGuildConfigs, CommandService, Credentials, this);
var stats = new StatsService(Client, commandHandler, Credentials); var stats = new StatsService(Client, commandHandler, Credentials);
var images = new ImagesService(); var images = new ImagesService();
var currencyHandler = new CurrencyService(BotConfig, Db); var currencyHandler = new CurrencyService(BotConfig, Db);
@ -112,6 +109,14 @@ namespace NadekoBot
var commandMapService = new CommandMapService(AllGuildConfigs); var commandMapService = new CommandMapService(AllGuildConfigs);
#endregion #endregion
#region permissions
var permissionsService = new PermissionService(Db, BotConfig);
var blacklistService = new BlacklistService(BotConfig);
var cmdcdsService = new CmdCdService(AllGuildConfigs);
var filterService = new FilterService(Client, AllGuildConfigs);
var globalPermsService = new GlobalPermissionService(BotConfig);
#endregion
#region Searches #region Searches
var searchesService = new SearchesService(Client, googleApiService, Db); var searchesService = new SearchesService(Client, googleApiService, Db);
var streamNotificationService = new StreamNotificationService(Db, Client, strings); var streamNotificationService = new StreamNotificationService(Db, Client, strings);
@ -119,12 +124,12 @@ namespace NadekoBot
var clashService = new ClashOfClansService(Client, Db, localization, strings); var clashService = new ClashOfClansService(Client, Db, localization, strings);
var musicService = new MusicService(googleApiService, strings, localization, Db, soundcloudApiService, Credentials, AllGuildConfigs); var musicService = new MusicService(googleApiService, strings, localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
var crService = new CustomReactionsService(Db, Client); var crService = new CustomReactionsService(permissionsService, Db, Client);
var helpService = new HelpService(BotConfig); var helpService = new HelpService(BotConfig);
#region Games #region Games
var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images); var gamesService = new GamesService(Client, BotConfig, AllGuildConfigs, strings, images, commandHandler);
var chatterBotService = new ChatterBotService(Client, AllGuildConfigs); var chatterBotService = new ChatterBotService(Client, permissionsService, AllGuildConfigs);
var pollService = new PollService(Client, strings); var pollService = new PollService(Client, strings);
#endregion #endregion
@ -140,13 +145,9 @@ namespace NadekoBot
var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService); var playingRotateService = new PlayingRotateService(Client, BotConfig, musicService);
var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs); var gameVcService = new GameVoiceChannelService(Client, Db, AllGuildConfigs);
var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs); var autoAssignRoleService = new AutoAssignRoleService(Client, AllGuildConfigs);
var permissionsService = new PermissionsService(Db, BotConfig);
var blacklistService = new BlacklistService(BotConfig);
var cmdcdsService = new CmdCdService(AllGuildConfigs);
var filterService = new FilterService(Client, AllGuildConfigs);
var globalPermsService = new GlobalPermissionService(BotConfig);
#endregion #endregion
//initialize Services //initialize Services
Services = new NServiceProvider.ServiceProviderBuilder() Services = new NServiceProvider.ServiceProviderBuilder()
.Add<ILocalization>(localization) .Add<ILocalization>(localization)
@ -188,7 +189,7 @@ namespace NadekoBot
.Add(gameVcService) .Add(gameVcService)
.Add(autoAssignRoleService) .Add(autoAssignRoleService)
.Add(protectionService) .Add(protectionService)
.Add<PermissionsService>(permissionsService) .Add<PermissionService>(permissionsService)
.Add(blacklistService) .Add(blacklistService)
.Add(cmdcdsService) .Add(cmdcdsService)
.Add(filterService) .Add(filterService)
@ -199,8 +200,8 @@ namespace NadekoBot
//setup typereaders //setup typereaders
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader()); CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader(CommandService)); CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader(CommandService, commandHandler));
CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader(crService, CommandService)); CommandService.AddTypeReader<CommandOrCrInfo>(new CommandOrCrTypeReader(crService, CommandService, commandHandler));
CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService)); CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader(CommandService));
CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService)); CommandService.AddTypeReader<ModuleOrCrInfo>(new ModuleOrCrTypeReader(CommandService));
CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client)); CommandService.AddTypeReader<IGuild>(new GuildTypeReader(Client));

View File

@ -41,6 +41,7 @@
<Compile Include="Modules\Administration\Commands\Migration\MigrationException.cs" /> <Compile Include="Modules\Administration\Commands\Migration\MigrationException.cs" />
<Compile Include="Modules\Administration\Commands\MuteCommands.cs" /> <Compile Include="Modules\Administration\Commands\MuteCommands.cs" />
<Compile Include="Modules\Administration\Commands\PlayingRotateCommands.cs" /> <Compile Include="Modules\Administration\Commands\PlayingRotateCommands.cs" />
<Compile Include="Modules\Administration\Commands\PrefixCommands.cs" />
<Compile Include="Modules\Administration\Commands\ProtectionCommands.cs" /> <Compile Include="Modules\Administration\Commands\ProtectionCommands.cs" />
<Compile Include="Modules\Administration\Commands\RatelimitCommand.cs" /> <Compile Include="Modules\Administration\Commands\RatelimitCommand.cs" />
<Compile Include="Modules\Administration\Commands\SelfAssignedRolesCommand.cs" /> <Compile Include="Modules\Administration\Commands\SelfAssignedRolesCommand.cs" />

View File

@ -3474,4 +3474,22 @@
<data name="resetglobalpermissions_usage" xml:space="preserve"> <data name="resetglobalpermissions_usage" xml:space="preserve">
<value>`{0}resetglobalperms`</value> <value>`{0}resetglobalperms`</value>
</data> </data>
<data name="prefix_cmd" xml:space="preserve">
<value>prefix</value>
</data>
<data name="prefix_usage" xml:space="preserve">
<value>`{0}prefix +`</value>
</data>
<data name="prefix_desc" xml:space="preserve">
<value>Sets this server's prefix for all bot commands. Provide no arguments to see the current server prefix.</value>
</data>
<data name="defprefix_cmd" xml:space="preserve">
<value>defprefix</value>
</data>
<data name="defprefix_usage" xml:space="preserve">
<value>`{0}defprefix +`</value>
</data>
<data name="defprefix_desc" xml:space="preserve">
<value>Sets bot's default prefix for all bot commands. Provide no arguments to see the current default prefix. This will not change this server's current prefix.</value>
</data>
</root> </root>

View File

@ -1,6 +1,7 @@
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
@ -33,9 +34,10 @@ namespace NadekoBot.Services.Administration
_client = client; _client = client;
_db = db; _db = db;
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(gcs GuildMuteRoles = gcs
.Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName)) .Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName))
.ToDictionary(c => c.GuildId, c => c.MuteRoleName)); .ToDictionary(c => c.GuildId, c => c.MuteRoleName)
.ToConcurrent();
MutedUsers = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>(gcs.ToDictionary( MutedUsers = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>(gcs.ToDictionary(
k => k.GuildId, k => k.GuildId,

View File

@ -12,6 +12,8 @@ using System.Threading;
using NadekoBot.DataStructures; using NadekoBot.DataStructures;
using System.Collections.Immutable; using System.Collections.Immutable;
using NadekoBot.DataStructures.ModuleBehaviors; using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Services.Database.Models;
using NadekoBot.Services;
namespace NadekoBot.Services namespace NadekoBot.Services
{ {
@ -31,6 +33,8 @@ namespace NadekoBot.Services
private readonly IBotCredentials _creds; private readonly IBotCredentials _creds;
private readonly NadekoBot _bot; private readonly NadekoBot _bot;
private INServiceProvider _services; private INServiceProvider _services;
public string DefaultPrefix { get; private set; }
private ConcurrentDictionary<ulong, string> _prefixes { get; } = new ConcurrentDictionary<ulong, string>();
private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels { get; set; } = new ImmutableArray<AsyncLazy<IDMChannel>>(); private ImmutableArray<AsyncLazy<IDMChannel>> ownerChannels { get; set; } = new ImmutableArray<AsyncLazy<IDMChannel>>();
@ -42,12 +46,13 @@ namespace NadekoBot.Services
public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>(); public ConcurrentHashSet<ulong> UsersOnShortCooldown { get; } = new ConcurrentHashSet<ulong>();
private readonly Timer _clearUsersOnShortCooldown; private readonly Timer _clearUsersOnShortCooldown;
public CommandHandler(DiscordShardedClient client, CommandService commandService, IBotCredentials credentials, NadekoBot bot) public CommandHandler(DiscordShardedClient client, DbService db, BotConfig bc, IEnumerable<GuildConfig> gcs, CommandService commandService, IBotCredentials credentials, NadekoBot bot)
{ {
_client = client; _client = client;
_commandService = commandService; _commandService = commandService;
_creds = credentials; _creds = credentials;
_bot = bot; _bot = bot;
_db = db;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
@ -55,8 +60,60 @@ namespace NadekoBot.Services
{ {
UsersOnShortCooldown.Clear(); UsersOnShortCooldown.Clear();
}, null, GlobalCommandsCooldown, GlobalCommandsCooldown); }, null, GlobalCommandsCooldown, GlobalCommandsCooldown);
DefaultPrefix = bc.DefaultPrefix;
_prefixes = gcs
.Where(x => x.Prefix != null)
.ToDictionary(x => x.GuildId, x => x.Prefix)
.ToConcurrent();
} }
public string GetPrefix(IGuild guild) => GetPrefix(guild?.Id);
public string GetPrefix(ulong? id)
{
if (id == null || !_prefixes.TryGetValue(id.Value, out var prefix))
return DefaultPrefix;
return prefix;
}
public string SetDefaultPrefix(string prefix)
{
if (string.IsNullOrWhiteSpace(prefix))
throw new ArgumentNullException(nameof(prefix));
prefix = prefix.ToLowerInvariant();
using (var uow = _db.UnitOfWork)
{
uow.BotConfig.GetOrCreate(set => set).DefaultPrefix = prefix;
uow.Complete();
}
return DefaultPrefix = prefix;
}
public string SetPrefix(IGuild guild, string prefix)
{
if (string.IsNullOrWhiteSpace(prefix))
throw new ArgumentNullException(nameof(prefix));
if (guild == null)
throw new ArgumentNullException(nameof(guild));
prefix = prefix.ToLowerInvariant();
using (var uow = _db.UnitOfWork)
{
var gc = uow.GuildConfigs.For(guild.Id, set => set);
gc.Prefix = prefix;
uow.Complete();
}
_prefixes.AddOrUpdate(guild.Id, prefix, (key, old) => prefix);
return prefix;
}
public void AddServices(INServiceProvider services) public void AddServices(INServiceProvider services)
{ {
_services = services; _services = services;
@ -87,13 +144,14 @@ namespace NadekoBot.Services
public Task StartHandling() public Task StartHandling()
{ {
_client.MessageReceived += MessageReceivedHandler; _client.MessageReceived += (msg) => { var _ = Task.Run(() => MessageReceivedHandler(msg)); return Task.CompletedTask; };
return Task.CompletedTask; return Task.CompletedTask;
} }
private const float _oneThousandth = 1.0f / 1000; private const float _oneThousandth = 1.0f / 1000;
private readonly DbService _db;
private Task LogSuccessfulExecution(IUserMessage usrMsg, bool exec, ITextChannel channel, params int[] execPoints) private Task LogSuccessfulExecution(IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
{ {
_log.Info("Command Executed after " + string.Join("/", execPoints.Select(x => x * _oneThousandth)) + "s\n\t" + _log.Info("Command Executed after " + string.Join("/", execPoints.Select(x => x * _oneThousandth)) + "s\n\t" +
"User: {0}\n\t" + "User: {0}\n\t" +
@ -108,7 +166,7 @@ namespace NadekoBot.Services
return Task.CompletedTask; return Task.CompletedTask;
} }
private void LogErroredExecution(IUserMessage usrMsg, bool exec, ITextChannel channel, params int[] execPoints) private void LogErroredExecution(string errorMessage, IUserMessage usrMsg, ITextChannel channel, params int[] execPoints)
{ {
_log.Warn("Command Errored after " + string.Join("/", execPoints.Select(x => x * _oneThousandth)) + "s\n\t" + _log.Warn("Command Errored after " + string.Join("/", execPoints.Select(x => x * _oneThousandth)) + "s\n\t" +
"User: {0}\n\t" + "User: {0}\n\t" +
@ -120,7 +178,7 @@ namespace NadekoBot.Services
(channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1} (channel == null ? "PRIVATE" : channel.Guild.Name + " [" + channel.Guild.Id + "]"), // {1}
(channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2} (channel == null ? "PRIVATE" : channel.Name + " [" + channel.Id + "]"), // {2}
usrMsg.Content,// {3} usrMsg.Content,// {3}
exec errorMessage
//exec.Result.ErrorReason // {4} //exec.Result.ErrorReason // {4}
); );
} }
@ -199,33 +257,25 @@ namespace NadekoBot.Services
break; break;
} }
} }
var prefix = GetPrefix(guild.Id);
// execute the command and measure the time it took // execute the command and measure the time it took
if (messageContent.StartsWith(NadekoBot.Prefix)) if (messageContent.StartsWith(prefix))
{ {
var exec = await Task.Run(() => ExecuteCommandAsync(new CommandContext(_client, usrMsg), messageContent, NadekoBot.Prefix.Length, _services, MultiMatchHandling.Best)).ConfigureAwait(false); var result = await ExecuteCommandAsync(new CommandContext(_client, usrMsg), messageContent, prefix.Length, _services, MultiMatchHandling.Best);
execTime = Environment.TickCount - execTime; execTime = Environment.TickCount - execTime;
////todo commandHandler if (result.Success)
if (exec)
{ {
// await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false); // await CommandExecuted(usrMsg, exec.CommandInfo).ConfigureAwait(false);
await LogSuccessfulExecution(usrMsg, exec, channel as ITextChannel, exec2, exec3, execTime).ConfigureAwait(false); await LogSuccessfulExecution(usrMsg, channel as ITextChannel, exec2, exec3, execTime).ConfigureAwait(false);
return; return;
} }
//else if (!exec.Result.IsSuccess && exec.Result.Error != CommandError.UnknownCommand) else if (result.Error != null)
//{ {
// LogErroredExecution(usrMsg, exec, channel, exec2, exec3, execTime); //todo 80 should have log levels and it should return some kind of result,
// if (guild != null && exec.CommandInfo != null && exec.Result.Error == CommandError.Exception) // instead of tuple with the type of thing that went wrong, like before
// { LogErroredExecution(result.Error, usrMsg, channel as ITextChannel, exec2, exec3, execTime);
// if (exec.PermissionCache != null && exec.PermissionCache.Verbose) }
// try { await usrMsg.Channel.SendMessageAsync("⚠️ " + exec.Result.ErrorReason).ConfigureAwait(false); } catch { }
// }
// return;
//}
if (exec)
return;
} }
@ -239,15 +289,15 @@ namespace NadekoBot.Services
} }
public Task<bool> ExecuteCommandAsync(CommandContext context, string input, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) public Task<(bool Success, string Error)> ExecuteCommandAsync(CommandContext context, string input, int argPos, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
=> ExecuteCommand(context, input.Substring(argPos), serviceProvider, multiMatchHandling); => ExecuteCommand(context, input.Substring(argPos), serviceProvider, multiMatchHandling);
public async Task<bool> ExecuteCommand(CommandContext context, string input, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception) public async Task<(bool Success, string Error)> ExecuteCommand(CommandContext context, string input, IServiceProvider serviceProvider, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
{ {
var searchResult = _commandService.Search(context, input); var searchResult = _commandService.Search(context, input);
if (!searchResult.IsSuccess) if (!searchResult.IsSuccess)
return false; return (false, null);
var commands = searchResult.Commands; var commands = searchResult.Commands;
for (int i = commands.Count - 1; i >= 0; i--) for (int i = commands.Count - 1; i >= 0; i--)
@ -256,7 +306,7 @@ namespace NadekoBot.Services
if (!preconditionResult.IsSuccess) if (!preconditionResult.IsSuccess)
{ {
if (commands.Count == 1) if (commands.Count == 1)
return false; return (false, null);
else else
continue; continue;
} }
@ -280,33 +330,18 @@ namespace NadekoBot.Services
if (!parseResult.IsSuccess) if (!parseResult.IsSuccess)
{ {
if (commands.Count == 1) if (commands.Count == 1)
return false; return (false, null);
else else
continue; continue;
} }
} }
var cmd = commands[i].Command; var cmd = commands[i].Command;
var resetCommand = cmd.Name == "resetperms";
var module = cmd.Module.GetTopLevelModule();
if (context.Guild != null)
{
//////future
////int price;
////if (Permissions.CommandCostCommands.CommandCosts.TryGetValue(cmd.Aliases.First().Trim().ToLowerInvariant(), out price) && price > 0)
////{
//// var success = await _cs.RemoveCurrencyAsync(context.User.Id, $"Running {cmd.Name} command.", price).ConfigureAwait(false);
//// if (!success)
//// {
//// return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"Insufficient funds. You need {price}{NadekoBot.BotConfig.CurrencySign} to run this command."));
//// }
////}
}
// Bot will ignore commands which are ran more often than what specified by // Bot will ignore commands which are ran more often than what specified by
// GlobalCommandsCooldown constant (miliseconds) // GlobalCommandsCooldown constant (miliseconds)
if (!UsersOnShortCooldown.Add(context.Message.Author.Id)) if (!UsersOnShortCooldown.Add(context.Message.Author.Id))
return false; return (false, null);
//return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown."); //return SearchResult.FromError(CommandError.Exception, "You are on a global cooldown.");
var commandName = cmd.Aliases.First(); var commandName = cmd.Aliases.First();
@ -316,15 +351,17 @@ namespace NadekoBot.Services
await exec.TryBlockLate(_client, context.Message, context.Guild, context.Channel, context.User, cmd.Module.GetTopLevelModule().Name, commandName).ConfigureAwait(false)) await exec.TryBlockLate(_client, context.Message, context.Guild, context.Channel, context.User, cmd.Module.GetTopLevelModule().Name, commandName).ConfigureAwait(false))
{ {
_log.Info("Late blocking User [{0}] Command: [{1}] in [{2}]", context.User, commandName, svc.GetType().Name); _log.Info("Late blocking User [{0}] Command: [{1}] in [{2}]", context.User, commandName, svc.GetType().Name);
return false; return (false, null);
} }
} }
await commands[i].ExecuteAsync(context, parseResult, serviceProvider); var execResult = await commands[i].ExecuteAsync(context, parseResult, serviceProvider);
return true; if (execResult.Exception != null) //todo temp, to not be blind
_log.Warn(execResult.Exception);
return (true, null);
} }
return false; return (false, null);
//return new ExecuteCommandResult(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload.")); //return new ExecuteCommandResult(null, null, SearchResult.FromError(CommandError.UnknownCommand, "This input does not match any overload."));
} }
} }

View File

@ -9,6 +9,7 @@ using System.Linq;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services.Permissions; using NadekoBot.Services.Permissions;
using NadekoBot.Extensions;
namespace NadekoBot.Services.CustomReactions namespace NadekoBot.Services.CustomReactions
{ {
@ -22,9 +23,9 @@ namespace NadekoBot.Services.CustomReactions
private readonly Logger _log; private readonly Logger _log;
private readonly DbService _db; private readonly DbService _db;
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly PermissionsService _perms; private readonly PermissionService _perms;
public CustomReactionsService(PermissionsService perms, DbService db, DiscordShardedClient client) public CustomReactionsService(PermissionService perms, DbService db, DiscordShardedClient client)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_db = db; _db = db;
@ -100,16 +101,18 @@ namespace NadekoBot.Services.CustomReactions
{ {
try try
{ {
//todo permissions
if (guild is SocketGuild sg) if (guild is SocketGuild sg)
{ {
PermissionCache pc = _perms.GetCache(guild.Id); var pc = _perms.GetCache(guild.Id);
if (!pc.Permissions.CheckPermissions(msg, cr.Trigger, "ActualCustomReactions", if (!pc.Permissions.CheckPermissions(msg, cr.Trigger, "ActualCustomReactions",
out int index)) out int index))
{ {
var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(sg)}** is preventing this action."; if (pc.Verbose)
_log.Info(returnMsg); {
var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(sg)}** is preventing this action.";
try { await msg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
_log.Info(returnMsg);
}
return true; return true;
} }
} }

View File

@ -65,6 +65,7 @@ Nadeko Support Server: https://discord.gg/nadekobot";
public HashSet<BlockedCmdOrMdl> BlockedCommands { get; set; } public HashSet<BlockedCmdOrMdl> BlockedCommands { get; set; }
public HashSet<BlockedCmdOrMdl> BlockedModules { get; set; } public HashSet<BlockedCmdOrMdl> BlockedModules { get; set; }
public int PermissionVersion { get; set; } = 1; public int PermissionVersion { get; set; } = 1;
public string DefaultPrefix { get; set; } = ".";
} }
public class BlockedCmdOrMdl : DbEntity public class BlockedCmdOrMdl : DbEntity

View File

@ -6,6 +6,9 @@ namespace NadekoBot.Services.Database.Models
public class GuildConfig : DbEntity public class GuildConfig : DbEntity
{ {
public ulong GuildId { get; set; } public ulong GuildId { get; set; }
public string Prefix { get; set; } = null;
public bool DeleteMessageOnCommand { get; set; } public bool DeleteMessageOnCommand { get; set; }
public ulong AutoAssignRoleId { get; set; } public ulong AutoAssignRoleId { get; set; }
//greet stuff //greet stuff

View File

@ -3,6 +3,7 @@ using Discord.WebSocket;
using NadekoBot.DataStructures.ModuleBehaviors; using NadekoBot.DataStructures.ModuleBehaviors;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Services.Permissions;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
@ -16,13 +17,15 @@ namespace NadekoBot.Services.Games
{ {
private readonly DiscordShardedClient _client; private readonly DiscordShardedClient _client;
private readonly Logger _log; private readonly Logger _log;
private readonly PermissionService _perms;
public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> ChatterBotGuilds { get; } public ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> ChatterBotGuilds { get; }
public ChatterBotService(DiscordShardedClient client, IEnumerable<GuildConfig> gcs) public ChatterBotService(DiscordShardedClient client, PermissionService perms, IEnumerable<GuildConfig> gcs)
{ {
_client = client; _client = client;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_perms = perms;
ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>( ChatterBotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
gcs.Where(gc => gc.CleverbotEnabled) gcs.Where(gc => gc.CleverbotEnabled)
@ -80,27 +83,29 @@ namespace NadekoBot.Services.Games
public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg) public async Task<bool> TryExecuteEarly(DiscordShardedClient client, IGuild guild, IUserMessage usrMsg)
{ {
if (guild == null) if (!(guild is SocketGuild sg))
return false; return false;
try try
{ {
var message = PrepareMessage(usrMsg, out ChatterBotSession cbs); var message = PrepareMessage(usrMsg, out ChatterBotSession cbs);
if (message == null || cbs == null) if (message == null || cbs == null)
return false; return false;
//todo permissions var pc = _perms.GetCache(guild.Id);
//PermissionCache pc = Permissions.GetCache(guild.Id); if (!pc.Permissions.CheckPermissions(usrMsg,
//if (!pc.Permissions.CheckPermissions(usrMsg, "cleverbot",
// NadekoBot.Prefix + "cleverbot", "Games".ToLowerInvariant(),
// "Games".ToLowerInvariant(), out int index))
// out int index)) {
//{ if (pc.Verbose)
// //todo 46 print in guild actually {
// var returnMsg = //todo move this to permissions, prefix is always "." as a placeholder, fix that when you move it
// $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(guild)}** is preventing this action."; var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand(sg)}** is preventing this action.";
// _log.Info(returnMsg); try { await usrMsg.Channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
// return true; _log.Info(returnMsg);
//} }
return true;
}
var cleverbotExecuted = await TryAsk(cbs, (ITextChannel)usrMsg.Channel, message).ConfigureAwait(false); var cleverbotExecuted = await TryAsk(cbs, (ITextChannel)usrMsg.Channel, message).ConfigureAwait(false);
if (cleverbotExecuted) if (cleverbotExecuted)

View File

@ -29,15 +29,18 @@ namespace NadekoBot.Services.Games
private readonly Logger _log; private readonly Logger _log;
public readonly string TypingArticlesPath = "data/typing_articles2.json"; public readonly string TypingArticlesPath = "data/typing_articles2.json";
private readonly CommandHandler _cmdHandler;
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>(); public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
public GamesService(DiscordShardedClient client, BotConfig bc, IEnumerable<GuildConfig> gcs, public GamesService(DiscordShardedClient client, BotConfig bc, IEnumerable<GuildConfig> gcs,
NadekoStrings strings, IImagesService images) NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
{ {
_bc = bc; _bc = bc;
_client = client; _client = client;
_strings = strings; _strings = strings;
_images = images; _images = images;
_cmdHandler = cmdHandler;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
//8ball //8ball
@ -123,7 +126,7 @@ namespace NadekoBot.Services.Games
if (dropAmount > 0) if (dropAmount > 0)
{ {
var msgs = new IUserMessage[dropAmount]; var msgs = new IUserMessage[dropAmount];
var prefix = NadekoBot.Prefix; var prefix = _cmdHandler.GetPrefix(channel.Guild.Id);
var toSend = dropAmount == 1 var toSend = dropAmount == 1
? GetText(channel, "curgen_sn", _bc.CurrencySign) ? GetText(channel, "curgen_sn", _bc.CurrencySign)
+ " " + GetText(channel, "pick_sn", prefix) + " " + GetText(channel, "pick_sn", prefix)

View File

@ -90,7 +90,7 @@ namespace NadekoBot.Services.Music
case MusicType.Radio: case MusicType.Radio:
return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links return "https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
case MusicType.Normal: case MusicType.Normal:
//todo have videoid in songinfo from the start //todo 50 have videoid in songinfo from the start
var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+"); var videoId = Regex.Match(SongInfo.Query, "<=v=[a-zA-Z0-9-]+(?=&)|(?<=[0-9])[^&\n]+|(?<=v=)[^&\n]+");
return $"https://img.youtube.com/vi/{ videoId }/0.jpg"; return $"https://img.youtube.com/vi/{ videoId }/0.jpg";
case MusicType.Local: case MusicType.Local:

View File

@ -116,7 +116,7 @@ namespace NadekoBot.Services.Permissions
break; break;
} }
return NadekoBot.Prefix + com; return "." + com;
} }
public static IEnumerable<Permission> AsEnumerable(this Permission perm) public static IEnumerable<Permission> AsEnumerable(this Permission perm)

View File

@ -9,10 +9,11 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord; using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions;
namespace NadekoBot.Services.Permissions namespace NadekoBot.Services.Permissions
{ {
public class PermissionsService : ILateBlocker public class PermissionService : ILateBlocker
{ {
private readonly DbService _db; private readonly DbService _db;
private readonly Logger _log; private readonly Logger _log;
@ -21,7 +22,7 @@ namespace NadekoBot.Services.Permissions
public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } = public ConcurrentDictionary<ulong, PermissionCache> Cache { get; } =
new ConcurrentDictionary<ulong, PermissionCache>(); new ConcurrentDictionary<ulong, PermissionCache>();
public PermissionsService(DbService db, BotConfig bc) public PermissionService(DbService db, BotConfig bc)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_db = db; _db = db;
@ -177,6 +178,8 @@ namespace NadekoBot.Services.Permissions
if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index)) if (!resetCommand && !pc.Permissions.CheckPermissions(msg, commandName, moduleName, out int index))
{ {
var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand((SocketGuild)guild)}** is preventing this action."; var returnMsg = $"Permission number #{index + 1} **{pc.Permissions[index].GetCommand((SocketGuild)guild)}** is preventing this action.";
if (pc.Verbose)
try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
return true; return true;
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); //return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
} }
@ -187,6 +190,9 @@ namespace NadekoBot.Services.Permissions
var roles = (user as SocketGuildUser)?.Roles ?? ((IGuildUser)user).RoleIds.Select(x => guild.GetRole(x)).Where(x => x != null); var roles = (user as SocketGuildUser)?.Roles ?? ((IGuildUser)user).RoleIds.Select(x => guild.GetRole(x)).Where(x => x != null);
if (!roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()) && user.Id != ((IGuildUser)user).Guild.OwnerId) if (!roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()) && user.Id != ((IGuildUser)user).Guild.OwnerId)
{ {
var returnMsg = $"You need the **{pc.PermRole}** role in order to use permission commands.";
if (pc.Verbose)
try { await channel.SendErrorAsync(returnMsg).ConfigureAwait(false); } catch { }
return true; return true;
//return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands.")); //return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, $"You need the **{pc.PermRole}** role in order to use permission commands."));
} }

View File

@ -35,8 +35,7 @@ namespace NadekoBot.Services.Utility
if (guild == null || string.IsNullOrWhiteSpace(input)) if (guild == null || string.IsNullOrWhiteSpace(input))
return input; return input;
//todo alias mapping
if (guild != null) if (guild != null)
{ {
input = input.ToLowerInvariant(); input = input.ToLowerInvariant();

View File

@ -18,6 +18,9 @@ namespace NadekoBot.Extensions
{ {
public static class Extensions public static class Extensions
{ {
public static ConcurrentDictionary<TKey, TValue> ToConcurrent<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> dict)
=> new ConcurrentDictionary<TKey, TValue>(dict);
public static bool IsAuthor(this IMessage msg, IDiscordClient client) => public static bool IsAuthor(this IMessage msg, IDiscordClient client) =>
msg.Author?.Id == client.CurrentUser.Id; msg.Author?.Id == client.CurrentUser.Id;

View File

@ -165,14 +165,14 @@
"administration_rc": "Color of {0} role has been changed.", "administration_rc": "Color of {0} role has been changed.",
"administration_rc_not_exist": "That role does not exist.", "administration_rc_not_exist": "That role does not exist.",
"administration_rc_params": "The parameters specified are invalid.", "administration_rc_params": "The parameters specified are invalid.",
"administration_rc_perms": "Error occured due to invalid color or insufficient permissions.", "administration_rc_perms": "Error occurred due to invalid color or insufficient permissions.",
"administration_remrole": "Successfully removed role {0} from user {1}", "administration_remrole": "Successfully removed role {0} from user {1}",
"administration_remrole_err": "Failed to remove role. I have insufficient permissions.", "administration_remrole_err": "Failed to remove role. I have insufficient permissions.",
"administration_renrole": "Role renamed.", "administration_renrole": "Role renamed.",
"administration_renrole_err": "Failed to rename role. I have insufficient permissions.", "administration_renrole_err": "Failed to rename role. I have insufficient permissions.",
"administration_renrole_perms": "You can't edit roles higher than your highest role.", "administration_renrole_perms": "You can't edit roles higher than your highest role.",
"administration_reprm": "Removed the playing message: {0}", "administration_reprm": "Removed the playing message: {0}",
"administration_role_added": "Role {0} as been added to the list.", "administration_role_added": "Role {0} has been added to the list.",
"administration_role_clean": "{0} not found.Cleaned up.", "administration_role_clean": "{0} not found.Cleaned up.",
"administration_role_in_list": "Role {0} is already in the list.", "administration_role_in_list": "Role {0} is already in the list.",
"administration_ropl_added": "Added.", "administration_ropl_added": "Added.",
@ -236,7 +236,7 @@
"administration_vt_enabled": "Enabled voice + text feature.", "administration_vt_enabled": "Enabled voice + text feature.",
"administration_vt_exit": "I don't have **manage roles** and/or **manage channels** permission, so I cannot run `voice+text` on {0} server.", "administration_vt_exit": "I don't have **manage roles** and/or **manage channels** permission, so I cannot run `voice+text` on {0} server.",
"administration_vt_no_admin": "You are enabling/disabling this feature and **I do not have ADMINISTRATOR permissions**. This may cause some issues, and you will have to clean up text channels yourself afterwards.", "administration_vt_no_admin": "You are enabling/disabling this feature and **I do not have ADMINISTRATOR permissions**. This may cause some issues, and you will have to clean up text channels yourself afterwards.",
"administration_vt_perms": "I require atleast **manage roles** and **manage channels** permissions to enable this feature. (preffered Administration permission)", "administration_vt_perms": "I require at least **manage roles** and **manage channels** permissions to enable this feature. (preferred Administration permission)",
"administration_xmuted_text": "User {0} from text chat", "administration_xmuted_text": "User {0} from text chat",
"administration_xmuted_text_and_voice": "User {0} from text and voice chat", "administration_xmuted_text_and_voice": "User {0} from text and voice chat",
"administration_xmuted_voice": "User {0} from voice chat", "administration_xmuted_voice": "User {0} from voice chat",
@ -519,7 +519,7 @@
"searches_define": "Define:", "searches_define": "Define:",
"searches_dropped": "Dropped", "searches_dropped": "Dropped",
"searches_episodes": "Episodes", "searches_episodes": "Episodes",
"searches_error_occured": "Error occured.", "searches_error_occured": "Error occurred.",
"searches_example": "Example", "searches_example": "Example",
"searches_failed_finding_anime": "Failed finding that animu.", "searches_failed_finding_anime": "Failed finding that animu.",
"searches_failed_finding_manga": "Failed finding that mango.", "searches_failed_finding_manga": "Failed finding that mango.",
@ -605,9 +605,9 @@
"utility_convert_not_found": "Cannot convert {0} to {1}: units not found", "utility_convert_not_found": "Cannot convert {0} to {1}: units not found",
"utility_convert_type_error": "Cannot convert {0} to {1}: types of unit are not equal", "utility_convert_type_error": "Cannot convert {0} to {1}: types of unit are not equal",
"utility_created_at": "Created at", "utility_created_at": "Created at",
"utility_chc_join": "Joined cross server channel.", "utility_csc_join": "Joined cross server channel.",
"utility_chc_leave": "Left cross server channel.", "utility_csc_leave": "Left cross server channel.",
"utility_chc_token": "This is your CSC token", "utility_csc_token": "This is your CSC token",
"utility_custom_emojis": "Custom emojis", "utility_custom_emojis": "Custom emojis",
"utility_error": "Error", "utility_error": "Error",
"utility_features": "Features", "utility_features": "Features",
@ -638,7 +638,7 @@
"utility_presence_txt": "{0} Servers\n{1} Text Channels\n{2} Voice Channels", "utility_presence_txt": "{0} Servers\n{1} Text Channels\n{2} Voice Channels",
"utility_quotes_deleted": "Deleted all quotes with {0} keyword.", "utility_quotes_deleted": "Deleted all quotes with {0} keyword.",
"utility_quotes_page": "Page {0} of quotes", "utility_quotes_page": "Page {0} of quotes",
"utility_quotes_page_none": "No quotes found matching the quote ID specified.", "utility_quotes_page_none": "No quotes found on that page.",
"utility_quotes_remove_none": "No quotes found which you can remove.", "utility_quotes_remove_none": "No quotes found which you can remove.",
"utility_quote_added": "Quote Added", "utility_quote_added": "Quote Added",
"utility_quote_deleted": "Quote #{0} deleted.", "utility_quote_deleted": "Quote #{0} deleted.",
@ -779,5 +779,12 @@
"permissions_gcmd_remove": "Command {0} has been enabled on all servers.", "permissions_gcmd_remove": "Command {0} has been enabled on all servers.",
"permissions_gmod_add": "Module {0} has been disabled on all servers.", "permissions_gmod_add": "Module {0} has been disabled on all servers.",
"permissions_gmod_remove": "Module {0} has been enabled on all servers.", "permissions_gmod_remove": "Module {0} has been enabled on all servers.",
"permissions_lgp_none": "No blocked commands or modules." "permissions_lgp_none": "No blocked commands or modules.",
"gambling_animal_race_no_race": "This Animal Race is full!",
"utility_cant_read_or_send": "You can't read from or send messages to that channel.",
"utility_quotes_notfound": "No quotes found matching the quote ID specified.",
"administration_prefix_current": "Prefix on this server is {0}",
"administration_prefix_new": "Changed prefix on this server from {0} to {1}",
"administration_defprefix_current": "Default bot prefix is {0}",
"administration_defprefix_new": "Changed Default bot prefix from {0} to {1}"
} }