Merge remote-tracking branch 'refs/remotes/Kwoth/master' into selfassignedtoggle

merging branch
This commit is contained in:
appelemac
2016-07-17 20:49:25 +02:00
33 changed files with 886 additions and 402 deletions

View File

@ -6,8 +6,11 @@ using NadekoBot.DataModels;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Commands;
using NadekoBot.Modules.Permissions.Classes;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration
@ -76,7 +79,7 @@ namespace NadekoBot.Modules.Administration
});
cgb.CreateCommand(Prefix + "restart")
.Description("Restarts the bot. Might not work.")
.Description("Restarts the bot. Might not work. **Bot Owner Only**")
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
@ -902,6 +905,33 @@ namespace NadekoBot.Modules.Administration
await e.Channel.SendMessage("`Done.`").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "savechat")
.Description("Saves a number of messages to a text file and sends it to you. **Bot Owner Only** | `.chatsave 150`")
.Parameter("cnt", ParameterType.Required)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var cntstr = e.GetArg("cnt")?.Trim();
int cnt;
if (!int.TryParse(cntstr, out cnt))
return;
ulong? lastmsgId = null;
var sb = new StringBuilder();
var msgs = new List<Message>(cnt);
while (cnt > 0)
{
var dlcnt = cnt < 100 ? cnt : 100;
var dledMsgs = await e.Channel.DownloadMessages(dlcnt, lastmsgId);
if (!dledMsgs.Any())
break;
msgs.AddRange(dledMsgs);
lastmsgId = msgs[msgs.Count - 1].Id;
cnt -= 100;
}
await e.User.SendFile($"Chatlog-{e.Server.Name}/#{e.Channel.Name}-{DateTime.Now}.txt", JsonConvert.SerializeObject(new { Messages = msgs.Select(s => s.ToString()) }, Formatting.Indented).ToStream());
});
});
}
}

View File

@ -2,6 +2,7 @@
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -45,14 +46,88 @@ namespace NadekoBot.Modules.Administration.Commands
cgb.CreateCommand(Prefix + "listcustreact")
.Alias(Prefix + "lcr")
.Description($"Lists all current custom reactions (paginated with 5 commands per page).\n**Usage**:{Prefix}lcr 1")
.Description($"Lists all current custom reactions (paginated with 30 commands per page).\n**Usage**:{Prefix}lcr 1")
.Parameter("num", ParameterType.Required)
.Do(async e =>
{
int num;
if (!int.TryParse(e.GetArg("num"), out num) || num <= 0) return;
string result = GetCustomsOnPage(num - 1); //People prefer starting with 1
await e.Channel.SendMessage(result).ConfigureAwait(false);
if (!int.TryParse(e.GetArg("num"), out num) || num <= 0) num = 1;
var cmds = GetCustomsOnPage(num - 1);
if (!cmds.Any())
{
await e.Channel.SendMessage("");
}
else
{
string result = SearchHelper.ShowInPrettyCode<string>(cmds, s => $"{s,-25}"); //People prefer starting with 1
await e.Channel.SendMessage($"`Showing page {num}:`\n" + result).ConfigureAwait(false);
}
});
cgb.CreateCommand(Prefix + "showcustreact")
.Alias(Prefix + "scr")
.Description($"Shows all possible responses from a single custom reaction.\n**Usage**:{Prefix}scr %mention% bb")
.Parameter("name", ParameterType.Unparsed)
.Do(async e =>
{
var name = e.GetArg("name")?.Trim();
if (string.IsNullOrWhiteSpace(name))
return;
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
{
await e.Channel.SendMessage("`Can't find that custom reaction.`").ConfigureAwait(false);
return;
}
var items = NadekoBot.Config.CustomReactions[name];
var message = new StringBuilder($"Responses for {Format.Bold(name)}:\n");
var last = items.Last();
int i = 1;
foreach (var reaction in items)
{
message.AppendLine($"[{i++}] " + Format.Code(reaction));
}
await e.Channel.SendMessage(message.ToString());
});
cgb.CreateCommand(Prefix + "editcustreact")
.Alias(Prefix + "ecr")
.Description("Edits a custom reaction, arguments are custom reactions name, index to change, and a (multiword) message **Bot Owner Only** | `.ecr \"%mention% disguise\" 2 Test 123`")
.Parameter("name", ParameterType.Required)
.Parameter("index", ParameterType.Required)
.Parameter("message", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.OwnerOnly())
.Do(async e =>
{
var name = e.GetArg("name")?.Trim();
if (string.IsNullOrWhiteSpace(name))
return;
var indexstr = e.GetArg("index")?.Trim();
if (string.IsNullOrWhiteSpace(indexstr))
return;
var msg = e.GetArg("message")?.Trim();
if (string.IsNullOrWhiteSpace(msg))
return;
if (!NadekoBot.Config.CustomReactions.ContainsKey(name))
{
await e.Channel.SendMessage("`Could not find given commandname`").ConfigureAwait(false);
return;
}
int index;
if (!int.TryParse(indexstr, out index) || index < 1 || index > NadekoBot.Config.CustomReactions[name].Count)
{
await e.Channel.SendMessage("`Invalid index.`").ConfigureAwait(false);
return;
}
index = index - 1;
NadekoBot.Config.CustomReactions[name][index] = msg;
await Task.Run(() => Classes.JSONModels.ConfigHandler.SaveConfig()).ConfigureAwait(false);
await e.Channel.SendMessage($"Edited response #{index + 1} from `{name}`").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "delcustreact")
@ -99,19 +174,21 @@ namespace NadekoBot.Modules.Administration.Commands
});
}
private readonly int ItemsPerPage = 5;
private readonly int ItemsPerPage = 30;
private string GetCustomsOnPage(int page)
private IEnumerable<string> GetCustomsOnPage(int page)
{
var items = NadekoBot.Config.CustomReactions.Skip(page * ItemsPerPage).Take(ItemsPerPage);
if (!items.Any())
{
return $"No items on page {page + 1}.";
return Enumerable.Empty<string>();
}
return items.Select(kvp => kvp.Key);
/*
var message = new StringBuilder($"--- Custom reactions - page {page + 1} ---\n");
foreach (var cr in items)
{
message.Append($"{ Format.Code(cr.Key)}\n");
message.Append($"{Format.Code(cr.Key)}\n");
int i = 1;
var last = cr.Value.Last();
foreach (var reaction in cr.Value)
@ -123,6 +200,7 @@ namespace NadekoBot.Modules.Administration.Commands
}
}
return message.ToString() + "\n";
*/
}
}
}

