This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Idle Whois

Requests for complete scripts or modifications/fixes for scripts you didn't write. Response not guaranteed, and no thread bumping!
Post Reply
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Idle Whois

Post by MrBeta »

There is an idle tcl that kick / ban you taking the time to whois?
I do not find a tcl that every 10/15 minutes to do a whois to the user and if exceeds 90 minutes of inactivity in the public and private give the kick/ban.
I look for an antidle that makes a Whois to the user verifying how long it really is inactive, many antiidle do not detect that a person can be in PVT. I have no connection problem from multiple servers since certain clients connect only to a server
Last edited by MrBeta on Wed Apr 07, 2021 6:06 am, edited 1 time in total.
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

check the tcl archive i saw several there

http://www.egghelp.org/tclhtml/3478-4-0-0-1-idle.htm
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

I have search but no one perform a whois for see the real idle time, i don't want kick or ban people to talk in private but only who is inactive.
More tcl work on idle of the user in the public channel because in all irc network with many server is impossible to see the idle time if the user isn't in the same server of the bot.
I search for a tcl that not ban for mistake the user and perform a real user's whois in the same server
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Most, if not all, use the get the idle time from the channel aka getchanidle, but this like you also mentioned doesn't mean that person isn't active in another channel or talks with someone in PM.

Unless the bot has ircop privileges you have no other way but rely on getchanidle and filter out the members that didn't get over the defined limit and whois only those that did.

Will get back to this in the morning with something for you to test. Now going to bed. :roll:
Once the game is over, the king and the pawn go back in the same box.
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

Thank you very much caesar :wink:
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

been a bit busy with work yesterday and didn't get to finish the code as I wanted so done it today. :)

Code: Select all

namespace eval idleBan {

	# Default idle time in minutes
	set idle(idle_default) 30
	
	# Delay in seconds between WHOIS commands so the bot won't flood itself off
	set idle(whois_delay) 3

	# kick reason for beeing idle in the channel
	set idle(reason) "Don't be idle in %channel channel please, %duration minutes ban."
	
	# Ban type: 1 - channel ban, 2 - ban in it's internal bans list (newchanban)
	set idle(ban_type) 1
	
	# Ban lifetime (if above is set to 2) in minutes. If set to 0 will be permanent.
	set idle(ban_lifetime) 60

	# Don't edit past this line unless you know what you are doing!

	setudef flag idleban
	setudef int idletime

	bind cron - {?0*} [namespace current]::idle:cron
	bind raw - 317 [namespace current]::idle:raw
	bind part - * [namespace current]::idle:del
	bind sign - * [namespace current]::idle:del
	bind nick - * [namespace current]::idle:nick
	bind kick - * [namespace current]::idle:kick

	proc idle:cron {min hour day month weekday} {
		variable idle
		foreach channel [channels] {
			if {![channel get $channel idleban]} continue
			if {![botisop $channel]} continue
			set idletime [channel get $channel idletime]
			if {!$idletime} {
				channel set idletime $idle(default)
			}
			set channel [string tolower $channel]
			foreach member [chanlist $channel] {
				if {[isbotnick $member]} continue
				if {[isop $member $channel]} continue
				if {[isvoice $member $channel]} continue
				set handle [nick2hand $member $channel]
				if {[matchattr $handle f|f]} continue
				set chanidle [getchanidle $member $channel]
				if {$chanidle >= $idletime} {
					variable check
					if {![onchan $member $channel]} return
					set pos -1
					if {[info exists check($channel)]} {
						set pos [idle:pos $member $check($channel)]
					}
					if {$pos == -1} {
						lappend check($channel) $member
					}
					utimer $idle(whois_delay) [list puthelp "WHOIS $member $member"]
				}
			}
		}
	}

