diff options
Diffstat (limited to '')
-rw-r--r-- | scripts/joininfo.pl | 1097 |
1 files changed, 1097 insertions, 0 deletions
diff --git a/scripts/joininfo.pl b/scripts/joininfo.pl new file mode 100644 index 0000000..492fbd3 --- /dev/null +++ b/scripts/joininfo.pl @@ -0,0 +1,1097 @@ +############################################################################### +# +# Shows WHOIS: info including realname and channel names on joins to +# channels. +# +# This script is based on the autorealname script, and shares a little +# code and many ideas with that script. I use the same globals as they do, +# but with totally different fields because their structure was not really +# easy to adapt to a situation where more info is used on one query. +# +# Rewrote all that code, except for parts of request_whois and some init code +# +# I would like to thank Timo 'cras' Sirainen and Bastian Blank for writing +# the autorealname script. It was a good example. +# +# The script contains very simple flood protection in the form that it will +# not allow for more then $max_queued_requests per server at one time to be +# running. It tries to be smart about netsplits, so this should be okay. +# We have a 5-second timeout to make sure we really don't flood, ans also to +# make sure that we don't wait indefinitely for answers that won't come. +# +# Themes: +# You can change the way the WHOIS messages look using the /format command, +# For example: +# /FORMAT ji_whois_success %GWHOIS:%n {channick_hilight $0} \ +# is "{hilight $1}"%n on {channel $2} +# +# Will add a green WHOIS: to the line to make it stand out, save your +# formatting in irssi using '/SAVE -formats' +# +# Add 'server: "{hilight $3}"' to the format string to also print the +# server name (Thanks to Svein Skogen for suggesting this) +# +# Add 'flags: "{hilight $4}"' to the format string to also print +# some additional flags for the user. These flags are tailored for +# some unknown irc network but also work quite well on IRCNet and EFNet +# after the 'idle' modifications I added to them. Thanks to +# Francesco Rolando for providing me with the initial patch. +# +# Commands (/JOININFO ...) +# INFO - Show info on and contents of the current cache of this script +# GC - Manually run the garbage collector once +# FORCE - Fake join of a nick to a chan (/JOININFO FORCE ichiban) use with +# care. Useful for testing theme changes, timeouts and the garbage +# collector on a quiet day or network. Will ignore your own nick. +# HELP - Shows help +# +# Settings +# /SET whois_expire_time # time to expire one saves record +# # until this age has been reched no +# # new WHOISs will be put on the server +# +# /SET whois_max_requests # max concurrent requests per server +# # flood protection, keep low +# +# /SET whois_timeout_ms # timeout after which a whois is lost (ms) +# # (default: 5000) +# +# /SET whois_gc_interval_ms # run gc ever x MS (default: 300000) +# # Requires script reload when changed. +# +# /SET whois_debug # 0 = show no debug info, 1 = debug info +# +# /SET whois_printing_level # Level at which all non-debug output is +# # printed, influences logging and IGNORE +# # (default: JOINS) +# +# ChangeLog: +# - Tue Jul 15 2003, pbijdens +# Initial release version 0.5.1 +# - Thu Jul 17 2003, pbijdens +# Version 0.5.2 +# Added garbage collection for the stored info. +# Added /AWINFO and /AWGC commands to show info and to run the garbage +# collector manually respectively +# Added timeout for the putserv WHOIS making sure we do not record too many +# jobs as BUSY. +# - Thu Jul 17 2003, pbijdens +# Version 0.5.3 +# Added settings (whois_...) to the irssi config so there is no need to +# modify the script when changing them +# - Thu Jul 17 2003, pbijdens +# Version 0.5.5 +# Making sure the settings are reloaded when they are changed. Added a +# signal handler for that +# - Thu Jul 17 2003, pbijdens +# Version 0.6.0 +# Added setting for whois_debug +# Added theme support +# Bugfix for servers sending 401 without 318 no need to wait for +# timeout anymore on those +# Added configurable printing level for the realname+channel messages. +# use /SET whois_printing_level +# Added /AWFORCE command (see above) +# - Mon Jul 28 2003, pbijdens +# Version 0.6.1 +# Various updates and bug fixes +# Changed awforce command to strip spaces +# - Wed Aug 13 2003, pbijdens +# Version 0.7.0 +# Fixed typo in comment line +# Changed /AW* commands to be /JOININFO <subcommand> and added a +# /JOININFO HELP command. Renamed some subs to make their purpose +# more clear. +# - Wed Feb 2 2004, pbijdens +# Added features for filtering channels from the list, and adding +# support for hilighting channels in colors. +# - Mon Mar 8 2004, pbijdens +# Fixed bug where also on SILCNET the WHOIS queries would be run, now +# this service is restricted to IRC networks. Thanks to Tony den Haan +# for supplying this patch. +# - Mon Mar 8 2004, pbijdens +# Added support for printing the servername also in the output for those +# who want to see it. Thanks to Svein Skogen for suggesting this and +# sending me a patch. +# NOTE: Requires you to add {hilight $3} to your format string manually. +# By default the information is not diplayed. +# - Mon Mar 8 2004, pbijdens +# Added support for additional flags to the WHOIS output. This is stuff +# like IrcOP, Away, Idle and more. Thanks to Francesco Rolando for +# providing the additional patch, which I modified. +# NOTE: Requires you to add {hilight $4} to your format string manually. +# By default the information is not diplayed. +# - Tue Mar 1 2005, pbijdens +# Updated the script for compliance with a wider range of servers, +# and removed some functionality that generally did not work, or break +# on some servers. Been runing on 4 networks now with these patches for +# many months, declaring stable and releasing 1.0. +# +################################################################################ + +use Irssi 20011207; +use strict; +use vars qw($VERSION %IRSSI); +use integer; + +################################################################################ + +$VERSION = "1.0.0"; +%IRSSI = ( + authors => "Pieter-Bas IJdens", + contact => "irssi-scripts\@nospam.mi4.org.uk", + name => "joininfo", + description => "Reports WHOIS information and channel list for those who join a channel", + license => "GPLv2 or later", + url => "http://pieter-bas.ijdens.com/irssi/", + changed => "2005-03-10" +); + +################################################################################ + +# Note that all settings below can and should be changed with /SET, see +# /joininfo help or /set whois + +# The maximum acceeptable age for a cached whois record is 60 seconds +# after this amount of time the cache record is discareded +my $whois_maxage = 60; + +# The maximum number of requests queued at a time, if the queue reaches +# a lrger size, ignore new requets until we have space left. This could +# happen in a netjoin preceded by a very long netsplit +my $max_queued_requests = 7; + +# Timeout after which a whois request is assumed not having been answered +# by the server. In milliseconds +my $whois_timeout = 5000; + +# Interval for the times at which GC takes place automatically. In milliseconds +my $whois_gc_interval = 300000; + +# Debug poutput on or off +my $whois_debug = 0; + +# Output level (the whois_printing_level_n is the numeric information for the +# output level) +my $whois_printing_level = "JOINS"; +my $whois_printing_level_n; + +################################################################################ + +# Cached records per server, plus information about the amount of queued +# reuests +my %servers; + +################################################################################ + +# Registers the theme messages with irssi so they can be changed later by the +# user using the /FORMAT command +sub register_messages +{ + Irssi::theme_register([ + 'ji_whois_success', + '{channick_hilight $0} is "{hilight $1}"%n on {channel $2}', + 'ji_whois_list_header', + 'Server: {hilight $0} ($1 pending)', + 'ji_whois_list_nick', + '{channick_hilight $0} is "{hilight $1}"%n on {channel $2}', + 'ji_whois_list_status', + 'Status: $0; Record age: $1s; Server tag: $2' + ]); +} + +################################################################################ + +# Register the settings we use, and specify a DEFAULT for when Irssi +# did not have them saved yet. Allows users to use /SET later. +sub register_settings +{ + Irssi::settings_add_int( + "joininfo", + "whois_expire_time", + $whois_maxage + ); + Irssi::settings_add_int( + "joininfo", + "whois_max_requests", + $max_queued_requests + ); + Irssi::settings_add_int( + "joininfo", + "whois_timeout_ms", + $whois_timeout + ); + Irssi::settings_add_int( + "joininfo", + "whois_gc_interval_ms", + $whois_gc_interval + ); + Irssi::settings_add_int( + "joininfo", + "whois_debug", + $whois_debug + ); + Irssi::settings_add_str( + "joininfo", + "whois_printing_level", + $whois_printing_level + ); +} + +################################################################################ + +# Now (re-)read the settings, those saved in the config will be returned, +# unless not present in which case the default will be returned +# This function is called once on script start, and later is run as an +# event handler when irssi notifies us of a change in settings. +sub load_settings +{ + $whois_maxage = Irssi::settings_get_int("whois_expire_time"); + $max_queued_requests = Irssi::settings_get_int("whois_max_requests"); + $whois_timeout = Irssi::settings_get_int("whois_timeout_ms"); + $whois_gc_interval = Irssi::settings_get_int("whois_gc_interval_ms"); + $whois_debug = Irssi::settings_get_int("whois_debug"); + $whois_printing_level = Irssi::settings_get_str("whois_printing_level"); + + $whois_printing_level = uc($whois_printing_level); + $whois_printing_level =~ s/[^A-Z]//gi; + + my($definedlvl); + eval("\$definedlvl = defined(MSGLEVEL_" . $whois_printing_level. ");"); + + if (!$definedlvl) + { + Irssi::print( + "%RJOININFO:%n illegal /set whois_printing_level, see /help levels". + " for more informations. Assuming JOINS in stead of ". + "\"$whois_printing_level\"." + ); + $whois_printing_level = "JOINS"; + $whois_printing_level_n = MSGLEVEL_JOINS; + return; + } + + eval("\$whois_printing_level_n = MSGLEVEL_" . $whois_printing_level . ";"); + + if ($whois_printing_level_n == 0) + { + Irssi::print( + "%RJOININFO:%n illegal /set whois_printing_level, see /help levels". + " for more informations. Assuming JOINS in stead of ". + "\"$whois_printing_level\"." + ); + $whois_printing_level = "JOINS"; + $whois_printing_level_n = MSGLEVEL_JOINS; + return; + } +} + +################################################################################ + +# We keep records of all nicks that ever joined a channel in our memory, +# without ever freeing them up. This can get quite large over time, therefore +# evere once in a while we go out and remove the garbage +# +# Now this function also corrects the pending counter in case strange things +# happen on strange nets +sub garbage_collector +{ + my($runtime) = time(); + + foreach my $tag (keys(%servers)) + { + my($busy) = 0; + my($rec) = $servers{$tag}; + + foreach my $nick (keys %{$rec->{nicks}}) + { + my($age) = $runtime - $rec->{nicks}->{$nick}->{record_time}; + + if ($rec->{nicks}->{$nick}->{busy}) + { + # Re-calculate the number of pending requests + $busy = $busy + 1; + + # we can safely delete it because 600 seconds should have + # caused a good oldfashioned ping timeout anyway + # if the server is not still going to respond after 10 + # minutes we can crash for all I care + if ($age > 600) + { + Irssi::print( + "%RWHOIS:%n Giving up on %c$nick%n, because 600 " . + "seconds have passed since we first asked %c$tag%n.%N" + ) if ($whois_debug); + + # We have one request less to process now + $busy = $busy - 1; + + # Drop the request completely and forget all about this + # nick + delete $rec->{nicks}->{$nick}; + } + } + elsif ($age >= 2 * $whois_maxage) + { + delete $rec->{nicks}->{$nick}; + } + + $rec->{processing} = $busy; + } + } +} + +################################################################################ + +# This is a very simple job to warp the call to the garbage collector. Used to +# be self-scheduling, but irssi happily does that for us +# +# Pointless function, waste of memory, need one of those in every good +# program, here is mine. +sub aw_gc_scheduler +{ + garbage_collector(); +} + +################################################################################ + +# Show information about the autowhois stuff and about who we still know +# Basically displays the cache contents. Some stuff may still be in the cache +# though it is already outdated, The barbage collector will take care of +# those entries +sub cmd_joininfo_info +{ + my($runtime) = time(); + + foreach my $tag (keys(%servers)) + { + my($rec) = $servers{$tag}; + + Irssi::printformat( + MSGLEVEL_CRAP, + 'ji_whois_list_header', + $tag, + $rec->{processing} + ); + + foreach my $nick (keys %{$rec->{nicks}}) + { + my($age) = $runtime - $rec->{nicks}->{$nick}->{record_time}; + my($status) = "OK"; + + if ($rec->{nicks}->{$nick}->{busy}) + { + $status = "BUSY"; + } + elsif ($rec->{nicks}->{$nick}->{aborted}) + { + $status = "ABORTED"; + + if ($rec->{nicks}->{$nick}->{known}) + { + $status = $status . " but KNOWN"; + } + } + else + { + $status = "COMPLETE"; + } + + Irssi::printformat( + MSGLEVEL_CRAP, + 'ji_whois_list_nick', + $nick, + $rec->{nicks}->{$nick}->{realname}, + $rec->{nicks}->{$nick}->{channels}, + $rec->{nicks}->{$nick}->{server}, + $rec->{nicks}->{$nick}->{flags} + ); + Irssi::printformat( + MSGLEVEL_CRAP, + 'ji_whois_list_status', + $status, + $age, + $tag + ); + } + } +} + +################################################################################ + +# A timeout is put for this function just after the WHOIS has been sent to +# the server. When the server does not reply, then we will mark the action as +# aborted. If a reply still ariives later (due to lag) that is not a problem +# as it will simply be reported then. The only thing this function makes sure +# of is that the system is not marked busy anymore so other WHOIS requests +# can go through +sub server_whois_timeout +{ + my ($server, $nick) = @{$_[0]}; + my $rec = $servers{$server->{tag}}; + + if ((defined($rec->{nicks}->{$nick})) + && ($rec->{nicks}->{$nick}->{busy} == 1) + ) + { + $rec->{nicks}->{$nick}->{aborted} = 1; + $rec->{nicks}->{$nick}->{busy} = 0; + + $rec->{processing} = $rec->{processing} - 1; + + Irssi::print( + "%RWHOIS:%n whois timeout for nick %C$nick%n ". + "(still running $rec->{processing} requests)" + ) if ($whois_debug); + } + + # Run once, so we remove this job + Irssi::timeout_remove($rec->{nicks}->{$nick}->{timeout_job}); +} + +################################################################################ + +# Put a whois request on the server (for one nick only) if and only if the +# number of outstanding rrequests on that server is not too high +# +# Also installs an event handler for the next related SHOIS event that the +# server throws at us +sub request_whois +{ + my ($server, $nick) = @_; + my $rec = $servers{$server->{tag}}; + + return if $server->{chat_type} ne "IRC"; + + if ($rec->{processing} > $max_queued_requests) + { + Irssi::print( + "%RWHOIS:%n Ignoring WHOIS request for %C$nick%n (too busy)%N" + ) if ($whois_debug); + record_reset($server, $nick); + return; + } + + $server->redirect_event( + "whois", + 1, + $nick, + 0, + "redir autowhois_default", + { + "event 311" => "redir autowhois_realname", + "event 319" => "redir autowhois_channels", + "event 312" => "redir autowhois_server", + "event 301" => "redir autowhois_away", + "event 307" => "redir autowhois_identified", + "event 275" => "redir autowhois_ssl", + "event 310" => "redir autowhois_irchelp", + "event 313" => "redir autowhois_ircop", + "event 325" => "redir autowhois_ircbot", + "event 317" => "redir autowhois_idle", +# "event 263" => "redir autowhois_busy", + "event 318" => "redir autowhois_end", + "event 401" => "redir autowhois_unknown", + "" => "event empty" + } + ); + + $rec->{processing} = $rec->{processing} + 1; + + # This format requests additional information on $nick + # used to be: $server->send_raw("WHOIS $nick :$nick"); + $server->send_raw("WHOIS $nick"); + + $rec->{nicks}->{$nick}->{timeout_job} = Irssi::timeout_add( + $whois_timeout, + \&server_whois_timeout, + [$server, $nick] + ); +} + +################################################################################ + +# A whois record is built as and when server messages with info for a specific +# user arrive. After the WHOIS END message has arrived for that user, we can +# report the stored whois information with this function. +sub report_stored_whois_info +{ + my ($server, $nick) = @_; + my $rec = $servers{$server->{tag}}; + + if (!defined($rec->{nicks}->{$nick})) + { + Irssi::print( + "%RWHOIS:%n Report called for undefined hash %C$nick%N" + ) if ($whois_debug); + return; + } + + foreach my $channame (@{$rec->{nicks}->{$nick}->{queued_channels}}) + { + my $chanrec = $server->channel_find($channame); + + if ($chanrec) + { + $rec->{nicks}->{$nick}->{flags} =~ s/[ ]{1,}$//; + + $chanrec->printformat( + $whois_printing_level_n, + 'ji_whois_success', + $nick, + $rec->{nicks}->{$nick}->{realname}, + $rec->{nicks}->{$nick}->{channels}, + $rec->{nicks}->{$nick}->{server}, + $rec->{nicks}->{$nick}->{flags} + ); + } + else + { + Irssi::print( + "%RWHOIS:%n chanrec not found for %W$channame%n :-(%N" + ) if ($whois_debug); + } + } + + $rec->{nicks}->{$nick}->{queued_channels} = []; +} + +################################################################################ + +# Create an empty record for this nick on that server, we will gradually fill +# out this record as and when we go along. +sub record_reset +{ + my ($server, $nick) = @_; + my $rec = $servers{$server->{tag}}; + + if (defined($rec->{nicks}->{$nick})) + { + delete $rec->{nicks}->{$nick}; + } + + $rec->{nicks}->{$nick} = + { + record_time => time(), + queued_channels => [], + realname => "(unknown)", + channels => "(unknown)", + server => "(unknown)", + flags => "", + aborted => 0, + busy => 0, + known => 0, + timeout_job => 0 + }; +} + +################################################################################ + +# Sent when a user joins a channel we are on, whic is where we check if we +# have the user info cached, if it is still valid, and if not we put +# a WHOIS request on the server for this user and are done. +sub event_join +{ + my ($server, $channame, $nick, $host) = @_; + + return if $server->{chat_type} ne "IRC"; + + $channame =~ s/^://; + my $rec = $servers{$server->{tag}}; + + return if ($nick eq $server->{nick}); + + return if ($server->netsplit_find($nick, $host)); + + if (!defined($rec->{nicks}->{$nick})) + { + # If the nick has no requests joined yet, we will create a new + # empty record for the nick, so we can assume later it does + # exist + record_reset($server, $nick); + } + + if (($rec->{nicks}->{$nick}->{known}) + && ((time() - $rec->{nicks}->{$nick}->{record_time}) <= $whois_maxage) + ) + { + # If we asked less than whois_maxage seconds ago for a WHOIS on this + # nick, we will not re-issue a request. + # + # NOTE: When a person (manually) joins multiple channels you are + # on, this may cause you not seeing all channels in the + # channel list, You can set this to something like 5 + # seconds to reduce the probability of this happening + push @{$rec->{nicks}->{$nick}->{queued_channels}}, $channame; + + report_stored_whois_info($server, $nick); + } + elsif ($rec->{nicks}->{$nick}->{busy} == 1) + { + # If we already issued a WHOIS request for this nick but did not + # receive a result yet, we just push this channel name on the + # list of channels that want a report when the result is known + push @{$rec->{nicks}->{$nick}->{queued_channels}}, $channame; + } + else + { + # Finally, we are not already processing this nick, and either + # we have no information for it, or the information we have is + # too old, so we send a WHOIS request to the server. + push @{$rec->{nicks}->{$nick}->{queued_channels}}, $channame; + + $rec->{nicks}->{$nick}->{busy} = 1; + + request_whois($server, $nick); + } +} + +################################################################################ + +# Implementation of the WFORCE <nick> command. Useful for testing purposes +# only, for example to see if the theme changes you made are correct, if the +# timeouts are interpreted properly, and if the garbage collector works +sub cmd_joininfo_force +{ + my ($data, $server, $window) = @_; + $data =~ s/^[ ]{1,}//g; + $data =~ s/[ ]{1,}$//g; + + if (!$server || !$server->{connected}) + { + Irssi::print("Not connected."); + return; + } + + if ($window->{type} ne "CHANNEL") + { + Irssi::print("Not a channel window."); + return; + } + + event_join($server, $window->{name}, $data, "testuser\@test.example.com"); +} + +################################################################################ + +# Event handler for the whois realname line returned by the server. When we +# issue a whois request, we bind an event handler for whois info for that +# nick. +# +# Does nothing, except for updating the record for that nick. +sub event_whois_realname +{ + my ($server, $data) = @_; + my ($num, $nick, $user, $host, $empty, $realname) = split(/ +/, $data, 6); + $realname =~ s/^://; + my $rec = $servers{$server->{tag}}; + + $rec->{nicks}->{$nick}->{realname} = $realname; +} + +################################################################################ + +# Event handler for the whois channels line returned by the server. When we +# issue a whois request, we bind an event handler for whois info for that +# nick. +# +# Does nothing, except for updating the record for that nick. +sub event_whois_channels +{ + my ($server, $data) = @_; + my ($num, $nick, $channels) = split(/ +/, $data, 3); + $channels =~ s/^://; + my $rec = $servers{$server->{tag}}; + + $channels =~ s/[ ]{1,}$//; + $rec->{nicks}->{$nick}->{channels} = $channels; +} + +################################################################################ + +# Event handler for the whois server line returned by the server. When we +# issue a whois request, we bind an event handler for whois info for that +# nick. +# +# Does nothing, except for updating the record for that nick. +# +# NOTE: In the default report the server is not repported, it is however +# stored in the record, so if you need it, you can simply update the +# reporting function to show it. +sub event_whois_server +{ + my ($server, $data) = @_; + my ($num, $nick, $serverstr) = split(/ +/, $data, 3); + $serverstr =~ s/^://; + my $rec = $servers{$server->{tag}}; + + $serverstr =~ s/ :.*$//; + + $rec->{nicks}->{$nick}->{server} = $serverstr; +} + +################################################################################ + +# This is the end of the whois request, all info available we should have +# now, so we mark the record as know, not bust, timestamp it so we can +# expire it later and we report back to the user on those channels waiting +# for whois info for nick +# +# Note that a No Such Nick error is not always followed by a WHOIS END. +# hyb7-based servers interpret the RFC differently from for example hyb6 +# and the IRCNet servers and will not send the WHOIS END line, but just +# the No Such Nick error (401). +sub event_whois_end +{ + my($server, $data) = @_; + my ($num, $nick, $serverstr) = split(/ +/, $data, 3); + my $rec = $servers{$server->{tag}}; + + $rec->{nicks}->{$nick}->{record_time} = time(); + $rec->{nicks}->{$nick}->{known} = 1; + $rec->{nicks}->{$nick}->{busy} = 0; + + if (!$rec->{nicks}->{$nick}->{aborted}) + { + $rec->{processing} = $rec->{processing} - 1; + } + + report_stored_whois_info($server, $nick); +} + +################################################################################ + +# Some servers (hyb7) do not send an end of whois when the nick is +# not known, they just send a 401 unknown message. Ircnet sends both, hyb6 +# sends both, but other servers seem to interpret the RFC differently. We +# just treat this event_whois_unknown as a 318 tag, and mark the lookup +# aborted (which it is in some way) +sub event_whois_unknown +{ + my($server, $data) = @_; + my ($num, $nick, $serverstr) = split(/ +/, $data, 3); + my $rec = $servers{$server->{tag}}; + + # Fill out the record with some bogus information, so when we + # end up reporting it, we can at least see what is going on. + $rec->{nicks}->{$nick}->{record_time} = time(); + $rec->{nicks}->{$nick}->{known} = 1; + $rec->{nicks}->{$nick}->{busy} = 0; + $rec->{nicks}->{$nick}->{realname} = "(unknown)"; + $rec->{nicks}->{$nick}->{channels} = "(unknown)"; + $rec->{nicks}->{$nick}->{server} = "(unknown)"; + $rec->{nicks}->{$nick}->{flags} = "(unknown)"; + + if (!$rec->{nicks}->{$nick}->{aborted}) + { + $rec->{processing} = $rec->{processing} - 1; + $rec->{nicks}->{$nick}->{aborted} = 1; + } + + report_stored_whois_info($server, $nick); +} + +################################################################################ + +# If the server is busy +sub event_whois_busy +{ + my($server, $data) = @_; + my($num, $nick, $serverstr) = split(/ +/, $data, 3); + my($rec) = $servers{$server->{tag}}; + + Irssi::print("******************* SERVER BUSY *******************************"); +} + +################################################################################ + +# No clue what this is for, maybe I should read the irssi documentation +# (if it existed....) +# +# Judging from the debug output this function is never called. +sub event_whois_default +{ + my($server, $nick) = @_; + my $rec = $servers{$server->{tag}}; + + Irssi::print( + "%RWHOIS:%n Got event_whois_default, ignoring." + ) if ($whois_debug); +} + +################################################################################ + +# Some chat networks support extra falgs for their users and display those +# in WHOIS results. The following fields allow this information to be +# stored in the channel records and to be displayed as well. + +sub event_whois_away +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."Away "; +} + +################################################################################ + +sub event_whois_identified +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."NickREG "; +} + +################################################################################ + +sub event_whois_ssl +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."SSL "; +} + +################################################################################ + +sub event_whois_irchelp +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."IrcHELP "; +} + +################################################################################ + +sub event_whois_ircop +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."IrcOP "; +} + +################################################################################ + +sub event_whois_ircbot +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."IrcBOT "; +} + +################################################################################ + +sub number_to_timestr +{ + my($number) = @_; + my ($result) = ""; + + # Force integer + $number = 1 * $number; + + my($days) = $number / 86400; + $number = $number % 86400; + my($hours) = $number / 3600; + $number = $number % 3600; + my($minutes) = $number / 60; + $number = $number % 60; + my($seconds) = $number; + + if ($days) { $result = $result . "${days}d"; } + if ($hours || $result) { $result = $result . "${hours}h"; } + if ($minutes || $result) { $result = $result . "${minutes}m"; } + $result = $result . "${seconds}s"; + + return $result; +} + +################################################################################ + +sub event_whois_idle +{ + my ($server, $data) = @_; + my $rec = $servers{$server->{tag}}; + my ($num, $nick, $msg) = split(/ +/, $data, 3); + $msg =~ s/^://; + + if ($msg =~ /^([0-9]{1,}) ([0-9]{1,}) :.*$/) + { + my($idle) = 1 * $1; + my($signon) = 1 * $2; + + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags} + . "Idle=" . number_to_timestr($idle). " "; + } + elsif ($msg =~ /^([0-9]{1,}) :.*$/) + { + my($idle) = 1 * $1; + + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags} + . "Idle=" . number_to_timestr($idle). " "; + } + else + { + $rec->{nicks}->{$nick}->{flags} = $rec->{nicks}->{$nick}->{flags}."SameSRV "; + } +} + +################################################################################ + +# Initializes a server record for the autowhois. Either called when a server +# does connect to the network, or on script load for all connected servers at +# that time +sub event_connected +{ + my($server) = @_; + + $servers{$server->{tag}} = { + processing => 0, # waiting reply for WHOIS request + nicks => {} # nick => [ #chan1, #chan2, .. ] + }; +} + +################################################################################ + +# Deletes a server record for the autowhois. We do this on disconnect +sub event_disconnected +{ + my($server) = @_; + + delete $servers{$server->{tag}}; +} + +################################################################################ + +# Implementation of what I call the /JOININFO umbrella command. Below +# we bind all subcommands for this command already, so all we need to +# do is hand off the event to irssi again so it can call the right +# implementation function for it. +sub cmd_joininfo +{ + my ($data, $server, $item) = @_; + $data =~ s/\s+$//g; + Irssi::command_runsub ('joininfo', $data, $server, $item); +} + +################################################################################ + +# Shows help +sub cmd_joininfo_help +{ + Irssi::print( <<EOF + +JOININFO FORCE <nick> +JOININFO GC +JOININFO INFO +JOININFO HELP + +JOININFO FORCE <nick> + Fakes the join of a certain nick to the channel, and shows you + what the WHOIS line would look like. +JOININFO GC + Forces running the garbage collector once +JOININFO INFO + Shows the WHOIS cache as it exists. Note that records in the cache + may be outdated but not deleted yet by the garbage collector +JOININFO HELP + This page + +Example: + JOININFO FORCE ichiban + +Settings: + Use /SET to change whois_expire_time, whois_max_requests, + whois_timeout_ms, whois_gc_interval_ms, whois_debug, or + whois_printing_level + +These settings: + Use /FORMAT to change ji_whois_success, ji_whois_list_header, + ji_whois_list_nick, or ji_whois_list_status + +Note: If you want to hilight certain channels in the output, just use +/HILIGHT -level JOINS #channel + +See also: HILIGHT +EOF + , MSGLEVEL_CLIENTCRAP); +} + +################################################################################ + +# Tegister messages for /FORMAT and theme support +register_messages(); + +# Register settings for /SET support +register_settings(); + +# Load the previously stored settings from the config file, will be called +# again later each time the settings change +load_settings(); + +################################################################################ + +# Mark all currently connected servers as connected +foreach my $server (Irssi::servers()) +{ + event_connected($server); +} + +################################################################################ + +# Add and register our signal handlers +Irssi::signal_add( +{ 'server connected' => \&event_connected, + 'server disconnected' => \&event_disconnected, + 'message join' => \&event_join, + 'redir autowhois_realname' => \&event_whois_realname, + 'redir autowhois_channels' => \&event_whois_channels, + 'redir autowhois_server' => \&event_whois_server, + 'redir autowhois_away' => \&event_whois_away, + 'redir autowhois_identified' => \&event_whois_identified, + 'redir autowhois_ssl' => \&event_whois_ssl, + 'redir autowhois_irchelp' => \&event_whois_irchelp, + 'redir autowhois_ircop' => \&event_whois_ircop, + 'redir autowhois_ircbot' => \&event_whois_ircbot, + 'redir autowhois_idle' => \&event_whois_idle, + 'redir autowhois_end' => \&event_whois_end, + 'redir autowhois_unknown' => \&event_whois_unknown, + 'redir autowhois_busy' => \&event_whois_busy, + 'setup changed' => \&load_settings } +); + +################################################################################ + +# Schedule the garbase collector to run every whois_gc_interval ms +Irssi::timeout_add( + $whois_gc_interval, + \&aw_gc_scheduler, + 0 +); + +################################################################################ + +# OLD STYLE COMMANDS ARE DISABLED AND REPLACED BY /JOININFO WITH SUB-COMMANDS +# Bind the /AWFORCE, /AWGC and /AWINFO commands. Uncomment the next three lines +# if you would like to keep the old-style commands +### Irssi::command_bind("awforce", "cmd_joininfo_force"); +### Irssi::command_bind("awgc", "garbage_collector"); +### Irssi::command_bind("awinfo", "cmd_joininfo_info"); + +Irssi::command_bind("joininfo force", \&cmd_joininfo_force); +Irssi::command_bind("joininfo gc", \&garbage_collector); +Irssi::command_bind("joininfo info", \&cmd_joininfo_info); +Irssi::command_bind("joininfo help", \&cmd_joininfo_help); +Irssi::command_bind("joininfo", \&cmd_joininfo); + +################################################################################ +### EOF |