View File

@ -4,19 +4,12 @@ using NadekoBot.Classes;
using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Administration.Commands
{
internal class LogCommand : DiscordCommand
{
private readonly ConcurrentDictionary<Server, Channel> logs = new ConcurrentDictionary<Server, Channel>();
private readonly ConcurrentDictionary<Server, Channel> loggingPresences = new ConcurrentDictionary<Server, Channel>();
private readonly ConcurrentDictionary<Channel, Channel> voiceChannelLog = new ConcurrentDictionary<Channel, Channel>();
private string prettyCurrentTime => $"【{DateTime.Now:HH:mm:ss}】";
public LogCommand(DiscordModule module) : base(module)
@ -58,8 +51,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (e.Before.Name != e.After.Name)
await ch.SendMessage($@"`{prettyCurrentTime}` **Channel Name Changed** `#{e.Before.Name}` (*{e.After.Id}*)
@ -76,8 +72,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"❗`{prettyCurrentTime}`❗`Channel Deleted:` #{e.Channel.Name} (*{e.Channel.Id}*)").ConfigureAwait(false);
}
@ -88,8 +87,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`🆕`Channel Created:` #{e.Channel.Mention} (*{e.Channel.Id}*)").ConfigureAwait(false);
}
@ -100,8 +102,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`♻`User was unbanned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
@ -112,8 +117,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`✅`User joined:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
@ -124,8 +132,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"`{prettyCurrentTime}`❗`User left:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
@ -136,35 +147,28 @@ namespace NadekoBot.Modules.Administration.Commands
{
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage($"❗`{prettyCurrentTime}`❌`User banned:` **{e.User.Name}** ({e.User.Id})").ConfigureAwait(false);
}
catch { }
}
public Func<CommandEventArgs, Task> DoFunc() => async e =>
{
Channel ch;
if (!logs.TryRemove(e.Server, out ch))
{
logs.TryAdd(e.Server, e.Channel);
await e.Channel.SendMessage($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false);
return;
}
await e.Channel.SendMessage($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false);
};
private async void MsgRecivd(object sender, MessageEventArgs e)
{
try
{
if (e.Server == null || e.Channel.IsPrivate || e.User.Id == NadekoBot.Client.CurrentUser.Id)
return;
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null || e.Channel.Id == chId)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (!string.IsNullOrWhiteSpace(e.Message.Text))
{
@ -188,8 +192,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
return;
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null || e.Channel.Id == chId)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
if (!string.IsNullOrWhiteSpace(e.Message.Text))
{
@ -212,8 +219,11 @@ namespace NadekoBot.Modules.Administration.Commands
{
if (e.Server == null || e.Channel.IsPrivate || e.User?.Id == NadekoBot.Client.CurrentUser.Id)
return;
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null || e.Channel.Id == chId)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch) || e.Channel == ch)
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
await ch.SendMessage(
$@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
@ -225,19 +235,28 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
}
private async void UsrUpdtd(object sender, UserUpdatedEventArgs e)
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
try
{
Channel ch;
if (loggingPresences.TryGetValue(e.Server, out ch))
if (e.Before.Status != e.After.Status)
var chId = config.LogPresenceChannel;
if (chId != null)
{
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) != null)
{
await ch.SendMessage($"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.").ConfigureAwait(false);
if (e.Before.Status != e.After.Status)
{
await ch.SendMessage($"`{prettyCurrentTime}`**{e.Before.Name}** is now **{e.After.Status}**.").ConfigureAwait(false);
}
}
}
}
catch { }
try
{
ulong notifyChBeforeId;
ulong notifyChAfterId;
Channel notifyChBefore = null;
Channel notifyChAfter = null;
var beforeVch = e.Before.VoiceChannel;
@ -246,11 +265,11 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
var notifyJoin = false;
if ((beforeVch != null || afterVch != null) && (beforeVch != afterVch)) // this means we need to notify for sure.
{
if (beforeVch != null && voiceChannelLog.TryGetValue(beforeVch, out notifyChBefore))
if (beforeVch != null && config.VoiceChannelLog.TryGetValue(beforeVch.Id, out notifyChBeforeId) && (notifyChBefore = e.Before.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChBeforeId)) != null)
{
notifyLeave = true;
}
if (afterVch != null && voiceChannelLog.TryGetValue(afterVch, out notifyChAfter))
if (afterVch != null && config.VoiceChannelLog.TryGetValue(afterVch.Id, out notifyChAfterId) && (notifyChAfter = e.After.Server.TextChannels.FirstOrDefault(tc => tc.Id == notifyChAfterId)) != null)
{
notifyJoin = true;
}
@ -272,8 +291,11 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
try
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
return;
Channel ch;
if (!logs.TryGetValue(e.Server, out ch))
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
string str = $"🕔`{prettyCurrentTime}`";
if (e.Before.Name != e.After.Name)
@ -331,21 +353,36 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
.Description("Toggles logging in this channel. Logs every message sent/deleted/edited on the server. **Bot Owner Only!**")
.AddCheck(SimpleCheckers.OwnerOnly())
.AddCheck(SimpleCheckers.ManageServer())
.Do(DoFunc());
.Do(async e =>
{
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel;
if (chId == null)
{
SpecificConfigurations.Default.Of(e.Server.Id).LogServerChannel = e.Channel.Id;
await e.Channel.SendMessage($"❗**I WILL BEGIN LOGGING SERVER ACTIVITY IN THIS CHANNEL**❗").ConfigureAwait(false);
return;
}
Channel ch;
if ((ch = e.Server.TextChannels.Where(tc => tc.Id == chId).FirstOrDefault()) == null)
return;
SpecificConfigurations.Default.Of (e.Server.Id).LogServerChannel = null;
await e.Channel.SendMessage($"❗**NO LONGER LOGGING IN {ch.Mention} CHANNEL**❗").ConfigureAwait(false);
});
cgb.CreateCommand(Module.Prefix + "userpresence")
.Description("Starts logging to this channel when someone from the server goes online/offline/idle.")
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
Channel ch;
if (!loggingPresences.TryRemove(e.Server, out ch))
var chId = SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel;
if (chId == null)
{
loggingPresences.TryAdd(e.Server, e.Channel);
SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = e.Channel.Id;
await e.Channel.SendMessage($"**User presence notifications enabled.**").ConfigureAwait(false);
return;
}
SpecificConfigurations.Default.Of(e.Server.Id).LogPresenceChannel = null;
await e.Channel.SendMessage($"**User presence notifications disabled.**").ConfigureAwait(false);
});
@ -356,11 +393,12 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (e.GetArg("all")?.ToLower() == "all")
{
foreach (var voiceChannel in e.Server.VoiceChannels)
{
voiceChannelLog.TryAdd(voiceChannel, e.Channel);
config.VoiceChannelLog.TryAdd(voiceChannel.Id, e.Channel.Id);
}
await e.Channel.SendMessage("Started logging user presence for **ALL** voice channels!").ConfigureAwait(false);
return;
@ -371,10 +409,10 @@ $@"🕔`{prettyCurrentTime}` **Message** 📝 `#{e.Channel.Name}`
await e.Channel.SendMessage("💢 You are not in a voice channel right now. If you are, please rejoin it.").ConfigureAwait(false);
return;
}
Channel throwaway;
if (!voiceChannelLog.TryRemove(e.User.VoiceChannel, out throwaway))
ulong throwaway;
if (!config.VoiceChannelLog.TryRemove(e.User.VoiceChannel.Id, out throwaway))
{
voiceChannelLog.TryAdd(e.User.VoiceChannel, e.Channel);
config.VoiceChannelLog.TryAdd(e.User.VoiceChannel.Id, e.Channel.Id);
await e.Channel.SendMessage($"`Logging user updates for` {e.User.VoiceChannel.Mention} `voice channel.`").ConfigureAwait(false);
}
else