	proc idle:raw {from key text} {
		variable check
		if {![info exists check]} return
		if {[scan [lrange $text 1 2] {%s%d} member seconds] != 2} return
		foreach channel [channels] {
			if {![channel get $channel idleban] || ![botisop $channel]} {
				idle:action channel $channel
				continue
			}
			set idletime [channel get $channel idletime]
			set idle [expr $seconds / 60]
			if {$idle < $idletime} {
				idle:action member $channel $member
			} else {
				idle:punish $channel $member $idle
			}
		}
	}

	proc idle:del {nick uhost hand channel {text ""}} {
		if {[channel get $channel idleban]} {
			if {[isbotnick $nick]} {
				idle:action channel $channel
			} else {
				idle:action member $channel $nick
			}
		}
	}

	proc idle:nick {nick uhost hand channel newnick} {
		if {[isbotnick $nick]} return
		if {[channel get $channel idleban]} {
			idle:action nick $channel $nick $newnick
		}
	}

	proc idle:kick {nick uhost hand channel vict reason} {
		if {[channel get $channel idleban]} {
			if {[isbotnick $vict]} {
				idle:action channel $channel
			} else {
				idle:action member $channel $vict
			}
		}
	}

	proc idle:action {act channel {member ""} {newnick ""}} {
		variable check
		set channel [string tolower $channel]
		if {![info exists check($channel)]} return
		switch -- $act {
			default {
				return
			}
			"member" {
				set pos [idle:pos $member [join $check($channel)]]
				if {$pos != -1} {
					set check($channel) [lreplace $check($channel) $pos $pos]
				}
			}
			"channel" {
				if {[info exists check($channel)]} {
					unset check($channel)
				}
			}
			"nick" {
				set pos [idle:pos $member [join $check($channel)]]
				if {$pos != -1} {
					set check($channel) [lreplace $check($channel) $pos $pos $newnick]
				}
			}
		}
	}

	proc idle:getChannels {member} {
		variable check
		set matched ""
		foreach channel [channels] {
			if {![channel get $channel idleban] || ![botisop $channel]} {
				idle:action channel $channel
				continue
			}
			foreach member [join $check($channel)] {
				if {![onchan $member $channel]} {
					idle:action member $channel $member
				}
				if {[string equal -nocase $nick $member]} {
					lappend matched $channel
				}
			}
		}
		return $matched
	}

	proc idle:punish {channels member idle} {
		variable check
		foreach channel [join $channels] {
			if {![channel get $channel idleban] || ![botisop $channel]} {
				idle:action channel $channel
			} else {
				if {[onchan $member $channel]} {
					scan [getchanhost $member $channel] {%*[^@]@%s} host
					set mask "*!*@$host"
				}
				idle:action member $channel $member
				idle:stack $channel $member $mask
				idle:check $channel
			}
		}
	}

	proc idle:stack {channel member mask} {
		variable kicks
		variable bans
		set channel [string tolower $channel]
		set pos -1
		if {[info exists kicks($channel)]} {
			set pos [idle:pos $member $kicks($channel)]
		}
		if {$pos == -1} {
			lappend kicks($channel) $member
		} else {
			set pos -1
		}
		if {[info exists bans($channel)]} {
			set pos [idle:pos $mask $bans($channel)]
		}
		if {$pos == -1} {
			lappend bans($channel) $mask
		}
	}

	proc idle:pos {needle haystack} {
		set count -1
		set match 0
		foreach element [join $haystack] {
			incr count
			if {[string equal -nocase $needle $element]} {
				set match 1
				break
			}
		}
		return "[expr $match>0?$count:"-1"]"
	}

	proc idle:check {channel} {
		variable check
		if {[info exists check($channel)]} {
			set len [llength [join $check($channel)]]
			if {$len} {
				utimer 3 [list [namespace current]::idle:action check $channel]
			} else {
				if {[botisop $channel]} {
					variable bans
					if {[info exists bans($channel)]} {
						idle:stackBans $channel $bans($channel)
					}
					unset bans($channel)
					variable kicks
					if {[info exists kicks($channel)]} {
						idle:stackKicks $channel $kicks($channel)
					}
					unset kicks($channel)
				}
			}
		}
	}

