The easy to use and full featured Irc Bot everyone is talking about!
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. using Combot.IRCServices;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using Combot.IRCServices.Messaging;
  6. using Combot.IRCServices.Commanding;
  7. namespace Combot.Modules.Plugins
  8. {
  9. public class Relay : Module
  10. {
  11. public override void Initialize()
  12. {
  13. Bot.CommandReceivedEvent += HandleCommandEvent;
  14. // Incoming Messages
  15. Bot.IRC.Message.CTCPMessageReceivedEvent += CTCPRelayHandler;
  16. Bot.IRC.Message.CTCPNoticeReceivedEvent += CTCPRelayHandler;
  17. Bot.IRC.Message.ChannelMessageReceivedEvent += RelayChannelMessage;
  18. Bot.IRC.Message.PrivateMessageReceivedEvent += RelayPrivateMessage;
  19. Bot.IRC.Message.ChannelNoticeReceivedEvent += RelayChannelNotice;
  20. Bot.IRC.Message.PrivateNoticeReceivedEvent += RelayPrivateNotice;
  21. Bot.IRC.Message.ChannelModeChangeEvent += RelayChannelMode;
  22. Bot.IRC.Message.UserModeChangeEvent += RelayUserMode;
  23. Bot.IRC.Message.JoinChannelEvent += RelayChannelJoin;
  24. Bot.IRC.Message.InviteChannelEvent += RelayChannelInvite;
  25. Bot.IRC.Message.PartChannelEvent += RelayChannelPart;
  26. Bot.IRC.Message.KickEvent += RelayChannelKick;
  27. Bot.IRC.Message.TopicChangeEvent += RelayTopicChange;
  28. Bot.IRC.Message.QuitEvent += RelayQuit;
  29. Bot.IRC.Message.NickChangeEvent += RelayNickChange;
  30. // Outgoing messages
  31. //Bot.IRC.Command.CTCPMessageCommandEvent += RelayCTCPMessageCommand;
  32. //Bot.IRC.Command.CTCPNoticeCommandEvent += RelayCTCPNoticeCommand;
  33. //Bot.IRC.Command.PrivateMessageCommandEvent += RelayPrivateMessageCommand;
  34. //Bot.IRC.Command.PrivateNoticeCommandEvent += RelayPrivateNoticeCommand;
  35. //Bot.IRC.Command.ChannelModeCommandEvent += RelayChannelModeCommand;
  36. //Bot.IRC.Command.UserModeCommandEvent += RelayUserModeCommand;
  37. //Bot.IRC.Command.KickCommandEvent += RelayKickCommand;
  38. //Bot.IRC.Command.InviteCommandEvent += RelayInviteCommand;
  39. //Bot.IRC.Command.PartCommandEvent += RelayPartCommand;
  40. //Bot.IRC.Command.TopicCommandEvent += RelayTopicCommand;
  41. //Bot.IRC.Command.JoinCommandEvent += RelayJoinCommand;
  42. //Bot.IRC.Command.NickCommandEvent += RelayNickCommand;
  43. }
  44. public override void ParseCommand(CommandMessage command)
  45. {
  46. Command foundCommand = Commands.Find(c => c.Triggers.Contains(command.Command));
  47. switch (foundCommand.Name)
  48. {
  49. case "Relay":
  50. string method = command.Arguments["Method"];
  51. switch (method.ToLower())
  52. {
  53. case "add":
  54. AddRelay(command);
  55. break;
  56. case "edit":
  57. EditRelay(command);
  58. break;
  59. case "delete":
  60. case "del":
  61. DeleteRelay(command);
  62. break;
  63. case "view":
  64. ViewRelay(command);
  65. break;
  66. }
  67. break;
  68. }
  69. }
  70. private void AddRelay(CommandMessage command)
  71. {
  72. string source = command.Arguments.ContainsKey("Source") ? command.Arguments["Source"] : command.Location;
  73. string target = command.Arguments.ContainsKey("Target") ? command.Arguments["Target"] : command.Nick.Nickname;
  74. string type = command.Arguments.ContainsKey("Type") ? command.Arguments["Type"] : "Message";
  75. string modes = command.Arguments.ContainsKey("Modes") ? command.Arguments["Modes"] : string.Empty;
  76. string chanAccess = GetOptionValue("Channel Access").ToString();
  77. AccessType access = AccessType.User;
  78. Enum.TryParse(chanAccess, out access);
  79. // verify access in source and target
  80. if (!CheckAccess(source, command.Nick.Nickname, access))
  81. {
  82. string invalid = string.Format("You do not have permission to use '{0}' as a source.", source);
  83. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  84. return;
  85. }
  86. if (Channel.IsChannel(target) && !CheckAccess(target, command.Nick.Nickname, access))
  87. {
  88. string invalid = string.Format("You do not have permission to use '{0}' as a target.", source);
  89. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  90. return;
  91. }
  92. RelayType relayType = RelayType.Message;
  93. Enum.TryParse(type, true, out relayType);
  94. AddNick(command.Nick);
  95. string query = "INSERT INTO `relays` SET " +
  96. "`server_id` = (SELECT `id` FROM `servers` WHERE `name` = {0}), " +
  97. "`nick_id` = (SELECT `nicks`.`id` FROM `nicks` INNER JOIN `servers` ON `servers`.`id` = `nicks`.`server_id` WHERE `servers`.`name` = {1} && `nickname` = {2}), " +
  98. "`source` = {3}, " +
  99. "`target` = {4}, " +
  100. "`type` = {5}, " +
  101. "`modes` = {6}, " +
  102. "`date_added` = {7}";
  103. Bot.Database.Execute(query, new object[] { Bot.ServerConfig.Name, Bot.ServerConfig.Name, command.Nick.Nickname, source, target, (int)relayType, modes, command.TimeStamp });
  104. List<Dictionary<string, object>> results = GetRelayList(command.Nick.Nickname);
  105. string relayMessage = string.Format("Added relay from \u0002{0}\u0002 to \u0002{1}\u0002. You now have \u0002{2}\u0002 relays created.", source, target, results.Count);
  106. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, relayMessage);
  107. }
  108. private void EditRelay(CommandMessage command)
  109. {
  110. string source = command.Arguments.ContainsKey("Source") ? command.Arguments["Source"] : command.Location;
  111. string target = command.Arguments.ContainsKey("Target") ? command.Arguments["Target"] : command.Nick.Nickname;
  112. string type = command.Arguments.ContainsKey("Type") ? command.Arguments["Type"] : "Message";
  113. string modes = command.Arguments.ContainsKey("Modes") ? command.Arguments["Modes"] : string.Empty;
  114. string chanAccess = GetOptionValue("Channel Access").ToString();
  115. AccessType access = AccessType.User;
  116. Enum.TryParse(chanAccess, out access);
  117. // verify access in source and target
  118. if (!CheckAccess(source, command.Nick.Nickname, access))
  119. {
  120. string invalid = string.Format("You do not have permission to use '{0}' as a source.", source);
  121. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  122. return;
  123. }
  124. if (Channel.IsChannel(target) && !CheckAccess(target, command.Nick.Nickname, access))
  125. {
  126. string invalid = string.Format("You do not have permission to use '{0}' as a target.", source);
  127. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  128. return;
  129. }
  130. RelayType relayType = RelayType.Message;
  131. Enum.TryParse(type, true, out relayType);
  132. int num = HasValidID(command);
  133. if (num > 0)
  134. {
  135. List<Dictionary<string, object>> results = GetRelayList(command.Nick.Nickname);
  136. int id = Convert.ToInt32(results[num - 1]["id"]);
  137. string query = "UPDATE `relays` SET " +
  138. "`source` = {0}, " +
  139. "`target` = {1}, " +
  140. "`type` = {2}, " +
  141. "`modes` = {3} " +
  142. "WHERE `id` = {4}";
  143. Bot.Database.Execute(query, new object[] { source, target, (int)relayType, modes, id });
  144. string relayMessage = string.Format("Updated relay \u0002{0}\u0002 to be from \u0002{1}\u0002 to \u0002{2}\u0002.", num, source, target);
  145. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, relayMessage);
  146. }
  147. else
  148. {
  149. string invalid = "Invalid relay ID.";
  150. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  151. }
  152. }
  153. private void DeleteRelay(CommandMessage command)
  154. {
  155. int num = HasValidID(command);
  156. if (num > 0)
  157. {
  158. List<Dictionary<string, object>> results = GetRelayList(command.Nick.Nickname);
  159. int id = Convert.ToInt32(results[num - 1]["id"]);
  160. string query = "DELETE FROM `relays` " +
  161. "WHERE `id` = {0}";
  162. Bot.Database.Execute(query, new object[] { id });
  163. string relayMessage = string.Format("Relay #\u0002{0}\u0002 has been deleted.", num);
  164. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, relayMessage);
  165. }
  166. else
  167. {
  168. string invalid = "Invalid relay ID.";
  169. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  170. }
  171. }
  172. private void ViewRelay(CommandMessage command)
  173. {
  174. List<Dictionary<string, object>> results = GetRelayList(command.Nick.Nickname);
  175. if (command.Arguments.ContainsKey("ID"))
  176. {
  177. int num = HasValidID(command);
  178. if (num > 0)
  179. {
  180. int relayInt = 0;
  181. Int32.TryParse(results[num - 1]["type"].ToString(), out relayInt);
  182. string relayMessage = string.Format("Relay #\u0002{0}\u0002 - Source: \u0002{1}\u0002 | Target: \u0002{2}\u0002 | Type: \u0002{3}\u0002",
  183. num, results[num - 1]["source"], results[num - 1]["target"], (RelayType)relayInt);
  184. if ((RelayType)relayInt == RelayType.Mode)
  185. {
  186. relayMessage = string.Format("{0} | Modes: \u0002{1}\u0002", relayMessage, results[num - 1]["modes"]);
  187. }
  188. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, relayMessage);
  189. }
  190. else
  191. {
  192. string invalid = "Invalid relay ID.";
  193. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  194. }
  195. }
  196. else
  197. {
  198. if (results.Any())
  199. {
  200. for (int i = 0; i < results.Count; i++)
  201. {
  202. int relayInt = 0;
  203. Int32.TryParse(results[i]["type"].ToString(), out relayInt);
  204. string relayMessage = string.Format("Relay #\u0002{0}\u0002 - Source: \u0002{1}\u0002 | Target: \u0002{2}\u0002 | Type: \u0002{3}\u0002",
  205. i + 1, results[i]["source"], results[i]["target"], (RelayType)relayInt);
  206. if ((RelayType)relayInt == RelayType.Mode)
  207. {
  208. relayMessage = string.Format("{0} | Modes: \u0002{1}\u0002", relayMessage, results[i]["modes"]);
  209. }
  210. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, relayMessage, true);
  211. }
  212. }
  213. else
  214. {
  215. string invalid = "You do not have any relays set.";
  216. SendResponse(command.MessageType, command.Location, command.Nick.Nickname, invalid, true);
  217. }
  218. }
  219. }
  220. private List<Dictionary<string, object>> GetRelayList(string nickname)
  221. {
  222. string search = "SELECT `relays`.`id`, `relays`.`source`, `relays`.`target`, `relays`.`type`, `relays`.`modes` FROM `relays` " +
  223. "INNER JOIN `nicks` " +
  224. "ON `relays`.`nick_id` = `nicks`.`id` " +
  225. "INNER JOIN `servers` " +
  226. "ON `nicks`.`server_id` = `servers`.`id` " +
  227. "WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1}";
  228. return Bot.Database.Query(search, new object[] { Bot.ServerConfig.Name, nickname });
  229. }
  230. private List<Dictionary<string, object>> GetRelayList(string source, RelayType type)
  231. {
  232. string search = "SELECT `relays`.`target`, `relays`.`modes` FROM `relays` " +
  233. "INNER JOIN `servers` " +
  234. "ON `relays`.`server_id` = `servers`.`id` " +
  235. "WHERE `servers`.`name` = {0} AND `relays`.`source` = {1} AND `relays`.`type` = {2}";
  236. return Bot.Database.Query(search, new object[] { Bot.ServerConfig.Name, source, (int)type });
  237. }
  238. private bool CheckAccess(string source, string nick, AccessType access)
  239. {
  240. // Owners get to have all the fun
  241. if (Bot.ServerConfig.Owners.Contains(nick))
  242. return true;
  243. // The source is a channel
  244. if (Bot.IRC.Channels.Exists(chan => chan.Name == source))
  245. {
  246. bool valid = Bot.CheckChannelAccess(source, nick, AccessType.Operator);
  247. if (!valid)
  248. return false;
  249. }
  250. // The source is a nickname
  251. else
  252. {
  253. if (source != nick)
  254. return false;
  255. }
  256. return true;
  257. }
  258. /* Returns the parsed ID field if valid, otherwise returns 0 */
  259. private int HasValidID(CommandMessage command)
  260. {
  261. int num = 0;
  262. int ret = 0;
  263. List<Dictionary<string, object>> results = GetRelayList(command.Nick.Nickname);
  264. if (int.TryParse(command.Arguments["ID"], out num))
  265. {
  266. if (results.Count >= num && num > 0)
  267. {
  268. ret = num;
  269. }
  270. }
  271. return ret;
  272. }
  273. private void ProcessRelay(string source, RelayType type, string message, List<UserModeInfo> userModes = null, List<ChannelModeInfo> channelModes = null)
  274. {
  275. List<Dictionary<string, object>> relays = GetRelayList(source, type);
  276. switch (type)
  277. {
  278. case RelayType.Mode:
  279. for (int i = 0; i < relays.Count; i++)
  280. {
  281. string modeStr = relays[i]["modes"].ToString();
  282. char[] modes = modeStr.ToCharArray();
  283. bool modeFound = false;
  284. foreach (char mode in modes)
  285. {
  286. if (userModes != null)
  287. {
  288. if (userModes.Exists(info => info.Mode.ToString() == mode.ToString()))
  289. {
  290. modeFound = true;
  291. break;
  292. }
  293. }
  294. if (channelModes != null)
  295. {
  296. if (channelModes.Exists(info => info.Mode.ToString() == mode.ToString()))
  297. {
  298. modeFound = true;
  299. break;
  300. }
  301. }
  302. }
  303. if (!modeFound)
  304. {
  305. relays.RemoveAt(i);
  306. i--;
  307. }
  308. }
  309. break;
  310. default:
  311. break;
  312. }
  313. foreach (Dictionary<string, object> relay in relays)
  314. {
  315. string target = relay["target"].ToString();
  316. MessageType msgType = MessageType.Channel;
  317. if (!Channel.IsChannel(target))
  318. msgType = MessageType.Query;
  319. SendResponse(msgType, target, target, message);
  320. }
  321. }
  322. #region Incomming Messages
  323. private void RelayQuit(object sender, QuitInfo e)
  324. {
  325. string msg = string.Format(" * {0} has quit. ({1})", e.Nick.Nickname, e.Message);
  326. ProcessRelay(e.Nick.Nickname, RelayType.Quit, msg);
  327. }
  328. private void RelayTopicChange(object sender, TopicChangeInfo e)
  329. {
  330. string msg = string.Format("[{0}] {1} has changed the topic to: {2}.", e.Channel, e.Nick.Nickname, e.Topic);
  331. ProcessRelay(e.Channel, RelayType.Topic, msg);
  332. }
  333. private void RelayChannelKick(object sender, KickInfo e)
  334. {
  335. string msg = string.Format("[{0}] * {1} has kicked {2} ({3})", e.Channel, e.Nick.Nickname, e.KickedNick.Nickname, e.Reason);
  336. ProcessRelay(e.Channel, RelayType.Kick, msg);
  337. }
  338. private void RelayChannelPart(object sender, PartChannelInfo e)
  339. {
  340. string msg = string.Format("[{0}] * {1} has left.", e.Channel, e.Nick.Nickname);
  341. ProcessRelay(e.Channel, RelayType.Part, msg);
  342. }
  343. private void RelayChannelInvite(object sender, InviteChannelInfo e)
  344. {
  345. string msg = string.Format("[{0}] * {1} invited {2}", e.Channel, e.Requester.Nickname, e.Recipient.Nickname);
  346. ProcessRelay(e.Channel, RelayType.Invite, msg);
  347. }
  348. private void RelayChannelJoin(object sender, JoinChannelInfo e)
  349. {
  350. string msg = string.Format("[{0}] * {1} ({2}) has joined.", e.Channel, e.Nick.Nickname, e.Nick.Host);
  351. ProcessRelay(e.Channel, RelayType.Join, msg);
  352. }
  353. private void RelayUserMode(object sender, UserModeChangeInfo e)
  354. {
  355. string msg = string.Format(" * {0} sets mode {1}", e.Nick.Nickname, e.Modes.ModesToString());
  356. ProcessRelay(e.Nick.Nickname, RelayType.Mode, msg, e.Modes);
  357. }
  358. private void RelayChannelMode(object sender, ChannelModeChangeInfo e)
  359. {
  360. string msg = string.Format("[{0}] * {1} sets mode {2} on {3}.", e.Channel, e.Nick.Nickname, e.Modes.ModesToString(), e.Channel);
  361. ProcessRelay(e.Channel, RelayType.Mode, msg, null, e.Modes);
  362. }
  363. private void RelayPrivateNotice(object sender, PrivateNotice e)
  364. {
  365. string msg = string.Format("[-{0}-] {1}", e.Sender.Nickname, e.Message);
  366. ProcessRelay(e.Sender.Nickname, RelayType.Message, msg);
  367. }
  368. private void RelayChannelNotice(object sender, ChannelNotice e)
  369. {
  370. string msg = string.Format("[{0}] [-{1}-] {2}", e.Channel, e.Sender.Nickname, e.Message);
  371. ProcessRelay(e.Channel, RelayType.Message, msg);
  372. }
  373. private void RelayPrivateMessage(object sender, PrivateMessage e)
  374. {
  375. string msg = string.Format("[{0}] {1}", e.Sender.Nickname, e.Message);
  376. ProcessRelay(e.Sender.Nickname, RelayType.Message, msg);
  377. }
  378. private void RelayChannelMessage(object sender, ChannelMessage e)
  379. {
  380. string msg = string.Format("[{0}] [{1}] {2}", e.Channel, e.Sender.Nickname, e.Message);
  381. ProcessRelay(e.Channel, RelayType.Message, msg);
  382. }
  383. private void CTCPRelayHandler(object sender, CTCPMessage e)
  384. {
  385. string msg = string.Format("[{0}] [CTCP] <{1}> {2}", e.Sender.Nickname, e.Command, e.Arguments);
  386. ProcessRelay(e.Location, RelayType.CTCP, msg);
  387. }
  388. private void RelayNickChange(object sender, NickChangeInfo e)
  389. {
  390. string msg = string.Format(" * {0} is now known as {1}", e.OldNick.Nickname, e.NewNick.Nickname);
  391. ProcessRelay(e.NewNick.Nickname, RelayType.Nick, msg);
  392. }
  393. #endregion
  394. #region Outgoing Commands
  395. private void RelayPrivateNoticeCommand(object sender, PrivateNoticeCommand e)
  396. {
  397. string msg = string.Format("[-{0}-] {1}", Bot.IRC.Nickname, e.Message);
  398. ProcessRelay(e.Recipient, RelayType.Message, msg);
  399. }
  400. private void RelayPrivateMessageCommand(object sender, PrivateMessageCommand e)
  401. {
  402. string msg = string.Format("[{0}] {1}", Bot.IRC.Nickname, e.Message);
  403. //ProcessRelay(e.Recipient, RelayType.Message, msg);
  404. }
  405. private void RelayUserModeCommand(object sender, UserModeCommand e)
  406. {
  407. string msg = string.Format(" * {0} sets mode {1}", e.Nick, e.Mode.ModeToString());
  408. ProcessRelay(e.Nick, RelayType.Mode, msg, new List<UserModeInfo> { e.Mode });
  409. }
  410. private void RelayChannelModeCommand(object sender, ChannelModeCommand e)
  411. {
  412. string msg = string.Format("[{0}] * {1} sets mode {2} on {3}.", e.Channel, Bot.IRC.Nickname, e.Mode.ModeToString(), e.Channel);
  413. ProcessRelay(e.Channel, RelayType.Mode, msg, null, new List<ChannelModeInfo> { e.Mode });
  414. }
  415. private void RelayCTCPNoticeCommand(object sender, CTCPNoticeCommand e)
  416. {
  417. string msg = string.Format("[-{0}-] [CTCP] <{1}> {2}", Bot.IRC.Nickname, e.Command, e.Arguments);
  418. ProcessRelay(e.Recipient, RelayType.CTCP, msg);
  419. }
  420. private void RelayCTCPMessageCommand(object sender, CTCPMessageCommand e)
  421. {
  422. string msg = string.Format("[{0}] [CTCP] <{1}> {2}", Bot.IRC.Nickname, e.Command, e.Arguments);
  423. ProcessRelay(e.Recipient, RelayType.CTCP, msg);
  424. }
  425. private void RelayNickCommand(object sender, NickCommand e)
  426. {
  427. string msg = string.Format(" * {0} is now known as {1}", Bot.IRC.Nickname, e.Nick);
  428. ProcessRelay(Bot.IRC.Nickname, RelayType.Nick, msg);
  429. }
  430. private void RelayJoinCommand(object sender, JoinCommand e)
  431. {
  432. string msg = string.Format("[{0}] * {1} has joined.", e.Channel, Bot.IRC.Nickname);
  433. ProcessRelay(e.Channel, RelayType.Join, msg);
  434. }
  435. private void RelayTopicCommand(object sender, TopicCommand e)
  436. {
  437. string msg = string.Format("[{0}] {1} has changed the topic to: {2}.", e.Channel, Bot.IRC.Nickname, e.Topic);
  438. ProcessRelay(e.Channel, RelayType.Topic, msg);
  439. }
  440. private void RelayPartCommand(object sender, PartCommand e)
  441. {
  442. string msg = string.Format("[{0}] * {1} has left.", e.Channel, Bot.IRC.Nickname);
  443. ProcessRelay(e.Channel, RelayType.Part, msg);
  444. }
  445. private void RelayKickCommand(object sender, KickCommand e)
  446. {
  447. string msg = string.Format("[{0}] * {1} has kicked {2} ({3})", e.Channel, Bot.IRC.Nickname, e.Nick, e.Reason);
  448. ProcessRelay(e.Channel, RelayType.Kick, msg);
  449. }
  450. private void RelayInviteCommand(object sender, InviteCommand e)
  451. {
  452. string msg = string.Format("[{0}] * {1} invited {2}", e.Channel, Bot.IRC.Nickname, e.Nick);
  453. ProcessRelay(e.Channel, RelayType.Invite, msg);
  454. }
  455. #endregion
  456. }
  457. }