View File

@ -51,11 +51,9 @@ namespace NadekoBot.Modules.Administration.Commands
{
if (PlayingPlaceholders.Count == 0
|| NadekoBot.Config.RotatingStatuses.Count == 0
|| i >= PlayingPlaceholders.Count
|| i >= NadekoBot.Config.RotatingStatuses.Count)
{
i = -1;
return;
i = 0;
}
status = NadekoBot.Config.RotatingStatuses[i];
status = PlayingPlaceholders.Aggregate(status,

View File

@ -1,62 +0,0 @@
using Discord.Commands;
using NadekoBot.Modules;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace NadekoBot.Classes.Conversations.Commands
{
internal class CopyCommand : DiscordCommand
{
private readonly HashSet<ulong> CopiedUsers = new HashSet<ulong>();
public CopyCommand(DiscordModule module) : base(module)
{
NadekoBot.Client.MessageReceived += Client_MessageReceived;
}
private async void Client_MessageReceived(object sender, Discord.MessageEventArgs e)
{
if (e.User.Id == NadekoBot.Client.CurrentUser.Id) return;
try
{
if (string.IsNullOrWhiteSpace(e.Message.Text))
return;
if (CopiedUsers.Contains(e.User.Id))
{
await e.Channel.SendMessage(e.Message.Text).ConfigureAwait(false);
}
}
catch { }
}
public Func<CommandEventArgs, Task> DoFunc() => async e =>
{
if (CopiedUsers.Contains(e.User.Id)) return;
CopiedUsers.Add(e.User.Id);
await e.Channel.SendMessage(" I'll start copying you now.").ConfigureAwait(false);
};
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand("copyme")
.Alias("cm")
.Description("Nadeko starts copying everything you say. Disable with cs")
.Do(DoFunc());
cgb.CreateCommand("cs")
.Alias("copystop")
.Description("Nadeko stops copying you")
.Do(StopCopy());
}
private Func<CommandEventArgs, Task> StopCopy() => async e =>
{
if (!CopiedUsers.Contains(e.User.Id)) return;
CopiedUsers.Remove(e.User.Id);
await e.Channel.SendMessage(" I wont copy anymore.").ConfigureAwait(false);
};
}
}

View File

@ -1,7 +1,6 @@
using Discord;
using Discord.Commands;
using Discord.Modules;
using NadekoBot.Classes.Conversations.Commands;
using NadekoBot.DataModels;
using NadekoBot.Extensions;
using NadekoBot.Modules.Conversations.Commands;
@ -19,7 +18,6 @@ namespace NadekoBot.Modules.Conversations
private const string firestr = "🔥 ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็ด้้้้้็็็็็้้้้้็็็็็้้้้้้้้็็็็็้้้้้็็็็็้้้้ 🔥";
public Conversations()
{
commands.Add(new CopyCommand(this));
commands.Add(new RipCommand(this));
}
@ -255,21 +253,6 @@ namespace NadekoBot.Modules.Conversations
await e.Channel.SendMessage(construct).ConfigureAwait(false);
});
cgb.CreateCommand("av")
.Alias("avatar")
.Parameter("mention", ParameterType.Required)
.Description("Shows a mentioned person's avatar.\n**Usage**: ~av @X")
.Do(async e =>
{
var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
if (usr == null)
{
await e.Channel.SendMessage("Invalid user specified.").ConfigureAwait(false);
return;
}
await e.Channel.SendMessage(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false);
});
});
}

