diff --git a/src/NadekoBot/Modules/Games/Commands/CleverBotCommands.cs b/src/NadekoBot/Modules/Games/Commands/CleverBotCommands.cs index a192a528..5858fb63 100644 --- a/src/NadekoBot/Modules/Games/Commands/CleverBotCommands.cs +++ b/src/NadekoBot/Modules/Games/Commands/CleverBotCommands.cs @@ -5,6 +5,7 @@ using NadekoBot.Services; using NadekoBot.Services.Database; using Newtonsoft.Json; using NLog; +using Services.CleverBotApi; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -21,26 +22,27 @@ namespace NadekoBot.Modules.Games [Group] public class CleverBotCommands { - private Logger _log { get; } + private static Logger _log { get; } class CleverAnswer { public string Status { get; set; } public string Response { get; set; } } - public CleverBotCommands() - { - _log = LogManager.GetCurrentClassLogger(); - } - //user#discrim is the key public static ConcurrentHashSet ChannelsInConversation { get; } = new ConcurrentHashSet(); - public static ConcurrentHashSet CleverbotGuilds { get; } = new ConcurrentHashSet(); + public static ConcurrentDictionary CleverbotGuilds { get; } = new ConcurrentDictionary(); static CleverBotCommands() { + _log = LogManager.GetCurrentClassLogger(); + using (var uow = DbHandler.UnitOfWork()) { - CleverbotGuilds = new ConcurrentHashSet(uow.GuildConfigs.GetAll().Where(gc => gc.CleverbotEnabled).Select(gc => gc.GuildId)); + var bot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT); + CleverbotGuilds = new ConcurrentDictionary( + uow.GuildConfigs.GetAll() + .Where(gc => gc.CleverbotEnabled) + .ToDictionary(gc => gc.GuildId, gc => bot.CreateSession())); } } @@ -50,9 +52,8 @@ namespace NadekoBot.Modules.Games if (channel == null) return false; - var nick = msg.Channel.Id + "NadekoBot"; - - if (!ChannelsInConversation.Contains(nick) && !CleverbotGuilds.Contains(channel.Guild.Id)) + ChatterBotSession cleverbot; + if (!CleverbotGuilds.TryGetValue(channel.Guild.Id, out cleverbot)) return false; var nadekoId = NadekoBot.Client.GetCurrentUser().Id; @@ -61,11 +62,11 @@ namespace NadekoBot.Modules.Games string message; if (msg.Content.StartsWith(normalMention)) { - message = msg.Content.Substring(normalMention.Length); + message = msg.Content.Substring(normalMention.Length).Trim(); } else if (msg.Content.StartsWith(nickMention)) { - message = msg.Content.Substring(nickMention.Length); + message = msg.Content.Substring(nickMention.Length).Trim(); } else { @@ -74,98 +75,51 @@ namespace NadekoBot.Modules.Games await msg.Channel.TriggerTypingAsync().ConfigureAwait(false); - using (var http = new HttpClient()) + var response = await cleverbot.Think(message).ConfigureAwait(false); + try { - var content = new FormUrlEncodedContent(new Dictionary - { - { "user", NadekoBot.Credentials.CleverbotApiUser}, - { "key", NadekoBot.Credentials.CleverbotApiKey}, - { "nick", nick}, - { "text", message}, - }); - var res = await http.PostAsync("https://cleverbot.io/1.0/ask", content).ConfigureAwait(false); - - if (res.StatusCode == System.Net.HttpStatusCode.OK) - { - try - { - var answer = JsonConvert.DeserializeObject(await res.Content.ReadAsStringAsync().ConfigureAwait(false)); - try - { - await msg.Channel.SendMessageAsync(WebUtility.HtmlDecode(answer.Response)).ConfigureAwait(false); - } - catch - { - await msg.Channel.SendMessageAsync(answer.Response).ConfigureAwait(false); // try twice :\ - } - } - catch { } - return true; - } - return false; + await msg.Channel.SendMessageAsync(response).ConfigureAwait(false); } + catch (Exception ex) + { + _log.Warn(ex, "Eror sending response"); + await msg.Channel.SendMessageAsync(response).ConfigureAwait(false); // try twice :\ + } + return true; } [NadekoCommand, Usage, Description, Aliases] [RequireContext(ContextType.Guild)] [RequirePermission(ChannelPermission.ManageMessages)] - public async Task Cleverbot(IUserMessage imsg, string all = null) + public async Task Cleverbot(IUserMessage imsg) { var channel = (ITextChannel)imsg.Channel; - - if (string.IsNullOrWhiteSpace(NadekoBot.Credentials.CleverbotApiKey) || - string.IsNullOrWhiteSpace(NadekoBot.Credentials.CleverbotApiKey)) - { - await channel.SendMessageAsync(":anger: `Bot owner didn't setup Cleverbot Api keys. Session will not start.`").ConfigureAwait(false); - return; - } - if (all?.Trim().ToLowerInvariant() == "all") + ChatterBotSession throwaway; + if (CleverbotGuilds.TryRemove(channel.Guild.Id, out throwaway)) { - var cleverbotEnabled = CleverbotGuilds.Add(channel.Guild.Id); - if (!cleverbotEnabled) - CleverbotGuilds.TryRemove(channel.Guild.Id); - using (var uow = DbHandler.UnitOfWork()) { - uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, cleverbotEnabled); + uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, false); await uow.CompleteAsync().ConfigureAwait(false); } - - await channel.SendMessageAsync($"{imsg.Author.Mention} `{(cleverbotEnabled ? "Enabled" : "Disabled")} cleverbot for all users.`").ConfigureAwait(false); + await channel.SendMessageAsync($"{imsg.Author.Mention} `Disabled cleverbot on this server.`").ConfigureAwait(false); return; } + var cleverbot = ChatterBotFactory.Create(ChatterBotType.CLEVERBOT); + var session = cleverbot.CreateSession(); - var nick = channel.Id + "NadekoBot"; + CleverbotGuilds.TryAdd(channel.Guild.Id, session); - if (ChannelsInConversation.TryRemove(nick)) + using (var uow = DbHandler.UnitOfWork()) { - await channel.SendMessageAsync($"{imsg.Author.Mention} `I will no longer reply to your messages starting with my mention.`").ConfigureAwait(false); - return; + uow.GuildConfigs.SetCleverbotEnabled(channel.Guild.Id, true); + await uow.CompleteAsync().ConfigureAwait(false); } - using (var http = new HttpClient()) - { - var content = new FormUrlEncodedContent(new Dictionary() - { - { "user", NadekoBot.Credentials.CleverbotApiUser}, - { "key", NadekoBot.Credentials.CleverbotApiKey}, - { "nick", nick}, - }); - var res = await http.PostAsync("https://cleverbot.io/1.0/create", content).ConfigureAwait(false); - if (res.StatusCode != System.Net.HttpStatusCode.OK) - { - await channel.SendMessageAsync($"{imsg.Author.Mention} `Something went wrong in starting your cleverbot session :\\`"); - _log.Warn(await res.Content.ReadAsStringAsync()); - return; - } - - ChannelsInConversation.Add(nick); - } - await channel.SendMessageAsync($"{imsg.Author.Mention} `I will reply to your messages starting with my mention.`").ConfigureAwait(false); + await channel.SendMessageAsync($"{imsg.Author.Mention} `Enabled cleverbot on this server.`").ConfigureAwait(false); } - } } } diff --git a/src/NadekoBot/Resources/CommandStrings.resx b/src/NadekoBot/Resources/CommandStrings.resx index 2c5db911..c14896e3 100644 --- a/src/NadekoBot/Resources/CommandStrings.resx +++ b/src/NadekoBot/Resources/CommandStrings.resx @@ -166,7 +166,7 @@ greetdel grdel - Toggles automatic deletion of greet messages. + Toggles automatic deletion of greet messages. `{0}greetdel` @@ -175,7 +175,7 @@ greet - Toggles anouncements on the current channel when someone joins the server. + Toggles anouncements on the current channel when someone joins the server. `{0}greet` @@ -184,7 +184,7 @@ greetmsg - Sets a new join announcement message which will be shown in the server's channel. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. + Sets a new join announcement message which will be shown in the server's channel. Type %user% if you want to mention the new member. Using it with no message will show the current greet message. `{0}greetmsg Welcome, %user%.` @@ -202,7 +202,7 @@ byemsg - Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. + Sets a new leave announcement message. Type %user% if you want to mention the new member. Using it with no message will show the current bye message. `{0}byemsg %user% has left.` @@ -211,7 +211,7 @@ byedel - Toggles automatic deletion of bye messages. + Toggles automatic deletion of bye messages. `{0}byedel` @@ -220,7 +220,7 @@ greetdm - Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). + Toggles whether the greet messages will be sent in a DM (This is separate from greet - you can have both, any or neither enabled). `{0}greetdm` @@ -247,7 +247,7 @@ userpresence - Starts logging to this channel when someone from the server goes online/offline/idle. + Starts logging to this channel when someone from the server goes online/offline/idle. `{0}userpresence` @@ -256,7 +256,7 @@ voicepresence - Toggles logging to this channel whenever someone joins or leaves a voice channel you are currently in. + Toggles logging to this channel whenever someone joins or leaves a voice channel you are currently in. `{0}voicepresence` @@ -265,7 +265,7 @@ repeatinvoke repinv - Immediately shows the repeat message and restarts the timer. + Immediately shows the repeat message and restarts the timer. `{0}repinv` @@ -310,7 +310,7 @@ removeplaying rmpl repl - Removes a playing string on a given number. + Removes a playing string on a given number. `{0}rmpl` @@ -337,7 +337,7 @@ voice+text v+t - Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. + Creates a text channel for each voice channel only users in that voice channel can see.If you are server owner, keep in mind you will see them all the time regardless. `{0}voice+text` @@ -355,7 +355,7 @@ jcsc - Joins current channel to an instance of cross server channel using the token. + Joins current channel to an instance of cross server channel using the token. `{0}jcsc TokenHere` @@ -364,7 +364,7 @@ lcsc - Leaves Cross server channel instance from this channel. + Leaves Cross server channel instance from this channel. `{0}lcsc` @@ -463,7 +463,7 @@ autoassignrole aar - Automaticaly assigns a specified role to every user who joins the server. + Automaticaly assigns a specified role to every user who joins the server. `{0}aar` to disable, `{0}aar Role Name` to enable @@ -472,7 +472,7 @@ leave - Makes Nadeko leave the server. Either name or id required. + Makes Nadeko leave the server. Either name or id required. `{0}leave 123123123331` @@ -499,7 +499,7 @@ setrole sr - Sets a role for a given user. + Sets a role for a given user. `{0}sr @User Guest` @@ -508,7 +508,7 @@ removerole rr - Removes a role from a given user. + Removes a role from a given user. `{0}rr @User Admin` @@ -526,7 +526,7 @@ removeallroles rar - Removes all roles from a mentioned user. + Removes all roles from a mentioned user. `{0}rar @User` @@ -535,7 +535,7 @@ createrole cr - Creates a role with a given name. + Creates a role with a given name. `{0}cr Awesome Role` @@ -544,7 +544,7 @@ rolecolor rc - Set a role's color to the hex or 0-255 rgb color value provided. + Set a role's color to the hex or 0-255 rgb color value provided. `{0}rc Admin 255 200 100` or `{0}rc Admin ffba55` @@ -562,7 +562,7 @@ softban sb - Bans and then unbans a user by ID or name with an optional message. + Bans and then unbans a user by ID or name with an optional message. `{0}sb "@some Guy" Your behaviour is toxic.` @@ -571,7 +571,7 @@ kick k - Kicks a mentioned user. + Kicks a mentioned user. `{0}k "@some Guy" Your behaviour is toxic.` @@ -589,7 +589,7 @@ voiceunmute - Gives a previously voice-muted user a permission to speak. + Gives a previously voice-muted user a permission to speak. `{0}voiceunmute @Someguy` @@ -598,7 +598,7 @@ deafen deaf - Deafens mentioned user or users. + Deafens mentioned user or users. `{0}deaf "@Someguy"` or `{0}deaf "@Someguy" "@Someguy"` @@ -607,7 +607,7 @@ undeafen undef - Undeafens mentioned user or users. + Undeafens mentioned user or users. `{0}undef "@Someguy"` or `{0}undef "@Someguy" "@Someguy"` @@ -616,7 +616,7 @@ delvoichanl dvch - Deletes a voice channel with a given name. + Deletes a voice channel with a given name. `{0}dvch VoiceChannelName` @@ -625,7 +625,7 @@ creatvoichanl cvch - Creates a new voice channel with a given name. + Creates a new voice channel with a given name. `{0}cvch VoiceChannelName` @@ -634,7 +634,7 @@ deltxtchanl dtch - Deletes a text channel with a given name. + Deletes a text channel with a given name. `{0}dtch TextChannelName` @@ -643,7 +643,7 @@ creatxtchanl ctch - Creates a new text channel with a given name. + Creates a new text channel with a given name. `{0}ctch TextChannelName` @@ -652,7 +652,7 @@ settopic st - Sets a topic on the current channel. + Sets a topic on the current channel. `{0}st My new topic` @@ -661,7 +661,7 @@ setchanlname schn - Changes the name of the current channel. + Changes the name of the current channel. `{0}schn NewName` @@ -670,7 +670,7 @@ prune clr - `{0}prune` removes all nadeko's messages in the last 100 messages.`{0}prune X` removes last X messages from the channel (up to 100)`{0}prune @Someone` removes all Someone's messages in the last 100 messages.`{0}prune @Someone X` removes last X 'Someone's' messages in the channel. + `{0}prune` removes all nadeko's messages in the last 100 messages.`{0}prune X` removes last X messages from the channel (up to 100)`{0}prune @Someone` removes all Someone's messages in the last 100 messages.`{0}prune @Someone X` removes last X 'Someone's' messages in the channel. `{0}prune` or `{0}prune 5` or `{0}prune @Someone` or `{0}prune @Someone X` @@ -688,7 +688,7 @@ setname newnm - Gives the bot a new name. + Gives the bot a new name. `{0}newnm BotName` @@ -697,7 +697,7 @@ setavatar setav - Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. + Sets a new avatar image for the NadekoBot. Argument is a direct link to an image. `{0}setav http://i.imgur.com/xTG3a1I.jpg` @@ -706,7 +706,7 @@ setgame - Sets the bots game. + Sets the bots game. `{0}setgame with snakes` @@ -733,7 +733,7 @@ unstuck - Clears the message queue. + Clears the message queue. `{0}unstuck` @@ -787,7 +787,7 @@ remindtemplate - Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. + Sets message for when the remind is triggered. Available placeholders are %user% - user who ran the command, %message% - Message specified in the remind, %target% - target channel of the remind. `{0}remindtemplate %user%, you gotta do %message%!` @@ -1255,7 +1255,7 @@ take - Takes a certain amount of currency from someone. + Takes a certain amount of currency from someone. `{0}take 1 "@someguy"` @@ -1615,7 +1615,7 @@ cleanup - Cleans up hanging voice connections. + Cleans up hanging voice connections. `{0}cleanup` @@ -2311,7 +2311,7 @@ `{0}greetdmmsg Welcome to the server, %user%`. - Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. + Sets a new join announcement message which will be sent to the user who joined. Type %user% if you want to mention the new member. Using it with no message will show the current DM greet message. Check how much currency a person has. (Defaults to yourself) @@ -2623,7 +2623,7 @@ cleverbot - Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the channel this command is ran in. You can specify "all" parameter to enable it in the whole server. Custom reactions starting with %mention% won't work if cleverbot is enabled.' + Toggles cleverbot session. When enabled, the bot will reply to messages starting with bot mention in the server. Custom reactions starting with %mention% won't work if cleverbot is enabled. `{0}cleverbot` diff --git a/src/NadekoBot/Services/CleverBotApi/ChatterBot.cs b/src/NadekoBot/Services/CleverBotApi/ChatterBot.cs new file mode 100644 index 00000000..746b44aa --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/ChatterBot.cs @@ -0,0 +1,25 @@ + /* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + public interface ChatterBot + { + ChatterBotSession CreateSession(); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/ChatterBotFactory.cs b/src/NadekoBot/Services/CleverBotApi/ChatterBotFactory.cs new file mode 100644 index 00000000..642b2a23 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/ChatterBotFactory.cs @@ -0,0 +1,45 @@ +using System; + +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + public class ChatterBotFactory + { + public static ChatterBot Create(ChatterBotType type) + { + return Create(type, null); + } + + public static ChatterBot Create(ChatterBotType type, object arg) + { + switch (type) + { + case ChatterBotType.CLEVERBOT: + return new Cleverbot("http://www.cleverbot.com/", "http://www.cleverbot.com/webservicemin?uc=165", 26); + case ChatterBotType.JABBERWACKY: + return new Cleverbot("http://jabberwacky.com", "http://jabberwacky.com/webservicemin", 20); + case ChatterBotType.PANDORABOTS: + if (arg == null) throw new ArgumentException("PANDORABOTS needs a botid arg", nameof(arg)); + return new Pandorabots(arg.ToString()); + } + return null; + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/ChatterBotSession.cs b/src/NadekoBot/Services/CleverBotApi/ChatterBotSession.cs new file mode 100644 index 00000000..0f063571 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/ChatterBotSession.cs @@ -0,0 +1,28 @@ +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +using System.Threading.Tasks; + +namespace Services.CleverBotApi +{ + public interface ChatterBotSession + { + Task Think(ChatterBotThought thought); + Task Think(string text); + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/ChatterBotThought.cs b/src/NadekoBot/Services/CleverBotApi/ChatterBotThought.cs new file mode 100644 index 00000000..1a385642 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/ChatterBotThought.cs @@ -0,0 +1,26 @@ +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + public class ChatterBotThought + { + public string[] Emotions { get; set; } + public string Text { get; set; } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/ChatterBotType.cs b/src/NadekoBot/Services/CleverBotApi/ChatterBotType.cs new file mode 100644 index 00000000..e4e8fab8 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/ChatterBotType.cs @@ -0,0 +1,27 @@ +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + public enum ChatterBotType + { + CLEVERBOT, + JABBERWACKY, + PANDORABOTS + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/Cleverbot.cs b/src/NadekoBot/Services/CleverBotApi/Cleverbot.cs new file mode 100644 index 00000000..328c0500 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/Cleverbot.cs @@ -0,0 +1,116 @@ +using System.Collections.Generic; +using System.Net; +using System.Threading.Tasks; + +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + internal class Cleverbot : ChatterBot + { + private readonly int endIndex; + private readonly string baseUrl; + private readonly string url; + + public Cleverbot(string baseUrl, string url, int endIndex) + { + this.baseUrl = baseUrl; + this.url = url; + this.endIndex = endIndex; + } + + public ChatterBotSession CreateSession() + { + return new CleverbotSession(baseUrl, url, endIndex); + } + } + + internal class CleverbotSession : ChatterBotSession + { + private readonly int endIndex; + private readonly string url; + private readonly IDictionary vars; + private readonly CookieCollection cookies; + + public CleverbotSession(string baseUrl, string url, int endIndex) + { + this.url = url; + this.endIndex = endIndex; + vars = new Dictionary(); + //vars["start"] = "y"; + vars["stimulus"] = ""; + vars["islearning"] = "1"; + vars["icognoid"] = "wsf"; + //vars["fno"] = "0"; + //vars["sub"] = "Say"; + //vars["cleanslate"] = "false"; + cookies = Utils.GetCookies(baseUrl); + } + + public async Task Think(ChatterBotThought thought) + { + vars["stimulus"] = thought.Text; + + var formData = Utils.ParametersToWWWFormURLEncoded(vars); + var formDataToDigest = formData.Substring(9, endIndex); + var formDataDigest = Utils.MD5(formDataToDigest); + vars["icognocheck"] = formDataDigest; + + var response = await Utils.Post(url, vars, cookies).ConfigureAwait(false); + + var responseValues = response.Split('\r'); + + //vars[""] = Utils.StringAtIndex(responseValues, 0); ?? + vars["sessionid"] = Utils.StringAtIndex(responseValues, 1); + vars["logurl"] = Utils.StringAtIndex(responseValues, 2); + vars["vText8"] = Utils.StringAtIndex(responseValues, 3); + vars["vText7"] = Utils.StringAtIndex(responseValues, 4); + vars["vText6"] = Utils.StringAtIndex(responseValues, 5); + vars["vText5"] = Utils.StringAtIndex(responseValues, 6); + vars["vText4"] = Utils.StringAtIndex(responseValues, 7); + vars["vText3"] = Utils.StringAtIndex(responseValues, 8); + vars["vText2"] = Utils.StringAtIndex(responseValues, 9); + vars["prevref"] = Utils.StringAtIndex(responseValues, 10); + //vars[""] = Utils.StringAtIndex(responseValues, 11); ?? +// vars["emotionalhistory"] = Utils.StringAtIndex(responseValues, 12); +// vars["ttsLocMP3"] = Utils.StringAtIndex(responseValues, 13); +// vars["ttsLocTXT"] = Utils.StringAtIndex(responseValues, 14); +// vars["ttsLocTXT3"] = Utils.StringAtIndex(responseValues, 15); +// vars["ttsText"] = Utils.StringAtIndex(responseValues, 16); +// vars["lineRef"] = Utils.StringAtIndex(responseValues, 17); +// vars["lineURL"] = Utils.StringAtIndex(responseValues, 18); +// vars["linePOST"] = Utils.StringAtIndex(responseValues, 19); +// vars["lineChoices"] = Utils.StringAtIndex(responseValues, 20); +// vars["lineChoicesAbbrev"] = Utils.StringAtIndex(responseValues, 21); +// vars["typingData"] = Utils.StringAtIndex(responseValues, 22); +// vars["divert"] = Utils.StringAtIndex(responseValues, 23); + + var responseThought = new ChatterBotThought(); + + responseThought.Text = Utils.StringAtIndex(responseValues, 0); + + return responseThought; + } + + public async Task Think(string text) + { + return (await Think(new ChatterBotThought {Text = text}).ConfigureAwait(false)).Text; + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/Pandorabots.cs b/src/NadekoBot/Services/CleverBotApi/Pandorabots.cs new file mode 100644 index 00000000..384b2e63 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/Pandorabots.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + internal class Pandorabots : ChatterBot + { + private readonly string botid; + + public Pandorabots(string botid) + { + this.botid = botid; + } + + public ChatterBotSession CreateSession() + { + return new PandorabotsSession(botid); + } + } + + internal class PandorabotsSession : ChatterBotSession + { + private readonly IDictionary vars; + + public PandorabotsSession(string botid) + { + vars = new Dictionary(); + vars["botid"] = botid; + vars["custid"] = Guid.NewGuid().ToString(); + } + + public async Task Think(ChatterBotThought thought) + { + vars["input"] = thought.Text; + + var response = await Utils.Post("http://www.pandorabots.com/pandora/talk-xml", vars, null).ConfigureAwait(false); + + var responseThought = new ChatterBotThought(); + responseThought.Text = Utils.XPathSearch(response, "//result/that/text()"); + + return responseThought; + } + + public async Task Think(string text) + { + return (await Think(new ChatterBotThought {Text = text}).ConfigureAwait(false)).Text; + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/CleverBotApi/Utils.cs b/src/NadekoBot/Services/CleverBotApi/Utils.cs new file mode 100644 index 00000000..3f4596a7 --- /dev/null +++ b/src/NadekoBot/Services/CleverBotApi/Utils.cs @@ -0,0 +1,148 @@ +using NadekoBot.Extensions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using System.Xml.XPath; + +/* + ChatterBotAPI + Copyright (C) 2011 pierredavidbelanger@gmail.com + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +namespace Services.CleverBotApi +{ + internal static class Utils + { + public static string ParametersToWWWFormURLEncoded(IDictionary parameters) + { + string wwwFormUrlEncoded = null; + foreach (var parameterKey in parameters.Keys) + { + var parameterValue = parameters[parameterKey]; + var parameter = string.Format("{0}={1}", System.Uri.EscapeDataString(parameterKey), System.Uri.EscapeDataString(parameterValue)); + if (wwwFormUrlEncoded == null) + { + wwwFormUrlEncoded = parameter; + } + else + { + wwwFormUrlEncoded = string.Format("{0}&{1}", wwwFormUrlEncoded, parameter); + } + } + return wwwFormUrlEncoded; + } + + public static string MD5(string input) + { + // step 1, calculate MD5 hash from input + var md5 = System.Security.Cryptography.MD5.Create(); + var inputBytes = Encoding.ASCII.GetBytes(input); + var hash = md5.ComputeHash(inputBytes); + + // step 2, convert byte array to hex string + var sb = new StringBuilder(); + for (var i = 0; i < hash.Length; i++) + { + sb.Append(hash[i].ToString("X2")); + } + return sb.ToString(); + + } + + public static CookieCollection GetCookies(string url) + { + CookieContainer container = new CookieContainer(); + + HttpResponseMessage res; + using (var handler = new HttpClientHandler() { CookieContainer = container }) + using (var http = new HttpClient(handler)) + { + http.AddFakeHeaders(); + http.DefaultRequestHeaders.Add("ContentType", "text/html"); + res = http.GetAsync(url).GetAwaiter().GetResult(); + } + var response = res.Content.ReadAsStringAsync().GetAwaiter().GetResult(); + + return container.GetCookies(res.RequestMessage.RequestUri); + } + + public static async Task Post(string url, IDictionary parameters, CookieCollection cookies) + { + var postData = ParametersToWWWFormURLEncoded(parameters); + var postDataBytes = Encoding.ASCII.GetBytes(postData); + + var request = (HttpWebRequest)WebRequest.Create(url); + + if (cookies != null) + { + var container = new CookieContainer(); + container.Add(new Uri(url), cookies); + request.CookieContainer = container; + } + + + request.Method = "POST"; + request.ContentType = "application/x-www-form-urlencoded"; + + using (var outputStream = await request.GetRequestStreamAsync()) + { + outputStream.Write(postDataBytes, 0, postDataBytes.Length); + outputStream.Flush(); + + var response = (HttpWebResponse)await request.GetResponseAsync(); + using (var responseStreamReader = new StreamReader(response.GetResponseStream())) + { + return responseStreamReader.ReadToEnd().Trim(); + } + } + + //HttpClientHandler handler; + //var uri = new Uri(url); + //if (cookies == null) + // handler = new HttpClientHandler(); + //else + //{ + // var cookieContainer = new CookieContainer(); + // cookieContainer.Add(uri, cookies); + // handler = new HttpClientHandler() { CookieContainer = cookieContainer }; + //} + //using (handler) + //using (var http = new HttpClient(handler)) + //{ + // var res = await http.PostAsync(url, new FormUrlEncodedContent(parameters)).ConfigureAwait(false); + // return await res.Content.ReadAsStringAsync().ConfigureAwait(false); + //} + } + + + public static string XPathSearch(string input, string expression) + { + var document = new XPathDocument(new MemoryStream(Encoding.ASCII.GetBytes(input))); + var navigator = document.CreateNavigator(); + return navigator.SelectSingleNode(expression).Value.Trim(); + } + + public static string StringAtIndex(string[] strings, int index) + { + if (index >= strings.Length) return ""; + return strings[index]; + } + } +} \ No newline at end of file diff --git a/src/NadekoBot/Services/Impl/BotCredentials.cs b/src/NadekoBot/Services/Impl/BotCredentials.cs index a5f326eb..d52e8ad7 100644 --- a/src/NadekoBot/Services/Impl/BotCredentials.cs +++ b/src/NadekoBot/Services/Impl/BotCredentials.cs @@ -26,8 +26,6 @@ namespace NadekoBot.Services.Impl public string LoLApiKey { get; } public string OsuApiKey { get; } public string SoundCloudClientId { get; } - public string CleverbotApiUser { get; } - public string CleverbotApiKey { get; } public DB Db { get; } public int TotalShards { get; } @@ -52,8 +50,6 @@ namespace NadekoBot.Services.Impl ClientId = cm.ClientId; SoundCloudClientId = cm.SoundCloudClientId; CarbonKey = cm.CarbonKey; - CleverbotApiKey = cm.CleverbotApiKey; - CleverbotApiUser = cm.CleverbotApiUser; if (cm.Db == null) Db = new DB("sqlite", ""); else @@ -81,8 +77,6 @@ namespace NadekoBot.Services.Impl public string CarbonKey { get; set; } = ""; public DB Db { get; set; } public int TotalShards { get; set; } = 1; - public string CleverbotApiUser { get; set; } - public string CleverbotApiKey { get; set; } } private class DbModel diff --git a/src/NadekoBot/credentials_example.json b/src/NadekoBot/credentials_example.json index 50577cd6..34925301 100644 --- a/src/NadekoBot/credentials_example.json +++ b/src/NadekoBot/credentials_example.json @@ -12,7 +12,5 @@ "SoundCloudClientId": "", "CarbonKey": "", "Db": null, - "TotalShards": 1, - "CleverbotApiUser": null, - "CleverbotApiKey": null + "TotalShards": 1 } \ No newline at end of file diff --git a/src/NadekoBot/project.json b/src/NadekoBot/project.json index 9ed621ff..e44b0284 100644 --- a/src/NadekoBot/project.json +++ b/src/NadekoBot/project.json @@ -41,7 +41,8 @@ }, "Discord.Net": { "target": "project" - } + }, + "System.Xml.XPath": "4.0.1" }, "tools": { "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"