The easy to use and full featured Irc Bot everyone is talking about!
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

Messages.cs 21KB

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