View File

@ -79,7 +79,7 @@ namespace NadekoBot.Modules.Gambling
await e.Channel.SendFile(images.Count + " cards.jpg", bitmap.ToStream()).ConfigureAwait(false);
if (cardObjects.Count == 5)
{
await e.Channel.SendMessage(Cards.GetHandValue(cardObjects)).ConfigureAwait(false);
await e.Channel.SendMessage($"{e.User.Mention} `{Cards.GetHandValue(cardObjects)}`").ConfigureAwait(false);
}
}
catch (Exception ex)

View File

@ -1,10 +1,12 @@
using Discord;
using Discord.Commands;
using NadekoBot.Classes;
using NadekoBot.Modules.Permissions.Classes;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
namespace NadekoBot.Modules.Games.Commands
@ -18,11 +20,31 @@ namespace NadekoBot.Modules.Games.Commands
/// </summary>
class PlantPick : DiscordCommand
{
private Random rng;
public PlantPick(DiscordModule module) : base(module)
{
NadekoBot.Client.MessageReceived += PotentialFlowerGeneration;
rng = new Random();
}
private async void PotentialFlowerGeneration(object sender, Discord.MessageEventArgs e)
{
if (e.Server == null || e.Channel.IsPrivate)
return;
var config = Classes.SpecificConfigurations.Default.Of(e.Server.Id);
if (config.GenerateCurrencyChannels.Contains(e.Channel.Id))
{
var rnd = Math.Abs(GetRandomNumber());
if ((rnd % 50) == 0)
{
var msg = await e.Channel.SendFile(GetRandomCurrencyImagePath());
await e.Channel.SendMessage($"❗ A random {NadekoBot.Config.CurrencyName} appeared! Pick it up by typing `>pick`");
plantedFlowerChannels.AddOrUpdate(e.Channel.Id, msg, (u, m) => { m.Delete().GetAwaiter().GetResult(); return msg; });
}
}
}
//channelid/messageid pair
ConcurrentDictionary<ulong, Message> plantedFlowerChannels = new ConcurrentDictionary<ulong, Message>();
@ -65,8 +87,7 @@ namespace NadekoBot.Modules.Games.Commands
return;
}
var rng = new Random();
var file = Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
var file = GetRandomCurrencyImagePath();
Message msg;
//todo send message after, not in lock
if (file == null)
@ -80,6 +101,38 @@ namespace NadekoBot.Modules.Games.Commands
await Task.Delay(20000).ConfigureAwait(false);
await msg2.Delete().ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "gencurrency")
.Alias(Prefix + "gc")
.Description($"Toggles currency generation on this channel. Every posted message will have 2% chance to spawn a {NadekoBot.Config.CurrencyName}. Requires Manage Messages permission. | `>gc`")
.AddCheck(SimpleCheckers.ManageMessages())
.Do(async e =>
{
var config = SpecificConfigurations.Default.Of(e.Server.Id);
if (config.GenerateCurrencyChannels.Remove(e.Channel.Id))
{
await e.Channel.SendMessage("`Currency generation disabled on this channel.`");
}
else
{
config.GenerateCurrencyChannels.Add(e.Channel.Id);
await e.Channel.SendMessage("`Currency generation enabled on this channel.`");
}
});
}
private string GetRandomCurrencyImagePath() =>
Directory.GetFiles("data/currency_images").OrderBy(s => rng.Next()).FirstOrDefault();
int GetRandomNumber()
{
using (RNGCryptoServiceProvider rg = new RNGCryptoServiceProvider())
{
byte[] rno = new byte[4];
rg.GetBytes(rno);
int randomvalue = BitConverter.ToInt32(rno, 0);
return randomvalue;
}
}
}
}

View File

