The easy to use and full featured Irc Bot everyone is talking about!
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

Spam_Control.cs 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text.RegularExpressions;
  5. using System.Threading;
  6. using Combot.IRCServices;
  7. using Combot.IRCServices.Messaging;
  8. namespace Combot.Modules.Plugins
  9. {
  10. public class Spam_Control : Module
  11. {
  12. private List<SpamMessageInfo> SpamMessageList;
  13. private List<SpamHighlightInfo> SpamHighlightList;
  14. private ReaderWriterLockSlim SpamMessageLock;
  15. private ReaderWriterLockSlim SpamHighlightLock;
  16. private List<System.Timers.Timer> unbanTimers;
  17. private ReaderWriterLockSlim unbanLock;
  18. private List<System.Timers.Timer> devoiceTimers;
  19. private ReaderWriterLockSlim devoiceLock;
  20. public override void Initialize()
  21. {
  22. unbanTimers = new List<System.Timers.Timer>();
  23. unbanLock = new ReaderWriterLockSlim();
  24. devoiceTimers = new List<System.Timers.Timer>();
  25. devoiceLock = new ReaderWriterLockSlim();
  26. SpamMessageList = new List<SpamMessageInfo>();
  27. SpamHighlightList = new List<SpamHighlightInfo>();
  28. SpamMessageLock = new ReaderWriterLockSlim();
  29. SpamHighlightLock = new ReaderWriterLockSlim();
  30. Bot.IRC.Message.ChannelMessageReceivedEvent += HandleChannelMessage;
  31. }
  32. private void HandleChannelMessage(object sender, ChannelMessage message)
  33. {
  34. if (Enabled && !ChannelBlacklist.Contains(message.Channel) && !NickBlacklist.Contains(message.Sender.Nickname))
  35. {
  36. CheckFlood(message);
  37. CheckHighlight(message);
  38. }
  39. }
  40. private void CheckFlood(ChannelMessage message)
  41. {
  42. int timeThreshold = Convert.ToInt32(GetOptionValue("Time Threshold"));
  43. int maxMessages = Convert.ToInt32(GetOptionValue("Max Messages"));
  44. int devoiceTime = Convert.ToInt32(GetOptionValue("Devoice Time"));
  45. int unbanTime = Convert.ToInt32(GetOptionValue("Unban Time"));
  46. bool voiceResponse = Convert.ToBoolean(GetOptionValue("Voice Response"));
  47. bool kickResponse = Convert.ToBoolean(GetOptionValue("Kick Response"));
  48. bool banResponse = Convert.ToBoolean(GetOptionValue("Ban Response"));
  49. bool unbanResponse = Convert.ToBoolean(GetOptionValue("Unban Response"));
  50. // Check for line spam
  51. if (SpamMessageList.Exists(msg => msg.Channel == message.Channel && msg.Nick == message.Sender.Nickname))
  52. {
  53. SpamMessageLock.EnterReadLock();
  54. SpamMessageInfo info = SpamMessageList.Find(msg => msg.Channel == message.Channel && msg.Nick == message.Sender.Nickname);
  55. SpamMessageLock.ExitReadLock();
  56. TimeSpan difference = message.TimeStamp.Subtract(info.FirstMessageTime);
  57. if (difference.TotalMilliseconds < timeThreshold)
  58. {
  59. info.Lines++;
  60. if (info.Lines > maxMessages)
  61. {
  62. if (voiceResponse)
  63. {
  64. TimedDeVoice(message, devoiceTime);
  65. }
  66. if (kickResponse)
  67. {
  68. Bot.IRC.Command.SendKick(info.Channel, info.Nick, string.Format("Please do not spam. You have messaged {0} times within {1}ms.", info.Lines, timeThreshold));
  69. }
  70. if (banResponse)
  71. {
  72. if (unbanResponse)
  73. {
  74. TimedBan(message, unbanTime);
  75. }
  76. else
  77. {
  78. BanNick(true, message);
  79. }
  80. }
  81. if (!kickResponse)
  82. {
  83. string spamMessage = string.Format("Please do not spam. You have messaged {0} times within {1}ms.", info.Lines, timeThreshold);
  84. SendResponse(MessageType.Channel, message.Channel, message.Sender.Nickname, spamMessage);
  85. }
  86. SpamMessageLock.EnterWriteLock();
  87. SpamMessageList.Remove(info);
  88. SpamMessageLock.ExitWriteLock();
  89. }
  90. }
  91. else
  92. {
  93. SpamMessageLock.EnterWriteLock();
  94. info.Lines = 1;
  95. info.FirstMessageTime = message.TimeStamp;
  96. SpamMessageLock.ExitWriteLock();
  97. }
  98. }
  99. else
  100. {
  101. SpamMessageInfo info = new SpamMessageInfo();
  102. info.Channel = message.Channel;
  103. info.Nick = message.Sender.Nickname;
  104. info.Lines = 1;
  105. info.FirstMessageTime = message.TimeStamp;
  106. SpamMessageLock.EnterWriteLock();
  107. SpamMessageList.Add(info);
  108. SpamMessageLock.ExitWriteLock();
  109. }
  110. }
  111. private void CheckHighlight(ChannelMessage message)
  112. {
  113. int timeThreshold = Convert.ToInt32(GetOptionValue("Time Threshold"));
  114. int maxHighlights = Convert.ToInt32(GetOptionValue("Max Highlights"));
  115. int devoiceTime = Convert.ToInt32(GetOptionValue("Devoice Time"));
  116. int unbanTime = Convert.ToInt32(GetOptionValue("Unban Time"));
  117. bool voiceResponse = Convert.ToBoolean(GetOptionValue("Voice Response"));
  118. bool kickResponse = Convert.ToBoolean(GetOptionValue("Kick Response"));
  119. bool banResponse = Convert.ToBoolean(GetOptionValue("Ban Response"));
  120. bool unbanResponse = Convert.ToBoolean(GetOptionValue("Unban Response"));
  121. // Check for highlight spam
  122. Regex regEx = new Regex(@"[^a-zA-Z0-9_\-\[\]`\^|\\]");
  123. string cleanMessage = regEx.Replace(message.Message, " ");
  124. List<string> splitMessage = cleanMessage.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList();
  125. Channel channel = Bot.IRC.Channels.Find(chan => chan.Name == message.Channel);
  126. if (channel != null)
  127. {
  128. List<string> foundNicks = splitMessage.FindAll(msg => channel.Nicks.Exists(nick => msg.Equals(nick.Nickname, StringComparison.InvariantCultureIgnoreCase)));
  129. if (foundNicks.Any())
  130. {
  131. if (!SpamHighlightList.Exists(msg => msg.Channel == message.Channel && msg.Nick == message.Sender.Nickname))
  132. {
  133. SpamHighlightInfo newInfo = new SpamHighlightInfo();
  134. newInfo.Channel = message.Channel;
  135. newInfo.Nick = message.Sender.Nickname;
  136. newInfo.Highlights = 0;
  137. newInfo.FirstHighlightTime = message.TimeStamp;
  138. SpamHighlightLock.EnterWriteLock();
  139. SpamHighlightList.Add(newInfo);
  140. SpamHighlightLock.ExitWriteLock();
  141. }
  142. SpamHighlightLock.EnterReadLock();
  143. SpamHighlightInfo info = SpamHighlightList.Find(highlight => highlight.Channel == message.Channel && highlight.Nick == message.Sender.Nickname);
  144. SpamHighlightLock.ExitReadLock();
  145. TimeSpan difference = message.TimeStamp.Subtract(info.FirstHighlightTime);
  146. if (difference.TotalMilliseconds < timeThreshold)
  147. {
  148. info.Highlights += foundNicks.Count;
  149. if (info.Highlights > maxHighlights)
  150. {
  151. if (voiceResponse)
  152. {
  153. TimedDeVoice(message, devoiceTime);
  154. }
  155. if (kickResponse)
  156. {
  157. Bot.IRC.Command.SendKick(info.Channel, info.Nick, string.Format("Please do not highlight spam. You have highlighted {0} nicks within {1}ms.", info.Highlights, timeThreshold));
  158. }
  159. if (banResponse)
  160. {
  161. if (unbanResponse)
  162. {
  163. TimedBan(message, unbanTime);
  164. }
  165. else
  166. {
  167. BanNick(true, message);
  168. }
  169. }
  170. if (!kickResponse)
  171. {
  172. string spamMessage = string.Format("Please do not highlight spam. You have highlighted {0} nicks within {1}ms.", info.Highlights, timeThreshold);
  173. SendResponse(MessageType.Channel, message.Channel, message.Sender.Nickname, spamMessage);
  174. }
  175. SpamHighlightLock.EnterWriteLock();
  176. SpamHighlightList.Remove(info);
  177. SpamHighlightLock.ExitWriteLock();
  178. }
  179. }
  180. else
  181. {
  182. SpamHighlightLock.EnterWriteLock();
  183. info.Highlights = foundNicks.Count;
  184. info.FirstHighlightTime = message.TimeStamp;
  185. SpamHighlightLock.ExitWriteLock();
  186. }
  187. }
  188. }
  189. }
  190. private void TimedDeVoice(ChannelMessage message, int timeout)
  191. {
  192. SetMode(false, message.Channel, ChannelMode.v, message.Sender.Nickname);
  193. System.Timers.Timer devoiceTrigger = new System.Timers.Timer();
  194. devoiceTrigger.Interval = (timeout * 1000.0);
  195. devoiceTrigger.Enabled = true;
  196. devoiceTrigger.AutoReset = false;
  197. devoiceTrigger.Elapsed += (sender, e) => TimedVoice(sender, e, message);
  198. devoiceLock.EnterWriteLock();
  199. devoiceTimers.Add(devoiceTrigger);
  200. devoiceLock.ExitWriteLock();
  201. }
  202. private void TimedVoice(object sender, EventArgs e, ChannelMessage message)
  203. {
  204. System.Timers.Timer devoiceTimer = (System.Timers.Timer)sender;
  205. devoiceTimer.Enabled = false;
  206. SetMode(true, message.Channel, ChannelMode.v, message.Sender.Nickname);
  207. devoiceLock.EnterWriteLock();
  208. devoiceTimers.Remove(devoiceTimer);
  209. devoiceLock.ExitWriteLock();
  210. }
  211. private void TimedBan(ChannelMessage message, int timeout)
  212. {
  213. BanNick(true, message);
  214. System.Timers.Timer unban_trigger = new System.Timers.Timer();
  215. unban_trigger.Interval = (timeout * 1000.0);
  216. unban_trigger.Enabled = true;
  217. unban_trigger.AutoReset = false;
  218. unban_trigger.Elapsed += (sender, e) => TimedUnBan(sender, e, message);
  219. unbanLock.EnterWriteLock();
  220. unbanTimers.Add(unban_trigger);
  221. unbanLock.ExitWriteLock();
  222. }
  223. private void TimedUnBan(object sender, EventArgs e, ChannelMessage message)
  224. {
  225. System.Timers.Timer unbanTimer = (System.Timers.Timer)sender;
  226. unbanTimer.Enabled = false;
  227. BanNick(false, message);
  228. unbanLock.EnterWriteLock();
  229. unbanTimers.Remove(unbanTimer);
  230. unbanLock.ExitWriteLock();
  231. }
  232. private void BanNick(bool set, ChannelMessage message)
  233. {
  234. string banMask = message.Sender.Nickname;
  235. if (!banMask.Contains("@") || !banMask.Contains("!"))
  236. {
  237. string search = "SELECT `nickinfo`.`username`, `nickinfo`.`host`, `nicks`.`nickname` FROM `nickinfo` " +
  238. "INNER JOIN `nicks` " +
  239. "ON `nickinfo`.`nick_id` = `nicks`.`id` " +
  240. "INNER JOIN `servers` " +
  241. "ON `nicks`.`server_id` = `servers`.`id` " +
  242. "WHERE `servers`.`name` = {0} AND `nicks`.`nickname` = {1}";
  243. List<Dictionary<string, object>> results = Bot.Database.Query(search, new object[] {Bot.ServerConfig.Name, banMask});
  244. if (results.Any())
  245. {
  246. List<string> banMasks = new List<string>();
  247. foreach (Dictionary<string, object> result in results)
  248. {
  249. var nickname = result["nickname"].ToString();
  250. var host = result["host"].ToString();
  251. var username = result["username"].ToString();
  252. if (!string.IsNullOrEmpty(host) && !string.IsNullOrEmpty(username))
  253. {
  254. banMask = string.Format("*!*{0}@{1}", username, host);
  255. }
  256. else if (!string.IsNullOrEmpty(host))
  257. {
  258. banMask = string.Format("*!*@{0}", host);
  259. }
  260. else if (!string.IsNullOrEmpty(username))
  261. {
  262. banMask = string.Format("{0}!*{1}@*", nickname, username);
  263. }
  264. else
  265. {
  266. banMask = string.Format("{0}!*@*", nickname);
  267. }
  268. banMasks.Add(banMask);
  269. }
  270. SetMode(set, message.Channel, ChannelMode.b, banMasks);
  271. }
  272. else
  273. {
  274. SetMode(set, message.Channel, ChannelMode.b, string.Format("{0}!*@*", banMask));
  275. }
  276. }
  277. }
  278. private void SetMode(bool set, string channel, ChannelMode mode, string nickname)
  279. {
  280. ChannelModeInfo modeInfo = new ChannelModeInfo();
  281. modeInfo.Mode = mode;
  282. modeInfo.Parameter = nickname;
  283. modeInfo.Set = set;
  284. Bot.IRC.Command.SendMode(channel, modeInfo);
  285. }
  286. private void SetMode(bool set, string channel, ChannelMode mode, List<string> nicknames)
  287. {
  288. List<ChannelModeInfo> modeInfos = new List<ChannelModeInfo>();
  289. foreach (var nickname in nicknames)
  290. {
  291. ChannelModeInfo modeInfo = new ChannelModeInfo();
  292. modeInfo.Mode = mode;
  293. modeInfo.Parameter = nickname;
  294. modeInfo.Set = set;
  295. modeInfos.Add(modeInfo);
  296. }
  297. Bot.IRC.Command.SendMode(channel, modeInfos);
  298. }
  299. }
  300. }