The easy to use and full featured Irc Bot everyone is talking about!
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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. }