diff --git a/src/NadekoBot/Modules/Administration/Commands/DMForwardCommands.cs b/src/NadekoBot/Modules/Administration/Commands/DMForwardCommands.cs new file mode 100644 index 00000000..9a872341 --- /dev/null +++ b/src/NadekoBot/Modules/Administration/Commands/DMForwardCommands.cs @@ -0,0 +1,89 @@ +using Discord; +using Discord.Commands; +using NadekoBot.Attributes; +using NadekoBot.Services; +using NadekoBot.Services.Database; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NadekoBot.Modules.Administration +{ + public partial class Administration + { + [Group] + public class DMForwardCommands + { + private static bool ForwardDMs { get; set; } + private static bool ForwardDMsToAllOwners { get; set; } + + static DMForwardCommands() + { + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.BotConfig.GetOrCreate(); + ForwardDMs = config.ForwardMessages; + ForwardDMsToAllOwners = config.ForwardToAllOwners; + } + } + + [NadekoCommand, Usage, Description, Aliases] + [OwnerOnly] + public async Task ForwardMessages(IUserMessage imsg) + { + var channel = imsg.Channel; + + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.BotConfig.GetOrCreate(); + ForwardDMs = config.ForwardMessages = !config.ForwardMessages; + uow.Complete(); + } + if (ForwardDMs) + await channel.SendMessageAsync("`I will forward DMs from now on.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("`I will stop forwarding DMs.`").ConfigureAwait(false); + } + + [NadekoCommand, Usage, Description, Aliases] + [OwnerOnly] + public async Task ForwardToAll(IUserMessage imsg) + { + var channel = imsg.Channel; + + using (var uow = DbHandler.UnitOfWork()) + { + var config = uow.BotConfig.GetOrCreate(); + ForwardDMsToAllOwners = config.ForwardToAllOwners = !config.ForwardToAllOwners; + uow.Complete(); + } + if (ForwardDMsToAllOwners) + await channel.SendMessageAsync("`I will forward DMs to all owners.`").ConfigureAwait(false); + else + await channel.SendMessageAsync("`I will forward DMs only to the first owner.`").ConfigureAwait(false); + + } + + public static async Task HandleDMForwarding(IMessage msg, List ownerChannels) + { + if (ForwardDMs && ownerChannels.Any()) + { + var toSend = $"`I received a message from {msg.Author} ({msg.Author.Id})`: {msg.Content}"; + if (ForwardDMsToAllOwners) + { + var msgs = await Task.WhenAll(ownerChannels.Where(ch => ch.Recipient.Id != msg.Author.Id) + .Select(ch => ch.SendMessageAsync(toSend))).ConfigureAwait(false); + } + else + { + var firstOwnerChannel = ownerChannels.First(); + if (firstOwnerChannel.Recipient.Id != msg.Author.Id) + try { await firstOwnerChannel.SendMessageAsync(msg.Content).ConfigureAwait(false); } catch { } + } + } + } + } + } +} diff --git a/src/NadekoBot/NadekoBot.cs b/src/NadekoBot/NadekoBot.cs index bf26ad28..0b8e3e7e 100644 --- a/src/NadekoBot/NadekoBot.cs +++ b/src/NadekoBot/NadekoBot.cs @@ -88,6 +88,9 @@ namespace NadekoBot { ModulePrefixes = new ReadOnlyDictionary(uow.BotConfig.GetOrCreate().ModulePrefixes.ToDictionary(m => m.ModuleName, m => m.Prefix)); } + // start handling messages received in commandhandler + await CommandHandler.StartHandling(); + await CommandService.LoadAssembly(Assembly.GetEntryAssembly(), depMap).ConfigureAwait(false); Console.WriteLine(await Stats.Print().ConfigureAwait(false)); diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 45b92683..7595805c 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -2381,6 +2381,60 @@ namespace NadekoBot.Resources { } } + /// + /// Looks up a localized string similar to fwmsgs. + /// + public static string forwardmessages_cmd { + get { + return ResourceManager.GetString("forwardmessages_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles forwarding of non-command messages sent to bot's DM to the bot owners. + /// + public static string forwardmessages_desc { + get { + return ResourceManager.GetString("forwardmessages_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `.fwmsgs`. + /// + public static string forwardmessages_usage { + get { + return ResourceManager.GetString("forwardmessages_usage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to fwtoall. + /// + public static string forwardtoall_cmd { + get { + return ResourceManager.GetString("forwardtoall_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json. + /// + public static string forwardtoall_desc { + get { + return ResourceManager.GetString("forwardtoall_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `.fwtoall`. + /// + public static string forwardtoall_usage { + get { + return ResourceManager.GetString("forwardtoall_usage", resourceCulture); + } + } + /// /// Looks up a localized string similar to gelbooru. /// diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 8af562f3..1ea02dbc 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2619,4 +2619,22 @@ `$sh` + + fwmsgs + + + Toggles forwarding of non-command messages sent to bot's DM to the bot owners + + + `.fwmsgs` + + + fwtoall + + + Toggles whether messages will be forwarded to all bot owners or only to the first one specified in the credentials.json + + + `.fwtoall` + \ No newline at end of file diff --git a/src/NadekoBot/Services/CommandHandler.cs b/src/NadekoBot/Services/CommandHandler.cs index da9cbe68..4516bb90 100644 --- a/src/NadekoBot/Services/CommandHandler.cs +++ b/src/NadekoBot/Services/CommandHandler.cs @@ -17,15 +17,30 @@ using NadekoBot.Extensions; using static NadekoBot.Modules.Permissions.Permissions; using System.Collections.Concurrent; using NadekoBot.Modules.Help; +using static NadekoBot.Modules.Administration.Administration; namespace NadekoBot.Services { + public class IGuildUserComparer : IEqualityComparer + { + public bool Equals(IGuildUser x, IGuildUser y) + { + return x.Id == y.Id; + } + + public int GetHashCode(IGuildUser obj) + { + return obj.Id.GetHashCode(); + } + } public class CommandHandler { - private ShardedDiscordClient _client; + private ShardedDiscordClient _client; private CommandService _commandService; private Logger _log; + private List ownerChannels { get; set; } + public event EventHandler CommandExecuted = delegate { }; public CommandHandler(ShardedDiscordClient client, CommandService commandService) @@ -33,6 +48,20 @@ namespace NadekoBot.Services _client = client; _commandService = commandService; _log = LogManager.GetCurrentClassLogger(); + } + public async Task StartHandling() + { + ownerChannels = (await Task.WhenAll(_client.GetGuilds().SelectMany(g => g.GetUsers()) + .Where(u => NadekoBot.Credentials.OwnerIds.Contains(u.Id)) + .Distinct(new IGuildUserComparer()) + .Select(async u => { try { return await u.CreateDMChannelAsync(); } catch { return null; } }))) + .Where(ch => ch != null) + .ToList(); + + if (!ownerChannels.Any()) + _log.Warn("No owner channels created! Make sure you've specified correct OwnerId in the credentials.json file."); + else + _log.Info($"Created {ownerChannels.Count} out of {NadekoBot.Credentials.OwnerIds.Length} owner message channels."); _client.MessageReceived += MessageReceivedHandler; } @@ -110,7 +139,7 @@ namespace NadekoBot.Services permRole = config.PermissionRole.Trim().ToLowerInvariant(); } - + } var throwaway = Task.Run(async () => @@ -158,7 +187,7 @@ namespace NadekoBot.Services if (guild != null && command != null && result.Error == CommandError.Exception) { if (verbose) - await msg.Channel.SendMessageAsync(":warning: " + result.ErrorReason).ConfigureAwait(false); + try { await msg.Channel.SendMessageAsync(":warning: " + result.ErrorReason).ConfigureAwait(false); } catch { } } } else @@ -166,6 +195,8 @@ namespace NadekoBot.Services if (msg.Channel is IPrivateChannel) { await msg.Channel.SendMessageAsync(Help.DMHelpString).ConfigureAwait(false); + + await DMForwardCommands.HandleDMForwarding(msg, ownerChannels); } } } @@ -185,7 +216,7 @@ namespace NadekoBot.Services } } - public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, Permission rootPerm, string permRole, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { + public async Task> ExecuteCommand(IUserMessage message, string input, IGuild guild, IUser user, Permission rootPerm, string permRole, MultiMatchHandling multiMatchHandling = MultiMatchHandling.Best) { var searchResult = _commandService.Search(message, input); if (!searchResult.IsSuccess) return new Tuple(null, searchResult);