Merge pull request #940 from Kwoth/dev

1.1 beta
This commit is contained in:
Master Kwoth 2017-01-03 16:19:19 +01:00 committed by GitHub
commit a42abd6bcc
101 changed files with 2600 additions and 3067 deletions

8
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "discord.net"] [submodule "Discord.Net"]
path = discord.net path = Discord.Net
url = https://github.com/kwoth/discord.net url = https://github.com/Kwoth/Discord.Net
branch = dev branch = rogue-dev

1
Discord.Net Submodule

@ -0,0 +1 @@
Subproject commit fa2568bc312ba35f1518e47601c62fccdb949731

View File

@ -12,10 +12,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NadekoBot", "src\NadekoBot\NadekoBot.xproj", "{45EC1473-C678-4857-A544-07DFE0D0B478}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "NadekoBot", "src\NadekoBot\NadekoBot.xproj", "{45EC1473-C678-4857-A544-07DFE0D0B478}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net", "discord.net\src\Discord.Net\Discord.Net.xproj", "{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.API", "discord.net\src\Discord.Net.API\Discord.Net.API.xproj", "{834C70DF-1230-4AAA-9C13-48AB232E8D76}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "discord.net\src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}" Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Commands", "discord.net\src\Discord.Net.Commands\Discord.Net.Commands.xproj", "{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}"
EndProject EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Core", "discord.net\src\Discord.Net.Core\Discord.Net.Core.xproj", "{E5F4786F-58F3-469E-8C87-1908A95436B7}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.Rest", "discord.net\src\Discord.Net.Rest\Discord.Net.Rest.xproj", "{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Discord.Net.WebSocket", "discord.net\src\Discord.Net.WebSocket\Discord.Net.WebSocket.xproj", "{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -25,22 +31,40 @@ Global
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{45EC1473-C678-4857-A544-07DFE0D0B478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{45EC1473-C678-4857-A544-07DFE0D0B478}.Debug|Any CPU.Build.0 = Debug|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45EC1473-C678-4857-A544-07DFE0D0B478}.GlobalNadeko|Any CPU.ActiveCfg = GlobalNadeko|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.GlobalNadeko|Any CPU.ActiveCfg = Release|Any CPU
{45EC1473-C678-4857-A544-07DFE0D0B478}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.GlobalNadeko|Any CPU.Build.0 = Release|Any CPU
{45EC1473-C678-4857-A544-07DFE0D0B478}.Release|Any CPU.ActiveCfg = Release|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45EC1473-C678-4857-A544-07DFE0D0B478}.Release|Any CPU.Build.0 = Release|Any CPU {45EC1473-C678-4857-A544-07DFE0D0B478}.Release|Any CPU.Build.0 = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.GlobalNadeko|Any CPU.ActiveCfg = GlobalNadeko|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91E9E7BD-75C9-4E98-84AA-2C271922E5C2}.Release|Any CPU.Build.0 = Release|Any CPU {834C70DF-1230-4AAA-9C13-48AB232E8D76}.Release|Any CPU.Build.0 = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.ActiveCfg = GlobalNadeko|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.Build.0 = GlobalNadeko|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU {078DD7E6-943D-4D09-AFC2-D2BA58B76C9C}.Release|Any CPU.Build.0 = Release|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5F4786F-58F3-469E-8C87-1908A95436B7}.Release|Any CPU.Build.0 = Release|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63F5B5C8-56FE-4B53-8003-B58CEB451EF9}.Release|Any CPU.Build.0 = Release|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.GlobalNadeko|Any CPU.ActiveCfg = Debug|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.GlobalNadeko|Any CPU.Build.0 = Debug|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E9800F7A-3354-41B1-BDBB-2D59F8124EC9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

@ -1 +0,0 @@
Subproject commit 508026d5d4f4d8780d983c63ab25e4c15ad69e59

View File

@ -60,7 +60,7 @@ Command and aliases | Description | Usage
`.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable` `.logserver` | Enables or Disables ALL log events. If enabled, all log events will log to this channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logserver enable` or `.logserver disable`
`.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore` `.logignore` | Toggles whether the .logserver command ignores this channel. Useful if you have hidden admin channel and public log channel. **Requires Administrator server permission.** **Bot Owner only.** | `.logignore`
`.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents` `.logevents` | Shows a list of all events you can subscribe to with `.log` **Requires Administrator server permission.** **Bot Owner only.** | `.logevents`
`.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a lit of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner only.** | `.log userpresence` or `.log userbanned` `.log` | Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `.logevents` to see a list of all events you can subscribe to. **Requires Administrator server permission.** **Bot Owner only.** | `.log userpresence` or `.log userbanned`
`.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv` `.repeatinvoke` `.repinv` | Immediately shows the repeat message and restarts the timer. **Requires ManageMessages server permission.** | `.repinv`
`.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there` `.repeat` | Repeat a message every X minutes. If no parameters are specified, repeat is disabled. **Requires ManageMessages server permission.** | `.repeat 5 Hello there`
`.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata` `.migratedata` | Migrate data from old bot configuration **Bot Owner only.** | `.migratedata`
@ -228,6 +228,7 @@ Command and aliases | Description | Usage
Command and aliases | Description | Usage Command and aliases | Description | Usage
----------------|--------------|------- ----------------|--------------|-------
`~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri` `~hentai` | Shows a hentai image from a random website (gelbooru or danbooru or konachan or atfbooru or yandere) with a given tag. Tag is optional but preferred. Only 1 tag allowed. | `~hentai yuri`
`~autohentai` | Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable. | `~autohentai 30 yuri|tail|long_hair` or `~autohentai`
`~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri` `~hentaibomb` | Shows a total 5 images (from gelbooru, danbooru, konachan, yandere and atfbooru). Tag is optional but preferred. | `~hentaibomb yuri`
`~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing` `~danbooru` | Shows a random hentai image from danbooru with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~danbooru yuri+kissing`
`~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2` `~yandere` | Shows a random image from yandere with a given tag. Tag is optional but preferred. (multiple tags are appended with +) | `~yandere tag1+tag2`
@ -368,6 +369,7 @@ Command and aliases | Description | Usage
`.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | `.sinfo Some Server` `.serverinfo` `.sinfo` | Shows info about the server the bot is on. If no channel is supplied, it defaults to current one. | `.sinfo Some Server`
`.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel` `.channelinfo` `.cinfo` | Shows info about the channel. If no channel is supplied, it defaults to current one. | `.cinfo #some-channel`
`.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser` `.userinfo` `.uinfo` | Shows info about the user. If no user is supplied, it defaults a user running the command. | `.uinfo @SomeUser`
`.activity` | Checks for spammers. **Bot Owner only.** | `.activity`
`.listquotes` `.liqu` | `.liqu` or `.liqu 3` | Lists all quotes on the server ordered alphabetically. 15 Per page. `.listquotes` `.liqu` | `.liqu` or `.liqu 3` | Lists all quotes on the server ordered alphabetically. 15 Per page.
`...` | Shows a random quote with a specified name. | `... abc` `...` | Shows a random quote with a specified name. | `... abc`
`..` | Adds a new quote with the specified name and message. | `.. sayhi Hi` `..` | Adds a new quote with the specified name and message. | `.. sayhi Hi`

View File

@ -1,3 +1,3 @@
{ {
"projects": [ "discord.net/src", "src" ] "projects": [ "Discord.Net/src", "src" ]
} }

View File

@ -4,12 +4,11 @@ TITLE Downloading NadekoBot, please wait
SET root=%~dp0 SET root=%~dp0
CD /D %root% CD /D %root%
SET rootdir=%cd% SET rootdir=%cd%
SET build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.API\ SET build1=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\
SET build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Core\ SET build2=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\
SET build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Rest\ SET build3=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\
SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.WebSocket\ SET build4=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\
SET build5=%root%NadekoInstall_Temp\NadekoBot\Discord.Net\src\Discord.Net.Commands\ SET build5=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\
SET build6=%root%NadekoInstall_Temp\NadekoBot\src\NadekoBot\
SET installtemp=%root%NadekoInstall_Temp\ SET installtemp=%root%NadekoInstall_Temp\
::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists ::Deleting traces of last setup for the sake of clean folders, if by some miracle it still exists
IF EXIST %installtemp% ( RMDIR %installtemp% /S /Q >nul 2>&1) IF EXIST %installtemp% ( RMDIR %installtemp% /S /Q >nul 2>&1)
@ -39,8 +38,6 @@ CD /D %build4%
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
CD /D %build5% CD /D %build5%
dotnet restore >nul 2>&1 dotnet restore >nul 2>&1
CD /D %build6%
dotnet restore >nul 2>&1
dotnet build --configuration Release >nul 2>&1 dotnet build --configuration Release >nul 2>&1
::Attempts to backup old files if they currently exist in the same folder as the batch file ::Attempts to backup old files if they currently exist in the same folder as the batch file
IF EXIST "%root%NadekoBot\" (GOTO :backupinstall) IF EXIST "%root%NadekoBot\" (GOTO :backupinstall)

View File

@ -7,7 +7,7 @@ using System.Linq;
namespace NadekoBot.Attributes namespace NadekoBot.Attributes
{ {
[System.AttributeUsage(AttributeTargets.Class)] [System.AttributeUsage(AttributeTargets.Class)]
sealed class NadekoModuleAttribute : ModuleAttribute sealed class NadekoModuleAttribute : GroupAttribute
{ {
//modulename / prefix //modulename / prefix
private static Dictionary<string, string> modulePrefixes = null; private static Dictionary<string, string> modulePrefixes = null;
@ -26,9 +26,9 @@ namespace NadekoBot.Attributes
} }
} }
public NadekoModuleAttribute(string moduleName, string defaultPrefix) : base(GetModulePrefix(moduleName, defaultPrefix)) public NadekoModuleAttribute(string moduleName, string defaultPrefix) : base(GetModulePrefix(moduleName, defaultPrefix), moduleName)
{ {
AppendSpace = false; //AppendSpace = false;
} }
private static string GetModulePrefix(string moduleName, string defaultPrefix) private static string GetModulePrefix(string moduleName, string defaultPrefix)

View File

@ -1,12 +1,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord.Commands; using Discord.Commands;
using Discord;
namespace NadekoBot.Attributes namespace NadekoBot.Attributes
{ {
public class OwnerOnlyAttribute : PreconditionAttribute public class OwnerOnlyAttribute : PreconditionAttribute
{ {
public override Task<PreconditionResult> CheckPermissions(IUserMessage context, Command executingCommand, object moduleInstance) => public override Task<PreconditionResult> CheckPermissions(ICommandContext context, CommandInfo executingCommand,IDependencyMap depMap) =>
Task.FromResult((NadekoBot.Credentials.IsOwner(context.Author) ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner"))); Task.FromResult((NadekoBot.Credentials.IsOwner(context.User) ? PreconditionResult.FromSuccess() : PreconditionResult.FromError("Not owner")));
} }
} }

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -1,6 +1,4 @@
using System; using Microsoft.EntityFrameworkCore.Migrations;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -2,10 +2,7 @@
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;
using NadekoBot.Modules.Music.Classes;
namespace NadekoBot.Migrations namespace NadekoBot.Migrations
{ {

View File

@ -16,8 +16,6 @@ using System.IO;
using static NadekoBot.Modules.Permissions.Permissions; using static NadekoBot.Modules.Permissions.Permissions;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NLog; using NLog;
using NadekoBot.Services.Database;
using Microsoft.EntityFrameworkCore;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
@ -27,36 +25,27 @@ namespace NadekoBot.Modules.Administration
private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>(); private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>();
private new static Logger _log { get; } private static ConcurrentHashSet<ulong> DeleteMessagesOnCommand { get; } = new ConcurrentHashSet<ulong>();
public Administration() : base() private new static Logger _log { get; }
{
}
static Administration() static Administration()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler; NadekoBot.CommandHandler.CommandExecuted += DelMsgOnCmd_Handler;
DeleteMessagesOnCommand = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs.Where(g => g.DeleteMessageOnCommand).Select(g => g.GuildId));
} }
private static async Task DelMsgOnCmd_Handler(IUserMessage msg, Command cmd) private static async Task DelMsgOnCmd_Handler(SocketUserMessage msg, CommandInfo cmd)
{ {
try try
{ {
var channel = msg.Channel as ITextChannel; var channel = msg.Channel as SocketTextChannel;
if (channel == null) if (channel == null)
return; return;
if (DeleteMessagesOnCommand.Contains(channel.Guild.Id))
//todo cache this
bool shouldDelete;
using (var uow = DbHandler.UnitOfWork())
{
shouldDelete = uow.GuildConfigs.For(channel.Guild.Id, set => set).DeleteMessageOnCommand;
}
if (shouldDelete)
await msg.DeleteAsync().ConfigureAwait(false); await msg.DeleteAsync().ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
@ -67,14 +56,13 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task ResetPermissions(IUserMessage imsg) public async Task ResetPermissions()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(channel.Guild.Id); var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
config.RootPermission = Permission.GetDefaultRoot(); config.RootPermission = Permission.GetDefaultRoot();
var toAdd = new PermissionCache() var toAdd = new PermissionCache()
{ {
@ -87,143 +75,138 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
await channel.SendConfirmAsync($"{imsg.Author.Mention} 🆗 **Permissions for this server are reset.**"); await channel.SendConfirmAsync($"{Context.Message.Author.Mention} 🆗 **Permissions for this server are reset.**");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task Delmsgoncmd(IUserMessage umsg) public async Task Delmsgoncmd()
{ {
var channel = (ITextChannel)umsg.Channel;
bool enabled; bool enabled;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var conf = uow.GuildConfigs.For(channel.Guild.Id, set => set); var conf = uow.GuildConfigs.For(Context.Guild.Id, set => set);
enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand; enabled = conf.DeleteMessageOnCommand = !conf.DeleteMessageOnCommand;
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
if (enabled) if (enabled)
await channel.SendConfirmAsync("✅ **Now automatically deleting successful command invokations.**").ConfigureAwait(false); {
DeleteMessagesOnCommand.Add(Context.Guild.Id);
await Context.Channel.SendConfirmAsync("✅ **Now automatically deleting successful command invokations.**").ConfigureAwait(false);
}
else else
await channel.SendConfirmAsync("❗**Stopped automatic deletion of successful command invokations.**").ConfigureAwait(false); {
DeleteMessagesOnCommand.TryRemove(Context.Guild.Id);
await Context.Channel.SendConfirmAsync("❗**Stopped automatic deletion of successful command invokations.**").ConfigureAwait(false);
}
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task Setrole(IUserMessage umsg, IGuildUser usr, [Remainder] IRole role) public async Task Setrole(IGuildUser usr, [Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await usr.AddRolesAsync(role).ConfigureAwait(false); await usr.AddRolesAsync(role).ConfigureAwait(false);
await channel.SendConfirmAsync($" Successfully added role **{role.Name}** to user **{usr.Username}**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" Successfully added role **{role.Name}** to user **{usr.Username}**").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync("⚠️ Failed to add role. **Bot has insufficient permissions.**\n").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Failed to add role. **Bot has insufficient permissions.**\n").ConfigureAwait(false);
Console.WriteLine(ex.ToString()); Console.WriteLine(ex.ToString());
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task Removerole(IUserMessage umsg, IGuildUser usr, [Remainder] IRole role) public async Task Removerole(IGuildUser usr, [Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await usr.RemoveRolesAsync(role).ConfigureAwait(false); await usr.RemoveRolesAsync(role).ConfigureAwait(false);
await channel.SendConfirmAsync($" Successfully removed role **{role.Name}** from user **{usr.Username}**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" Successfully removed role **{role.Name}** from user **{usr.Username}**").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ Failed to remove role. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Failed to remove role. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task RenameRole(IUserMessage umsg, IRole roleToEdit, string newname) public async Task RenameRole(IRole roleToEdit, string newname)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
if (roleToEdit.Position > (await channel.Guild.GetCurrentUserAsync().ConfigureAwait(false)).Roles.Max(r => r.Position)) if (roleToEdit.Position > (await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false)).GetRoles().Max(r => r.Position))
{ {
await channel.SendErrorAsync("🚫 You can't edit roles higher than your highest role.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🚫 You can't edit roles higher than your highest role.").ConfigureAwait(false);
return; return;
} }
await roleToEdit.ModifyAsync(g => g.Name = newname).ConfigureAwait(false); await roleToEdit.ModifyAsync(g => g.Name = newname).ConfigureAwait(false);
await channel.SendConfirmAsync("✅ Role renamed.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ Role renamed.").ConfigureAwait(false);
} }
catch (Exception) catch (Exception)
{ {
await channel.SendErrorAsync("⚠️ Failed to rename role. Probably **insufficient permissions.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Failed to rename role. Probably **insufficient permissions.**").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task RemoveAllRoles(IUserMessage umsg, [Remainder] IGuildUser user) public async Task RemoveAllRoles([Remainder] IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await user.RemoveRolesAsync(user.Roles).ConfigureAwait(false); await user.RemoveRolesAsync(user.GetRoles()).ConfigureAwait(false);
await channel.SendConfirmAsync($"🗑 Successfully removed **all** roles from user **{user.Username}**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🗑 Successfully removed **all** roles from user **{user.Username}**").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ Failed to remove roles. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Failed to remove roles. Most likely reason: **Insufficient permissions.**").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task CreateRole(IUserMessage umsg, [Remainder] string roleName = null) public async Task CreateRole([Remainder] string roleName = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(roleName)) if (string.IsNullOrWhiteSpace(roleName))
return; return;
try try
{ {
var r = await channel.Guild.CreateRoleAsync(roleName).ConfigureAwait(false); var r = await Context.Guild.CreateRoleAsync(roleName).ConfigureAwait(false);
await channel.SendConfirmAsync($"✅ Successfully created role **{r.Name}**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✅ Successfully created role **{r.Name}**.").ConfigureAwait(false);
} }
catch (Exception) catch (Exception)
{ {
await channel.SendErrorAsync("⚠️ Unspecified error.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Unspecified error.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task RoleColor(IUserMessage umsg, params string[] args) public async Task RoleColor(params string[] args)
{ {
var channel = (ITextChannel)umsg.Channel;
if (args.Count() != 2 && args.Count() != 4) if (args.Count() != 2 && args.Count() != 4)
{ {
await channel.SendErrorAsync("❌ The parameters specified are **invalid.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❌ The parameters specified are **invalid.**").ConfigureAwait(false);
return; return;
} }
var roleName = args[0].ToUpperInvariant(); var roleName = args[0].ToUpperInvariant();
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleName).FirstOrDefault(); var role = Context.Guild.Roles.Where(r=>r.Name.ToUpperInvariant() == roleName).FirstOrDefault();
if (role == null) if (role == null)
{ {
await channel.SendErrorAsync("🚫 That role **does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🚫 That role **does not exist.**").ConfigureAwait(false);
return; return;
} }
try try
@ -235,109 +218,105 @@ namespace NadekoBot.Modules.Administration
var green = Convert.ToByte(rgb ? int.Parse(args[2]) : Convert.ToInt32(arg1.Substring(2, 2), 16)); var green = Convert.ToByte(rgb ? int.Parse(args[2]) : Convert.ToInt32(arg1.Substring(2, 2), 16));
var blue = Convert.ToByte(rgb ? int.Parse(args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16)); var blue = Convert.ToByte(rgb ? int.Parse(args[3]) : Convert.ToInt32(arg1.Substring(4, 2), 16));
await role.ModifyAsync(r => r.Color = new Discord.Color(red, green, blue).RawValue).ConfigureAwait(false); await role.ModifyAsync(r => r.Color = new Color(red, green, blue)).ConfigureAwait(false);
await channel.SendConfirmAsync($"☑️ Role **{role.Name}'s** color has been changed.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"☑️ Role **{role.Name}'s** color has been changed.").ConfigureAwait(false);
} }
catch (Exception) catch (Exception)
{ {
await channel.SendErrorAsync("⚠️ Error occured, most likely **invalid parameters** or **insufficient permissions.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Error occured, most likely **invalid parameters** or **insufficient permissions.**").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.BanMembers)] [RequireUserPermission(GuildPermission.BanMembers)]
public async Task Ban(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null) public async Task Ban(IGuildUser user, [Remainder] string msg = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(msg)) if (string.IsNullOrWhiteSpace(msg))
{ {
msg = "❗No reason provided."; msg = "❗No reason provided.";
} }
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max()) if (Context.User.Id != user.Guild.OwnerId && ((IGuildUser)Context.User).GetRoles().Select(r=>r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{ {
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy."); await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.").ConfigureAwait(false);
return; return;
} }
try try
{ {
await (await user.CreateDMChannelAsync()).SendErrorAsync($"⛔️ **You have been BANNED from `{channel.Guild.Name}` server.**\n" + await (await user.CreateDMChannelAsync()).SendErrorAsync($"⛔️ **You have been BANNED from `{Context.Guild.Name}` server.**\n" +
$"⚖ *Reason:* {msg}").ConfigureAwait(false); $"⚖ *Reason:* {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); await Task.Delay(2000).ConfigureAwait(false);
} }
catch { } catch { }
try try
{ {
await channel.Guild.AddBanAsync(user, 7).ConfigureAwait(false); await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
await channel.SendConfirmAsync("⛔️ **Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("⛔️ **Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ **Error.** Most likely I don't have sufficient permissions.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ **Error.** Most likely I don't have sufficient permissions.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.KickMembers)] [RequireUserPermission(GuildPermission.KickMembers)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Softban(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null) public async Task Softban(IGuildUser user, [Remainder] string msg = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(msg)) if (string.IsNullOrWhiteSpace(msg))
{ {
msg = "❗No reason provided."; msg = "❗No reason provided.";
} }
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max()) if (Context.User.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{ {
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy."); await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
return; return;
} }
try try
{ {
await user.SendErrorAsync($"☣ **You have been SOFT-BANNED from `{channel.Guild.Name}` server.**\n" + await user.SendErrorAsync($"☣ **You have been SOFT-BANNED from `{Context.Guild.Name}` server.**\n" +
$"⚖ *Reason:* {msg}").ConfigureAwait(false); $"⚖ *Reason:* {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); await Task.Delay(2000).ConfigureAwait(false);
} }
catch { } catch { }
try try
{ {
await channel.Guild.AddBanAsync(user, 7).ConfigureAwait(false); await Context.Guild.AddBanAsync(user, 7).ConfigureAwait(false);
try { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); } try { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
catch { await channel.Guild.RemoveBanAsync(user).ConfigureAwait(false); } catch { await Context.Guild.RemoveBanAsync(user).ConfigureAwait(false); }
await channel.SendConfirmAsync("☣ **Soft-Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("☣ **Soft-Banned** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.KickMembers)] [RequireUserPermission(GuildPermission.KickMembers)]
public async Task Kick(IUserMessage umsg, IGuildUser user, [Remainder] string msg = null) public async Task Kick(IGuildUser user, [Remainder] string msg = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (user == null) if (user == null)
{ {
await channel.SendErrorAsync("❗User not found.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❗User not found.").ConfigureAwait(false);
return; return;
} }
if (umsg.Author.Id != user.Guild.OwnerId && user.Roles.Select(r => r.Position).Max() >= ((IGuildUser)umsg.Author).Roles.Select(r => r.Position).Max()) if (Context.Message.Author.Id != user.Guild.OwnerId && user.GetRoles().Select(r => r.Position).Max() >= ((IGuildUser)Context.User).GetRoles().Select(r => r.Position).Max())
{ {
await channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy."); await Context.Channel.SendErrorAsync("⚠️ You can't use this command on users with a role higher or equal to yours in the role hierarchy.");
return; return;
} }
if (!string.IsNullOrWhiteSpace(msg)) if (!string.IsNullOrWhiteSpace(msg))
{ {
try try
{ {
await user.SendErrorAsync($"‼️**You have been KICKED from `{channel.Guild.Name}` server.**\n" + await user.SendErrorAsync($"‼️**You have been KICKED from `{Context.Guild.Name}` server.**\n" +
$"⚖ *Reason:* {msg}").ConfigureAwait(false); $"⚖ *Reason:* {msg}").ConfigureAwait(false);
await Task.Delay(2000).ConfigureAwait(false); await Task.Delay(2000).ConfigureAwait(false);
} }
@ -346,21 +325,19 @@ namespace NadekoBot.Modules.Administration
try try
{ {
await user.KickAsync().ConfigureAwait(false); await user.KickAsync().ConfigureAwait(false);
await channel.SendConfirmAsync("‼️**Kicked** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("‼️**Kicked** user **" + user.Username + "** ID: `" + user.Id + "`").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Error. Most likely I don't have sufficient permissions.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.DeafenMembers)] [RequireUserPermission(GuildPermission.DeafenMembers)]
public async Task Deafen(IUserMessage umsg, params IGuildUser[] users) public async Task Deafen(params IGuildUser[] users)
{ {
var channel = (ITextChannel)umsg.Channel;
if (!users.Any()) if (!users.Any())
return; return;
try try
@ -369,21 +346,19 @@ namespace NadekoBot.Modules.Administration
{ {
await u.ModifyAsync(usr => usr.Deaf = true).ConfigureAwait(false); await u.ModifyAsync(usr => usr.Deaf = true).ConfigureAwait(false);
} }
await channel.SendConfirmAsync("🔇 **Deafen** successful.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🔇 **Deafen** successful.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.DeafenMembers)] [RequireUserPermission(GuildPermission.DeafenMembers)]
public async Task UnDeafen(IUserMessage umsg, params IGuildUser[] users) public async Task UnDeafen(params IGuildUser[] users)
{ {
var channel = (ITextChannel)umsg.Channel;
if (!users.Any()) if (!users.Any())
return; return;
try try
@ -392,58 +367,56 @@ namespace NadekoBot.Modules.Administration
{ {
await u.ModifyAsync(usr => usr.Deaf = false).ConfigureAwait(false); await u.ModifyAsync(usr => usr.Deaf = false).ConfigureAwait(false);
} }
await channel.SendConfirmAsync("🔊 **Undeafen** successful.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🔊 **Undeafen** successful.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task DelVoiChanl(IUserMessage umsg, [Remainder] IVoiceChannel voiceChannel) public async Task DelVoiChanl([Remainder] IVoiceChannel voiceChannel)
{ {
await voiceChannel.DeleteAsync().ConfigureAwait(false); await voiceChannel.DeleteAsync().ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync($"🗑 Removed voice channel **{voiceChannel.Name}** successfully.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🗑 Removed voice channel **{voiceChannel.Name}** successfully.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task CreatVoiChanl(IUserMessage umsg, [Remainder] string channelName) public async Task CreatVoiChanl([Remainder] string channelName)
{ {
var channel = (ITextChannel)umsg.Channel; var ch = await Context.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false);
var ch = await channel.Guild.CreateVoiceChannelAsync(channelName).ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✅ Created voice channel **{ch.Name}**. ID: `{ch.Id}`").ConfigureAwait(false);
await channel.SendConfirmAsync($"✅ Created voice channel **{ch.Name}**. ID: `{ch.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task DelTxtChanl(IUserMessage umsg, [Remainder] ITextChannel toDelete) public async Task DelTxtChanl([Remainder] ITextChannel toDelete)
{ {
await toDelete.DeleteAsync().ConfigureAwait(false); await toDelete.DeleteAsync().ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync($"🗑 Removed text channel **{toDelete.Name}**. ID: `{toDelete.Id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🗑 Removed text channel **{toDelete.Name}**. ID: `{toDelete.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task CreaTxtChanl(IUserMessage umsg, [Remainder] string channelName) public async Task CreaTxtChanl([Remainder] string channelName)
{ {
var channel = (ITextChannel)umsg.Channel; var txtCh = await Context.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false);
var txtCh = await channel.Guild.CreateTextChannelAsync(channelName).ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✅ Added text channel **{txtCh.Name}**. ID: `{txtCh.Id}`").ConfigureAwait(false);
await channel.SendConfirmAsync($"✅ Added text channel **{txtCh.Name}**. ID: `{txtCh.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task SetTopic(IUserMessage umsg, [Remainder] string topic = null) public async Task SetTopic([Remainder] string topic = null)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
topic = topic ?? ""; topic = topic ?? "";
await channel.ModifyAsync(c => c.Topic = topic); await channel.ModifyAsync(c => c.Topic = topic);
await channel.SendConfirmAsync("🆗 **New channel topic set.**").ConfigureAwait(false); await channel.SendConfirmAsync("🆗 **New channel topic set.**").ConfigureAwait(false);
@ -451,11 +424,10 @@ namespace NadekoBot.Modules.Administration
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task SetChanlName(IUserMessage umsg, [Remainder] string name) public async Task SetChanlName([Remainder] string name)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
await channel.ModifyAsync(c => c.Name = name).ConfigureAwait(false); await channel.ModifyAsync(c => c.Name = name).ConfigureAwait(false);
await channel.SendConfirmAsync("🆗 **New channel name set.**").ConfigureAwait(false); await channel.SendConfirmAsync("🆗 **New channel name set.**").ConfigureAwait(false);
} }
@ -464,183 +436,55 @@ namespace NadekoBot.Modules.Administration
//delets her own messages, no perm required //delets her own messages, no perm required
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Prune(IUserMessage umsg) public async Task Prune()
{ {
var channel = (ITextChannel)umsg.Channel; var user = await Context.Guild.GetCurrentUserAsync().ConfigureAwait(false);
var user = channel.Guild.GetCurrentUser(); var enumerable = (await Context.Channel.GetMessagesAsync().Flatten()).AsEnumerable();
var enumerable = (await umsg.Channel.GetMessagesAsync()).AsEnumerable();
enumerable = enumerable.Where(x => x.Author.Id == user.Id); enumerable = enumerable.Where(x => x.Author.Id == user.Id);
await umsg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false); await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
} }
// prune x // prune x
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(ChannelPermission.ManageMessages)] [RequireUserPermission(ChannelPermission.ManageMessages)]
public async Task Prune(IUserMessage msg, int count) public async Task Prune(int count)
{ {
var channel = (ITextChannel)msg.Channel; await Context.Message.DeleteAsync().ConfigureAwait(false);
await (msg as IUserMessage).DeleteAsync();
int limit = (count < 100) ? count : 100; int limit = (count < 100) ? count : 100;
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit)); var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten().ConfigureAwait(false));
await msg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false); await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
} }
//prune @user [x] //prune @user [x]
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(ChannelPermission.ManageMessages)] [RequireUserPermission(ChannelPermission.ManageMessages)]
public async Task Prune(IUserMessage msg, IGuildUser user, int count = 100) public async Task Prune(IGuildUser user, int count = 100)
{ {
var channel = (ITextChannel)msg.Channel;
int limit = (count < 100) ? count : 100; int limit = (count < 100) ? count : 100;
var enumerable = (await msg.Channel.GetMessagesAsync(limit: limit)).Where(m => m.Author == user); var enumerable = (await Context.Channel.GetMessagesAsync(limit: limit).Flatten()).Where(m => m.Author == user);
await msg.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false); await Context.Channel.DeleteMessagesAsync(enumerable).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Die(IUserMessage umsg)
{
try { await umsg.Channel.SendConfirmAsync(" **Shutting down.**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
await Task.Delay(2000).ConfigureAwait(false);
Environment.Exit(0);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetName(IUserMessage umsg, [Remainder] string newName)
{
if (string.IsNullOrWhiteSpace(newName))
return;
await (await NadekoBot.Client.GetCurrentUserAsync()).ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync($" Successfully changed name to **{newName}**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetAvatar(IUserMessage umsg, [Remainder] string img = null)
{
if (string.IsNullOrWhiteSpace(img))
return;
using (var http = new HttpClient())
{
using (var sr = await http.GetStreamAsync(img))
{
var imgStream = new MemoryStream();
await sr.CopyToAsync(imgStream);
imgStream.Position = 0;
await (await NadekoBot.Client.GetCurrentUserAsync().ConfigureAwait(false)).ModifyAsync(u => u.Avatar = imgStream).ConfigureAwait(false);
}
}
await umsg.Channel.SendConfirmAsync("🆒 **New avatar set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetGame(IUserMessage umsg, [Remainder] string game = null)
{
game = game ?? "";
await NadekoBot.Client.SetGame(game).ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync("👾 **New game set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetStream(IUserMessage umsg, string url, [Remainder] string name = null)
{
name = name ?? "";
await NadekoBot.Client.SetStream(name, url).ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync(" **New stream set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Send(IUserMessage umsg, string where, [Remainder] string msg = null)
{
if (string.IsNullOrWhiteSpace(msg))
return;
var ids = where.Split('|');
if (ids.Length != 2)
return;
var sid = ulong.Parse(ids[0]);
var server = NadekoBot.Client.GetGuilds().Where(s => s.Id == sid).FirstOrDefault();
if (server == null)
return;
if (ids[1].ToUpperInvariant().StartsWith("C:"))
{
var cid = ulong.Parse(ids[1].Substring(2));
var ch = server.GetTextChannels().Where(c => c.Id == cid).FirstOrDefault();
if (ch == null)
{
return;
}
await ch.SendMessageAsync(msg).ConfigureAwait(false);
}
else if (ids[1].ToUpperInvariant().StartsWith("U:"))
{
var uid = ulong.Parse(ids[1].Substring(2));
var user = server.GetUsers().Where(u => u.Id == uid).FirstOrDefault();
if (user == null)
{
return;
}
await user.SendMessageAsync(msg).ConfigureAwait(false);
}
else
{
await umsg.Channel.SendErrorAsync("⚠️ Invalid format.").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Announce(IUserMessage umsg, [Remainder] string message)
{
var channels = await Task.WhenAll(NadekoBot.Client.GetGuilds().Select(g =>
g.GetDefaultChannelAsync()
)).ConfigureAwait(false);
if (channels == null)
return;
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync($"🆕 Message from {umsg.Author} `[Bot Owner]`:", message)))
.ConfigureAwait(false);
await umsg.Channel.SendConfirmAsync("🆗").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task SaveChat(IUserMessage umsg, int cnt) public async Task SaveChat(int cnt)
{ {
var channel = (ITextChannel)umsg.Channel;
ulong? lastmsgId = null; ulong? lastmsgId = null;
var sb = new StringBuilder(); var sb = new StringBuilder();
var msgs = new List<IMessage>(cnt); var msgs = new List<IMessage>(cnt);
while (cnt > 0) while (cnt > 0)
{ {
var dlcnt = cnt < 100 ? cnt : 100; var dlcnt = cnt < 100 ? cnt : 100;
IReadOnlyCollection<IMessage> dledMsgs; IEnumerable<IMessage> dledMsgs;
if (lastmsgId == null) if (lastmsgId == null)
dledMsgs = await umsg.Channel.GetMessagesAsync(cnt).ConfigureAwait(false); dledMsgs = await Context.Channel.GetMessagesAsync(cnt).Flatten().ConfigureAwait(false);
else else
dledMsgs = await umsg.Channel.GetMessagesAsync(lastmsgId.Value, Direction.Before, dlcnt); dledMsgs = await Context.Channel.GetMessagesAsync(lastmsgId.Value, Direction.Before, dlcnt).Flatten().ConfigureAwait(false);
if (!dledMsgs.Any()) if (!dledMsgs.Any())
break; break;
@ -649,43 +493,41 @@ namespace NadekoBot.Modules.Administration
lastmsgId = msgs[msgs.Count - 1].Id; lastmsgId = msgs[msgs.Count - 1].Id;
cnt -= 100; cnt -= 100;
} }
var title = $"Chatlog-{channel.Guild.Name}/#{channel.Name}-{DateTime.Now}.txt"; var title = $"Chatlog-{Context.Guild.Name}/#{Context.Channel.Name}-{DateTime.Now}.txt";
var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}") var grouping = msgs.GroupBy(x => $"{x.CreatedAt.Date:dd.MM.yyyy}")
.Select(g => new { date = g.Key, messages = g.OrderBy(x=>x.CreatedAt).Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) }); .Select(g => new { date = g.Key, messages = g.OrderBy(x => x.CreatedAt).Select(s => $"【{s.Timestamp:HH:mm:ss}】{s.Author}:" + s.ToString()) });
await (umsg.Author as IGuildUser).SendFileAsync( await (Context.User as IGuildUser).SendFileAsync(
await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false), await JsonConvert.SerializeObject(grouping, Formatting.Indented).ToStream().ConfigureAwait(false),
title, title).ConfigureAwait(false); title, title).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.MentionEveryone)] [RequireUserPermission(GuildPermission.MentionEveryone)]
public async Task MentionRole(IUserMessage umsg, params IRole[] roles) public async Task MentionRole(params IRole[] roles)
{ {
var channel = (ITextChannel)umsg.Channel; string send = $"❕{Context.User.Mention} has invoked a mention on the following roles ❕";
string send = $"❕{umsg.Author.Mention} has invoked a mention on the following roles ❕";
foreach (var role in roles) foreach (var role in roles)
{ {
send += $"\n**{role.Name}**\n"; send += $"\n**{role.Name}**\n";
send += string.Join(", ", (await channel.Guild.GetUsersAsync()).Where(u => u.Roles.Contains(role)).Distinct().Select(u => u.Mention)); send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.GetRoles().Contains(role)).Distinct().Select(u=>u.Mention));
} }
while (send.Length > 2000) while (send.Length > 2000)
{ {
var curstr = send.Substring(0, 2000); var curstr = send.Substring(0, 2000);
await channel.SendMessageAsync(curstr.Substring(0, await Context.Channel.SendMessageAsync(curstr.Substring(0,
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false); curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) + send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
send.Substring(2000); send.Substring(2000);
} }
await channel.SendMessageAsync(send).ConfigureAwait(false); await Context.Channel.SendMessageAsync(send).ConfigureAwait(false);
} }
IGuild nadekoSupportServer; IGuild nadekoSupportServer;
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Donators(IUserMessage umsg) public async Task Donators()
{ {
IEnumerable<Donator> donatorsOrdered; IEnumerable<Donator> donatorsOrdered;
@ -693,7 +535,7 @@ namespace NadekoBot.Modules.Administration
{ {
donatorsOrdered = uow.Donators.GetDonatorsOrdered(); donatorsOrdered = uow.Donators.GetDonatorsOrdered();
} }
await umsg.Channel.SendConfirmAsync("Thanks to the people listed below for making this project happen!", string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Thanks to the people listed below for making this project happen!", string.Join("⭐", donatorsOrdered.Select(d => d.Name))).ConfigureAwait(false);
nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850); nadekoSupportServer = nadekoSupportServer ?? NadekoBot.Client.GetGuild(117523346618318850);
@ -704,14 +546,14 @@ namespace NadekoBot.Modules.Administration
if (patreonRole == null) if (patreonRole == null)
return; return;
var usrs = nadekoSupportServer.GetUsers().Where(u => u.Roles.Contains(patreonRole)); var usrs = (await nadekoSupportServer.GetUsersAsync()).Where(u => u.RoleIds.Contains(236667642088259585u));
await umsg.Channel.SendConfirmAsync("Patreon supporters", string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Patreon supporters", string.Join("⭐", usrs.Select(d => d.Username))).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task Donadd(IUserMessage umsg, IUser donator, int amount) public async Task Donadd(IUser donator, int amount)
{ {
Donator don; Donator don;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -720,7 +562,7 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
await umsg.Channel.SendConfirmAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Successfuly added a new donator. Total donated amount from this user: {don.Amount} 👑").ConfigureAwait(false);
} }
} }
} }

View File

@ -67,7 +67,7 @@ namespace NadekoBot.Modules.Administration
} }
[Group] [Group]
public class AntiRaidCommands public class AntiRaidCommands : ModuleBase
{ {
private static ConcurrentDictionary<ulong, AntiRaidSetting> antiRaidGuilds = private static ConcurrentDictionary<ulong, AntiRaidSetting> antiRaidGuilds =
new ConcurrentDictionary<ulong, AntiRaidSetting>(); new ConcurrentDictionary<ulong, AntiRaidSetting>();
@ -152,7 +152,7 @@ namespace NadekoBot.Modules.Administration
case PunishmentAction.Mute: case PunishmentAction.Mute:
try try
{ {
await MuteCommands.Mute(gu).ConfigureAwait(false); await MuteCommands.MuteUser(gu).ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); } catch (Exception ex) { _log.Warn(ex, "I can't apply punishement"); }
break; break;
@ -190,30 +190,28 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task AntiRaid(IUserMessage imsg, int userThreshold, int seconds, PunishmentAction action) public async Task AntiRaid(int userThreshold, int seconds, PunishmentAction action)
{ {
var channel = (ITextChannel)imsg.Channel;
if (userThreshold < 2 || userThreshold > 30) if (userThreshold < 2 || userThreshold > 30)
{ {
await channel.SendErrorAsync("❗User threshold must be between **2** and **30**.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❗User threshold must be between **2** and **30**.").ConfigureAwait(false);
return; return;
} }
if (seconds < 2 || seconds > 300) if (seconds < 2 || seconds > 300)
{ {
await channel.SendErrorAsync("❗Time must be between **2** and **300** seconds.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❗Time must be between **2** and **300** seconds.").ConfigureAwait(false);
return; return;
} }
try try
{ {
await MuteCommands.GetMuteRole(channel.Guild).ConfigureAwait(false); await MuteCommands.GetMuteRole(Context.Guild).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendConfirmAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" + await Context.Channel.SendConfirmAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
"or create 'nadeko-mute' role with disabled SendMessages and try again.") "or create 'nadeko-mute' role with disabled SendMessages and try again.")
.ConfigureAwait(false); .ConfigureAwait(false);
_log.Warn(ex); _log.Warn(ex);
@ -226,48 +224,46 @@ namespace NadekoBot.Modules.Administration
Seconds = seconds, Seconds = seconds,
UserThreshold = userThreshold, UserThreshold = userThreshold,
}; };
antiRaidGuilds.AddOrUpdate(channel.Guild.Id, setting, (id, old) => setting); antiRaidGuilds.AddOrUpdate(Context.Guild.Id, setting, (id, old) => setting);
await channel.SendConfirmAsync($" {imsg.Author.Mention} If **{userThreshold}** or more users join within **{seconds}** seconds, I will **{action}** them.") await Context.Channel.SendConfirmAsync($" {Context.User.Mention} If **{userThreshold}** or more users join within **{seconds}** seconds, I will **{action}** them.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
public async Task AntiSpam(IUserMessage imsg, int messageCount = 3, PunishmentAction action = PunishmentAction.Mute) public async Task AntiSpam(int messageCount=3, PunishmentAction action = PunishmentAction.Mute)
{ {
var channel = (ITextChannel)imsg.Channel;
if (messageCount < 2 || messageCount > 10) if (messageCount < 2 || messageCount > 10)
return; return;
AntiSpamSetting throwaway; AntiSpamSetting throwaway;
if (antiSpamGuilds.TryRemove(channel.Guild.Id, out throwaway)) if (antiSpamGuilds.TryRemove(Context.Guild.Id, out throwaway))
{ {
await channel.SendConfirmAsync("🆗 **Anti-Spam feature** has been **disabled** on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 **Anti-Spam feature** has been **disabled** on this server.").ConfigureAwait(false);
} }
else else
{ {
try try
{ {
await MuteCommands.GetMuteRole(channel.Guild).ConfigureAwait(false); await MuteCommands.GetMuteRole(Context.Guild).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" + await Context.Channel.SendErrorAsync("⚠️ Failed creating a mute role. Give me ManageRoles permission" +
"or create 'nadeko-mute' role with disabled SendMessages and try again.") "or create 'nadeko-mute' role with disabled SendMessages and try again.")
.ConfigureAwait(false); .ConfigureAwait(false);
_log.Warn(ex); _log.Warn(ex);
return; return;
} }
if (antiSpamGuilds.TryAdd(channel.Guild.Id, new AntiSpamSetting() if (antiSpamGuilds.TryAdd(Context.Guild.Id, new AntiSpamSetting()
{ {
Action = action, Action = action,
MessageThreshold = messageCount, MessageThreshold = messageCount,
})) }))
await channel.SendConfirmAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ **Anti-Spam feature** has been **enabled** on this server.").ConfigureAwait(false);
} }
} }

View File

@ -7,6 +7,7 @@ using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,7 +16,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class AutoAssignRoleCommands public class AutoAssignRoleCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
//guildid/roleid //guildid/roleid
@ -23,9 +24,11 @@ namespace NadekoBot.Modules.Administration
static AutoAssignRoleCommands() static AutoAssignRoleCommands()
{ {
_log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0) AutoAssignedRoles = new ConcurrentDictionary<ulong, ulong>(NadekoBot.AllGuildConfigs.Where(x => x.AutoAssignRoleId != 0)
.ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId)); .ToDictionary(k => k.GuildId, v => v.AutoAssignRoleId));
_log = LogManager.GetCurrentClassLogger();
NadekoBot.Client.UserJoined += async (user) => NadekoBot.Client.UserJoined += async (user) =>
{ {
try try
@ -43,29 +46,30 @@ namespace NadekoBot.Modules.Administration
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
}; };
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task AutoAssignRole(IUserMessage umsg, [Remainder] IRole role = null) public async Task AutoAssignRole([Remainder] IRole role = null)
{ {
var channel = (ITextChannel)umsg.Channel;
GuildConfig conf; GuildConfig conf;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
conf = uow.GuildConfigs.For(channel.Guild.Id, set => set); conf = uow.GuildConfigs.For(Context.Guild.Id, set => set);
if (role == null) if (role == null)
{ {
conf.AutoAssignRoleId = 0; conf.AutoAssignRoleId = 0;
ulong throwaway; ulong throwaway;
AutoAssignedRoles.TryRemove(channel.Guild.Id, out throwaway); AutoAssignedRoles.TryRemove(Context.Guild.Id, out throwaway);
} }
else else
{ {
conf.AutoAssignRoleId = role.Id; conf.AutoAssignRoleId = role.Id;
AutoAssignedRoles.AddOrUpdate(channel.Guild.Id, role.Id, (key, val) => role.Id); AutoAssignedRoles.AddOrUpdate(Context.Guild.Id, role.Id, (key, val) => role.Id);
} }
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
@ -73,11 +77,11 @@ namespace NadekoBot.Modules.Administration
if (role == null) if (role == null)
{ {
await channel.SendConfirmAsync("🆗 **Auto assign role** on user join is now **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 **Auto assign role** on user join is now **disabled**.").ConfigureAwait(false);
return; return;
} }
await channel.SendConfirmAsync("✅ **Auto assign role** on user join is now **enabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ **Auto assign role** on user join is now **enabled**.").ConfigureAwait(false);
} }
} }
} }

View File

@ -14,7 +14,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class CrossServerTextChannel public class CrossServerTextChannel : ModuleBase
{ {
static CrossServerTextChannel() static CrossServerTextChannel()
{ {
@ -31,11 +31,11 @@ namespace NadekoBot.Modules.Administration
var channel = imsg.Channel as ITextChannel; var channel = imsg.Channel as ITextChannel;
if (channel == null) if (channel == null)
return; return;
if (msg.Author.Id == NadekoBot.Client.GetCurrentUser().Id) return; if (msg.Author.Id == NadekoBot.Client.CurrentUser().Id) return;
foreach (var subscriber in Subscribers) foreach (var subscriber in Subscribers)
{ {
var set = subscriber.Value; var set = subscriber.Value;
if (!set.Contains(msg.Channel)) if (!set.Contains(channel))
continue; continue;
foreach (var chan in set.Except(new[] { channel })) foreach (var chan in set.Except(new[] { channel }))
{ {
@ -58,44 +58,39 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Scsc(IUserMessage msg) public async Task Scsc()
{ {
var channel = (ITextChannel)msg.Channel;
var token = new NadekoRandom().Next(); var token = new NadekoRandom().Next();
var set = new ConcurrentHashSet<ITextChannel>(); var set = new ConcurrentHashSet<ITextChannel>();
if (Subscribers.TryAdd(token, set)) if (Subscribers.TryAdd(token, set))
{ {
set.Add(channel); set.Add((ITextChannel)Context.Channel);
await ((IGuildUser)msg.Author).SendConfirmAsync("This is your CSC token", token.ToString()).ConfigureAwait(false); await ((IGuildUser)Context.User).SendConfirmAsync("This is your CSC token", token.ToString()).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Jcsc(IUserMessage imsg, int token) public async Task Jcsc(int token)
{ {
var channel = (ITextChannel)imsg.Channel;
ConcurrentHashSet<ITextChannel> set; ConcurrentHashSet<ITextChannel> set;
if (!Subscribers.TryGetValue(token, out set)) if (!Subscribers.TryGetValue(token, out set))
return; return;
set.Add(channel); set.Add((ITextChannel)Context.Channel);
await channel.SendConfirmAsync("Joined cross server channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Joined cross server channel.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Lcsc(IUserMessage imsg) public async Task Lcsc()
{ {
var channel = (ITextChannel)imsg.Channel;
foreach (var subscriber in Subscribers) foreach (var subscriber in Subscribers)
{ {
subscriber.Value.TryRemove(channel); subscriber.Value.TryRemove((ITextChannel)Context.Channel);
} }
await channel.SendMessageAsync("Left cross server channel.").ConfigureAwait(false); await Context.Channel.SendMessageAsync("Left cross server channel.").ConfigureAwait(false);
} }
} }
} }

View File

@ -1,9 +1,12 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NLog;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,13 +15,17 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class DMForwardCommands public class DMForwardCommands : ModuleBase
{ {
private static bool ForwardDMs { get; set; } private static bool ForwardDMs { get; set; }
private static bool ForwardDMsToAllOwners { get; set; } private static bool ForwardDMsToAllOwners { get; set; }
private static readonly Logger _log;
static DMForwardCommands() static DMForwardCommands()
{ {
_log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
@ -29,10 +36,8 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task ForwardMessages(IUserMessage imsg) public async Task ForwardMessages()
{ {
var channel = imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
@ -40,17 +45,15 @@ namespace NadekoBot.Modules.Administration
uow.Complete(); uow.Complete();
} }
if (ForwardDMs) if (ForwardDMs)
await channel.SendConfirmAsync("✅ **I will forward DMs from now on.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ **I will forward DMs from now on.**").ConfigureAwait(false);
else else
await channel.SendConfirmAsync("🆗 **I will stop forwarding DMs from now on.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 **I will stop forwarding DMs from now on.**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task ForwardToAll(IUserMessage imsg) public async Task ForwardToAll()
{ {
var channel = imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
@ -58,13 +61,13 @@ namespace NadekoBot.Modules.Administration
uow.Complete(); uow.Complete();
} }
if (ForwardDMsToAllOwners) if (ForwardDMsToAllOwners)
await channel.SendConfirmAsync(" **I will forward DMs to all owners.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" **I will forward DMs to all owners.**").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" **I will forward DMs only to the first owner.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" **I will forward DMs only to the first owner.**").ConfigureAwait(false);
} }
public static async Task HandleDMForwarding(IMessage msg, List<IDMChannel> ownerChannels) public static async Task HandleDMForwarding(SocketMessage msg, List<IDMChannel> ownerChannels)
{ {
if (ForwardDMs && ownerChannels.Any()) if (ForwardDMs && ownerChannels.Any())
{ {

View File

@ -11,6 +11,7 @@ using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -20,7 +21,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class LogCommands public class LogCommands : ModuleBase
{ {
private static ShardedDiscordClient _client { get; } private static ShardedDiscordClient _client { get; }
private static Logger _log { get; } private static Logger _log { get; }
@ -37,6 +38,7 @@ namespace NadekoBot.Modules.Administration
{ {
_client = NadekoBot.Client; _client = NadekoBot.Client;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -62,10 +64,10 @@ namespace NadekoBot.Modules.Administration
_log.Warn(ex); _log.Warn(ex);
} }
}, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10)); }, null, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10));
}
public LogCommands() sw.Stop();
{ _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
//_client.MessageReceived += _client_MessageReceived; //_client.MessageReceived += _client_MessageReceived;
_client.MessageUpdated += _client_MessageUpdated; _client.MessageUpdated += _client_MessageUpdated;
_client.MessageDeleted += _client_MessageDeleted; _client.MessageDeleted += _client_MessageDeleted;
@ -86,7 +88,7 @@ namespace NadekoBot.Modules.Administration
MuteCommands.UserUnmuted += MuteCommands_UserUnmuted; MuteCommands.UserUnmuted += MuteCommands_UserUnmuted;
} }
private async void _client_UserVoiceStateUpdated_TTS(IUser iusr, IVoiceState before, IVoiceState after) private static async void _client_UserVoiceStateUpdated_TTS(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{ {
try try
{ {
@ -106,7 +108,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresenceTTS)) == null)
return; return;
string str = null; string str = null;
@ -128,7 +130,7 @@ namespace NadekoBot.Modules.Administration
catch { } catch { }
} }
private async void MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType) private static async void MuteCommands_UserMuted(IGuildUser usr, MuteCommands.MuteType muteType)
{ {
try try
{ {
@ -138,7 +140,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
return; return;
string mutes = ""; string mutes = "";
switch (muteType) switch (muteType)
@ -158,7 +160,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType) private static async void MuteCommands_UserUnmuted(IGuildUser usr, MuteCommands.MuteType muteType)
{ {
try try
{ {
@ -168,7 +170,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserMuted)) == null)
return; return;
string mutes = ""; string mutes = "";
@ -201,7 +203,7 @@ namespace NadekoBot.Modules.Administration
|| (logSetting.LogOtherId == null)) || (logSetting.LogOtherId == null))
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null) if ((logChannel = await TryGetLogChannel(users.First().Guild, logSetting, LogType.Other)) == null)
return; return;
var punishment = ""; var punishment = "";
@ -221,47 +223,49 @@ namespace NadekoBot.Modules.Administration
//punishment = "BANNED"; //punishment = "BANNED";
} }
await logChannel.SendMessageAsync(String.Join("\n", users.Select(user => $"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server."))) await logChannel.SendMessageAsync(String.Join("\n", users.Select(user => $"‼️ {Format.Bold(user.ToString())} got **{punishment}** due to __**{protection}**__ protection on **{user.Guild.Name}** server.")))
//await logChannel.SendMessageAsync(String.Join("\n",users.Select(user=>$"{Format.Bold(user.ToString())} was **{punishment}** due to `{protection}` protection on **{user.Guild.Name}** server.")))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_UserUpdated(IGuildUser before, IGuildUser after) private static async void _client_UserUpdated(SocketUser uBefore, SocketUser uAfter)
{ {
try try
{ {
var before = uBefore as SocketGuildUser;
if (before == null)
return;
var after = uAfter as SocketGuildUser;
if (after == null)
return;
LogSetting logSetting; LogSetting logSetting;
if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting) if (!GuildLogSettings.TryGetValue(before.Guild.Id, out logSetting)
|| (logSetting.UserUpdatedId == null)) || (logSetting.UserUpdatedId == null))
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null) if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.UserUpdated)) == null)
return; return;
string str = $"🕔`{prettyCurrentTime}`"; string str = $"🕔`{prettyCurrentTime}`";
if (before.Username != after.Username) if (before.Username != after.Username)
//str += $"**Name Changed**`{before.Username}#{before.Discriminator}`\n\t\t`New:`{after.ToString()}`";
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**"; str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Name Changed |** 🆔 `{before.Id}`\n\t\t`New:` **{after.ToString()}**";
else if (before.Nickname != after.Nickname) else if (before.Nickname != after.Nickname)
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**"; str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Nickname Changed |** 🆔 `{before.Id}`\n\t\t`Old:` **{before.Nickname}#{before.Discriminator}**\n\t\t`New:` **{after.Nickname}#{after.Discriminator}**";
//str += $"**Nickname Changed**`{before.Username}#{before.Discriminator}`\n\t\t`Old:` {before.Nickname}#{before.Discriminator}\n\t\t`New:` {after.Nickname}#{after.Discriminator}";
else if (before.AvatarUrl != after.AvatarUrl) else if (before.AvatarUrl != after.AvatarUrl)
//str += $"**Avatar Changed**👤`{before.Username}#{before.Discriminator}`\n\t {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}"; str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await NadekoBot.Google.ShortenUrl(before.AvatarUrl)} `=>` {await NadekoBot.Google.ShortenUrl(after.AvatarUrl)}";
str += $"👤__**{before.Username}#{before.Discriminator}**__ **| Avatar Changed |** 🆔 `{before.Id}`\n\t🖼 {await _google.ShortenUrl(before.AvatarUrl)} `=>` {await _google.ShortenUrl(after.AvatarUrl)}"; else if (!before.RoleIds.SequenceEqual(after.RoleIds))
else if (!before.Roles.SequenceEqual(after.Roles))
{ {
if (before.Roles.Count() < after.Roles.Count()) if (before.RoleIds.Count < after.RoleIds.Count)
{ {
var diffRoles = after.Roles.Where(r => !before.Roles.Contains(r)).Select(r => "**" + r.Name + "**"); var diffRoles = after.RoleIds.Where(r => !before.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
//str += $"**User's Roles changed ⚔➕**👤`{before.ToString()}`\n\tNow has {string.Join(", ", diffRoles)} role."; str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
str += $"👤__**{before.ToString()}**__ **| User's Role Added |** 🆔 `{before.Id}`\n\t✅ {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
} }
else if (before.Roles.Count() > after.Roles.Count()) else if (before.RoleIds.Count > after.RoleIds.Count)
{ {
var diffRoles = before.Roles.Where(r => !after.Roles.Contains(r)).Select(r => "**" + r.Name + "**"); var diffRoles = before.RoleIds.Where(r => !after.RoleIds.Contains(r)).Select(r => "**" + before.Guild.GetRole(r).Name + "**");
//str += $"**User's Roles changed **`{before.ToString()}`\n\tNo longer has {string.Join(", ", diffRoles)} role."; str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.GetRoles().Select(r => r.Name)).SanitizeMentions()}`** ⚔";
str += $"👤__**{before.ToString()}**__ **| User's Role Removed |** 🆔 `{before.Id}`\n\t🚮 {string.Join(", ", diffRoles).SanitizeMentions()}\n\t\t⚔ **`{string.Join(", ", after.Roles.Select(r => r.Name)).SanitizeMentions()}`** ⚔";
} }
} }
else else
@ -271,7 +275,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_ChannelUpdated(IChannel cbefore, IChannel cafter) private static async void _client_ChannelUpdated(IChannel cbefore, IChannel cafter)
{ {
try try
{ {
@ -287,15 +291,13 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null) if ((logChannel = await TryGetLogChannel(before.Guild, logSetting, LogType.ChannelUpdated)) == null)
return; return;
if (before.Name != after.Name) if (before.Name != after.Name)
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Name Changed** `#{after.Name}` ({after.Id})
await logChannel.SendMessageAsync($@"🕓`{prettyCurrentTime}` **| Channel Name Changed |** #⃣ `{after.Name} ({after.Id})` await logChannel.SendMessageAsync($@"🕓`{prettyCurrentTime}` **| Channel Name Changed |** #⃣ `{after.Name} ({after.Id})`
`Old:` {before.Name} `Old:` {before.Name}
**`New:`** {after.Name}").ConfigureAwait(false); **`New:`** {after.Name}").ConfigureAwait(false);
else if ((before as ITextChannel).Topic != (after as ITextChannel).Topic) else if ((before as ITextChannel).Topic != (after as ITextChannel).Topic)
//await logChannel.SendMessageAsync($@"`{prettyCurrentTime}` **Channel Topic Changed** `#{after.Name}` ({after.Id})
await logChannel.SendMessageAsync($@"🕘`{prettyCurrentTime}` **| Channel Topic Changed |** #⃣ `{after.Name} ({after.Id})` await logChannel.SendMessageAsync($@"🕘`{prettyCurrentTime}` **| Channel Topic Changed |** #⃣ `{after.Name} ({after.Id})`
`Old:` {((ITextChannel)before).Topic} `Old:` {((ITextChannel)before).Topic}
**`New:`** {((ITextChannel)after).Topic}").ConfigureAwait(false); **`New:`** {((ITextChannel)after).Topic}").ConfigureAwait(false);
@ -303,7 +305,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_ChannelDestroyed(IChannel ich) private static async void _client_ChannelDestroyed(IChannel ich)
{ {
try try
{ {
@ -318,7 +320,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null) if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelDestroyed)) == null)
return; return;
await logChannel.SendMessageAsync($"🕕`{prettyCurrentTime}`🗑 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Deleted #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); await logChannel.SendMessageAsync($"🕕`{prettyCurrentTime}`🗑 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Deleted #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false);
@ -326,7 +328,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_ChannelCreated(IChannel ich) private static async void _client_ChannelCreated(IChannel ich)
{ {
try try
{ {
@ -340,7 +342,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null) if ((logChannel = await TryGetLogChannel(ch.Guild, logSetting, LogType.ChannelCreated)) == null)
return; return;
await logChannel.SendMessageAsync($"🕓`{prettyCurrentTime}`🆕 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Created: #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false); await logChannel.SendMessageAsync($"🕓`{prettyCurrentTime}`🆕 **| {(ch is IVoiceChannel ? "Voice" : "Text")} Channel Created: #⃣ {ch.Name}** `({ch.Id})`").ConfigureAwait(false);
@ -348,7 +350,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_UserVoiceStateUpdated(IUser iusr, IVoiceState before, IVoiceState after) => await Task.Run(() => private static async void _client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState before, SocketVoiceState after)
{ {
try try
{ {
@ -368,7 +370,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.VoicePresence)) == null)
return; return;
string str = null; string str = null;
@ -391,20 +393,25 @@ namespace NadekoBot.Modules.Administration
{ {
_log.Warn(ex); _log.Warn(ex);
} }
}); }
private async void _client_UserPresenceUpdated(IGuildUser usr, IPresence before, IPresence after) => await Task.Run(() => private static async void _client_UserPresenceUpdated(Optional<SocketGuild> optGuild, SocketUser usr, SocketPresence before, SocketPresence after)
{ {
try try
{ {
var guild = optGuild.IsSpecified ? optGuild.Value : null;
if (guild == null)
return;
LogSetting logSetting; LogSetting logSetting;
if (!GuildLogSettings.TryGetValue(usr.Guild.Id, out logSetting) if (!GuildLogSettings.TryGetValue(guild.Id, out logSetting)
|| (logSetting.LogUserPresenceId == null) || (logSetting.LogUserPresenceId == null)
|| before.Status == after.Status) || before.Status == after.Status)
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserPresence)) == null) if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserPresence)) == null)
return; return;
string str; string str;
if (before.Status != after.Status) if (before.Status != after.Status)
@ -415,9 +422,9 @@ namespace NadekoBot.Modules.Administration
UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; }); UserPresenceUpdates.AddOrUpdate(logChannel, new List<string>() { str }, (id, list) => { list.Add(str); return list; });
} }
catch { } catch { }
}); }
private async void _client_UserLeft(IGuildUser usr) private static async void _client_UserLeft(IGuildUser usr)
{ {
try try
{ {
@ -427,14 +434,14 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserLeft)) == null)
return; return;
await logChannel.SendMessageAsync($"❗️🕛`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__❌ **| USER LEFT |** 🆔 `{usr.Id}`").ConfigureAwait(false); await logChannel.SendMessageAsync($"❗️🕛`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__❌ **| USER LEFT |** 🆔 `{usr.Id}`").ConfigureAwait(false);
} }
catch { } catch { }
} }
private async void _client_UserJoined(IGuildUser usr) private static async void _client_UserJoined(IGuildUser usr)
{ {
try try
{ {
@ -444,7 +451,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null) if ((logChannel = await TryGetLogChannel(usr.Guild, logSetting, LogType.UserJoined)) == null)
return; return;
await logChannel.SendMessageAsync($"❕🕓`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__✅ **| USER JOINED |** 🆔 `{usr.Id}`").ConfigureAwait(false); await logChannel.SendMessageAsync($"❕🕓`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__✅ **| USER JOINED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
@ -452,7 +459,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_UserUnbanned(IUser usr, IGuild guild) private static async void _client_UserUnbanned(IUser usr, IGuild guild)
{ {
try try
{ {
@ -462,7 +469,7 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null) if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserUnbanned)) == null)
return; return;
await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); await logChannel.SendMessageAsync($"❕🕘`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__♻ **| USER UN-BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
@ -470,7 +477,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_UserBanned(IUser usr, IGuild guild) private static async void _client_UserBanned(IUser usr, IGuild guild)
{ {
try try
{ {
@ -480,14 +487,14 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null) if ((logChannel = await TryGetLogChannel(guild, logSetting, LogType.UserBanned)) == null)
return; return;
await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🚫 **| USER BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false); await logChannel.SendMessageAsync($"‼️🕕`{prettyCurrentTime}`👤__**{usr.Username}#{usr.Discriminator}**__🚫 **| USER BANNED |** 🆔 `{usr.Id}`").ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_MessageDeleted(ulong arg1, Optional<IMessage> imsg) private static async void _client_MessageDeleted(ulong arg1, Optional<SocketMessage> imsg)
{ {
try try
@ -507,10 +514,10 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id) if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageDeleted)) == null || logChannel.Id == msg.Id)
return; return;
var str = $@"🕔`{prettyCurrentTime}`👤__**{msg.Author.Username}#{msg.Author.Discriminator}**__ **| Deleted Message |** 🆔 `{msg.Author.Id}` #⃣ `{channel.Name}` var str = $@"🕔`{prettyCurrentTime}`👤__**{msg.Author.Username}#{msg.Author.Discriminator}**__ **| Deleted Message |** 🆔 `{msg.Author.Id}` #⃣ `{channel.Name}`
🗑 {msg.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator)}"; 🗑 {msg.Resolve(userHandling: TagHandling.FullName)}";
if (msg.Attachments.Any()) if (msg.Attachments.Any())
str += $"{Environment.NewLine}📎 {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}"; str += $"{Environment.NewLine}📎 {string.Join(", ", msg.Attachments.Select(a => a.ProxyUrl))}";
await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false); await logChannel.SendMessageAsync(str.SanitizeMentions()).ConfigureAwait(false);
@ -518,7 +525,7 @@ namespace NadekoBot.Modules.Administration
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void _client_MessageUpdated(Optional<IMessage> optmsg, IMessage imsg2) private static async void _client_MessageUpdated(Optional<SocketMessage> optmsg, SocketMessage imsg2)
{ {
try try
{ {
@ -544,11 +551,11 @@ namespace NadekoBot.Modules.Administration
return; return;
ITextChannel logChannel; ITextChannel logChannel;
if ((logChannel = TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id) if ((logChannel = await TryGetLogChannel(channel.Guild, logSetting, LogType.MessageUpdated)) == null || logChannel.Id == after.Channel.Id)
return; return;
await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}` await logChannel.SendMessageAsync($@"🕔`{prettyCurrentTime}`👤__**{before.Author.Username}#{before.Author.Discriminator}**__ **| 📝 Edited Message |** 🆔 `{before.Author.Id}` #⃣ `{channel.Name}`
`Old:` {before.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()} `Old:` {before.Resolve(userHandling: TagHandling.FullName).SanitizeMentions()}
**`New:`** {after.Resolve(userHandling: UserMentionHandling.NameAndDiscriminator).SanitizeMentions()}").ConfigureAwait(false); **`New:`** {after.Resolve(userHandling: TagHandling.FullName).SanitizeMentions()}").ConfigureAwait(false);
} }
catch (Exception ex) { _log.Warn(ex); } catch (Exception ex) { _log.Warn(ex); }
} }
@ -572,7 +579,7 @@ namespace NadekoBot.Modules.Administration
UserMuted UserMuted
}; };
private static ITextChannel TryGetLogChannel(IGuild guild, LogSetting logSetting, LogType logChannelType) private static async Task<ITextChannel> TryGetLogChannel(IGuild guild, LogSetting logSetting, LogType logChannelType)
{ {
ulong? id = null; ulong? id = null;
switch (logChannelType) switch (logChannelType)
@ -631,7 +638,7 @@ namespace NadekoBot.Modules.Administration
UnsetLogSetting(guild.Id, logChannelType); UnsetLogSetting(guild.Id, logChannelType);
return null; return null;
} }
var channel = guild.GetTextChannel(id.Value); var channel = await guild.GetTextChannelAsync(id.Value).ConfigureAwait(false);
if (channel == null) if (channel == null)
{ {
@ -710,11 +717,11 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[OwnerOnly] [OwnerOnly]
public async Task LogServer(IUserMessage msg, PermissionAction action) public async Task LogServer(PermissionAction action)
{ {
var channel = (ITextChannel)msg.Channel; var channel = (ITextChannel)Context.Channel;
LogSetting logSetting; LogSetting logSetting;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -745,11 +752,11 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[OwnerOnly] [OwnerOnly]
public async Task LogIgnore(IUserMessage imsg) public async Task LogIgnore()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
int removed; int removed;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -774,20 +781,20 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[OwnerOnly] [OwnerOnly]
public async Task LogEvents(IUserMessage imsg) public async Task LogEvents()
{ {
await imsg.Channel.SendConfirmAsync("Log events you can subscribe to:", String.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>())); await Context.Channel.SendConfirmAsync("Log events you can subscribe to:", String.Join(", ", Enum.GetNames(typeof(LogType)).Cast<string>()));
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[OwnerOnly] [OwnerOnly]
public async Task Log(IUserMessage imsg, LogType type) public async Task Log(LogType type)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
ulong? channelId = null; ulong? channelId = null;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -8,6 +7,7 @@ using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class RepeatCommands public class RepeatCommands : ModuleBase
{ {
public static ConcurrentDictionary<ulong, RepeatRunner> repeaters { get; } public static ConcurrentDictionary<ulong, RepeatRunner> repeaters { get; }
@ -34,7 +34,7 @@ namespace NadekoBot.Modules.Administration
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
this.Repeater = repeater; this.Repeater = repeater;
this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannel(repeater.ChannelId); this.Channel = channel ?? NadekoBot.Client.GetGuild(repeater.GuildId)?.GetTextChannelAsync(repeater.ChannelId).GetAwaiter().GetResult();
if (Channel == null) if (Channel == null)
return; return;
Task.Run(Run); Task.Run(Run);
@ -79,37 +79,39 @@ namespace NadekoBot.Modules.Administration
static RepeatCommands() static RepeatCommands()
{ {
var _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
repeaters = new ConcurrentDictionary<ulong, RepeatRunner>(uow.Repeaters.GetAll().Select(r => new RepeatRunner(r)).Where(r => r != null).ToDictionary(r => r.Repeater.ChannelId)); repeaters = new ConcurrentDictionary<ulong, RepeatRunner>(uow.Repeaters.GetAll().Select(r => new RepeatRunner(r)).Where(r => r != null).ToDictionary(r => r.Repeater.ChannelId));
} }
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task RepeatInvoke(IUserMessage imsg) public async Task RepeatInvoke()
{ {
var channel = (ITextChannel)imsg.Channel;
RepeatRunner rep; RepeatRunner rep;
if (!repeaters.TryGetValue(channel.Id, out rep)) if (!repeaters.TryGetValue(Context.Channel.Id, out rep))
{ {
await channel.SendErrorAsync(" **No repeating message found on this server.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync(" **No repeating message found on this server.**").ConfigureAwait(false);
return; return;
} }
rep.Reset(); rep.Reset();
await channel.SendMessageAsync("🔄 " + rep.Repeater.Message).ConfigureAwait(false); await Context.Channel.SendMessageAsync("🔄 " + rep.Repeater.Message).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Repeat(IUserMessage imsg) public async Task Repeat()
{ {
var channel = (ITextChannel)imsg.Channel;
RepeatRunner rep; RepeatRunner rep;
if (repeaters.TryRemove(channel.Id, out rep)) if (repeaters.TryRemove(Context.Channel.Id, out rep))
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -117,19 +119,17 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
rep.Stop(); rep.Stop();
await channel.SendConfirmAsync("✅ **Stopped repeating a message.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ **Stopped repeating a message.**").ConfigureAwait(false);
} }
else else
await channel.SendConfirmAsync(" **No message is repeating.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" **No message is repeating.**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Repeat(IUserMessage imsg, int minutes, [Remainder] string message) public async Task Repeat(int minutes, [Remainder] string message)
{ {
var channel = (ITextChannel)imsg.Channel;
if (minutes < 1 || minutes > 10080) if (minutes < 1 || minutes > 10080)
return; return;
@ -138,20 +138,20 @@ namespace NadekoBot.Modules.Administration
RepeatRunner rep; RepeatRunner rep;
rep = repeaters.AddOrUpdate(channel.Id, (cid) => rep = repeaters.AddOrUpdate(Context.Channel.Id, (cid) =>
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var localRep = new Repeater var localRep = new Repeater
{ {
ChannelId = channel.Id, ChannelId = Context.Channel.Id,
GuildId = channel.Guild.Id, GuildId = Context.Guild.Id,
Interval = TimeSpan.FromMinutes(minutes), Interval = TimeSpan.FromMinutes(minutes),
Message = message, Message = message,
}; };
uow.Repeaters.Add(localRep); uow.Repeaters.Add(localRep);
uow.Complete(); uow.Complete();
return new RepeatRunner(localRep, channel); return new RepeatRunner(localRep, (ITextChannel)Context.Channel);
} }
}, (cid, old) => }, (cid, old) =>
{ {
@ -166,7 +166,7 @@ namespace NadekoBot.Modules.Administration
return old; return old;
}); });
await channel.SendConfirmAsync($"🔁 Repeating **\"{rep.Repeater.Message}\"** every `{rep.Repeater.Interval.Days} day(s), {rep.Repeater.Interval.Hours} hour(s) and {rep.Repeater.Interval.Minutes} minute(s)`.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔁 Repeating **\"{rep.Repeater.Message}\"** every `{rep.Repeater.Interval.Days} day(s), {rep.Repeater.Interval.Hours} hour(s) and {rep.Repeater.Interval.Minutes} minute(s)`.").ConfigureAwait(false);
} }
} }
} }

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Services; using NadekoBot.Services;
@ -21,23 +20,21 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class Migration public class Migration : ModuleBase
{ {
private const int CURRENT_VERSION = 1; private const int CURRENT_VERSION = 1;
private Logger _log { get; } private static Logger _log { get; }
public Migration() static Migration()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task MigrateData(IUserMessage umsg) public async Task MigrateData()
{ {
var channel = (ITextChannel)umsg.Channel;
var version = 0; var version = 0;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -54,12 +51,12 @@ namespace NadekoBot.Modules.Administration
break; break;
} }
} }
await umsg.Channel.SendMessageAsync("🆙 **Migration done.**").ConfigureAwait(false); await Context.Channel.SendMessageAsync("🆙 **Migration done.**").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
_log.Error(ex); _log.Error(ex);
await umsg.Channel.SendMessageAsync("⚠️ **Error while migrating, check `logs` for more informations.**").ConfigureAwait(false); await Context.Channel.SendMessageAsync("⚠️ **Error while migrating, check `logs` for more informations.**").ConfigureAwait(false);
} }
} }

View File

@ -1,16 +1,16 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class MuteCommands public class MuteCommands : ModuleBase
{ {
private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>(); private static ConcurrentDictionary<ulong, string> GuildMuteRoles { get; } = new ConcurrentDictionary<ulong, string>();
@ -34,21 +34,25 @@ namespace NadekoBot.Modules.Administration
All All
} }
static MuteCommands() { static MuteCommands()
using (var uow = DbHandler.UnitOfWork()) {
{ var _log = LogManager.GetCurrentClassLogger();
var configs = NadekoBot.AllGuildConfigs; var sw = Stopwatch.StartNew();
GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
.Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName))
.ToDictionary(c => c.GuildId, c => c.MuteRoleName));
MutedUsers = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>(configs.ToDictionary( var configs = NadekoBot.AllGuildConfigs;
k => k.GuildId, GuildMuteRoles = new ConcurrentDictionary<ulong, string>(configs
v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId)) .Where(c => !string.IsNullOrWhiteSpace(c.MuteRoleName))
)); .ToDictionary(c => c.GuildId, c => c.MuteRoleName));
}
MutedUsers = new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>(configs.ToDictionary(
k => k.GuildId,
v => new ConcurrentHashSet<ulong>(v.MutedUsers.Select(m => m.UserId))
));
NadekoBot.Client.UserJoined += Client_UserJoined; NadekoBot.Client.UserJoined += Client_UserJoined;
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
private static async void Client_UserJoined(IGuildUser usr) private static async void Client_UserJoined(IGuildUser usr)
@ -61,7 +65,7 @@ namespace NadekoBot.Modules.Administration
if (muted == null || !muted.Contains(usr.Id)) if (muted == null || !muted.Contains(usr.Id))
return; return;
else else
await Mute(usr).ConfigureAwait(false); await MuteUser(usr).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -70,7 +74,7 @@ namespace NadekoBot.Modules.Administration
} }
public static async Task Mute(IGuildUser usr) public static async Task MuteUser(IGuildUser usr)
{ {
await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false); await usr.ModifyAsync(x => x.Mute = true).ConfigureAwait(false);
await usr.AddRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); await usr.AddRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
@ -90,7 +94,7 @@ namespace NadekoBot.Modules.Administration
UserMuted(usr, MuteType.All); UserMuted(usr, MuteType.All);
} }
public static async Task Unmute(IGuildUser usr) public static async Task UnmuteUser(IGuildUser usr)
{ {
await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false); await usr.ModifyAsync(x => x.Mute = false).ConfigureAwait(false);
await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false); await usr.RemoveRolesAsync(await GetMuteRole(usr.Guild)).ConfigureAwait(false);
@ -128,7 +132,7 @@ namespace NadekoBot.Modules.Administration
await guild.CreateRoleAsync(defaultMuteRoleName, GuildPermissions.None).ConfigureAwait(false); await guild.CreateRoleAsync(defaultMuteRoleName, GuildPermissions.None).ConfigureAwait(false);
} }
foreach (var toOverwrite in guild.GetTextChannels()) foreach (var toOverwrite in (await guild.GetTextChannelsAsync()))
{ {
try try
{ {
@ -144,142 +148,131 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[Priority(1)] [Priority(1)]
public async Task SetMuteRole(IUserMessage imsg, [Remainder] string name) public async Task SetMuteRole([Remainder] string name)
{ {
var channel = (ITextChannel)imsg.Channel; //var channel = (ITextChannel)Context.Channel;
name = name.Trim(); name = name.Trim();
if (string.IsNullOrWhiteSpace(name)) if (string.IsNullOrWhiteSpace(name))
return; return;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
config.MuteRoleName = name; config.MuteRoleName = name;
GuildMuteRoles.AddOrUpdate(channel.Guild.Id, name, (id, old) => name); GuildMuteRoles.AddOrUpdate(Context.Guild.Id, name, (id, old) => name);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync("☑️ **New mute role set.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("☑️ **New mute role set.**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[Priority(0)] [Priority(0)]
public Task SetMuteRole(IUserMessage imsg, [Remainder] IRole role) public Task SetMuteRole([Remainder] IRole role)
=> SetMuteRole(imsg, role.Name); => SetMuteRole(role.Name);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequirePermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
public async Task Mute(IUserMessage umsg, IGuildUser user) public async Task Mute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await Mute(user).ConfigureAwait(false); await MuteUser(user).ConfigureAwait(false);
await channel.SendConfirmAsync($"🔇 **{user}** has been **muted** from text and voice chat.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔇 **{user}** has been **muted** from text and voice chat.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequirePermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
public async Task Unmute(IUserMessage umsg, IGuildUser user) public async Task Unmute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await Unmute(user).ConfigureAwait(false); await UnmuteUser(user).ConfigureAwait(false);
await channel.SendConfirmAsync($"🔉 **{user}** has been **unmuted** from text and voice chat.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔉 **{user}** has been **unmuted** from text and voice chat.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task ChatMute(IUserMessage umsg, IGuildUser user) public async Task ChatMute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await user.AddRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false); await user.AddRolesAsync(await GetMuteRole(Context.Guild).ConfigureAwait(false)).ConfigureAwait(false);
UserMuted(user, MuteType.Chat); UserMuted(user, MuteType.Chat);
await channel.SendConfirmAsync($"✏️🚫 **{user}** has been **muted** from chatting.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✏️🚫 **{user}** has been **muted** from chatting.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task ChatUnmute(IUserMessage umsg, IGuildUser user) public async Task ChatUnmute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await user.RemoveRolesAsync(await GetMuteRole(channel.Guild).ConfigureAwait(false)).ConfigureAwait(false); await user.RemoveRolesAsync(await GetMuteRole(Context.Guild).ConfigureAwait(false)).ConfigureAwait(false);
UserUnmuted(user, MuteType.Chat); UserUnmuted(user, MuteType.Chat);
await channel.SendConfirmAsync($"✏️✅ **{user}** has been **unmuted** from chatting.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✏️✅ **{user}** has been **unmuted** from chatting.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
public async Task VoiceMute(IUserMessage umsg, IGuildUser user) public async Task VoiceMute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false); await user.ModifyAsync(usr => usr.Mute = true).ConfigureAwait(false);
UserMuted(user, MuteType.Voice); UserMuted(user, MuteType.Voice);
await channel.SendConfirmAsync($"🎙🚫 **{user}** has been **voice muted**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🎙🚫 **{user}** has been **voice muted**.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.MuteMembers)] [RequireUserPermission(GuildPermission.MuteMembers)]
public async Task VoiceUnmute(IUserMessage umsg, IGuildUser user) public async Task VoiceUnmute(IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false); await user.ModifyAsync(usr => usr.Mute = false).ConfigureAwait(false);
UserUnmuted(user, MuteType.Voice); UserUnmuted(user, MuteType.Voice);
await channel.SendConfirmAsync($"🎙✅ **{user}** has been **voice unmuted**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🎙✅ **{user}** has been **voice unmuted**.").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ I most likely don't have the permission necessary for that.").ConfigureAwait(false);
} }
} }
} }

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -8,6 +7,7 @@ using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -16,14 +16,17 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class PlayingRotateCommands public class PlayingRotateCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
public static List<PlayingStatus> RotatingStatusMessages { get; } public static List<PlayingStatus> RotatingStatusMessages { get; }
public static bool RotatingStatuses { get; private set; } = false; public static bool RotatingStatuses { get; private set; } = false;
//todo wtf is with this while(true) in constructor
static PlayingRotateCommands() static PlayingRotateCommands()
{ {
_log = LogManager.GetCurrentClassLogger();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var conf = uow.BotConfig.GetOrCreate(); var conf = uow.BotConfig.GetOrCreate();
@ -31,7 +34,6 @@ namespace NadekoBot.Modules.Administration
RotatingStatuses = conf.RotatingStatuses; RotatingStatuses = conf.RotatingStatuses;
} }
_log = LogManager.GetCurrentClassLogger();
var t = Task.Run(async () => var t = Task.Run(async () =>
{ {
var index = 0; var index = 0;
@ -70,7 +72,7 @@ namespace NadekoBot.Modules.Administration
public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } = public static Dictionary<string, Func<string>> PlayingPlaceholders { get; } =
new Dictionary<string, Func<string>> { new Dictionary<string, Func<string>> {
{"%servers%", () => NadekoBot.Client.GetGuilds().Count().ToString()}, {"%servers%", () => NadekoBot.Client.GetGuilds().Count().ToString()},
{"%users%", () => NadekoBot.Client.GetGuilds().Select(s => s.GetUsers().Count).Sum().ToString()}, {"%users%", () => NadekoBot.Client.GetGuilds().Select(s => s.Users.Count).Sum().ToString()},
{"%playing%", () => { {"%playing%", () => {
var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null); var cnt = Music.Music.MusicPlayers.Count(kvp => kvp.Value.CurrentSong != null);
if (cnt != 1) return cnt.ToString(); if (cnt != 1) return cnt.ToString();
@ -88,7 +90,7 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task RotatePlaying(IUserMessage umsg) public async Task RotatePlaying()
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -98,14 +100,14 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
if (RotatingStatuses) if (RotatingStatuses)
await umsg.Channel.SendConfirmAsync("🆗 **Rotating playing status enabled.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 **Rotating playing status enabled.**").ConfigureAwait(false);
else else
await umsg.Channel.SendConfirmAsync(" **Rotating playing status disabled.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" **Rotating playing status disabled.**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task AddPlaying(IUserMessage umsg, [Remainder] string status) public async Task AddPlaying([Remainder] string status)
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -116,26 +118,26 @@ namespace NadekoBot.Modules.Administration
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
await umsg.Channel.SendConfirmAsync("✅ **Added.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ **Added.**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task ListPlaying(IUserMessage umsg) public async Task ListPlaying()
{ {
if (!RotatingStatusMessages.Any()) if (!RotatingStatusMessages.Any())
await umsg.Channel.SendErrorAsync("❎ **No rotating playing statuses set.**"); await Context.Channel.SendErrorAsync("❎ **No rotating playing statuses set.**");
else else
{ {
var i = 1; var i = 1;
await umsg.Channel.SendConfirmAsync($" {umsg.Author.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}"))); await Context.Channel.SendConfirmAsync($" {Context.User.Mention} `Here is a list of rotating statuses:`\n\n\t" + string.Join("\n\t", RotatingStatusMessages.Select(rs => $"`{i++}.` {rs.Status}")));
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public async Task RemovePlaying(IUserMessage umsg, int index) public async Task RemovePlaying(int index)
{ {
index -= 1; index -= 1;
@ -151,7 +153,7 @@ namespace NadekoBot.Modules.Administration
RotatingStatusMessages.RemoveAt(index); RotatingStatusMessages.RemoveAt(index);
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
await umsg.Channel.SendConfirmAsync($"🗑 **Removed the the playing message:** {msg}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🗑 **Removed the the playing message:** {msg}").ConfigureAwait(false);
} }
} }
} }

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class RatelimitCommand public class RatelimitCommand : ModuleBase
{ {
public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>(); public static ConcurrentDictionary<ulong, Ratelimiter> RatelimitingChannels = new ConcurrentDictionary<ulong, Ratelimiter>();
private static Logger _log { get; } private static Logger _log { get; }
@ -88,42 +88,39 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Slowmode(IUserMessage umsg) public async Task Slowmode()
{ {
var channel = (ITextChannel)umsg.Channel;
Ratelimiter throwaway; Ratelimiter throwaway;
if (RatelimitingChannels.TryRemove(channel.Id, out throwaway)) if (RatelimitingChannels.TryRemove(Context.Channel.Id, out throwaway))
{ {
throwaway.cancelSource.Cancel(); throwaway.cancelSource.Cancel();
await channel.SendConfirmAsync(" Slow mode disabled.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Slow mode disabled.").ConfigureAwait(false);
return; return;
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Slowmode(IUserMessage umsg, int msg, int perSec) public async Task Slowmode(int msg, int perSec)
{ {
await Slowmode(umsg).ConfigureAwait(false); // disable if exists await Slowmode().ConfigureAwait(false); // disable if exists
var channel = (ITextChannel)umsg.Channel;
if (msg < 1 || perSec < 1 || msg > 100 || perSec > 3600) if (msg < 1 || perSec < 1 || msg > 100 || perSec > 3600)
{ {
await channel.SendErrorAsync("⚠️ Invalid parameters."); await Context.Channel.SendErrorAsync("⚠️ Invalid parameters.");
return; return;
} }
var toAdd = new Ratelimiter() var toAdd = new Ratelimiter()
{ {
ChannelId = channel.Id, ChannelId = Context.Channel.Id,
MaxMessages = msg, MaxMessages = msg,
PerSeconds = perSec, PerSeconds = perSec,
}; };
if (RatelimitingChannels.TryAdd(channel.Id, toAdd)) if(RatelimitingChannels.TryAdd(Context.Channel.Id, toAdd))
{ {
await channel.SendConfirmAsync("Slow mode initiated", await Context.Channel.SendConfirmAsync("Slow mode initiated",
$"Users can't send more than `{toAdd.MaxMessages} message(s)` every `{toAdd.PerSeconds} second(s)`.") $"Users can't send more than `{toAdd.MaxMessages} message(s)` every `{toAdd.PerSeconds} second(s)`.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }

View File

@ -16,84 +16,81 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class SelfAssignedRolesCommands public class SelfAssignedRolesCommands : ModuleBase
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task AdSarm(IUserMessage imsg) public async Task AdSarm()
{ {
var channel = (ITextChannel)imsg.Channel;
bool newval; bool newval;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages; newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages;
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($" Automatic deleting of `iam` and `iamn` confirmations has been {(newval ? "**enabled**" : "**disabled**")}.") await Context.Channel.SendConfirmAsync($" Automatic deleting of `iam` and `iamn` confirmations has been {(newval ? "**enabled**" : "**disabled**")}.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task Asar(IUserMessage umsg, [Remainder] IRole role) public async Task Asar([Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel;
IEnumerable<SelfAssignedRole> roles; IEnumerable<SelfAssignedRole> roles;
string msg; string msg;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id); roles = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id);
if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.GuildId)) if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id))
{ {
await channel.SendMessageAsync($"💢 Role **{role.Name}** is already in the list.").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"💢 Role **{role.Name}** is already in the list.").ConfigureAwait(false);
return; return;
} }
else else
{ {
uow.SelfAssignedRoles.Add(new SelfAssignedRole { uow.SelfAssignedRoles.Add(new SelfAssignedRole {
RoleId = role.Id, RoleId = role.Id,
GuildId = role.GuildId GuildId = role.Guild.Id
}); });
await uow.CompleteAsync(); await uow.CompleteAsync();
msg = $"🆗 Role **{role.Name}** added to the list."; msg = $"🆗 Role **{role.Name}** added to the list.";
} }
} }
await channel.SendConfirmAsync(msg.ToString()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(msg.ToString()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task Rsar(IUserMessage umsg, [Remainder] IRole role) public async Task Rsar([Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel; //var channel = (ITextChannel)Context.Channel;
bool success; bool success;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
success = uow.SelfAssignedRoles.DeleteByGuildAndRoleId(role.GuildId, role.Id); success = uow.SelfAssignedRoles.DeleteByGuildAndRoleId(role.Guild.Id, role.Id);
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
if (!success) if (!success)
{ {
await channel.SendErrorAsync("❎ That role is not self-assignable.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❎ That role is not self-assignable.").ConfigureAwait(false);
return; return;
} }
await channel.SendConfirmAsync($"🗑 **{role.Name}** has been removed from the list of self-assignable roles.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🗑 **{role.Name}** has been removed from the list of self-assignable roles.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Lsar(IUserMessage umsg) public async Task Lsar()
{ {
var channel = (ITextChannel)umsg.Channel; //var channel = (ITextChannel)Context.Channel;
var toRemove = new ConcurrentHashSet<SelfAssignedRole>(); var toRemove = new ConcurrentHashSet<SelfAssignedRole>();
var removeMsg = new StringBuilder(); var removeMsg = new StringBuilder();
@ -101,13 +98,13 @@ namespace NadekoBot.Modules.Administration
var roleCnt = 0; var roleCnt = 0;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var roleModels = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id).ToList(); var roleModels = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id).ToList();
roleCnt = roleModels.Count; roleCnt = roleModels.Count;
msg.AppendLine(); msg.AppendLine();
foreach (var roleModel in roleModels) foreach (var roleModel in roleModels)
{ {
var role = channel.Guild.Roles.FirstOrDefault(r => r.Id == roleModel.RoleId); var role = Context.Guild.Roles.FirstOrDefault(r => r.Id == roleModel.RoleId);
if (role == null) if (role == null)
{ {
uow.SelfAssignedRoles.Remove(roleModel); uow.SelfAssignedRoles.Remove(roleModel);
@ -123,61 +120,61 @@ namespace NadekoBot.Modules.Administration
} }
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
await channel.SendConfirmAsync($" There are `{roleCnt}` self assignable roles:", msg.ToString() + "\n\n" + removeMsg.ToString()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" There are `{roleCnt}` self assignable roles:", msg.ToString() + "\n\n" + removeMsg.ToString()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task Tesar(IUserMessage umsg) public async Task Tesar()
{ {
var channel = (ITextChannel)umsg.Channel; //var channel = (ITextChannel)Context.Channel;
bool areExclusive; bool areExclusive;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles; areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles;
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
string exl = areExclusive ? "**exclusive**." : "**not exclusive**."; string exl = areExclusive ? "**exclusive**." : "**not exclusive**.";
await channel.SendConfirmAsync(" Self assigned roles are now " + exl); await Context.Channel.SendConfirmAsync(" Self assigned roles are now " + exl);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Iam(IUserMessage umsg, [Remainder] IRole role) public async Task Iam([Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel; //var channel = (ITextChannel)Context.Channel;
var guildUser = (IGuildUser)umsg.Author; var guildUser = (IGuildUser)Context.User;
var usrMsg = (IUserMessage)umsg;
GuildConfig conf; GuildConfig conf;
IEnumerable<SelfAssignedRole> roles; IEnumerable<SelfAssignedRole> roles;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
conf = uow.GuildConfigs.For(channel.Guild.Id, set => set); conf = uow.GuildConfigs.For(Context.Guild.Id, set => set);
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id); roles = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id);
} }
SelfAssignedRole roleModel; SelfAssignedRole roleModel;
if ((roleModel = roles.FirstOrDefault(r=>r.RoleId == role.Id)) == null) if ((roleModel = roles.FirstOrDefault(r=>r.RoleId == role.Id)) == null)
{ {
await channel.SendErrorAsync("That role is not self-assignable.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("That role is not self-assignable.").ConfigureAwait(false);
return; return;
} }
if (guildUser.Roles.Contains(role)) if (guildUser.RoleIds.Contains(role.Id))
{ {
await channel.SendErrorAsync($"You already have **{role.Name}** role.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"You already have **{role.Name}** role.").ConfigureAwait(false);
return; return;
} }
if (conf.ExclusiveSelfAssignedRoles) if (conf.ExclusiveSelfAssignedRoles)
{ {
var sameRoles = guildUser.Roles.Where(r => roles.Any(rm => rm.RoleId == r.Id)); var sameRoleId = guildUser.RoleIds.Where(r => roles.Select(sar => sar.RoleId).Contains(r)).FirstOrDefault();
if (sameRoles.Any()) var sameRole = Context.Guild.GetRole(sameRoleId);
if (sameRoleId != default(ulong))
{ {
await channel.SendErrorAsync($"You already have **{sameRoles.FirstOrDefault().Name}** `exclusive self-assigned` role.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"You already have **{sameRole?.Name}** `exclusive self-assigned` role.").ConfigureAwait(false);
return; return;
} }
} }
@ -187,42 +184,41 @@ namespace NadekoBot.Modules.Administration
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't add roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
Console.WriteLine(ex); Console.WriteLine(ex);
return; return;
} }
var msg = await channel.SendConfirmAsync($"🆗 You now have **{role.Name}** role.").ConfigureAwait(false); var msg = await Context.Channel.SendConfirmAsync($"🆗 You now have **{role.Name}** role.").ConfigureAwait(false);
if (conf.AutoDeleteSelfAssignedRoleMessages) if (conf.AutoDeleteSelfAssignedRoleMessages)
{ {
msg.DeleteAfter(3); msg.DeleteAfter(3);
umsg.DeleteAfter(3); Context.Message.DeleteAfter(3);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Iamnot(IUserMessage umsg, [Remainder] IRole role) public async Task Iamnot([Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel; var guildUser = (IGuildUser)Context.User;
var guildUser = (IGuildUser)umsg.Author;
bool autoDeleteSelfAssignedRoleMessages; bool autoDeleteSelfAssignedRoleMessages;
IEnumerable<SelfAssignedRole> roles; IEnumerable<SelfAssignedRole> roles;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
autoDeleteSelfAssignedRoleMessages = uow.GuildConfigs.For(channel.Guild.Id, set => set).AutoDeleteSelfAssignedRoleMessages; autoDeleteSelfAssignedRoleMessages = uow.GuildConfigs.For(Context.Guild.Id, set => set).AutoDeleteSelfAssignedRoleMessages;
roles = uow.SelfAssignedRoles.GetFromGuild(channel.Guild.Id); roles = uow.SelfAssignedRoles.GetFromGuild(Context.Guild.Id);
} }
SelfAssignedRole roleModel; SelfAssignedRole roleModel;
if ((roleModel = roles.FirstOrDefault(r => r.RoleId == role.Id)) == null) if ((roleModel = roles.FirstOrDefault(r => r.RoleId == role.Id)) == null)
{ {
await channel.SendErrorAsync("💢 That role is not self-assignable.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("💢 That role is not self-assignable.").ConfigureAwait(false);
return; return;
} }
if (!guildUser.Roles.Contains(role)) if (!guildUser.RoleIds.Contains(role.Id))
{ {
await channel.SendErrorAsync($"❎ You don't have **{role.Name}** role.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"❎ You don't have **{role.Name}** role.").ConfigureAwait(false);
return; return;
} }
try try
@ -231,15 +227,15 @@ namespace NadekoBot.Modules.Administration
} }
catch (Exception) catch (Exception)
{ {
await channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't remove roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"⚠️ I am unable to add that role to you. `I can't remove roles to owners or other roles higher than my role in the role hierarchy.`").ConfigureAwait(false);
return; return;
} }
var msg = await channel.SendConfirmAsync($"🆗 You no longer have **{role.Name}** role.").ConfigureAwait(false); var msg = await Context.Channel.SendConfirmAsync($"🆗 You no longer have **{role.Name}** role.").ConfigureAwait(false);
if (autoDeleteSelfAssignedRoleMessages) if (autoDeleteSelfAssignedRoleMessages)
{ {
msg.DeleteAfter(3); msg.DeleteAfter(3);
umsg.DeleteAfter(3); Context.Message.DeleteAfter(3);
} }
} }
} }

View File

@ -2,7 +2,10 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System;
using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
@ -10,42 +13,155 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
class SelfCommands class SelfCommands : ModuleBase
{ {
private ShardedDiscordClient _client;
public SelfCommands()
{
this._client = NadekoBot.Client;
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Leave(IUserMessage umsg, [Remainder] string guildStr) public async Task Leave([Remainder] string guildStr)
{ {
var channel = (ITextChannel)umsg.Channel;
guildStr = guildStr.Trim().ToUpperInvariant(); guildStr = guildStr.Trim().ToUpperInvariant();
var server = _client.GetGuilds().FirstOrDefault(g => g.Id.ToString().Trim().ToUpperInvariant() == guildStr) ?? var server = NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Id.ToString().Trim().ToUpperInvariant() == guildStr) ??
_client.GetGuilds().FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == guildStr); NadekoBot.Client.GetGuilds().FirstOrDefault(g => g.Name.Trim().ToUpperInvariant() == guildStr);
if (server == null) if (server == null)
{ {
await channel.SendErrorAsync("⚠️ Cannot find that server").ConfigureAwait(false); await Context.Channel.SendErrorAsync("⚠️ Cannot find that server").ConfigureAwait(false);
return; return;
} }
if (server.OwnerId != _client.GetCurrentUser().Id) if (server.OwnerId != NadekoBot.Client.CurrentUser().Id)
{ {
await server.LeaveAsync().ConfigureAwait(false); await server.LeaveAsync().ConfigureAwait(false);
await channel.SendConfirmAsync("✅ Left server " + server.Name).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ Left server " + server.Name).ConfigureAwait(false);
} }
else else
{ {
await server.DeleteAsync().ConfigureAwait(false); await server.DeleteAsync().ConfigureAwait(false);
await channel.SendConfirmAsync("Deleted server " + server.Name).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Deleted server " + server.Name).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Die()
{
try { await Context.Channel.SendConfirmAsync(" **Shutting down.**").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
await Task.Delay(2000).ConfigureAwait(false);
Environment.Exit(0);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetName([Remainder] string newName)
{
if (string.IsNullOrWhiteSpace(newName))
return;
await NadekoBot.Client.CurrentUser().ModifyAsync(u => u.Username = newName).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync($" Successfully changed name to **{newName}**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetAvatar([Remainder] string img = null)
{
if (string.IsNullOrWhiteSpace(img))
return;
using (var http = new HttpClient())
{
using (var sr = await http.GetStreamAsync(img))
{
var imgStream = new MemoryStream();
await sr.CopyToAsync(imgStream);
imgStream.Position = 0;
await NadekoBot.Client.CurrentUser().ModifyAsync(u => u.Avatar = new Image(imgStream)).ConfigureAwait(false);
}
}
await Context.Channel.SendConfirmAsync("🆒 **New avatar set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetGame([Remainder] string game = null)
{
game = game ?? "";
await NadekoBot.Client.SetGame(game).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync("👾 **New game set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task SetStream(string url, [Remainder] string name = null)
{
name = name ?? "";
await NadekoBot.Client.SetStream(name, url).ConfigureAwait(false);
await Context.Channel.SendConfirmAsync(" **New stream set.**").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Send(string where, [Remainder] string msg = null)
{
if (string.IsNullOrWhiteSpace(msg))
return;
var ids = where.Split('|');
if (ids.Length != 2)
return;
var sid = ulong.Parse(ids[0]);
var server = NadekoBot.Client.GetGuilds().Where(s => s.Id == sid).FirstOrDefault();
if (server == null)
return;
if (ids[1].ToUpperInvariant().StartsWith("C:"))
{
var cid = ulong.Parse(ids[1].Substring(2));
var ch = (await server.GetTextChannelsAsync()).Where(c => c.Id == cid).FirstOrDefault();
if (ch == null)
{
return;
}
await ch.SendMessageAsync(msg).ConfigureAwait(false);
}
else if (ids[1].ToUpperInvariant().StartsWith("U:"))
{
var uid = ulong.Parse(ids[1].Substring(2));
var user = server.Users.Where(u => u.Id == uid).FirstOrDefault();
if (user == null)
{
return;
}
await user.SendMessageAsync(msg).ConfigureAwait(false);
}
else
{
await Context.Channel.SendErrorAsync("⚠️ Invalid format.").ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases]
[OwnerOnly]
public async Task Announce([Remainder] string message)
{
var channels = await Task.WhenAll(NadekoBot.Client.GetGuilds().Select(g =>
g.GetDefaultChannelAsync()
)).ConfigureAwait(false);
if (channels == null)
return;
await Task.WhenAll(channels.Where(c => c != null).Select(c => c.SendConfirmAsync($"🆕 Message from {Context.User} `[Bot Owner]`:", message)))
.ConfigureAwait(false);
await Context.Channel.SendConfirmAsync("🆗").ConfigureAwait(false);
}
} }
} }
} }

View File

@ -1,9 +1,9 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Services.Database;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NLog; using NLog;
using System; using System;
@ -15,7 +15,7 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class ServerGreetCommands public class ServerGreetCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
@ -108,19 +108,19 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task GreetDel(IUserMessage umsg, int timer = 30) public async Task GreetDel(int timer = 30)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
if (timer < 0 || timer > 600) if (timer < 0 || timer > 600)
return; return;
await ServerGreetCommands.SetGreetDel(channel.Guild.Id, timer).ConfigureAwait(false); await ServerGreetCommands.SetGreetDel(Context.Guild.Id, timer).ConfigureAwait(false);
if (timer > 0) if (timer > 0)
await channel.SendConfirmAsync($"🆗 Greet messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🆗 Greet messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" Automatic deletion of greet messages has been **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Automatic deletion of greet messages has been **disabled**.").ConfigureAwait(false);
} }
private static async Task SetGreetDel(ulong id, int timer) private static async Task SetGreetDel(ulong id, int timer)
@ -139,17 +139,15 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Greet(IUserMessage umsg) public async Task Greet()
{ {
var channel = (ITextChannel)umsg.Channel; var enabled = await ServerGreetCommands.SetGreet(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
var enabled = await ServerGreetCommands.SetGreet(channel.Guild.Id, channel.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await channel.SendConfirmAsync("✅ Greeting messages **enabled** on this channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ Greeting messages **enabled** on this channel.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" Greeting messages **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Greeting messages **disabled**.").ConfigureAwait(false);
} }
private static async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null) private static async Task<bool> SetGreet(ulong guildId, ulong channelId, bool? value = null)
@ -168,27 +166,25 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task GreetMsg(IUserMessage umsg, [Remainder] string text = null) public async Task GreetMsg([Remainder] string text = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
{ {
string channelGreetMessageText; string channelGreetMessageText;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
channelGreetMessageText = uow.GuildConfigs.For(channel.Guild.Id, set => set).ChannelGreetMessageText; channelGreetMessageText = uow.GuildConfigs.For(Context.Guild.Id, set => set).ChannelGreetMessageText;
} }
await channel.SendConfirmAsync("Current greet message: ", channelGreetMessageText?.SanitizeMentions()); await Context.Channel.SendConfirmAsync("Current greet message: ", channelGreetMessageText?.SanitizeMentions());
return; return;
} }
var sendGreetEnabled = ServerGreetCommands.SetGreetMessage(channel.Guild.Id, ref text); var sendGreetEnabled = ServerGreetCommands.SetGreetMessage(Context.Guild.Id, ref text);
await channel.SendConfirmAsync("🆗 New greet message **set**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 New greet message **set**.").ConfigureAwait(false);
if (!sendGreetEnabled) if (!sendGreetEnabled)
await channel.SendConfirmAsync(" Enable greet messsages by typing `.greet`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Enable greet messsages by typing `.greet`").ConfigureAwait(false);
} }
public static bool SetGreetMessage(ulong guildId, ref string message) public static bool SetGreetMessage(ulong guildId, ref string message)
@ -212,17 +208,15 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task GreetDm(IUserMessage umsg) public async Task GreetDm()
{ {
var channel = (ITextChannel)umsg.Channel; var enabled = await ServerGreetCommands.SetGreetDm(Context.Guild.Id).ConfigureAwait(false);
var enabled = await ServerGreetCommands.SetGreetDm(channel.Guild.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await channel.SendConfirmAsync("🆗 DM Greet announcements **enabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 DM Greet announcements **enabled**.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" Greet announcements **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Greet announcements **disabled**.").ConfigureAwait(false);
} }
private static async Task<bool> SetGreetDm(ulong guildId, bool? value = null) private static async Task<bool> SetGreetDm(ulong guildId, bool? value = null)
@ -240,27 +234,25 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task GreetDmMsg(IUserMessage umsg, [Remainder] string text = null) public async Task GreetDmMsg([Remainder] string text = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
{ {
GuildConfig config; GuildConfig config;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
config = uow.GuildConfigs.For(channel.Guild.Id); config = uow.GuildConfigs.For(Context.Guild.Id);
} }
await channel.SendConfirmAsync(" Current **DM greet** message: `" + config.DmGreetMessageText?.SanitizeMentions() + "`"); await Context.Channel.SendConfirmAsync(" Current **DM greet** message: `" + config.DmGreetMessageText?.SanitizeMentions() + "`");
return; return;
} }
var sendGreetEnabled = ServerGreetCommands.SetGreetDmMessage(channel.Guild.Id, ref text); var sendGreetEnabled = ServerGreetCommands.SetGreetDmMessage(Context.Guild.Id, ref text);
await channel.SendConfirmAsync("🆗 New DM greet message **set**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 New DM greet message **set**.").ConfigureAwait(false);
if (!sendGreetEnabled) if (!sendGreetEnabled)
await channel.SendConfirmAsync($" Enable DM greet messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}greetdm`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" Enable DM greet messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}greetdm`").ConfigureAwait(false);
} }
public static bool SetGreetDmMessage(ulong guildId, ref string message) public static bool SetGreetDmMessage(ulong guildId, ref string message)
@ -284,17 +276,15 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task Bye(IUserMessage umsg) public async Task Bye()
{ {
var channel = (ITextChannel)umsg.Channel; var enabled = await ServerGreetCommands.SetBye(Context.Guild.Id, Context.Channel.Id).ConfigureAwait(false);
var enabled = await ServerGreetCommands.SetBye(channel.Guild.Id, channel.Id).ConfigureAwait(false);
if (enabled) if (enabled)
await channel.SendConfirmAsync("✅ Bye announcements **enabled** on this channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ Bye announcements **enabled** on this channel.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" Bye announcements **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Bye announcements **disabled**.").ConfigureAwait(false);
} }
private static async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null) private static async Task<bool> SetBye(ulong guildId, ulong channelId, bool? value = null)
@ -313,27 +303,25 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task ByeMsg(IUserMessage umsg, [Remainder] string text = null) public async Task ByeMsg([Remainder] string text = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
{ {
string byeMessageText; string byeMessageText;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
byeMessageText = uow.GuildConfigs.For(channel.Guild.Id, set => set).ChannelByeMessageText; byeMessageText = uow.GuildConfigs.For(Context.Guild.Id, set => set).ChannelByeMessageText;
} }
await channel.SendConfirmAsync(" Current **bye** message: `" + byeMessageText?.SanitizeMentions() + "`"); await Context.Channel.SendConfirmAsync(" Current **bye** message: `" + byeMessageText?.SanitizeMentions() + "`");
return; return;
} }
var sendByeEnabled = ServerGreetCommands.SetByeMessage(channel.Guild.Id, ref text); var sendByeEnabled = ServerGreetCommands.SetByeMessage(Context.Guild.Id, ref text);
await channel.SendConfirmAsync("🆗 New bye message **set**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 New bye message **set**.").ConfigureAwait(false);
if (!sendByeEnabled) if (!sendByeEnabled)
await channel.SendConfirmAsync($" Enable bye messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}bye`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" Enable bye messsages by typing `{NadekoBot.ModulePrefixes[typeof(Administration).Name]}bye`").ConfigureAwait(false);
} }
public static bool SetByeMessage(ulong guildId, ref string message) public static bool SetByeMessage(ulong guildId, ref string message)
@ -357,17 +345,15 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageGuild)] [RequireUserPermission(GuildPermission.ManageGuild)]
public async Task ByeDel(IUserMessage umsg, int timer = 30) public async Task ByeDel(int timer = 30)
{ {
var channel = (ITextChannel)umsg.Channel; await ServerGreetCommands.SetByeDel(Context.Guild.Id, timer).ConfigureAwait(false);
await ServerGreetCommands.SetByeDel(channel.Guild.Id, timer).ConfigureAwait(false);
if (timer > 0) if (timer > 0)
await channel.SendConfirmAsync($"🆗 Bye messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🆗 Bye messages **will be deleted** after `{timer} seconds`.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync(" Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Automatic deletion of bye messages has been **disabled**.").ConfigureAwait(false);
} }
private static async Task SetByeDel(ulong id, int timer) private static async Task SetByeDel(ulong id, int timer)

View File

@ -4,8 +4,10 @@ using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,23 +17,28 @@ namespace NadekoBot.Modules.Administration
public partial class Administration public partial class Administration
{ {
[Group] [Group]
public class VoicePlusTextCommands public class VoicePlusTextCommands : ModuleBase
{ {
private static Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled); private static Regex channelNameRegex = new Regex(@"[^a-zA-Z0-9 -]", RegexOptions.Compiled);
private static ConcurrentHashSet<ulong> voicePlusTextCache { get; } private static ConcurrentHashSet<ulong> voicePlusTextCache { get; }
static VoicePlusTextCommands() static VoicePlusTextCommands()
{ {
var _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
voicePlusTextCache = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId)); voicePlusTextCache = new ConcurrentHashSet<ulong>(NadekoBot.AllGuildConfigs.Where(g => g.VoicePlusTextEnabled).Select(g => g.GuildId));
} }
NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler; NadekoBot.Client.UserVoiceStateUpdated += UserUpdatedEventHandler;
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
private static async void UserUpdatedEventHandler(IUser iuser, IVoiceState before, IVoiceState after) private static async void UserUpdatedEventHandler(SocketUser iuser, SocketVoiceState before, SocketVoiceState after)
{ {
var user = (iuser as IGuildUser); var user = (iuser as SocketGuildUser);
var guild = user?.Guild; var guild = user?.Guild;
if (guild == null) if (guild == null)
@ -39,7 +46,7 @@ namespace NadekoBot.Modules.Administration
try try
{ {
var botUserPerms = guild.GetCurrentUser().GuildPermissions; var botUserPerms = guild.CurrentUser.GuildPermissions;
if (before.VoiceChannel == after.VoiceChannel) return; if (before.VoiceChannel == after.VoiceChannel) return;
@ -68,7 +75,7 @@ namespace NadekoBot.Modules.Administration
var beforeVch = before.VoiceChannel; var beforeVch = before.VoiceChannel;
if (beforeVch != null) if (beforeVch != null)
{ {
var textChannel = guild.GetTextChannels().Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault(); var textChannel = (await guild.GetTextChannelsAsync()).Where(t => t.Name == GetChannelName(beforeVch.Name).ToLowerInvariant()).FirstOrDefault();
if (textChannel != null) if (textChannel != null)
await textChannel.AddPermissionOverwriteAsync(user, await textChannel.AddPermissionOverwriteAsync(user,
new OverwritePermissions(readMessages: PermValue.Deny, new OverwritePermissions(readMessages: PermValue.Deny,
@ -77,7 +84,7 @@ namespace NadekoBot.Modules.Administration
var afterVch = after.VoiceChannel; var afterVch = after.VoiceChannel;
if (afterVch != null && guild.AFKChannelId != afterVch.Id) if (afterVch != null && guild.AFKChannelId != afterVch.Id)
{ {
var textChannel = guild.GetTextChannels() var textChannel = (await guild.GetTextChannelsAsync())
.Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant()) .Where(t => t.Name == GetChannelName(afterVch.Name).ToLowerInvariant())
.FirstOrDefault(); .FirstOrDefault();
if (textChannel == null) if (textChannel == null)
@ -103,17 +110,16 @@ namespace NadekoBot.Modules.Administration
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
public async Task VoicePlusText(IUserMessage msg) public async Task VoicePlusText()
{ {
var channel = (ITextChannel)msg.Channel; var guild = Context.Guild;
var guild = channel.Guild;
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false); var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels) if (!botUser.GuildPermissions.ManageRoles || !botUser.GuildPermissions.ManageChannels)
{ {
await channel.SendErrorAsync("I require atleast **manage roles** and **manage channels permissions** to enable this feature. `(preffered Administration permission)`"); await Context.Channel.SendErrorAsync("I require atleast **manage roles** and **manage channels permissions** to enable this feature. `(preffered Administration permission)`");
return; return;
} }
@ -121,7 +127,7 @@ namespace NadekoBot.Modules.Administration
{ {
try try
{ {
await channel.SendErrorAsync("⚠️ You are enabling this feature and **I do not have ADMINISTRATOR permissions**. " + await Context.Channel.SendErrorAsync("⚠️ You are enabling 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.`"); "`This may cause some issues, and you will have to clean up text channels yourself afterwards.`");
} }
catch { } catch { }
@ -138,39 +144,38 @@ namespace NadekoBot.Modules.Administration
if (!isEnabled) if (!isEnabled)
{ {
voicePlusTextCache.TryRemove(guild.Id); voicePlusTextCache.TryRemove(guild.Id);
foreach (var textChannel in guild.GetTextChannels().Where(c => c.Name.EndsWith("-voice"))) foreach (var textChannel in (await guild.GetTextChannelsAsync().ConfigureAwait(false)).Where(c => c.Name.EndsWith("-voice")))
{ {
try { await textChannel.DeleteAsync().ConfigureAwait(false); } catch { } try { await textChannel.DeleteAsync().ConfigureAwait(false); } catch { }
} }
await channel.SendConfirmAsync(" Successfuly **removed** voice + text feature.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" Successfuly **removed** voice + text feature.").ConfigureAwait(false);
return; return;
} }
voicePlusTextCache.Add(guild.Id); voicePlusTextCache.Add(guild.Id);
await channel.SendConfirmAsync("🆗 Successfuly **enabled** voice + text feature.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🆗 Successfuly **enabled** voice + text feature.").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync(ex.ToString()).ConfigureAwait(false); await Context.Channel.SendErrorAsync(ex.ToString()).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageChannels)] [RequireUserPermission(GuildPermission.ManageChannels)]
[RequirePermission(GuildPermission.ManageRoles)] [RequireUserPermission(GuildPermission.ManageRoles)]
public async Task CleanVPlusT(IUserMessage msg) public async Task CleanVPlusT()
{ {
var channel = (ITextChannel)msg.Channel; var guild = Context.Guild;
var guild = channel.Guild;
var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false); var botUser = await guild.GetCurrentUserAsync().ConfigureAwait(false);
if (!botUser.GuildPermissions.Administrator) if (!botUser.GuildPermissions.Administrator)
{ {
await channel.SendErrorAsync("I need **Administrator permission** to do that.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("I need **Administrator permission** to do that.").ConfigureAwait(false);
return; return;
} }
var allTxtChannels = guild.GetTextChannels().Where(c => c.Name.EndsWith("-voice")); var allTxtChannels = (await guild.GetTextChannelsAsync()).Where(c => c.Name.EndsWith("-voice"));
var validTxtChannelNames = guild.GetVoiceChannels().Select(c => GetChannelName(c.Name).ToLowerInvariant()); var validTxtChannelNames = (await guild.GetVoiceChannelsAsync()).Select(c => GetChannelName(c.Name).ToLowerInvariant());
var invalidTxtChannels = allTxtChannels.Where(c => !validTxtChannelNames.Contains(c.Name)); var invalidTxtChannels = allTxtChannels.Where(c => !validTxtChannelNames.Contains(c.Name));
@ -180,7 +185,7 @@ namespace NadekoBot.Modules.Administration
await Task.Delay(500); await Task.Delay(500);
} }
await channel.SendConfirmAsync("Cleaned v+t.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Cleaned v+t.").ConfigureAwait(false);
} }
} }
} }

View File

@ -7,11 +7,12 @@ using System.Threading.Tasks;
using Discord; using Discord;
using NadekoBot.Services; using NadekoBot.Services;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Linq; using System.Linq;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Threading; using System.Threading;
using System.Diagnostics;
using NLog;
namespace NadekoBot.Modules.ClashOfClans namespace NadekoBot.Modules.ClashOfClans
{ {
@ -22,8 +23,12 @@ namespace NadekoBot.Modules.ClashOfClans
private static Timer checkWarTimer { get; } private static Timer checkWarTimer { get; }
private static new readonly Logger _log;
static ClashOfClans() static ClashOfClans()
{ {
_log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>( ClashWars = new ConcurrentDictionary<ulong, List<ClashWar>>(
@ -32,7 +37,9 @@ namespace NadekoBot.Modules.ClashOfClans
.Select(cw => .Select(cw =>
{ {
cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId) cw.Channel = NadekoBot.Client.GetGuild(cw.GuildId)
?.GetTextChannel(cw.ChannelId); ?.GetTextChannelAsync(cw.ChannelId)
.GetAwaiter()
.GetResult();
return cw; return cw;
}) })
.Where(cw => cw.Channel != null) .Where(cw => cw.Channel != null)
@ -77,11 +84,9 @@ namespace NadekoBot.Modules.ClashOfClans
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task CreateWar(IUserMessage umsg, int size, [Remainder] string enemyClan = null) public async Task CreateWar(int size, [Remainder] string enemyClan = null)
{ {
var channel = (ITextChannel)umsg.Channel; if (!(Context.User as IGuildUser).GuildPermissions.ManageChannels)
if (!(umsg.Author as IGuildUser).GuildPermissions.ManageChannels)
return; return;
if (string.IsNullOrWhiteSpace(enemyClan)) if (string.IsNullOrWhiteSpace(enemyClan))
@ -89,67 +94,64 @@ namespace NadekoBot.Modules.ClashOfClans
if (size < 10 || size > 50 || size % 5 != 0) if (size < 10 || size > 50 || size % 5 != 0)
{ {
await channel.SendErrorAsync("🔰 Not a Valid war size").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 Not a Valid war size").ConfigureAwait(false);
return; return;
} }
List<ClashWar> wars; List<ClashWar> wars;
if (!ClashWars.TryGetValue(channel.Guild.Id, out wars)) if (!ClashWars.TryGetValue(Context.Guild.Id, out wars))
{ {
wars = new List<ClashWar>(); wars = new List<ClashWar>();
if (!ClashWars.TryAdd(channel.Guild.Id, wars)) if (!ClashWars.TryAdd(Context.Guild.Id, wars))
return; return;
} }
var cw = await CreateWar(enemyClan, size, channel.Guild.Id, umsg.Channel.Id); var cw = await CreateWar(enemyClan, size, Context.Guild.Id, Context.Channel.Id);
wars.Add(cw); wars.Add(cw);
await channel.SendConfirmAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"❗🔰**CREATED CLAN WAR AGAINST {cw.ShortPrint()}**").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task StartWar(IUserMessage umsg, [Remainder] string number = null) public async Task StartWar([Remainder] string number = null)
{ {
var channel = (ITextChannel)umsg.Channel;
int num = 0; int num = 0;
int.TryParse(number, out num); int.TryParse(number, out num);
var warsInfo = GetWarInfo(umsg, num); var warsInfo = GetWarInfo(Context.Guild, num);
if (warsInfo == null) if (warsInfo == null)
{ {
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
return; return;
} }
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
try try
{ {
war.Start(); war.Start();
await channel.SendConfirmAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔰**STARTED WAR AGAINST {war.ShortPrint()}**").ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"🔰**WAR AGAINST {war.ShortPrint()} HAS ALREADY STARTED**").ConfigureAwait(false);
} }
SaveWar(war); SaveWar(war);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ListWar(IUserMessage umsg, [Remainder] string number = null) public async Task ListWar([Remainder] string number = null)
{ {
var channel = (ITextChannel)umsg.Channel;
// if number is null, print all wars in a short way // if number is null, print all wars in a short way
if (string.IsNullOrWhiteSpace(number)) if (string.IsNullOrWhiteSpace(number))
{ {
//check if there are any wars //check if there are any wars
List<ClashWar> wars = null; List<ClashWar> wars = null;
ClashWars.TryGetValue(channel.Guild.Id, out wars); ClashWars.TryGetValue(Context.Guild.Id, out wars);
if (wars == null || wars.Count == 0) if (wars == null || wars.Count == 0)
{ {
await channel.SendErrorAsync("🔰 **No active wars.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **No active wars.**").ConfigureAwait(false);
return; return;
} }
@ -162,90 +164,84 @@ namespace NadekoBot.Modules.ClashOfClans
sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**"); sb.AppendLine($"\t\t`Size:` **{wars[i].Size} v {wars[i].Size}**");
sb.AppendLine("**-------------------------**"); sb.AppendLine("**-------------------------**");
} }
await channel.SendConfirmAsync(sb.ToString()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(sb.ToString()).ConfigureAwait(false);
return; return;
} }
var num = 0; var num = 0;
int.TryParse(number, out num); int.TryParse(number, out num);
//if number is not null, print the war needed //if number is not null, print the war needed
var warsInfo = GetWarInfo(umsg, num); var warsInfo = GetWarInfo(Context.Guild, num);
if (warsInfo == null) if (warsInfo == null)
{ {
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
return; return;
} }
await channel.SendConfirmAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(warsInfo.Item1[warsInfo.Item2].ToPrettyString()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Claim(IUserMessage umsg, int number, int baseNumber, [Remainder] string other_name = null) public async Task Claim(int number, int baseNumber, [Remainder] string other_name = null)
{ {
var channel = (ITextChannel)umsg.Channel; var warsInfo = GetWarInfo(Context.Guild, number);
var warsInfo = GetWarInfo(umsg, number);
if (warsInfo == null || warsInfo.Item1.Count == 0) if (warsInfo == null || warsInfo.Item1.Count == 0)
{ {
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
return; return;
} }
var usr = var usr =
string.IsNullOrWhiteSpace(other_name) ? string.IsNullOrWhiteSpace(other_name) ?
umsg.Author.Username : Context.User.Username :
other_name; other_name;
try try
{ {
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
war.Call(usr, baseNumber - 1); war.Call(usr, baseNumber - 1);
SaveWar(war); SaveWar(war);
await channel.SendConfirmAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔰**{usr}** claimed a base #{baseNumber} for a war against {war.ShortPrint()}").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ClaimFinish1(IUserMessage umsg, int number, int baseNumber = 0) public async Task ClaimFinish1(int number, int baseNumber = 0)
{ {
var channel = (ITextChannel)umsg.Channel; await FinishClaim(number, baseNumber - 1, 1);
await FinishClaim(umsg, number, baseNumber - 1, 1);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ClaimFinish2(IUserMessage umsg, int number, int baseNumber = 0) public async Task ClaimFinish2(int number, int baseNumber = 0)
{ {
var channel = (ITextChannel)umsg.Channel; await FinishClaim(number, baseNumber - 1, 2);
await FinishClaim(umsg, number, baseNumber - 1, 2);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ClaimFinish(IUserMessage umsg, int number, int baseNumber = 0) public async Task ClaimFinish(int number, int baseNumber = 0)
{ {
var channel = (ITextChannel)umsg.Channel; await FinishClaim(number, baseNumber - 1);
await FinishClaim(umsg, number, baseNumber - 1);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task EndWar(IUserMessage umsg, int number) public async Task EndWar(int number)
{ {
var channel = (ITextChannel)umsg.Channel; var warsInfo = GetWarInfo(Context.Guild, number);
var warsInfo = GetWarInfo(umsg, number);
if (warsInfo == null) if (warsInfo == null)
{ {
await channel.SendErrorAsync("🔰 That war does not exist.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 That war does not exist.").ConfigureAwait(false);
return; return;
} }
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
war.End(); war.End();
SaveWar(war); SaveWar(war);
await channel.SendConfirmAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"❗🔰**War against {warsInfo.Item1[warsInfo.Item2].ShortPrint()} ended.**").ConfigureAwait(false);
var size = warsInfo.Item1[warsInfo.Item2].Size; var size = warsInfo.Item1[warsInfo.Item2].Size;
warsInfo.Item1.RemoveAt(warsInfo.Item2); warsInfo.Item1.RemoveAt(warsInfo.Item2);
@ -253,40 +249,37 @@ namespace NadekoBot.Modules.ClashOfClans
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Unclaim(IUserMessage umsg, int number, [Remainder] string otherName = null) public async Task Unclaim(int number, [Remainder] string otherName = null)
{ {
var channel = (ITextChannel)umsg.Channel; var warsInfo = GetWarInfo(Context.Guild, number);
var warsInfo = GetWarInfo(umsg, number);
if (warsInfo == null || warsInfo.Item1.Count == 0) if (warsInfo == null || warsInfo.Item1.Count == 0)
{ {
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
return; return;
} }
var usr = var usr =
string.IsNullOrWhiteSpace(otherName) ? string.IsNullOrWhiteSpace(otherName) ?
umsg.Author.Username : Context.User.Username :
otherName; otherName;
try try
{ {
var war = warsInfo.Item1[warsInfo.Item2]; var war = warsInfo.Item1[warsInfo.Item2];
var baseNumber = war.Uncall(usr); var baseNumber = war.Uncall(usr);
SaveWar(war); SaveWar(war);
await channel.SendConfirmAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔰 @{usr} has **UNCLAIMED** a base #{baseNumber + 1} from a war against {war.ShortPrint()}").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
} }
} }
private async Task FinishClaim(IUserMessage umsg, int number, int baseNumber, int stars = 3) private async Task FinishClaim(int number, int baseNumber, int stars = 3)
{ {
var channel = (ITextChannel)umsg.Channel; var warInfo = GetWarInfo(Context.Guild, number);
var warInfo = GetWarInfo(umsg, number);
if (warInfo == null || warInfo.Item1.Count == 0) if (warInfo == null || warInfo.Item1.Count == 0)
{ {
await channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🔰 **That war does not exist.**").ConfigureAwait(false);
return; return;
} }
var war = warInfo.Item1[warInfo.Item2]; var war = warInfo.Item1[warInfo.Item2];
@ -294,27 +287,25 @@ namespace NadekoBot.Modules.ClashOfClans
{ {
if (baseNumber == -1) if (baseNumber == -1)
{ {
baseNumber = war.FinishClaim(umsg.Author.Username, stars); baseNumber = war.FinishClaim(Context.User.Username, stars);
SaveWar(war); SaveWar(war);
} }
else else
{ {
war.FinishClaim(baseNumber, stars); war.FinishClaim(baseNumber, stars);
} }
await channel.SendConfirmAsync($"❗🔰{umsg.Author.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"❗🔰{Context.User.Mention} **DESTROYED** a base #{baseNumber + 1} in a war against {war.ShortPrint()}").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"🔰 {ex.Message}").ConfigureAwait(false);
} }
} }
private static Tuple<List<ClashWar>, int> GetWarInfo(IUserMessage umsg, int num) private static Tuple<List<ClashWar>, int> GetWarInfo(IGuild guild, int num)
{ {
var channel = (ITextChannel)umsg.Channel;
//check if there are any wars
List<ClashWar> wars = null; List<ClashWar> wars = null;
ClashWars.TryGetValue(channel.Guild.Id, out wars); ClashWars.TryGetValue(guild.Id, out wars);
if (wars == null || wars.Count == 0) if (wars == null || wars.Count == 0)
{ {
return null; return null;
@ -331,6 +322,7 @@ namespace NadekoBot.Modules.ClashOfClans
public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId) public static async Task<ClashWar> CreateWar(string enemyClan, int size, ulong serverId, ulong channelId)
{ {
var channel = await NadekoBot.Client.GetGuild(serverId)?.GetTextChannelAsync(channelId);
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var cw = new ClashWar var cw = new ClashWar
@ -340,8 +332,7 @@ namespace NadekoBot.Modules.ClashOfClans
Bases = new List<ClashCaller>(size), Bases = new List<ClashCaller>(size),
GuildId = serverId, GuildId = serverId,
ChannelId = channelId, ChannelId = channelId,
Channel = NadekoBot.Client.GetGuild(serverId) Channel = channel,
?.GetTextChannel(channelId)
}; };
cw.Bases.Capacity = size; cw.Bases.Capacity = size;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)

View File

@ -7,6 +7,9 @@ using System.Collections.Concurrent;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using Discord; using Discord;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NLog;
using System.Diagnostics;
using Discord.WebSocket;
namespace NadekoBot.Modules.CustomReactions namespace NadekoBot.Modules.CustomReactions
{ {
@ -18,29 +21,33 @@ namespace NadekoBot.Modules.CustomReactions
public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>(); public static ConcurrentDictionary<string, uint> ReactionStats { get; } = new ConcurrentDictionary<string, uint>();
private static new readonly Logger _log;
static CustomReactions() static CustomReactions()
{ {
_log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var items = uow.CustomReactions.GetAll(); var items = uow.CustomReactions.GetAll();
GuildReactions = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet<CustomReaction>(g))); GuildReactions = new ConcurrentDictionary<ulong, ConcurrentHashSet<CustomReaction>>(items.Where(g => g.GuildId != null && g.GuildId != 0).GroupBy(k => k.GuildId.Value).ToDictionary(g => g.Key, g => new ConcurrentHashSet<CustomReaction>(g)));
GlobalReactions = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0)); GlobalReactions = new ConcurrentHashSet<CustomReaction>(items.Where(g => g.GuildId == null || g.GuildId == 0));
} }
} sw.Stop();
public CustomReactions() : base() _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
{
} }
public void ClearStats() => ReactionStats.Clear(); public void ClearStats() => ReactionStats.Clear();
public static async Task<bool> TryExecuteCustomReaction(IUserMessage umsg) public static async Task<bool> TryExecuteCustomReaction(SocketUserMessage umsg)
{ {
var channel = umsg.Channel as ITextChannel; var channel = umsg.Channel as SocketTextChannel;
if (channel == null) if (channel == null)
return false; return false;
var content = umsg.Content.Trim().ToLowerInvariant(); var content = umsg.Content.Trim().ToLowerInvariant();
ConcurrentHashSet<CustomReaction> reactions; ConcurrentHashSet<CustomReaction> reactions;
GuildReactions.TryGetValue(channel.Guild.Id, out reactions); GuildReactions.TryGetValue(channel.Guild.Id, out reactions);
if (reactions != null && reactions.Any()) if (reactions != null && reactions.Any())
{ {
@ -76,17 +83,17 @@ namespace NadekoBot.Modules.CustomReactions
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task AddCustReact(IUserMessage imsg, string key, [Remainder] string message) public async Task AddCustReact(string key, [Remainder] string message)
{ {
var channel = imsg.Channel as ITextChannel; var channel = Context.Channel as ITextChannel;
if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key)) if (string.IsNullOrWhiteSpace(message) || string.IsNullOrWhiteSpace(key))
return; return;
key = key.ToLowerInvariant(); key = key.ToLowerInvariant();
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator)) if ((channel == null && !NadekoBot.Credentials.IsOwner(Context.User)) || (channel != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
{ {
try { await imsg.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { } try { await Context.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
return; return;
} }
@ -111,36 +118,34 @@ namespace NadekoBot.Modules.CustomReactions
} }
else else
{ {
var reactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()); var reactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
reactions.Add(cr); reactions.Add(cr);
} }
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle("New Custom Reaction") .WithTitle("New Custom Reaction")
.WithDescription($"#{cr.Id}") .WithDescription($"#{cr.Id}")
.AddField(efb => efb.WithName("Trigger").WithValue(key)) .AddField(efb => efb.WithName("Trigger").WithValue(key))
.AddField(efb => efb.WithName("Response").WithValue(message)) .AddField(efb => efb.WithName("Response").WithValue(message))
.Build()).ConfigureAwait(false); ).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(0)] [Priority(0)]
public async Task ListCustReact(IUserMessage imsg, int page = 1) public async Task ListCustReact(int page = 1)
{ {
var channel = imsg.Channel as ITextChannel;
if (page < 1 || page > 1000) if (page < 1 || page > 1000)
return; return;
ConcurrentHashSet<CustomReaction> customReactions; ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null) if (Context.Guild == null)
customReactions = GlobalReactions; customReactions = GlobalReactions;
else else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()); customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
if (customReactions == null || !customReactions.Any()) if (customReactions == null || !customReactions.Any())
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
else else
await imsg.Channel.SendConfirmAsync( await Context.Channel.SendConfirmAsync(
$"Page {page} of custom reactions:", $"Page {page} of custom reactions:",
string.Join("\n", customReactions.OrderBy(cr => cr.Trigger) string.Join("\n", customReactions.OrderBy(cr => cr.Trigger)
.Skip((page - 1) * 20) .Skip((page - 1) * 20)
@ -156,18 +161,16 @@ namespace NadekoBot.Modules.CustomReactions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(1)] [Priority(1)]
public async Task ListCustReact(IUserMessage imsg, All x) public async Task ListCustReact(All x)
{ {
var channel = imsg.Channel as ITextChannel;
ConcurrentHashSet<CustomReaction> customReactions; ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null) if (Context.Guild == null)
customReactions = GlobalReactions; customReactions = GlobalReactions;
else else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()); customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
if (customReactions == null || !customReactions.Any()) if (customReactions == null || !customReactions.Any())
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
else else
{ {
var txtStream = await customReactions.GroupBy(cr => cr.Trigger) var txtStream = await customReactions.GroupBy(cr => cr.Trigger)
@ -176,29 +179,28 @@ namespace NadekoBot.Modules.CustomReactions
.ToJson() .ToJson()
.ToStream() .ToStream()
.ConfigureAwait(false); .ConfigureAwait(false);
if (channel == null) // its a private one, just send back if (Context.Guild == null) // its a private one, just send back
await imsg.Channel.SendFileAsync(txtStream, "customreactions.txt", "List of all custom reactions").ConfigureAwait(false); await Context.Channel.SendFileAsync(txtStream, "customreactions.txt", "List of all custom reactions").ConfigureAwait(false);
else else
await ((IGuildUser)imsg.Author).SendFileAsync(txtStream, "customreactions.txt", "List of all custom reactions").ConfigureAwait(false); await ((IGuildUser)Context.User).SendFileAsync(txtStream, "customreactions.txt", "List of all custom reactions").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task ListCustReactG(IUserMessage imsg, int page = 1) public async Task ListCustReactG(int page = 1)
{ {
var channel = imsg.Channel as ITextChannel;
if (page < 1 || page > 10000) if (page < 1 || page > 10000)
return; return;
ConcurrentHashSet<CustomReaction> customReactions; ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null) if (Context.Guild == null)
customReactions = GlobalReactions; customReactions = GlobalReactions;
else else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()); customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
if (customReactions == null || !customReactions.Any()) if (customReactions == null || !customReactions.Any())
await imsg.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No custom reactions found").ConfigureAwait(false);
else else
await imsg.Channel.SendConfirmAsync($"Page {page} of custom reactions (grouped):", await Context.Channel.SendConfirmAsync($"Page {page} of custom reactions (grouped):",
string.Join("\r\n", customReactions string.Join("\r\n", customReactions
.GroupBy(cr => cr.Trigger) .GroupBy(cr => cr.Trigger)
.OrderBy(cr => cr.Key) .OrderBy(cr => cr.Key)
@ -209,38 +211,34 @@ namespace NadekoBot.Modules.CustomReactions
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task ShowCustReact(IUserMessage imsg, int id) public async Task ShowCustReact(int id)
{ {
var channel = imsg.Channel as ITextChannel;
ConcurrentHashSet<CustomReaction> customReactions; ConcurrentHashSet<CustomReaction> customReactions;
if (channel == null) if (Context.Guild == null)
customReactions = GlobalReactions; customReactions = GlobalReactions;
else else
customReactions = GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()); customReactions = GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>());
var found = customReactions.FirstOrDefault(cr => cr.Id == id); var found = customReactions.FirstOrDefault(cr => cr.Id == id);
if (found == null) if (found == null)
await imsg.Channel.SendErrorAsync("No custom reaction found with that id.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No custom reaction found with that id.").ConfigureAwait(false);
else else
{ {
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription($"#{id}") .WithDescription($"#{id}")
.AddField(efb => efb.WithName("Trigger").WithValue(found.Trigger)) .AddField(efb => efb.WithName("Trigger").WithValue(found.Trigger))
.AddField(efb => efb.WithName("Response").WithValue(found.Response + "\n```css\n" + found.Response + "```")) .AddField(efb => efb.WithName("Response").WithValue(found.Response + "\n```css\n" + found.Response + "```"))
.Build()).ConfigureAwait(false); ).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task DelCustReact(IUserMessage imsg, int id) public async Task DelCustReact(int id)
{ {
var channel = imsg.Channel as ITextChannel; if ((Context.Guild == null && !NadekoBot.Credentials.IsOwner(Context.User)) || (Context.Guild != null && !((IGuildUser)Context.User).GuildPermissions.Administrator))
if ((channel == null && !NadekoBot.Credentials.IsOwner(imsg.Author)) || (channel != null && !((IGuildUser)imsg.Author).GuildPermissions.Administrator))
{ {
try { await imsg.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { } try { await Context.Channel.SendErrorAsync("Insufficient permissions. Requires Bot ownership for global custom reactions, and Administrator for guild custom reactions."); } catch { }
return; return;
} }
@ -252,16 +250,16 @@ namespace NadekoBot.Modules.CustomReactions
if (toDelete == null) //not found if (toDelete == null) //not found
return; return;
if ((toDelete.GuildId == null || toDelete.GuildId == 0) && channel == null) if ((toDelete.GuildId == null || toDelete.GuildId == 0) && Context.Guild == null)
{ {
uow.CustomReactions.Remove(toDelete); uow.CustomReactions.Remove(toDelete);
GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id); GlobalReactions.RemoveWhere(cr => cr.Id == toDelete.Id);
success = true; success = true;
} }
else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && channel?.Guild.Id == toDelete.GuildId) else if ((toDelete.GuildId != null && toDelete.GuildId != 0) && Context.Guild.Id == toDelete.GuildId)
{ {
uow.CustomReactions.Remove(toDelete); uow.CustomReactions.Remove(toDelete);
GuildReactions.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr => cr.Id == toDelete.Id); GuildReactions.GetOrAdd(Context.Guild.Id, new ConcurrentHashSet<CustomReaction>()).RemoveWhere(cr => cr.Id == toDelete.Id);
success = true; success = true;
} }
if (success) if (success)
@ -269,44 +267,45 @@ namespace NadekoBot.Modules.CustomReactions
} }
if (success) if (success)
await imsg.Channel.SendConfirmAsync("Deleted custom reaction", toDelete.ToString()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Deleted custom reaction", toDelete.ToString()).ConfigureAwait(false);
else else
await imsg.Channel.SendErrorAsync("Failed to find that custom reaction.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed to find that custom reaction.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task CrStatsClear(IUserMessage imsg, string trigger = null) [OwnerOnly]
public async Task CrStatsClear(string trigger = null)
{ {
if (string.IsNullOrWhiteSpace(trigger)) if (string.IsNullOrWhiteSpace(trigger))
{ {
ClearStats(); ClearStats();
await imsg.Channel.SendConfirmAsync($"Custom reaction stats cleared.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Custom reaction stats cleared.").ConfigureAwait(false);
} }
else else
{ {
uint throwaway; uint throwaway;
if (ReactionStats.TryRemove(trigger, out throwaway)) if (ReactionStats.TryRemove(trigger, out throwaway))
{ {
await imsg.Channel.SendConfirmAsync($"Stats cleared for `{trigger}` custom reaction.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Stats cleared for `{trigger}` custom reaction.").ConfigureAwait(false);
} }
else else
{ {
await imsg.Channel.SendErrorAsync("No stats for that trigger found, no action taken.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No stats for that trigger found, no action taken.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task CrStats(IUserMessage imsg, int page = 1) public async Task CrStats(int page = 1)
{ {
if (page < 1) if (page < 1)
return; return;
await imsg.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value) await Context.Channel.EmbedAsync(ReactionStats.OrderByDescending(x => x.Value)
.Skip((page - 1) * 9) .Skip((page - 1) * 9)
.Take(9) .Take(9)
.Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"), .Aggregate(new EmbedBuilder().WithOkColor().WithTitle($"Custom Reaction stats page #{page}"),
(agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true))) (agg, cur) => agg.AddField(efb => efb.WithName(cur.Key).WithValue(cur.Value.ToString()).WithIsInline(true)))
.Build()) )
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }

View File

@ -18,7 +18,7 @@ namespace NadekoBot.Modules.CustomReactions
public static Dictionary<string, Func<IUserMessage, string>> placeholders = new Dictionary<string, Func<IUserMessage, string>>() public static Dictionary<string, Func<IUserMessage, string>> placeholders = new Dictionary<string, Func<IUserMessage, string>>()
{ {
{"%mention%", (ctx) => { return $"<@{NadekoBot.Client.GetCurrentUser().Id}>"; } }, {"%mention%", (ctx) => { return $"<@{NadekoBot.Client.CurrentUser().Id}>"; } },
{"%user%", (ctx) => { return ctx.Author.Mention; } }, {"%user%", (ctx) => { return ctx.Author.Mention; } },
{"%rnduser%", (ctx) => { {"%rnduser%", (ctx) => {
var ch = ctx.Channel as ITextChannel; var ch = ctx.Channel as ITextChannel;

View File

@ -1,10 +1,9 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Services;
using NLog; using NLog;
namespace NadekoBot.Modules namespace NadekoBot.Modules
{ {
public class DiscordModule public abstract class DiscordModule : ModuleBase
{ {
protected Logger _log { get; } protected Logger _log { get; }
protected string _prefix { get; } protected string _prefix { get; }

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -16,39 +17,36 @@ namespace NadekoBot.Modules.Gambling
public partial class Gambling public partial class Gambling
{ {
[Group] [Group]
public class AnimalRacing public class AnimalRacing : ModuleBase
{ {
public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>(); public static ConcurrentDictionary<ulong, AnimalRace> AnimalRaces { get; } = new ConcurrentDictionary<ulong, AnimalRace>();
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Race(IUserMessage umsg) public async Task Race()
{ {
var channel = (ITextChannel)umsg.Channel; var ar = new AnimalRace(Context.Guild.Id, (ITextChannel)Context.Channel);
var ar = new AnimalRace(channel.Guild.Id, channel);
if (ar.Fail) if (ar.Fail)
await channel.SendErrorAsync("Animal Race", "Failed starting. Another race is probably running.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🏁 `Failed starting a race. Another race is probably running.`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task JoinRace(IUserMessage umsg, int amount = 0) public async Task JoinRace(int amount = 0)
{ {
var channel = (ITextChannel)umsg.Channel;
if (amount < 0) if (amount < 0)
amount = 0; amount = 0;
AnimalRace ar; AnimalRace ar;
if (!AnimalRaces.TryGetValue(channel.Guild.Id, out ar)) if (!AnimalRaces.TryGetValue(Context.Guild.Id, out ar))
{ {
await channel.SendErrorAsync("No race exists on this server").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No race exists on this server").ConfigureAwait(false);
return; return;
} }
await ar.JoinRace(umsg.Author as IGuildUser, amount); await ar.JoinRace(Context.User as IGuildUser, amount);
} }
public class AnimalRace public class AnimalRace
@ -209,9 +207,9 @@ namespace NadekoBot.Modules.Gambling
} }
private void Client_MessageReceived(IMessage imsg) private void Client_MessageReceived(SocketMessage imsg)
{ {
var msg = imsg as IUserMessage; var msg = imsg as SocketUserMessage;
if (msg == null) if (msg == null)
return; return;
if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel) if (msg.IsAuthor() || !(imsg.Channel is ITextChannel) || imsg.Channel != raceChannel)

View File

@ -10,13 +10,14 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using Image = ImageSharp.Image;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
public partial class Gambling public partial class Gambling
{ {
[Group] [Group]
public class DriceRollCommands public class DriceRollCommands : ModuleBase
{ {
private Regex dndRegex { get; } = new Regex(@"^(?<n1>\d+)d(?<n2>\d+)(?:\+(?<add>\d+))?(?:\-(?<sub>\d+))?$", RegexOptions.Compiled); private Regex dndRegex { get; } = new Regex(@"^(?<n1>\d+)d(?<n2>\d+)(?:\+(?<add>\d+))?(?:\-(?<sub>\d+))?$", RegexOptions.Compiled);
private Regex fudgeRegex { get; } = new Regex(@"^(?<n1>\d+)d(?:F|f)$", RegexOptions.Compiled); private Regex fudgeRegex { get; } = new Regex(@"^(?<n1>\d+)d(?:F|f)$", RegexOptions.Compiled);
@ -24,12 +25,8 @@ namespace NadekoBot.Modules.Gambling
private readonly char[] fateRolls = new[] { '-', ' ', '+' }; private readonly char[] fateRolls = new[] { '-', ' ', '+' };
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Roll()
public async Task Roll(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
if (channel == null)
return;
var rng = new NadekoRandom(); var rng = new NadekoRandom();
var gen = rng.Next(1, 101); var gen = rng.Next(1, 101);
@ -47,7 +44,7 @@ namespace NadekoBot.Modules.Gambling
catch { return new MemoryStream(); } catch { return new MemoryStream(); }
}); });
await channel.SendFileAsync(imageStream, "dice.png", $"{umsg.Author.Mention} rolled " + Format.Code(gen.ToString())).ConfigureAwait(false); await Context.Channel.SendFileAsync(imageStream, "dice.png", $"{Context.User.Mention} rolled " + Format.Code(gen.ToString())).ConfigureAwait(false);
} }
public enum RollOrderType public enum RollOrderType
@ -57,47 +54,39 @@ namespace NadekoBot.Modules.Gambling
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(0)] [Priority(0)]
public async Task Roll(IUserMessage umsg, int num) public async Task Roll(int num)
{ {
await InternalRoll(umsg, num, true).ConfigureAwait(false); await InternalRoll(num, true).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(0)] [Priority(0)]
public async Task Rolluo(IUserMessage umsg, int num) public async Task Rolluo(int num)
{ {
await InternalRoll(umsg, num, false).ConfigureAwait(false); await InternalRoll(num, false).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public async Task Roll(IUserMessage umsg, string arg) public async Task Roll(string arg)
{ {
await InternallDndRoll(umsg, arg, true).ConfigureAwait(false); await InternallDndRoll(arg, true).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public async Task Rolluo(IUserMessage umsg, string arg) public async Task Rolluo(string arg)
{ {
await InternallDndRoll(umsg, arg, false).ConfigureAwait(false); await InternallDndRoll(arg, false).ConfigureAwait(false);
} }
private async Task InternalRoll(IUserMessage umsg, int num, bool ordered) private async Task InternalRoll( int num, bool ordered)
{ {
var channel = (ITextChannel)umsg.Channel;
if (channel == null)
return;
if (num < 1 || num > 30) if (num < 1 || num > 30)
{ {
await channel.SendErrorAsync("Invalid number specified. You can roll up to 1-30 dice at a time.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Invalid number specified. You can roll up to 1-30 dice at a time.").ConfigureAwait(false);
return; return;
} }
@ -135,15 +124,11 @@ namespace NadekoBot.Modules.Gambling
var ms = new MemoryStream(); var ms = new MemoryStream();
bitmap.SaveAsPng(ms); bitmap.SaveAsPng(ms);
ms.Position = 0; ms.Position = 0;
await channel.SendFileAsync(ms, "dice.png", $"{umsg.Author.Mention} rolled {values.Count} {(values.Count == 1 ? "die" : "dice")}. Total: **{values.Sum()}** Average: **{(values.Sum() / (1.0f * values.Count)).ToString("N2")}**").ConfigureAwait(false); await Context.Channel.SendFileAsync(ms, "dice.png", $"{Context.User.Mention} rolled {values.Count} {(values.Count == 1 ? "die" : "dice")}. Total: **{values.Sum()}** Average: **{(values.Sum() / (1.0f * values.Count)).ToString("N2")}**").ConfigureAwait(false);
} }
private async Task InternallDndRoll(IUserMessage umsg, string arg, bool ordered) private async Task InternallDndRoll(string arg, bool ordered)
{ {
var channel = (ITextChannel)umsg.Channel;
if (channel == null)
return;
Match match; Match match;
int n1; int n1;
int n2; int n2;
@ -159,10 +144,10 @@ namespace NadekoBot.Modules.Gambling
{ {
rolls.Add(fateRolls[rng.Next(0, fateRolls.Length)]); rolls.Add(fateRolls[rng.Next(0, fateRolls.Length)]);
} }
var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} fate {(n1 == 1 ? "die" : "dice")}.") var embed = new EmbedBuilder().WithOkColor().WithDescription($"{Context.User.Mention} rolled {n1} fate {(n1 == 1 ? "die" : "dice")}.")
.AddField(efb => efb.WithName(Format.Bold("Result")) .AddField(efb => efb.WithName(Format.Bold("Result"))
.WithValue(string.Join(" ", rolls.Select(c => Format.Code($"[{c}]"))))); .WithValue(string.Join(" ", rolls.Select(c => Format.Code($"[{c}]")))));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
else if ((match = dndRegex.Match(arg)).Length != 0) else if ((match = dndRegex.Match(arg)).Length != 0)
{ {
@ -182,20 +167,17 @@ namespace NadekoBot.Modules.Gambling
arr[i] = rng.Next(1, n2 + 1) + add - sub; arr[i] = rng.Next(1, n2 + 1) + add - sub;
} }
var embed = new EmbedBuilder().WithOkColor().WithDescription($"{umsg.Author.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`") var embed = new EmbedBuilder().WithOkColor().WithDescription($"{Context.User.Mention} rolled {n1} {(n1 == 1 ? "die" : "dice")} `1 to {n2}` +`{add}` -`{sub}`")
.AddField(efb => efb.WithName(Format.Bold("Result")) .AddField(efb => efb.WithName(Format.Bold("Result"))
.WithValue(string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString()))))); .WithValue(string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString())))));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task NRoll([Remainder] string range)
public async Task NRoll(IUserMessage umsg, [Remainder] string range)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
int rolled; int rolled;
@ -214,11 +196,11 @@ namespace NadekoBot.Modules.Gambling
rolled = new NadekoRandom().Next(0, int.Parse(range) + 1); rolled = new NadekoRandom().Next(0, int.Parse(range) + 1);
} }
await channel.SendConfirmAsync($"{umsg.Author.Mention} rolled **{rolled}**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} rolled **{rolled}**.").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($":anger: {ex.Message}").ConfigureAwait(false); await Context.Channel.SendErrorAsync($":anger: {ex.Message}").ConfigureAwait(false);
} }
} }

View File

@ -10,31 +10,24 @@ using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Image = ImageSharp.Image;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
public partial class Gambling public partial class Gambling
{ {
[Group] [Group]
public class DrawCommands public class DrawCommands : ModuleBase
{ {
private static readonly ConcurrentDictionary<IGuild, Cards> AllDecks = new ConcurrentDictionary<IGuild, Cards>(); private static readonly ConcurrentDictionary<IGuild, Cards> AllDecks = new ConcurrentDictionary<IGuild, Cards>();
public DrawCommands()
{
_log = LogManager.GetCurrentClassLogger();
}
private const string cardsPath = "data/images/cards"; private const string cardsPath = "data/images/cards";
private Logger _log { get; }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Draw(IUserMessage msg, int num = 1) public async Task Draw(int num = 1)
{ {
var channel = (ITextChannel)msg.Channel; var cards = AllDecks.GetOrAdd(Context.Guild, (s) => new Cards());
var cards = AllDecks.GetOrAdd(channel.Guild, (s) => new Cards());
var images = new List<Image>(); var images = new List<Image>();
var cardObjects = new List<Cards.Card>(); var cardObjects = new List<Cards.Card>();
if (num > 5) num = 5; if (num > 5) num = 5;
@ -42,7 +35,7 @@ namespace NadekoBot.Modules.Gambling
{ {
if (cards.CardPool.Count == 0 && i != 0) if (cards.CardPool.Count == 0 && i != 0)
{ {
try { await channel.SendErrorAsync("No more cards in a deck.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } try { await Context.Channel.SendErrorAsync("No more cards in a deck.").ConfigureAwait(false); } catch { }
break; break;
} }
var currentCard = cards.DrawACard(); var currentCard = cards.DrawACard();
@ -53,21 +46,20 @@ namespace NadekoBot.Modules.Gambling
MemoryStream bitmapStream = new MemoryStream(); MemoryStream bitmapStream = new MemoryStream();
images.Merge().SaveAsPng(bitmapStream); images.Merge().SaveAsPng(bitmapStream);
bitmapStream.Position = 0; bitmapStream.Position = 0;
var toSend = $"{Context.User.Mention}";
var toSend = $"{msg.Author.Mention}";
if (cardObjects.Count == 5) if (cardObjects.Count == 5)
toSend += $" drew `{Cards.GetHandValue(cardObjects)}`"; toSend += $" drew `{Cards.GetHandValue(cardObjects)}`";
await channel.SendFileAsync(bitmapStream, images.Count + " cards.jpg", toSend).ConfigureAwait(false); await Context.Channel.SendFileAsync(bitmapStream, images.Count + " cards.jpg", toSend).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ShuffleDeck(IUserMessage imsg) public async Task ShuffleDeck()
{ {
var channel = (ITextChannel)imsg.Channel; //var channel = (ITextChannel)Context.Channel;
AllDecks.AddOrUpdate(channel.Guild, AllDecks.AddOrUpdate(Context.Guild,
(g) => new Cards(), (g) => new Cards(),
(g, c) => (g, c) =>
{ {
@ -75,7 +67,7 @@ namespace NadekoBot.Modules.Gambling
return c; return c;
}); });
await channel.SendConfirmAsync("Deck reshuffled.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Deck reshuffled.").ConfigureAwait(false);
} }
} }
} }

View File

@ -7,34 +7,33 @@ using NadekoBot.Services;
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using Image = ImageSharp.Image;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
public partial class Gambling public partial class Gambling
{ {
[Group] [Group]
public class FlipCoinCommands public class FlipCoinCommands : ModuleBase
{ {
private static NadekoRandom rng { get; } = new NadekoRandom(); private static NadekoRandom rng { get; } = new NadekoRandom();
private const string headsPath = "data/images/coins/heads.png"; private const string headsPath = "data/images/coins/heads.png";
private const string tailsPath = "data/images/coins/tails.png"; private const string tailsPath = "data/images/coins/tails.png";
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Flip(int count = 1)
public async Task Flip(IUserMessage imsg, int count = 1)
{ {
var channel = (ITextChannel)imsg.Channel;
if (count == 1) if (count == 1)
{ {
if (rng.Next(0, 2) == 1) if (rng.Next(0, 2) == 1)
await channel.SendFileAsync(headsPath, $"{imsg.Author.Mention} flipped " + Format.Code("Heads") + ".").ConfigureAwait(false); await Context.Channel.SendFileAsync(headsPath, $"{Context.User.Mention} flipped " + Format.Code("Heads") + ".").ConfigureAwait(false);
else else
await channel.SendFileAsync(tailsPath, $"{imsg.Author.Mention} flipped " + Format.Code("Tails") + ".").ConfigureAwait(false); await Context.Channel.SendFileAsync(tailsPath, $"{Context.User.Mention} flipped " + Format.Code("Tails") + ".").ConfigureAwait(false);
return; return;
} }
if (count > 10 || count < 1) if (count > 10 || count < 1)
{ {
await channel.SendErrorAsync("`Invalid number specified. You can flip 1 to 10 coins.`"); await Context.Channel.SendErrorAsync("`Invalid number specified. You can flip 1 to 10 coins.`");
return; return;
} }
var imgs = new Image[count]; var imgs = new Image[count];
@ -44,29 +43,26 @@ namespace NadekoBot.Modules.Gambling
new Image(File.OpenRead(headsPath)) : new Image(File.OpenRead(headsPath)) :
new Image(File.OpenRead(tailsPath)); new Image(File.OpenRead(tailsPath));
} }
await channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false); await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Betflip(int amount, string guess)
public async Task Betflip(IUserMessage umsg, int amount, string guess)
{ {
var channel = (ITextChannel)umsg.Channel;
var guildUser = (IGuildUser)umsg.Author;
var guessStr = guess.Trim().ToUpperInvariant(); var guessStr = guess.Trim().ToUpperInvariant();
if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS") if (guessStr != "H" && guessStr != "T" && guessStr != "HEADS" && guessStr != "TAILS")
return; return;
if (amount < 3) if (amount < 3)
{ {
await channel.SendErrorAsync($"You can't bet less than 3{Gambling.CurrencySign}.") await Context.Channel.SendErrorAsync($"You can't bet less than 3{Gambling.CurrencySign}.")
.ConfigureAwait(false); .ConfigureAwait(false);
return; return;
} }
var removed = await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betflip Gamble", amount, false).ConfigureAwait(false); var removed = await CurrencyHandler.RemoveCurrencyAsync(Context.User, "Betflip Gamble", amount, false).ConfigureAwait(false);
if (!removed) if (!removed)
{ {
await channel.SendErrorAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"{Context.User.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false);
return; return;
} }
//heads = true //heads = true
@ -89,15 +85,15 @@ namespace NadekoBot.Modules.Gambling
if (isHeads == result) if (isHeads == result)
{ {
var toWin = (int)Math.Round(amount * 1.8); var toWin = (int)Math.Round(amount * 1.8);
str = $"{umsg.Author.Mention}`You guessed it!` You won {toWin}{Gambling.CurrencySign}"; str = $"{Context.User.Mention}`You guessed it!` You won {toWin}{Gambling.CurrencySign}";
await CurrencyHandler.AddCurrencyAsync((IGuildUser)umsg.Author, "Betflip Gamble", toWin, false).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(Context.User, "Betflip Gamble", toWin, false).ConfigureAwait(false);
} }
else else
{ {
str = $"{umsg.Author.Mention}`Better luck next time.`"; str = $"{Context.User.Mention}`Better luck next time.`";
} }
await channel.SendFileAsync(imgPathToSend, str).ConfigureAwait(false); await Context.Channel.SendFileAsync(imgPathToSend, str).ConfigureAwait(false);
} }
} }
} }

View File

@ -6,10 +6,8 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services; using NadekoBot.Services;
using Discord.WebSocket;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Generic; using System.Collections.Generic;
using NadekoBot.Services.Database;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
@ -20,7 +18,7 @@ namespace NadekoBot.Modules.Gambling
public static string CurrencyPluralName { get; set; } public static string CurrencyPluralName { get; set; }
public static string CurrencySign { get; set; } public static string CurrencySign { get; set; }
public Gambling() : base() static Gambling()
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -42,94 +40,84 @@ namespace NadekoBot.Modules.Gambling
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Raffle(IUserMessage umsg, [Remainder] IRole role = null) public async Task Raffle([Remainder] IRole role = null)
{ {
var channel = (ITextChannel)umsg.Channel; role = role ?? Context.Guild.EveryoneRole;
role = role ?? channel.Guild.EveryoneRole;
var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown); var members = role.Members().Where(u => u.Status != UserStatus.Offline && u.Status != UserStatus.Unknown);
var membersArray = members as IUser[] ?? members.ToArray(); var membersArray = members as IUser[] ?? members.ToArray();
var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)]; var usr = membersArray[new NadekoRandom().Next(0, membersArray.Length)];
await channel.SendConfirmAsync("🎟 Raffled user", $"**{usr.Username}#{usr.Discriminator}** ID: `{usr.Id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🎟 Raffled user", $"**{usr.Username}#{usr.Discriminator}** ID: `{usr.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(0)] [Priority(0)]
public async Task Cash(IUserMessage umsg, [Remainder] IUser user = null) public async Task Cash([Remainder] IUser user = null)
{ {
var channel = umsg.Channel; user = user ?? Context.User;
user = user ?? umsg.Author; await Context.Channel.SendConfirmAsync($"{user.Username} has {GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false);
await channel.SendConfirmAsync($"{user.Username} has {GetCurrency(user.Id)} {CurrencySign}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[Priority(1)] [Priority(1)]
public async Task Cash(IUserMessage umsg, ulong userId) public async Task Cash(ulong userId)
{ {
var channel = umsg.Channel; await Context.Channel.SendConfirmAsync($"`{userId}` has {GetCurrency(userId)} {CurrencySign}").ConfigureAwait(false);
await channel.SendConfirmAsync($"`{userId}` has {GetCurrency(userId)} {CurrencySign}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Give(IUserMessage umsg, long amount, [Remainder] IGuildUser receiver) public async Task Give(long amount, [Remainder] IGuildUser receiver)
{ {
var channel = (ITextChannel)umsg.Channel; if (amount <= 0 || Context.User.Id == receiver.Id)
if (amount <= 0 || umsg.Author.Id == receiver.Id)
return; return;
var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)umsg.Author, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false); var success = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)Context.User, $"Gift to {receiver.Username} ({receiver.Id}).", amount, true).ConfigureAwait(false);
if (!success) if (!success)
{ {
await channel.SendErrorAsync($"{umsg.Author.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"{Context.User.Mention} You don't have enough {Gambling.CurrencyPluralName}.").ConfigureAwait(false);
return; return;
} }
await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {umsg.Author.Username} ({umsg.Author.Id}).", amount, true).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(receiver, $"Gift from {Context.User.Username} ({Context.User.Id}).", amount, true).ConfigureAwait(false);
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} successfully sent {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to {receiver.Mention}!").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
[Priority(2)] [Priority(2)]
public Task Award(IUserMessage umsg, int amount, [Remainder] IGuildUser usr) => public Task Award(int amount, [Remainder] IGuildUser usr) =>
Award(umsg, amount, usr.Id); Award(amount, usr.Id);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
[Priority(1)] [Priority(1)]
public async Task Award(IUserMessage umsg, int amount, ulong usrId) public async Task Award(int amount, ulong usrId)
{ {
var channel = (ITextChannel)umsg.Channel;
if (amount <= 0) if (amount <= 0)
return; return;
await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(usrId, $"Awarded by bot owner. ({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false);
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} successfully awarded {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} to <@{usrId}>!").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
[Priority(0)] [Priority(0)]
public async Task Award(IUserMessage umsg, int amount, [Remainder] IRole role) public async Task Award(int amount, [Remainder] IRole role)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
var users = channel.Guild.GetUsers() var users = (await Context.Guild.GetUsersAsync())
.Where(u => u.Roles.Contains(role)) .Where(u => u.GetRoles().Contains(role))
.ToList(); .ToList();
await Task.WhenAll(users.Select(u => CurrencyHandler.AddCurrencyAsync(u.Id, await Task.WhenAll(users.Select(u => CurrencyHandler.AddCurrencyAsync(u.Id,
$"Awarded by bot owner to **{role.Name}** role. ({umsg.Author.Username}/{umsg.Author.Id})", $"Awarded by bot owner to **{role.Name}** role. ({Context.User.Username}/{Context.User.Id})",
amount))) amount)))
.ConfigureAwait(false); .ConfigureAwait(false);
await channel.SendConfirmAsync($"Awarded `{amount}` {Gambling.CurrencyPluralName} to `{users.Count}` users from `{role.Name}` role.") await Context.Channel.SendConfirmAsync($"Awarded `{amount}` {Gambling.CurrencyPluralName} to `{users.Count}` users from `{role.Name}` role.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -137,61 +125,53 @@ namespace NadekoBot.Modules.Gambling
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Take(IUserMessage umsg, long amount, [Remainder] IGuildUser user) public async Task Take(long amount, [Remainder] IGuildUser user)
{ {
var channel = (ITextChannel)umsg.Channel;
if (amount <= 0) if (amount <= 0)
return; return;
if(await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount, true).ConfigureAwait(false)) if (await CurrencyHandler.RemoveCurrencyAsync(user, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount, true).ConfigureAwait(false))
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user}!").ConfigureAwait(false);
else else
await channel.SendErrorAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"{Context.User.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from {user} because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Take(IUserMessage umsg, long amount, [Remainder] ulong usrId) public async Task Take(long amount, [Remainder] ulong usrId)
{ {
var channel = (ITextChannel)umsg.Channel;
if (amount <= 0) if (amount <= 0)
return; return;
if(await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({umsg.Author.Username}/{umsg.Author.Id})", amount).ConfigureAwait(false)) if (await CurrencyHandler.RemoveCurrencyAsync(usrId, $"Taken by bot owner.({Context.User.Username}/{Context.User.Id})", amount).ConfigureAwait(false))
await channel.SendConfirmAsync($"{umsg.Author.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} successfully took {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from <@{usrId}>!").ConfigureAwait(false);
else else
await channel.SendErrorAsync($"{umsg.Author.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"{Context.User.Mention} was unable to take {amount} {(amount == 1 ? Gambling.CurrencyName : Gambling.CurrencyPluralName)} from `{usrId}` because the user doesn't have that much {Gambling.CurrencyPluralName}!").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task BetRoll(long amount)
public async Task BetRoll(IUserMessage umsg, long amount)
{ {
var channel = (ITextChannel)umsg.Channel;
if (amount < 1) if (amount < 1)
return; return;
var guildUser = (IGuildUser)umsg.Author;
long userFlowers; long userFlowers;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
userFlowers = uow.Currency.GetOrCreate(umsg.Author.Id).Amount; userFlowers = uow.Currency.GetOrCreate(Context.User.Id).Amount;
} }
if (userFlowers < amount) if (userFlowers < amount)
{ {
await channel.SendErrorAsync($"{guildUser.Mention} You don't have enough {Gambling.CurrencyPluralName}. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"{Context.User.Mention} You don't have enough {Gambling.CurrencyPluralName}. You only have {userFlowers}{Gambling.CurrencySign}.").ConfigureAwait(false);
return; return;
} }
await CurrencyHandler.RemoveCurrencyAsync(guildUser, "Betroll Gamble", amount, false).ConfigureAwait(false); await CurrencyHandler.RemoveCurrencyAsync(Context.User, "Betroll Gamble", amount, false).ConfigureAwait(false);
var rng = new NadekoRandom().Next(0, 101); var rng = new NadekoRandom().Next(0, 101);
var str = $"{guildUser.Mention} `You rolled {rng}.` "; var str = $"{Context.User.Mention} `You rolled {rng}.` ";
if (rng < 67) if (rng < 67)
{ {
str += "Better luck next time."; str += "Better luck next time.";
@ -199,28 +179,25 @@ namespace NadekoBot.Modules.Gambling
else if (rng < 91) else if (rng < 91)
{ {
str += $"Congratulations! You won {amount * 2}{Gambling.CurrencySign} for rolling above 66"; str += $"Congratulations! You won {amount * 2}{Gambling.CurrencySign} for rolling above 66";
await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 2, false).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(Context.User, "Betroll Gamble", amount * 2, false).ConfigureAwait(false);
} }
else if (rng < 100) else if (rng < 100)
{ {
str += $"Congratulations! You won {amount * 3}{Gambling.CurrencySign} for rolling above 90."; str += $"Congratulations! You won {amount * 3}{Gambling.CurrencySign} for rolling above 90.";
await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 3, false).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(Context.User, "Betroll Gamble", amount * 3, false).ConfigureAwait(false);
} }
else else
{ {
str += $"👑 Congratulations! You won {amount * 10}{Gambling.CurrencySign} for rolling **100**. 👑"; str += $"👑 Congratulations! You won {amount * 10}{Gambling.CurrencySign} for rolling **100**. 👑";
await CurrencyHandler.AddCurrencyAsync(guildUser, "Betroll Gamble", amount * 10, false).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync(Context.User, "Betroll Gamble", amount * 10, false).ConfigureAwait(false);
} }
await channel.SendConfirmAsync(str).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(str).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Leaderboard()
public async Task Leaderboard(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
IEnumerable<Currency> richest = new List<Currency>(); IEnumerable<Currency> richest = new List<Currency>();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -228,14 +205,14 @@ namespace NadekoBot.Modules.Gambling
} }
if (!richest.Any()) if (!richest.Any())
return; return;
await channel.SendMessageAsync( await Context.Channel.SendMessageAsync(
richest.Aggregate(new StringBuilder( richest.Aggregate(new StringBuilder(
$@"```xl $@"```xl
Id $$$ Id $$$
"), "),
(cur, cs) => cur.AppendLine($@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━┫ (cur, cs) => cur.AppendLine($@"┣━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━┫
{(channel.Guild.GetUser(cs.UserId)?.Username?.TrimTo(18, true) ?? cs.UserId.ToString()),-20} {cs.Amount,6} ") {(Context.Guild.GetUserAsync(cs.UserId).GetAwaiter().GetResult()?.Username?.TrimTo(18, true) ?? cs.UserId.ToString()),-20} {cs.Amount,6} ")
).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┛```").ConfigureAwait(false); ).ToString() + "┗━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━┛```").ConfigureAwait(false);
} }
} }

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -18,16 +19,16 @@ namespace NadekoBot.Modules.Games
public partial class Games public partial class Games
{ {
[Group] [Group]
public class Acropobia public class Acropobia : ModuleBase
{ {
//channelId, game //channelId, game
public static ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>(); public static ConcurrentDictionary<ulong, AcrophobiaGame> AcrophobiaGames { get; } = new ConcurrentDictionary<ulong, AcrophobiaGame>();
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Acro(IUserMessage imsg, int time = 60) public async Task Acro(int time = 60)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
var game = new AcrophobiaGame(channel, time); var game = new AcrophobiaGame(channel, time);
if (AcrophobiaGames.TryAdd(channel.Id, game)) if (AcrophobiaGames.TryAdd(channel.Id, game))
@ -123,7 +124,7 @@ namespace NadekoBot.Modules.Games
var embed = GetEmbed(); var embed = GetEmbed();
//SUBMISSIONS PHASE //SUBMISSIONS PHASE
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await channel.EmbedAsync(embed).ConfigureAwait(false);
try try
{ {
await Task.Delay(time * 1000, source.Token).ConfigureAwait(false); await Task.Delay(time * 1000, source.Token).ConfigureAwait(false);
@ -144,13 +145,13 @@ namespace NadekoBot.Modules.Games
{ {
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription($"{submissions.First().Value.Mention} is the winner for being the only user who made a submission!") .WithDescription($"{submissions.First().Value.Mention} is the winner for being the only user who made a submission!")
.WithFooter(efb => efb.WithText(submissions.First().Key.ToLowerInvariant().ToTitleCase())) .WithFooter(efb => efb.WithText(submissions.First().Key.ToLowerInvariant().ToTitleCase())))
.Build()).ConfigureAwait(false); .ConfigureAwait(false);
return; return;
} }
var submissionClosedEmbed = GetEmbed(); var submissionClosedEmbed = GetEmbed();
await channel.EmbedAsync(submissionClosedEmbed.Build()).ConfigureAwait(false); await channel.EmbedAsync(submissionClosedEmbed).ConfigureAwait(false);
//VOTING PHASE //VOTING PHASE
this.phase = AcroPhase.Voting; this.phase = AcroPhase.Voting;
@ -167,11 +168,11 @@ namespace NadekoBot.Modules.Games
await End().ConfigureAwait(false); await End().ConfigureAwait(false);
} }
private async void PotentialAcro(IMessage arg) private async void PotentialAcro(SocketMessage arg)
{ {
try try
{ {
var msg = arg as IUserMessage; var msg = arg as SocketUserMessage;
if (msg == null || msg.Author.IsBot || msg.Channel.Id != channel.Id) if (msg == null || msg.Author.IsBot || msg.Channel.Id != channel.Id)
return; return;
@ -186,7 +187,7 @@ namespace NadekoBot.Modules.Games
if (spamCount > 10) if (spamCount > 10)
{ {
spamCount = 0; spamCount = 0;
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); } try { await channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); }
catch { } catch { }
} }
//user didn't input something already //user didn't input something already
@ -226,7 +227,7 @@ namespace NadekoBot.Modules.Games
if (spamCount > 10) if (spamCount > 10)
{ {
spamCount = 0; spamCount = 0;
try { await channel.EmbedAsync(GetEmbed().Build()).ConfigureAwait(false); } try { await channel.EmbedAsync(GetEmbed()).ConfigureAwait(false); }
catch { } catch { }
} }
@ -277,7 +278,7 @@ namespace NadekoBot.Modules.Games
.WithDescription($"Winner is {submissions[winner.Key].Mention} with {winner.Value} points.\n") .WithDescription($"Winner is {submissions[winner.Key].Mention} with {winner.Value} points.\n")
.WithFooter(efb => efb.WithText(winner.Key.ToLowerInvariant().ToTitleCase())); .WithFooter(efb => efb.WithText(winner.Key.ToLowerInvariant().ToTitleCase()));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await channel.EmbedAsync(embed).ConfigureAwait(false);
} }
public void EnsureStopped() public void EnsureStopped()

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -7,6 +8,7 @@ using NLog;
using Services.CleverBotApi; using Services.CleverBotApi;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,43 +17,48 @@ namespace NadekoBot.Modules.Games
public partial class Games public partial class Games
{ {
[Group] [Group]
public class CleverBotCommands public class CleverBotCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
class CleverAnswer { class CleverAnswer
{
public string Status { get; set; } public string Status { get; set; }
public string Response { get; set; } public string Response { get; set; }
} }
//user#discrim is the key
public static ConcurrentHashSet<string> ChannelsInConversation { get; } = new ConcurrentHashSet<string>(); public static ConcurrentDictionary<ulong, Lazy<ChatterBotSession>> CleverbotGuilds { get; } = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>();
public static ConcurrentDictionary<ulong, ChatterBotSession> CleverbotGuilds { get; } = new ConcurrentDictionary<ulong, ChatterBotSession>();
static CleverBotCommands() static CleverBotCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT); var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
CleverbotGuilds = new ConcurrentDictionary<ulong, ChatterBotSession>( CleverbotGuilds = new ConcurrentDictionary<ulong, Lazy<ChatterBotSession>>(
NadekoBot.AllGuildConfigs NadekoBot.AllGuildConfigs
.Where(gc => gc.CleverbotEnabled) .Where(gc => gc.CleverbotEnabled)
.ToDictionary(gc => gc.GuildId, gc => bot.CreateSession())); .ToDictionary(gc => gc.GuildId, gc => new Lazy<ChatterBotSession>(() => bot.CreateSession(), true)));
} }
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
public static async Task<bool> TryAsk(IUserMessage msg) { public static async Task<bool> TryAsk(SocketUserMessage msg)
{
var channel = msg.Channel as ITextChannel; var channel = msg.Channel as ITextChannel;
if (channel == null) if (channel == null)
return false; return false;
ChatterBotSession cleverbot; Lazy<ChatterBotSession> cleverbot;
if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out cleverbot)) if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out cleverbot))
return false; return false;
var nadekoId = NadekoBot.Client.GetCurrentUser().Id; var nadekoId = NadekoBot.Client.CurrentUser().Id;
var normalMention = $"<@{nadekoId}> "; var normalMention = $"<@{nadekoId}> ";
var nickMention = $"<@!{nadekoId}> "; var nickMention = $"<@!{nadekoId}> ";
string message; string message;
@ -70,7 +77,7 @@ namespace NadekoBot.Modules.Games
await msg.Channel.TriggerTypingAsync().ConfigureAwait(false); await msg.Channel.TriggerTypingAsync().ConfigureAwait(false);
var response = await cleverbot.Think(message).ConfigureAwait(false); var response = await cleverbot.Value.Think(message).ConfigureAwait(false);
try try
{ {
await msg.Channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false); await msg.Channel.SendConfirmAsync(response.SanitizeMentions()).ConfigureAwait(false);
@ -84,35 +91,34 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(ChannelPermission.ManageMessages)] [RequireUserPermission(ChannelPermission.ManageMessages)]
public async Task Cleverbot(IUserMessage imsg) public async Task Cleverbot()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
ChatterBotSession throwaway; Lazy<ChatterBotSession> throwaway;
if (CleverbotGuilds.TryRemove(channel.Guild.Id, out throwaway)) if (CleverbotGuilds.TryRemove(channel.Guild.Id, out throwaway))
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, false); uow.GuildConfigs.SetCleverbotEnabled(Context.Guild.Id, false);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{imsg.Author.Mention} Disabled cleverbot on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} Disabled cleverbot on this server.").ConfigureAwait(false);
return; return;
} }
var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT); var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT);
var session = cleverbot.CreateSession();
CleverbotGuilds.TryAdd(channel.Guild.Id, session); CleverbotGuilds.TryAdd(channel.Guild.Id, new Lazy<ChatterBotSession>(() => cleverbot.CreateSession(), true));
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, true); uow.GuildConfigs.SetCleverbotEnabled(Context.Guild.Id, true);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{imsg.Author.Mention} Enabled cleverbot on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention} Enabled cleverbot on this server.").ConfigureAwait(false);
} }
} }
} }

View File

@ -1,4 +1,5 @@
using Discord; using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
using Newtonsoft.Json; using Newtonsoft.Json;
@ -7,7 +8,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Games.Commands.Hangman namespace NadekoBot.Modules.Games.Commands.Hangman
@ -121,19 +121,19 @@ namespace NadekoBot.Modules.Games.Commands.Hangman
var embed = new EmbedBuilder().WithTitle("Hangman Game") var embed = new EmbedBuilder().WithTitle("Hangman Game")
.WithDescription(toSend) .WithDescription(toSend)
.AddField(efb => efb.WithName("It was").WithValue(Term.Word)) .AddField(efb => efb.WithName("It was").WithValue(Term.Word))
.WithImage(eib => eib.WithUrl(Term.ImageUrl)) .WithImageUrl(Term.ImageUrl)
.WithFooter(efb => efb.WithText(string.Join(" ", Guesses))); .WithFooter(efb => efb.WithText(string.Join(" ", Guesses)));
if (Errors >= MaxErrors) if (Errors >= MaxErrors)
await GameChannel.EmbedAsync(embed.WithErrorColor().Build()).ConfigureAwait(false); await GameChannel.EmbedAsync(embed.WithErrorColor()).ConfigureAwait(false);
else else
await GameChannel.EmbedAsync(embed.WithOkColor().Build()).ConfigureAwait(false); await GameChannel.EmbedAsync(embed.WithOkColor()).ConfigureAwait(false);
} }
private async void PotentialGuess(IMessage msg) private async void PotentialGuess(SocketMessage msg)
{ {
try try
{ {
if (!(msg is IUserMessage)) if (!(msg is SocketUserMessage))
return; return;
if (msg.Channel != GameChannel) if (msg.Channel != GameChannel)

View File

@ -1,10 +1,4 @@
using System; namespace NadekoBot.Modules.Games.Commands.Hangman
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Games.Commands.Hangman
{ {
public class HangmanObject public class HangmanObject
{ {

View File

@ -1,54 +1,45 @@
using Discord; using Discord.Commands;
using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Games.Commands.Hangman; using NadekoBot.Modules.Games.Commands.Hangman;
using NLog; using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Games namespace NadekoBot.Modules.Games
{ {
public partial class Games public partial class Games
{ {
[Group] [Group]
public class HangmanCommands public class HangmanCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
//channelId, game //channelId, game
public static ConcurrentDictionary<ulong, HangmanGame> HangmanGames { get; } = new ConcurrentDictionary<ulong, HangmanGame>(); public static ConcurrentDictionary<ulong, HangmanGame> HangmanGames { get; } = new ConcurrentDictionary<ulong, HangmanGame>();
private static string typesStr { get; } = "";
static HangmanCommands() static HangmanCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
}
string typesStr { get; } = "";
public HangmanCommands()
{
typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Games).Name]}hangman\" term types:`\n" + String.Join(", ", Enum.GetNames(typeof(HangmanTermPool.HangmanTermType))); typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Games).Name]}hangman\" term types:`\n" + String.Join(", ", Enum.GetNames(typeof(HangmanTermPool.HangmanTermType)));
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Hangmanlist(IUserMessage imsg) public async Task Hangmanlist()
{ {
await imsg.Channel.SendConfirmAsync(typesStr); await Context.Channel.SendConfirmAsync(typesStr);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Hangman(IUserMessage imsg, HangmanTermPool.HangmanTermType type = HangmanTermPool.HangmanTermType.All) public async Task Hangman(HangmanTermPool.HangmanTermType type = HangmanTermPool.HangmanTermType.All)
{ {
var hm = new HangmanGame(imsg.Channel, type); var hm = new HangmanGame(Context.Channel, type);
if (!HangmanGames.TryAdd(imsg.Channel.Id, hm)) if (!HangmanGames.TryAdd(Context.Channel.Id, hm))
{ {
await imsg.Channel.SendErrorAsync("Hangman game already running on this channel.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Hangman game already running on this channel.").ConfigureAwait(false);
return; return;
} }
@ -59,7 +50,7 @@ namespace NadekoBot.Modules.Games
}; };
hm.Start(); hm.Start();
await imsg.Channel.SendConfirmAsync("Hangman game started", hm.ScrambledWord + "\n" + hm.GetHangman() + "\n" + hm.ScrambledWord); await Context.Channel.SendConfirmAsync("Hangman game started", hm.ScrambledWord + "\n" + hm.GetHangman() + "\n" + hm.ScrambledWord);
} }
} }
} }

View File

@ -13,15 +13,12 @@ namespace NadekoBot.Modules.Games
public partial class Games public partial class Games
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Leet(int level, [Remainder] string text = null)
public async Task Leet(IUserMessage umsg, int level, [Remainder] string text = null)
{ {
var channel = (ITextChannel)umsg.Channel;
text = text.Trim(); text = text.Trim();
if (string.IsNullOrWhiteSpace(text)) if (string.IsNullOrWhiteSpace(text))
return; return;
await channel.SendConfirmAsync("L33t", ToLeet(text, level).SanitizeMentions()).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("L33t", ToLeet(text, level).SanitizeMentions()).ConfigureAwait(false);
} }

View File

@ -10,6 +10,7 @@ using NLog;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Security.Cryptography; using System.Security.Cryptography;
@ -27,7 +28,7 @@ namespace NadekoBot.Modules.Games
/// https://discord.gg/0TYNJfCU4De7YIk8 /// https://discord.gg/0TYNJfCU4De7YIk8
/// </summary> /// </summary>
[Group] [Group]
public class PlantPickCommands public class PlantPickCommands : ModuleBase
{ {
private static ConcurrentHashSet<ulong> generationChannels { get; } = new ConcurrentHashSet<ulong>(); private static ConcurrentHashSet<ulong> generationChannels { get; } = new ConcurrentHashSet<ulong>();
//channelid/message //channelid/message
@ -44,8 +45,10 @@ namespace NadekoBot.Modules.Games
static PlantPickCommands() static PlantPickCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
#if !GLOBAL_NADEKO
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration; NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
#endif
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var conf = uow.BotConfig.GetOrCreate(); var conf = uow.BotConfig.GetOrCreate();
@ -55,13 +58,16 @@ namespace NadekoBot.Modules.Games
chance = conf.CurrencyGenerationChance; chance = conf.CurrencyGenerationChance;
cooldown = conf.CurrencyGenerationCooldown; cooldown = conf.CurrencyGenerationCooldown;
} }
sw.Stop();
_log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
private static async void PotentialFlowerGeneration(IMessage imsg) private static async void PotentialFlowerGeneration(SocketMessage imsg)
{ {
try try
{ {
var msg = imsg as IUserMessage; var msg = imsg as SocketUserMessage;
if (msg == null || msg.IsAuthor() || msg.Author.IsBot) if (msg == null || msg.IsAuthor() || msg.Author.IsBot)
return; return;
@ -95,14 +101,14 @@ namespace NadekoBot.Modules.Games
} }
catch { } catch { }
} }
#if !GLOBAL_NADEKO
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Pick(IUserMessage imsg) public async Task Pick()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
if (!channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages || !usersRecentlyPicked.Add(imsg.Author.Id)) if (!(await channel.Guild.GetCurrentUserAsync()).GetPermissions(channel).ManageMessages || !usersRecentlyPicked.Add(Context.User.Id))
return; return;
try try
@ -110,33 +116,31 @@ namespace NadekoBot.Modules.Games
List<IUserMessage> msgs; List<IUserMessage> msgs;
try { await imsg.DeleteAsync().ConfigureAwait(false); } catch { } try { await Context.Message.DeleteAsync().ConfigureAwait(false); } catch { }
if (!plantedFlowers.TryRemove(channel.Id, out msgs)) if (!plantedFlowers.TryRemove(channel.Id, out msgs))
return; return;
await Task.WhenAll(msgs.Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false); await Task.WhenAll(msgs.Select(toDelete => toDelete.DeleteAsync())).ConfigureAwait(false);
await CurrencyHandler.AddCurrencyAsync((IGuildUser)imsg.Author, "Picked flower(s).", msgs.Count, false).ConfigureAwait(false); await CurrencyHandler.AddCurrencyAsync((IGuildUser)Context.User, "Picked flower(s).", msgs.Count, false).ConfigureAwait(false);
var msg = await channel.SendConfirmAsync($"**{imsg.Author}** picked {msgs.Count}{Gambling.Gambling.CurrencySign}!").ConfigureAwait(false); var msg = await channel.SendConfirmAsync($"**{Context.User}** picked {msgs.Count}{Gambling.Gambling.CurrencySign}!").ConfigureAwait(false);
msg.DeleteAfter(10); msg.DeleteAfter(10);
} }
finally finally
{ {
await Task.Delay(60000); await Task.Delay(60000);
usersRecentlyPicked.TryRemove(imsg.Author.Id); usersRecentlyPicked.TryRemove(Context.User.Id);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Plant(IUserMessage imsg) public async Task Plant()
{ {
var channel = (ITextChannel)imsg.Channel; var removed = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)Context.User, "Planted a flower.", 1, false).ConfigureAwait(false);
var removed = await CurrencyHandler.RemoveCurrencyAsync((IGuildUser)imsg.Author, "Planted a flower.", 1, false).ConfigureAwait(false);
if (!removed) if (!removed)
{ {
await channel.SendErrorAsync($"You don't have any {Gambling.Gambling.CurrencyPluralName}.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"You don't have any {Gambling.Gambling.CurrencyPluralName}.").ConfigureAwait(false);
return; return;
} }
@ -144,24 +148,24 @@ namespace NadekoBot.Modules.Games
IUserMessage msg; IUserMessage msg;
var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.Gambling.CurrencyName[0]); var vowelFirst = new[] { 'a', 'e', 'i', 'o', 'u' }.Contains(Gambling.Gambling.CurrencyName[0]);
var msgToSend = $"Oh how Nice! **{imsg.Author.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using {NadekoBot.ModulePrefixes[typeof(Games).Name]}pick"; var msgToSend = $"Oh how Nice! **{Context.User.Username}** planted {(vowelFirst ? "an" : "a")} {Gambling.Gambling.CurrencyName}. Pick it using {NadekoBot.ModulePrefixes[typeof(Games).Name]}pick";
if (file == null) if (file == null)
{ {
msg = await channel.SendConfirmAsync(Gambling.Gambling.CurrencySign).ConfigureAwait(false); msg = await Context.Channel.SendConfirmAsync(Gambling.Gambling.CurrencySign).ConfigureAwait(false);
} }
else else
{ {
msg = await channel.SendFileAsync(file, msgToSend).ConfigureAwait(false); msg = await Context.Channel.SendFileAsync(file, msgToSend).ConfigureAwait(false);
} }
plantedFlowers.AddOrUpdate(channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; }); plantedFlowers.AddOrUpdate(Context.Channel.Id, new List<IUserMessage>() { msg }, (id, old) => { old.Add(msg); return old; });
} }
#endif
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task GenCurrency(IUserMessage imsg) public async Task GenCurrency()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
bool enabled; bool enabled;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
@ -13,168 +14,172 @@ namespace NadekoBot.Modules.Games
{ {
public partial class Games public partial class Games
{ {
public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>(); [Group]
public class PollCommands : ModuleBase
[NadekoCommand, Usage, Description, Aliases]
[RequirePermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public Task Poll(IUserMessage umsg, [Remainder] string arg = null)
=> InternalStartPoll(umsg, arg, isPublic: false);
[NadekoCommand, Usage, Description, Aliases]
[RequirePermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public Task PublicPoll(IUserMessage umsg, [Remainder] string arg = null)
=> InternalStartPoll(umsg, arg, isPublic: true);
private async Task InternalStartPoll(IUserMessage umsg, string arg, bool isPublic = false)
{ {
var channel = (ITextChannel)umsg.Channel; public static ConcurrentDictionary<IGuild, Poll> ActivePolls = new ConcurrentDictionary<IGuild, Poll>();
if (!(umsg.Author as IGuildUser).GuildPermissions.ManageChannels) [NadekoCommand, Usage, Description, Aliases]
return; [RequireUserPermission(GuildPermission.ManageMessages)]
if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";")) [RequireContext(ContextType.Guild)]
return; public Task Poll([Remainder] string arg = null)
var data = arg.Split(';'); => InternalStartPoll(arg, isPublic: false);
if (data.Length < 3)
return;
var poll = new Poll(umsg, data[0], data.Skip(1), isPublic: isPublic); [NadekoCommand, Usage, Description, Aliases]
if (ActivePolls.TryAdd(channel.Guild, poll)) [RequireUserPermission(GuildPermission.ManageMessages)]
[RequireContext(ContextType.Guild)]
public Task PublicPoll([Remainder] string arg = null)
=> InternalStartPoll(arg, isPublic: true);
private async Task InternalStartPoll(string arg, bool isPublic = false)
{ {
await poll.StartPoll().ConfigureAwait(false); var channel = (ITextChannel)Context.Channel;
}
else
await channel.SendErrorAsync("Poll is already running on this server.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases] if (!(Context.User as IGuildUser).GuildPermissions.ManageChannels)
[RequirePermission(GuildPermission.ManageMessages)] return;
[RequireContext(ContextType.Guild)] if (string.IsNullOrWhiteSpace(arg) || !arg.Contains(";"))
public async Task Pollend(IUserMessage umsg) return;
{ var data = arg.Split(';');
var channel = (ITextChannel)umsg.Channel; if (data.Length < 3)
return;
Poll poll; var poll = new Poll(Context.Message, data[0], data.Skip(1), isPublic: isPublic);
ActivePolls.TryRemove(channel.Guild, out poll); if (ActivePolls.TryAdd(channel.Guild, poll))
await poll.StopPoll().ConfigureAwait(false);
}
}
public class Poll
{
private readonly IUserMessage originalMessage;
private readonly IGuild guild;
private readonly string[] answers;
private ConcurrentDictionary<ulong, int> participants = new ConcurrentDictionary<ulong, int>();
private readonly string question;
private DateTime started;
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
private readonly bool isPublic;
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
{
this.originalMessage = umsg;
this.guild = ((ITextChannel)umsg.Channel).Guild;
this.question = question;
this.answers = enumerable as string[] ?? enumerable.ToArray();
this.isPublic = isPublic;
}
public async Task StartPoll()
{
started = DateTime.Now;
NadekoBot.Client.MessageReceived += Vote;
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
var num = 1;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
if (!isPublic)
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
else
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
await originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
}
public async Task StopPoll()
{
NadekoBot.Client.MessageReceived -= Vote;
try
{
var results = participants.GroupBy(kvp => kvp.Value)
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
.OrderByDescending(kvp => kvp.Value);
var totalVotesCast = results.Sum(kvp => kvp.Value);
if (totalVotesCast == 0)
{ {
await originalMessage.Channel.SendMessageAsync("📄 **No votes have been cast.**").ConfigureAwait(false); await poll.StartPoll().ConfigureAwait(false);
return;
}
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
$"📄 , here are the results:\n";
closeMessage = results.Aggregate(closeMessage, (current, kvp) => current + $"`{kvp.Key}.` **[{answers[kvp.Key - 1]}]**" +
$" has {kvp.Value} votes." +
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
await originalMessage.Channel.SendConfirmAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine($"Error in poll game {ex}");
}
}
private async void Vote(IMessage imsg)
{
try
{
// has to be a user message
var msg = imsg as IUserMessage;
if (msg == null || msg.Author.IsBot)
return;
// has to be an integer
int vote;
if (!int.TryParse(imsg.Content, out vote))
return;
if (vote < 1 || vote > answers.Length)
return;
IMessageChannel ch;
if (isPublic)
{
//if public, channel must be the same the poll started in
if (originalMessage.Channel.Id != imsg.Channel.Id)
return;
ch = imsg.Channel;
} }
else else
{ await channel.SendErrorAsync("Poll is already running on this server.").ConfigureAwait(false);
//if private, channel must be dm channel }
if ((ch = msg.Channel as IDMChannel) == null)
return;
// user must be a member of the guild this poll is in [NadekoCommand, Usage, Description, Aliases]
var guildUsers = await guild.GetUsersAsync().ConfigureAwait(false); [RequireUserPermission(GuildPermission.ManageMessages)]
if (!guildUsers.Any(u => u.Id == imsg.Author.Id)) [RequireContext(ContextType.Guild)]
return; public async Task Pollend()
} {
var channel = (ITextChannel)Context.Channel;
//user can vote only once Poll poll;
if (participants.TryAdd(msg.Author.Id, vote)) ActivePolls.TryRemove(channel.Guild, out poll);
await poll.StopPoll().ConfigureAwait(false);
}
}
public class Poll
{
private readonly IUserMessage originalMessage;
private readonly IGuild guild;
private readonly string[] answers;
private ConcurrentDictionary<ulong, int> participants = new ConcurrentDictionary<ulong, int>();
private readonly string question;
private DateTime started;
private CancellationTokenSource pollCancellationSource = new CancellationTokenSource();
private readonly bool isPublic;
public Poll(IUserMessage umsg, string question, IEnumerable<string> enumerable, bool isPublic = false)
{
this.originalMessage = umsg;
this.guild = ((ITextChannel)umsg.Channel).Guild;
this.question = question;
this.answers = enumerable as string[] ?? enumerable.ToArray();
this.isPublic = isPublic;
}
public async Task StartPoll()
{
started = DateTime.Now;
NadekoBot.Client.MessageReceived += Vote;
var msgToSend = $"📃**{originalMessage.Author.Username}** has created a poll which requires your attention:\n\n**{question}**\n";
var num = 1;
msgToSend = answers.Aggregate(msgToSend, (current, answ) => current + $"`{num++}.` **{answ}**\n");
if (!isPublic)
msgToSend += "\n**Private Message me with the corresponding number of the answer.**";
else
msgToSend += "\n**Send a Message here with the corresponding number of the answer.**";
await originalMessage.Channel.SendConfirmAsync(msgToSend).ConfigureAwait(false);
}
public async Task StopPoll()
{
NadekoBot.Client.MessageReceived -= Vote;
try
{ {
if (!isPublic) var results = participants.GroupBy(kvp => kvp.Value)
.ToDictionary(x => x.Key, x => x.Sum(kvp => 1))
.OrderByDescending(kvp => kvp.Value);
var totalVotesCast = results.Sum(kvp => kvp.Value);
if (totalVotesCast == 0)
{ {
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false); await originalMessage.Channel.SendMessageAsync("📄 **No votes have been cast.**").ConfigureAwait(false);
return;
}
var closeMessage = $"--------------**POLL CLOSED**--------------\n" +
$"📄 , here are the results:\n";
closeMessage = results.Aggregate(closeMessage, (current, kvp) => current + $"`{kvp.Key}.` **[{answers[kvp.Key - 1]}]**" +
$" has {kvp.Value} votes." +
$"({kvp.Value * 1.0f / totalVotesCast * 100}%)\n");
await originalMessage.Channel.SendConfirmAsync($"📄 **Total votes cast**: {totalVotesCast}\n{closeMessage}").ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine($"Error in poll game {ex}");
}
}
private async void Vote(SocketMessage imsg)
{
try
{
// has to be a user message
var msg = imsg as SocketUserMessage;
if (msg == null || msg.Author.IsBot)
return;
// has to be an integer
int vote;
if (!int.TryParse(imsg.Content, out vote))
return;
if (vote < 1 || vote > answers.Length)
return;
IMessageChannel ch;
if (isPublic)
{
//if public, channel must be the same the poll started in
if (originalMessage.Channel.Id != imsg.Channel.Id)
return;
ch = imsg.Channel;
} }
else else
{ {
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false); //if private, channel must be dm channel
toDelete.DeleteAfter(5); if ((ch = msg.Channel as IDMChannel) == null)
return;
// user must be a member of the guild this poll is in
var guildUsers = await guild.GetUsersAsync().ConfigureAwait(false);
if (!guildUsers.Any(u => u.Id == imsg.Author.Id))
return;
}
//user can vote only once
if (participants.TryAdd(msg.Author.Id, vote))
{
if (!isPublic)
{
await ch.SendConfirmAsync($"Thanks for voting **{msg.Author.Username}**.").ConfigureAwait(false);
}
else
{
var toDelete = await ch.SendConfirmAsync($"{msg.Author.Mention} cast their vote.").ConfigureAwait(false);
toDelete.DeleteAfter(5);
}
} }
} }
catch { }
} }
catch { }
} }
} }
} }

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Games.Commands.Models; using NadekoBot.Modules.Games.Commands.Models;
@ -105,13 +106,13 @@ namespace NadekoBot.Modules.Games
NadekoBot.Client.MessageReceived += AnswerReceived; NadekoBot.Client.MessageReceived += AnswerReceived;
} }
private async void AnswerReceived(IMessage imsg) private async void AnswerReceived(SocketMessage imsg)
{ {
try try
{ {
if (imsg.Author.IsBot) if (imsg.Author.IsBot)
return; return;
var msg = imsg as IUserMessage; var msg = imsg as SocketUserMessage;
if (msg == null) if (msg == null)
return; return;
@ -125,15 +126,15 @@ namespace NadekoBot.Modules.Games
{ {
var wpm = CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60; var wpm = CurrentSentence.Length / WORD_VALUE / sw.Elapsed.Seconds * 60;
finishedUserIds.Add(msg.Author.Id); finishedUserIds.Add(msg.Author.Id);
await Extensions.Extensions.EmbedAsync(this.Channel, (Discord.API.Embed)new EmbedBuilder().WithColor((uint)NadekoBot.OkColor) await this.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle((string)$"{msg.Author} finished the race!") .WithTitle((string)$"{msg.Author} finished the race!")
.AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true)) .AddField(efb => efb.WithName("Place").WithValue($"#{finishedUserIds.Count}").WithIsInline(true))
.AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F2} *[{sw.Elapsed.Seconds.ToString()}sec]*").WithIsInline(true)) .AddField(efb => efb.WithName("WPM").WithValue($"{wpm:F2} *[{sw.Elapsed.Seconds.ToString()}sec]*").WithIsInline(true))
.AddField(efb => efb.WithName((string)"Errors").WithValue((string)distance.ToString()).WithIsInline((bool)true)) .AddField(efb => efb.WithName((string)"Errors").WithValue((string)distance.ToString()).WithIsInline((bool)true)))
.Build()).ConfigureAwait(false); .ConfigureAwait(false);
if (finishedUserIds.Count % 4 == 0) if (finishedUserIds.Count % 4 == 0)
{ {
await Extensions.Extensions.SendConfirmAsync(this.Channel, (string)$":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize((string)CurrentSentence.Replace((string)" ", (string)" \x200B")).SanitizeMentions()}**").ConfigureAwait(false); await this.Channel.SendConfirmAsync($":exclamation: A lot of people finished, here is the text for those still typing:\n\n**{Format.Sanitize(CurrentSentence.Replace(" ", " \x200B")).SanitizeMentions()}**").ConfigureAwait(false);
} }
} }
} }
@ -145,9 +146,8 @@ namespace NadekoBot.Modules.Games
} }
[Group] [Group]
public class SpeedTypingCommands public class SpeedTypingCommands : ModuleBase
{ {
public static List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>(); public static List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
const string typingArticlesPath = "data/typing_articles.json"; const string typingArticlesPath = "data/typing_articles.json";
@ -156,18 +156,13 @@ namespace NadekoBot.Modules.Games
{ {
try { TypingArticles = JsonConvert.DeserializeObject<List<TypingArticle>>(File.ReadAllText(typingArticlesPath)); } catch { } try { TypingArticles = JsonConvert.DeserializeObject<List<TypingArticle>>(File.ReadAllText(typingArticlesPath)); } catch { }
} }
public static ConcurrentDictionary<ulong, TypingGame> RunningContests; public static ConcurrentDictionary<ulong, TypingGame> RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
public SpeedTypingCommands()
{
RunningContests = new ConcurrentDictionary<ulong, TypingGame>();
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task TypeStart(IUserMessage msg) public async Task TypeStart()
{ {
var channel = (ITextChannel)msg.Channel; var channel = (ITextChannel)Context.Channel;
var game = RunningContests.GetOrAdd(channel.Guild.Id, id => new TypingGame(channel)); var game = RunningContests.GetOrAdd(channel.Guild.Id, id => new TypingGame(channel));
@ -186,9 +181,9 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task TypeStop(IUserMessage imsg) public async Task TypeStop()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
TypingGame game; TypingGame game;
if (RunningContests.TryRemove(channel.Guild.Id, out game)) if (RunningContests.TryRemove(channel.Guild.Id, out game))
{ {
@ -202,13 +197,13 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Typeadd(IUserMessage imsg, [Remainder] string text) public async Task Typeadd([Remainder] string text)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
TypingArticles.Add(new TypingArticle TypingArticles.Add(new TypingArticle
{ {
Title = $"Text added on {DateTime.UtcNow} by {imsg.Author}", Title = $"Text added on {DateTime.UtcNow} by {Context.User}",
Text = text.SanitizeMentions(), Text = text.SanitizeMentions(),
}); });
@ -219,9 +214,9 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Typelist(IUserMessage imsg, int page = 1) public async Task Typelist(int page = 1)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
if (page < 1) if (page < 1)
return; return;
@ -230,7 +225,7 @@ namespace NadekoBot.Modules.Games
if (!articles.Any()) if (!articles.Any())
{ {
await channel.SendErrorAsync($"{imsg.Author.Mention} `No articles found on that page.`").ConfigureAwait(false); await channel.SendErrorAsync($"{Context.User.Mention} `No articles found on that page.`").ConfigureAwait(false);
return; return;
} }
var i = (page - 1) * 15; var i = (page - 1) * 15;
@ -241,9 +236,9 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Typedel(IUserMessage imsg, int index) public async Task Typedel(int index)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
index -= 1; index -= 1;
if (index < 0 || index >= TypingArticles.Count) if (index < 0 || index >= TypingArticles.Count)

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Net; using Discord.Net;
using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NLog; using NLog;
using System; using System;
@ -70,7 +71,7 @@ namespace NadekoBot.Modules.Games.Trivia
.AddField(eab => eab.WithName("Category").WithValue(CurrentQuestion.Category)) .AddField(eab => eab.WithName("Category").WithValue(CurrentQuestion.Category))
.AddField(eab => eab.WithName("Question").WithValue(CurrentQuestion.Question)); .AddField(eab => eab.WithName("Question").WithValue(CurrentQuestion.Question));
questionMessage = await channel.EmbedAsync(questionEmbed.Build()).ConfigureAwait(false); questionMessage = await channel.EmbedAsync(questionEmbed).ConfigureAwait(false);
} }
catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden) catch (HttpException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound || ex.StatusCode == System.Net.HttpStatusCode.Forbidden)
{ {
@ -130,8 +131,7 @@ namespace NadekoBot.Modules.Games.Trivia
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Trivia Game Ended")) .WithAuthor(eab => eab.WithName("Trivia Game Ended"))
.WithTitle("Final Results") .WithTitle("Final Results")
.WithDescription(GetLeaderboard()) .WithDescription(GetLeaderboard())).ConfigureAwait(false);
.Build()).ConfigureAwait(false);
} }
public async Task StopGame() public async Task StopGame()
@ -142,14 +142,14 @@ namespace NadekoBot.Modules.Games.Trivia
try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } try { await channel.SendConfirmAsync("Trivia Game", "Stopping after this question.").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
} }
private async void PotentialGuess(IMessage imsg) private async void PotentialGuess(SocketMessage imsg)
{ {
try try
{ {
if (imsg.Author.IsBot) if (imsg.Author.IsBot)
return; return;
var umsg = imsg as IUserMessage; var umsg = imsg as SocketUserMessage;
if (umsg == null) if (umsg == null)
return; return;

View File

@ -8,26 +8,26 @@ using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
//todo Rewrite? Fix trivia not stopping bug
namespace NadekoBot.Modules.Games namespace NadekoBot.Modules.Games
{ {
public partial class Games public partial class Games
{ {
[Group] [Group]
public class TriviaCommands public class TriviaCommands : ModuleBase
{ {
public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias = new ConcurrentDictionary<ulong, TriviaGame>(); public static ConcurrentDictionary<ulong, TriviaGame> RunningTrivias { get; } = new ConcurrentDictionary<ulong, TriviaGame>();
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task Trivia(IUserMessage umsg, [Remainder] string additionalArgs = "") public Task Trivia([Remainder] string additionalArgs = "")
=> Trivia(umsg, 10, additionalArgs); => Trivia(10, additionalArgs);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Trivia(IUserMessage umsg, int winReq = 10, [Remainder] string additionalArgs = "") public async Task Trivia(int winReq = 10, [Remainder] string additionalArgs = "")
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
var showHints = !additionalArgs.Contains("nohint"); var showHints = !additionalArgs.Contains("nohint");
@ -45,15 +45,15 @@ namespace NadekoBot.Modules.Games
} }
return; return;
} }
else
await channel.SendErrorAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false); await Context.Channel.SendErrorAsync("Trivia game is already running on this server.\n" + trivia.CurrentQuestion).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Tl(IUserMessage umsg) public async Task Tl()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
TriviaGame trivia; TriviaGame trivia;
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia)) if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))
@ -67,9 +67,9 @@ namespace NadekoBot.Modules.Games
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Tq(IUserMessage umsg) public async Task Tq()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
TriviaGame trivia; TriviaGame trivia;
if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia)) if (RunningTrivias.TryGetValue(channel.Guild.Id, out trivia))

View File

@ -21,46 +21,35 @@ namespace NadekoBot.Modules.Games
} }
} }
} }
public Games() : base()
{
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Choose([Remainder] string list = null)
public async Task Choose(IUserMessage umsg, [Remainder] string list = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(list)) if (string.IsNullOrWhiteSpace(list))
return; return;
var listArr = list.Split(';'); var listArr = list.Split(';');
if (listArr.Count() < 2) if (listArr.Count() < 2)
return; return;
var rng = new NadekoRandom(); var rng = new NadekoRandom();
await channel.SendConfirmAsync("🤔", listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🤔", listArr[rng.Next(0, listArr.Length)]).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task _8Ball([Remainder] string question = null)
public async Task _8Ball(IUserMessage umsg, [Remainder] string question = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(question)) if (string.IsNullOrWhiteSpace(question))
return; return;
var rng = new NadekoRandom(); var rng = new NadekoRandom();
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithColor(NadekoBot.OkColor)
.AddField(efb => efb.WithName("❓ Question").WithValue(question).WithIsInline(false)) .AddField(efb => efb.WithName("❓ Question").WithValue(question).WithIsInline(false))
.AddField(efb => efb.WithName("🎱 8Ball").WithValue(_8BallResponses.Shuffle().FirstOrDefault()).WithIsInline(false)) .AddField(efb => efb.WithName("🎱 8Ball").WithValue(_8BallResponses.Shuffle().FirstOrDefault()).WithIsInline(false)));
.Build());
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Rps(string input)
public async Task Rps(IUserMessage umsg, string input)
{ {
var channel = (ITextChannel)umsg.Channel;
Func<int,string> GetRPSPick = (p) => Func<int,string> GetRPSPick = (p) =>
{ {
if (p == 0) if (p == 0)
@ -98,20 +87,17 @@ namespace NadekoBot.Modules.Games
else if ((pick == 0 && nadekoPick == 1) || else if ((pick == 0 && nadekoPick == 1) ||
(pick == 1 && nadekoPick == 2) || (pick == 1 && nadekoPick == 2) ||
(pick == 2 && nadekoPick == 0)) (pick == 2 && nadekoPick == 0))
msg = $"{NadekoBot.Client.GetCurrentUser().Mention} won! {GetRPSPick(nadekoPick)} beats {GetRPSPick(pick)}"; msg = $"{NadekoBot.Client.CurrentUser().Mention} won! {GetRPSPick(nadekoPick)} beats {GetRPSPick(pick)}";
else else
msg = $"{umsg.Author.Mention} won! {GetRPSPick(pick)} beats {GetRPSPick(nadekoPick)}"; msg = $"{Context.User.Mention} won! {GetRPSPick(pick)} beats {GetRPSPick(nadekoPick)}";
await channel.SendConfirmAsync(msg).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(msg).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Linux(string guhnoo, string loonix)
public async Task Linux(IUserMessage umsg, string guhnoo, string loonix)
{ {
var channel = (ITextChannel)umsg.Channel; await Context.Channel.SendConfirmAsync(
await channel.SendConfirmAsync(
$@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX. $@"I'd just like to interject for moment. What you're refering to as {loonix}, is in fact, {guhnoo}/{loonix}, or as I've recently taken to calling it, {guhnoo} plus {loonix}. {loonix} is not an operating system unto itself, but rather another free component of a fully functioning {guhnoo} system made useful by the {guhnoo} corelibs, shell utilities and vital system components comprising a full OS as defined by POSIX.
Many computer users run a modified version of the {guhnoo} system every day, without realizing it. Through a peculiar turn of events, the version of {guhnoo} which is widely used today is often called {loonix}, and many of its users are not aware that it is basically the {guhnoo} system, developed by the {guhnoo} Project. Many computer users run a modified version of the {guhnoo} system every day, without realizing it. Through a peculiar turn of events, the version of {guhnoo} which is widely used today is often called {loonix}, and many of its users are not aware that it is basically the {guhnoo} system, developed by the {guhnoo} Project.

View File

@ -22,6 +22,8 @@ namespace NadekoBot.Modules.Help
static Help() static Help()
{ {
//todo don't cache this, just query db when someone wants -h
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.BotConfig.GetOrCreate(); var config = uow.BotConfig.GetOrCreate();
@ -35,29 +37,28 @@ namespace NadekoBot.Modules.Help
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Modules(IUserMessage umsg) public async Task Modules()
{ {
var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText($" Type `-cmds ModuleName` to get a list of commands in that module. eg `-cmds games`")) var embed = new EmbedBuilder().WithOkColor().WithFooter(efb => efb.WithText($" Type `-cmds ModuleName` to get a list of commands in that module. eg `-cmds games`"))
.WithTitle("📜 List Of Modules").WithDescription("\n• " + string.Join("\n• ", NadekoBot.CommandService.Modules.Select(m => m.Name).OrderBy(s=>s))) .WithTitle("📜 List Of Modules").WithDescription("\n• " + string.Join("\n• ", NadekoBot.CommandService.Modules.GroupBy(m => m.GetTopLevelModule()).Select(m => m.Key.Name).OrderBy(s => s)));
.Build(); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
await umsg.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Commands(IUserMessage umsg, [Remainder] string module = null) public async Task Commands([Remainder] string module = null)
{ {
var channel = umsg.Channel; var channel = Context.Channel;
module = module?.Trim().ToUpperInvariant(); module = module?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(module)) if (string.IsNullOrWhiteSpace(module))
return; return;
var cmds = NadekoBot.CommandService.Commands.Where(c => c.Module.Name.ToUpperInvariant().StartsWith(module)) var cmds = NadekoBot.CommandService.Commands.Where(c => c.Module.GetTopLevelModule().Name.ToUpperInvariant().StartsWith(module))
.OrderBy(c => c.Text) .OrderBy(c => c.Aliases.First())
.Distinct(new CommandTextEqualityComparer()) .Distinct(new CommandTextEqualityComparer())
.AsEnumerable(); .AsEnumerable();
var cmdsArray = cmds as Command[] ?? cmds.ToArray(); var cmdsArray = cmds as CommandInfo[] ?? cmds.ToArray();
if (!cmdsArray.Any()) if (!cmdsArray.Any())
{ {
await channel.SendErrorAsync("That module does not exist.").ConfigureAwait(false); await channel.SendErrorAsync("That module does not exist.").ConfigureAwait(false);
@ -65,64 +66,63 @@ namespace NadekoBot.Modules.Help
} }
if (module != "customreactions" && module != "conversations") if (module != "customreactions" && module != "conversations")
{ {
await channel.SendTableAsync("📃 **List Of Commands:**\n", cmdsArray, el => $"{el.Text,-15} {"["+el.Aliases.Skip(1).FirstOrDefault()+"]",-8}").ConfigureAwait(false); await channel.SendTableAsync("📃 **List Of Commands:**\n", cmdsArray, el => $"{el.Aliases.First(),-15} {"["+el.Aliases.Skip(1).FirstOrDefault()+"]",-8}").ConfigureAwait(false);
} }
else else
{ {
await channel.SendMessageAsync("📃 **List Of Commands:**\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}"))); await channel.SendMessageAsync("📃 **List Of Commands:**\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Aliases.First()}")));
} }
await channel.SendConfirmAsync($" **Type** `\"{NadekoBot.ModulePrefixes[typeof(Help).Name]}h CommandName\"` **to see the help for that specified command.** ***e.g.*** `-h >8ball`").ConfigureAwait(false); await channel.SendConfirmAsync($" **Type** `\"{NadekoBot.ModulePrefixes[typeof(Help).Name]}h CommandName\"` **to see the help for that specified command.** ***e.g.*** `-h >8ball`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task H(IUserMessage umsg, [Remainder] string comToFind = null) public async Task H([Remainder] string comToFind = null)
{ {
var channel = umsg.Channel; var channel = Context.Channel;
comToFind = comToFind?.ToLowerInvariant(); comToFind = comToFind?.ToLowerInvariant();
if (string.IsNullOrWhiteSpace(comToFind)) if (string.IsNullOrWhiteSpace(comToFind))
{ {
IMessageChannel ch = channel is ITextChannel ? await ((IGuildUser)umsg.Author).CreateDMChannelAsync() : channel; IMessageChannel ch = channel is ITextChannel ? await ((IGuildUser)Context.User).CreateDMChannelAsync() : channel;
await ch.SendMessageAsync(HelpString).ConfigureAwait(false); await ch.SendMessageAsync(HelpString).ConfigureAwait(false);
return; return;
} }
var com = NadekoBot.CommandService.Commands.FirstOrDefault(c => c.Text.ToLowerInvariant() == comToFind || c.Aliases.Select(a=>a.ToLowerInvariant()).Contains(comToFind)); var com = NadekoBot.CommandService.Commands.FirstOrDefault(c => c.Aliases.Select(a=>a.ToLowerInvariant()).Contains(comToFind));
if (com == null) if (com == null)
{ {
await channel.SendErrorAsync("I can't find that command. Please check the **command** and **command prefix** before trying again."); await channel.SendErrorAsync("I can't find that command. Please check the **command** and **command prefix** before trying again.");
return; return;
} }
var str = $"**`{com.Text}`**"; var str = $"**`{com.Aliases.First()}`**";
var alias = com.Aliases.Skip(1).FirstOrDefault(); var alias = com.Aliases.Skip(1).FirstOrDefault();
if (alias != null) if (alias != null)
str += $" **/ `{alias}`**"; str += $" **/ `{alias}`**";
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.AddField(fb => fb.WithIndex(1).WithName(str).WithValue($"{ string.Format(com.Summary, com.Module.Prefix)} { GetCommandRequirements(com)}").WithIsInline(true)) .AddField(fb => fb.WithName(str).WithValue($"{ string.Format(com.Summary, com.Module.Aliases.First())} { GetCommandRequirements(com)}").WithIsInline(true))
.AddField(fb => fb.WithIndex(2).WithName("**Usage**").WithValue($"{string.Format(com.Remarks, com.Module.Prefix)}").WithIsInline(false)) .AddField(fb => fb.WithName("**Usage**").WithValue($"{string.Format(com.Remarks, com.Module.Aliases.First())}").WithIsInline(false))
.WithOkColor(); .WithColor(NadekoBot.OkColor);
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await channel.EmbedAsync(embed).ConfigureAwait(false);
} }
private string GetCommandRequirements(Command cmd) private string GetCommandRequirements(CommandInfo cmd) =>
{ String.Join(" ", cmd.Preconditions
return String.Join(" ", cmd.Source.CustomAttributes .Where(ca => ca is OwnerOnlyAttribute || ca is RequireUserPermissionAttribute)
.Where(ca => ca.AttributeType == typeof(OwnerOnlyAttribute) || ca.AttributeType == typeof(RequirePermissionAttribute)) .Select(ca =>
.Select(ca => {
{ if (ca is OwnerOnlyAttribute)
if (ca.AttributeType == typeof(OwnerOnlyAttribute)) return "**Bot Owner only.**";
return "**Bot Owner only.**"; var cau = (RequireUserPermissionAttribute)ca;
else if (ca.AttributeType == typeof(RequirePermissionAttribute)) if (cau.GuildPermission != null)
return $"**Requires {(GuildPermission)ca.ConstructorArguments.FirstOrDefault().Value} server permission.**".Replace("Guild", "Server"); return $"**Requires {cau.GuildPermission} server permission.**".Replace("Guild", "Server");
else else
return $"**Requires {(GuildPermission)ca.ConstructorArguments.FirstOrDefault().Value} channel permission.**".Replace("Guild", "Server"); return $"**Requires {cau.ChannelPermission} channel permission.**".Replace("Guild", "Server");
})); }));
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public Task Hgit(IUserMessage umsg) public Task Hgit()
{ {
var helpstr = new StringBuilder(); var helpstr = new StringBuilder();
helpstr.AppendLine("You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: <https://www.paypal.me/Kwoth>\n"); helpstr.AppendLine("You can support the project on patreon: <https://patreon.com/nadekobot> or paypal: <https://www.paypal.me/Kwoth>\n");
@ -130,7 +130,7 @@ namespace NadekoBot.Modules.Help
helpstr.AppendLine(string.Join("\n", NadekoBot.CommandService.Modules.Where(m => m.Name.ToLowerInvariant() != "help").OrderBy(m => m.Name).Prepend(NadekoBot.CommandService.Modules.FirstOrDefault(m=>m.Name.ToLowerInvariant()=="help")).Select(m => $"- [{m.Name}](#{m.Name.ToLowerInvariant()})"))); helpstr.AppendLine(string.Join("\n", NadekoBot.CommandService.Modules.Where(m => m.Name.ToLowerInvariant() != "help").OrderBy(m => m.Name).Prepend(NadekoBot.CommandService.Modules.FirstOrDefault(m=>m.Name.ToLowerInvariant()=="help")).Select(m => $"- [{m.Name}](#{m.Name.ToLowerInvariant()})")));
helpstr.AppendLine(); helpstr.AppendLine();
string lastModule = null; string lastModule = null;
foreach (var com in NadekoBot.CommandService.Commands.OrderBy(com=>com.Module.Name).GroupBy(c=>c.Text).Select(g=>g.First())) foreach (var com in NadekoBot.CommandService.Commands.OrderBy(com => com.Module.Name).GroupBy(c => c.Aliases.First()).Select(g => g.First()))
{ {
if (com.Module.Name != lastModule) if (com.Module.Name != lastModule)
{ {
@ -145,18 +145,18 @@ namespace NadekoBot.Modules.Help
helpstr.AppendLine("----------------|--------------|-------"); helpstr.AppendLine("----------------|--------------|-------");
lastModule = com.Module.Name; lastModule = com.Module.Name;
} }
helpstr.AppendLine($"`{com.Text}` {string.Join(" ", com.Aliases.Skip(1).Select(a=>"`"+a+"`"))} | {string.Format(com.Summary, com.Module.Prefix)} {GetCommandRequirements(com)} | {string.Format(com.Remarks, com.Module.Prefix)}"); helpstr.AppendLine($"{string.Join(" ", com.Aliases.Select(a => "`" + a + "`"))} | {string.Format(com.Summary, com.Module.GetPrefix())} {GetCommandRequirements(com)} | {string.Format(com.Remarks, com.Module.GetPrefix())}");
} }
helpstr = helpstr.Replace(NadekoBot.Client.GetCurrentUser().Username , "@BotName"); helpstr = helpstr.Replace(NadekoBot.Client.CurrentUser().Username , "@BotName");
File.WriteAllText("../../docs/Commands List.md", helpstr.ToString()); File.WriteAllText("../../docs/Commands List.md", helpstr.ToString());
return Task.CompletedTask; return Task.CompletedTask;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Guide(IUserMessage umsg) public async Task Guide()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
await channel.SendConfirmAsync( await channel.SendConfirmAsync(
@"**LIST OF COMMANDS**: <http://nadekobot.readthedocs.io/en/latest/Commands%20List/> @"**LIST OF COMMANDS**: <http://nadekobot.readthedocs.io/en/latest/Commands%20List/>
@ -165,9 +165,9 @@ namespace NadekoBot.Modules.Help
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Donate(IUserMessage umsg) public async Task Donate()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
await channel.SendConfirmAsync( await channel.SendConfirmAsync(
$@"You can support the NadekoBot project on patreon. <https://patreon.com/nadekobot> or $@"You can support the NadekoBot project on patreon. <https://patreon.com/nadekobot> or
@ -178,11 +178,11 @@ Don't forget to leave your discord name or id in the message.
} }
} }
public class CommandTextEqualityComparer : IEqualityComparer<Command> public class CommandTextEqualityComparer : IEqualityComparer<CommandInfo>
{ {
public bool Equals(Command x, Command y) => x.Text == y.Text; public bool Equals(CommandInfo x, CommandInfo y) => x.Aliases.First() == y.Aliases.First();
public int GetHashCode(Command obj) => obj.Text.GetHashCode(); public int GetHashCode(CommandInfo obj) => obj.Aliases.First().GetHashCode();
} }
} }

View File

@ -77,6 +77,8 @@ namespace NadekoBot.Modules.Music.Classes
public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%"; public string PrettyVolume => $"🔉 {(int)(Volume * 100)}%";
public event Action<Song> SongRemoved = delegate { };
public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume) public MusicPlayer(IVoiceChannel startingVoiceChannel, float? defaultVolume)
{ {
if (startingVoiceChannel == null) if (startingVoiceChannel == null)
@ -277,7 +279,12 @@ namespace NadekoBot.Modules.Music.Classes
{ {
if (index < 0 || index >= playlist.Count) if (index < 0 || index >= playlist.Count)
return; return;
playlist.RemoveAt(index); var song = playlist.ElementAtOrDefault(index);
if (playlist.Remove(song))
{
SongRemoved(song);
}
}); });
} }

View File

@ -71,11 +71,11 @@ namespace NadekoBot.Modules.Music.Classes
switch (SongInfo.ProviderType) switch (SongInfo.ProviderType)
{ {
case MusicType.Radio: case MusicType.Radio:
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
case MusicType.Normal:
//todo have videoid in songinfo from the start //todo 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.Normal:
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850925063340032/1482522097_radio.png"; //test links
case MusicType.Local: case MusicType.Local:
return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links return $"https://cdn.discordapp.com/attachments/155726317222887425/261850914783100928/1482522077_music.png"; //test links
case MusicType.Soundcloud: case MusicType.Soundcloud:

View File

@ -19,14 +19,15 @@ using System.Threading;
namespace NadekoBot.Modules.Music namespace NadekoBot.Modules.Music
{ {
[NadekoModule("Music", "!!", AutoLoad = false)] [NadekoModule("Music", "!!")]
[DontAutoLoad]
public partial class Music : DiscordModule public partial class Music : DiscordModule
{ {
public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>(); public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
public const string MusicDataPath = "data/musicdata"; public const string MusicDataPath = "data/musicdata";
public Music() : base() static Music()
{ {
//it can fail if its currenctly opened or doesn't exist. Either way i don't care //it can fail if its currenctly opened or doesn't exist. Either way i don't care
try { Directory.Delete(MusicDataPath, true); } catch { } try { Directory.Delete(MusicDataPath, true); } catch { }
@ -36,39 +37,42 @@ namespace NadekoBot.Modules.Music
Directory.CreateDirectory(MusicDataPath); Directory.CreateDirectory(MusicDataPath);
} }
private void Client_UserVoiceStateUpdated(IUser iusr, IVoiceState oldState, IVoiceState newState) private static async void Client_UserVoiceStateUpdated(SocketUser iusr, SocketVoiceState oldState, SocketVoiceState newState)
{ {
var usr = iusr as IGuildUser; var usr = iusr as SocketGuildUser;
if (usr == null || if (usr == null ||
oldState.VoiceChannel == newState.VoiceChannel) oldState.VoiceChannel == newState.VoiceChannel)
return; return;
MusicPlayer player; MusicPlayer player;
if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player)) if (!MusicPlayers.TryGetValue(usr.Guild.Id, out player))
return; return;
if ((player.PlaybackVoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause try
player.Paused &&
player.PlaybackVoiceChannel.GetUsers().Count == 2) || // keep in mind bot is in the channel (+1)
(player.PlaybackVoiceChannel == oldState.VoiceChannel && // if left last, and player unpaused, pause
!player.Paused &&
player.PlaybackVoiceChannel.GetUsers().Count == 1))
{ {
player.TogglePause(); var users = await player.PlaybackVoiceChannel.GetUsersAsync().Flatten().ConfigureAwait(false);
if ((player.PlaybackVoiceChannel == newState.VoiceChannel && //if joined first, and player paused, unpause
player.Paused &&
users.Count() == 2) || // keep in mind bot is in the channel (+1)
(player.PlaybackVoiceChannel == oldState.VoiceChannel && // if left last, and player unpaused, pause
!player.Paused &&
users.Count() == 1))
{
player.TogglePause();
}
} }
return; catch { }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task Next(IUserMessage umsg, int skipCount = 1) public Task Next(int skipCount = 1)
{ {
var channel = (ITextChannel)umsg.Channel;
if (skipCount < 1) if (skipCount < 1)
return Task.CompletedTask; return Task.CompletedTask;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)umsg.Author).VoiceChannel) if (musicPlayer.PlaybackVoiceChannel == ((IGuildUser)Context.User).VoiceChannel)
{ {
while (--skipCount > 0) while (--skipCount > 0)
{ {
@ -81,13 +85,11 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task Stop(IUserMessage umsg) public Task Stop()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
if (((IGuildUser)umsg.Author).VoiceChannel == musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel == musicPlayer.PlaybackVoiceChannel)
{ {
musicPlayer.Autoplay = false; musicPlayer.Autoplay = false;
musicPlayer.Stop(); musicPlayer.Stop();
@ -97,10 +99,9 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Destroy(IUserMessage umsg) public async Task Destroy()
{ {
var channel = (ITextChannel)umsg.Channel; await Context.Channel.SendErrorAsync("This command is temporarily disabled.").ConfigureAwait(false);
await channel.SendErrorAsync("This command is temporarily disabled.").ConfigureAwait(false);
/*MusicPlayer musicPlayer; /*MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask;
@ -112,13 +113,11 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task Pause(IUserMessage umsg) public Task Pause()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return Task.CompletedTask; if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return Task.CompletedTask;
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return Task.CompletedTask; return Task.CompletedTask;
musicPlayer.TogglePause(); musicPlayer.TogglePause();
return Task.CompletedTask; return Task.CompletedTask;
@ -126,12 +125,12 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Fairplay(IUserMessage umsg) public async Task Fairplay()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return;
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return; return;
var val = musicPlayer.FairPlay = !musicPlayer.FairPlay; var val = musicPlayer.FairPlay = !musicPlayer.FairPlay;
@ -140,39 +139,35 @@ namespace NadekoBot.Modules.Music
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Queue(IUserMessage umsg, [Remainder] string query) public async Task Queue([Remainder] string query)
{ {
var channel = (ITextChannel)umsg.Channel; await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query).ConfigureAwait(false);
if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query).ConfigureAwait(false);
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
{ {
umsg.DeleteAfter(10); Context.Message.DeleteAfter(10);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SoundCloudQueue(IUserMessage umsg, [Remainder] string query) public async Task SoundCloudQueue([Remainder] string query)
{ {
var channel = (ITextChannel)umsg.Channel; await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, query, musicType: MusicType.Soundcloud).ConfigureAwait(false);
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages)
{ {
umsg.DeleteAfter(10); Context.Message.DeleteAfter(10);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ListQueue(IUserMessage umsg, int page = 1) public async Task ListQueue(int page = 1)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
{ {
await channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false);
return; return;
} }
if (page <= 0) if (page <= 0)
@ -181,7 +176,7 @@ namespace NadekoBot.Modules.Music
var currentSong = musicPlayer.CurrentSong; var currentSong = musicPlayer.CurrentSong;
if (currentSong == null) if (currentSong == null)
{ {
await channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("🎵 No active music player.").ConfigureAwait(false);
return; return;
} }
@ -202,7 +197,7 @@ namespace NadekoBot.Modules.Music
.Select(v => $"`{++number}.` {v.PrettyFullName}"))) .Select(v => $"`{++number}.` {v.PrettyFullName}")))
.WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " + .WithFooter(ef => ef.WithText($"{musicPlayer.PrettyVolume} | {musicPlayer.Playlist.Count} " +
$"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " + $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {total.Minutes}m {total.Seconds}s | " +
(musicPlayer.FairPlay? "✔fairplay" : "✖fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit"))) (musicPlayer.FairPlay ? "✔fairplay" : "✖fairplay") + $" | " + (maxPlaytime == 0 ? "unlimited" : $"{maxPlaytime}s limit")))
.WithOkColor(); .WithOkColor();
if (musicPlayer.RepeatSong) if (musicPlayer.RepeatSong)
@ -217,17 +212,15 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
{ {
embed.WithTitle("🎵 Song queue is full!"); embed.WithTitle("🎵 Song queue is full!");
} }
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task NowPlaying(IUserMessage umsg) public async Task NowPlaying()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
var currentSong = musicPlayer.CurrentSong; var currentSong = musicPlayer.CurrentSong;
if (currentSong == null) if (currentSong == null)
@ -237,99 +230,98 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
var embed = new EmbedBuilder().WithOkColor() var embed = new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Now Playing").WithMusicIcon()) .WithAuthor(eab => eab.WithName("Now Playing").WithMusicIcon())
.WithDescription(currentSong.PrettyName) .WithDescription(currentSong.PrettyName)
.WithThumbnail(tn => tn.Url = currentSong.Thumbnail) .WithThumbnailUrl(currentSong.Thumbnail)
.WithFooter(ef => ef.WithText(musicPlayer.PrettyVolume + " | " + currentSong.PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}")); .WithFooter(ef => ef.WithText(musicPlayer.PrettyVolume + " | " + currentSong.PrettyFullTime + $" | {currentSong.PrettyProvider} | {currentSong.QueuerName}"));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Volume(IUserMessage umsg, int val) public async Task Volume(int val)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return; return;
if (val < 0) if (val < 0)
return; return;
var volume = musicPlayer.SetVolume(val); var volume = musicPlayer.SetVolume(val);
await channel.SendConfirmAsync($"🎵 Volume set to {volume}%").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🎵 Volume set to {volume}%").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Defvol(IUserMessage umsg, [Remainder] int val) public async Task Defvol([Remainder] int val)
{ {
var channel = (ITextChannel)umsg.Channel;
if (val < 0 || val > 100) if (val < 0 || val > 100)
{ {
await channel.SendErrorAsync("Volume number invalid. Must be between 0 and 100").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Volume number invalid. Must be between 0 and 100").ConfigureAwait(false);
return; return;
} }
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
uow.GuildConfigs.For(channel.Guild.Id, set => set).DefaultMusicVolume = val / 100.0f; uow.GuildConfigs.For(Context.Guild.Id, set => set).DefaultMusicVolume = val / 100.0f;
uow.Complete(); uow.Complete();
} }
await channel.SendConfirmAsync($"🎵 Default volume set to {val}%").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🎵 Default volume set to {val}%").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ShufflePlaylist(IUserMessage umsg) public async Task ShufflePlaylist()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return; return;
if (musicPlayer.Playlist.Count < 2) if (musicPlayer.Playlist.Count < 2)
{ {
await channel.SendErrorAsync("💢 Not enough songs in order to perform the shuffle.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("💢 Not enough songs in order to perform the shuffle.").ConfigureAwait(false);
return; return;
} }
musicPlayer.Shuffle(); musicPlayer.Shuffle();
await channel.SendConfirmAsync("🎵 Songs shuffled.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🎵 Songs shuffled.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Playlist(IUserMessage umsg, [Remainder] string playlist) public async Task Playlist([Remainder] string playlist)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = playlist; var arg = playlist;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild) if (((IGuildUser)Context.User).VoiceChannel?.Guild != Context.Guild)
{ {
await channel.SendErrorAsync("💢 You need to be in a **voice channel** on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("💢 You need to be in a **voice channel** on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining it.").ConfigureAwait(false);
return; return;
} }
var plId = (await NadekoBot.Google.GetPlaylistIdsByKeywordsAsync(arg).ConfigureAwait(false)).FirstOrDefault(); var plId = (await NadekoBot.Google.GetPlaylistIdsByKeywordsAsync(arg).ConfigureAwait(false)).FirstOrDefault();
if (plId == null) if (plId == null)
{ {
await channel.SendErrorAsync("No search results for that query."); await Context.Channel.SendErrorAsync("No search results for that query.");
return; return;
} }
var ids = await NadekoBot.Google.GetPlaylistTracksAsync(plId, 500).ConfigureAwait(false); var ids = await NadekoBot.Google.GetPlaylistTracksAsync(plId, 500).ConfigureAwait(false);
if (!ids.Any()) if (!ids.Any())
{ {
await channel.SendErrorAsync($"🎵 Failed to find any songs.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"🎵 Failed to find any songs.").ConfigureAwait(false);
return; return;
} }
var count = ids.Count(); var count = ids.Count();
var msg = await channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false); var msg = await Context.Channel.SendMessageAsync($"🎵 Attempting to queue **{count}** songs".SnPl(count) + "...").ConfigureAwait(false);
var cancelSource = new CancellationTokenSource(); var cancelSource = new CancellationTokenSource();
var gusr = (IGuildUser)umsg.Author; var gusr = (IGuildUser)Context.User;
while (ids.Any() && !cancelSource.IsCancellationRequested) while (ids.Any() && !cancelSource.IsCancellationRequested)
{ {
@ -339,7 +331,7 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
return; return;
try try
{ {
await QueueSong(gusr, channel, gusr.VoiceChannel, id, true).ConfigureAwait(false); await QueueSong(gusr, (ITextChannel)Context.Channel, gusr.VoiceChannel, id, true).ConfigureAwait(false);
} }
catch (SongNotFoundException) { } catch (SongNotFoundException) { }
catch { try { cancelSource.Cancel(); } catch { } } catch { try { cancelSource.Cancel(); } catch { } }
@ -354,9 +346,9 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SoundCloudPl(IUserMessage umsg, [Remainder] string pl) public async Task SoundCloudPl([Remainder] string pl)
{ {
var channel = (ITextChannel)umsg.Channel;
pl = pl?.Trim(); pl = pl?.Trim();
if (string.IsNullOrWhiteSpace(pl)) if (string.IsNullOrWhiteSpace(pl))
@ -365,10 +357,10 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false))["tracks"].ToObject<SoundCloudVideo[]>(); var scvids = JObject.Parse(await http.GetStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Credentials.SoundCloudClientId}").ConfigureAwait(false))["tracks"].ToObject<SoundCloudVideo[]>();
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false); await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, scvids[0].TrackLink).ConfigureAwait(false);
MusicPlayer mp; MusicPlayer mp;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out mp)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out mp))
return; return;
foreach (var svideo in scvids.Skip(1)) foreach (var svideo in scvids.Skip(1))
@ -382,7 +374,7 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
Uri = svideo.StreamLink, Uri = svideo.StreamLink,
ProviderType = MusicType.Normal, ProviderType = MusicType.Normal,
Query = svideo.TrackLink, Query = svideo.TrackLink,
}), ((IGuildUser)umsg.Author).Username); }), ((IGuildUser)Context.User).Username);
} }
catch (PlaylistFullException) { break; } catch (PlaylistFullException) { break; }
} }
@ -392,9 +384,9 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task LocalPl(IUserMessage umsg, [Remainder] string directory) public async Task LocalPl([Remainder] string directory)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = directory; var arg = directory;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;
@ -403,12 +395,12 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
var dir = new DirectoryInfo(arg); var dir = new DirectoryInfo(arg);
var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories) var fileEnum = dir.GetFiles("*", SearchOption.AllDirectories)
.Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System)); .Where(x => !x.Attributes.HasFlag(FileAttributes.Hidden | FileAttributes.System));
var gusr = (IGuildUser)umsg.Author; var gusr = (IGuildUser)Context.User;
foreach (var file in fileEnum) foreach (var file in fileEnum)
{ {
try try
{ {
await QueueSong(gusr, channel, gusr.VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false); await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, file.FullName, true, MusicType.Local).ConfigureAwait(false);
} }
catch (PlaylistFullException) catch (PlaylistFullException)
{ {
@ -416,49 +408,49 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
} }
catch { } catch { }
} }
await channel.SendConfirmAsync("🎵 Directory queue complete.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🎵 Directory queue complete.").ConfigureAwait(false);
} }
catch { } catch { }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Radio(IUserMessage umsg, string radio_link) public async Task Radio(string radio_link)
{ {
var channel = (ITextChannel)umsg.Channel;
if (((IGuildUser)umsg.Author).VoiceChannel?.Guild != channel.Guild) if (((IGuildUser)Context.User).VoiceChannel?.Guild != Context.Guild)
{ {
await channel.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining it.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining it.").ConfigureAwait(false);
return; return;
} }
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false); await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, radio_link, musicType: MusicType.Radio).ConfigureAwait(false);
if (channel.Guild.GetCurrentUser().GetPermissions(channel).ManageMessages) if ((await Context.Guild.GetCurrentUserAsync()).GetPermissions((IGuildChannel)Context.Channel).ManageMessages)
{ {
umsg.DeleteAfter(10); Context.Message.DeleteAfter(10);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task Local(IUserMessage umsg, [Remainder] string path) public async Task Local([Remainder] string path)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = path; var arg = path;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;
await QueueSong(((IGuildUser)umsg.Author), channel, ((IGuildUser)umsg.Author).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false); await QueueSong(((IGuildUser)Context.User), (ITextChannel)Context.Channel, ((IGuildUser)Context.User).VoiceChannel, path, musicType: MusicType.Local).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Move(IUserMessage umsg) public async Task Move()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
var voiceChannel = ((IGuildUser)umsg.Author).VoiceChannel; var voiceChannel = ((IGuildUser)Context.User).VoiceChannel;
if (voiceChannel == null || voiceChannel.Guild != channel.Guild || !MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (voiceChannel == null || voiceChannel.Guild != Context.Guild || !MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
await musicPlayer.MoveToVoiceChannel(voiceChannel); await musicPlayer.MoveToVoiceChannel(voiceChannel);
} }
@ -466,55 +458,56 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(0)] [Priority(0)]
public async Task Remove(IUserMessage umsg, int num) public async Task Remove(int num)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return;
if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return;
musicPlayer.SongRemoved += async (song) =>
{ {
return; try
} {
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) var embed = new EmbedBuilder()
return; .WithAuthor(eab => eab.WithName("Removed song #" + num).WithMusicIcon())
if (num <= 0 || num > musicPlayer.Playlist.Count) .WithDescription(song.PrettyName)
return; .WithFooter(ef => ef.WithText(song.PrettyInfo))
var song = (musicPlayer.Playlist as List<Song>)?[num - 1]; .WithErrorColor();
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
}
catch { }
};
musicPlayer.RemoveSongAt(num - 1); musicPlayer.RemoveSongAt(num - 1);
var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName("Song Removed!").WithMusicIcon())
.AddField(fb => fb.WithName("**Song Position**").WithValue($"#{num}").WithIsInline(true))
.AddField(fb => fb.WithName("**Song Name**").WithValue(song.PrettyName).WithIsInline(true))
.WithFooter(ef => ef.WithText($"{song.PrettyProvider} | {song.QueuerName}"))
.WithErrorColor();
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public async Task Remove(IUserMessage umsg, string all) public async Task Remove(string all)
{ {
var channel = (ITextChannel)umsg.Channel;
if (all.Trim().ToUpperInvariant() != "ALL") if (all.Trim().ToUpperInvariant() != "ALL")
return; return;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) return; if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer)) return;
musicPlayer.ClearQueue(); musicPlayer.ClearQueue();
await channel.SendConfirmAsync($"🎵 Queue cleared!").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🎵 Queue cleared!").ConfigureAwait(false);
return; return;
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task MoveSong(IUserMessage umsg, [Remainder] string fromto) public async Task MoveSong([Remainder] string fromto)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
{ {
return; return;
} }
@ -530,7 +523,7 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
!int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 || !int.TryParse(fromtoArr[1], out n2) || n1 < 1 || n2 < 1 || n1 == n2 ||
n1 > playlist.Count || n2 > playlist.Count) n1 > playlist.Count || n2 > playlist.Count)
{ {
await channel.SendErrorAsync("Invalid input.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Invalid input.").ConfigureAwait(false);
return; return;
} }
@ -540,41 +533,44 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
playlist.RemoveAt(nn1); playlist.RemoveAt(nn1);
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.WithTitle(s.SongInfo.Title.TrimTo(70)) .WithTitle($"{s.SongInfo.Title.TrimTo(70)}")
.WithUrl(s.SongInfo.Query) .WithUrl($"{s.SongInfo.Query}")
.WithAuthor(eab => eab.WithName("Song Moved").WithMusicIcon()) .WithAuthor(eab => eab.WithName("Song Moved").WithIconUrl("https://cdn.discordapp.com/attachments/155726317222887425/258605269972549642/music1.png"))
.AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true)) .AddField(fb => fb.WithName("**From Position**").WithValue($"#{n1}").WithIsInline(true))
.AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true)) .AddField(fb => fb.WithName("**To Position**").WithValue($"#{n2}").WithIsInline(true))
.WithFooter(ef => ef.WithText($"{s.PrettyProvider} | {s.QueuerName}")) .WithColor(NadekoBot.OkColor);
.WithOkColor(); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
//await channel.SendConfirmAsync($"🎵Moved {s.PrettyName} `from #{n1} to #{n2}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SetMaxQueue(IUserMessage umsg, uint size) public async Task SetMaxQueue(uint size)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
musicPlayer.MaxQueueSize = size; musicPlayer.MaxQueueSize = size;
await channel.SendConfirmAsync($"🎵 Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}."); await Context.Channel.SendConfirmAsync($"🎵 Max queue set to {(size == 0 ? ("unlimited") : size + " tracks")}.");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SetMaxPlaytime(IUserMessage imsg, uint seconds) public async Task SetMaxPlaytime(uint seconds)
{ {
if (seconds < 15 && seconds != 0) if (seconds < 15 && seconds != 0)
return; return;
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer))
return; return;
musicPlayer.MaxPlaytimeSeconds = seconds; musicPlayer.MaxPlaytimeSeconds = seconds;
if(seconds == 0) if (seconds == 0)
await channel.SendConfirmAsync($"🎵 Max playtime has no limit now."); await channel.SendConfirmAsync($"🎵 Max playtime has no limit now.");
else else
await channel.SendConfirmAsync($"🎵 Max playtime set to {seconds} seconds."); await channel.SendConfirmAsync($"🎵 Max playtime set to {seconds} seconds.");
@ -582,11 +578,11 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ReptCurSong(IUserMessage umsg) public async Task ReptCurSong()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
var currentSong = musicPlayer.CurrentSong; var currentSong = musicPlayer.CurrentSong;
if (currentSong == null) if (currentSong == null)
@ -594,36 +590,35 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
var currentValue = musicPlayer.ToggleRepeatSong(); var currentValue = musicPlayer.ToggleRepeatSong();
if (currentValue) if (currentValue)
await channel.EmbedAsync(new EmbedBuilder() await Context.Channel.EmbedAsync(new EmbedBuilder()
.WithOkColor() .WithOkColor()
.WithAuthor(eab => eab.WithMusicIcon().WithName("🔂 Repeating track")) .WithAuthor(eab => eab.WithMusicIcon().WithName("🔂 Repeating track"))
.WithDescription(currentSong.PrettyName) .WithDescription(currentSong.PrettyName)
.WithFooter(ef => ef.WithText(currentSong.PrettyInfo)) .WithFooter(ef => ef.WithText(currentSong.PrettyInfo))).ConfigureAwait(false);
.Build()).ConfigureAwait(false);
else else
await channel.SendConfirmAsync($"🔂 Current track repeat stopped.") await Context.Channel.SendConfirmAsync($"🔂 Current track repeat stopped.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task RepeatPl(IUserMessage umsg) public async Task RepeatPl()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
var currentValue = musicPlayer.ToggleRepeatPlaylist(); var currentValue = musicPlayer.ToggleRepeatPlaylist();
await channel.SendConfirmAsync($"🔁 Repeat playlist {(currentValue ? "**enabled**." : "**disabled**.")}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🔁 Repeat playlist {(currentValue ? "**enabled**." : "**disabled**.")}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Save(IUserMessage umsg, [Remainder] string name) public async Task Save([Remainder] string name)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
var curSong = musicPlayer.CurrentSong; var curSong = musicPlayer.CurrentSong;
@ -643,23 +638,21 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
playlist = new MusicPlaylist playlist = new MusicPlaylist
{ {
Name = name, Name = name,
Author = umsg.Author.Username, Author = Context.User.Username,
AuthorId = umsg.Author.Id, AuthorId = Context.User.Id,
Songs = songs, Songs = songs,
}; };
uow.MusicPlaylists.Add(playlist); uow.MusicPlaylists.Add(playlist);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync(($"🎵 Saved playlist as **{name}**, ID: {playlist.Id}.")).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(($"🎵 Saved playlist as **{name}**, ID: {playlist.Id}.")).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Load(IUserMessage umsg, [Remainder] int id) public async Task Load([Remainder] int id)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlaylist mpl; MusicPlaylist mpl;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
@ -668,18 +661,17 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
if (mpl == null) if (mpl == null)
{ {
await channel.SendErrorAsync("Can't find playlist with that ID.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Can't find playlist with that ID.").ConfigureAwait(false);
return; return;
} }
IUserMessage msg = null; IUserMessage msg = null;
try { msg = await channel.SendMessageAsync($"🎶 Attempting to load **{mpl.Songs.Count}** songs...").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); } try { msg = await Context.Channel.SendMessageAsync($"🎶 Attempting to load **{mpl.Songs.Count}** songs...").ConfigureAwait(false); } catch (Exception ex) { _log.Warn(ex); }
var usr = (IGuildUser)umsg.Author;
foreach (var item in mpl.Songs) foreach (var item in mpl.Songs)
{ {
var usr = (IGuildUser)Context.User;
try try
{ {
await QueueSong(usr, channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false); await QueueSong(usr, (ITextChannel)Context.Channel, usr.VoiceChannel, item.Query, true, item.ProviderType).ConfigureAwait(false);
} }
catch (SongNotFoundException) { } catch (SongNotFoundException) { }
catch { break; } catch { break; }
@ -690,9 +682,9 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Playlists(IUserMessage umsg, [Remainder] int num = 1) public async Task Playlists([Remainder] int num = 1)
{ {
var channel = (ITextChannel)umsg.Channel;
if (num <= 0) if (num <= 0)
return; return;
@ -708,16 +700,16 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
.WithAuthor(eab => eab.WithName($"Page {num} of Saved Playlists").WithMusicIcon()) .WithAuthor(eab => eab.WithName($"Page {num} of Saved Playlists").WithMusicIcon())
.WithDescription(string.Join("\n", playlists.Select(r => $"`#{r.Id}` - **{r.Name}** by *{r.Author}* ({r.Songs.Count} songs)"))) .WithDescription(string.Join("\n", playlists.Select(r => $"`#{r.Id}` - **{r.Name}** by *{r.Author}* ({r.Songs.Count} songs)")))
.WithOkColor(); .WithOkColor();
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
//todo only author or owner //todo only author or owner
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task DeletePlaylist(IUserMessage umsg, [Remainder] int id) public async Task DeletePlaylist([Remainder] int id)
{ {
var channel = (ITextChannel)umsg.Channel;
bool success = false; bool success = false;
MusicPlaylist pl = null; MusicPlaylist pl = null;
@ -729,7 +721,7 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
if (pl != null) if (pl != null)
{ {
if (NadekoBot.Credentials.IsOwner(umsg.Author) || pl.AuthorId == umsg.Author.Id) if (NadekoBot.Credentials.IsOwner(Context.User) || pl.AuthorId == Context.User.Id)
{ {
uow.MusicPlaylists.Remove(pl); uow.MusicPlaylists.Remove(pl);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
@ -741,9 +733,9 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
} }
if (!success) if (!success)
await channel.SendErrorAsync("Failed to delete that playlist. It either doesn't exist, or you are not its author.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed to delete that playlist. It either doesn't exist, or you are not its author.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync("🗑 Playlist successfully **deleted**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🗑 Playlist successfully **deleted**.").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -753,14 +745,12 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Goto(IUserMessage umsg, int time) public async Task Goto(int time)
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
if (((IGuildUser)umsg.Author).VoiceChannel != musicPlayer.PlaybackVoiceChannel) if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
return; return;
if (time < 0) if (time < 0)
@ -785,22 +775,21 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
if (seconds.Length == 1) if (seconds.Length == 1)
seconds = "0" + seconds; seconds = "0" + seconds;
await channel.SendConfirmAsync($"Skipped to `{minutes}:{seconds}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Skipped to `{minutes}:{seconds}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Autoplay(IUserMessage umsg) public async Task Autoplay()
{ {
var channel = (ITextChannel)umsg.Channel;
MusicPlayer musicPlayer; MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(channel.Guild.Id, out musicPlayer)) if (!MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
return; return;
if (!musicPlayer.ToggleAutoplay()) if (!musicPlayer.ToggleAutoplay())
await channel.SendConfirmAsync("❌ Autoplay disabled.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("❌ Autoplay disabled.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync("✅ Autoplay enabled.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✅ Autoplay enabled.").ConfigureAwait(false);
} }
public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal) public static async Task QueueSong(IGuildUser queuer, ITextChannel textCh, IVoiceChannel voiceCh, string query, bool silent = false, MusicType musicType = MusicType.Normal)
@ -808,7 +797,7 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
if (voiceCh == null || voiceCh.Guild != textCh.Guild) if (voiceCh == null || voiceCh.Guild != textCh.Guild)
{ {
if (!silent) if (!silent)
await textCh.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice channel, try rejoining.").ConfigureAwait(false); await textCh.SendErrorAsync("💢 You need to be in a voice channel on this server.\n If you are already in a voice (ITextChannel)Context.Channel, try rejoining.").ConfigureAwait(false);
throw new ArgumentNullException(nameof(voiceCh)); throw new ArgumentNullException(nameof(voiceCh));
} }
if (string.IsNullOrWhiteSpace(query) || query.Length < 3) if (string.IsNullOrWhiteSpace(query) || query.Length < 3)
@ -822,30 +811,28 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
vol = uow.GuildConfigs.For(textCh.Guild.Id, set => set).DefaultMusicVolume; vol = uow.GuildConfigs.For(textCh.Guild.Id, set => set).DefaultMusicVolume;
} }
var mp = new MusicPlayer(voiceCh, vol); var mp = new MusicPlayer(voiceCh, vol);
IUserMessage playingMessage = null;
IUserMessage finishedMessage = null; IUserMessage lastFinishedMessage = null;
mp.OnCompleted += async (s, song) => mp.OnCompleted += async (s, song) =>
{ {
try try
{ {
if (finishedMessage != null) if (lastFinishedMessage != null)
finishedMessage.DeleteAfter(0); lastFinishedMessage.DeleteAfter(0);
finishedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor() lastFinishedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Finished Song").WithMusicIcon()) .WithAuthor(eab => eab.WithName("Finished Song").WithMusicIcon())
.WithDescription(song.PrettyName) .WithDescription(song.PrettyName)
.WithFooter(ef => ef.WithText(song.PrettyInfo)) .WithFooter(ef => ef.WithText(song.PrettyInfo)))
.Build()) .ConfigureAwait(false);
.ConfigureAwait(false);
if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube") if (mp.Autoplay && mp.Playlist.Count == 0 && song.SongInfo.Provider == "YouTube")
{ {
await QueueSong(queuer.Guild.GetCurrentUser(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false); await QueueSong(await queuer.Guild.GetCurrentUserAsync(), textCh, voiceCh, (await NadekoBot.Google.GetRelatedVideosAsync(song.SongInfo.Query, 4)).ToList().Shuffle().FirstOrDefault(), silent, musicType).ConfigureAwait(false);
} }
} }
catch { } catch { }
}; };
IUserMessage playingMessage = null;
mp.OnStarted += async (player, song) => mp.OnStarted += async (player, song) =>
{ {
@ -861,31 +848,22 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
playingMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor() playingMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Playing Song").WithMusicIcon()) .WithAuthor(eab => eab.WithName("Playing Song").WithMusicIcon())
.WithDescription(song.PrettyName) .WithDescription(song.PrettyName)
.WithFooter(ef => ef.WithText(song.PrettyInfo)) .WithFooter(ef => ef.WithText(song.PrettyInfo)))
.Build())
.ConfigureAwait(false); .ConfigureAwait(false);
} }
catch { } catch { }
}; };
mp.OnPauseChanged += async (paused) => mp.OnPauseChanged += async (paused) =>
{
try
{
IUserMessage pauseMessage = null;
if (paused)
{ {
pauseMessage = await textCh.SendConfirmAsync("🎵 Music playback **paused**.").ConfigureAwait(false); try
} {
else if (paused)
{ await textCh.SendConfirmAsync("🎵 Music playback **paused**.").ConfigureAwait(false);
pauseMessage = await textCh.SendConfirmAsync("🎵 Music playback **resumed**.").ConfigureAwait(false); else
} await textCh.SendConfirmAsync("🎵 Music playback **resumed**.").ConfigureAwait(false);
if (pauseMessage != null) }
pauseMessage.DeleteAfter(15); catch { }
} };
catch { }
};
return mp; return mp;
}); });
Song resolvedSong; Song resolvedSong;
@ -912,9 +890,8 @@ $"{("tracks".SnPl(musicPlayer.Playlist.Count))} | {(int)total.TotalHours}h {tota
var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor() var queuedMessage = await textCh.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName("Queued Song #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon()) .WithAuthor(eab => eab.WithName("Queued Song #" + (musicPlayer.Playlist.Count + 1)).WithMusicIcon())
.WithDescription($"{resolvedSong.PrettyName}\nQueue ") .WithDescription($"{resolvedSong.PrettyName}\nQueue ")
.WithThumbnail(tn => tn.Url = resolvedSong.Thumbnail) .WithThumbnailUrl(resolvedSong.Thumbnail)
.WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)) .WithFooter(ef => ef.WithText(resolvedSong.PrettyProvider)))
.Build())
.ConfigureAwait(false); .ConfigureAwait(false);
if (queuedMessage != null) if (queuedMessage != null)
queuedMessage.DeleteAfter(10); queuedMessage.DeleteAfter(10);

View File

@ -11,22 +11,18 @@ using System.Text.RegularExpressions;
using System.Xml.Linq; using System.Xml.Linq;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Xml; using System.Xml;
using System.Threading;
using System.Collections.Concurrent;
namespace NadekoBot.Modules.NSFW namespace NadekoBot.Modules.NSFW
{ {
[NadekoModule("NSFW", "~")] [NadekoModule("NSFW", "~")]
public class NSFW : DiscordModule public class NSFW : DiscordModule
{ {
public NSFW() : base() private static ConcurrentDictionary<ulong, Timer> AutoHentaiTimers { get; } = new ConcurrentDictionary<ulong, Timer>();
{
}
[NadekoCommand, Usage, Description, Aliases] private async Task InternalHentai(IMessageChannel channel, string tag, bool noError)
[RequireContext(ContextType.Guild)]
public async Task Hentai(IUserMessage umsg, [Remainder] string tag = null)
{ {
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
tag = "rating%3Aexplicit+" + tag; tag = "rating%3Aexplicit+" + tag;
@ -52,18 +48,66 @@ namespace NadekoBot.Modules.NSFW
} }
var link = await provider.ConfigureAwait(false); var link = await provider.ConfigureAwait(false);
if (string.IsNullOrWhiteSpace(link)) if (string.IsNullOrWhiteSpace(link))
await channel.SendErrorAsync("No results found.").ConfigureAwait(false); {
else if (noError)
await channel.SendMessageAsync(link).ConfigureAwait(false); await channel.SendErrorAsync("No results found.").ConfigureAwait(false);
return;
}
await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithImageUrl(link)
.WithDescription("Tag: " + tag)).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
public Task Hentai([Remainder] string tag = null) =>
InternalHentai(Context.Channel, tag, false);
[NadekoCommand, Usage, Description, Aliases]
public async Task AutoHentai(int interval = 0, string tags = null)
{
Timer t;
if (interval == 0)
{
if (AutoHentaiTimers.TryRemove(Context.Channel.Id, out t))
{
t.Change(Timeout.Infinite, Timeout.Infinite); //proper way to disable the timer
await Context.Channel.SendConfirmAsync("Autohentai stopped.").ConfigureAwait(false);
}
return;
}
if (interval < 20)
return;
var tagsArr = tags?.Split('|');
t = new Timer(async (state) =>
{
try
{
if (tagsArr == null || tagsArr.Length == 0)
await InternalHentai(Context.Channel, null, true).ConfigureAwait(false);
else
await InternalHentai(Context.Channel, tagsArr[new NadekoRandom().Next(0, tagsArr.Length)], true);
}
catch { }
}, null, interval * 1000, interval * 1000);
AutoHentaiTimers.AddOrUpdate(Context.Channel.Id, t, (key, old) =>
{
old.Change(Timeout.Infinite, Timeout.Infinite);
return t;
});
await Context.Channel.SendConfirmAsync($"Autohentai started. Reposting every {interval}s with one of the following tags:\n{string.Join(", ", tagsArr)}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task HentaiBomb([Remainder] string tag = null)
public async Task HentaiBomb(IUserMessage umsg, [Remainder] string tag = null)
{ {
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
tag = "rating%3Aexplicit+" + tag; tag = "rating%3Aexplicit+" + tag;
@ -72,90 +116,74 @@ namespace NadekoBot.Modules.NSFW
GetKonachanImageLink(tag), GetKonachanImageLink(tag),
GetYandereImageLink(tag)).ConfigureAwait(false); GetYandereImageLink(tag)).ConfigureAwait(false);
if (links.All(l => l == null)) var linksEnum = links?.Where(l => l != null);
if (links == null || !linksEnum.Any())
{ {
await channel.SendErrorAsync("No results found.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No results found.").ConfigureAwait(false);
return; return;
} }
await channel.SendMessageAsync(String.Join("\n\n", links)).ConfigureAwait(false); await Context.Channel.SendMessageAsync(String.Join("\n\n", linksEnum)).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Danbooru([Remainder] string tag = null)
public async Task Danbooru(IUserMessage umsg, [Remainder] string tag = null)
{ {
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
var url = await GetDanbooruImageLink(tag).ConfigureAwait(false); var url = await GetDanbooruImageLink(tag).ConfigureAwait(false);
if (url == null) if (url == null)
await channel.SendErrorAsync(umsg.Author.Mention + " No results."); await Context.Channel.SendErrorAsync(Context.User.Mention + " No results.");
else else
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(umsg.Author.Mention + " " + tag) .WithDescription(Context.User.Mention + " " + tag)
.WithImageUrl(url) .WithImageUrl(url)
.WithFooter(efb => efb.WithText("Danbooru")) .WithFooter(efb => efb.WithText("Danbooru"))).ConfigureAwait(false);
.Build()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public Task Yandere([Remainder] string tag = null)
public Task Yandere(IUserMessage umsg, [Remainder] string tag = null) => Searches.Searches.InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Yandere);
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Yandere);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public Task Konachan([Remainder] string tag = null)
public Task Konachan(IUserMessage umsg, [Remainder] string tag = null) => Searches.Searches.InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Konachan);
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Konachan);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public Task Gelbooru([Remainder] string tag = null)
public Task Gelbooru(IUserMessage umsg, [Remainder] string tag = null) => Searches.Searches.InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Gelbooru);
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Gelbooru);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public Task Rule34([Remainder] string tag = null)
public Task Rule34(IUserMessage umsg, [Remainder] string tag = null) => Searches.Searches.InternalDapiCommand(Context.Message, tag, Searches.Searches.DapiSearchType.Rule34);
=> Searches.Searches.InternalDapiCommand(umsg, tag, Searches.Searches.DapiSearchType.Rule34);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task E621([Remainder] string tag = null)
public async Task E621(IUserMessage umsg, [Remainder] string tag = null)
{ {
var channel = (ITextChannel)umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
var url = await GetE621ImageLink(tag).ConfigureAwait(false); var url = await GetE621ImageLink(tag).ConfigureAwait(false);
if (url == null) if (url == null)
await channel.SendErrorAsync(umsg.Author.Mention + " No results."); await Context.Channel.SendErrorAsync(Context.User.Mention + " No results.");
else else
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(umsg.Author.Mention + " " + tag) .WithDescription(Context.User.Mention + " " + tag)
.WithImageUrl(url) .WithImageUrl(url)
.WithFooter(efb => efb.WithText("e621")) .WithFooter(efb => efb.WithText("e621"))).ConfigureAwait(false);
.Build()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Cp()
public async Task Cp(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel; await Context.Channel.SendMessageAsync("http://i.imgur.com/MZkY1md.jpg").ConfigureAwait(false);
await channel.SendMessageAsync("http://i.imgur.com/MZkY1md.jpg").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Boobs()
public async Task Boobs(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
JToken obj; JToken obj;
@ -163,20 +191,17 @@ namespace NadekoBot.Modules.NSFW
{ {
obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new NadekoRandom().Next(0, 10229) }").ConfigureAwait(false))[0]; obj = JArray.Parse(await http.GetStringAsync($"http://api.oboobs.ru/boobs/{ new NadekoRandom().Next(0, 10229) }").ConfigureAwait(false))[0];
} }
await channel.SendMessageAsync($"http://media.oboobs.ru/{ obj["preview"].ToString() }").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"http://media.oboobs.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync(ex.Message).ConfigureAwait(false); await Context.Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Butts()
public async Task Butts(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
JToken obj; JToken obj;
@ -184,11 +209,11 @@ namespace NadekoBot.Modules.NSFW
{ {
obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new NadekoRandom().Next(0, 4222) }").ConfigureAwait(false))[0]; obj = JArray.Parse(await http.GetStringAsync($"http://api.obutts.ru/butts/{ new NadekoRandom().Next(0, 4222) }").ConfigureAwait(false))[0];
} }
await channel.SendMessageAsync($"http://media.obutts.ru/{ obj["preview"].ToString() }").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"http://media.obutts.ru/{ obj["preview"].ToString() }").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync(ex.Message).ConfigureAwait(false); await Context.Channel.SendErrorAsync(ex.Message).ConfigureAwait(false);
} }
} }

View File

@ -21,7 +21,7 @@ namespace NadekoBot.Modules.Permissions
} }
[Group] [Group]
public class BlacklistCommands public class BlacklistCommands : ModuleBase
{ {
public static ConcurrentHashSet<BlacklistItem> BlacklistedItems { get; set; } = new ConcurrentHashSet<BlacklistItem>(); public static ConcurrentHashSet<BlacklistItem> BlacklistedItems { get; set; } = new ConcurrentHashSet<BlacklistItem>();
@ -35,33 +35,31 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public Task UserBlacklist(IUserMessage imsg, AddRemove action, ulong id) public Task UserBlacklist(AddRemove action, ulong id)
=> Blacklist(imsg, action, id, BlacklistType.User); => Blacklist(action, id, BlacklistType.User);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public Task UserBlacklist(IUserMessage imsg, AddRemove action, IUser usr) public Task UserBlacklist(AddRemove action, IUser usr)
=> Blacklist(imsg, action, usr.Id, BlacklistType.User); => Blacklist(action, usr.Id, BlacklistType.User);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public Task ChannelBlacklist(IUserMessage imsg, AddRemove action, ulong id) public Task ChannelBlacklist(AddRemove action, ulong id)
=> Blacklist(imsg, action, id, BlacklistType.Channel); => Blacklist(action, id, BlacklistType.Channel);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public Task ServerBlacklist(IUserMessage imsg, AddRemove action, ulong id) public Task ServerBlacklist(AddRemove action, ulong id)
=> Blacklist(imsg, action, id, BlacklistType.Server); => Blacklist(action, id, BlacklistType.Server);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[OwnerOnly] [OwnerOnly]
public Task ServerBlacklist(IUserMessage imsg, AddRemove action, IGuild guild) public Task ServerBlacklist(AddRemove action, IGuild guild)
=> Blacklist(imsg, action, guild.Id, BlacklistType.Server); => Blacklist(action, guild.Id, BlacklistType.Server);
private async Task Blacklist(IUserMessage imsg, AddRemove action, ulong id, BlacklistType type) private async Task Blacklist(AddRemove action, ulong id, BlacklistType type)
{ {
var channel = imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
if (action == AddRemove.Add) if (action == AddRemove.Add)
@ -106,9 +104,9 @@ namespace NadekoBot.Modules.Permissions
} }
if(action == AddRemove.Add) if(action == AddRemove.Add)
await channel.SendConfirmAsync($"Blacklisted a `{type}` with id `{id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Blacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
else else
await channel.SendConfirmAsync($"Unblacklisted a `{type}` with id `{id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Unblacklisted a `{type}` with id `{id}`").ConfigureAwait(false);
} }
} }
} }

View File

@ -21,24 +21,21 @@ namespace NadekoBot.Modules.Permissions
} }
[Group] [Group]
public class CmdCdsCommands public class CmdCdsCommands : ModuleBase
{ {
public static ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> commandCooldowns { get; } public static ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>> commandCooldowns { get; }
private static ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> activeCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>(); private static ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>> activeCooldowns { get; } = new ConcurrentDictionary<ulong, ConcurrentHashSet<ActiveCooldown>>();
static CmdCdsCommands() static CmdCdsCommands()
{ {
using (var uow = DbHandler.UnitOfWork()) var configs = NadekoBot.AllGuildConfigs;
{ commandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(configs.ToDictionary(k => k.GuildId, v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
var configs = NadekoBot.AllGuildConfigs;
commandCooldowns = new ConcurrentDictionary<ulong, ConcurrentHashSet<CommandCooldown>>(configs.ToDictionary(k => k.GuildId, v => new ConcurrentHashSet<CommandCooldown>(v.CommandCooldowns)));
}
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task CmdCooldown(IUserMessage imsg, Command command, int secs) public async Task CmdCooldown(CommandInfo command, int secs)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
if (secs < 0 || secs > 3600) if (secs < 0 || secs > 3600)
{ {
await channel.SendErrorAsync("Invalid second parameter. (Must be a number between 0 and 3600)").ConfigureAwait(false); await channel.SendErrorAsync("Invalid second parameter. (Must be a number between 0 and 3600)").ConfigureAwait(false);
@ -50,13 +47,13 @@ namespace NadekoBot.Modules.Permissions
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.CommandCooldowns)); var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.CommandCooldowns));
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>()); var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
config.CommandCooldowns.RemoveWhere(cc => cc.CommandName == command.Text.ToLowerInvariant()); config.CommandCooldowns.RemoveWhere(cc => cc.CommandName == command.Aliases.First().ToLowerInvariant());
localSet.RemoveWhere(cc => cc.CommandName == command.Text.ToLowerInvariant()); localSet.RemoveWhere(cc => cc.CommandName == command.Aliases.First().ToLowerInvariant());
if (secs != 0) if (secs != 0)
{ {
var cc = new CommandCooldown() var cc = new CommandCooldown()
{ {
CommandName = command.Text.ToLowerInvariant(), CommandName = command.Aliases.First().ToLowerInvariant(),
Seconds = secs, Seconds = secs,
}; };
config.CommandCooldowns.Add(cc); config.CommandCooldowns.Add(cc);
@ -67,7 +64,7 @@ namespace NadekoBot.Modules.Permissions
if (secs == 0) if (secs == 0)
{ {
var activeCds = activeCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>()); var activeCds = activeCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<ActiveCooldown>());
activeCds.RemoveWhere(ac => ac.Command == command.Text.ToLowerInvariant()); activeCds.RemoveWhere(ac => ac.Command == command.Aliases.First().ToLowerInvariant());
await channel.SendConfirmAsync($"🚮 Command **{command}** has no coooldown now and all existing cooldowns have been cleared.") await channel.SendConfirmAsync($"🚮 Command **{command}** has no coooldown now and all existing cooldowns have been cleared.")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -80,9 +77,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllCmdCooldowns(IUserMessage imsg) public async Task AllCmdCooldowns()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>()); var localSet = commandCooldowns.GetOrAdd(channel.Guild.Id, new ConcurrentHashSet<CommandCooldown>());
if (!localSet.Any()) if (!localSet.Any())
@ -91,16 +88,16 @@ namespace NadekoBot.Modules.Permissions
await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + " secs"), s => $"{s,-30}", 2).ConfigureAwait(false); await channel.SendTableAsync("", localSet.Select(c => c.CommandName + ": " + c.Seconds + " secs"), s => $"{s,-30}", 2).ConfigureAwait(false);
} }
public static bool HasCooldown(Command cmd, IGuild guild, IUser user) public static bool HasCooldown(CommandInfo cmd, IGuild guild, IUser user)
{ {
if (guild == null) if (guild == null)
return false; return false;
var cmdcds = CmdCdsCommands.commandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>()); var cmdcds = CmdCdsCommands.commandCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<CommandCooldown>());
CommandCooldown cdRule; CommandCooldown cdRule;
if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == cmd.Text.ToLowerInvariant())) != null) if ((cdRule = cmdcds.FirstOrDefault(cc => cc.CommandName == cmd.Aliases.First().ToLowerInvariant())) != null)
{ {
var activeCdsForGuild = activeCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>()); var activeCdsForGuild = activeCooldowns.GetOrAdd(guild.Id, new ConcurrentHashSet<ActiveCooldown>());
if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == cmd.Text.ToLowerInvariant()) != null) if (activeCdsForGuild.FirstOrDefault(ac => ac.UserId == user.Id && ac.Command == cmd.Aliases.First().ToLowerInvariant()) != null)
{ {
return true; return true;
} }
@ -109,14 +106,14 @@ namespace NadekoBot.Modules.Permissions
activeCdsForGuild.Add(new ActiveCooldown() activeCdsForGuild.Add(new ActiveCooldown()
{ {
UserId = user.Id, UserId = user.Id,
Command = cmd.Text.ToLowerInvariant(), Command = cmd.Aliases.First().ToLowerInvariant(),
}); });
var t = Task.Run(async () => var t = Task.Run(async () =>
{ {
try try
{ {
await Task.Delay(cdRule.Seconds * 1000); await Task.Delay(cdRule.Seconds * 1000);
activeCdsForGuild.RemoveWhere(ac => ac.Command == cmd.Text.ToLowerInvariant() && ac.UserId == user.Id); activeCdsForGuild.RemoveWhere(ac => ac.Command == cmd.Aliases.First().ToLowerInvariant() && ac.UserId == user.Id);
} }
catch { } catch { }
}); });

View File

@ -13,7 +13,7 @@ namespace NadekoBot.Modules.Permissions
public partial class Permissions public partial class Permissions
{ {
[Group] [Group]
public class FilterCommands public class FilterCommands : ModuleBase
{ {
public static ConcurrentHashSet<ulong> InviteFilteringChannels { get; } public static ConcurrentHashSet<ulong> InviteFilteringChannels { get; }
public static ConcurrentHashSet<ulong> InviteFilteringServers { get; } public static ConcurrentHashSet<ulong> InviteFilteringServers { get; }
@ -63,9 +63,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrFilterInv(IUserMessage imsg) public async Task SrvrFilterInv()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
bool enabled; bool enabled;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -89,9 +89,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlFilterInv(IUserMessage imsg) public async Task ChnlFilterInv()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
int removed; int removed;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -122,9 +122,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrFilterWords(IUserMessage imsg) public async Task SrvrFilterWords()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
bool enabled; bool enabled;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -148,9 +148,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlFilterWords(IUserMessage imsg) public async Task ChnlFilterWords()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
int removed; int removed;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -181,9 +181,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task FilterWord(IUserMessage imsg, [Remainder] string word) public async Task FilterWord([Remainder] string word)
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
word = word?.Trim().ToLowerInvariant(); word = word?.Trim().ToLowerInvariant();
@ -221,9 +221,9 @@ namespace NadekoBot.Modules.Permissions
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task LstFilterWords(IUserMessage imsg) public async Task LstFilterWords()
{ {
var channel = (ITextChannel)imsg.Channel; var channel = (ITextChannel)Context.Channel;
ConcurrentHashSet<string> filteredWords; ConcurrentHashSet<string> filteredWords;
ServerFilteredWords.TryGetValue(channel.Guild.Id, out filteredWords); ServerFilteredWords.TryGetValue(channel.Guild.Id, out filteredWords);

View File

@ -10,7 +10,7 @@ namespace NadekoBot.Modules.Permissions
{ {
public static class PermissionExtensions public static class PermissionExtensions
{ {
public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, Command command) public static bool CheckPermissions(this IEnumerable<Permission> permsEnumerable, IUserMessage message, CommandInfo command)
{ {
var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList(); var perms = permsEnumerable as List<Permission> ?? permsEnumerable.ToList();
int throwaway; int throwaway;
@ -75,7 +75,7 @@ namespace NadekoBot.Modules.Permissions
case PrimaryPermissionType.Role: case PrimaryPermissionType.Role:
if (guildUser == null) if (guildUser == null)
break; break;
if (guildUser.Roles.Any(r => r.Id == perm.PrimaryTargetId)) if (guildUser.RoleIds.Contains(perm.PrimaryTargetId))
return perm.State; return perm.State;
break; break;
case PrimaryPermissionType.Server: case PrimaryPermissionType.Server:
@ -86,7 +86,7 @@ namespace NadekoBot.Modules.Permissions
return null; return null;
} }
public static string GetCommand(this Permission perm, IGuild guild = null) public static string GetCommand(this Permission perm, SocketGuild guild = null)
{ {
var com = ""; var com = "";
switch (perm.PrimaryTarget) switch (perm.PrimaryTarget)

View File

@ -8,6 +8,9 @@ using Discord;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using Discord.WebSocket;
using System.Diagnostics;
using NLog;
namespace NadekoBot.Modules.Permissions namespace NadekoBot.Modules.Permissions
{ {
@ -26,6 +29,9 @@ namespace NadekoBot.Modules.Permissions
static Permissions() static Permissions()
{ {
var _log = LogManager.GetCurrentClassLogger();
var sw = Stopwatch.StartNew();
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
Cache = new ConcurrentDictionary<ulong, PermissionCache>(uow.GuildConfigs Cache = new ConcurrentDictionary<ulong, PermissionCache>(uow.GuildConfigs
@ -38,23 +44,20 @@ namespace NadekoBot.Modules.Permissions
PermRole = v.PermissionRole PermRole = v.PermissionRole
})); }));
} }
}
public Permissions() : base() sw.Stop();
{ _log.Debug($"Loaded in {sw.Elapsed.TotalSeconds:F2}s");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Verbose(IUserMessage msg, PermissionAction action) public async Task Verbose(PermissionAction action)
{ {
var channel = (ITextChannel)msg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
config.VerbosePermissions = action.Value; config.VerbosePermissions = action.Value;
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(), RootPermission = Permission.GetDefaultRoot(),
@ -63,25 +66,24 @@ namespace NadekoBot.Modules.Permissions
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync(" I will " + (action.Value ? "now" : "no longer") + " show permission warnings.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(" I will " + (action.Value ? "now" : "no longer") + " show permission warnings.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task PermRole(IUserMessage msg, [Remainder] IRole role = null) public async Task PermRole([Remainder] IRole role = null)
{ {
var channel = (ITextChannel)msg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set);
if (role == null) if (role == null)
{ {
await channel.SendConfirmAsync($" Current permission role is **{config.PermissionRole}**.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($" Current permission role is **{config.PermissionRole}**.").ConfigureAwait(false);
return; return;
} }
else { else {
config.PermissionRole = role.Name.Trim(); config.PermissionRole = role.Name.Trim();
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = Permission.GetDefaultRoot(), RootPermission = Permission.GetDefaultRoot(),
@ -91,40 +93,37 @@ namespace NadekoBot.Modules.Permissions
} }
} }
await channel.SendConfirmAsync($"Users now require **{role.Name}** role in order to edit permissions.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Users now require **{role.Name}** role in order to edit permissions.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ListPerms(IUserMessage msg, int page = 1) public async Task ListPerms(int page = 1)
{ {
var channel = (ITextChannel)msg.Channel;
if (page < 1 || page > 4) if (page < 1 || page > 4)
return; return;
string toSend = ""; string toSend = "";
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var perms = uow.GuildConfigs.PermissionsFor(channel.Guild.Id).RootPermission; var perms = uow.GuildConfigs.PermissionsFor(Context.Guild.Id).RootPermission;
var i = 1 + 20 * (page - 1); var i = 1 + 20 * (page - 1);
toSend = Format.Code($"📄 Permissions page {page}") + "\n\n" + String.Join("\n", perms.AsEnumerable().Skip((page - 1) * 20).Take(20).Select(p => $"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand(channel.Guild) + " [uneditable]") : (p.GetCommand(channel.Guild)))}")); toSend = Format.Code($"📄 Permissions page {page}") + "\n\n" + String.Join("\n", perms.AsEnumerable().Skip((page - 1) * 20).Take(20).Select(p => $"`{(i++)}.` {(p.Next == null ? Format.Bold(p.GetCommand((SocketGuild)Context.Guild) + " [uneditable]") : (p.GetCommand((SocketGuild)Context.Guild)))}"));
} }
await channel.SendMessageAsync(toSend).ConfigureAwait(false); await Context.Channel.SendMessageAsync(toSend).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task RemovePerm(IUserMessage imsg, int index) public async Task RemovePerm(int index)
{ {
var channel = (ITextChannel)imsg.Channel;
index -= 1; index -= 1;
try try
{ {
Permission p; Permission p;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(channel.Guild.Id); var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
var perms = config.RootPermission; var perms = config.RootPermission;
if (index == perms.Count() - 1) if (index == perms.Count() - 1)
{ {
@ -139,7 +138,7 @@ namespace NadekoBot.Modules.Permissions
{ {
p = perms.RemoveAt(index); p = perms.RemoveAt(index);
} }
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -154,21 +153,20 @@ namespace NadekoBot.Modules.Permissions
uow2._context.SaveChanges(); uow2._context.SaveChanges();
} }
await channel.SendConfirmAsync($"✅ {imsg.Author.Mention} removed permission **{p.GetCommand(channel.Guild)}** from position #{index + 1}.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"✅ {Context.User.Mention} removed permission **{p.GetCommand((SocketGuild)Context.Guild)}** from position #{index + 1}.").ConfigureAwait(false);
} }
catch (ArgumentOutOfRangeException) catch (ArgumentOutOfRangeException)
{ {
await channel.SendErrorAsync("❗️`No command on that index found.`").ConfigureAwait(false); await Context.Channel.SendErrorAsync("❗️`No command on that index found.`").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task MovePerm(IUserMessage imsg, int from, int to) public async Task MovePerm(int from, int to)
{ {
from -= 1; from -= 1;
to -= 1; to -= 1;
var channel = (ITextChannel)imsg.Channel;
if (!(from == to || from < 0 || to < 0)) if (!(from == to || from < 0 || to < 0))
{ {
try try
@ -177,7 +175,7 @@ namespace NadekoBot.Modules.Permissions
Permission toPerm = null; Permission toPerm = null;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(channel.Guild.Id); var config = uow.GuildConfigs.PermissionsFor(Context.Guild.Id);
var perms = config.RootPermission; var perms = config.RootPermission;
var root = perms; var root = perms;
var index = 0; var index = 0;
@ -206,13 +204,13 @@ namespace NadekoBot.Modules.Permissions
{ {
if (!fromFound) if (!fromFound)
{ {
await channel.SendErrorAsync($"Can't find permission at index `#{++from}`").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Can't find permission at index `#{++from}`").ConfigureAwait(false);
return; return;
} }
if (!toFound) if (!toFound)
{ {
await channel.SendErrorAsync($"Can't find permission at index `#{++to}`").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Can't find permission at index `#{++to}`").ConfigureAwait(false);
return; return;
} }
} }
@ -254,7 +252,7 @@ namespace NadekoBot.Modules.Permissions
} }
config.RootPermission = fromPerm.GetRoot(); config.RootPermission = fromPerm.GetRoot();
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -262,22 +260,20 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"`Moved permission:` \"{fromPerm.GetCommand(channel.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"`Moved permission:` \"{fromPerm.GetCommand((SocketGuild)Context.Guild)}\" `from #{++from} to #{++to}.`").ConfigureAwait(false);
return; return;
} }
catch (Exception e) when (e is ArgumentOutOfRangeException || e is IndexOutOfRangeException) catch (Exception e) when (e is ArgumentOutOfRangeException || e is IndexOutOfRangeException)
{ {
} }
} }
await channel.SendErrorAsync("`Invalid index(es) specified.`").ConfigureAwait(false); await Context.Channel.SendErrorAsync("`Invalid index(es) specified.`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrCmd(IUserMessage imsg, Command command, PermissionAction action) public async Task SrvrCmd(CommandInfo command, PermissionAction action)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -285,11 +281,11 @@ namespace NadekoBot.Modules.Permissions
PrimaryTarget = PrimaryPermissionType.Server, PrimaryTarget = PrimaryPermissionType.Server,
PrimaryTargetId = 0, PrimaryTargetId = 0,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Text.ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -298,15 +294,13 @@ namespace NadekoBot.Modules.Permissions
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Text}` command on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Aliases.First()}` command on this server.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task SrvrMdl(IUserMessage imsg, Module module, PermissionAction action) public async Task SrvrMdl(ModuleInfo module, PermissionAction action)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -317,8 +311,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -326,15 +320,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of **`{module.Name}`** module on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of **`{module.Name}`** module on this server.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrCmd(IUserMessage imsg, Command command, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrCmd(CommandInfo command, PermissionAction action, [Remainder] IGuildUser user)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -342,11 +334,11 @@ namespace NadekoBot.Modules.Permissions
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = user.Id, PrimaryTargetId = user.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Text.ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -354,15 +346,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{user}` user.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Aliases.First()}` command for `{user}` user.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UsrMdl(IUserMessage imsg, Module module, PermissionAction action, [Remainder] IGuildUser user) public async Task UsrMdl(ModuleInfo module, PermissionAction action, [Remainder] IGuildUser user)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -373,8 +363,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -382,15 +372,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{user}` user.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task RoleCmd(IUserMessage imsg, Command command, PermissionAction action, [Remainder] IRole role) public async Task RoleCmd(CommandInfo command, PermissionAction action, [Remainder] IRole role)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -398,11 +386,11 @@ namespace NadekoBot.Modules.Permissions
PrimaryTarget = PrimaryPermissionType.Role, PrimaryTarget = PrimaryPermissionType.Role,
PrimaryTargetId = role.Id, PrimaryTargetId = role.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Text.ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -410,15 +398,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{role}` role.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Aliases.First()}` command for `{role}` role.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task RoleMdl(IUserMessage imsg, Module module, PermissionAction action, [Remainder] IRole role) public async Task RoleMdl(ModuleInfo module, PermissionAction action, [Remainder] IRole role)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -429,8 +415,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -438,14 +424,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{role}` role.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlCmd(IUserMessage imsg, Command command, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlCmd(CommandInfo command, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
var channel = (ITextChannel)imsg.Channel;
try try
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
@ -455,11 +440,11 @@ namespace NadekoBot.Modules.Permissions
PrimaryTarget = PrimaryPermissionType.Channel, PrimaryTarget = PrimaryPermissionType.Channel,
PrimaryTargetId = chnl.Id, PrimaryTargetId = chnl.Id,
SecondaryTarget = SecondaryPermissionType.Command, SecondaryTarget = SecondaryPermissionType.Command,
SecondaryTargetName = command.Text.ToLowerInvariant(), SecondaryTargetName = command.Aliases.First().ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -471,15 +456,13 @@ namespace NadekoBot.Modules.Permissions
catch (Exception ex) { catch (Exception ex) {
_log.Error(ex); _log.Error(ex);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Text}` command for `{chnl}` channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{command.Aliases.First()}` command for `{chnl}` channel.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChnlMdl(IUserMessage imsg, Module module, PermissionAction action, [Remainder] ITextChannel chnl) public async Task ChnlMdl(ModuleInfo module, PermissionAction action, [Remainder] ITextChannel chnl)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -490,8 +473,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = module.Name.ToLowerInvariant(), SecondaryTargetName = module.Name.ToLowerInvariant(),
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -499,15 +482,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `{module.Name}` module for `{chnl}` channel.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllChnlMdls(IUserMessage imsg, PermissionAction action, [Remainder] ITextChannel chnl) public async Task AllChnlMdls(PermissionAction action, [Remainder] ITextChannel chnl)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -518,8 +499,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -527,15 +508,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{chnl}` channel.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllRoleMdls(IUserMessage imsg, PermissionAction action, [Remainder] IRole role) public async Task AllRoleMdls(PermissionAction action, [Remainder] IRole role)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -546,8 +525,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -555,15 +534,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{role}` role.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllUsrMdls(IUserMessage imsg, PermissionAction action, [Remainder] IUser user) public async Task AllUsrMdls(PermissionAction action, [Remainder] IUser user)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -574,8 +551,8 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -583,15 +560,13 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` for `{user}` user.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AllSrvrMdls(IUserMessage imsg, PermissionAction action) public async Task AllSrvrMdls(PermissionAction action)
{ {
var channel = (ITextChannel)imsg.Channel;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var newPerm = new Permission var newPerm = new Permission
@ -602,19 +577,19 @@ namespace NadekoBot.Modules.Permissions
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = action.Value, State = action.Value,
}; };
uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, newPerm); uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, newPerm);
var allowUser = new Permission var allowUser = new Permission
{ {
PrimaryTarget = PrimaryPermissionType.User, PrimaryTarget = PrimaryPermissionType.User,
PrimaryTargetId = imsg.Author.Id, PrimaryTargetId = Context.User.Id,
SecondaryTarget = SecondaryPermissionType.AllModules, SecondaryTarget = SecondaryPermissionType.AllModules,
SecondaryTargetName = "*", SecondaryTargetName = "*",
State = true, State = true,
}; };
var config = uow.GuildConfigs.SetNewRootPermission(channel.Guild.Id, allowUser); var config = uow.GuildConfigs.SetNewRootPermission(Context.Guild.Id, allowUser);
Cache.AddOrUpdate(channel.Guild.Id, new PermissionCache() Cache.AddOrUpdate(Context.Guild.Id, new PermissionCache()
{ {
PermRole = config.PermissionRole, PermRole = config.PermissionRole,
RootPermission = config.RootPermission, RootPermission = config.RootPermission,
@ -622,7 +597,7 @@ namespace NadekoBot.Modules.Permissions
}, (id, old) => { old.RootPermission = config.RootPermission; return old; }); }, (id, old) => { old.RootPermission = config.RootPermission; return old; });
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{(action.Value ? " Allowed" : "🆗 Denied")} usage of `ALL MODULES` on this server.").ConfigureAwait(false);
} }
} }
} }

View File

@ -16,7 +16,6 @@ using static NadekoBot.Modules.Gambling.Gambling;
namespace NadekoBot.Modules.Pokemon namespace NadekoBot.Modules.Pokemon
{ {
[NadekoModule("Pokemon", ">")] [NadekoModule("Pokemon", ">")]
public partial class Pokemon : DiscordModule public partial class Pokemon : DiscordModule
{ {
@ -25,18 +24,18 @@ namespace NadekoBot.Modules.Pokemon
public const string PokemonTypesFile = "data/pokemon_types.json"; public const string PokemonTypesFile = "data/pokemon_types.json";
private Logger _pokelog { get; } private static new Logger _log { get; }
public Pokemon() : base() static Pokemon()
{ {
_pokelog = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
if (File.Exists(PokemonTypesFile)) if (File.Exists(PokemonTypesFile))
{ {
PokemonTypes = JsonConvert.DeserializeObject<List<PokemonType>>(File.ReadAllText(PokemonTypesFile)); PokemonTypes = JsonConvert.DeserializeObject<List<PokemonType>>(File.ReadAllText(PokemonTypesFile));
} }
else else
{ {
_pokelog.Warn(PokemonTypesFile + " is missing. Pokemon types not loaded."); _log.Warn(PokemonTypesFile + " is missing. Pokemon types not loaded.");
} }
} }
@ -97,10 +96,9 @@ namespace NadekoBot.Modules.Pokemon
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Attack(IUserMessage umsg, string move, IGuildUser targetUser = null) public async Task Attack(string move, IGuildUser targetUser = null)
{ {
var channel = (ITextChannel)umsg.Channel; IGuildUser user = (IGuildUser)Context.User;
IGuildUser user = (IGuildUser)umsg.Author;
if (string.IsNullOrWhiteSpace(move)) { if (string.IsNullOrWhiteSpace(move)) {
return; return;
@ -108,12 +106,12 @@ namespace NadekoBot.Modules.Pokemon
if (targetUser == null) if (targetUser == null)
{ {
await channel.SendMessageAsync("No such person.").ConfigureAwait(false); await Context.Channel.SendMessageAsync("No such person.").ConfigureAwait(false);
return; return;
} }
else if (targetUser == user) else if (targetUser == user)
{ {
await channel.SendMessageAsync("You can't attack yourself.").ConfigureAwait(false); await Context.Channel.SendMessageAsync("You can't attack yourself.").ConfigureAwait(false);
return; return;
} }
@ -127,17 +125,17 @@ namespace NadekoBot.Modules.Pokemon
//User not able if HP < 0, has made more than 4 attacks //User not able if HP < 0, has made more than 4 attacks
if (userStats.Hp < 0) if (userStats.Hp < 0)
{ {
await channel.SendMessageAsync($"{user.Mention} has fainted and was not able to move!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} has fainted and was not able to move!").ConfigureAwait(false);
return; return;
} }
if (userStats.MovesMade >= 5) if (userStats.MovesMade >= 5)
{ {
await channel.SendMessageAsync($"{user.Mention} has used too many moves in a row and was not able to move!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} has used too many moves in a row and was not able to move!").ConfigureAwait(false);
return; return;
} }
if (userStats.LastAttacked.Contains(targetUser.Id)) if (userStats.LastAttacked.Contains(targetUser.Id))
{ {
await channel.SendMessageAsync($"{user.Mention} can't attack again without retaliation!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} can't attack again without retaliation!").ConfigureAwait(false);
return; return;
} }
//get target stats //get target stats
@ -147,7 +145,7 @@ namespace NadekoBot.Modules.Pokemon
//If target's HP is below 0, no use attacking //If target's HP is below 0, no use attacking
if (targetStats.Hp <= 0) if (targetStats.Hp <= 0)
{ {
await channel.SendMessageAsync($"{targetUser.Mention} has already fainted!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{targetUser.Mention} has already fainted!").ConfigureAwait(false);
return; return;
} }
@ -157,7 +155,7 @@ namespace NadekoBot.Modules.Pokemon
var enabledMoves = userType.Moves; var enabledMoves = userType.Moves;
if (!enabledMoves.Contains(move.ToLowerInvariant())) if (!enabledMoves.Contains(move.ToLowerInvariant()))
{ {
await channel.SendMessageAsync($"{user.Mention} is not able to use **{move}**. Type {NadekoBot.ModulePrefixes[typeof(Pokemon).Name]}ml to see moves").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} is not able to use **{move}**. Type {NadekoBot.ModulePrefixes[typeof(Pokemon).Name]}ml to see moves").ConfigureAwait(false);
return; return;
} }
@ -209,16 +207,15 @@ namespace NadekoBot.Modules.Pokemon
Stats[user.Id] = userStats; Stats[user.Id] = userStats;
Stats[targetUser.Id] = targetStats; Stats[targetUser.Id] = targetStats;
await channel.SendMessageAsync(response).ConfigureAwait(false); await Context.Channel.SendMessageAsync(response).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Movelist(IUserMessage umsg) public async Task Movelist()
{ {
var channel = (ITextChannel)umsg.Channel; IGuildUser user = (IGuildUser)Context.User;
IGuildUser user = (IGuildUser)umsg.Author;
var userType = GetPokeType(user.Id); var userType = GetPokeType(user.Id);
var movesList = userType.Moves; var movesList = userType.Moves;
@ -227,18 +224,17 @@ namespace NadekoBot.Modules.Pokemon
{ {
str += $"\n{userType.Icon}{m}"; str += $"\n{userType.Icon}{m}";
} }
await channel.SendMessageAsync(str).ConfigureAwait(false); await Context.Channel.SendMessageAsync(str).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Heal(IUserMessage umsg, IGuildUser targetUser = null) public async Task Heal(IGuildUser targetUser = null)
{ {
var channel = (ITextChannel)umsg.Channel; IGuildUser user = (IGuildUser)Context.User;
IGuildUser user = (IGuildUser)umsg.Author;
if (targetUser == null) { if (targetUser == null) {
await channel.SendMessageAsync("No such person.").ConfigureAwait(false); await Context.Channel.SendMessageAsync("No such person.").ConfigureAwait(false);
return; return;
} }
@ -247,7 +243,7 @@ namespace NadekoBot.Modules.Pokemon
var targetStats = Stats[targetUser.Id]; var targetStats = Stats[targetUser.Id];
if (targetStats.Hp == targetStats.MaxHp) if (targetStats.Hp == targetStats.MaxHp)
{ {
await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false);
return; return;
} }
//Payment~ //Payment~
@ -258,7 +254,7 @@ namespace NadekoBot.Modules.Pokemon
{ {
if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false)) if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"Poke-Heal {target}", amount, true).ConfigureAwait(false))
{ {
try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { } try { await Context.Channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { }
return; return;
} }
} }
@ -271,30 +267,29 @@ namespace NadekoBot.Modules.Pokemon
Stats[targetUser.Id].Hp = (targetStats.MaxHp / 2); Stats[targetUser.Id].Hp = (targetStats.MaxHp / 2);
if (target == "yourself") if (target == "yourself")
{ {
await channel.SendMessageAsync($"You revived yourself with one {CurrencySign}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"You revived yourself with one {CurrencySign}").ConfigureAwait(false);
} }
else else
{ {
await channel.SendMessageAsync($"{user.Mention} revived {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} revived {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false);
} }
return; return;
} }
await channel.SendMessageAsync($"{user.Mention} healed {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{user.Mention} healed {targetUser.Mention} with one {CurrencySign}").ConfigureAwait(false);
return; return;
} }
else else
{ {
await channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"{targetUser.Mention} already has full HP!").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Type(IUserMessage umsg, IGuildUser targetUser = null) public async Task Type(IGuildUser targetUser = null)
{ {
var channel = (ITextChannel)umsg.Channel; IGuildUser user = (IGuildUser)Context.User;
IGuildUser user = (IGuildUser)umsg.Author;
if (targetUser == null) if (targetUser == null)
{ {
@ -302,26 +297,29 @@ namespace NadekoBot.Modules.Pokemon
} }
var pType = GetPokeType(targetUser.Id); var pType = GetPokeType(targetUser.Id);
await channel.SendMessageAsync($"Type of {targetUser.Mention} is **{pType.Name.ToLowerInvariant()}**{pType.Icon}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"Type of {targetUser.Mention} is **{pType.Name.ToLowerInvariant()}**{pType.Icon}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Settype(IUserMessage umsg, [Remainder] string typeTargeted = null) public async Task Settype([Remainder] string typeTargeted = null)
{ {
var channel = (ITextChannel)umsg.Channel; IGuildUser user = (IGuildUser)Context.User;
IGuildUser user = (IGuildUser)umsg.Author;
var targetType = StringToPokemonType(typeTargeted); var targetType = StringToPokemonType(typeTargeted);
if (targetType == null) if (targetType == null)
{ {
await channel.EmbedAsync(PokemonTypes.Aggregate(new EmbedBuilder().WithDescription("List of the available types:"), (eb, pt) => eb.AddField(efb => efb.WithName(pt.Name).WithValue(pt.Icon).WithIsInline(true))).WithOkColor().Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(PokemonTypes.Aggregate(new EmbedBuilder().WithDescription("List of the available types:"),
(eb, pt) => eb.AddField(efb => efb.WithName(pt.Name)
.WithValue(pt.Icon)
.WithIsInline(true)))
.WithColor(NadekoBot.OkColor)).ConfigureAwait(false);
return; return;
} }
if (targetType == GetPokeType(user.Id)) if (targetType == GetPokeType(user.Id))
{ {
await channel.SendMessageAsync($"Your type is already {targetType.Name.ToLowerInvariant()}{targetType.Icon}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"Your type is already {targetType.Name.ToLowerInvariant()}{targetType.Icon}").ConfigureAwait(false);
return; return;
} }
@ -331,7 +329,7 @@ namespace NadekoBot.Modules.Pokemon
{ {
if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"{user.Mention} change type to {typeTargeted}", amount, true).ConfigureAwait(false)) if (!await CurrencyHandler.RemoveCurrencyAsync(user, $"{user.Mention} change type to {typeTargeted}", amount, true).ConfigureAwait(false))
{ {
try { await channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { } try { await Context.Channel.SendMessageAsync($"{user.Mention} You don't have enough {CurrencyName}s.").ConfigureAwait(false); } catch { }
return; return;
} }
} }
@ -364,7 +362,7 @@ namespace NadekoBot.Modules.Pokemon
} }
//Now for the response //Now for the response
await channel.SendMessageAsync($"Set type of {user.Mention} to {typeTargeted}{targetType.Icon} for a {CurrencySign}").ConfigureAwait(false); await Context.Channel.SendMessageAsync($"Set type of {user.Mention} to {typeTargeted}{targetType.Icon} for a {CurrencySign}").ConfigureAwait(false);
} }
} }

View File

@ -1,8 +1,4 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Pokemon namespace NadekoBot.Modules.Pokemon
{ {

View File

@ -1,5 +1,4 @@
using Discord; using Discord;
using Discord.API;
using Discord.Commands; using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
@ -18,7 +17,7 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class AnimeSearchCommands public class AnimeSearchCommands : ModuleBase
{ {
private static Timer anilistTokenRefresher { get; } private static Timer anilistTokenRefresher { get; }
private static Logger _log { get; } private static Logger _log { get; }
@ -54,11 +53,8 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Anime([Remainder] string query)
public async Task Anime(IUserMessage umsg, [Remainder] string query)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
@ -66,7 +62,7 @@ namespace NadekoBot.Modules.Searches
if (animeData == null) if (animeData == null)
{ {
await umsg.Channel.SendErrorAsync("Failed finding that animu.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed finding that animu.").ConfigureAwait(false);
return; return;
} }
@ -79,15 +75,13 @@ namespace NadekoBot.Modules.Searches
.AddField(efb => efb.WithName("Status").WithValue(animeData.AiringStatus.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName("Status").WithValue(animeData.AiringStatus.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", animeData.Genres)).WithIsInline(true)) .AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", animeData.Genres)).WithIsInline(true))
.WithFooter(efb => efb.WithText("Score: " + animeData.average_score + " / 100")); .WithFooter(efb => efb.WithText("Score: " + animeData.average_score + " / 100"));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Manga(IUserMessage umsg, [Remainder] string query) public async Task Manga([Remainder] string query)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
@ -95,7 +89,7 @@ namespace NadekoBot.Modules.Searches
if (mangaData == null) if (mangaData == null)
{ {
await umsg.Channel.SendErrorAsync("Failed finding that mango.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed finding that mango.").ConfigureAwait(false);
return; return;
} }
@ -109,7 +103,7 @@ namespace NadekoBot.Modules.Searches
.AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", mangaData.Genres)).WithIsInline(true)) .AddField(efb => efb.WithName("Genres").WithValue(String.Join(", ", mangaData.Genres)).WithIsInline(true))
.WithFooter(efb => efb.WithText("Score: " + mangaData.average_score + " / 100")); .WithFooter(efb => efb.WithText("Score: " + mangaData.average_score + " / 100"));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
private async Task<AnimeResult> GetAnimeData(string query) private async Task<AnimeResult> GetAnimeData(string query)

View File

@ -1,5 +1,4 @@
using Discord; using Discord.Commands;
using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Models; using NadekoBot.Modules.Searches.Models;
@ -8,6 +7,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using NLog; using NLog;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
@ -18,7 +18,7 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class JokeCommands public class JokeCommands : ModuleBase
{ {
private static List<WoWJoke> wowJokes { get; } = new List<WoWJoke>(); private static List<WoWJoke> wowJokes { get; } = new List<WoWJoke>();
private static List<MagicItem> magicItems { get; } = new List<MagicItem>(); private static List<MagicItem> magicItems { get; } = new List<MagicItem>();
@ -27,6 +27,7 @@ namespace NadekoBot.Modules.Searches
static JokeCommands() static JokeCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
if (File.Exists("data/wowjokes.json")) if (File.Exists("data/wowjokes.json"))
{ {
wowJokes = JsonConvert.DeserializeObject<List<WoWJoke>>(File.ReadAllText("data/wowjokes.json")); wowJokes = JsonConvert.DeserializeObject<List<WoWJoke>>(File.ReadAllText("data/wowjokes.json"));
@ -43,64 +44,58 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Yomama()
public async Task Yomama(IUserMessage msg)
{ {
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false); var response = await http.GetStringAsync("http://api.yomomma.info/").ConfigureAwait(false);
System.Console.WriteLine(response); await Context.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false);
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Randjoke()
public async Task Randjoke(IUserMessage msg)
{ {
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false); var response = await http.GetStringAsync("http://tambal.azurewebsites.net/joke/random").ConfigureAwait(false);
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(JObject.Parse(response)["joke"].ToString() + " 😆").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task ChuckNorris()
public async Task ChuckNorris(IUserMessage msg)
{ {
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var response = await http.GetStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false); var response = await http.GetStringAsync("http://api.icndb.com/jokes/random/").ConfigureAwait(false);
await msg.Channel.SendConfirmAsync(JObject.Parse(response)["value"]["joke"].ToString() + " 😆").ConfigureAwait(false); await Context.Channel.SendConfirmAsync(JObject.Parse(response)["value"]["joke"].ToString() + " 😆").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task WowJoke()
public async Task WowJoke(IUserMessage msg)
{ {
if (!wowJokes.Any()) if (!wowJokes.Any())
{ {
await msg.Channel.SendErrorAsync("Jokes not loaded.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Jokes not loaded.").ConfigureAwait(false);
return; return;
} }
var joke = wowJokes[new NadekoRandom().Next(0, wowJokes.Count)]; var joke = wowJokes[new NadekoRandom().Next(0, wowJokes.Count)];
await msg.Channel.SendConfirmAsync(joke.Question, joke.Answer).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(joke.Question, joke.Answer).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task MagicItem()
public async Task MagicItem(IUserMessage msg)
{ {
if (!wowJokes.Any()) if (!wowJokes.Any())
{ {
await msg.Channel.SendErrorAsync("MagicItems not loaded.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("MagicItems not loaded.").ConfigureAwait(false);
return; return;
} }
var item = magicItems[new NadekoRandom().Next(0, magicItems.Count)]; var item = magicItems[new NadekoRandom().Next(0, magicItems.Count)];
await msg.Channel.SendConfirmAsync("✨" + item.Name, item.Description).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("✨" + item.Name, item.Description).ConfigureAwait(false);
} }
} }
} }

View File

@ -1,5 +1,4 @@
using Discord; using Discord;
using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -8,7 +7,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
//todo drawing //todo drawing
@ -33,13 +31,8 @@ namespace NadekoBot.Modules.Searches
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Lolban()
public async Task Lolban(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
var showCount = 8; var showCount = 8;
//http://api.champion.gg/stats/champs/mostBanned?api_key=YOUR_API_TOKEN&page=1&limit=2 //http://api.champion.gg/stats/champs/mostBanned?api_key=YOUR_API_TOKEN&page=1&limit=2
try try
@ -58,12 +51,12 @@ namespace NadekoBot.Modules.Searches
eb.AddField(efb => efb.WithName(champ["name"].ToString()).WithValue(champ["general"]["banRate"] + "%").WithIsInline(true)); eb.AddField(efb => efb.WithName(champ["name"].ToString()).WithValue(champ["general"]["banRate"] + "%").WithIsInline(true));
} }
await channel.EmbedAsync(eb.Build(), Format.Italics(trashTalk[new NadekoRandom().Next(0, trashTalk.Length)])).ConfigureAwait(false); await Context.Channel.EmbedAsync(eb, Format.Italics(trashTalk[new NadekoRandom().Next(0, trashTalk.Length)])).ConfigureAwait(false);
} }
} }
catch (Exception) catch (Exception)
{ {
await channel.SendMessageAsync("Something went wrong.").ConfigureAwait(false); await Context.Channel.SendMessageAsync("Something went wrong.").ConfigureAwait(false);
} }
} }
} }
@ -112,7 +105,7 @@ namespace NadekoBot.Modules.Searches
// public override void Init(CommandGroupBuilder cgb) // public override void Init(CommandGroupBuilder cgb)
// { // {
// cgb.CreateCommand(Module.Prefix + "lolchamp") // cgb.CreateCommand(Module.Name + "lolchamp")
// .Description($"Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. |`{Prefix}lolchamp Riven` or `{Prefix}lolchamp Annie sup`") // .Description($"Shows League Of Legends champion statistics. If there are spaces/apostrophes or in the name - omit them. Optional second parameter is a role. |`{Prefix}lolchamp Riven` or `{Prefix}lolchamp Annie sup`")
// .Parameter("champ", ParameterType.Required) // .Parameter("champ", ParameterType.Required)
// .Parameter("position", ParameterType.Unparsed) // .Parameter("position", ParameterType.Unparsed)

View File

@ -1,10 +1,8 @@
using Discord.Commands;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Discord;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using System.Net.Http; using System.Net.Http;
@ -15,10 +13,8 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Memelist()
public async Task Memelist(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
HttpClientHandler handler = new HttpClientHandler(); HttpClientHandler handler = new HttpClientHandler();
handler.AllowAutoRedirect = false; handler.AllowAutoRedirect = false;
@ -29,19 +25,16 @@ namespace NadekoBot.Modules.Searches
var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawJson) var data = JsonConvert.DeserializeObject<Dictionary<string, string>>(rawJson)
.Select(kvp => Path.GetFileName(kvp.Value)); .Select(kvp => Path.GetFileName(kvp.Value));
await channel.SendTableAsync(data, x => $"{x,-17}", 3).ConfigureAwait(false); await Context.Channel.SendTableAsync(data, x => $"{x,-17}", 3).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Memegen(string meme, string topText, string botText)
public async Task Memegen(IUserMessage umsg, string meme, string topText, string botText)
{ {
var channel = (ITextChannel)umsg.Channel; var top = Uri.EscapeDataString(topText.Replace(' ', '-'));
var bot = Uri.EscapeDataString(botText.Replace(' ', '-'));
var top = topText.Replace(' ', '-'); await Context.Channel.SendMessageAsync($"http://memegen.link/{meme}/{top}/{bot}.jpg")
var bot = botText.Replace(' ', '-');
await channel.SendMessageAsync($"http://memegen.link/{meme}/{top}/{bot}.jpg")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }

View File

@ -1,5 +1,4 @@
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Globalization;
namespace NadekoBot.Modules.Searches.Models namespace NadekoBot.Modules.Searches.Models
{ {

View File

@ -1,6 +1,5 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace NadekoBot.Modules.Searches.Models namespace NadekoBot.Modules.Searches.Models

View File

@ -35,7 +35,7 @@ namespace NadekoBot.Modules.Searches.Commands.OMDB
public string Plot { get; set; } public string Plot { get; set; }
public string Poster { get; set; } public string Poster { get; set; }
public Embed GetEmbed() => public EmbedBuilder GetEmbed() =>
new EmbedBuilder().WithOkColor() new EmbedBuilder().WithOkColor()
.WithTitle(Title) .WithTitle(Title)
.WithUrl($"http://www.imdb.com/title/{ImdbId}/") .WithUrl($"http://www.imdb.com/title/{ImdbId}/")
@ -43,8 +43,7 @@ namespace NadekoBot.Modules.Searches.Commands.OMDB
.AddField(efb => efb.WithName("Rating").WithValue(ImdbRating).WithIsInline(true)) .AddField(efb => efb.WithName("Rating").WithValue(ImdbRating).WithIsInline(true))
.AddField(efb => efb.WithName("Genre").WithValue(Genre).WithIsInline(true)) .AddField(efb => efb.WithName("Genre").WithValue(Genre).WithIsInline(true))
.AddField(efb => efb.WithName("Year").WithValue(Year).WithIsInline(true)) .AddField(efb => efb.WithName("Year").WithValue(Year).WithIsInline(true))
.WithImage(eib => eib.WithUrl(Poster)) .WithImageUrl(Poster);
.Build();
public override string ToString() => public override string ToString() =>
$@"`Title:` {Title} $@"`Title:` {Title}

View File

@ -16,7 +16,7 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class OsuCommands public class OsuCommands : ModuleBase
{ {
private static Logger _log { get; } private static Logger _log { get; }
@ -25,11 +25,8 @@ namespace NadekoBot.Modules.Searches
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Osu(string usr, [Remainder] string mode = null)
public async Task Osu(IUserMessage umsg, string usr, [Remainder] string mode = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(usr)) if (string.IsNullOrWhiteSpace(usr))
return; return;
@ -48,25 +45,22 @@ namespace NadekoBot.Modules.Searches
MemoryStream ms = new MemoryStream(); MemoryStream ms = new MemoryStream();
res.CopyTo(ms); res.CopyTo(ms);
ms.Position = 0; ms.Position = 0;
await channel.SendFileAsync(ms, $"{usr}.png", $"🎧 **Profile Link: **https://osu.ppy.sh/u/{Uri.EscapeDataString(usr)}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false); await Context.Channel.SendFileAsync(ms, $"{usr}.png", $"🎧 **Profile Link: **https://osu.ppy.sh/u/{Uri.EscapeDataString(usr)}\n`Image provided by https://lemmmy.pw/osusig`").ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync("Failed retrieving osu signature.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed retrieving osu signature.").ConfigureAwait(false);
_log.Warn(ex, "Osu command failed"); _log.Warn(ex, "Osu command failed");
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Osub([Remainder] string map)
public async Task Osub(IUserMessage umsg, [Remainder] string map)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
{ {
await channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false);
return; return;
} }
@ -85,21 +79,20 @@ namespace NadekoBot.Modules.Searches
var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss"); var time = TimeSpan.FromSeconds(Double.Parse($"{obj["total_length"]}")).ToString(@"mm\:ss");
sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}"); sb.AppendLine($"{obj["artist"]} - {obj["title"]}, mapped by {obj["creator"]}. https://osu.ppy.sh/s/{obj["beatmapset_id"]}");
sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}"); sb.AppendLine($"{starRating} stars, {obj["bpm"]} BPM | AR{obj["diff_approach"]}, CS{obj["diff_size"]}, OD{obj["diff_overall"]} | Length: {time}");
await channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false); await Context.Channel.SendMessageAsync(sb.ToString()).ConfigureAwait(false);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync("Something went wrong."); await Context.Channel.SendErrorAsync("Something went wrong.");
_log.Warn(ex, "Osub command failed"); _log.Warn(ex, "Osub command failed");
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Osu5(string user, [Remainder] string mode = null)
public async Task Osu5(IUserMessage umsg, string user, [Remainder] string mode = null)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.OsuApiKey))
{ {
await channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false); await channel.SendErrorAsync("An osu! API key is required.").ConfigureAwait(false);

View File

@ -5,8 +5,6 @@ using NadekoBot.Extensions;
using NadekoBot.Modules.Searches.Models; using NadekoBot.Modules.Searches.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using System;
using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -16,25 +14,24 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class OverwatchCommands public class OverwatchCommands : ModuleBase
{ {
private Logger _log; private readonly Logger _log;
public OverwatchCommands() public OverwatchCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Overwatch(string region, [Remainder] string query = null)
public async Task Overwatch(IUserMessage umsg, string region, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
var battletag = Regex.Replace(query, "#", "-", RegexOptions.IgnoreCase); var battletag = Regex.Replace(query, "#", "-", RegexOptions.IgnoreCase);
await channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
try try
{ {
await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
var model = await GetProfile(region, battletag); var model = await GetProfile(region, battletag);
var rankimg = $"{model.Competitive.rank_img}"; var rankimg = $"{model.Competitive.rank_img}";
@ -46,7 +43,7 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(eau => eau.WithName($"{model.username}") .WithAuthor(eau => eau.WithName($"{model.username}")
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}") .WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
.WithIconUrl($"{model.avatar}")) .WithIconUrl($"{model.avatar}"))
.WithThumbnail(th => th.WithUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png")) .WithThumbnailUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png")
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true)) .AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true)) .AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
.AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true)) .AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
@ -56,7 +53,7 @@ namespace NadekoBot.Modules.Searches
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true)) .AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true)) .AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
.WithOkColor(); .WithOkColor();
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
else else
{ {
@ -64,7 +61,7 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(eau => eau.WithName($"{model.username}") .WithAuthor(eau => eau.WithName($"{model.username}")
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}") .WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
.WithIconUrl($"{model.avatar}")) .WithIconUrl($"{model.avatar}"))
.WithThumbnail(th => th.WithUrl(rankimg)) .WithThumbnailUrl(rankimg)
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true)) .AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true)) .AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
.AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true)) .AddField(fb => fb.WithName("**Current Competitive Wins**").WithValue($"{model.Games.Competitive.wins}").WithIsInline(true))
@ -73,27 +70,14 @@ namespace NadekoBot.Modules.Searches
.AddField(fb => fb.WithName("**Competitive Rank**").WithValue(rank).WithIsInline(true)) .AddField(fb => fb.WithName("**Competitive Rank**").WithValue(rank).WithIsInline(true))
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true)) .AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"{model.Playtime.competitive}").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true)) .AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
.WithOkColor(); .WithColor(NadekoBot.OkColor);
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} return;
if (string.IsNullOrWhiteSpace(competitiveplay))
{
var embed = new EmbedBuilder()
.WithAuthor(eau => eau.WithName($"{model.username}")
.WithUrl($"https://www.overbuff.com/players/pc/{battletag}")
.WithIconUrl($"{model.avatar}"))
.WithThumbnail(th => th.WithUrl("https://cdn.discordapp.com/attachments/155726317222887425/255653487512256512/YZ4w2ey.png"))
.AddField(fb => fb.WithName("**Level**").WithValue($"{model.level}").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Wins**").WithValue($"{model.Games.Quick.wins}").WithIsInline(true))
.AddField(fb => fb.WithName("**Competitive Playtime**").WithValue($"0 hour").WithIsInline(true))
.AddField(fb => fb.WithName("**Quick Playtime**").WithValue($"{model.Playtime.quick}").WithIsInline(true))
.WithOkColor();
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
} }
} }
catch catch
{ {
await channel.SendErrorAsync("Found no user! Please check the **Region** and **BattleTag** before trying again."); await Context.Channel.SendErrorAsync("Found no user! Please check the **Region** and **BattleTag** before trying again.");
} }
} }
public async Task<OverwatchApiModel.OverwatchPlayer.Data> GetProfile(string region, string battletag) public async Task<OverwatchApiModel.OverwatchPlayer.Data> GetProfile(string region, string battletag)

View File

@ -1,5 +1,4 @@
using Discord; using Discord.Commands;
using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -11,13 +10,9 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class PlaceCommands public class PlaceCommands : ModuleBase
{ {
string typesStr { get; } = ""; private static string typesStr { get; } = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Searches).Name]}place\" tags:`\n" + String.Join(", ", Enum.GetNames(typeof(PlaceType)));
public PlaceCommands()
{
typesStr = $"`List of \"{NadekoBot.ModulePrefixes[typeof(Searches).Name]}place\" tags:`\n" + String.Join(", ", Enum.GetNames(typeof(PlaceType)));
}
public enum PlaceType public enum PlaceType
{ {
@ -32,21 +27,15 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Placelist()
public async Task Placelist(IUserMessage imsg)
{ {
var channel = (ITextChannel)imsg.Channel; await Context.Channel.SendConfirmAsync(typesStr)
await channel.SendConfirmAsync(typesStr)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Place(PlaceType placeType, uint width = 0, uint height = 0)
public async Task Place(IUserMessage imsg, PlaceType placeType, uint width = 0, uint height = 0)
{ {
var channel = (ITextChannel)imsg.Channel;
string url = ""; string url = "";
switch (placeType) switch (placeType)
{ {
@ -84,7 +73,7 @@ namespace NadekoBot.Modules.Searches
url += $"/{width}/{height}"; url += $"/{width}/{height}";
await channel.SendMessageAsync(url).ConfigureAwait(false); await Context.Channel.SendMessageAsync(url).ConfigureAwait(false);
} }
} }
} }

View File

@ -6,6 +6,7 @@ using NadekoBot.Modules.Searches.Models;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -15,7 +16,7 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class PokemonSearchCommands public class PokemonSearchCommands : ModuleBase
{ {
private static Dictionary<string, SearchPokemon> pokemons { get; } = new Dictionary<string, SearchPokemon>(); private static Dictionary<string, SearchPokemon> pokemons { get; } = new Dictionary<string, SearchPokemon>();
private static Dictionary<string, SearchPokemonAbility> pokemonAbilities { get; } = new Dictionary<string, SearchPokemonAbility>(); private static Dictionary<string, SearchPokemonAbility> pokemonAbilities { get; } = new Dictionary<string, SearchPokemonAbility>();
@ -28,6 +29,7 @@ namespace NadekoBot.Modules.Searches
static PokemonSearchCommands() static PokemonSearchCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
if (File.Exists(PokemonListFile)) if (File.Exists(PokemonListFile))
{ {
pokemons = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemon>>(File.ReadAllText(PokemonListFile)); pokemons = JsonConvert.DeserializeObject<Dictionary<string, SearchPokemon>>(File.ReadAllText(PokemonListFile));
@ -41,11 +43,8 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Pokemon([Remainder] string pokemon = null)
public async Task Pokemon(IUserMessage umsg, [Remainder] string pokemon = null)
{ {
var channel = (ITextChannel)umsg.Channel;
pokemon = pokemon?.Trim().ToUpperInvariant(); pokemon = pokemon?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(pokemon)) if (string.IsNullOrWhiteSpace(pokemon))
return; return;
@ -55,25 +54,22 @@ namespace NadekoBot.Modules.Searches
if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant()) if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant())
{ {
var p = kvp.Value; var p = kvp.Value;
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(kvp.Key.ToTitleCase()) .WithTitle(kvp.Key.ToTitleCase())
.WithDescription(p.BaseStats.ToString()) .WithDescription(p.BaseStats.ToString())
.AddField(efb => efb.WithName("Types").WithValue(string.Join(",\n", p.Types)).WithIsInline(true)) .AddField(efb => efb.WithName("Types").WithValue(string.Join(",\n", p.Types)).WithIsInline(true))
.AddField(efb => efb.WithName("Height/Weight").WithValue($"{p.HeightM}m/{p.WeightKg}kg").WithIsInline(true)) .AddField(efb => efb.WithName("Height/Weight").WithValue($"{p.HeightM}m/{p.WeightKg}kg").WithIsInline(true))
.AddField(efb => efb.WithName("Abilitities").WithValue(string.Join(",\n", p.Abilities.Select(a => a.Value))).WithIsInline(true)) .AddField(efb => efb.WithName("Abilitities").WithValue(string.Join(",\n", p.Abilities.Select(a => a.Value))).WithIsInline(true))
.Build()); );
return; return;
} }
} }
await channel.SendErrorAsync("No pokemon found."); await Context.Channel.SendErrorAsync("No pokemon found.");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task PokemonAbility([Remainder] string ability = null)
public async Task PokemonAbility(IUserMessage umsg, [Remainder] string ability = null)
{ {
var channel = (ITextChannel)umsg.Channel;
ability = ability?.Trim().ToUpperInvariant().Replace(" ", ""); ability = ability?.Trim().ToUpperInvariant().Replace(" ", "");
if (string.IsNullOrWhiteSpace(ability)) if (string.IsNullOrWhiteSpace(ability))
return; return;
@ -81,15 +77,15 @@ namespace NadekoBot.Modules.Searches
{ {
if (kvp.Key.ToUpperInvariant() == ability) if (kvp.Key.ToUpperInvariant() == ability)
{ {
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithTitle(kvp.Value.Name) .WithTitle(kvp.Value.Name)
.WithDescription(kvp.Value.Desc) .WithDescription(kvp.Value.Desc)
.AddField(efb => efb.WithName("Rating").WithValue(kvp.Value.Rating.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName("Rating").WithValue(kvp.Value.Rating.ToString()).WithIsInline(true))
.Build()).ConfigureAwait(false); ).ConfigureAwait(false);
return; return;
} }
} }
await channel.SendErrorAsync("No ability found."); await Context.Channel.SendErrorAsync("No ability found.");
} }
} }
} }

View File

@ -1,22 +1,20 @@
using Discord.Commands; using Discord.Commands;
using Newtonsoft.Json.Linq; using Discord;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using NadekoBot.Services; using NadekoBot.Services;
using System.Threading; using System.Threading;
using System.Collections.Generic; using System.Collections.Generic;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Net.Http; using System.Net.Http;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NadekoBot.Services.Database;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Diagnostics;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
@ -67,7 +65,7 @@ namespace NadekoBot.Modules.Searches
} }
[Group] [Group]
public class StreamNotificationCommands public class StreamNotificationCommands : ModuleBase
{ {
private static Timer checkTimer { get; } private static Timer checkTimer { get; }
private static ConcurrentDictionary<string, StreamStatus> oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(); private static ConcurrentDictionary<string, StreamStatus> oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>();
@ -78,8 +76,8 @@ namespace NadekoBot.Modules.Searches
static StreamNotificationCommands() static StreamNotificationCommands()
{ {
_log = LogManager.GetCurrentClassLogger();
_log = NLog.LogManager.GetCurrentClassLogger();
checkTimer = new Timer(async (state) => checkTimer = new Timer(async (state) =>
{ {
oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(cachedStatuses); oldCachedStatuses = new ConcurrentDictionary<string, StreamStatus>(cachedStatuses);
@ -105,14 +103,14 @@ namespace NadekoBot.Modules.Searches
oldStatus.IsLive != newStatus.IsLive) oldStatus.IsLive != newStatus.IsLive)
{ {
var server = NadekoBot.Client.GetGuild(fs.GuildId); var server = NadekoBot.Client.GetGuild(fs.GuildId);
var channel = server?.GetTextChannel(fs.ChannelId); if (server == null)
return;
var channel = await server.GetTextChannelAsync(fs.ChannelId);
if (channel == null) if (channel == null)
return; return;
try try
{ {
var msg = await channel.EmbedAsync(fs.GetEmbed(newStatus).Build()).ConfigureAwait(false); var msg = await channel.EmbedAsync(fs.GetEmbed(newStatus)).ConfigureAwait(false);
if (!newStatus.IsLive)
msg.DeleteAfter(60);
} }
catch { } catch { }
} }
@ -198,66 +196,63 @@ namespace NadekoBot.Modules.Searches
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Hitbox(IUserMessage msg, [Remainder] string username) => public async Task Hitbox([Remainder] string username) =>
await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Hitbox) await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Hitbox)
.ConfigureAwait(false); .ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Twitch(IUserMessage msg, [Remainder] string username) => public async Task Twitch([Remainder] string username) =>
await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Twitch) await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Twitch)
.ConfigureAwait(false); .ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task Beam(IUserMessage msg, [Remainder] string username) => public async Task Beam([Remainder] string username) =>
await TrackStream((ITextChannel)msg.Channel, username, FollowedStream.FollowedStreamType.Beam) await TrackStream((ITextChannel)Context.Channel, username, FollowedStream.FollowedStreamType.Beam)
.ConfigureAwait(false); .ConfigureAwait(false);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ListStreams(IUserMessage imsg) public async Task ListStreams()
{ {
var channel = (ITextChannel)imsg.Channel;
IEnumerable<FollowedStream> streams; IEnumerable<FollowedStream> streams;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
streams = uow.GuildConfigs streams = uow.GuildConfigs
.For(channel.Guild.Id, .For(Context.Guild.Id,
set => set.Include(gc => gc.FollowedStreams)) set => set.Include(gc => gc.FollowedStreams))
.FollowedStreams; .FollowedStreams;
} }
if (!streams.Any()) if (!streams.Any())
{ {
await channel.SendConfirmAsync("You are not following any streams on this server.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync("You are not following any streams on this server.").ConfigureAwait(false);
return; return;
} }
var text = string.Join("\n", streams.Select(snc => var text = string.Join("\n", await Task.WhenAll(streams.Select(async snc =>
{ {
return $"`{snc.Username}`'s stream on **{channel.Guild.GetTextChannel(snc.ChannelId)?.Name}** channel. 【`{snc.Type.ToString()}`】"; var ch = await Context.Guild.GetTextChannelAsync(snc.ChannelId);
})); return $"`{snc.Username}`'s stream on **{(ch)?.Name}** channel. 【`{snc.Type.ToString()}`】";
})));
await channel.SendConfirmAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"You are following **{streams.Count()}** streams on this server.\n\n" + text).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]
public async Task RemoveStream(IUserMessage msg, FollowedStream.FollowedStreamType type, [Remainder] string username) public async Task RemoveStream(FollowedStream.FollowedStreamType type, [Remainder] string username)
{ {
var channel = (ITextChannel)msg.Channel;
username = username.ToLowerInvariant().Trim(); username = username.ToLowerInvariant().Trim();
var fs = new FollowedStream() var fs = new FollowedStream()
{ {
ChannelId = channel.Id, ChannelId = Context.Channel.Id,
Username = username, Username = username,
Type = type Type = type
}; };
@ -265,25 +260,23 @@ namespace NadekoBot.Modules.Searches
bool removed; bool removed;
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.For(channel.Guild.Id, set => set.Include(gc => gc.FollowedStreams)); var config = uow.GuildConfigs.For(Context.Guild.Id, set => set.Include(gc => gc.FollowedStreams));
removed = config.FollowedStreams.Remove(fs); removed = config.FollowedStreams.Remove(fs);
if (removed) if (removed)
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
if (!removed) if (!removed)
{ {
await channel.SendErrorAsync("No such stream.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No such stream.").ConfigureAwait(false);
return; return;
} }
await channel.SendConfirmAsync($"Removed `{username}`'s stream ({type}) from notifications.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Removed `{username}`'s stream ({type}) from notifications.").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task CheckStream(IUserMessage imsg, FollowedStream.FollowedStreamType platform, [Remainder] string username) public async Task CheckStream(FollowedStream.FollowedStreamType platform, [Remainder] string username)
{ {
var channel = (ITextChannel)imsg.Channel;
var stream = username?.Trim(); var stream = username?.Trim();
if (string.IsNullOrWhiteSpace(stream)) if (string.IsNullOrWhiteSpace(stream))
return; return;
@ -296,20 +289,20 @@ namespace NadekoBot.Modules.Searches
})); }));
if (streamStatus.IsLive) if (streamStatus.IsLive)
{ {
await channel.SendConfirmAsync($"Streamer {username} is online with {streamStatus.Views} viewers."); await Context.Channel.SendConfirmAsync($"Streamer {username} is online with {streamStatus.Views} viewers.");
} }
else else
{ {
await channel.SendConfirmAsync($"Streamer {username} is offline."); await Context.Channel.SendConfirmAsync($"Streamer {username} is offline.");
} }
} }
catch catch
{ {
await channel.SendErrorAsync("No channel found."); await Context.Channel.SendErrorAsync("No channel found.");
} }
} }
private async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type) private static async Task TrackStream(ITextChannel channel, string username, FollowedStream.FollowedStreamType type)
{ {
username = username.ToLowerInvariant().Trim(); username = username.ToLowerInvariant().Trim();
var fs = new FollowedStream var fs = new FollowedStream
@ -338,7 +331,7 @@ namespace NadekoBot.Modules.Searches
.Add(fs); .Add(fs);
await uow.CompleteAsync().ConfigureAwait(false); await uow.CompleteAsync().ConfigureAwait(false);
} }
await channel.EmbedAsync(fs.GetEmbed(status).Build(), $"🆗 I will notify this channel when status changes.").ConfigureAwait(false); await channel.EmbedAsync(fs.GetEmbed(status), $"🆗 I will notify this channel when status changes.").ConfigureAwait(false);
} }
} }
} }

View File

@ -6,6 +6,7 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using Discord.WebSocket;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
@ -18,21 +19,18 @@ namespace NadekoBot.Modules.Searches
} }
[Group] [Group]
public class TranslateCommands public class TranslateCommands : ModuleBase
{ {
private static ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } private static ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>();
private static ConcurrentDictionary<UserChannelPair, string> UserLanguages { get; } private static ConcurrentDictionary<UserChannelPair, string> UserLanguages { get; } = new ConcurrentDictionary<UserChannelPair, string>();
static TranslateCommands() static TranslateCommands()
{ {
TranslatedChannels = new ConcurrentDictionary<ulong, bool>();
UserLanguages = new ConcurrentDictionary<UserChannelPair, string>();
NadekoBot.Client.MessageReceived += async (msg) => NadekoBot.Client.MessageReceived += async (msg) =>
{ {
try try
{ {
var umsg = msg as IUserMessage; var umsg = msg as SocketUserMessage;
if (umsg == null) if (umsg == null)
return; return;
@ -49,7 +47,7 @@ namespace NadekoBot.Modules.Searches
if (!UserLanguages.TryGetValue(key, out langs)) if (!UserLanguages.TryGetValue(key, out langs))
return; return;
var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true) var text = await TranslateInternal(langs, umsg.Resolve(TagHandling.Ignore), true)
.ConfigureAwait(false); .ConfigureAwait(false);
if (autoDelete) if (autoDelete)
try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { } try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { }
@ -60,24 +58,21 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Translate(string langs, [Remainder] string text = null)
public async Task Translate(IUserMessage umsg, string langs, [Remainder] string text = null)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
var translation = await TranslateInternal(umsg, langs, text); var translation = await TranslateInternal(langs, text);
await channel.SendConfirmAsync("Translation " + langs, translation).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("Translation " + langs, translation).ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("Bad input format, or something went wrong...").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Bad input format, or something went wrong...").ConfigureAwait(false);
} }
} }
private static async Task<string> TranslateInternal(IUserMessage umsg, string langs, [Remainder] string text = null, bool silent = false) private static async Task<string> TranslateInternal(string langs, [Remainder] string text = null, bool silent = false)
{ {
var langarr = langs.ToLowerInvariant().Split('>'); var langarr = langs.ToLowerInvariant().Split('>');
if (langarr.Length != 2) if (langarr.Length != 2)
@ -98,11 +93,11 @@ namespace NadekoBot.Modules.Searches
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] [RequireUserPermission(GuildPermission.Administrator)]
[OwnerOnly] [OwnerOnly]
public async Task AutoTranslate(IUserMessage msg, AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel) public async Task AutoTranslate(AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel)
{ {
var channel = (ITextChannel)msg.Channel; var channel = (ITextChannel)Context.Channel;
if (autoDelete == AutoDeleteAutoTranslate.Del) if (autoDelete == AutoDeleteAutoTranslate.Del)
{ {
@ -125,20 +120,18 @@ namespace NadekoBot.Modules.Searches
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task AutoTransLang(IUserMessage msg, [Remainder] string langs = null) public async Task AutoTransLang([Remainder] string langs = null)
{ {
var channel = (ITextChannel)msg.Channel;
var ucp = new UserChannelPair var ucp = new UserChannelPair
{ {
UserId = msg.Author.Id, UserId = Context.User.Id,
ChannelId = msg.Channel.Id, ChannelId = Context.Channel.Id,
}; };
if (string.IsNullOrWhiteSpace(langs)) if (string.IsNullOrWhiteSpace(langs))
{ {
if (UserLanguages.TryRemove(ucp, out langs)) if (UserLanguages.TryRemove(ucp, out langs))
await channel.SendConfirmAsync($"{msg.Author.Mention}'s auto-translate language has been removed.").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"{Context.User.Mention}'s auto-translate language has been removed.").ConfigureAwait(false);
return; return;
} }
@ -150,22 +143,20 @@ namespace NadekoBot.Modules.Searches
if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to)) if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to))
{ {
try { await channel.SendErrorAsync("Invalid source and/or target language.").ConfigureAwait(false); } catch { } try { await Context.Channel.SendErrorAsync("Invalid source and/or target language.").ConfigureAwait(false); } catch { }
return; return;
} }
UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs); UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs);
await channel.SendConfirmAsync($"Your auto-translate language has been set to {from}>{to}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"Your auto-translate language has been set to {from}>{to}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Translangs(IUserMessage umsg) public async Task Translangs()
{ {
var channel = (ITextChannel)umsg.Channel; await Context.Channel.SendTableAsync(GoogleTranslator.Instance.Languages, str => $"{str,-15}", columns: 3);
await channel.SendTableAsync(GoogleTranslator.Instance.Languages, str => $"{str,-15}", columns: 3);
} }
} }

View File

@ -12,24 +12,21 @@ namespace NadekoBot.Modules.Searches
public partial class Searches public partial class Searches
{ {
[Group] [Group]
public class XkcdCommands public class XkcdCommands : ModuleBase
{ {
private const string xkcdUrl = "https://xkcd.com"; private const string xkcdUrl = "https://xkcd.com";
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public async Task Xkcd(IUserMessage msg, string arg = null) public async Task Xkcd(string arg = null)
{ {
var channel = (ITextChannel)msg.Channel;
if (arg?.ToLowerInvariant().Trim() == "latest") if (arg?.ToLowerInvariant().Trim() == "latest")
{ {
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var res = await http.GetStringAsync($"{xkcdUrl}/info.0.json").ConfigureAwait(false); var res = await http.GetStringAsync($"{xkcdUrl}/info.0.json").ConfigureAwait(false);
var comic = JsonConvert.DeserializeObject<XkcdComic>(res); var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
var sent = await channel.SendMessageAsync($"{msg.Author.Mention} " + comic.ToString()) var sent = await Context.Channel.SendMessageAsync($"{Context.User.Mention} " + comic.ToString())
.ConfigureAwait(false); .ConfigureAwait(false);
await Task.Delay(10000).ConfigureAwait(false); await Task.Delay(10000).ConfigureAwait(false);
@ -38,16 +35,13 @@ namespace NadekoBot.Modules.Searches
} }
return; return;
} }
await Xkcd(msg, new NadekoRandom().Next(1, 1750)).ConfigureAwait(false); await Xkcd(new NadekoRandom().Next(1, 1750)).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[Priority(0)] [Priority(0)]
public async Task Xkcd(IUserMessage msg, int num) public async Task Xkcd(int num)
{ {
var channel = (ITextChannel)msg.Channel;
if (num < 1) if (num < 1)
return; return;
@ -56,12 +50,12 @@ namespace NadekoBot.Modules.Searches
var res = await http.GetStringAsync($"{xkcdUrl}/{num}/info.0.json").ConfigureAwait(false); var res = await http.GetStringAsync($"{xkcdUrl}/{num}/info.0.json").ConfigureAwait(false);
var comic = JsonConvert.DeserializeObject<XkcdComic>(res); var comic = JsonConvert.DeserializeObject<XkcdComic>(res);
var embed = new EmbedBuilder().WithOkColor() var embed = new EmbedBuilder().WithColor(NadekoBot.OkColor)
.WithImage(eib => eib.WithUrl(comic.ImageLink)) .WithImageUrl(comic.ImageLink)
.WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{xkcdUrl}/{num}").WithIconUrl("http://xkcd.com/s/919f27.ico")) .WithAuthor(eab => eab.WithName(comic.Title).WithUrl($"{xkcdUrl}/{num}").WithIconUrl("http://xkcd.com/s/919f27.ico"))
.AddField(efb => efb.WithName("Comic#").WithValue(comic.Num.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName("Comic#").WithValue(comic.Num.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName("Date").WithValue($"{comic.Month}/{comic.Year}").WithIsInline(true)); .AddField(efb => efb.WithName("Date").WithValue($"{comic.Month}/{comic.Year}").WithIsInline(true));
var sent = await channel.EmbedAsync(embed.Build()) var sent = await Context.Channel.EmbedAsync(embed)
.ConfigureAwait(false); .ConfigureAwait(false);
await Task.Delay(10000).ConfigureAwait(false); await Task.Delay(10000).ConfigureAwait(false);

View File

@ -31,10 +31,8 @@ namespace NadekoBot.Modules.Searches
public partial class Searches : DiscordModule public partial class Searches : DiscordModule
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Weather([Remainder] string query)
public async Task Weather(IUserMessage umsg, [Remainder] string query)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
@ -56,75 +54,63 @@ namespace NadekoBot.Modules.Searches
.AddField(fb => fb.WithName("🌇 **Sunset (utc)**").WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm}").WithIsInline(true)) .AddField(fb => fb.WithName("🌇 **Sunset (utc)**").WithValue($"{data.sys.sunset.ToUnixTimestamp():HH:mm}").WithIsInline(true))
.WithOkColor() .WithOkColor()
.WithFooter(efb => efb.WithText("Powered by http://openweathermap.org")); .WithFooter(efb => efb.WithText("Powered by http://openweathermap.org"));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Youtube([Remainder] string query = null)
public async Task Youtube(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel; if (!(await ValidateQuery(Context.Channel, query).ConfigureAwait(false))) return;
if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return;
var result = (await NadekoBot.Google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault(); var result = (await NadekoBot.Google.GetVideosByKeywordsAsync(query, 1)).FirstOrDefault();
if (string.IsNullOrWhiteSpace(result)) if (string.IsNullOrWhiteSpace(result))
{ {
await channel.SendErrorAsync("No results found for that query.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No results found for that query.").ConfigureAwait(false);
return; return;
} }
await channel.SendMessageAsync(result).ConfigureAwait(false); await Context.Channel.SendMessageAsync(result).ConfigureAwait(false);
//await channel.EmbedAsync(new Discord.API.Embed() { Video = new Discord.API.EmbedVideo() { Url = result.Replace("watch?v=", "embed/") }, Color = NadekoBot.OkColor }).ConfigureAwait(false); //await Context.Channel.EmbedAsync(new Discord.API.Embed() { Video = new Discord.API.EmbedVideo() { Url = result.Replace("watch?v=", "embed/") }, Color = NadekoBot.OkColor }).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Imdb([Remainder] string query = null)
public async Task Imdb(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel; if (!(await ValidateQuery(Context.Channel, query).ConfigureAwait(false))) return;
await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
if (!(await ValidateQuery(channel, query).ConfigureAwait(false))) return;
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false);
var movie = await OmdbProvider.FindMovie(query); var movie = await OmdbProvider.FindMovie(query);
if (movie == null) if (movie == null)
{ {
await channel.SendErrorAsync("Failed to find that movie.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed to find that movie.").ConfigureAwait(false);
return; return;
} }
await channel.EmbedAsync(movie.GetEmbed()).ConfigureAwait(false); await Context.Channel.EmbedAsync(movie.GetEmbed()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task RandomCat()
public async Task RandomCat(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var res = JObject.Parse(await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false)); var res = JObject.Parse(await http.GetStringAsync("http://www.random.cat/meow").ConfigureAwait(false));
await channel.SendMessageAsync(res["file"].ToString()).ConfigureAwait(false); await Context.Channel.SendMessageAsync(res["file"].ToString()).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task RandomDog()
public async Task RandomDog(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
await channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof") await Context.Channel.SendMessageAsync("http://random.dog/" + await http.GetStringAsync("http://random.dog/woof")
.ConfigureAwait(false)).ConfigureAwait(false); .ConfigureAwait(false)).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task I([Remainder] string query = null)
public async Task I(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
try try
@ -133,29 +119,26 @@ namespace NadekoBot.Modules.Searches
{ {
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}"; var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}";
var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false));
await channel.SendMessageAsync(obj["items"][0]["link"].ToString()).ConfigureAwait(false); await Context.Channel.SendMessageAsync(obj["items"][0]["link"].ToString()).ConfigureAwait(false);
} }
} }
catch (HttpRequestException exception) catch (HttpRequestException exception)
{ {
if (exception.Message.Contains("403 (Forbidden)")) if (exception.Message.Contains("403 (Forbidden)"))
{ {
await channel.SendErrorAsync("Daily limit reached!"); await Context.Channel.SendErrorAsync("Daily limit reached!");
} }
else else
{ {
await channel.SendErrorAsync("Something went wrong."); await Context.Channel.SendErrorAsync("Something went wrong.");
_log.Error(exception); _log.Error(exception);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Ir([Remainder] string query = null)
public async Task Ir(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
try try
@ -166,40 +149,35 @@ namespace NadekoBot.Modules.Searches
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}"; var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(query)}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Credentials.GoogleApiKey}";
var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false)); var obj = JObject.Parse(await http.GetStringAsync(reqString).ConfigureAwait(false));
var items = obj["items"] as JArray; var items = obj["items"] as JArray;
await channel.SendMessageAsync(items[0]["link"].ToString()).ConfigureAwait(false); await Context.Channel.SendMessageAsync(items[0]["link"].ToString()).ConfigureAwait(false);
} }
} }
catch (HttpRequestException exception) catch (HttpRequestException exception)
{ {
if (exception.Message.Contains("403 (Forbidden)")) if (exception.Message.Contains("403 (Forbidden)"))
{ {
await channel.SendErrorAsync("Daily limit reached!"); await Context.Channel.SendErrorAsync("Daily limit reached!");
} }
else else
{ {
await channel.SendErrorAsync("Something went wrong."); await Context.Channel.SendErrorAsync("Something went wrong.");
_log.Error(exception); _log.Error(exception);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Lmgtfy([Remainder] string ffs = null)
public async Task Lmgtfy(IUserMessage umsg, [Remainder] string ffs = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(ffs)) if (string.IsNullOrWhiteSpace(ffs))
return; return;
await channel.SendConfirmAsync(await NadekoBot.Google.ShortenUrl($"<http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }>")) await Context.Channel.SendConfirmAsync(await NadekoBot.Google.ShortenUrl($"<http://lmgtfy.com/?q={ Uri.EscapeUriString(ffs) }>"))
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Shorten([Remainder] string arg)
public async Task Shorten(IUserMessage msg, [Remainder] string arg)
{ {
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;
@ -208,15 +186,14 @@ namespace NadekoBot.Modules.Searches
if (shortened == arg) if (shortened == arg)
{ {
await msg.Channel.SendErrorAsync("Failed to shorten that url.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed to shorten that url.").ConfigureAwait(false);
} }
await msg.Channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithColor(NadekoBot.OkColor)
.AddField(efb => efb.WithName("Original Url") .AddField(efb => efb.WithName("Original Url")
.WithValue($"<{arg}>")) .WithValue($"<{arg}>"))
.AddField(efb => efb.WithName("Short Url") .AddField(efb => efb.WithName("Short Url")
.WithValue($"<{shortened}>")) .WithValue($"<{shortened}>")))
.Build())
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -224,11 +201,8 @@ namespace NadekoBot.Modules.Searches
//private readonly Regex htmlReplace = new Regex(@"(?:<b>(.*?)<\/b>|<em>(.*?)<\/em>)", RegexOptions.Compiled); //private readonly Regex htmlReplace = new Regex(@"(?:<b>(.*?)<\/b>|<em>(.*?)<\/em>)", RegexOptions.Compiled);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Google([Remainder] string terms = null)
public async Task Google(IUserMessage umsg, [Remainder] string terms = null)
{ {
var channel = (ITextChannel)umsg.Channel;
terms = terms?.Trim(); terms = terms?.Trim();
if (string.IsNullOrWhiteSpace(terms)) if (string.IsNullOrWhiteSpace(terms))
return; return;
@ -269,28 +243,26 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(eab => eab.WithName("Search For: " + terms.TrimTo(50)) .WithAuthor(eab => eab.WithName("Search For: " + terms.TrimTo(50))
.WithUrl(fullQueryLink) .WithUrl(fullQueryLink)
.WithIconUrl("http://i.imgur.com/G46fm8J.png")) .WithIconUrl("http://i.imgur.com/G46fm8J.png"))
.WithTitle(umsg.Author.Mention) .WithTitle(Context.User.Mention)
.WithFooter(efb => efb.WithText(totalResults)); .WithFooter(efb => efb.WithText(totalResults));
var desc = await Task.WhenAll(results.Select(async res => var desc = await Task.WhenAll(results.Select(async res =>
$"[{Format.Bold(res?.Title)}]({(await NadekoBot.Google.ShortenUrl(res?.Link))})\n{res?.Text}\n\n")) $"[{Format.Bold(res?.Title)}]({(await NadekoBot.Google.ShortenUrl(res?.Link))})\n{res?.Text}\n\n"))
.ConfigureAwait(false); .ConfigureAwait(false);
await channel.EmbedAsync(embed.WithDescription(String.Concat(desc)).Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed.WithDescription(String.Concat(desc))).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task MagicTheGathering([Remainder] string name = null)
public async Task MagicTheGathering(IUserMessage umsg, [Remainder] string name = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = name; var arg = name;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
string response = ""; string response = "";
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
@ -311,40 +283,38 @@ namespace NadekoBot.Modules.Searches
var embed = new EmbedBuilder().WithOkColor() var embed = new EmbedBuilder().WithOkColor()
.WithTitle(item["name"].ToString()) .WithTitle(item["name"].ToString())
.WithDescription(desc) .WithDescription(desc)
.WithImage(eib => eib.WithUrl(img)) .WithImageUrl(img)
.AddField(efb => efb.WithName("Store Url").WithValue(storeUrl).WithIsInline(true)) .AddField(efb => efb.WithName("Store Url").WithValue(storeUrl).WithIsInline(true))
.AddField(efb => efb.WithName("Cost").WithValue(cost).WithIsInline(true)) .AddField(efb => efb.WithName("Cost").WithValue(cost).WithIsInline(true))
.AddField(efb => efb.WithName("Types").WithValue(types).WithIsInline(true)); .AddField(efb => efb.WithName("Types").WithValue(types).WithIsInline(true));
//.AddField(efb => efb.WithName("Store Url").WithValue(await NadekoBot.Google.ShortenUrl(items[0]["store_url"].ToString())).WithIsInline(true)); //.AddField(efb => efb.WithName("Store Url").WithValue(await NadekoBot.Google.ShortenUrl(items[0]["store_url"].ToString())).WithIsInline(true));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync($"Error could not find the card '{arg}'.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Error could not find the card '{arg}'.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Hearthstone([Remainder] string name = null)
public async Task Hearthstone(IUserMessage umsg, [Remainder] string name = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = name; var arg = name;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a card name to search for.").ConfigureAwait(false);
return; return;
} }
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{ {
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
string response = ""; string response = "";
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
@ -355,7 +325,7 @@ namespace NadekoBot.Modules.Searches
try try
{ {
var items = JArray.Parse(response).Shuffle().ToList(); var items = JArray.Parse(response).Shuffle().ToList();
var images = new List<Image>(); var images = new List<ImageSharp.Image>();
if (items == null) if (items == null)
throw new KeyNotFoundException("Cannot find a card by that name"); throw new KeyNotFoundException("Cannot find a card by that name");
foreach (var item in items.Where(item => item.HasValues && item["img"] != null).Take(4)) foreach (var item in items.Where(item => item.HasValues && item["img"] != null).Take(4))
@ -365,7 +335,7 @@ namespace NadekoBot.Modules.Searches
var imgStream = new MemoryStream(); var imgStream = new MemoryStream();
await sr.CopyToAsync(imgStream); await sr.CopyToAsync(imgStream);
imgStream.Position = 0; imgStream.Position = 0;
images.Add(new Image(imgStream)); images.Add(new ImageSharp.Image(imgStream));
} }
} }
string msg = null; string msg = null;
@ -374,37 +344,34 @@ namespace NadekoBot.Modules.Searches
msg = "⚠ Found over 4 images. Showing random 4."; msg = "⚠ Found over 4 images. Showing random 4.";
} }
var ms = new MemoryStream(); var ms = new MemoryStream();
images.Merge().SaveAsPng(ms); images.AsEnumerable().Merge().SaveAsPng(ms);
ms.Position = 0; ms.Position = 0;
await channel.SendFileAsync(ms, arg + ".png", msg).ConfigureAwait(false); await Context.Channel.SendFileAsync(ms, arg + ".png", msg).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
await channel.SendErrorAsync($"Error occured.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Error occured.").ConfigureAwait(false);
_log.Error(ex); _log.Error(ex);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Yodify([Remainder] string query = null)
public async Task Yodify(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{ {
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
return; return;
} }
var arg = query; var arg = query;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter a sentence.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a sentence.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
http.DefaultRequestHeaders.Clear(); http.DefaultRequestHeaders.Clear();
@ -418,34 +385,31 @@ namespace NadekoBot.Modules.Searches
.WithAuthor(au => au.WithName("Yoda").WithIconUrl("http://www.yodaspeak.co.uk/yoda-small1.gif")) .WithAuthor(au => au.WithName("Yoda").WithIconUrl("http://www.yodaspeak.co.uk/yoda-small1.gif"))
.WithDescription(res) .WithDescription(res)
.WithOkColor(); .WithOkColor();
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("Failed to yodify your sentence.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed to yodify your sentence.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task UrbanDict([Remainder] string query = null)
public async Task UrbanDict(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{ {
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
return; return;
} }
var arg = query; var arg = query;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
http.DefaultRequestHeaders.Clear(); http.DefaultRequestHeaders.Clear();
@ -462,21 +426,18 @@ namespace NadekoBot.Modules.Searches
.WithUrl(link) .WithUrl(link)
.WithAuthor(eab => eab.WithIconUrl("http://i.imgur.com/nwERwQE.jpg").WithName(word)) .WithAuthor(eab => eab.WithIconUrl("http://i.imgur.com/nwERwQE.jpg").WithName(word))
.WithDescription(def); .WithDescription(def);
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
catch catch
{ {
await channel.SendErrorAsync("Failed finding a definition for that term.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed finding a definition for that term.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Define([Remainder] string word)
public async Task Define(IUserMessage msg, [Remainder] string word)
{ {
var channel = (ITextChannel)msg.Channel;
if (string.IsNullOrWhiteSpace(word)) if (string.IsNullOrWhiteSpace(word))
return; return;
@ -503,29 +464,26 @@ namespace NadekoBot.Modules.Searches
if (sense.Examples != null) if (sense.Examples != null)
embed.AddField(efb => efb.WithName("Example").WithValue(sense.Examples.First().text)); embed.AddField(efb => efb.WithName("Example").WithValue(sense.Examples.First().text));
await channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Hashtag([Remainder] string query = null)
public async Task Hashtag(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = query; var arg = query;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a search term.").ConfigureAwait(false);
return; return;
} }
if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey)) if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.MashapeKey))
{ {
await channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Bot owner didn't specify MashapeApiKey. You can't use this functionality.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
string res = ""; string res = "";
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
@ -541,24 +499,21 @@ namespace NadekoBot.Modules.Searches
var hashtag = item["hashtag"].ToString(); var hashtag = item["hashtag"].ToString();
var link = item["uri"].ToString(); var link = item["uri"].ToString();
var desc = item["text"].ToString(); var desc = item["text"].ToString();
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithUrl(link) .WithAuthor(eab => eab.WithUrl(link)
.WithIconUrl("http://res.cloudinary.com/urbandictionary/image/upload/a_exif,c_fit,h_200,w_200/v1394975045/b8oszuu3tbq7ebyo7vo1.jpg") .WithIconUrl("http://res.cloudinary.com/urbandictionary/image/upload/a_exif,c_fit,h_200,w_200/v1394975045/b8oszuu3tbq7ebyo7vo1.jpg")
.WithName(query)) .WithName(query))
.WithDescription(desc) .WithDescription(desc));
.Build());
} }
catch catch
{ {
await channel.SendErrorAsync("Failed finding a definition for that tag.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Failed finding a definition for that tag.").ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Catfact()
public async Task Catfact(IUserMessage umsg)
{ {
var channel = (ITextChannel)umsg.Channel;
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false); var response = await http.GetStringAsync("http://catfacts-api.appspot.com/api/facts").ConfigureAwait(false);
@ -566,44 +521,35 @@ namespace NadekoBot.Modules.Searches
return; return;
var fact = JObject.Parse(response)["facts"][0].ToString(); var fact = JObject.Parse(response)["facts"][0].ToString();
await channel.SendConfirmAsync("🐈fact", fact).ConfigureAwait(false); await Context.Channel.SendConfirmAsync("🐈fact", fact).ConfigureAwait(false);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Revav([Remainder] IUser usr = null)
public async Task Revav(IUserMessage umsg, [Remainder] IUser usr = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (usr == null) if (usr == null)
usr = umsg.Author; usr = Context.User;
await channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={usr.AvatarUrl}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Revimg([Remainder] string imageLink = null)
public async Task Revimg(IUserMessage umsg, [Remainder] string imageLink = null)
{ {
var channel = (ITextChannel)umsg.Channel;
imageLink = imageLink?.Trim() ?? ""; imageLink = imageLink?.Trim() ?? "";
if (string.IsNullOrWhiteSpace(imageLink)) if (string.IsNullOrWhiteSpace(imageLink))
return; return;
await channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"https://images.google.com/searchbyimage?image_url={imageLink}").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public Task Safebooru([Remainder] string tag = null)
public Task Safebooru(IUserMessage umsg, [Remainder] string tag = null) => InternalDapiCommand(Context.Message, tag, DapiSearchType.Safebooru);
=> InternalDapiCommand(umsg, tag, DapiSearchType.Safebooru);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Wiki([Remainder] string query = null)
public async Task Wiki(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
query = query?.Trim(); query = query?.Trim();
if (string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(query))
return; return;
@ -612,22 +558,19 @@ namespace NadekoBot.Modules.Searches
var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query)); var result = await http.GetStringAsync("https://en.wikipedia.org//w/api.php?action=query&format=json&prop=info&redirects=1&formatversion=2&inprop=url&titles=" + Uri.EscapeDataString(query));
var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result); var data = JsonConvert.DeserializeObject<WikipediaApiModel>(result);
if (data.Query.Pages[0].Missing) if (data.Query.Pages[0].Missing)
await channel.SendErrorAsync("That page could not be found."); await Context.Channel.SendErrorAsync("That page could not be found.");
else else
await channel.SendMessageAsync(data.Query.Pages[0].FullUrl); await Context.Channel.SendMessageAsync(data.Query.Pages[0].FullUrl);
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Color([Remainder] string color = null)
public async Task Color(IUserMessage umsg, [Remainder] string color = null)
{ {
var channel = (ITextChannel)umsg.Channel;
color = color?.Trim().Replace("#", ""); color = color?.Trim().Replace("#", "");
if (string.IsNullOrWhiteSpace((string)color)) if (string.IsNullOrWhiteSpace((string)color))
return; return;
var img = new Image(50, 50); var img = new ImageSharp.Image(50, 50);
var red = Convert.ToInt32(color.Substring(0, 2), 16); var red = Convert.ToInt32(color.Substring(0, 2), 16);
var green = Convert.ToInt32(color.Substring(2, 2), 16); var green = Convert.ToInt32(color.Substring(2, 2), 16);
@ -635,18 +578,15 @@ namespace NadekoBot.Modules.Searches
img.BackgroundColor(new ImageSharp.Color(color)); img.BackgroundColor(new ImageSharp.Color(color));
await channel.SendFileAsync(img.ToStream(), $"{color}.png"); await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png");
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Videocall([Remainder] params IUser[] users)
public async Task Videocall(IUserMessage umsg, [Remainder] string arg = null)
{ {
var channel = (ITextChannel)umsg.Channel;
try try
{ {
var allUsrs = umsg.MentionedUsers.Append(umsg.Author); var allUsrs = users.Append(Context.User);
var allUsrsArray = allUsrs.ToArray(); var allUsrsArray = allUsrs.ToArray();
var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Username[0].ToString())); var str = allUsrsArray.Aggregate("http://appear.in/", (current, usr) => current + Uri.EscapeUriString(usr.Username[0].ToString()));
str += new NadekoRandom().Next(); str += new NadekoRandom().Next();
@ -662,31 +602,25 @@ namespace NadekoBot.Modules.Searches
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Avatar([Remainder] IUser usr = null)
public async Task Avatar(IUserMessage umsg, [Remainder] string mention = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var usr = umsg.MentionedUsers.FirstOrDefault();
if (usr == null) if (usr == null)
{ usr = Context.User;
await channel.SendErrorAsync("Invalid user specified.").ConfigureAwait(false);
return; await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
} .WithTitle($"{usr}'s Avatar")
await channel.SendMessageAsync(await NadekoBot.Google.ShortenUrl(usr.AvatarUrl).ConfigureAwait(false)).ConfigureAwait(false); .WithImageUrl(usr.AvatarUrl)).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task Wikia(string target, [Remainder] string query = null)
public async Task Wikia(IUserMessage umsg, string target, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query)) if (string.IsNullOrWhiteSpace(target) || string.IsNullOrWhiteSpace(query))
{ {
await channel.SendErrorAsync("Please enter a target wikia, followed by search query.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter a target wikia, followed by search query.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
http.DefaultRequestHeaders.Clear(); http.DefaultRequestHeaders.Clear();
@ -698,27 +632,25 @@ namespace NadekoBot.Modules.Searches
var response = $@"`Title:` {found["title"].ToString()} var response = $@"`Title:` {found["title"].ToString()}
`Quality:` {found["quality"]} `Quality:` {found["quality"]}
`URL:` {await NadekoBot.Google.ShortenUrl(found["url"].ToString()).ConfigureAwait(false)}"; `URL:` {await NadekoBot.Google.ShortenUrl(found["url"].ToString()).ConfigureAwait(false)}";
await channel.SendMessageAsync(response); await Context.Channel.SendMessageAsync(response);
} }
catch catch
{ {
await channel.SendErrorAsync($"Failed finding `{query}`.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Failed finding `{query}`.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task MCPing([Remainder] string query = null)
public async Task MCPing(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = query; var arg = query;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("💢 Please enter a `ip:port`.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
http.DefaultRequestHeaders.Clear(); http.DefaultRequestHeaders.Clear();
@ -735,27 +667,25 @@ namespace NadekoBot.Modules.Searches
sb.AppendLine($"`Description:` {items["description"].ToString()}"); sb.AppendLine($"`Description:` {items["description"].ToString()}");
sb.AppendLine($"`Online Players:` {items["players"]["online"].ToString()}/{items["players"]["max"].ToString()}"); sb.AppendLine($"`Online Players:` {items["players"]["online"].ToString()}/{items["players"]["max"].ToString()}");
sb.Append($"`Latency:` {ping}"); sb.Append($"`Latency:` {ping}");
await channel.SendMessageAsync(sb.ToString()); await Context.Channel.SendMessageAsync(sb.ToString());
} }
catch catch
{ {
await channel.SendErrorAsync($"Failed finding `{arg}`.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Failed finding `{arg}`.").ConfigureAwait(false);
} }
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task MCQ([Remainder] string query = null)
public async Task MCQ(IUserMessage umsg, [Remainder] string query = null)
{ {
var channel = (ITextChannel)umsg.Channel;
var arg = query; var arg = query;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
{ {
await channel.SendErrorAsync("Please enter `ip:port`.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Please enter `ip:port`.").ConfigureAwait(false);
return; return;
} }
await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); await Context.Channel.TriggerTypingAsync().ConfigureAwait(false);
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
http.DefaultRequestHeaders.Clear(); http.DefaultRequestHeaders.Clear();
@ -775,11 +705,11 @@ namespace NadekoBot.Modules.Searches
sb.AppendLine($"`Online Players:` {items["Players"]} / {items["MaxPlayers"]}"); sb.AppendLine($"`Online Players:` {items["Players"]} / {items["MaxPlayers"]}");
sb.AppendLine($"`Plugins:` {items["Plugins"]}"); sb.AppendLine($"`Plugins:` {items["Plugins"]}");
sb.Append($"`Version:` {items["Version"]}"); sb.Append($"`Version:` {items["Version"]}");
await channel.SendMessageAsync(sb.ToString()); await Context.Channel.SendMessageAsync(sb.ToString());
} }
catch catch
{ {
await channel.SendErrorAsync($"Failed finding server `{arg}`.").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"Failed finding server `{arg}`.").ConfigureAwait(false);
} }
} }
} }
@ -795,7 +725,7 @@ namespace NadekoBot.Modules.Searches
public static async Task InternalDapiCommand(IUserMessage umsg, string tag, DapiSearchType type) public static async Task InternalDapiCommand(IUserMessage umsg, string tag, DapiSearchType type)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = umsg.Channel;
tag = tag?.Trim() ?? ""; tag = tag?.Trim() ?? "";
@ -807,8 +737,7 @@ namespace NadekoBot.Modules.Searches
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithDescription(umsg.Author.Mention + " " + tag) .WithDescription(umsg.Author.Mention + " " + tag)
.WithImageUrl(url) .WithImageUrl(url)
.WithFooter(efb => efb.WithText(type.ToString())) .WithFooter(efb => efb.WithText(type.ToString()))).ConfigureAwait(false);
.Build()).ConfigureAwait(false);
} }
public static async Task<string> InternalDapiSearch(string tag, DapiSearchType type) public static async Task<string> InternalDapiSearch(string tag, DapiSearchType type)
@ -855,7 +784,7 @@ namespace NadekoBot.Modules.Searches
return null; return null;
} }
} }
public static async Task<bool> ValidateQuery(ITextChannel ch, string query) public static async Task<bool> ValidateQuery(IMessageChannel ch, string query)
{ {
if (!string.IsNullOrEmpty(query.Trim())) return true; if (!string.IsNullOrEmpty(query.Trim())) return true;
await ch.SendErrorAsync("Please specify search parameters.").ConfigureAwait(false); await ch.SendErrorAsync("Please specify search parameters.").ConfigureAwait(false);

View File

@ -1,145 +0,0 @@
//using Discord.Modules;
//using Manatee.Trello;
//using Manatee.Trello.ManateeJson;
//using NadekoBot.Extensions;
//using NadekoBot.Modules.Permissions.Classes;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Timers;
//using Action = Manatee.Trello.Action;
////todo rewrite
//namespace NadekoBot.Modules.Trello
//{
// public class Trello : DiscordModule
// {
// private readonly Timer t = new Timer { Interval = 2000 };
// public override string Prefix { get; } = NadekoBot.Config.CommandPrefixes.Trello;
// public override void Install(ModuleManager manager)
// {
// var client = manager.Client;
// var serializer = new ManateeSerializer();
// TrelloConfiguration.Serializer = serializer;
// TrelloConfiguration.Deserializer = serializer;
// TrelloConfiguration.JsonFactory = new ManateeFactory();
// TrelloConfiguration.RestClientProvider = new Manatee.Trello.WebApi.WebApiClientProvider();
// TrelloAuthorization.Default.AppKey = NadekoBot.Credentials.TrelloAppKey;
// //TrelloAuthorization.Default.UserToken = "[your user token]";
// Discord.Channel bound = null;
// Board board = null;
// List<string> last5ActionIDs = null;
// t.Elapsed += async (s, e) =>
// {
// try
// {
// if (board == null || bound == null)
// return; //do nothing if there is no bound board
// board.Refresh();
// var cur5Actions = board.Actions.Take(board.Actions.Count() < 5 ? board.Actions.Count() : 5);
// var cur5ActionsArray = cur5Actions as Action[] ?? cur5Actions.ToArray();
// if (last5ActionIDs == null)
// {
// last5ActionIDs = cur5ActionsArray.Select(a => a.Id).ToList();
// return;
// }
// foreach (var a in cur5ActionsArray.Where(ca => !last5ActionIDs.Contains(ca.Id)))
// {
// await bound.Send("**--TRELLO NOTIFICATION--**\n" + a.ToString()).ConfigureAwait(false);
// }
// last5ActionIDs.Clear();
// last5ActionIDs.AddRange(cur5ActionsArray.Select(a => a.Id));
// }
// catch (Exception ex)
// {
// Console.WriteLine("Timer failed " + ex.ToString());
// }
// };
// manager.CreateCommands("", cgb =>
// {
// cgb.AddCheck(PermissionChecker.Instance);
// cgb.CreateCommand(Prefix + "bind")
// .Description("Bind a trello bot to a single channel. " +
// "You will receive notifications from your board when something is added or edited." +
// $" **Bot Owner Only!**| `{Prefix}bind [board_id]`")
// .Parameter("board_id", Discord.Commands.ParameterType.Required)
// .Do(async e =>
// {
// if (!NadekoBot.IsOwner(umsg.Author.Id)) return;
// if (bound != null) return;
// try
// {
// bound = e.Channel;
// board = new Board(board_id.Trim());
// board.Refresh();
// await channel.SendMessageAsync("Successfully bound to this channel and board " + board.Name);
// t.Start();
// }
// catch (Exception ex)
// {
// Console.WriteLine("Failed to join the board. " + ex.ToString());
// }
// });
// cgb.CreateCommand(Prefix + "unbind")
// .Description($"Unbinds a bot from the channel and board. **Bot Owner Only!**| `{Prefix}unbind`")
// .Do(async e =>
// {
// if (!NadekoBot.IsOwner(umsg.Author.Id)) return;
// if (bound == null || bound != e.Channel) return;
// t.Stop();
// bound = null;
// board = null;
// await channel.SendMessageAsync("Successfully unbound trello from this channel.").ConfigureAwait(false);
// });
// cgb.CreateCommand(Prefix + "lists")
// .Alias(Prefix + "list")
// .Description($"Lists all lists, yo ;) **Bot Owner Only!**| `{Prefix}list`")
// .Do(async e =>
// {
// if (!NadekoBot.IsOwner(umsg.Author.Id)) return;
// if (bound == null || board == null || bound != e.Channel) return;
// await channel.SendMessageAsync("Lists for a board '" + board.Name + "'\n" + string.Join("\n", board.Lists.Select(l => "**• " + l.ToString() + "**")))
// .ConfigureAwait(false);
// });
// cgb.CreateCommand(Prefix + "cards")
// .Description($"Lists all cards from the supplied list. You can supply either a name or an index. **Bot Owner Only!**| `{Prefix}cards index`")
// .Parameter("list_name", Discord.Commands.ParameterType.Unparsed)
// .Do(async e =>
// {
// if (!NadekoBot.IsOwner(umsg.Author.Id)) return;
// if (bound == null || board == null || bound != e.Channel || list_name == null) return;
// int num;
// var success = int.TryParse(list_name, out num);
// List list = null;
// if (success && num <= board.Lists.Count() && num > 0)
// list = board.Lists[num - 1];
// else
// list = board.Lists.FirstOrDefault(l => l.Name == list_name);
// if (list != null)
// await channel.SendMessageAsync("There are " + list.Cards.Count() + " cards in a **" + list.Name + "** list\n" + string.Join("\n", list.Cards.Select(c => "**• " + c.ToString() + "**")))
// .ConfigureAwait(false);
// else
// await channel.SendMessageAsync("No such list.")
// .ConfigureAwait(false);
// });
// });
// }
// }
//}

View File

@ -1,68 +1,70 @@
using Discord; using Discord.Commands;
using Discord.Commands;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
public partial class Utility public partial class Utility
{ {
[NadekoCommand, Usage, Description, Aliases] [Group]
[RequireContext(ContextType.Guild)] public class CalcCommands : ModuleBase
public static async Task Calculate(IUserMessage msg, [Remainder] string expression)
{ {
var expr = new NCalc.Expression(expression, NCalc.EvaluateOptions.IgnoreCase); [NadekoCommand, Usage, Description, Aliases]
expr.EvaluateParameter += Expr_EvaluateParameter; public async Task Calculate([Remainder] string expression)
var result = expr.Evaluate();
if (expr.Error == null)
await msg.Channel.SendConfirmAsync("Result", $"{result}");
else
await msg.Channel.SendErrorAsync($"⚙ Error", expr.Error);
}
private static void Expr_EvaluateParameter(string name, NCalc.ParameterArgs args)
{
switch (name.ToLowerInvariant()) {
case "pi": args.Result= Math.PI;
break;
case "e": args.Result = Math.E;
break;
}
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task CalcOps(IUserMessage msg)
{
var selection = typeof(Math).GetTypeInfo().GetMethods().Except(typeof(object).GetTypeInfo().GetMethods()).Distinct(new MethodInfoEqualityComparer()).Select(x =>
{ {
return x.Name; var expr = new NCalc.Expression(expression, NCalc.EvaluateOptions.IgnoreCase);
}) expr.EvaluateParameter += Expr_EvaluateParameter;
.Except(new[] { "ToString", var result = expr.Evaluate();
if (expr.Error == null)
await Context.Channel.SendConfirmAsync("Result", $"{result}");
else
await Context.Channel.SendErrorAsync($"⚙ Error", expr.Error);
}
private static void Expr_EvaluateParameter(string name, NCalc.ParameterArgs args)
{
switch (name.ToLowerInvariant())
{
case "pi":
args.Result = Math.PI;
break;
case "e":
args.Result = Math.E;
break;
}
}
[NadekoCommand, Usage, Description, Aliases]
public async Task CalcOps()
{
var selection = typeof(Math).GetTypeInfo().GetMethods().Except(typeof(object).GetTypeInfo().GetMethods()).Distinct(new MethodInfoEqualityComparer()).Select(x =>
{
return x.Name;
})
.Except(new[] { "ToString",
"Equals", "Equals",
"GetHashCode", "GetHashCode",
"GetType"}); "GetType"});
await msg.Channel.SendConfirmAsync("Available functions in calc", string.Join(", ", selection)); await Context.Channel.SendConfirmAsync("Available functions in calc", string.Join(", ", selection));
}
} }
class MethodInfoEqualityComparer : IEqualityComparer<MethodInfo>
{
public bool Equals(MethodInfo x, MethodInfo y) => x.Name == y.Name;
public int GetHashCode(MethodInfo obj) => obj.Name.GetHashCode();
}
class ExpressionContext
{
public double Pi { get; set; } = Math.PI;
}
} }
class MethodInfoEqualityComparer : IEqualityComparer<MethodInfo>
{
public bool Equals(MethodInfo x, MethodInfo y) => x.Name == y.Name;
public int GetHashCode(MethodInfo obj) => obj.Name.GetHashCode();
}
class ExpressionContext
{
public double Pi { get; set; } = Math.PI;
}
} }

View File

@ -4,7 +4,6 @@ using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -12,88 +11,93 @@ namespace NadekoBot.Modules.Utility
{ {
public partial class Utility public partial class Utility
{ {
[NadekoCommand, Usage, Description, Aliases] [Group]
[RequireContext(ContextType.Guild)] public class InfoCommands : ModuleBase
public async Task ServerInfo(IUserMessage msg, string guildName = null)
{ {
var channel = (ITextChannel)msg.Channel; [NadekoCommand, Usage, Description, Aliases]
guildName = guildName?.ToUpperInvariant(); [RequireContext(ContextType.Guild)]
IGuild guild; public async Task ServerInfo(string guildName = null)
if (string.IsNullOrWhiteSpace(guildName))
guild = channel.Guild;
else
guild = NadekoBot.Client.GetGuilds().Where(g => g.Name.ToUpperInvariant() == guildName.ToUpperInvariant()).FirstOrDefault();
if (guild == null)
return;
var ownername = await guild.GetUserAsync(guild.OwnerId);
var textchn = (await guild.GetTextChannelsAsync()).Count();
var voicechn = (await guild.GetVoiceChannelsAsync()).Count();
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(guild.Id >> 22);
var sb = new StringBuilder();
var users = await guild.GetUsersAsync().ConfigureAwait(false);
var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName("Server Info"))
.WithTitle(guild.Name)
.AddField(fb => fb.WithName("**ID**").WithValue(guild.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Owner**").WithValue(ownername.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Members**").WithValue(users.Count.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Text Channels**").WithValue(textchn.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Voice Channels**").WithValue(voicechn.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Region**").WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Roles**").WithValue(guild.Roles.Count().ToString()).WithIsInline(true))
.WithImage(tn => tn.WithUrl(guild.IconUrl))
.WithOkColor();
if (guild.Emojis.Count() > 0)
{ {
embed.AddField(fb => fb.WithName("**Custom Emojis**").WithValue(Format.Italics(string.Join(", ", guild.Emojis))).WithIsInline(true)); var channel = (ITextChannel)Context.Channel;
guildName = guildName?.ToUpperInvariant();
IGuild guild;
if (string.IsNullOrWhiteSpace(guildName))
guild = channel.Guild;
else
guild = NadekoBot.Client.GetGuilds().Where(g => g.Name.ToUpperInvariant() == guildName.ToUpperInvariant()).FirstOrDefault();
if (guild == null)
return;
var ownername = await guild.GetUserAsync(guild.OwnerId);
var textchn = (await guild.GetTextChannelsAsync()).Count();
var voicechn = (await guild.GetVoiceChannelsAsync()).Count();
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(guild.Id >> 22);
var sb = new StringBuilder();
var users = await guild.GetUsersAsync().ConfigureAwait(false);
var embed = new EmbedBuilder()
.WithAuthor(eab => eab.WithName("Server Info"))
.WithTitle(guild.Name)
.AddField(fb => fb.WithName("**ID**").WithValue(guild.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Owner**").WithValue(ownername.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Members**").WithValue(users.Count.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Text Channels**").WithValue(textchn.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Voice Channels**").WithValue(voicechn.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Region**").WithValue(guild.VoiceRegionId.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Roles**").WithValue(guild.Roles.Count().ToString()).WithIsInline(true))
.WithImageUrl(guild.IconUrl)
.WithColor(NadekoBot.OkColor);
if (guild.Emojis.Count() > 0)
{
embed.AddField(fb => fb.WithName("**Custom Emojis**").WithValue(Format.Italics(string.Join(", ", guild.Emojis))).WithIsInline(true));
}
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChannelInfo(IUserMessage msg, ITextChannel channel = null) public async Task ChannelInfo(ITextChannel channel = null)
{ {
var ch = channel ?? (ITextChannel)msg.Channel; var ch = channel ?? (ITextChannel)Context.Channel;
if (ch == null) if (ch == null)
return; return;
var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22); var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22);
var usercount = (await ch.GetUsersAsync()).Count(); var usercount = (await ch.GetUsersAsync().Flatten()).Count();
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.WithTitle(ch.Name) .WithTitle(ch.Name)
.WithDescription(ch.Topic?.SanitizeMentions()) .WithDescription(ch.Topic?.SanitizeMentions())
.AddField(fb => fb.WithName("**ID**").WithValue(ch.Id.ToString()).WithIsInline(true)) .AddField(fb => fb.WithName("**ID**").WithValue(ch.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true)) .AddField(fb => fb.WithName("**Created At**").WithValue($"{createdAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Users**").WithValue(usercount.ToString()).WithIsInline(true)) .AddField(fb => fb.WithName("**Users**").WithValue(usercount.ToString()).WithIsInline(true))
.WithOkColor(); .WithColor(NadekoBot.OkColor);
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false); await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UserInfo(IUserMessage msg, IGuildUser usr = null) public async Task UserInfo(IGuildUser usr = null)
{ {
var channel = (ITextChannel)msg.Channel; var channel = (ITextChannel)Context.Channel;
var user = usr ?? msg.Author as IGuildUser; var user = usr ?? Context.User as IGuildUser;
if (user == null) if (user == null)
return; return;
var embed = new EmbedBuilder() var embed = new EmbedBuilder()
.AddField(fb => fb.WithName("**Name**").WithValue($"**{user.Username}**#{user.Discriminator}").WithIsInline(true)); .AddField(fb => fb.WithName("**Name**").WithValue($"**{user.Username}**#{user.Discriminator}").WithIsInline(true));
if (!string.IsNullOrWhiteSpace(user.Nickname)) { if (!string.IsNullOrWhiteSpace(user.Nickname))
embed.AddField(fb => fb.WithName("**Nickname**").WithValue(user.Nickname).WithIsInline(true)); {
embed.AddField(fb => fb.WithName("**Nickname**").WithValue(user.Nickname).WithIsInline(true));
}
embed.AddField(fb => fb.WithName("**ID**").WithValue(user.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Current Game**").WithValue($"{(user.Game?.Name == null ? "-" : user.Game.Value.Name)}").WithIsInline(true))
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.RoleIds.Count})** - {string.Join(", ", user.GetRoles().Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
.WithThumbnailUrl(user.AvatarUrl)
.WithColor(NadekoBot.OkColor);
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
} }
embed.AddField(fb => fb.WithName("**ID**").WithValue(user.Id.ToString()).WithIsInline(true))
.AddField(fb => fb.WithName("**Joined Server**").WithValue($"{user.JoinedAt?.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Joined Discord**").WithValue($"{user.CreatedAt.ToString("dd.MM.yyyy HH:mm")}").WithIsInline(true))
.AddField(fb => fb.WithName("**Current Game**").WithValue($"{(user.Game?.Name == null ? "-" : user.Game.Name)}").WithIsInline(true))
.AddField(fb => fb.WithName("**Roles**").WithValue($"**({user.Roles.Count()})** - {string.Join(", ", user.Roles.Select(r => r.Name)).SanitizeMentions()}").WithIsInline(true))
.WithThumbnail(tn => tn.WithUrl(user.AvatarUrl))
.WithOkColor();
await msg.Channel.EmbedAsync(embed.Build()).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
@ -118,8 +122,7 @@ namespace NadekoBot.Modules.Utility
await imsg.Channel.EmbedAsync(new EmbedBuilder().WithTitle($"Activity Page #{page}") await imsg.Channel.EmbedAsync(new EmbedBuilder().WithTitle($"Activity Page #{page}")
.WithOkColor() .WithOkColor()
.WithFooter(efb => efb.WithText($"{NadekoBot.CommandHandler.UserMessagesSent.Count} users total.")) .WithFooter(efb => efb.WithText($"{NadekoBot.CommandHandler.UserMessagesSent.Count} users total."))
.WithDescription(str.ToString()) .WithDescription(str.ToString()));
.Build());
} }
} }
} }

View File

@ -13,133 +13,127 @@ namespace NadekoBot.Modules.Utility
{ {
public partial class Utility public partial class Utility
{ {
[NadekoCommand, Usage, Description, Aliases] [Group]
[RequireContext(ContextType.Guild)] public class QuoteCommands : ModuleBase
public async Task ListQuotes(IUserMessage imsg, int page = 1)
{ {
var channel = (ITextChannel)imsg.Channel; [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
page -= 1; public async Task ListQuotes(int page = 1)
if (page < 0)
return;
IEnumerable<Quote> quotes;
using (var uow = DbHandler.UnitOfWork())
{ {
quotes = uow.Quotes.GetGroup(channel.Guild.Id, page * 16, 16); page -= 1;
}
if (quotes.Any()) if (page < 0)
await channel.SendConfirmAsync($"💬 **Page {page + 1} of quotes:**\n```xl\n" + String.Join("\n", quotes.Select((q) => $"{q.Keyword,-20} by {q.AuthorName}")) + "\n```")
.ConfigureAwait(false);
else
await channel.SendErrorAsync("No quotes on this page.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task ShowQuote(IUserMessage umsg, [Remainder] string keyword)
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(keyword))
return;
keyword = keyword.ToUpperInvariant();
Quote quote;
using (var uow = DbHandler.Instance.GetUnitOfWork())
{
quote = await uow.Quotes.GetRandomQuoteByKeywordAsync(channel.Guild.Id, keyword).ConfigureAwait(false);
}
if (quote == null)
return;
await channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions());
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task AddQuote(IUserMessage umsg, string keyword, [Remainder] string text)
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
return;
keyword = keyword.ToUpperInvariant();
using (var uow = DbHandler.UnitOfWork())
{
uow.Quotes.Add(new Quote
{
AuthorId = umsg.Author.Id,
AuthorName = umsg.Author.Username,
GuildId = channel.Guild.Id,
Keyword = keyword,
Text = text,
});
await uow.CompleteAsync().ConfigureAwait(false);
}
await channel.SendConfirmAsync("✅ Quote added.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task DeleteQuote(IUserMessage umsg, [Remainder] string keyword)
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(keyword))
return;
var isAdmin = ((IGuildUser)umsg.Author).GuildPermissions.Administrator;
keyword = keyword.ToUpperInvariant();
string response;
using (var uow = DbHandler.UnitOfWork())
{
var qs = uow.Quotes.GetAllQuotesByKeyword(channel.Guild.Id, keyword);
if (qs==null || !qs.Any())
{
await channel.SendErrorAsync("No quotes found.");
return; return;
IEnumerable<Quote> quotes;
using (var uow = DbHandler.UnitOfWork())
{
quotes = uow.Quotes.GetGroup(Context.Guild.Id, page * 16, 16);
} }
var q = qs.Shuffle().FirstOrDefault(elem => isAdmin || elem.AuthorId == umsg.Author.Id); if (quotes.Any())
await Context.Channel.SendConfirmAsync($"💬 **Page {page + 1} of quotes:**\n```xl\n" + String.Join("\n", quotes.Select((q) => $"{q.Keyword,-20} by {q.AuthorName}")) + "\n```")
uow.Quotes.Remove(q); .ConfigureAwait(false);
await uow.CompleteAsync().ConfigureAwait(false); else
response = "🗑 **Deleted a random quote.**"; await Context.Channel.SendErrorAsync("No quotes on this page.").ConfigureAwait(false);
} }
await channel.SendConfirmAsync(response);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequirePermission(GuildPermission.Administrator)] public async Task ShowQuote([Remainder] string keyword)
public async Task DelAllQuotes(IUserMessage umsg, [Remainder] string keyword)
{
var channel = (ITextChannel)umsg.Channel;
if (string.IsNullOrWhiteSpace(keyword))
return;
keyword = keyword.ToUpperInvariant();
using (var uow = DbHandler.UnitOfWork())
{ {
var quotes = uow.Quotes.GetAllQuotesByKeyword(channel.Guild.Id, keyword); if (string.IsNullOrWhiteSpace(keyword))
return;
uow.Quotes.RemoveRange(quotes.ToArray());//wtf?! keyword = keyword.ToUpperInvariant();
await uow.CompleteAsync(); Quote quote;
using (var uow = DbHandler.Instance.GetUnitOfWork())
{
quote = await uow.Quotes.GetRandomQuoteByKeywordAsync(Context.Guild.Id, keyword).ConfigureAwait(false);
}
if (quote == null)
return;
await Context.Channel.SendMessageAsync("📣 " + quote.Text.SanitizeMentions());
} }
await channel.SendConfirmAsync($"🗑 **Deleted all quotes** with **{keyword}** keyword."); [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task AddQuote(string keyword, [Remainder] string text)
{
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
return;
keyword = keyword.ToUpperInvariant();
using (var uow = DbHandler.UnitOfWork())
{
uow.Quotes.Add(new Quote
{
AuthorId = Context.Message.Author.Id,
AuthorName = Context.Message.Author.Username,
GuildId = Context.Guild.Id,
Keyword = keyword,
Text = text,
});
await uow.CompleteAsync().ConfigureAwait(false);
}
await Context.Channel.SendConfirmAsync("✅ Quote added.").ConfigureAwait(false);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public async Task DeleteQuote([Remainder] string keyword)
{
if (string.IsNullOrWhiteSpace(keyword))
return;
var isAdmin = ((IGuildUser)Context.Message.Author).GuildPermissions.Administrator;
keyword = keyword.ToUpperInvariant();
string response;
using (var uow = DbHandler.UnitOfWork())
{
var qs = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword);
if (qs == null || !qs.Any())
{
await Context.Channel.SendErrorAsync("No quotes found.").ConfigureAwait(false);
return;
}
var q = qs.Shuffle().FirstOrDefault(elem => isAdmin || elem.AuthorId == Context.Message.Author.Id);
uow.Quotes.Remove(q);
await uow.CompleteAsync().ConfigureAwait(false);
response = "🗑 **Deleted a random quote.**";
}
await Context.Channel.SendConfirmAsync(response);
}
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.Administrator)]
public async Task DelAllQuotes([Remainder] string keyword)
{
if (string.IsNullOrWhiteSpace(keyword))
return;
keyword = keyword.ToUpperInvariant();
using (var uow = DbHandler.UnitOfWork())
{
var quotes = uow.Quotes.GetAllQuotesByKeyword(Context.Guild.Id, keyword);
uow.Quotes.RemoveRange(quotes.ToArray());//wtf?!
await uow.CompleteAsync();
}
await Context.Channel.SendConfirmAsync($"🗑 **Deleted all quotes** with **{keyword}** keyword.");
}
} }
} }
} }

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -17,23 +16,23 @@ namespace NadekoBot.Modules.Utility
public partial class Utility public partial class Utility
{ {
[Group] [Group]
public class RemindCommands public class RemindCommands : ModuleBase
{ {
Regex regex = new Regex(@"^(?:(?<months>\d)mo)?(?:(?<weeks>\d)w)?(?:(?<days>\d{1,2})d)?(?:(?<hours>\d{1,2})h)?(?:(?<minutes>\d{1,2})m)?$", Regex regex = new Regex(@"^(?:(?<months>\d)mo)?(?:(?<weeks>\d)w)?(?:(?<days>\d{1,2})d)?(?:(?<hours>\d{1,2})h)?(?:(?<minutes>\d{1,2})m)?$",
RegexOptions.Compiled | RegexOptions.Multiline); RegexOptions.Compiled | RegexOptions.Multiline);
private string RemindMessageFormat { get; } private static string RemindMessageFormat { get; }
IDictionary<string, Func<Reminder, string>> replacements = new Dictionary<string, Func<Reminder, string>> private static IDictionary<string, Func<Reminder, string>> replacements = new Dictionary<string, Func<Reminder, string>>
{ {
{ "%message%" , (r) => r.Message }, { "%message%" , (r) => r.Message },
{ "%user%", (r) => $"<@!{r.UserId}>" }, { "%user%", (r) => $"<@!{r.UserId}>" },
{ "%target%", (r) => r.IsPrivate ? "Direct Message" : $"<#{r.ChannelId}>"} { "%target%", (r) => r.IsPrivate ? "Direct Message" : $"<#{r.ChannelId}>"}
}; };
private Logger _log { get; } private static Logger _log { get; }
public RemindCommands() static RemindCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
List<Reminder> reminders; List<Reminder> reminders;
@ -50,7 +49,7 @@ namespace NadekoBot.Modules.Utility
} }
} }
private async Task StartReminder(Reminder r) private static async Task StartReminder(Reminder r)
{ {
var now = DateTime.Now; var now = DateTime.Now;
var twoMins = new TimeSpan(0, 2, 0); var twoMins = new TimeSpan(0, 2, 0);
@ -62,14 +61,16 @@ namespace NadekoBot.Modules.Utility
await Task.Delay(time); await Task.Delay(time);
try try
{ {
IMessageChannel ch; IMessageChannel ch = null;
if (r.IsPrivate) if (r.IsPrivate)
{ {
ch = await NadekoBot.Client.GetDMChannelAsync(r.ChannelId).ConfigureAwait(false); ch = await NadekoBot.Client.GetDMChannelAsync(r.ChannelId).ConfigureAwait(false);
} }
else else
{ {
ch = NadekoBot.Client.GetGuild(r.ServerId)?.GetTextChannel(r.ChannelId); var t = NadekoBot.Client.GetGuild(r.ServerId)?.GetTextChannelAsync(r.ChannelId).ConfigureAwait(false);
if (t != null)
ch = await t.Value;
} }
if (ch == null) if (ch == null)
return; return;
@ -99,32 +100,30 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public async Task Remind(IUserMessage umsg, MeOrHere meorhere, string timeStr, [Remainder] string message) public async Task Remind(MeOrHere meorhere, string timeStr, [Remainder] string message)
{ {
var channel = (ITextChannel)umsg.Channel;
IMessageChannel target; IMessageChannel target;
if (meorhere == MeOrHere.Me) if (meorhere == MeOrHere.Me)
{ {
target = await ((IGuildUser)umsg.Author).CreateDMChannelAsync().ConfigureAwait(false); target = await ((IGuildUser)Context.User).CreateDMChannelAsync().ConfigureAwait(false);
} }
else else
{ {
target = channel; target = Context.Channel;
} }
await Remind(umsg, target, timeStr, message).ConfigureAwait(false); await Remind(target, timeStr, message).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(0)] [Priority(0)]
public async Task Remind(IUserMessage umsg, IMessageChannel ch, string timeStr, [Remainder] string message) public async Task Remind(IMessageChannel ch, string timeStr, [Remainder] string message)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
if (ch == null) if (ch == null)
{ {
await channel.SendErrorAsync($"{umsg.Author.Mention} Something went wrong (channel cannot be found) ;(").ConfigureAwait(false); await channel.SendErrorAsync($"{Context.User.Mention} Something went wrong (channel cannot be found) ;(").ConfigureAwait(false);
return; return;
} }
@ -177,7 +176,7 @@ namespace NadekoBot.Modules.Utility
IsPrivate = ch is IDMChannel, IsPrivate = ch is IDMChannel,
When = time, When = time,
Message = message, Message = message,
UserId = umsg.Author.Id, UserId = Context.User.Id,
ServerId = channel.Guild.Id ServerId = channel.Guild.Id
}; };
@ -187,16 +186,16 @@ namespace NadekoBot.Modules.Utility
await uow.CompleteAsync(); await uow.CompleteAsync();
} }
try { await channel.SendConfirmAsync($"⏰ I will remind **\"{(ch is ITextChannel ? ((ITextChannel)ch).Name : umsg.Author.Username)}\"** to **\"{message.SanitizeMentions()}\"** in **{output}** `({time:d.M.yyyy.} at {time:HH:mm})`").ConfigureAwait(false); } catch { } try { await channel.SendConfirmAsync($"⏰ I will remind **\"{(ch is ITextChannel ? ((ITextChannel)ch).Name : Context.User.Username)}\"** to **\"{message.SanitizeMentions()}\"** in **{output}** `({time:d.M.yyyy.} at {time:HH:mm})`").ConfigureAwait(false); } catch { }
await StartReminder(rem); await StartReminder(rem);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task RemindTemplate(IUserMessage umsg, [Remainder] string arg) public async Task RemindTemplate([Remainder] string arg)
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
if (string.IsNullOrWhiteSpace(arg)) if (string.IsNullOrWhiteSpace(arg))
return; return;

View File

@ -9,10 +9,10 @@ using Newtonsoft.Json;
using NLog; using NLog;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -21,9 +21,8 @@ namespace NadekoBot.Modules.Utility
public partial class Utility public partial class Utility
{ {
[Group] [Group]
public class UnitConverterCommands public class UnitConverterCommands : ModuleBase
{ {
public static List<ConvertUnit> Units { get; set; } = new List<ConvertUnit>(); public static List<ConvertUnit> Units { get; set; } = new List<ConvertUnit>();
private static Logger _log { get; } private static Logger _log { get; }
private static Timer _timer; private static Timer _timer;
@ -32,7 +31,6 @@ namespace NadekoBot.Modules.Utility
static UnitConverterCommands() static UnitConverterCommands()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
try try
{ {
var data = JsonConvert.DeserializeObject<List<MeasurementUnit>>(File.ReadAllText("data/units.json")).Select(u => new ConvertUnit() var data = JsonConvert.DeserializeObject<List<MeasurementUnit>>(File.ReadAllText("data/units.json")).Select(u => new ConvertUnit()
@ -56,16 +54,13 @@ namespace NadekoBot.Modules.Utility
{ {
_log.Warn("Could not load units: " + e.Message); _log.Warn("Could not load units: " + e.Message);
} }
}
public UnitConverterCommands()
{
_timer = new Timer(async (obj) => await UpdateCurrency(), null, (int)updateInterval.TotalMilliseconds, (int)updateInterval.TotalMilliseconds); _timer = new Timer(async (obj) => await UpdateCurrency(), null, (int)updateInterval.TotalMilliseconds, (int)updateInterval.TotalMilliseconds);
} }
public async Task UpdateCurrency() public static async Task UpdateCurrency()
{try {
try
{ {
var currencyRates = await UpdateCurrencyRates(); var currencyRates = await UpdateCurrencyRates();
var unitTypeString = "currency"; var unitTypeString = "currency";
@ -96,36 +91,37 @@ namespace NadekoBot.Modules.Utility
Units.AddRange(range); Units.AddRange(range);
_log.Info("Updated Currency"); _log.Info("Updated Currency");
} }
catch { catch
{
_log.Warn("Failed updating currency."); _log.Warn("Failed updating currency.");
} }
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task ConvertList()
public async Task ConvertList(IUserMessage msg)
{ {
var res = Units.GroupBy(x => x.UnitType) var res = Units.GroupBy(x => x.UnitType)
.Aggregate(new EmbedBuilder().WithTitle("__Units which can be used by the converter__") .Aggregate(new EmbedBuilder().WithTitle("__Units which can be used by the converter__")
.WithOkColor(), .WithColor(NadekoBot.OkColor),
(embed, g) => embed.AddField(efb => (embed, g) => embed.AddField(efb =>
efb.WithName(g.Key.ToTitleCase()) efb.WithName(g.Key.ToTitleCase())
.WithValue(String.Join(", ", g.Select(x => x.Triggers.FirstOrDefault()) .WithValue(String.Join(", ", g.Select(x => x.Triggers.FirstOrDefault())
.OrderBy(x => x))))); .OrderBy(x => x)))));
await msg.Channel.EmbedAsync(res.Build()); await Context.Channel.EmbedAsync(res);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Convert(IUserMessage msg, string origin, string target, decimal value) public async Task Convert(string origin, string target, decimal value)
{ {
var originUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant())); var originUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(origin.ToLowerInvariant()));
var targetUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant())); var targetUnit = Units.Find(x => x.Triggers.Select(y => y.ToLowerInvariant()).Contains(target.ToLowerInvariant()));
if (originUnit == null || targetUnit == null) if (originUnit == null || targetUnit == null)
{ {
await msg.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: units not found", origin, target)); await Context.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: units not found", origin, target));
return; return;
} }
if (originUnit.UnitType != targetUnit.UnitType) if (originUnit.UnitType != targetUnit.UnitType)
{ {
await msg.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: types of unit are not equal", originUnit.Triggers.First(), targetUnit.Triggers.First())); await Context.Channel.SendErrorAsync(string.Format("Cannot convert {0} to {1}: types of unit are not equal", originUnit.Triggers.First(), targetUnit.Triggers.First()));
return; return;
} }
decimal res; decimal res;
@ -169,7 +165,7 @@ namespace NadekoBot.Modules.Utility
} }
res = Math.Round(res, 4); res = Math.Round(res, 4);
await msg.Channel.SendConfirmAsync(string.Format("{0} {1} is equal to {2} {3}", value, (originUnit.Triggers.First() + "s").SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2))); await Context.Channel.SendConfirmAsync(string.Format("{0} {1} is equal to {2} {3}", value, (originUnit.Triggers.First() + "s").SnPl(value.IsInteger() ? (int)value : 2), res, (targetUnit.Triggers.First() + "s").SnPl(res.IsInteger() ? (int)res : 2)));
} }
} }

View File

@ -4,36 +4,21 @@ using NadekoBot.Attributes;
using System; using System;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Services;
using System.Text; using System.Text;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Reflection; using System.Reflection;
using Discord.WebSocket;
using NadekoBot.Services.Impl; using NadekoBot.Services.Impl;
using Discord.API;
using Embed = Discord.API.Embed;
using EmbedAuthor = Discord.API.EmbedAuthor;
using EmbedField = Discord.API.EmbedField;
using System.Net.Http; using System.Net.Http;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
[NadekoModule("Utility", ".")] [NadekoModule("Utility", ".")]
public partial class Utility : DiscordModule public partial class Utility : DiscordModule
{ {
public Utility() : base()
{
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] public async Task TogetherTube()
public async Task TogetherTube(IUserMessage imsg)
{ {
var channel = (ITextChannel)imsg.Channel;
Uri target; Uri target;
using (var http = new HttpClient()) using (var http = new HttpClient())
{ {
@ -41,113 +26,110 @@ namespace NadekoBot.Modules.Utility
target = res.RequestMessage.RequestUri; target = res.RequestMessage.RequestUri;
} }
await channel.EmbedAsync(new EmbedBuilder().WithOkColor() await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithIconUrl("https://togethertube.com/assets/img/favicons/favicon-32x32.png") .WithAuthor(eab => eab.WithIconUrl("https://togethertube.com/assets/img/favicons/favicon-32x32.png")
.WithName("Together Tube") .WithName("Together Tube")
.WithUrl("https://togethertube.com/")) .WithUrl("https://togethertube.com/"))
.WithDescription($"{imsg.Author.Mention} Here is your room link:\n{target}") .WithDescription($"{Context.User.Mention} Here is your room link:\n{target}"));
.Build());
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task WhosPlaying(IUserMessage umsg, [Remainder] string game = null) public async Task WhosPlaying([Remainder] string game = null)
{ {
var channel = (ITextChannel)umsg.Channel;
game = game.Trim().ToUpperInvariant(); game = game.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(game)) if (string.IsNullOrWhiteSpace(game))
return; return;
var usrs = (await (umsg.Channel as IGuildChannel).Guild.GetUsersAsync()) var arr = (await (Context.Channel as IGuildChannel).Guild.GetUsersAsync())
.Where(u => u.Game?.Name?.ToUpperInvariant() == game) .Where(u => u.Game?.Name?.ToUpperInvariant() == game)
.Select(u => u.Username) .Select(u => u.Username)
.ToList(); .ToList();
int i = 0; int i = 0;
if (!usrs.Any()) if (!arr.Any())
await channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("Nobody is playing that game.").ConfigureAwait(false);
else else
await channel.SendConfirmAsync($"List of users playing {game} game. Total {usrs.Count}.", "```css\n" + string.Join("\n", usrs.Take(30).GroupBy(item => (i++) / 2) await Context.Channel.SendConfirmAsync("```css\n" + string.Join("\n", arr.GroupBy(item => (i++) / 2)
.Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```") .Select(ig => string.Concat(ig.Select(el => $"• {el,-27}")))) + "\n```")
.ConfigureAwait(false); .ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task InRole(IUserMessage umsg, [Remainder] string roles) public async Task InRole([Remainder] string roles)
{ {
if (string.IsNullOrWhiteSpace(roles)) if (string.IsNullOrWhiteSpace(roles))
return; return;
var channel = (ITextChannel)umsg.Channel;
var arg = roles.Split(',').Select(r => r.Trim().ToUpperInvariant()); var arg = roles.Split(',').Select(r => r.Trim().ToUpperInvariant());
string send = " **Here is a list of users in those roles:**"; string send = " **Here is a list of users in those roles:**";
foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@EVERYONE" && str != "EVERYONE")) foreach (var roleStr in arg.Where(str => !string.IsNullOrWhiteSpace(str) && str != "@EVERYONE" && str != "EVERYONE"))
{ {
var role = channel.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleStr).FirstOrDefault(); var role = Context.Guild.Roles.Where(r => r.Name.ToUpperInvariant() == roleStr).FirstOrDefault();
if (role == null) continue; if (role == null) continue;
send += $"```css\n[{role.Name}]\n"; send += $"```css\n[{role.Name}]\n";
send += string.Join(", ", channel.Guild.GetUsers().Where(u => u.Roles.Contains(role)).Select(u => u.ToString())); send += string.Join(", ", (await Context.Guild.GetUsersAsync()).Where(u => u.RoleIds.Contains(role.Id)).Select(u => u.ToString()));
send += $"\n```"; send += $"\n```";
} }
var usr = umsg.Author as IGuildUser; var usr = Context.User as IGuildUser;
while (send.Length > 2000) while (send.Length > 2000)
{ {
if (!usr.GetPermissions(channel).ManageMessages) if (!usr.GetPermissions((ITextChannel)Context.Channel).ManageMessages)
{ {
await channel.SendErrorAsync($"⚠️ {usr.Mention} **you are not allowed to use this command on roles with a lot of users in them to prevent abuse.**").ConfigureAwait(false); await Context.Channel.SendErrorAsync($"⚠️ {usr.Mention} **you are not allowed to use this command on roles with a lot of users in them to prevent abuse.**").ConfigureAwait(false);
return; return;
} }
var curstr = send.Substring(0, 2000); var curstr = send.Substring(0, 2000);
await channel.SendConfirmAsync(curstr.Substring(0, await Context.Channel.SendConfirmAsync(curstr.Substring(0,
curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false); curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1)).ConfigureAwait(false);
send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) + send = curstr.Substring(curstr.LastIndexOf(", ", StringComparison.Ordinal) + 1) +
send.Substring(2000); send.Substring(2000);
} }
await channel.SendConfirmAsync(send).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(send).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task CheckMyPerms(IUserMessage msg) public async Task CheckMyPerms()
{ {
StringBuilder builder = new StringBuilder("```http\n"); StringBuilder builder = new StringBuilder("```http\n");
var user = msg.Author as IGuildUser; var user = Context.User as IGuildUser;
var perms = user.GetPermissions((ITextChannel)msg.Channel); var perms = user.GetPermissions((ITextChannel)Context.Channel);
foreach (var p in perms.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any())) foreach (var p in perms.GetType().GetProperties().Where(p => !p.GetGetMethod().GetParameters().Any()))
{ {
builder.AppendLine($"{p.Name} : {p.GetValue(perms, null).ToString()}"); builder.AppendLine($"{p.Name} : {p.GetValue(perms, null).ToString()}");
} }
builder.Append("```"); builder.Append("```");
await msg.Channel.SendConfirmAsync(builder.ToString()); await Context.Channel.SendConfirmAsync(builder.ToString());
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UserId(IUserMessage msg, IGuildUser target = null) public async Task UserId(IGuildUser target = null)
{ {
var usr = target ?? msg.Author; var usr = target ?? Context.User;
await msg.Channel.SendConfirmAsync($"🆔 of the user **{ usr.Username }** is `{ usr.Id }`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🆔 of the user **{ usr.Username }** is `{ usr.Id }`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task ChannelId(IUserMessage msg) public async Task ChannelId()
{ {
await msg.Channel.SendConfirmAsync($"🆔 of this channel is `{msg.Channel.Id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🆔 of this channel is `{Context.Channel.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ServerId(IUserMessage msg) public async Task ServerId()
{ {
await msg.Channel.SendConfirmAsync($"🆔 of this server is `{((ITextChannel)msg.Channel).Guild.Id}`").ConfigureAwait(false); await Context.Channel.SendConfirmAsync($"🆔 of this server is `{Context.Guild.Id}`").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task Roles(IUserMessage msg, IGuildUser target, int page = 1) public async Task Roles(IGuildUser target, int page = 1)
{ {
var channel = (ITextChannel)msg.Channel; var channel = (ITextChannel)Context.Channel;
var guild = channel.Guild; var guild = channel.Guild;
const int RolesPerPage = 20; const int RolesPerPage = 20;
@ -157,7 +139,7 @@ namespace NadekoBot.Modules.Utility
if (target != null) if (target != null)
{ {
var roles = target.Roles.Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage); var roles = target.GetRoles().Except(new[] { guild.EveryoneRole }).OrderBy(r => -r.Position).Skip((page - 1) * RolesPerPage).Take(RolesPerPage);
if (!roles.Any()) if (!roles.Any())
{ {
await channel.SendErrorAsync("No roles on this page.").ConfigureAwait(false); await channel.SendErrorAsync("No roles on this page.").ConfigureAwait(false);
@ -183,14 +165,14 @@ namespace NadekoBot.Modules.Utility
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public Task Roles(IUserMessage msg, int page = 1) => public Task Roles(int page = 1) =>
Roles(msg, null, page); Roles(null, page);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChannelTopic(IUserMessage umsg) public async Task ChannelTopic()
{ {
var channel = (ITextChannel)umsg.Channel; var channel = (ITextChannel)Context.Channel;
var topic = channel.Topic; var topic = channel.Topic;
if (string.IsNullOrWhiteSpace(topic)) if (string.IsNullOrWhiteSpace(topic))
@ -200,20 +182,18 @@ namespace NadekoBot.Modules.Utility
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Stats(IUserMessage umsg) public async Task Stats()
{ {
var channel = umsg.Channel;
var stats = NadekoBot.Stats; var stats = NadekoBot.Stats;
await channel.EmbedAsync( await Context.Channel.EmbedAsync(
new EmbedBuilder().WithOkColor() new EmbedBuilder().WithOkColor()
.WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}") .WithAuthor(eab => eab.WithName($"NadekoBot v{StatsService.BotVersion}")
.WithUrl("http://nadekobot.readthedocs.io/en/latest/") .WithUrl("http://nadekobot.readthedocs.io/en/latest/")
.WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg")) .WithIconUrl("https://cdn.discordapp.com/avatars/116275390695079945/b21045e778ef21c96d175400e779f0fb.jpg"))
.AddField(efb => efb.WithName(Format.Bold("Author")).WithValue(stats.Author).WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Author")).WithValue(stats.Author).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Library")).WithValue(stats.Library).WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Library")).WithValue(stats.Library).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.GetCurrentUser().Id.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Bot ID")).WithValue(NadekoBot.Client.CurrentUser().Id.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Commands Ran")).WithValue(stats.CommandsRan.ToString()).WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Commands Ran")).WithValue(stats.CommandsRan.ToString()).WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Messages")).WithValue($"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)").WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Messages")).WithValue($"{stats.MessageCounter} ({stats.MessagesPerSecond:F2}/sec)").WithIsInline(true))
.AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true)) .AddField(efb => efb.WithName(Format.Bold("Memory")).WithValue($"{stats.Heap} MB").WithIsInline(true))
@ -223,12 +203,12 @@ namespace NadekoBot.Modules.Utility
#if !GLOBAL_NADEKO #if !GLOBAL_NADEKO
.WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued.")) .WithFooter(efb => efb.WithText($"Playing {Music.Music.MusicPlayers.Where(mp => mp.Value.CurrentSong != null).Count()} songs, {Music.Music.MusicPlayers.Sum(mp => mp.Value.Playlist.Count)} queued."))
#endif #endif
.Build()); );
} }
private Regex emojiFinder { get; } = new Regex(@"<:(?<name>.+?):(?<id>\d*)>", RegexOptions.Compiled); private Regex emojiFinder { get; } = new Regex(@"<:(?<name>.+?):(?<id>\d*)>", RegexOptions.Compiled);
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Showemojis(IUserMessage msg, [Remainder] string emojis) public async Task Showemojis([Remainder] string emojis)
{ {
var matches = emojiFinder.Matches(emojis); var matches = emojiFinder.Matches(emojis);
@ -236,18 +216,15 @@ namespace NadekoBot.Modules.Utility
.Select(m => $"**Name:** {m.Groups["name"]} **Link:** http://discordapp.com/api/emojis/{m.Groups["id"]}.png")); .Select(m => $"**Name:** {m.Groups["name"]} **Link:** http://discordapp.com/api/emojis/{m.Groups["id"]}.png"));
if (string.IsNullOrWhiteSpace(result)) if (string.IsNullOrWhiteSpace(result))
await msg.Channel.SendErrorAsync("No special emojis found."); await Context.Channel.SendErrorAsync("No special emojis found.");
else else
await msg.Channel.SendMessageAsync(result).ConfigureAwait(false); await Context.Channel.SendMessageAsync(result).ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
[OwnerOnly] [OwnerOnly]
public async Task ListServers(IUserMessage imsg, int page = 1) public async Task ListServers(int page = 1)
{ {
var channel = (ITextChannel)imsg.Channel;
page -= 1; page -= 1;
if (page < 0) if (page < 0)
@ -257,15 +234,14 @@ namespace NadekoBot.Modules.Utility
if (!guilds.Any()) if (!guilds.Any())
{ {
await channel.SendErrorAsync("No servers found on that page.").ConfigureAwait(false); await Context.Channel.SendErrorAsync("No servers found on that page.").ConfigureAwait(false);
return; return;
} }
await channel.EmbedAsync(guilds.Aggregate(new EmbedBuilder().WithOkColor(), await Context.Channel.EmbedAsync(guilds.Aggregate(new EmbedBuilder().WithOkColor(),
(embed, g) => embed.AddField(efb => efb.WithName(g.Name) (embed, g) => embed.AddField(efb => efb.WithName(g.Name)
.WithValue($"```css\nID: {g.Id}\nMembers: {g.GetUsers().Count}\nOwnerID: {g.OwnerId} ```") .WithValue($"```css\nID: {g.Id}\nMembers: {g.Users.Count}\nOwnerID: {g.OwnerId} ```")
.WithIsInline(false))) .WithIsInline(false))))
.Build())
.ConfigureAwait(false); .ConfigureAwait(false);
} }
} }

View File

@ -12,12 +12,10 @@ using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Collections.Generic; using System.Collections.Generic;
using NadekoBot.Modules.Permissions; using NadekoBot.Modules.Permissions;
using Module = Discord.Commands.Module;
using NadekoBot.TypeReaders; using NadekoBot.TypeReaders;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using NadekoBot.Modules.Music; using NadekoBot.Modules.Music;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using NadekoBot.Modules.Games.Commands.Hangman;
namespace NadekoBot namespace NadekoBot
{ {
@ -25,12 +23,12 @@ namespace NadekoBot
{ {
private Logger _log; private Logger _log;
public static uint OkColor { get; } = 0x71cd40; public static Color OkColor { get; } = new Color(0x71cd40);
public static uint ErrorColor { get; } = 0xee281f; public static Color ErrorColor { get; } = new Color(0xee281f);
public static CommandService CommandService { get; private set; } public static CommandService CommandService { get; private set; }
public static CommandHandler CommandHandler { get; private set; } public static CommandHandler CommandHandler { get; private set; }
public static ShardedDiscordClient Client { get; private set; } public static ShardedDiscordClient Client { get; private set; }
public static BotCredentials Credentials { get; private set; } public static BotCredentials Credentials { get; private set; }
public static GoogleApiService Google { get; private set; } public static GoogleApiService Google { get; private set; }
@ -69,7 +67,9 @@ namespace NadekoBot
}); });
//initialize Services //initialize Services
CommandService = new CommandService(); CommandService = new CommandService(new CommandServiceConfig() {
CaseSensitiveCommands = false
});
Google = new GoogleApiService(); Google = new GoogleApiService();
CommandHandler = new CommandHandler(Client, CommandService); CommandHandler = new CommandHandler(Client, CommandService);
Stats = new StatsService(Client, CommandHandler); Stats = new StatsService(Client, CommandHandler);
@ -84,28 +84,28 @@ namespace NadekoBot
//setup typereaders //setup typereaders
CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader()); CommandService.AddTypeReader<PermissionAction>(new PermissionActionTypeReader());
CommandService.AddTypeReader<Command>(new CommandTypeReader()); CommandService.AddTypeReader<CommandInfo>(new CommandTypeReader());
CommandService.AddTypeReader<Module>(new ModuleTypeReader()); CommandService.AddTypeReader<ModuleInfo>(new ModuleTypeReader());
CommandService.AddTypeReader<IGuild>(new GuildTypeReader()); CommandService.AddTypeReader<IGuild>(new GuildTypeReader());
//connect //connect
await Client.LoginAsync(TokenType.Bot, Credentials.Token).ConfigureAwait(false); await Client.LoginAsync(TokenType.Bot, Credentials.Token).ConfigureAwait(false);
await Client.ConnectAsync().ConfigureAwait(false); await Client.ConnectAsync().ConfigureAwait(false);
await Client.DownloadAllUsersAsync().ConfigureAwait(false); //await Client.DownloadAllUsersAsync().ConfigureAwait(false);
_log.Info("Connected"); _log.Info("Connected");
//load commands and prefixes //load commands and prefixes
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
ModulePrefixes = new ConcurrentDictionary<string, string>(uow.BotConfig.GetOrCreate().ModulePrefixes.ToDictionary(m => m.ModuleName, m => m.Prefix)); ModulePrefixes = new ConcurrentDictionary<string, string>(uow.BotConfig.GetOrCreate().ModulePrefixes.OrderByDescending(mp => mp.Prefix.Length).ToDictionary(m => m.ModuleName, m => m.Prefix));
} }
// start handling messages received in commandhandler // start handling messages received in commandhandler
await CommandHandler.StartHandling().ConfigureAwait(false); await CommandHandler.StartHandling().ConfigureAwait(false);
await CommandService.LoadAssembly(this.GetType().GetTypeInfo().Assembly).ConfigureAwait(false); await CommandService.AddModulesAsync(this.GetType().GetTypeInfo().Assembly).ConfigureAwait(false);
#if !GLOBAL_NADEKO #if !GLOBAL_NADEKO
await CommandService.Load(new Music()).ConfigureAwait(false); await CommandService.AddModuleAsync<Music>().ConfigureAwait(false);
#endif #endif
Ready = true; Ready = true;
Console.WriteLine(await Stats.Print().ConfigureAwait(false)); Console.WriteLine(await Stats.Print().ConfigureAwait(false));

View File

@ -599,6 +599,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to autohentai.
/// </summary>
public static string autohentai_cmd {
get {
return ResourceManager.GetString("autohentai_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable..
/// </summary>
public static string autohentai_desc {
get {
return ResourceManager.GetString("autohentai_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}autohentai 30 yuri|tail|long_hair` or `{0}autohentai`.
/// </summary>
public static string autohentai_usage {
get {
return ResourceManager.GetString("autohentai_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to autoplay ap. /// Looks up a localized string similar to autoplay ap.
/// </summary> /// </summary>
@ -3984,7 +4011,7 @@ namespace NadekoBot.Resources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Toggles logging event. Disables it if it&apos;s active anywhere on the server. Enables if it&apos;s not active. Use `{0}logevents` to see a lit of all events you can subscribe to.. /// Looks up a localized string similar to Toggles logging event. Disables it if it&apos;s active anywhere on the server. Enables if it&apos;s not active. Use `{0}logevents` to see a list of all events you can subscribe to..
/// </summary> /// </summary>
public static string log_desc { public static string log_desc {
get { get {

View File

@ -2803,7 +2803,7 @@
<value>log</value> <value>log</value>
</data> </data>
<data name="log_desc" xml:space="preserve"> <data name="log_desc" xml:space="preserve">
<value>Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `{0}logevents` to see a lit of all events you can subscribe to.</value> <value>Toggles logging event. Disables it if it's active anywhere on the server. Enables if it's not active. Use `{0}logevents` to see a list of all events you can subscribe to.</value>
</data> </data>
<data name="log_usage" xml:space="preserve"> <data name="log_usage" xml:space="preserve">
<value>`{0}log userpresence` or `{0}log userbanned`</value> <value>`{0}log userpresence` or `{0}log userbanned`</value>
@ -2844,4 +2844,13 @@
<data name="activity_usage" xml:space="preserve"> <data name="activity_usage" xml:space="preserve">
<value>`{0}activity`</value> <value>`{0}activity`</value>
</data> </data>
<data name="autohentai_cmd" xml:space="preserve">
<value>autohentai</value>
</data>
<data name="autohentai_desc" xml:space="preserve">
<value>Posts a hentai every X seconds with a random tag from the provided tags. Use `|` to separate tags. 20 seconds minimum. Provide no arguments to disable.</value>
</data>
<data name="autohentai_usage" xml:space="preserve">
<value>`{0}autohentai 30 yuri|tail|long_hair` or `{0}autohentai`</value>
</data>
</root> </root>

View File

@ -34,7 +34,7 @@ namespace NadekoBot.Services
private List<IDMChannel> ownerChannels { get; set; } private List<IDMChannel> ownerChannels { get; set; }
public event Func<IUserMessage, Command, Task> CommandExecuted = delegate { return Task.CompletedTask; }; public event Func<SocketUserMessage, CommandInfo, Task> CommandExecuted = delegate { return Task.CompletedTask; };
//userid/msg count //userid/msg count
public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>(); public ConcurrentDictionary<ulong, uint> UserMessagesSent { get; } = new ConcurrentDictionary<ulong, uint>();
@ -47,7 +47,7 @@ namespace NadekoBot.Services
} }
public async Task StartHandling() public async Task StartHandling()
{ {
ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.GetUsers()) ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.Users)
.Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id)) .Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id))
.Distinct(new IGuildUserComparer()) .Distinct(new IGuildUserComparer())
.Select(async u => { try { return await u.CreateDMChannelAsync(); } catch { return null; } }))) .Select(async u => { try { return await u.CreateDMChannelAsync(); } catch { return null; } })))
@ -62,28 +62,27 @@ namespace NadekoBot.Services
_client.MessageReceived += MessageReceivedHandler; _client.MessageReceived += MessageReceivedHandler;
} }
private async void MessageReceivedHandler(IMessage msg) private async void MessageReceivedHandler(SocketMessage msg)
{ {
try try
{ {
var usrMsg = msg as IUserMessage;
var usrMsg = msg as SocketUserMessage;
if (usrMsg == null) if (usrMsg == null)
return; return;
if (!usrMsg.IsAuthor()) if (!usrMsg.IsAuthor())
UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old); UserMessagesSent.AddOrUpdate(usrMsg.Author.Id, 1, (key, old) => ++old);
if (usrMsg.Author.IsBot || !NadekoBot.Ready) //no bots if (msg.Author.IsBot || !NadekoBot.Ready) //no bots
return; return;
var sw = new Stopwatch();
sw.Start();
var guild = (msg.Channel as SocketTextChannel)?.Guild;
var guild = (msg.Channel as ITextChannel)?.Guild; if (guild != null && guild.OwnerId != msg.Author.Id)
if (guild != null && guild.OwnerId != usrMsg.Author.Id)
{ {
if (Permissions.FilterCommands.InviteFilteringChannels.Contains(usrMsg.Channel.Id) || //todo split checks into their own modules
if (Permissions.FilterCommands.InviteFilteringChannels.Contains(msg.Channel.Id) ||
Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id)) Permissions.FilterCommands.InviteFilteringServers.Contains(guild.Id))
{ {
if (usrMsg.Content.IsDiscordInvite()) if (usrMsg.Content.IsDiscordInvite())
@ -95,12 +94,12 @@ namespace NadekoBot.Services
} }
catch (HttpException ex) catch (HttpException ex)
{ {
_log.Warn("I do not have permission to filter invites in channel with id " + usrMsg.Channel.Id, ex); _log.Warn("I do not have permission to filter invites in channel with id " + msg.Channel.Id, ex);
} }
} }
} }
var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(usrMsg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id)); var filteredWords = Permissions.FilterCommands.FilteredWordsForChannel(msg.Channel.Id, guild.Id).Concat(Permissions.FilterCommands.FilteredWordsForServer(guild.Id));
var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' '); var wordsInMessage = usrMsg.Content.ToLowerInvariant().Split(' ');
if (filteredWords.Any(w => wordsInMessage.Contains(w))) if (filteredWords.Any(w => wordsInMessage.Contains(w)))
{ {
@ -111,7 +110,7 @@ namespace NadekoBot.Services
} }
catch (HttpException ex) catch (HttpException ex)
{ {
_log.Warn("I do not have permission to filter words in channel with id " + usrMsg.Channel.Id, ex); _log.Warn("I do not have permission to filter words in channel with id " + msg.Channel.Id, ex);
} }
} }
} }
@ -120,11 +119,11 @@ namespace NadekoBot.Services
if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi => if ((blacklistedItem = Permissions.BlacklistCommands.BlacklistedItems.FirstOrDefault(bi =>
(bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) || (bi.Type == BlacklistItem.BlacklistType.Server && bi.ItemId == guild?.Id) ||
(bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) || (bi.Type == BlacklistItem.BlacklistType.Channel && bi.ItemId == msg.Channel.Id) ||
(bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == usrMsg.Author.Id))) != null) (bi.Type == BlacklistItem.BlacklistType.User && bi.ItemId == msg.Author.Id))) != null)
{ {
return; return;
} }
#if !GLOBAL_NADEKO
try try
{ {
var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg); var cleverbotExecuted = await Games.CleverBotCommands.TryAsk(usrMsg);
@ -134,6 +133,7 @@ namespace NadekoBot.Services
} }
catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); } catch (Exception ex) { _log.Warn(ex, "Error in cleverbot"); }
#endif
try try
{ {
// maybe this message is a custom reaction // maybe this message is a custom reaction
@ -145,12 +145,16 @@ namespace NadekoBot.Services
} }
catch { } catch { }
var t = await ExecuteCommand(usrMsg, usrMsg.Content, guild, usrMsg.Author, MultiMatchHandling.Best); string messageContent = usrMsg.Content;
var command = t.Item1;
var permCache = t.Item2; var sw = new Stopwatch();
var result = t.Item3; sw.Start();
var exec = await ExecuteCommand(new CommandContext(_client.MainClient, usrMsg), messageContent, DependencyMap.Empty, MultiMatchHandling.Best);
var command = exec.CommandInfo;
var permCache = exec.PermissionCache;
var result = exec.Result;
sw.Stop(); sw.Stop();
var channel = (usrMsg.Channel as ITextChannel); var channel = (msg.Channel as ITextChannel);
if (result.IsSuccess) if (result.IsSuccess)
{ {
await CommandExecuted(usrMsg, command); await CommandExecuted(usrMsg, command);
@ -159,7 +163,7 @@ namespace NadekoBot.Services
"Server: {1}\n\t" + "Server: {1}\n\t" +
"Channel: {2}\n\t" + "Channel: {2}\n\t" +
"Message: {3}", "Message: {3}",
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0} msg.Author + " [" + msg.Author.Id + "]", // {0}
(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}
@ -174,7 +178,7 @@ namespace NadekoBot.Services
"Channel: {2}\n\t" + "Channel: {2}\n\t" +
"Message: {3}\n\t" + "Message: {3}\n\t" +
"Error: {4}", "Error: {4}",
usrMsg.Author + " [" + usrMsg.Author.Id + "]", // {0} msg.Author + " [" + msg.Author.Id + "]", // {0}
(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}
@ -207,27 +211,34 @@ namespace NadekoBot.Services
if (ex.InnerException != null) if (ex.InnerException != null)
_log.Warn(ex.InnerException, "Inner Exception of the error in CommandHandler"); _log.Warn(ex.InnerException, "Inner Exception of the error in CommandHandler");
} }
}
public async Task<Tuple<Command, PermissionCache, IResult>> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) return;
}
public Task<ExecuteCommandResult> ExecuteCommandAsync(CommandContext context, int argPos, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
=> ExecuteCommand(context, context.Message.Content.Substring(argPos), dependencyMap, multiMatchHandling);
public async Task<ExecuteCommandResult> ExecuteCommand(CommandContext context, string input, IDependencyMap dependencyMap = null, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Exception)
{ {
var searchResult = _commandService.Search(message, input); dependencyMap = dependencyMap ?? DependencyMap.Empty;
var searchResult = _commandService.Search(context, input);
if (!searchResult.IsSuccess) if (!searchResult.IsSuccess)
return new Tuple<Command, PermissionCache, IResult>(null, null, searchResult); return new ExecuteCommandResult(null, null, searchResult);
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--)
{ {
var preconditionResult = await commands[i].CheckPreconditions(message); var preconditionResult = await commands[i].CheckPreconditionsAsync(context).ConfigureAwait(false);
if (!preconditionResult.IsSuccess) if (!preconditionResult.IsSuccess)
{ {
if (commands.Count == 1) if (commands.Count == 1)
return new Tuple<Command, PermissionCache, IResult>(null, null, searchResult); return new ExecuteCommandResult(null, null, preconditionResult);
else else
continue; continue;
} }
var parseResult = await commands[i].Parse(message, searchResult, preconditionResult); var parseResult = await commands[i].ParseAsync(context, searchResult, preconditionResult).ConfigureAwait(false);
if (!parseResult.IsSuccess) if (!parseResult.IsSuccess)
{ {
if (parseResult.Error == CommandError.MultipleMatches) if (parseResult.Error == CommandError.MultipleMatches)
@ -246,22 +257,23 @@ namespace NadekoBot.Services
if (!parseResult.IsSuccess) if (!parseResult.IsSuccess)
{ {
if (commands.Count == 1) if (commands.Count == 1)
return new Tuple<Command, PermissionCache, IResult>(null, null, parseResult); return new ExecuteCommandResult(null, null, parseResult);
else else
continue; continue;
} }
} }
var cmd = commands[i]; var cmd = commands[i].Command;
bool resetCommand = cmd.Name == "ResetPermissions"; bool resetCommand = cmd.Name == "resetperms";
var module = cmd.Module.GetTopLevelModule();
PermissionCache pc; PermissionCache pc;
if (guild != null) if (context.Guild != null)
{ {
pc = Permissions.Cache.GetOrAdd(guild.Id, (id) => pc = Permissions.Cache.GetOrAdd(context.Guild.Id, (id) =>
{ {
using (var uow = DbHandler.UnitOfWork()) using (var uow = DbHandler.UnitOfWork())
{ {
var config = uow.GuildConfigs.PermissionsFor(guild.Id); var config = uow.GuildConfigs.PermissionsFor(context.Guild.Id);
return new PermissionCache() return new PermissionCache()
{ {
Verbose = config.VerbosePermissions, Verbose = config.VerbosePermissions,
@ -271,42 +283,44 @@ namespace NadekoBot.Services
} }
}); });
int index; int index;
if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(message, cmd.Text, cmd.Module.Name, out index)) if (!resetCommand && !pc.RootPermission.AsEnumerable().CheckPermissions(context.Message, cmd.Aliases.First(), module.Name, out index))
{ {
var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand(guild)}** is preventing this action."; var returnMsg = $"Permission number #{index + 1} **{pc.RootPermission.GetAt(index).GetCommand((SocketGuild)context.Guild)}** is preventing this action.";
return new Tuple<Command, PermissionCache, IResult>(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg)); return new ExecuteCommandResult(cmd, pc, SearchResult.FromError(CommandError.Exception, returnMsg));
} }
if (cmd.Module.Source.Name == typeof(Permissions).Name) //permissions, you must have special role if (module.Name == typeof(Permissions).Name)
{ {
if (!((IGuildUser)user).Roles.Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant())) if (!((IGuildUser)context.User).GetRoles().Any(r => r.Name.Trim().ToLowerInvariant() == pc.PermRole.Trim().ToLowerInvariant()))
{ {
return new Tuple<Command, PermissionCache, IResult>(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."));
} }
} }
} }
if (CmdCdsCommands.HasCooldown(cmd, guild, user)) if (CmdCdsCommands.HasCooldown(cmd, context.Guild, context.User))
return new Tuple<Command, PermissionCache, IResult>(cmd, null, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you.")); return new ExecuteCommandResult(cmd, null, SearchResult.FromError(CommandError.Exception, $"That command is on cooldown for you."));
return new Tuple<Command, PermissionCache, IResult>(commands[i], null, await commands[i].Execute(message, parseResult)); return new ExecuteCommandResult(cmd, null, await commands[i].ExecuteAsync(context, parseResult, dependencyMap));
} }
return new Tuple<Command, PermissionCache, IResult>(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."));
} }
}
public class CommandExecutedEventArgs public struct ExecuteCommandResult
{
public Command Command { get; }
public IUserMessage Message { get; }
public CommandExecutedEventArgs(IUserMessage msg, Command cmd)
{ {
Message = msg; public readonly CommandInfo CommandInfo;
Command = cmd; public readonly PermissionCache PermissionCache;
public readonly IResult Result;
public ExecuteCommandResult(CommandInfo commandInfo, PermissionCache cache, IResult result)
{
this.CommandInfo = commandInfo;
this.PermissionCache = cache;
this.Result = result;
}
} }
} }
} }

View File

@ -9,7 +9,7 @@ namespace NadekoBot.Services
{ {
public static class CurrencyHandler public static class CurrencyHandler
{ {
public static async Task<bool> RemoveCurrencyAsync(IGuildUser author, string reason, long amount, bool sendMessage) public static async Task<bool> RemoveCurrencyAsync(IUser author, string reason, long amount, bool sendMessage)
{ {
var success = await RemoveCurrencyAsync(author.Id, reason, amount); var success = await RemoveCurrencyAsync(author.Id, reason, amount);
@ -42,7 +42,7 @@ namespace NadekoBot.Services
return true; return true;
} }
public static async Task AddCurrencyAsync(IGuildUser author, string reason, long amount, bool sendMessage) public static async Task AddCurrencyAsync(IUser author, string reason, long amount, bool sendMessage)
{ {
await AddCurrencyAsync(author.Id, reason, amount); await AddCurrencyAsync(author.Id, reason, amount);

View File

@ -27,6 +27,6 @@ namespace NadekoBot.Services.Database.Models
[NotMapped] [NotMapped]
public ITextChannel Channel { get; set; } public ITextChannel Channel { get; set; }
public List<ClashCaller> Bases { get; set; } public List<ClashCaller> Bases { get; set; } = new List<ClashCaller>();
} }
} }

View File

@ -7,6 +7,6 @@ namespace NadekoBot.Services.Database.Models
public string Name { get; set; } public string Name { get; set; }
public string Author { get; set; } public string Author { get; set; }
public ulong AuthorId { get; set; } public ulong AuthorId { get; set; }
public List<PlaylistSong> Songs { get; set; } public List<PlaylistSong> Songs { get; set; } = new List<PlaylistSong>();
} }
} }

View File

@ -1,11 +1,4 @@
using Discord; namespace NadekoBot.Services.Database.Models
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Services.Database.Models
{ {
public class UserPokeTypes : DbEntity public class UserPokeTypes : DbEntity
{ {

View File

@ -1,5 +1,4 @@
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Collections.Generic;
namespace NadekoBot.Services.Database.Repositories namespace NadekoBot.Services.Database.Repositories
{ {

View File

@ -1,7 +1,4 @@
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace NadekoBot.Services.Database.Repositories.Impl namespace NadekoBot.Services.Database.Repositories.Impl

View File

@ -1,5 +1,4 @@
using Discord; using Discord;
using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,7 +14,7 @@ namespace NadekoBot.Services.Impl
private ShardedDiscordClient client; private ShardedDiscordClient client;
private DateTime started; private DateTime started;
public const string BotVersion = "1.0.0"; public const string BotVersion = "1.1.0-beta";
public string Author => "Kwoth#2560"; public string Author => "Kwoth#2560";
public string Library => "Discord.Net"; public string Library => "Discord.Net";
@ -23,12 +22,10 @@ namespace NadekoBot.Services.Impl
public int CommandsRan { get; private set; } = 0; public int CommandsRan { get; private set; } = 0;
public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString(); public string Heap => Math.Round((double)GC.GetTotalMemory(false) / 1.MiB(), 2).ToString();
public double MessagesPerSecond => MessageCounter / (double)GetUptime().TotalSeconds; public double MessagesPerSecond => MessageCounter / (double)GetUptime().TotalSeconds;
public int TextChannels => client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is ITextChannel)).Count(); public int TextChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is ITextChannel)).Count();
public int VoiceChannels => client.GetGuilds().SelectMany(g => g.GetChannels().Where(c => c is IVoiceChannel)).Count(); public int VoiceChannels => client.GetGuilds().SelectMany(g => g.Channels.Where(c => c is IVoiceChannel)).Count();
public string OwnerIds => string.Join(", ", NadekoBot.Credentials.OwnerIds); public string OwnerIds => string.Join(", ", NadekoBot.Credentials.OwnerIds);
Timer carbonitexTimer { get; } Timer carbonitexTimer { get; }
public StatsService(ShardedDiscordClient client, CommandHandler cmdHandler) public StatsService(ShardedDiscordClient client, CommandHandler cmdHandler)
@ -65,10 +62,10 @@ namespace NadekoBot.Services.Impl
catch { } catch { }
}, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1)); }, null, TimeSpan.FromHours(1), TimeSpan.FromHours(1));
} }
public async Task<string> Print() public Task<string> Print()
{ {
var curUser = await client.GetCurrentUserAsync(); var curUser = client.CurrentUser();
return $@" return Task.FromResult($@"
Author: [{Author}] | Library: [{Library}] Author: [{Author}] | Library: [{Library}]
Bot Version: [{BotVersion}] Bot Version: [{BotVersion}]
Bot ID: {curUser.Id} Bot ID: {curUser.Id}
@ -76,7 +73,7 @@ Owner ID(s): {OwnerIds}
Uptime: {GetUptimeString()} Uptime: {GetUptimeString()}
Servers: {client.GetGuilds().Count} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels} Servers: {client.GetGuilds().Count} | TextChannels: {TextChannels} | VoiceChannels: {VoiceChannels}
Commands Ran this session: {CommandsRan} Commands Ran this session: {CommandsRan}
Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]"; Messages: {MessageCounter} [{MessagesPerSecond:F2}/sec] Heap: [{Heap} MB]");
} }
public Task Reset() public Task Reset()

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using NLog; using NLog;
using System.Diagnostics;
namespace NadekoBot namespace NadekoBot
{ {
@ -13,24 +14,27 @@ namespace NadekoBot
private DiscordSocketConfig discordSocketConfig; private DiscordSocketConfig discordSocketConfig;
private Logger _log { get; } private Logger _log { get; }
public event Action<IGuildUser> UserJoined = delegate { }; public event Action<SocketGuildUser> UserJoined = delegate { };
public event Action<IMessage> MessageReceived = delegate { }; public event Action<SocketMessage> MessageReceived = delegate { };
public event Action<IGuildUser> UserLeft = delegate { }; public event Action<SocketGuildUser> UserLeft = delegate { };
public event Action<IGuildUser, IGuildUser> UserUpdated = delegate { }; public event Action<SocketUser, SocketUser> UserUpdated = delegate { };
public event Action<Optional<IMessage>, IMessage> MessageUpdated = delegate { }; public event Action<Optional<SocketMessage>, SocketMessage> MessageUpdated = delegate { };
public event Action<ulong, Optional<IMessage>> MessageDeleted = delegate { }; public event Action<ulong, Optional<SocketMessage>> MessageDeleted = delegate { };
public event Action<IUser, IGuild> UserBanned = delegate { }; public event Action<SocketUser, SocketGuild> UserBanned = delegate { };
public event Action<IUser, IGuild> UserUnbanned = delegate { }; public event Action<SocketUser, SocketGuild> UserUnbanned = delegate { };
public event Action<IGuildUser, IPresence, IPresence> UserPresenceUpdated = delegate { }; public event Action<Optional<SocketGuild>, SocketUser, SocketPresence, SocketPresence> UserPresenceUpdated = delegate { };
public event Action<IUser, IVoiceState, IVoiceState> UserVoiceStateUpdated = delegate { }; public event Action<SocketUser, SocketVoiceState, SocketVoiceState> UserVoiceStateUpdated = delegate { };
public event Action<IChannel> ChannelCreated = delegate { }; public event Action<SocketChannel> ChannelCreated = delegate { };
public event Action<IChannel> ChannelDestroyed = delegate { }; public event Action<SocketChannel> ChannelDestroyed = delegate { };
public event Action<IChannel, IChannel> ChannelUpdated = delegate { }; public event Action<SocketChannel, SocketChannel> ChannelUpdated = delegate { };
public event Action<Exception> Disconnected = delegate { }; public event Action<Exception> Disconnected = delegate { };
private uint _connectedCount = 0;
private uint _downloadedCount = 0;
private IReadOnlyList<DiscordSocketClient> Clients { get; } private IReadOnlyList<DiscordSocketClient> Clients { get; }
public ShardedDiscordClient (DiscordSocketConfig discordSocketConfig) public ShardedDiscordClient(DiscordSocketConfig discordSocketConfig)
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
this.discordSocketConfig = discordSocketConfig; this.discordSocketConfig = discordSocketConfig;
@ -54,7 +58,7 @@ namespace NadekoBot
client.MessageDeleted += (arg1, arg2) => { MessageDeleted(arg1, arg2); return Task.CompletedTask; }; client.MessageDeleted += (arg1, arg2) => { MessageDeleted(arg1, arg2); return Task.CompletedTask; };
client.UserBanned += (arg1, arg2) => { UserBanned(arg1, arg2); return Task.CompletedTask; }; client.UserBanned += (arg1, arg2) => { UserBanned(arg1, arg2); return Task.CompletedTask; };
client.UserUnbanned += (arg1, arg2) => { UserUnbanned(arg1, arg2); return Task.CompletedTask; }; client.UserUnbanned += (arg1, arg2) => { UserUnbanned(arg1, arg2); return Task.CompletedTask; };
client.UserPresenceUpdated += (arg1, arg2, arg3) => { UserPresenceUpdated(arg1, arg2, arg3); return Task.CompletedTask; }; client.UserPresenceUpdated += (arg1, arg2, arg3, arg4) => { UserPresenceUpdated(arg1, arg2, arg3, arg4); return Task.CompletedTask; };
client.UserVoiceStateUpdated += (arg1, arg2, arg3) => { UserVoiceStateUpdated(arg1, arg2, arg3); return Task.CompletedTask; }; client.UserVoiceStateUpdated += (arg1, arg2, arg3) => { UserVoiceStateUpdated(arg1, arg2, arg3); return Task.CompletedTask; };
client.ChannelCreated += arg => { ChannelCreated(arg); return Task.CompletedTask; }; client.ChannelCreated += arg => { ChannelCreated(arg); return Task.CompletedTask; };
client.ChannelDestroyed += arg => { ChannelDestroyed(arg); return Task.CompletedTask; }; client.ChannelDestroyed += arg => { ChannelDestroyed(arg); return Task.CompletedTask; };
@ -66,19 +70,16 @@ namespace NadekoBot
Clients = clientList.AsReadOnly(); Clients = clientList.AsReadOnly();
} }
public ISelfUser GetCurrentUser() => public DiscordSocketClient MainClient =>
Clients[0].GetCurrentUser(); Clients[0];
public Task<ISelfUser> GetCurrentUserAsync() => public SocketSelfUser CurrentUser() =>
Clients[0].GetCurrentUserAsync(); Clients[0].CurrentUser;
public Task<ISelfUser[]> GetAllCurrentUsersAsync() => public IReadOnlyCollection<SocketGuild> GetGuilds() =>
Task.WhenAll(Clients.Select(c => c.GetCurrentUserAsync())); Clients.SelectMany(c => c.Guilds).ToList();
public IReadOnlyCollection<IGuild> GetGuilds() => public SocketGuild GetGuild(ulong id) =>
Clients.SelectMany(c => c.GetGuilds()).ToArray();
public IGuild GetGuild(ulong id) =>
Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null); Clients.Select(c => c.GetGuild(id)).FirstOrDefault(g => g != null);
public Task<IDMChannel> GetDMChannelAsync(ulong channelId) => public Task<IDMChannel> GetDMChannelAsync(ulong channelId) =>
@ -89,12 +90,15 @@ namespace NadekoBot
internal async Task ConnectAsync() internal async Task ConnectAsync()
{ {
foreach (var c in Clients) foreach (var c in Clients)
{ {
try try
{ {
var sw = Stopwatch.StartNew();
await c.ConnectAsync().ConfigureAwait(false); await c.ConnectAsync().ConfigureAwait(false);
_log.Info($"Shard #{c.ShardId} connected."); sw.Stop();
_log.Info($"Shard #{c.ShardId} connected after {sw.Elapsed.TotalSeconds:F2}s ({++_connectedCount}/{Clients.Count})");
} }
catch catch
{ {
@ -110,19 +114,17 @@ namespace NadekoBot
} }
internal Task DownloadAllUsersAsync() => internal Task DownloadAllUsersAsync() =>
Task.WhenAll(Clients.Select(async c => { await c.DownloadAllUsersAsync().ConfigureAwait(false); _log.Info($"Shard #{c.ShardId} downloaded {c.GetGuilds().Sum(g => g.GetUsers().Count)} users."); })); Task.WhenAll(Clients.Select(async c =>
{
var sw = Stopwatch.StartNew();
await c.DownloadAllUsersAsync().ConfigureAwait(false);
sw.Stop();
_log.Info($"Shard #{c.ShardId} downloaded {c.Guilds.Sum(g => g.Users.Count)} users after {sw.Elapsed.TotalSeconds:F2}s ({++_downloadedCount}/{Clients.Count}).");
}));
public async Task SetGame(string game) public Task SetGame(string game) => Task.WhenAll(Clients.Select(ms => ms.SetGameAsync(game)));
{
await Task.WhenAll((await GetAllCurrentUsersAsync())
.Select(u => u.ModifyStatusAsync(ms => ms.Game = new Discord.Game(game))));
}
public async Task SetStream(string name, string url)
{
await Task.WhenAll((await GetAllCurrentUsersAsync())
.Select(u => u.ModifyStatusAsync(ms => ms.Game = new Discord.Game(name, url, StreamType.Twitch))));
} public Task SetStream(string name, string url) => Task.WhenAll(Clients.Select(ms => ms.SetGameAsync(name, url, StreamType.NotStreaming)));
} }
} }

View File

@ -1,18 +1,16 @@
using Discord.Commands; using Discord.Commands;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
namespace NadekoBot.TypeReaders namespace NadekoBot.TypeReaders
{ {
public class CommandTypeReader : TypeReader public class CommandTypeReader : TypeReader
{ {
public override Task<TypeReaderResult> Read(IUserMessage context, string input) public override Task<TypeReaderResult> Read(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var cmd = NadekoBot.CommandService.Commands.FirstOrDefault(c => var cmd = NadekoBot.CommandService.Commands.FirstOrDefault(c =>
c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input) || c.Aliases.Select(a => a.ToUpperInvariant()).Contains(input));
c.Text.ToUpperInvariant() == input);
if (cmd == null) if (cmd == null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such command found."));

View File

@ -1,13 +1,12 @@
using Discord.Commands; using Discord.Commands;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
namespace NadekoBot.TypeReaders namespace NadekoBot.TypeReaders
{ {
public class GuildTypeReader : TypeReader public class GuildTypeReader : TypeReader
{ {
public override Task<TypeReaderResult> Read(IUserMessage context, string input) public override Task<TypeReaderResult> Read(ICommandContext context, string input)
{ {
input = input.Trim().ToLowerInvariant(); input = input.Trim().ToLowerInvariant();
var guilds = NadekoBot.Client.GetGuilds(); var guilds = NadekoBot.Client.GetGuilds();

View File

@ -1,16 +1,16 @@
using Discord.Commands; using Discord.Commands;
using NadekoBot.Extensions;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
namespace NadekoBot.TypeReaders namespace NadekoBot.TypeReaders
{ {
public class ModuleTypeReader : TypeReader public class ModuleTypeReader : TypeReader
{ {
public override Task<TypeReaderResult> Read(IUserMessage context, string input) public override Task<TypeReaderResult> Read(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
var module = NadekoBot.CommandService.Modules.FirstOrDefault(m => m.Name.ToUpperInvariant() == input); var module = NadekoBot.CommandService.Modules.GroupBy(m => m.GetTopLevelModule()).FirstOrDefault(m => m.Key.Name.ToUpperInvariant() == input)?.Key;
if (module == null) if (module == null)
return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such module found.")); return Task.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "No such module found."));

View File

@ -1,6 +1,5 @@
using Discord.Commands; using Discord.Commands;
using System.Threading.Tasks; using System.Threading.Tasks;
using Discord;
using NadekoBot.Modules.Permissions; using NadekoBot.Modules.Permissions;
namespace NadekoBot.TypeReaders namespace NadekoBot.TypeReaders
@ -10,7 +9,7 @@ namespace NadekoBot.TypeReaders
/// </summary> /// </summary>
public class PermissionActionTypeReader : TypeReader public class PermissionActionTypeReader : TypeReader
{ {
public override Task<TypeReaderResult> Read(IUserMessage context, string input) public override Task<TypeReaderResult> Read(ICommandContext context, string input)
{ {
input = input.ToUpperInvariant(); input = input.ToUpperInvariant();
switch (input) switch (input)

View File

@ -1,6 +1,5 @@
using Discord; using Discord;
using Discord.API; using Discord.Commands;
using Discord.WebSocket;
using ImageSharp; using ImageSharp;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
@ -10,7 +9,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -25,8 +23,7 @@ namespace NadekoBot.Extensions
http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); http.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
} }
public static EmbedBuilder WithImageUrl(this EmbedBuilder eb, string url) => public static DateTime ToUnixTimestamp(this double number) => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(number);
eb.WithImage(eib => eib.WithUrl(url));
public static EmbedBuilder WithOkColor(this EmbedBuilder eb) => public static EmbedBuilder WithOkColor(this EmbedBuilder eb) =>
eb.WithColor(NadekoBot.OkColor); eb.WithColor(NadekoBot.OkColor);
@ -45,6 +42,16 @@ namespace NadekoBot.Extensions
return msg; return msg;
} }
public static string GetPrefix(this ModuleInfo module) => NadekoBot.ModulePrefixes[module.GetTopLevelModule().Name];
public static ModuleInfo GetTopLevelModule(this ModuleInfo module) {
while (module.Parent != null)
{
module = module.Parent;
}
return module;
}
public static async Task<IMessage> SendMessageToOwnerAsync(this IGuild guild, string message) public static async Task<IMessage> SendMessageToOwnerAsync(this IGuild guild, string message)
{ {
var ownerPrivate = await (await guild.GetOwnerAsync().ConfigureAwait(false)).CreateDMChannelAsync() var ownerPrivate = await (await guild.GetOwnerAsync().ConfigureAwait(false)).CreateDMChannelAsync()
@ -53,6 +60,12 @@ namespace NadekoBot.Extensions
return await ownerPrivate.SendMessageAsync(message).ConfigureAwait(false); return await ownerPrivate.SendMessageAsync(message).ConfigureAwait(false);
} }
//public static async Task<IEnumerable<IGuildUser>> MentionedUsers(this IUserMessage msg) =>
public static IEnumerable<IRole> GetRoles(this IGuildUser user) =>
user.RoleIds.Select(r => user.Guild.GetRole(r)).Where(r => r != null);
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> elems, Action<T> exec) public static IEnumerable<T> ForEach<T>(this IEnumerable<T> elems, Action<T> exec)
{ {
foreach (var elem in elems) foreach (var elem in elems)
@ -85,69 +98,51 @@ namespace NadekoBot.Extensions
public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds; public static double UnixTimestamp(this DateTime dt) => dt.ToUniversalTime().Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
public static DateTime ToUnixTimestamp(this double number) => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(number); public static async Task<IUserMessage> SendMessageAsync(this IUser user, string message, bool isTTS = false) =>
public static async Task<IUserMessage> SendMessageAsync(this IGuildUser user, string message, bool isTTS = false) =>
await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, isTTS).ConfigureAwait(false); await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendMessageAsync(message, isTTS).ConfigureAwait(false);
public static async Task<IUserMessage> SendConfirmAsync(this IGuildUser user, string text) public static async Task<IUserMessage> SendConfirmAsync(this IUser user, string text)
=> await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new Embed() { Description = text, Color = NadekoBot.OkColor }); => await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text));
public static async Task<IUserMessage> SendConfirmAsync(this IGuildUser user, string title, string text, string url = null) public static async Task<IUserMessage> SendConfirmAsync(this IUser user, string title, string text, string url = null)
=> await(await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new Embed() { Description = text, Title = title, Url = url, Color = NadekoBot.OkColor }); => await(await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text)
.WithTitle(title).WithUrl(url));
public static async Task<IUserMessage> SendErrorAsync(this IGuildUser user, string title, string error, string url = null) public static async Task<IUserMessage> SendErrorAsync(this IUser user, string title, string error, string url = null)
=> await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new Embed() { Description = error, Title = title, Url = url, Color = NadekoBot.ErrorColor }); => await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(error)
.WithTitle(title).WithUrl(url));
public static async Task<IUserMessage> SendErrorAsync(this IGuildUser user, string error) public static async Task<IUserMessage> SendErrorAsync(this IUser user, string error)
=> await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new Embed() { Description = error, Color = NadekoBot.ErrorColor }); => await (await user.CreateDMChannelAsync()).SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(error));
public static async Task<IUserMessage> SendFileAsync(this IGuildUser user, string filePath, string caption = null, bool isTTS = false) => public static async Task<IUserMessage> SendFileAsync(this IUser user, string filePath, string caption = null, string text = null, bool isTTS = false) =>
await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(filePath, caption, isTTS).ConfigureAwait(false); await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(File.Open(filePath, FileMode.Open), caption ?? "x", text, isTTS).ConfigureAwait(false);
public static async Task<IUserMessage> SendFileAsync(this IGuildUser user, Stream fileStream, string fileName, string caption = null, bool isTTS = false) => public static async Task<IUserMessage> SendFileAsync(this IUser user, Stream fileStream, string fileName, string caption = null, bool isTTS = false) =>
await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(fileStream, fileName, caption, isTTS).ConfigureAwait(false); await (await user.CreateDMChannelAsync().ConfigureAwait(false)).SendFileAsync(fileStream, fileName, caption, isTTS).ConfigureAwait(false);
public static bool IsAuthor(this IUserMessage msg) => public static bool IsAuthor(this IUserMessage msg) =>
NadekoBot.Client.GetCurrentUser().Id == msg.Author.Id; NadekoBot.Client.CurrentUser().Id == msg.Author.Id;
public static IEnumerable<IUser> Members(this IRole role) => public static IEnumerable<IUser> Members(this IRole role) =>
NadekoBot.Client.GetGuild(role.GuildId)?.GetUsers().Where(u => u.Roles.Contains(role)) ?? Enumerable.Empty<IUser>(); role.Guild.GetUsersAsync().GetAwaiter().GetResult().Where(u => u.RoleIds.Contains(role.Id)) ?? Enumerable.Empty<IUser>();
public static Task<IUserMessage> EmbedAsync(this IMessageChannel ch, Discord.API.Embed embed, string msg = "") public static Task<IUserMessage> EmbedAsync(this IMessageChannel ch, EmbedBuilder embed, string msg = "")
=> ch.SendMessageAsync(msg, embed: embed); => ch.SendMessageAsync(msg, embed: embed);
public static Task<IUserMessage> SendErrorAsync(this IMessageChannel ch, string title, string error, string url = null, string footer = null) public static Task<IUserMessage> SendErrorAsync(this IMessageChannel ch, string title, string error, string url = null, string footer = null)
=> ch.SendMessageAsync("", embed: new Embed() => ch.SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.ErrorColor).WithDescription(error)
{ .WithTitle(title).WithUrl(url).WithFooter(efb => efb.WithText(footer)));
Description = error,
Title = title,
Url = url,
Color = NadekoBot.ErrorColor,
Footer = new Discord.API.EmbedFooter()
{
Text = footer
}
});
public static Task<IUserMessage> SendErrorAsync(this IMessageChannel ch, string error) public static Task<IUserMessage> SendErrorAsync(this IMessageChannel ch, string error)
=> ch.SendMessageAsync("", embed: new Embed() { Description = error, Color = NadekoBot.ErrorColor }); => ch.SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(error));
public static Task<IUserMessage> SendConfirmAsync(this IMessageChannel ch, string title, string text, string url = null, string footer = null) public static Task<IUserMessage> SendConfirmAsync(this IMessageChannel ch, string title, string text, string url = null, string footer = null)
=> ch.SendMessageAsync("", embed: new Embed() => ch.SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text)
{ .WithTitle(title).WithUrl(url).WithFooter(efb => efb.WithText(footer)));
Description = text,
Title = title,
Url = url,
Color = NadekoBot.OkColor,
Footer = new Discord.API.EmbedFooter()
{
Text = footer
}
});
public static Task<IUserMessage> SendConfirmAsync(this IMessageChannel ch, string text) public static Task<IUserMessage> SendConfirmAsync(this IMessageChannel ch, string text)
=> ch.SendMessageAsync("", embed: new Embed() { Description = text, Color = NadekoBot.OkColor }); => ch.SendMessageAsync("", embed: new EmbedBuilder().WithColor(NadekoBot.OkColor).WithDescription(text));
public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, string seed, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3) public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, string seed, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3)
{ {
@ -158,10 +153,8 @@ namespace NadekoBot.Extensions
```"); ```");
} }
public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3) public static Task<IUserMessage> SendTableAsync<T>(this IMessageChannel ch, IEnumerable<T> items, Func<T, string> howToPrint, int columns = 3) =>
{ ch.SendTableAsync("", items, howToPrint, columns);
return ch.SendTableAsync("", items, howToPrint, columns);
}
/// <summary> /// <summary>
/// returns an IEnumerable with randomized element order /// returns an IEnumerable with randomized element order
@ -316,11 +309,11 @@ namespace NadekoBot.Extensions
public static string Unmention(this string str) => str.Replace("@", "ම"); public static string Unmention(this string str) => str.Replace("@", "ම");
public static Image Merge(this IEnumerable<Image> images) public static ImageSharp.Image Merge(this IEnumerable<ImageSharp.Image> images)
{ {
var imgList = images.ToList(); var imgList = images.ToList();
var canvas = new Image(imgList.Sum(img => img.Width), imgList.Max(img => img.Height)); var canvas = new ImageSharp.Image(imgList.Sum(img => img.Width), imgList.Max(img => img.Height));
var canvasPixels = canvas.Lock(); var canvasPixels = canvas.Lock();
int offsetX = 0; int offsetX = 0;
@ -339,7 +332,7 @@ namespace NadekoBot.Extensions
return canvas; return canvas;
} }
public static Stream ToStream(this Image img) public static Stream ToStream(this ImageSharp.Image img)
{ {
var imageStream = new MemoryStream(); var imageStream = new MemoryStream();
img.SaveAsPng(imageStream); img.SaveAsPng(imageStream);

Some files were not shown because too many files have changed in this diff Show More