public override void Execute(IrcMessage message, string args) { string hostmask = args.Trim(); if(hostmask.Contains(" ")) { throw new Exception("No name or hostmask was specified"); } if(!hostmask.Contains("!") || !hostmask.Contains("@")) { string name = hostmask; HostMask mask = BanSystem.FindBanByNick(name); #if QNETBOT if(mask == null) { throw new Exception("Name '" + name + "' was not found, check spelling or specify hostmask"); } #elif JTVBOT if (mask == null) mask = new HostMask(name); #endif hostmask = mask.Mask; } #if JTVBOT BanSystem.PerformUnban(hostmask, false); #elif QNETBOT BanSystem.PerformUnban(hostmask); #endif }
/// <summary> /// Checks if the provided host mask matches this hostmask /// </summary> /// <param name="mask">The host mask to check</param> /// <returns>True if the masks match</returns> public bool Matches(HostMask mask) { if (regex == null) { string pattern = "^"; foreach (char c in Mask) { if (char.IsLetterOrDigit(c)) pattern += c; else if (c == '*') pattern += ".*?"; else pattern += "\\" + c; } pattern += "$"; regex = new Regex(pattern, RegexOptions.IgnoreCase); } return regex.Match(mask.Mask).Success; }
/// <summary> /// Performs a ban /// </summary> /// <param name="hostmask">The mask to ban</param> /// <param name="duration_or_null">The duration, or null</param> /// <param name="reason">The reason for the ban</param> /// <param name="by">The user who set the ban</param> public static void PerformBan(string hostmask, string duration_or_null, string reason, string by) { lock (State.GlobalSync) { if (state != BanSystemState.Synchronized) throw new Exception("Bad state"); if (State.UseQEnforce.Value && CanQBan()) { //if we use Q enforcement, queue a Q command if (duration_or_null == null) new PermBanCommand(hostmask, reason); else new TempBanCommand(hostmask, duration_or_null, reason); } else { //hostmask HostMask mask = new HostMask(hostmask); //add to list Ban ban = new Ban(); TimeSpan actual_duration = duration_or_null == null ? TimeSpan.FromSeconds(0) : ParseDuration(duration_or_null); ban.Expires = duration_or_null == null ? DateTime.MaxValue : DateTime.UtcNow + actual_duration; ban.Enforcer = BanEnforcement.ByMe; ban.Affected = GetAffectedNicks(mask); ban.Mask = mask; ban.Reason = reason; ban.SetBy = by; //check if a longer ban already in place Ban existing = State.BanList.Lookup(ban.Mask.Mask); if (existing != null && existing.Expires > ban.Expires) { throw new Exception("A ban with a longer duration is already in place"); } //add to banlist if (existing != null) State.BanList.Remove(existing); State.BanList.Add(ban); //ban from channel if (!CanChannelBan() && FreeBanSlot(1) == 0) { foreach (User user in State.UserList.GetItems()) { if (user.Left == DateTime.MaxValue && mask.Matches(user.HostMask)) { //kick from channel Irc.Kick(user.Nick, "Enforcing ban: " + reason); } } } else { Irc.Ban(hostmask); if (State.UseQuietBan.Value == false || duration_or_null == null) { foreach (User user in State.UserList.GetItems()) { if (user.Left == DateTime.MaxValue && mask.Matches(user.HostMask)) { //kick from channel Irc.Kick(user.Nick, "Enforcing ban: " + reason); } } } else { //put channel message Irc.SendChannelMessage(GetAffectedNicks(mask) + " has been timed out from chatting for " + ((int)(actual_duration.TotalMinutes + 0.5)).ToString() + " minutes: " + reason, false); } } } } }
/// <summary> /// Gets a user-friendly display of nicknames affected by a ban /// </summary> /// <param name="banmask">The banmask being searched</param> /// <returns>User-friendly string</returns> public static string GetAffectedNicks(HostMask banmask) { lock (State.GlobalSync) { string result = null; foreach (User user in State.UserList.GetItems()) { if (banmask.Matches(user.HostMask)) result = (result == null ? user.Nick : result + ", " + user.Nick); } return result == null ? "" : result; } }
/// <summary> /// Called when a user leaves IRC (by PART, KICK or QUIT) /// </summary> /// <param name="mask">The hostmask of the user</param> public static void OnIrcLeave(HostMask mask) { //consider removing a ban here? }
/// <summary> /// Called when someone enters IRC (by JOIN or WHO) /// </summary> /// <param name="mask">The hostmask of the user</param> /// <param name="nick">The nickname of the user</param> public static void OnIrcEnter(HostMask mask, string nick) { lock (State.GlobalSync) { foreach (Ban ban in State.BanList.GetItems()) { if (ban.Enforcer == BanEnforcement.ByMe && ban.Mask.Matches(mask)) { if (!CanChannelBan() && FreeBanSlot(1) == 0) { Irc.Kick(nick, "Enforcing ban: " + ban.Reason); } else if (ban.Expires == DateTime.MaxValue || State.UseQuietBan.Value == false) { Irc.Kick(nick, "Enforcing ban: " + ban.Reason); Irc.Ban(ban.Mask.Mask); } else { Irc.Ban(ban.Mask.Mask); } return; } } } }
/// <summary> /// Looks for the banmask with which a user was banned /// </summary> /// <returns>The host mask with which the user was banned, or null, if not found</returns> public static HostMask FindBanByNick(string nick) { lock (State.GlobalSync) { HostMask tofind = new HostMask(nick); return State.BanList.Lookup(tofind.Mask) == null ? null : tofind; } }
/// <summary> /// Check if user banned /// </summary> /// <param name="nick">Person who spoke</param> /// <returns>True if banned</returns> public static bool OnIrcChannelMessage(string nick) { lock (State.GlobalSync) { HostMask mask = new HostMask(nick); Ban ban = State.BanList.Lookup(mask.Mask); if (ban == null || ban.Expires < DateTime.UtcNow || ban.Expires == DateTime.MaxValue || ban.Enforcer != BanEnforcement.ByJtv) return false; Irc.Kick(nick, ""); TimeSpan remaining = (ban.Expires - DateTime.UtcNow).Duration(); double seconds = remaining.TotalSeconds; string time = seconds < 100.0 ? ((int)seconds).ToString() + " seconds" : ((int)(seconds / 60.0 + 0.5)).ToString() + " minutes"; Irc.SendChannelMessage(nick + ", you are still banned for " + time + ": " + ban.Reason, false); return true; } }