@ -86,7 +86,7 @@ Version: `{NadekoStats.Instance.BotVersion}`";
.Description("Sends a readme and a guide links to the channel.")
.Do(async e =>
await e.Channel.SendMessage(
@"**FULL README**: <https://github.com/Kwoth/NadekoBot/blob/master/README.md>
@"**Wiki with all info**: <https://github.com/Kwoth/NadekoBot/wiki>
**WINDOWS SETUP GUIDE**: <https://github.com/Kwoth/NadekoBot/blob/master/ComprehensiveGuide.md>

View File

@ -1,5 +1,6 @@
using Discord.Commands;
using Discord.Modules;
using NadekoBot.Classes;
using NadekoBot.Classes.Help.Commands;
using NadekoBot.Extensions;
using NadekoBot.Modules.Permissions.Classes;
@ -54,10 +55,8 @@ namespace NadekoBot.Modules.Help
}
var i = 0;
if (module != "customreactions" && module != "conversations")
await e.Channel.SendMessage("`List Of Commands:`\n```xl\n" +
string.Join("\n", cmdsArray.GroupBy(item => (i++) / 3)
.Select(ig => string.Join("", ig.Select(el => $"{el.Text,-15}" + $"{"[" + el.Aliases.FirstOrDefault() + "]",-8}"))))
+ $"\n```")
await e.Channel.SendMessage("`List Of Commands:`\n" + SearchHelper.ShowInPrettyCode<Command>(cmdsArray,
el => $"{el.Text,-15}{"[" + el.Aliases.FirstOrDefault() + "]",-8}"))
.ConfigureAwait(false);
else
await e.Channel.SendMessage("`List Of Commands:`\n• " + string.Join("\n• ", cmdsArray.Select(c => $"{c.Text}")));

View File

@ -50,7 +50,7 @@ namespace NadekoBot.Modules.Music.Classes
private bool Destroyed { get; set; } = false;
public bool RepeatSong { get; private set; } = false;
public bool RepeatPlaylist { get; private set; } = false;
public bool Autoplay { get; private set; } = false;
public bool Autoplay { get; set; } = false;
public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume)
{
@ -174,6 +174,7 @@ namespace NadekoBot.Modules.Music.Classes
throw new ArgumentNullException(nameof(s));
lock (playlistLock)
{
s.MusicPlayer = this;
playlist.Add(s);
}
}

View File

