From 84a0fc4c8f3c4949bd8ade15361bf2798cb15bc6 Mon Sep 17 00:00:00 2001 From: Kwoth Date: Thu, 27 Oct 2016 11:45:57 +0200 Subject: [PATCH] Added auto-translate language feature (~atl and ~at) --- .../Modules/Searches/Commands/Translator.cs | 180 +++++++++++++++--- .../Resources/CommandStrings.Designer.cs | 56 +++++- src/NadekoBot/Resources/CommandStrings.resx | 20 +- 3 files changed, 229 insertions(+), 27 deletions(-) diff --git a/src/NadekoBot/Modules/Searches/Commands/Translator.cs b/src/NadekoBot/Modules/Searches/Commands/Translator.cs index 07d36f91..f82b1a98 100644 --- a/src/NadekoBot/Modules/Searches/Commands/Translator.cs +++ b/src/NadekoBot/Modules/Searches/Commands/Translator.cs @@ -6,47 +6,177 @@ using System; using System.Threading.Tasks; using NadekoBot.Services; using Discord.WebSocket; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Linq; namespace NadekoBot.Modules.Searches { public partial class Searches { - [NadekoCommand, Usage, Description, Aliases] - [RequireContext(ContextType.Guild)] - public async Task Translate(IUserMessage umsg, string langs, [Remainder] string text = null) + public struct UserChannelPair { - var channel = (ITextChannel)umsg.Channel; + public ulong UserId { get; set; } + public ulong ChannelId { get; set; } + } - try + [Group] + public class TranslateCommands + { + private static ConcurrentDictionary TranslatedChannels { get; } + private static ConcurrentDictionary UserLanguages { get; } + + static TranslateCommands() + { + TranslatedChannels = new ConcurrentDictionary(); + UserLanguages = new ConcurrentDictionary(); + + NadekoBot.Client.MessageReceived += (msg) => + { + var umsg = msg as IUserMessage; + if(umsg == null) + return Task.CompletedTask; + + bool autoDelete; + if (!TranslatedChannels.TryGetValue(umsg.Channel.Id, out autoDelete)) + return Task.CompletedTask; + + var t = Task.Run(async () => + { + var key = new UserChannelPair() + { + UserId = umsg.Author.Id, + ChannelId = umsg.Channel.Id, + }; + + string langs; + if (!UserLanguages.TryGetValue(key, out langs)) + return; + + try + { + var text = await TranslateInternal(umsg, langs, umsg.Resolve(UserMentionHandling.Ignore), true) + .ConfigureAwait(false); + if (autoDelete) + try { await umsg.DeleteAsync().ConfigureAwait(false); } catch { } + await umsg.Channel.SendMessageAsync($"{umsg.Author.Mention} `said:` "+text.Replace("<@ ", "<@").Replace("<@! ", "<@!")).ConfigureAwait(false); + } + catch { } + + }); + return Task.CompletedTask; + }; + } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Translate(IUserMessage umsg, string langs, [Remainder] string text = null) + { + var channel = (ITextChannel)umsg.Channel; + + try + { + await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); + var translation = await TranslateInternal(umsg, langs, text); + await channel.SendMessageAsync(translation).ConfigureAwait(false); + + } + catch + { + await channel.SendMessageAsync("Bad input format, or something went wrong...").ConfigureAwait(false); + } + } + + private static async Task TranslateInternal(IUserMessage umsg, string langs, [Remainder] string text = null, bool silent = false) { var langarr = langs.ToLowerInvariant().Split('>'); if (langarr.Length != 2) - return; + throw new ArgumentException(); string from = langarr[0]; string to = langarr[1]; text = text?.Trim(); if (string.IsNullOrWhiteSpace(text)) - return; - - await umsg.Channel.TriggerTypingAsync().ConfigureAwait(false); - string translation = await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false); - await channel.SendMessageAsync(translation).ConfigureAwait(false); + throw new ArgumentException(); + return await GoogleTranslator.Instance.Translate(text, from, to).ConfigureAwait(false); } - catch (Exception ex) + + public enum AutoDeleteAutoTranslate { - Console.WriteLine(ex); - await channel.SendMessageAsync("Bad input format, or something went wrong...").ConfigureAwait(false); + Del, + Nodel } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + [RequirePermission(GuildPermission.Administrator)] + [OwnerOnly] + public async Task AutoTranslate(IUserMessage msg, AutoDeleteAutoTranslate autoDelete = AutoDeleteAutoTranslate.Nodel) + { + var channel = (ITextChannel)msg.Channel; + + if (autoDelete == AutoDeleteAutoTranslate.Del) + { + TranslatedChannels.AddOrUpdate(channel.Id, true, (key, val) => true); + try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel. User messages will be auto-deleted.`").ConfigureAwait(false); } catch { } + return; + } + + bool throwaway; + if (TranslatedChannels.TryRemove(channel.Id, out throwaway)) + { + try { await channel.SendMessageAsync("`Stopped automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { } + return; + } + else if (TranslatedChannels.TryAdd(channel.Id, autoDelete == AutoDeleteAutoTranslate.Del)) + { + try { await channel.SendMessageAsync("`Started automatic translation of messages on this channel.`").ConfigureAwait(false); } catch { } + } + } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task AutoTransLang(IUserMessage msg, [Remainder] string langs = null) + { + var channel = (ITextChannel)msg.Channel; + + var ucp = new UserChannelPair + { + UserId = msg.Author.Id, + ChannelId = msg.Channel.Id, + }; + + if (string.IsNullOrWhiteSpace(langs)) + { + if (UserLanguages.TryRemove(ucp, out langs)) + await channel.SendMessageAsync($"{msg.Author.Mention}'s auto-translate language has been removed.").ConfigureAwait(false); + return; + } + + var langarr = langs.ToLowerInvariant().Split('>'); + if (langarr.Length != 2) + return; + var from = langarr[0]; + var to = langarr[1]; + + if (!GoogleTranslator.Instance.Languages.Contains(from) || !GoogleTranslator.Instance.Languages.Contains(to)) + { + try { await channel.SendMessageAsync("`Invalid source and/or target Language.`").ConfigureAwait(false); } catch { } + } + + UserLanguages.AddOrUpdate(ucp, langs, (key, val) => langs); + + await channel.SendMessageAsync(":ok:").ConfigureAwait(false); + } + + [NadekoCommand, Usage, Description, Aliases] + [RequireContext(ContextType.Guild)] + public async Task Translangs(IUserMessage umsg) + { + var channel = (ITextChannel)umsg.Channel; + + await channel.SendTableAsync(GoogleTranslator.Instance.Languages, str => $"{str,-15}", columns: 3); + } + } - - [NadekoCommand, Usage, Description, Aliases] - [RequireContext(ContextType.Guild)] - public async Task Translangs(IUserMessage umsg) - { - var channel = (ITextChannel)umsg.Channel; - - await channel.SendTableAsync(GoogleTranslator.Instance.Languages, str => $"{str,-15}", columns: 3); - } - } -} +} \ No newline at end of file diff --git a/src/NadekoBot/Resources/CommandStrings.Designer.cs b/src/NadekoBot/Resources/CommandStrings.Designer.cs index 8a728890..f4cf477f 100644 --- a/src/NadekoBot/Resources/CommandStrings.Designer.cs +++ b/src/NadekoBot/Resources/CommandStrings.Designer.cs @@ -519,7 +519,61 @@ namespace NadekoBot.Resources { } /// - /// Looks up a localized string similar to av avatar. + /// Looks up a localized string similar to autotranslang atl. + /// + public static string autotranslang_cmd { + get { + return ResourceManager.GetString("autotranslang_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}atl en>fr`. + /// + public static string autotranslang_desc { + get { + return ResourceManager.GetString("autotranslang_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Sets your source and target language to be used with `{0}at`. Specify no arguments to remove previously set value.. + /// + public static string autotranslang_usage { + get { + return ResourceManager.GetString("autotranslang_usage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to autotrans at. + /// + public static string autotranslate_cmd { + get { + return ResourceManager.GetString("autotranslate_cmd", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set "del" argument to automatically delete all translated user messages.. + /// + public static string autotranslate_desc { + get { + return ResourceManager.GetString("autotranslate_desc", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to `{0}at` or `{0}at del`. + /// + public static string autotranslate_usage { + get { + return ResourceManager.GetString("autotranslate_usage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to avatar av. /// public static string avatar_cmd { get { diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 36b807dc..8fc36849 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -2089,7 +2089,7 @@ `{0}videocall "@SomeGuy"` - av avatar + avatar av Shows a mentioned person's avatar. @@ -2547,4 +2547,22 @@ `{0}ppoll Question?;Answer1;Answ 2;A_3` + + autotranslang atl + + + `{0}atl en>fr` + + + Sets your source and target language to be used with `{0}at`. Specify no arguments to remove previously set value. + + + autotrans at + + + Starts automatic translation of all messages by users who set their `{0}atl` in this channel. You can set "del" argument to automatically delete all translated user messages. + + + `{0}at` or `{0}at del` + \ No newline at end of file