The easy to use and full featured Irc Bot everyone is talking about!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Url_Parsing.cs 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Net;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using System.Web;
  8. using Combot.IRCServices.Messaging;
  9. using Newtonsoft.Json;
  10. using Newtonsoft.Json.Linq;
  11. namespace Combot.Modules.Plugins
  12. {
  13. public class Url_Parsing : Module
  14. {
  15. public override void Initialize()
  16. {
  17. Bot.IRC.Message.ChannelMessageReceivedEvent += HandleChannelMessage;
  18. }
  19. public void HandleChannelMessage(object sender, ChannelMessage message)
  20. {
  21. Regex urlRegex = new Regex("(https?)://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?");
  22. if (Enabled
  23. && !Bot.ServerConfig.ChannelBlacklist.Contains(message.Channel)
  24. && !Bot.ServerConfig.NickBlacklist.Contains(message.Sender.Nickname)
  25. && !ChannelBlacklist.Contains(message.Channel)
  26. && !NickBlacklist.Contains(message.Sender.Nickname)
  27. && !Bot.IsCommand(message.Message))
  28. {
  29. if (urlRegex.IsMatch(message.Message))
  30. {
  31. MatchCollection urlMatches = urlRegex.Matches(message.Message);
  32. for (int i = 0; i < urlMatches.Count; i++)
  33. {
  34. Match urlMatch = urlMatches[i];
  35. Uri url = new Uri(urlMatch.Value);
  36. HttpWebRequest webRequest = (HttpWebRequest) WebRequest.Create(url);
  37. webRequest.Method = "HEAD";
  38. webRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
  39. ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  40. ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
  41. try
  42. {
  43. using (HttpWebResponse webResponse = (HttpWebResponse) webRequest.GetResponse())
  44. {
  45. int code = (int) webResponse.StatusCode;
  46. if (code == 200)
  47. {
  48. string contentType = webResponse.ContentType.Split('/')[0];
  49. long contentLength = webResponse.ContentLength;
  50. switch (contentType)
  51. {
  52. case "image":
  53. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[{0}] Size: {1}", webResponse.ContentType, ToFileSize(contentLength)));
  54. break;
  55. case "video":
  56. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[Video] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength)));
  57. break;
  58. case "application":
  59. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[Application] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength)));
  60. break;
  61. case "audio":
  62. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[Audio] Type: {0} | Size: {1}", webResponse.ContentType.Split('/')[1], ToFileSize(contentLength)));
  63. break;
  64. default:
  65. Regex ytRegex = new Regex("(((youtube.*(v=|/v/))|(youtu\\.be/))(?<ID>[-_a-zA-Z0-9]+))");
  66. if (ytRegex.IsMatch(urlMatch.ToString()))
  67. {
  68. Match ytMatch = ytRegex.Match(urlMatch.ToString());
  69. string youtubeMessage = GetYoutubeDescription(ytMatch.Groups["ID"].Value);
  70. Bot.IRC.Command.SendPrivateMessage(message.Channel, youtubeMessage);
  71. }
  72. else
  73. {
  74. ParseTitle(message, urlMatch.ToString());
  75. }
  76. break;
  77. }
  78. }
  79. else
  80. {
  81. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[URL] Returned Status Code \u0002{0}\u0002 ({1})", code, url.Host));
  82. }
  83. }
  84. }
  85. catch (WebException ex)
  86. {
  87. if (ex.Response != null)
  88. {
  89. int code = (int) ((HttpWebResponse) ex.Response).StatusCode;
  90. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[URL] Response Code: \u0002{0}\u0002 ({1})", code, url.Host));
  91. }
  92. }
  93. catch (OutOfMemoryException ex)
  94. {
  95. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[URL] \u0002Site content was too large\u0002 ({0})", url.Host));
  96. }
  97. }
  98. }
  99. }
  100. }
  101. public void ParseTitle(ChannelMessage message, string urlString)
  102. {
  103. string title = string.Empty;
  104. bool startTagFound = false;
  105. Uri url = new Uri(urlString);
  106. HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(urlString);
  107. StreamReader streamReader = new StreamReader(req.GetResponse().GetResponseStream());
  108. Char[] buf = new Char[256];
  109. int count = streamReader.Read(buf, 0, 256);
  110. var stopwatch = Stopwatch.StartNew();
  111. TimeSpan timeout = new TimeSpan(0, 0, 15);
  112. while (count > 0 && stopwatch.Elapsed < timeout)
  113. {
  114. String outputData = new String(buf, 0, count);
  115. if (!startTagFound)
  116. {
  117. // check for a full match
  118. Match fullMatch = Regex.Match(outputData, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase);
  119. if (fullMatch.Success)
  120. {
  121. title = fullMatch.Groups["Title"].Value;
  122. break;
  123. }
  124. }
  125. string pattern = string.Empty;
  126. if (startTagFound)
  127. {
  128. pattern = @"^(?<Title>[\s\S]*?)\</title\>";
  129. Match match = Regex.Match(outputData, pattern, RegexOptions.IgnoreCase);
  130. if (match.Success)
  131. {
  132. title += match.Groups["Title"].Value;
  133. break;
  134. }
  135. title += outputData;
  136. }
  137. else
  138. {
  139. pattern = @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)$";
  140. Match match = Regex.Match(outputData, pattern, RegexOptions.IgnoreCase);
  141. if (match.Success)
  142. {
  143. title = match.Groups["Title"].Value;
  144. startTagFound = true;
  145. }
  146. }
  147. count = streamReader.Read(buf, 0, 256);
  148. }
  149. streamReader.Close();
  150. if (!string.IsNullOrEmpty(title))
  151. {
  152. int maxTitle = Convert.ToInt32(GetOptionValue("Max Title"));
  153. if (title.Length > (int)maxTitle)
  154. {
  155. title = string.Format("{0}...", title.Substring(0, (int)maxTitle));
  156. }
  157. Bot.IRC.Command.SendPrivateMessage(message.Channel, string.Format("[URL] {0} ({1})", HttpUtility.HtmlDecode(HttpUtility.UrlDecode(StripTagsCharArray(title))), url.Host));
  158. }
  159. }
  160. /// <summary>
  161. /// Remove HTML tags from string using char array.
  162. /// </summary>
  163. public static string StripTagsCharArray(string source)
  164. {
  165. char[] array = new char[source.Length];
  166. int arrayIndex = 0;
  167. bool inside = false;
  168. for (int i = 0; i < source.Length; i++)
  169. {
  170. char let = source[i];
  171. if (let == '<')
  172. {
  173. inside = true;
  174. continue;
  175. }
  176. if (let == '>')
  177. {
  178. inside = false;
  179. continue;
  180. }
  181. if (!inside)
  182. {
  183. array[arrayIndex] = let;
  184. arrayIndex++;
  185. }
  186. }
  187. return new string(array, 0, arrayIndex);
  188. }
  189. public static string ToFileSize(long source)
  190. {
  191. const int byteConversion = 1024;
  192. double bytes = Convert.ToDouble(source);
  193. if (bytes >= Math.Pow(byteConversion, 3)) //GB Range
  194. {
  195. return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 3), 2), " GB");
  196. }
  197. else if (bytes >= Math.Pow(byteConversion, 2)) //MB Range
  198. {
  199. return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 2), 2), " MB");
  200. }
  201. else if (bytes >= byteConversion) //KB Range
  202. {
  203. return string.Concat(Math.Round(bytes / byteConversion, 2), " KB");
  204. }
  205. else //Bytes
  206. {
  207. return string.Concat(bytes, " Bytes");
  208. }
  209. }
  210. private string GetYoutubeDescription(string ID)
  211. {
  212. string description = string.Empty;
  213. string urlTemplate = "http://gdata.youtube.com/feeds/api/videos/{0}?v=2&alt=jsonc";
  214. Uri searchUrl = new Uri(string.Format(urlTemplate, ID));
  215. WebClient web = new WebClient();
  216. web.Encoding = Encoding.UTF8;
  217. try
  218. {
  219. string page = web.DownloadString(searchUrl);
  220. JObject parsed = (JObject)JsonConvert.DeserializeObject(page);
  221. var data = parsed["data"];
  222. description = string.Format("\u0002{0}\u000F", data["title"]);
  223. if (data["duration"] == null)
  224. {
  225. return description;
  226. }
  227. TimeSpan duration = TimeSpan.FromSeconds(data["duration"].Value<double>());
  228. description += string.Format(" | Length: \u0002{0}\u000F", duration.ToString("g"));
  229. if (data["ratingCount"] != null)
  230. {
  231. int likes = data["likeCount"].Value<int>();
  232. string pluralLikes = (likes > 1) ? "s" : string.Empty;
  233. int dislikes = data["ratingCount"].Value<int>() - likes;
  234. string pluralDislikes = (dislikes > 1) ? "s" : string.Empty;
  235. double percent = 100.0 * ((double)likes / data["ratingCount"].Value<int>());
  236. description += string.Format(" | Rating: {0} Like{1}, {2} Dislike{3} (\u0002{4}\u000F%)", likes, pluralLikes, dislikes, pluralDislikes, Math.Round(percent, 1));
  237. }
  238. if (data["viewCount"] != null)
  239. {
  240. description += string.Format(" | Views: \u0002{0}\u000F", data["viewCount"].Value<int>());
  241. }
  242. DateTime uploadDate = Convert.ToDateTime(data["uploaded"].Value<string>());
  243. description += string.Format(" | Uploaded By: \u0002{0}\u000F on \u0002{1}\u000F", data["uploader"].Value<string>(), uploadDate.ToString("R"));
  244. if (data["contentRating"] != null)
  245. {
  246. description += " | \u0002NSFW\u000F";
  247. }
  248. }
  249. catch (WebException ex)
  250. {
  251. description = string.Empty;
  252. }
  253. return description;
  254. }
  255. }
  256. }