diff options
| author | Alexander Færøy | 2014-05-31 13:10:46 +0200 | 
|---|---|---|
| committer | Alexander Færøy | 2014-05-31 13:10:46 +0200 | 
| commit | 2d0759e6ca5767b48bcc85bf38c2c43d5f0b63b1 (patch) | |
| tree | 1c5e6d817c88e67b46e216a50e0aef5428bf63df /scripts/joininfo.pl | |
| parent | 2d080422d79d1fd49d6c5528593ccaaff9bfc583 (diff) | |
| download | scripts.irssi.org-2d0759e6ca5767b48bcc85bf38c2c43d5f0b63b1.tar.bz2 | |
Import scripts from scripts.irssi.org
Diffstat (limited to 'scripts/joininfo.pl')
| -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 | 
