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.

Messages.cs 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Threading.Tasks;
  7. namespace Combot.IRCServices.Messaging
  8. {
  9. public class Messages
  10. {
  11. public event EventHandler<string> RawMessageEvent;
  12. public event EventHandler<IReply> ServerReplyEvent;
  13. public event EventHandler<ErrorMessage> ErrorMessageEvent;
  14. public event EventHandler<ChannelMessage> ChannelMessageReceivedEvent;
  15. public event EventHandler<PrivateMessage> PrivateMessageReceivedEvent;
  16. public event EventHandler<ServerNotice> ServerNoticeReceivedEvent;
  17. public event EventHandler<ChannelNotice> ChannelNoticeReceivedEvent;
  18. public event EventHandler<PrivateNotice> PrivateNoticeReceivedEvent;
  19. public event EventHandler<TopicChangeInfo> TopicChangeEvent;
  20. public event EventHandler<ChannelModeChangeInfo> ChannelModeChangeEvent;
  21. public event EventHandler<UserModeChangeInfo> UserModeChangeEvent;
  22. public event EventHandler<NickChangeInfo> NickChangeEvent;
  23. public event EventHandler<InviteChannelInfo> InviteChannelEvent;
  24. public event EventHandler<JoinChannelInfo> JoinChannelEvent;
  25. public event EventHandler<PartChannelInfo> PartChannelEvent;
  26. public event EventHandler<KickInfo> KickEvent;
  27. public event EventHandler<QuitInfo> QuitEvent;
  28. public event EventHandler<PingInfo> PingEvent;
  29. public event EventHandler<PongInfo> PongEvent;
  30. private IRC _IRC;
  31. internal Messages(IRC irc)
  32. {
  33. _IRC = irc;
  34. }
  35. internal void ParseTCPMessage(string tcpMessage)
  36. {
  37. DateTime messageTime = DateTime.Now;
  38. Regex messageRegex = new Regex(@"^:(?<Sender>[^\s]+)\s(?<Type>[^\s]+)\s(?<Recipient>[^\s]+)\s?(?<Args>.*)", RegexOptions.None);
  39. Regex senderRegex = new Regex(@"^(?<Nick>[^\s]+)!(?<Realname>[^\s]+)@(?<Host>[^\s]+)", RegexOptions.None);
  40. Regex pingRegex = new Regex(@"^PING :(?<Message>.+)", RegexOptions.None);
  41. Regex pongRegex = new Regex(@"^PONG :(?<Message>.+)", RegexOptions.None);
  42. Regex errorRegex = new Regex(@"^ERROR :(?<Message>.+)", RegexOptions.None);
  43. string[] messages = tcpMessage.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
  44. foreach (string message in messages)
  45. {
  46. if (messageRegex.IsMatch(message))
  47. {
  48. Match match = messageRegex.Match(message);
  49. string type = match.Groups["Type"].Value;
  50. string sender = match.Groups["Sender"].Value;
  51. string recipient = match.Groups["Recipient"].Value;
  52. string args = match.Groups["Args"].Value;
  53. Match senderMatch = senderRegex.Match(sender);
  54. string senderNick = sender;
  55. string senderRealname = sender;
  56. string senderHost = sender;
  57. if (senderMatch.Success)
  58. {
  59. senderNick = senderMatch.Groups["Nick"].Value;
  60. senderRealname = senderMatch.Groups["Realname"].Value;
  61. senderHost = senderMatch.Groups["Host"].Value;
  62. }
  63. int replyCode;
  64. if (int.TryParse(type, out replyCode))
  65. {
  66. // The message was a reply to a command sent
  67. if (Enum.IsDefined(typeof(IRCReplyCode), replyCode))
  68. {
  69. if (ServerReplyEvent != null)
  70. {
  71. ServerReplyEvent(this, new ServerReplyMessage() { TimeStamp = messageTime, ReplyCode = (IRCReplyCode)replyCode, Message = args });
  72. }
  73. }
  74. else if (Enum.IsDefined(typeof(IRCErrorCode), replyCode))
  75. {
  76. if (ServerReplyEvent != null)
  77. {
  78. ServerReplyEvent(this, new ServerErrorMessage() { TimeStamp = messageTime, ErrorCode = (IRCErrorCode)replyCode, Message = args });
  79. }
  80. }
  81. }
  82. else
  83. {
  84. switch (type)
  85. {
  86. case "PRIVMSG":
  87. if (recipient.StartsWith("&") || recipient.StartsWith("#"))
  88. {
  89. ChannelMessage msg = new ChannelMessage();
  90. msg.Channel = recipient;
  91. msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  92. msg.Message = args.Remove(0, 1);
  93. if (ChannelMessageReceivedEvent != null)
  94. {
  95. ChannelMessageReceivedEvent(this, msg);
  96. }
  97. }
  98. else
  99. {
  100. PrivateMessage msg = new PrivateMessage();
  101. msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  102. msg.Message = args.Remove(0, 1);
  103. if (PrivateMessageReceivedEvent != null)
  104. {
  105. PrivateMessageReceivedEvent(this, msg);
  106. }
  107. }
  108. break;
  109. case "NOTICE":
  110. if (recipient.StartsWith("&") || recipient.StartsWith("#"))
  111. {
  112. ChannelNotice msg = new ChannelNotice();
  113. msg.Channel = recipient;
  114. msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  115. msg.Message = args.Remove(0, 1);
  116. if (ChannelNoticeReceivedEvent != null)
  117. {
  118. ChannelNoticeReceivedEvent(this, msg);
  119. }
  120. }
  121. else
  122. {
  123. PrivateNotice msg = new PrivateNotice();
  124. msg.Sender = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  125. msg.Message = args.Remove(0, 1);
  126. if (PrivateNoticeReceivedEvent != null)
  127. {
  128. PrivateNoticeReceivedEvent(this, msg);
  129. }
  130. }
  131. break;
  132. case "MODE":
  133. if (recipient.StartsWith("&") || recipient.StartsWith("#"))
  134. {
  135. ChannelModeChangeInfo modeMsg = new ChannelModeChangeInfo();
  136. modeMsg.Modes = new List<ChannelModeInfo>();
  137. modeMsg.Channel = recipient;
  138. modeMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  139. string[] modeArgs = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  140. char[] modeInfo = modeArgs[0].TrimStart(':').ToCharArray();
  141. bool set = true;
  142. int argIndex = 1;
  143. foreach (char mode in modeInfo)
  144. {
  145. if (mode.Equals('-'))
  146. {
  147. set = false;
  148. }
  149. else if (mode.Equals('+'))
  150. {
  151. set = true;
  152. }
  153. else
  154. {
  155. ChannelModeInfo newMode = new ChannelModeInfo();
  156. newMode.Set = set;
  157. newMode.Mode = (ChannelMode)Enum.Parse(typeof(ChannelMode), mode.ToString());
  158. if (modeArgs.GetUpperBound(0) >= argIndex)
  159. {
  160. switch (newMode.Mode)
  161. {
  162. case ChannelMode.k:
  163. case ChannelMode.l:
  164. case ChannelMode.v:
  165. case ChannelMode.h:
  166. case ChannelMode.o:
  167. case ChannelMode.a:
  168. case ChannelMode.q:
  169. case ChannelMode.b:
  170. case ChannelMode.e:
  171. case ChannelMode.I:
  172. newMode.Parameter = modeArgs[argIndex];
  173. argIndex++;
  174. break;
  175. default:
  176. newMode.Parameter = string.Empty;
  177. break;
  178. }
  179. }
  180. else
  181. {
  182. newMode.Parameter = string.Empty;
  183. }
  184. modeMsg.Modes.Add(newMode);
  185. }
  186. }
  187. if (ChannelModeChangeEvent != null)
  188. {
  189. ChannelModeChangeEvent(this, modeMsg);
  190. }
  191. }
  192. else
  193. {
  194. UserModeChangeInfo modeMsg = new UserModeChangeInfo();
  195. modeMsg.Modes = new List<UserModeInfo>();
  196. string[] modeArgs = args.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
  197. char[] modeInfo = modeArgs[0].TrimStart(':').ToCharArray();
  198. bool set = true;
  199. foreach (char mode in modeInfo)
  200. {
  201. if (mode.Equals('-'))
  202. {
  203. set = false;
  204. }
  205. else if (mode.Equals('+'))
  206. {
  207. set = true;
  208. }
  209. else
  210. {
  211. UserModeInfo newMode = new UserModeInfo();
  212. newMode.Set = set;
  213. newMode.Mode = (UserMode)Enum.Parse(typeof(UserMode), mode.ToString());
  214. modeMsg.Modes.Add(newMode);
  215. }
  216. }
  217. if (UserModeChangeEvent != null)
  218. {
  219. UserModeChangeEvent(this, modeMsg);
  220. }
  221. }
  222. break;
  223. case "TOPIC":
  224. TopicChangeInfo topicMsg = new TopicChangeInfo();
  225. topicMsg.Channel = recipient;
  226. topicMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  227. topicMsg.Topic = args.Remove(0, 1);
  228. if (TopicChangeEvent != null)
  229. {
  230. TopicChangeEvent(this, topicMsg);
  231. }
  232. break;
  233. case "NICK":
  234. NickChangeInfo nickMsg = new NickChangeInfo();
  235. nickMsg.OldNick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  236. nickMsg.NewNick = new Nick() { Nickname = recipient.Remove(0, 1) };
  237. if (NickChangeEvent != null)
  238. {
  239. NickChangeEvent(this, nickMsg);
  240. }
  241. break;
  242. case "INVITE":
  243. InviteChannelInfo inviteMsg = new InviteChannelInfo();
  244. inviteMsg.Requester = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  245. inviteMsg.Recipient = new Nick() { Nickname = recipient };
  246. inviteMsg.Channel = args.Remove(0, 1);
  247. if (InviteChannelEvent != null)
  248. {
  249. InviteChannelEvent(this, inviteMsg);
  250. }
  251. break;
  252. case "JOIN":
  253. JoinChannelInfo joinMsg = new JoinChannelInfo();
  254. joinMsg.Channel = recipient.TrimStart(':');
  255. joinMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  256. if (JoinChannelEvent != null)
  257. {
  258. JoinChannelEvent(this, joinMsg);
  259. }
  260. break;
  261. case "PART":
  262. PartChannelInfo partMsg = new PartChannelInfo();
  263. partMsg.Channel = recipient;
  264. partMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  265. if (PartChannelEvent != null)
  266. {
  267. PartChannelEvent(this, partMsg);
  268. }
  269. break;
  270. case "KICK":
  271. KickInfo kickMsg = new KickInfo();
  272. kickMsg.Channel = recipient;
  273. kickMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  274. string[] argSplit = args.Split(new char[] { ' ' }, StringSplitOptions.None);
  275. kickMsg.KickedNick = new Nick() { Nickname = argSplit[0], Realname = argSplit[0], Host = argSplit[0] };
  276. List<string> reasonArgs = argSplit.ToList<string>();
  277. reasonArgs.RemoveAt(0);
  278. kickMsg.Reason = string.Join(" ", reasonArgs.ToArray()).Remove(0, 1);
  279. if (KickEvent != null)
  280. {
  281. KickEvent(this, kickMsg);
  282. }
  283. break;
  284. case "QUIT":
  285. QuitInfo quitMsg = new QuitInfo();
  286. quitMsg.Nick = new Nick() { Nickname = senderNick, Realname = senderRealname, Host = senderHost };
  287. quitMsg.Message = recipient.Remove(0, 1);
  288. if (QuitEvent != null)
  289. {
  290. QuitEvent(this, quitMsg);
  291. }
  292. break;
  293. default:
  294. break;
  295. }
  296. }
  297. }
  298. else if (pingRegex.IsMatch(message))
  299. {
  300. Match match = pingRegex.Match(message);
  301. PingInfo ping = new PingInfo();
  302. ping.Message = match.Groups["Message"].Value;
  303. if (PingEvent != null)
  304. {
  305. PingEvent(this, ping);
  306. }
  307. }
  308. else if (pongRegex.IsMatch(message))
  309. {
  310. Match match = pongRegex.Match(message);
  311. PongInfo pong = new PongInfo();
  312. pong.Message = match.Groups["Message"].Value;
  313. if (PongEvent != null)
  314. {
  315. PongEvent(this, pong);
  316. }
  317. }
  318. else if (errorRegex.IsMatch(message))
  319. {
  320. Match match = errorRegex.Match(message);
  321. ErrorMessage error = new ErrorMessage();
  322. error.Message = match.Groups["Message"].Value;
  323. if (ErrorMessageEvent != null)
  324. {
  325. ErrorMessageEvent(this, error);
  326. }
  327. }
  328. if (RawMessageEvent != null)
  329. {
  330. RawMessageEvent(this, message);
  331. }
  332. }
  333. }
  334. internal bool GetReply(List<IRCReplyCode> ReplyCodes, List<IRCErrorCode> ErrorCodes)
  335. {
  336. GetReply reply = new GetReply();
  337. reply.Replies = ReplyCodes;
  338. reply.Errors = ErrorCodes;
  339. ServerReplyEvent += (sender, e) => HandleReply(sender, e, reply);
  340. reply.Ready.Wait(TimeSpan.FromMilliseconds(5000));
  341. reply.Reattach = false;
  342. return reply.Result;
  343. }
  344. private void HandleReply(object sender, IReply message, GetReply reply)
  345. {
  346. bool replyFound = false;
  347. if (message.GetType() == typeof(ServerReplyMessage))
  348. {
  349. ServerReplyMessage msg = (ServerReplyMessage)message;
  350. replyFound = reply.Replies.Contains(msg.ReplyCode);
  351. }
  352. else
  353. {
  354. ServerErrorMessage msg = (ServerErrorMessage)message;
  355. replyFound = reply.Errors.Contains(msg.ErrorCode);
  356. }
  357. if (replyFound)
  358. {
  359. reply.Result = replyFound;
  360. reply.Ready.Set();
  361. }
  362. else
  363. {
  364. if (reply.Reattach)
  365. {
  366. ServerReplyEvent += (obj, e) => HandleReply(obj, e, reply);
  367. }
  368. }
  369. }
  370. }
  371. }