From 9b8a04a7bf876dd09a04c434201af2ded552eee4 Mon Sep 17 00:00:00 2001 From: Uncled1023 Date: Wed, 4 Feb 2015 01:20:53 -0800 Subject: [PATCH] Added Url Parsing. Added Wolfram Alpha. --- Combot/Combot.csproj | 12 +-- Combot/Modules/ModuleClasses/Help.cs | 65 +++++++-------- Combot/Modules/ModuleClasses/Search.cs | 3 +- Combot/Modules/ModuleClasses/UrlParsing.cs | 117 +++++++++++++++++++++++++++ Combot/Modules/ModuleClasses/WolframAlpha.cs | 92 +++++++++++++++++++++ Combot/Modules/ModuleClasses/YouTube.cs | 16 +++- Combot/packages.config | 3 - IRCServices/IRC.cs | 4 +- IRCServices/IRCSend.cs | 22 +++-- 9 files changed, 275 insertions(+), 59 deletions(-) create mode 100755 Combot/Modules/ModuleClasses/UrlParsing.cs create mode 100755 Combot/Modules/ModuleClasses/WolframAlpha.cs diff --git a/Combot/Combot.csproj b/Combot/Combot.csproj index 82537ef..053d2f6 100755 --- a/Combot/Combot.csproj +++ b/Combot/Combot.csproj @@ -45,21 +45,13 @@ 4 - - ..\packages\Google.GData.Client.2.2.0.0\lib\Google.GData.Client.dll - - - ..\packages\Google.GData.Extensions.2.2.0.0\lib\Google.GData.Extensions.dll - - - ..\packages\Google.GData.YouTube.2.2.0.0\lib\Google.GData.YouTube.dll - False ..\packages\Newtonsoft.Json.6.0.8\lib\net45\Newtonsoft.Json.dll + @@ -83,8 +75,10 @@ + + diff --git a/Combot/Modules/ModuleClasses/Help.cs b/Combot/Modules/ModuleClasses/Help.cs index 8d59a05..897b584 100755 --- a/Combot/Modules/ModuleClasses/Help.cs +++ b/Combot/Modules/ModuleClasses/Help.cs @@ -23,7 +23,7 @@ namespace Combot.Modules.ModuleClasses } else if (command.Arguments.ContainsKey("Command")) { - SendCommandHelp(command.Nick.Nickname, command.Access, command.Arguments["Command"].ToString()); + SendCommandHelp(command); } } } @@ -31,50 +31,47 @@ namespace Combot.Modules.ModuleClasses private void SendFullHelp(string recipient, List access) { Bot.IRC.SendNotice(recipient, string.Format("You have the following commands available to use. " + - "To use them either type \u0002{1}\u001Fcommand\u000F into a channel, send a private message by typing \u0002/msg {0} \u001Fcommand\u000F, or send a notice by typing \u0002/notice {0} \u001Fcommand\u000F. " + - "For more information on a specific command, type \u0002{1}help \u001Fcommand\u000F.", + "To use them either type \u0002{1}\u001Fcommand trigger\u000F into a channel, send a private message by typing \u0002/msg {0} \u001Fcommand trigger\u000F, or send a notice by typing \u0002/notice {0} \u001Fcommand trigger\u000F. ", Bot.IRC.Nickname, Bot.ServerConfig.CommandPrefix)); Bot.IRC.SendNotice(recipient, "\u200B"); + List commandList = new List(); foreach (Module module in Bot.Modules) { - if (module.Commands.Exists(command => command.AllowedAccess.Exists(allowed => access.Contains(allowed)) && command.ShowHelp)) - { - Bot.IRC.SendNotice(recipient, string.Format("\u0002\u001F{0} Module\u000F\u0002\u000F", module.Name)); - } module.Commands.ForEach(command => { if (command.AllowedAccess.Exists(allowed => access.Contains(allowed)) && command.ShowHelp) { - string commandDesc = string.Empty; - if (command.Description != string.Empty) - { - commandDesc = string.Format(" - {0}", command.Description); - } - Bot.IRC.SendNotice(recipient, string.Format("\t\t\u0002{0}\u000F{1}", command.Name, commandDesc)); + commandList.Add(command.Name); } }); } + Bot.IRC.SendNotice(recipient, string.Format("\u0002{0}\u000F", string.Join(", ", commandList))); + Bot.IRC.SendNotice(recipient, "\u200B"); + Bot.IRC.SendNotice(recipient, string.Format("For more information on a specific command, including viewing the triggers, type \u0002{0}help \u001Fcommand\u000F.", Bot.ServerConfig.CommandPrefix)); } - private void SendCommandHelp(string recipient, List access, string command) + private void SendCommandHelp(CommandMessage command) { - Module foundModule = Bot.Modules.Find(mod => mod.Commands.Exists(cmd => (cmd.Name == command || cmd.Triggers.Contains(command)) && cmd.ShowHelp)); + string helpCommand = command.Arguments["Command"].ToString(); + Module foundModule = Bot.Modules.Find(mod => mod.Commands.Exists(cmd => (cmd.Name.ToLower() == helpCommand.ToLower() || cmd.Triggers.Contains(helpCommand)) && cmd.ShowHelp)); if (foundModule != null) { - Command foundCommand = foundModule.Commands.Find(cmd => (cmd.Name == command || cmd.Triggers.Contains(command))); + Command foundCommand = foundModule.Commands.Find(cmd => (cmd.Name.ToLower() == helpCommand.ToLower() || cmd.Triggers.Contains(helpCommand))); if (foundCommand != null) { - if (foundCommand.AllowedAccess.Exists(allowed => access.Contains(allowed))) + if (foundCommand.AllowedAccess.Exists(allowed => command.Access.Contains(allowed))) { - Bot.IRC.SendNotice(recipient, string.Format("Help information for \u0002{0}\u000F", foundCommand.Name)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("Help information for \u0002{0}\u000F", foundCommand.Name)); if (foundCommand.Description != string.Empty) { - Bot.IRC.SendNotice(recipient, string.Format("{0}", foundCommand.Description)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("{0}", foundCommand.Description)); } - Bot.IRC.SendNotice(recipient, "\u200B"); + Bot.IRC.SendNotice(command.Nick.Nickname, "\u200B"); for (int i = 0; i < foundCommand.AllowedMessageTypes.Count; i++) { MessageType messageType = foundCommand.AllowedMessageTypes[i]; + + // Generate Message Syntax string messageSyntax = string.Empty; switch (messageType) { @@ -90,10 +87,9 @@ namespace Combot.Modules.ModuleClasses } List validArguments = foundCommand.Arguments.FindAll(arg => arg.MessageTypes.Contains(messageType)); string argHelp = string.Empty; - Bot.IRC.SendNotice(recipient, string.Format("Message Type: \u0002{0}\u000F", messageType.ToString())); if (validArguments.Count > 0) { - argHelp = string.Format(" \u0002\u001F{0}\u000F", string.Join("\u000F \u0002", validArguments.Select(arg => + argHelp = string.Format(" \u0002{0}\u000F", string.Join(" ", validArguments.Select(arg => { if (arg.Required) { @@ -102,14 +98,15 @@ namespace Combot.Modules.ModuleClasses return "[\u001F" + arg.Name + "\u000F\u0002]"; }))); } - foundCommand.Triggers.ForEach(trigger => + if (foundCommand.Triggers.Any()) { - Bot.IRC.SendNotice(recipient, string.Format("\t\tSyntax: {0} {1}\u0002{2}\u000F{3}", messageSyntax, Bot.ServerConfig.CommandPrefix, trigger, argHelp)); - }); + string triggerString = (foundCommand.Triggers.Count > 1) ? string.Format("({0})", string.Join("|", foundCommand.Triggers)) : foundCommand.Triggers.First(); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("Syntax: {0} {1}\u0002{2}\u000F{3}", messageSyntax, Bot.ServerConfig.CommandPrefix, triggerString, argHelp)); + } + // Display argument help if (validArguments.Count > 0) { - Bot.IRC.SendNotice(recipient, "\u200B"); validArguments.ForEach(arg => { string commandDesc = string.Empty; @@ -117,34 +114,28 @@ namespace Combot.Modules.ModuleClasses { commandDesc = string.Format(" - {0}", arg.Description); } - string required = string.Empty; - if (arg.Required) - { - required = " - Required"; - } - Bot.IRC.SendNotice(recipient, string.Format("\t\t\u0002{0}{1}\u000F{2}", arg.Name, required, commandDesc)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("\t\t\u0002{0}\u000F{1}", arg.Name, commandDesc)); if (arg.AllowedValues.Count > 0) { - Bot.IRC.SendNotice(recipient, string.Format("\t\t\t\t- Allowed Values: \u0002{0}\u000F", string.Join(", ", arg.AllowedValues))); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("\t\tAllowed Values: \u0002{0}\u000F", string.Join(", ", arg.AllowedValues))); } }); } - Bot.IRC.SendNotice(recipient, "\u200B"); } } else { - Bot.IRC.SendNotice(recipient, string.Format("You do not have access to view help on \u0002{0}\u000F.", command)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("You do not have access to view help on \u0002{0}\u000F.", helpCommand)); } } else { - Bot.IRC.SendNotice(recipient, string.Format("The command \u0002{0}\u000F does not exist.", command)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("The command \u0002{0}\u000F does not exist.", helpCommand)); } } else { - Bot.IRC.SendNotice(recipient, string.Format("The command \u0002{0}\u000F does not exist.", command)); + Bot.IRC.SendNotice(command.Nick.Nickname, string.Format("The command \u0002{0}\u000F does not exist.", helpCommand)); } } } diff --git a/Combot/Modules/ModuleClasses/Search.cs b/Combot/Modules/ModuleClasses/Search.cs index 7e1f37c..4e77ed4 100755 --- a/Combot/Modules/ModuleClasses/Search.cs +++ b/Combot/Modules/ModuleClasses/Search.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Net; using System.Text; -using Google.GData.Client; +using System.Web; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -126,6 +126,5 @@ namespace Combot.Modules.ModuleClasses } return new string(array, 0, arrayIndex); } - } } \ No newline at end of file diff --git a/Combot/Modules/ModuleClasses/UrlParsing.cs b/Combot/Modules/ModuleClasses/UrlParsing.cs new file mode 100755 index 0000000..35cc7f3 --- /dev/null +++ b/Combot/Modules/ModuleClasses/UrlParsing.cs @@ -0,0 +1,117 @@ +using System; +using System.Net; +using System.Web; +using System.Text.RegularExpressions; +using Combot.IRCServices.Messaging; + +namespace Combot.Modules.ModuleClasses +{ + public class UrlParsing : Module + { + public override void Initialize() + { + Bot.IRC.Message.ChannelMessageReceivedEvent += HandleChannelMessage; + } + + public void HandleChannelMessage(object sender, ChannelMessage message) + { + Regex urlRegex = new Regex("(https?)://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?"); + + if (urlRegex.IsMatch(message.Message)) + { + MatchCollection urlMatches = urlRegex.Matches(message.Message); + for (int i = 0; i < urlMatches.Count; i++) + { + Match urlMatch = urlMatches[i]; + Uri url = new Uri(urlMatch.Value); + WebRequest webRequest = HttpWebRequest.Create(url); + webRequest.Method = "HEAD"; + using (WebResponse webResponse = webRequest.GetResponse()) + { + string contentType = webResponse.ContentType.Split('/')[0]; + long contentLength = webResponse.ContentLength; + switch (contentType) + { + case "text": + Regex ytRegex = new Regex("(((youtube.*(v=|/v/))|(youtu\\.be/))(?[-_a-zA-Z0-9]+))"); + if (!ytRegex.IsMatch(message.Message) || !Bot.Modules.Exists(mod => mod.Name == "YouTube")) + { + WebClient x = new WebClient(); + string source = x.DownloadString(urlMatch.ToString()); + string title = Regex.Match(source, @"\]*\>\s*(?[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value; + Bot.IRC.SendPrivateMessage(message.Channel, string.Format("[URL] {0} ({1})", HttpUtility.UrlDecode(StripTagsCharArray(title)), url.Host)); + } + break; + case "image": + Bot.IRC.SendPrivateMessage(message.Channel, string.Format("[{0}] Size: {1}", webResponse.ContentType, ToFileSize(contentLength))); + break; + case "video": + Bot.IRC.SendPrivateMessage(message.Channel, string.Format("[Video] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength))); + break; + case "application": + Bot.IRC.SendPrivateMessage(message.Channel, string.Format("[Application] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength))); + break; + case "audio": + Bot.IRC.SendPrivateMessage(message.Channel, string.Format("[Audio] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength))); + break; + } + } + } + } + } + + /// <summary> + /// Remove HTML tags from string using char array. + /// </summary> + public static string StripTagsCharArray(string source) + { + char[] array = new char[source.Length]; + int arrayIndex = 0; + bool inside = false; + + for (int i = 0; i < source.Length; i++) + { + char let = source[i]; + if (let == '<') + { + inside = true; + continue; + } + if (let == '>') + { + inside = false; + continue; + } + if (!inside) + { + array[arrayIndex] = let; + arrayIndex++; + } + } + return new string(array, 0, arrayIndex); + } + + public static string ToFileSize(long source) + { + const int byteConversion = 1024; + double bytes = Convert.ToDouble(source); + + if (bytes >= Math.Pow(byteConversion, 3)) //GB Range + { + return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 3), 2), " GB"); + } + else if (bytes >= Math.Pow(byteConversion, 2)) //MB Range + { + return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 2), 2), " MB"); + } + else if (bytes >= byteConversion) //KB Range + { + return string.Concat(Math.Round(bytes / byteConversion, 2), " KB"); + } + else //Bytes + { + return string.Concat(bytes, " Bytes"); + } + } + } +} \ No newline at end of file diff --git a/Combot/Modules/ModuleClasses/WolframAlpha.cs b/Combot/Modules/ModuleClasses/WolframAlpha.cs new file mode 100755 index 0000000..2241f39 --- /dev/null +++ b/Combot/Modules/ModuleClasses/WolframAlpha.cs @@ -0,0 +1,92 @@ +using System.Net; +using System.Text; +using System.Xml; + +namespace Combot.Modules.ModuleClasses +{ + public class WolframAlpha : Module + { + public override void Initialize() + { + Bot.CommandReceivedEvent += HandleCommandEvent; + } + + public override void ParseCommand(CommandMessage command) + { + Command foundCommand = Commands.Find(c => c.Triggers.Contains(command.Command)); + switch (foundCommand.Name) + { + case "Wolfram Alpha Search": + GetResults(command); + break; + } + } + + private void GetResults(CommandMessage command) + { + string URL = "http://api.wolframalpha.com/v2/query?input=" + System.Web.HttpUtility.UrlEncode(command.Arguments["Query"]) + "&appid=" + GetOptionValue("API") + "&format=plaintext"; + XmlNodeList xnList = null; + try + { + WebClient web = new WebClient(); + web.Encoding = Encoding.UTF8; + string results = web.DownloadString(URL); + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.LoadXml(results); + xnList = xmlDoc.SelectNodes("/queryresult/pod"); + } + catch + { + string errorMessage = string.Format("Unable to fetch results for \u0002{0}\u000F.", command.Arguments["Query"]); + switch (command.MessageType) + { + case MessageType.Channel: + Bot.IRC.SendPrivateMessage(command.Location, errorMessage); + break; + case MessageType.Query: + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, errorMessage); + break; + case MessageType.Notice: + Bot.IRC.SendNotice(command.Nick.Nickname, errorMessage); + break; + } + } + if (xnList.Count > 1) + { + string queryMessage = string.Format("Result for: {0}", xnList[0]["subpod"]["plaintext"].InnerText); + string resultMessage = xnList[1]["subpod"]["plaintext"].InnerText; + switch (command.MessageType) + { + case MessageType.Channel: + Bot.IRC.SendPrivateMessage(command.Location, queryMessage); + Bot.IRC.SendPrivateMessage(command.Location, resultMessage); + break; + case MessageType.Query: + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, queryMessage); + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, resultMessage); + break; + case MessageType.Notice: + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, queryMessage); + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, resultMessage); + break; + } + } + else + { + string errorMessage = string.Format("No results found for \u0002{0}\u000F.", command.Arguments["Query"]); + switch (command.MessageType) + { + case MessageType.Channel: + Bot.IRC.SendPrivateMessage(command.Location, errorMessage); + break; + case MessageType.Query: + Bot.IRC.SendPrivateMessage(command.Nick.Nickname, errorMessage); + break; + case MessageType.Notice: + Bot.IRC.SendNotice(command.Nick.Nickname, errorMessage); + break; + } + } + } + } +} \ No newline at end of file diff --git a/Combot/Modules/ModuleClasses/YouTube.cs b/Combot/Modules/ModuleClasses/YouTube.cs index 62abd54..602cc07 100755 --- a/Combot/Modules/ModuleClasses/YouTube.cs +++ b/Combot/Modules/ModuleClasses/YouTube.cs @@ -2,6 +2,8 @@ using System.Linq; using System.Net; using System.Text; +using System.Text.RegularExpressions; +using Combot.IRCServices.Messaging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -12,6 +14,7 @@ namespace Combot.Modules.ModuleClasses public override void Initialize() { Bot.CommandReceivedEvent += HandleCommandEvent; + Bot.IRC.Message.ChannelMessageReceivedEvent += HandleChannelMessage; } public override void ParseCommand(CommandMessage command) @@ -26,6 +29,17 @@ namespace Combot.Modules.ModuleClasses } } + private void HandleChannelMessage(object sender, ChannelMessage message) + { + Regex urlRegex = new Regex("(((youtube.*(v=|/v/))|(youtu\\.be/))(?<ID>[-_a-zA-Z0-9]+))"); + if (urlRegex.IsMatch(message.Message)) + { + Match urlMatch = urlRegex.Match(message.Message); + string youtubeMessage = GetYoutubeDescription(urlMatch.Groups["ID"].Value); + Bot.IRC.SendPrivateMessage(message.Channel, youtubeMessage); + } + } + private void YoutubeSearch(CommandMessage command) { string urlTemplate = "http://gdata.youtube.com/feeds/api/videos?v=2&alt=jsonc&max-results=1&q={0}"; @@ -39,7 +53,7 @@ namespace Combot.Modules.ModuleClasses { string videoID = parsed["data"]["items"].First().Value<string>("id"); string vidDescription = GetYoutubeDescription(videoID); - string youtubeMessage = string.Format("{0} - {1}.", vidDescription, string.Format("http://youtu.be/{0}", videoID)); + string youtubeMessage = string.Format("{0} - {1}", vidDescription, string.Format("http://youtu.be/{0}", videoID)); switch (command.MessageType) { case MessageType.Channel: diff --git a/Combot/packages.config b/Combot/packages.config index 1afc958..af70bc8 100755 --- a/Combot/packages.config +++ b/Combot/packages.config @@ -1,7 +1,4 @@ <?xml version="1.0" encoding="utf-8"?> <packages> - <package id="Google.GData.Client" version="2.2.0.0" targetFramework="net451" /> - <package id="Google.GData.Extensions" version="2.2.0.0" targetFramework="net451" /> - <package id="Google.GData.YouTube" version="2.2.0.0" targetFramework="net451" /> <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net451" /> </packages> \ No newline at end of file diff --git a/IRCServices/IRC.cs b/IRCServices/IRC.cs index 954589e..5a6a791 100755 --- a/IRCServices/IRC.cs +++ b/IRCServices/IRC.cs @@ -217,7 +217,9 @@ namespace Combot.IRCServices { if (_TCP.Connected) { - _TCP.Write(message); + string replaceWith = string.Empty; + string parsedMessage = message.Replace("\r\n", replaceWith).Replace("\n", replaceWith).Replace("\r", replaceWith); + _TCP.Write(parsedMessage); } } diff --git a/IRCServices/IRCSend.cs b/IRCServices/IRCSend.cs index 4633db2..83b8d23 100755 --- a/IRCServices/IRCSend.cs +++ b/IRCServices/IRCSend.cs @@ -57,16 +57,26 @@ namespace Combot.IRCServices /// <param name="message"></param> public void SendNotice(string recipient, string message) { - if (message.Length > MaxMessageLength) + TimeSpan sinceLastMessage = (DateTime.Now - LastMessageSend); + if (sinceLastMessage.TotalMilliseconds < MessageSendDelay) { - string subMessage = message.Substring(0, MaxMessageLength); - string nextMessage = message.Remove(0, MaxMessageLength); - SendTCPMessage(string.Format("NOTICE {0} :{1}", recipient, message)); - SendNotice(recipient, nextMessage); + Thread.Sleep((int) sinceLastMessage.TotalMilliseconds); + SendNotice(recipient, message); } else { - SendTCPMessage(string.Format("NOTICE {0} :{1}", recipient, message)); + LastMessageSend = DateTime.Now; + if (message.Length > MaxMessageLength) + { + string subMessage = message.Substring(0, MaxMessageLength); + string nextMessage = message.Remove(0, MaxMessageLength); + SendTCPMessage(string.Format("NOTICE {0} :{1}", recipient, message)); + SendNotice(recipient, nextMessage); + } + else + { + SendTCPMessage(string.Format("NOTICE {0} :{1}", recipient, message)); + } } }