	proc idle:stackBans {channel banlist {max 6}} {
		variable idle
		set len [llength $banlist]
		while {$len > 0} {
			if {$len > $max} {
			set mode [string repeat "b" $max]
			set masks [join [lrange $banlist 0 [expr {$max - 1}]]]
			set banlist [lrange $banlist $max end]
			incr len -$max
			} else {
				set mode [string repeat "b" $len]
				set masks [join $banlist]
				incr len -$len
			}
			pushmode $channel +$mode $masks
			if {$idle(ban_type) == 2} {
				idle:newbans $channel $masks
			}
		}
	}
	
	proc idle:newbans {channel banlist} {
		variable idle
		foreach mask [join $banlist] {
			set reason [string map [list "%channel" "$channel" "%duration" "$idle(ban_lifetime)"] $idle(reason)]
			newchanban $channel $mask "Anti-Idle" $reason $idle(ban_lifetime)
		}
	}

	proc idle:stackKicks {channel kicklist {max 6}} {
		variable idle
		set len [llength $kicklist]
		while {$len > 0} {
			if {$len > $max} {
				set stack [join [lrange $kicklist 0 [expr {$max - 1}]]]
				set kicklist [lrange $kicklist $max end]
			} else {
				set stack [join $kicklist]
				incr len -$len
			}
			set reason [string map [list "%channel" "$channel" "%duration" "$idle(ban_lifetime)"] $idle(reason)]
			putkick [join $stack ","] $reason
		}
	}
}
I did some testings and should do what you want if I got it right.

The bot will do a idle check every 10 minutes and if a member is idle in the channel for more than the specified amount of minutes will do a whois. Depending on how many members had to be whois-ed the bot will wait until the list is empty and then proceed with the punishment.

This works for all channels that are set to +idleban (.chanset #channel +idleban from DCC Chat/Telnet with the bot). Be sure to set the idletime (.chanset #channel idletime <minutes> from DCC Chat/Telnet with the bot) else the default (30 minutes as I left it) will be set and used.

Load this on a test bot and see if things go as planned and reply back if you encounter any problems/issues.

Edit: I used pushmode and putkick that are using slow queues and it's better from my point of view, but I guess you can replace those with a faster queue system if it's badly needed.

I've extended this so much that I didn't think about all the features it should have so right now this misses two features that I'm working on:
- purge bans that are in the idle bans list upon outside ban settings
- purge nicks that are in the idle kicks list upon: nick change, kick, part and quit.

Will update this soon. :)
Last edited by caesar on Wed Apr 06, 2016 8:24 am, edited 1 time in total.
Once the game is over, the king and the pawn go back in the same box.
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

Great! If I may add another request is to not make whois for op that often are other eggy, exclude the ban and whois for operators, users who has certain flag on the bot
I test it in the evening, again thanks caesar
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Right now it will skip a member from idle checking if: has op (@), is voiced (+), or is a valid user having local or global friend (f) flag. Will add more.
Once the game is over, the king and the pawn go back in the same box.
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

[11:53:04] Tcl error [::idleBan::idle:kick]: can't read "channel": no such variable

Don't kick or ban, i have this error message
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Replace:

Code: Select all

proc idle:kick {nick uhost hand chan vict reason} {
with:

Code: Select all

proc idle:kick {nick uhost hand channel vict reason} {
Another busy day at work and didn't get to do much.. :roll:
Once the game is over, the king and the pawn go back in the same box.
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

Hello caesar now have not errors but don't ban.
Your work has rightly priority, idleban can wait :wink:
User avatar
MrBeta
Voice
Posts: 35
Joined: Sat Dec 28, 2013 2:16 pm
Contact:

Post by MrBeta »

Not developed project but returning useful :(
Post Reply