@ -54,7 +54,7 @@ namespace NadekoBot.Modules.Music.Classes
}
}
private Song(SongInfo songInfo)
public Song(SongInfo songInfo)
{
this.SongInfo = songInfo;
}
@ -67,6 +67,12 @@ namespace NadekoBot.Modules.Music.Classes
return s;
}
public Song SetMusicPlayer(MusicPlayer mp)
{
this.MusicPlayer = mp;
return this;
}
private Task BufferSong(CancellationToken cancelToken) =>
Task.Factory.StartNew(async () =>
{

View File

@ -1,4 +1,5 @@
using NadekoBot.Classes;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks;
@ -34,18 +35,22 @@ namespace NadekoBot.Modules.Music.Classes
public class SoundCloudVideo
{
public string Kind = "";
public long Id = 0;
public SoundCloudUser User = new SoundCloudUser();
public string Title = "";
public string Kind { get; set; } = "";
public long Id { get; set; } = 0;
public SoundCloudUser User { get; set; } = new SoundCloudUser();
public string Title { get; set; } = "";
[JsonIgnore]
public string FullName => User.Name + " - " + Title;
public bool Streamable = false;
public bool Streamable { get; set; } = false;
[JsonProperty("permalink_url")]
public string TrackLink { get; set; } = "";
[JsonIgnore]
public string StreamLink => $"https://api.soundcloud.com/tracks/{Id}/stream?client_id={NadekoBot.Creds.SoundCloudClientID}";
}
public class SoundCloudUser
{
[Newtonsoft.Json.JsonProperty("username")]
public string Name;
public string Name { get; set; }
}
/*
{"kind":"track",

View File

@ -6,6 +6,7 @@ using NadekoBot.DataModels;
using NadekoBot.Extensions;
using NadekoBot.Modules.Music.Classes;
using NadekoBot.Modules.Permissions.Classes;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@ -52,30 +53,27 @@ namespace NadekoBot.Modules.Music
cgb.CreateCommand("stop")
.Alias("s")
.Description("Stops the music and clears the playlist. Stays in the channel.\n**Usage**: `!m s`")
.Do(async e =>
.Do(e =>
{
await Task.Run(() =>
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer)) return;
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
musicPlayer.Stop();
}).ConfigureAwait(false);
musicPlayer.Autoplay = false;
musicPlayer.Stop();
}
});
cgb.CreateCommand("destroy")
.Alias("d")
.Description("Completely stops the music and unbinds the bot from the channel. " +
"(may cause weird behaviour)\n**Usage**: `!m d`")
.Do(async e =>
.Do(e =>
{
await Task.Run(() =>
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryRemove(e.Server, out musicPlayer)) return;
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
musicPlayer.Destroy();
}).ConfigureAwait(false);
MusicPlayer musicPlayer;
if (!MusicPlayers.TryRemove(e.Server, out musicPlayer)) return;
if (e.User.VoiceChannel == musicPlayer.PlaybackVoiceChannel)
musicPlayer.Destroy();
});
cgb.CreateCommand("pause")
@ -110,6 +108,21 @@ namespace NadekoBot.Modules.Music
}
});
//cgb.CreateCommand("soundcloudqueue")
// .Alias("sq")
// .Description("Queue a soundcloud song using keywords. Bot will join your voice channel." +
// "**You must be in a voice channel**.\n**Usage**: `!m sq Dream Of Venice`")
// .Parameter("query", ParameterType.Unparsed)
// .Do(async e =>
// {
// await QueueSong(e.Channel, e.User.VoiceChannel, e.GetArg("query")).ConfigureAwait(false);
// if (e.Server.CurrentUser.GetPermissions(e.Channel).ManageMessages)
// {
// await Task.Delay(10000).ConfigureAwait(false);
// await e.Message.Delete().ConfigureAwait(false);
// }
// });
cgb.CreateCommand("listqueue")
.Alias("lq")
.Description("Lists 15 currently queued songs per page. Default page is 1.\n**Usage**: `!m lq` or `!m lq 2`")
@ -188,7 +201,7 @@ namespace NadekoBot.Modules.Music
cgb.CreateCommand("defvol")
.Alias("dv")
.Description("Sets the default music volume when music playback is started (0-100)." +
" Does not persist through restarts.\n**Usage**: `!m dv 80`")
" Persists through restarts.\n**Usage**: `!m dv 80`")
.Parameter("val", ParameterType.Required)
.Do(async e =>
{
@ -302,6 +315,37 @@ namespace NadekoBot.Modules.Music
await msg.Edit("🎵 `Playlist queue complete.`").ConfigureAwait(false);
});
cgb.CreateCommand("soundcloudpl")
.Alias("scpl")
.Description("Queue a soundcloud playlist using a link. | `!m scpl https://soundcloud.com/saratology/sets/symphony`")
.Parameter("pl", ParameterType.Unparsed)
.Do(async e =>
{
var pl = e.GetArg("pl")?.Trim();
if (string.IsNullOrWhiteSpace(pl))
return;
var scvids = JObject.Parse(await SearchHelper.GetResponseStringAsync($"http://api.soundcloud.com/resolve?url={pl}&client_id={NadekoBot.Creds.SoundCloudClientID}"))["tracks"].ToObject<SoundCloudVideo[]>();
await QueueSong(e.Channel, e.User.VoiceChannel, scvids[0].TrackLink);
MusicPlayer mp;
if (!MusicPlayers.TryGetValue(e.Server, out mp))
return;
foreach (var svideo in scvids.Skip(1))
{
mp.AddSong(new Song(new Classes.SongInfo
{
Title = svideo.FullName,
Provider = "SoundCloud",
Uri = svideo.StreamLink,
ProviderType = MusicType.Normal,
Query = svideo.TrackLink,
}));
}
});
cgb.CreateCommand("localplaylst")
.Alias("lopl")
.Description("Queues all songs from a directory. **Bot Owner Only!**\n**Usage**: `!m lopl C:/music/classical`")
@ -757,8 +801,6 @@ namespace NadekoBot.Modules.Music
return mp;
});
var resolvedSong = await Song.ResolveSong(query, musicType).ConfigureAwait(false);
resolvedSong.MusicPlayer = musicPlayer;
musicPlayer.AddSong(resolvedSong);
if (!silent)
{

View File

@ -0,0 +1,46 @@
using Discord.Commands;
using NadekoBot.Classes;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace NadekoBot.Modules.Searches.Commands
{
class MemegenCommands : DiscordCommand
{
public MemegenCommands(DiscordModule module) : base(module)
{
}
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Prefix + "memelist")
.Description("Pulls a list of memes you can use with `~memegen` from http://memegen.link/templates/")
.Do(async e =>
{
int i = 0;
await e.Channel.SendMessage("`List Of Commands:`\n```xl\n" +
string.Join("\n", JsonConvert.DeserializeObject<Dictionary<string, string>>(await SearchHelper.GetResponseStringAsync("http://memegen.link/templates/"))
.Select(kvp => Path.GetFileName(kvp.Value))
.GroupBy(item => (i++) / 4)
.Select(ig => string.Join("", ig.Select(el => $"{el,-17}"))))
+ $"\n```").ConfigureAwait(false);
});
cgb.CreateCommand(Prefix + "memegen")
.Description("Generates a meme from memelist with top and bottom text. | `~memegen biw \"gets iced coffee\" \"in the winter\"`")
.Parameter("meme", ParameterType.Required)
.Parameter("toptext", ParameterType.Required)
.Parameter("bottext", ParameterType.Required)
.Do(async e =>
{
var meme = e.GetArg("meme");
var top = Uri.EscapeDataString(e.GetArg("toptext").Replace(' ', '-'));
var bot = Uri.EscapeDataString(e.GetArg("bottext").Replace(' ', '-'));
await e.Channel.SendMessage($"http://memegen.link/{meme}/{top}/{bot}.jpg");
});
}
}
}

View File

@ -17,7 +17,7 @@ namespace NadekoBot.Modules.Searches.Commands
internal override void Init(CommandGroupBuilder cgb)
{
cgb.CreateCommand(Module.Prefix + "osu")
.Description("Shows osu stats for a player.\n**Usage**: `~osu Name` or `~osu Name `")
.Description("Shows osu stats for a player.\n**Usage**: `~osu Name` or `~osu Name taiko`")
.Parameter("usr", ParameterType.Required)
.Parameter("mode", ParameterType.Unparsed)
.Do(async e =>

View File

@ -73,7 +73,7 @@ namespace NadekoBot.Modules.Searches.Commands
checkTimer.Start();
}
private async Task<Tuple<bool, string>> GetStreamStatus(StreamNotificationConfig stream)
private async Task<Tuple<bool, string>> GetStreamStatus(StreamNotificationConfig stream, bool checkCache = true)
{
bool isLive;
string response;
@ -83,7 +83,7 @@ namespace NadekoBot.Modules.Searches.Commands
{
case StreamNotificationConfig.StreamType.Hitbox:
var hitboxUrl = $"https://api.hitbox.tv/media/status/{stream.Username}";
if (cachedStatuses.TryGetValue(hitboxUrl, out result))
if (checkCache && cachedStatuses.TryGetValue(hitboxUrl, out result))
return result;
response = await SearchHelper.GetResponseStringAsync(hitboxUrl).ConfigureAwait(false);
data = JObject.Parse(response);
@ -93,7 +93,7 @@ namespace NadekoBot.Modules.Searches.Commands
return result;
case StreamNotificationConfig.StreamType.Twitch:
var twitchUrl = $"https://api.twitch.tv/kraken/streams/{Uri.EscapeUriString(stream.Username)}";
if (cachedStatuses.TryGetValue(twitchUrl, out result))
if (checkCache && cachedStatuses.TryGetValue(twitchUrl, out result))
return result;
response = await SearchHelper.GetResponseStringAsync(twitchUrl).ConfigureAwait(false);
data = JObject.Parse(response);
@ -103,7 +103,7 @@ namespace NadekoBot.Modules.Searches.Commands
return result;
case StreamNotificationConfig.StreamType.Beam:
var beamUrl = $"https://beam.pro/api/v1/channels/{stream.Username}";
if (cachedStatuses.TryGetValue(beamUrl, out result))
if (checkCache && cachedStatuses.TryGetValue(beamUrl, out result))
return result;
response = await SearchHelper.GetResponseStringAsync(beamUrl).ConfigureAwait(false);
data = JObject.Parse(response);
@ -143,6 +143,93 @@ namespace NadekoBot.Modules.Searches.Commands
.Parameter("username", ParameterType.Unparsed)
.Do(TrackStream(StreamNotificationConfig.StreamType.Beam));
cgb.CreateCommand(Module.Prefix + "checkhitbox")
.Alias(Module.Prefix + "chhb")
.Description("Checks if a certain user is streaming on the hitbox platform." +
"\n**Usage**: ~chhb SomeStreamer")
.Parameter("username", ParameterType.Unparsed)
.AddCheck(SimpleCheckers.ManageServer())
.Do(async e =>
{
var stream = e.GetArg("username")?.Trim();
if (string.IsNullOrWhiteSpace(stream))
return;
try
{
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
{
Username = stream,
Type = StreamNotificationConfig.StreamType.Hitbox
}));
if (streamStatus.Item1)
{
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
}
}
catch
{
await e.Channel.SendMessage("No channel found.");
}
});
cgb.CreateCommand(Module.Prefix + "checktwitch")
.Alias(Module.Prefix + "chtw")
.Description("Checks if a certain user is streaming on the twitch platform." +
"\n**Usage**: ~chtw SomeStreamer")
.AddCheck(SimpleCheckers.ManageServer())
.Parameter("username", ParameterType.Unparsed)
.Do(async e =>
{
var stream = e.GetArg("username")?.Trim();
if (string.IsNullOrWhiteSpace(stream))
return;
try
{
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
{
Username = stream,
Type = StreamNotificationConfig.StreamType.Twitch
}));
if (streamStatus.Item1)
{
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
}
}
catch
{
await e.Channel.SendMessage("No channel found.");
}
});
cgb.CreateCommand(Module.Prefix + "checkbeam")
.Alias(Module.Prefix + "chbm")
.Description("Checks if a certain user is streaming on the beam platform." +
"\n**Usage**: ~chbm SomeStreamer")
.AddCheck(SimpleCheckers.ManageServer())
.Parameter("username", ParameterType.Unparsed)
.Do(async e =>
{
var stream = e.GetArg("username")?.Trim();
if (string.IsNullOrWhiteSpace(stream))
return;
try
{
var streamStatus = (await GetStreamStatus(new StreamNotificationConfig
{
Username = stream,
Type = StreamNotificationConfig.StreamType.Beam
}));
if (streamStatus.Item1)
{
await e.Channel.SendMessage($"`Streamer {streamStatus.Item2} is online.`");
}
}
catch
{
await e.Channel.SendMessage("No channel found.");
}
});
cgb.CreateCommand(Module.Prefix + "removestream")
.Alias(Module.Prefix + "rms")
.Description("Removes notifications of a certain streamer on this channel." +

View File

@ -31,6 +31,7 @@ namespace NadekoBot.Modules.Searches
commands.Add(new CalcCommand(this));
commands.Add(new OsuCommands(this));
commands.Add(new PokemonSearchCommands(this));
commands.Add(new MemegenCommands(this));
rng = new Random();
}
@ -184,29 +185,30 @@ $@"🌍 **Weather for** 【{obj["target"]}】
cgb.CreateCommand(Prefix + "ir")
.Description("Pulls a random image using a search parameter.\n**Usage**: ~ir cute kitten")
.Parameter("query", ParameterType.Unparsed)
.Do(async e =>
{
if (string.IsNullOrWhiteSpace(e.GetArg("query")))
return;
try
{
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=50&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}";
var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false));
var items = obj["items"] as JArray;
await e.Channel.SendMessage(items[rng.Next(0, items.Count)]["link"].ToString()).ConfigureAwait(false);
}
catch (HttpRequestException exception)
{
if (exception.Message.Contains("403 (Forbidden)"))
{
await e.Channel.SendMessage("Daily limit reached!");
}
else
{
await e.Channel.SendMessage("Something went wrong.");
}
}
});
.Do(async e =>
{
if (string.IsNullOrWhiteSpace(e.GetArg("query")))
return;
try
{
var reqString = $"https://www.googleapis.com/customsearch/v1?q={Uri.EscapeDataString(e.GetArg("query"))}&cx=018084019232060951019%3Ahs5piey28-e&num=1&searchType=image&start={ rng.Next(1, 50) }&fields=items%2Flink&key={NadekoBot.Creds.GoogleAPIKey}";
var obj = JObject.Parse(await SearchHelper.GetResponseStringAsync(reqString).ConfigureAwait(false));
var items = obj["items"] as JArray;
await e.Channel.SendMessage(items[0]["link"].ToString()).ConfigureAwait(false);
}
catch (HttpRequestException exception)
{
if (exception.Message.Contains("403 (Forbidden)"))
{
await e.Channel.SendMessage("Daily limit reached!");
}
else
{
await e.Channel.SendMessage("Something went wrong.");
}
}
});
cgb.CreateCommand(Prefix + "lmgtfy")
.Description("Google something for an idiot.")
.Parameter("ffs", ParameterType.Unparsed)
@ -475,6 +477,21 @@ $@"🌍 **Weather for** 【{obj["target"]}】
}
});
cgb.CreateCommand(Prefix + "av")
.Alias(Prefix + "avatar")
.Parameter("mention", ParameterType.Required)
.Description("Shows a mentioned person's avatar.\n**Usage**: ~av @X")
.Do(async e =>
{
var usr = e.Channel.FindUsers(e.GetArg("mention")).FirstOrDefault();
if (usr == null)
{
await e.Channel.SendMessage("Invalid user specified.").ConfigureAwait(false);
return;
}
await e.Channel.SendMessage(await usr.AvatarUrl.ShortenUrl()).ConfigureAwait(false);
});
});
}
}

View File

@ -2,10 +2,12 @@
// License: Code Project Open License
// http://www.codeproject.com/info/cpol10.aspx
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace NadekoBot.Modules.Translator.Helpers
@ -26,32 +28,6 @@ namespace NadekoBot.Modules.Translator.Helpers
return GoogleTranslator._languageModeMap.Keys.OrderBy(p => p);
}
}
/// <summary>
/// Gets the time taken to perform the translation.
/// </summary>
public TimeSpan TranslationTime {
get;
private set;
}
/// <summary>
/// Gets the url used to speak the translation.
/// </summary>
/// <value>The url used to speak the translation.</value>
public string TranslationSpeechUrl {
get;
private set;
}
/// <summary>
/// Gets the error.
/// </summary>
public Exception Error {
get;
private set;
}
#endregion
#region Public methods
@ -63,92 +39,28 @@ namespace NadekoBot.Modules.Translator.Helpers
/// <param name="sourceLanguage">The source language.</param>
/// <param name="targetLanguage">The target language.</param>
/// <returns>The translation.</returns>
public string Translate
public async Task<string> Translate
(string sourceText,
string sourceLanguage,
string targetLanguage)
{
// Initialize
this.Error = null;
this.TranslationSpeechUrl = null;
this.TranslationTime = TimeSpan.Zero;
DateTime tmStart = DateTime.Now;
string translation = string.Empty;
string text = string.Empty;
try
// Download translation
string url = string.Format("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage),
GoogleTranslator.LanguageEnumToIdentifier(targetLanguage),
HttpUtility.UrlEncode(sourceText));
using (HttpClient http = new HttpClient())
{
// Download translation
string url = string.Format("https://translate.googleapis.com/translate_a/single?client=gtx&sl={0}&tl={1}&dt=t&q={2}",
GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage),
GoogleTranslator.LanguageEnumToIdentifier(targetLanguage),
HttpUtility.UrlEncode(sourceText));
using (WebClient wc = new WebClient())
{
wc.Headers.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
text = wc.DownloadString(url);
}
// Get translated text
// Get phrase collection
// string text = File.ReadAllText(outputFile);
int index = text.IndexOf(string.Format(",,\"{0}\"", GoogleTranslator.LanguageEnumToIdentifier(sourceLanguage)));
if (index == -1)
{
// Translation of single word
int startQuote = text.IndexOf('\"');
if (startQuote != -1)
{
int endQuote = text.IndexOf('\"', startQuote + 1);
if (endQuote != -1)
{
translation = text.Substring(startQuote + 1, endQuote - startQuote - 1);
}
}
else
{
// Translation of phrase
text = text.Substring(0, index);
text = text.Replace("],[", ",");
text = text.Replace("]", string.Empty);
text = text.Replace("[", string.Empty);
text = text.Replace("\",\"", "\"");
// Get translated phrases
string[] phrases = text.Split(new[] { '\"' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; (i < phrases.Count()); i += 2)
{
string translatedPhrase = phrases[i];
if (translatedPhrase.StartsWith(",,"))
{
i--;
continue;
}
translation += translatedPhrase + " ";
}
}
// Fix up translation
translation = translation.Trim();
translation = translation.Replace(" ?", "?");
translation = translation.Replace(" !", "!");
translation = translation.Replace(" ,", ",");
translation = translation.Replace(" .", ".");
translation = translation.Replace(" ;", ";");
// And translation speech URL
this.TranslationSpeechUrl = string.Format("https://translate.googleapis.com/translate_tts?ie=UTF-8&q={0}&tl={1}&total=1&idx=0&textlen={2}&client=gtx",
HttpUtility.UrlEncode(translation), GoogleTranslator.LanguageEnumToIdentifier(targetLanguage), translation.Length);
}
}
catch (Exception ex)
{
this.Error = ex;
http.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36");
text = await http.GetStringAsync(url).ConfigureAwait(false);
}
// Return result
this.TranslationTime = DateTime.Now - tmStart;
return translation;
return JArray.Parse(text)[0][0][0].ToString();
}
#endregion

View File

@ -27,13 +27,17 @@ namespace NadekoBot.Modules.Translator
await e.Channel.SendIsTyping().ConfigureAwait(false);
string from = e.GetArg("langs").ToLowerInvariant().Split('>')[0];
string to = e.GetArg("langs").ToLowerInvariant().Split('>')[1];
var text = e.GetArg("text")?.Trim();
if (string.IsNullOrWhiteSpace(text))
return;
string translation = t.Translate(e.GetArg("text"), from, to);
string translation = await t.Translate(text, from, to).ConfigureAwait(false);
await e.Channel.SendMessage(translation).ConfigureAwait(false);
}
catch
catch (Exception ex)
{
await e.Channel.SendMessage("Bad input format, or sth went wrong...").ConfigureAwait(false);
Console.WriteLine(ex);
await e.Channel.SendMessage("Bad input format, or something went wrong...").ConfigureAwait(false);
}
};