protected virtual void HandleChannelMessageOrAction(object sender, IChannelMessageEventArgs e, MessageFlags flags) { BounceCriterion crit = InterestingCriterion(e.SenderNickname, channel: null); if (crit != null && crit.ForgetOnChannelMessage) { RelevantJoins.RemoveAll(j => j.Nickname == e.SenderNickname); } }
protected virtual void HandleUserJoin(object sender, IUserJoinedChannelEventArgs e) { BounceCriterion criterion = InterestingCriterion(e.Nickname, e.Channel); if (criterion == null) { return; } // are hours set? if (criterion.StartingHour.HasValue && criterion.EndingHour.HasValue) { HandleHourCriterion(e.Channel, e.Nickname, criterion); } else { HandleStandardCriterion(e.Channel, e.Nickname, criterion); } }
protected virtual bool CheckAndDebounce(string channel, string nickname, BounceCriterion criterion, DateTimeOffset now) { // clear out all entries older than the time slice DateTimeOffset sliceStart = now.AddMinutes(-criterion.TimeSliceMinutes); RelevantJoins.RemoveAll(j => j.Timestamp < sliceStart); // how many are left? int count = RelevantJoins.Count(j => j.Nickname == nickname && j.Channel == channel); if (count < criterion.MaxJoinsQuitsInTimeSlice) { return(false); } // kickban! string message = (criterion.KickMessages.Count > 0) ? criterion.KickMessages[RNG.Next(criterion.KickMessages.Count)] : null; ConnectionManager.ChangeChannelMode(channel, $"+b {nickname}!*@*"); ConnectionManager.KickChannelUser(channel, nickname, message); return(true); }
protected virtual void HandleHourCriterion(string channel, string nickname, BounceCriterion criterion) { // find the starting hour relative to today DateTimeOffset now = DateTimeOffset.Now; DateTimeOffset today = new DateTimeOffset(now.Date, now.Offset); DateTimeOffset todayStart = today.AddHours(criterion.StartingHour.Value); DateTimeOffset todayEnd = today.AddHours(criterion.EndingHour.Value); if (todayEnd == todayStart) { // no time range return; } DateTimeOffset cutoff = (now >= todayStart) ? todayStart : todayStart.AddDays(-1); DateTimeOffset currentEnd; bool isActive; if (todayEnd > todayStart) { // daytime hours isActive = (now >= todayStart && now < todayEnd); currentEnd = todayEnd; } else { Debug.Assert(todayEnd < todayStart); // overnight hours if (now < todayEnd) { isActive = true; currentEnd = todayEnd; } else if (now >= todayStart) { isActive = true; currentEnd = todayEnd.AddDays(1); } else { isActive = false; } } if (!isActive) { // the entries are not interesting anymore RelevantJoins.Clear(); return; } // add this join RelevantJoins.Add(new JoinQuitEvent(channel, nickname, now)); // check if the criterion is fulfilled if (CheckAndDebounce(channel, nickname, criterion, now)) { // unban at the end time ConnectionManager.Timers.Register(currentEnd, () => Unban(channel, nickname)); } }
protected virtual void HandleStandardCriterion(string channel, string nickname, BounceCriterion criterion) { // add this join DateTimeOffset now = DateTimeOffset.Now; RelevantJoins.Add(new JoinQuitEvent(channel, nickname, now)); // calculate unban time DateTimeOffset unbanTimestamp = now.AddMinutes(criterion.BanDurationMinutes.Value); // check if the criterion is fulfilled if (CheckAndDebounce(channel, nickname, criterion, now)) { // unban after the set duration ConnectionManager.Timers.Register(unbanTimestamp, () => Unban(channel, nickname)); } }