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.

Relay.cs 24KB

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