The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

POE::Component::IRC::Service::P10 - a fully event-driven IRC services module for P10 compliant networks.

SYNOPSIS

  use POE::Component::IRC::Service::P10;

  # Do this when you create your sessions. 'IRC-Service' is just a
  # kernel alias to christen the new IRC connection with. Second argument
  # must be a hash reference with your options.

  my (%hash) =  { ServerNumeric     => 3,
                  ServerName        => 'services.lamenet.org',
                  ServerDesc        => 'Services for LameNET',
                  RemoteServer      => 'hub.lamenet.org',
                  ServerPort        => 4400,
                  Password          => 'password',
                  EventMode         => 0              # Default is 1
                  Reconnect         => 1              # Default is 0
                  Version           => 'LameServ0.1a' # Defaults to module name and version
                };

  my ($object) = POE::Component::IRC::Service::P10->new('IRC-Service', \%hash ) or die "Oh noooo! $!";

  # Do stuff like this from within your sessions. This line tells the
  # connection named "IRC-Service" to send your session the following
  # events when they happen.

  $kernel->post('IRC-Service', 'register', qw(connected msg public nick server));

  # You can guess what this line does.

  $kernel->post('IRC-Service', 'connect');

  # Add a services identity to the network

  $kernel->post('IRC-Service' => 'addnick',
                { NickName    => 'Lame',
                  Umode       => '+odk',
                  Description => 'Lame Services Bot', } );

  # Determine if a user is an IRCop

  if ( $object->is_operator( $numeric ) ) {
    $kernel->post( 'IRC-Service' => privmsg => $botnumeric => $numeric => "Access granted." );
  }

DESCRIPTION

POE::Component::IRC::Service::P10 is a POE component which acts as an easily controllable IRC Services server for your other POE components and sessions. You create an IRC Services component and tell it what events your session cares about and where to connect to, and it sends back interesting IRC events when they happen. You make the client do things by sending it events.

The component implements the basic functionality of an IRC server and will track state changes ( such as new users, channels, etc. ) on the IRC network. To access this state the component returns an object when created and there are a hat-full of methods to query the state from your POE sessions. This also means that it is not necessary to use 'connect' to link to your uplink server before creating nicks and joining channels, as the component will track all these changes and during connection to the IRC network will "burst" in the necessary information. See the events section below for more information about this.

[Note that this module requires a lot of familiarity with the details of the IRC protocol. I'd advise you to read up on the gory details of RFC 1459 <http://cs-pub.bu.edu/pub/irc/support/rfc1459.txt> before starting. Some knowledge of the P10 IRC Server-to-Server protocol would also be advisable. Consult <http://www.xs4all.nl/~carlo17/irc/P10.html> for details.]

In order to write a POE program with POE::Component::IRC::Service::P10: Create your session(s) and an alias for a new POE::Component::IRC::Service::P10 server. (Conceptually, it helps if you think of them as little IRC servers.) In your session's _start handler, send the IRC service a 'register' event to tell it which IRC events you want to receive from it. Send it a 'connect' event at some point to tell it to join the IRC network, and it should start sending you interesting events every once in a while. Use the 'addnick' event to add an IRC client to your "server". The IRC Service accepts two different sets of events, server and client. Server events are commands that are issued by (heh) the server and client events are commands issued by clients.

  # Example of a client command:

  $kernel->post( 'IRC-Service', 'join', 'ADAAA' , '#LameNET' );

  # Example of a server command:

  $kernel->post( 'IRC-Service', 'opmode', '#LameNET', '+o', 'ADAAA' );

Basically, client commands require a source nickname for the command, eg. it doesn't make sense for a server to "join" a channel.

The long version is the rest of this document.

METHODS

new

Takes two arguments: a name (kernel alias) which this new connection will be known by; a hash reference with the configuration for your new shiny component. The hash reference must contain the following mandatory items: "ServerNumeric", an unique number between 0-4095 or Base64 equivalent (read the P10 specification to clue up on this); "ServerName", the name your IRC Service will be called; "RemoteServer", the DNS or IP address of your uplink/hub server; "ServerPort", the port to connect to on your uplink/hub server; "Password", the password required to link to uplink/hub server. The following are optional: "ServerDesc", a brief description of your IRC Service; "LocalAddr", which local IP address on a multihomed box to connect as; "PingFreq", the frequency in seconds that we should send PINGs to our uplink server; "EventMode", this specifies what events the component should track, setting to 0 will only track user or nick events, whilst setting to 1 will track all events. Default is 1. If you aren't interested in channel events ( say you are writing a NickServ ) set this to 0 and save some overhead :o) "Version", specify a software version that will get returned to users who use /VERSION, defaults to the name of the module; "Reconnect", determines whether the module automatically reconnects to the IRC network on disconnects and socket errors, default is 0 ie. don't reconnect. There are also two additional settings "HIS_SERVERNAME" and "HIS_SERVERINFO", which provide the "name" of the server shown to users on a /WHOIS of another user and the server description, no defaults.

Returns an object which can be used to access the IRC network state with the following methods:

cmd_token

One argument, an IRC command. Returns the appropriate tokenised command.

decimal_to_base64

One argument, a number, and an optional argument, the length of BASE64 number to return, defaults to 2. Returns the appropriate BASE64 representation of that number.

base64_to_decimal

One argument, a BASE64 representation. Returns the corresponding decimal number.

server_numeric

Takes one argument, a server name. Returns the corresponding server numeric.

server_name

Takes one argument, a server numeric. Returns the corresponding server name.

server_clients

Takes one argument, a server numeric. Returns a list of the client numerics.

nick_info

Takes on argument, a client numeric. Returns an array consisting of [0] NickName, [1] UserName, [2] HostName, [3] IRCName, [4] UMode and [5] AuthName ( if applicable ).

nick_long_form

Takes one argument, a client numeric. Returns <nickname>!<username>@<hostname>

nick_numeric

Takes one argument, a nickname. Returns the corresponding client numeric.

nick_name

Takes one argument, a client numeric. Returns the corresponding nickname.

nick_channels

Takes one argument, a client numeric. Returns an array of channels that the client is joined, preceeded with '@' or '+' for ops or voice.

channel_exists

Takes one argument, a channel name ( with # prefix ). Returns the timestamp of the channel if it exists.

is_channel_operator

Takes two arguments, channel name and a client numeric. Returns 1 if that user is a channel operator on that channel, or 0 otherwise.

has_channel_voice

Takes two arguments, channel name and a client numeric. Returns 1 if that user has voice on that channel, or 0 otherwise.

is_operator

Takes one argument, a client numeric. Returns 1 if that user has umode +o or 0 otherwise.

has_account_set

Takes one argument, a client numeric. Returns the authname/account if set, undef otherwise.

channel_banlist

Takes one argument, a channel name. Returns a list of the current ban masks set on that channel.

channels_list

No arguments. Returns a list of all the channels on the IRC network.

irc_network_stats

No arguments. Returns an array made up of [0] number of servers on the network, [1] number of channels on network, [2] number of clients on the network.

channel_users

Takes one argument, a channel name. Returns a list of client numerics, who are joined to that channel.

channel_mode

Takes one argument, a channel name. Returns the current channel mode.

channel_limit

Takes one argument, a channel name. Returns the current channel limit +l if set.

channel_key

Takes one argument, a channel name. Returns the current channel key +k if set.

INPUT

How to talk to your new IRC Services component... here's the events we'll accept.

Important Commands

connect

Takes no arguments. This event tells the IRC Services client to connect to a new/different hub and join an IRC network. If it has a connection already open, it'll close it gracefully before reconnecting. You will receieve an irc_p10_connected event, but it is safer to wait for an irc_p10_eob_ack from the module before assuming that the connection is properly made.

addnick

Takes one argument: a hash reference of attributes for the new service client (see the SYNOPSIS section of this doc for an example). This event adds a new client to the IRC Service server. Multiple clients are allowed. Expect to receive an appropriate irc_p10_nick event for the new client, from which you can derive the clients numeric token. Possible attributes for the new client are "NickName", (duh) the nickname this client will appear as on the IRC network (only required attribute); "UserName", the user part of ident@host (default is nick); "HostName", the host part of ident@host (default is the name of the server); "AuthName", the network "account" this client will use (see P10 specification for details); "Umode", the user modes this client will have (defaults to +odk); "Description", equivalent to the IRCName (default server description);

register

Takes N arguments: a list of event names that your session wants to listen for, minus the "irc_p10_" prefix. So, for instance, if you just want a bot that keeps track of which people are on a channel, you'll need to listen for CREATEs, JOINs, PARTs, QUITs, and KICKs to people on the channel you're in. You'd tell POE::Component::IRC::Service::P10 that you want those events by saying this:

  $kernel->post( 'IRC-Service', 'register', qw(join part quit kick) );

Then, whenever people enter or leave a channel your bot is on (forcibly or not), your session will receive events with names like "irc_p10_join", "irc_p10__kick", etc., which you can use to update a list of people on the channel.

Registering for 'all' will cause it to send all IRC-related events to you; this is the easiest way to handle it.

unregister

Takes N arguments: a list of event names which you don't want to receive. If you've previously done a 'register' for a particular event which you no longer care about, this event will tell the IRC connection to stop sending them to you. (If you haven't, it just ignores you. No big deal.)

Server initiated commands

These are commands that come from the IRC Service itself and not from clients.

account

Sets a user's account name. Takes two arguments, the target user's numeric token and the account name. If a user's account name field is set, the ircd knows the user is "logged in", and can have a "is logged in as" or "is authed as" line in the whois reply.

clearmode

Clears the specified channel modes. Takes two arguments, the channel to clear and a string of chars representing the modes to clear. Eg. "o" would clear all people with +o on a channel, "b" would clear all bans, etc.

gline

Sets or removes a GLINE to the IRC network. A GLINE prevents matching users from connecting to the network. Implemented as if the IRC Service is a U: lined server, so ircd must be configured accordingly. Takes four arguments, the target for the gline which can be * (for all servers) or a server numeric; the mask to gline [!][-|+]<mask> the presence of the ! prefix means "force", + means add/activate, - means remove/deactivate; the duration of the gline, ie. the time to expire the gline in seconds since epoch ( ie. output from time() ); the reason for the gline. Mask may be a user@host mask, or a channel name. In the later case (mask starts with a # or &) it is a "BADCHAN". A BADCHAN prevents users from joining a channel with the same name.

jupe

A jupe prevents servers from joining the network. Takes five arguments, the target for the jupe, either * for all servers or a server numeric; what to jupe [!][-|+]<server>, ! is force, + activate jupe, - deactivate jupe; the duration of the jupe, ie. the time to expire the jupe in seconds since epoch; the last modification timestamp, ie. the output of time(); the reason for the jupe.

kill

Server kill :) Takes two arguments, the client numeric of the victim; the reason for the kill. If the numeric specified matches one of the IRC Service's internal clients, that client will be automatically removed.

opmode

Opmode forces channel mode changes, resistance is futile. Changes are not bounced or denied. Takes at least one argument: the mode changes to effect, as a single string (e.g., "+sm-p+o"), and any number of optional operands to the mode changes (nicks, hostmasks, channel keys, whatever.) Or just pass them all as one big string and it'll still work, whatever. Note, nicks must be specified as numerics.

$kernel->post( 'IRC-Service' => opmode => "#LameNET" => "+o" => "ZaAAA" );

squit

This will disconnect the IRC Service from its uplink/hub server. Expect to receive an "irc_p10_disconnected" event. Takes no arguments.

shutdown

This will shutdown the IRC Service.

sl_server

Send a raw server command. Exercise extreme caution. Takes one argument, a string representing the raw command that the server will send. The module prepends the appropriate server numeric for you, so don't worry about that. Note, IRC commands must be specified as tokenised equivalents as per P10 specification.

$kernel->post( 'IRC-Service' => sl_server => "OM #LameNET +o ZaAAA" );

Client initiated commands

These are commands that come from clients on the IRC Service.

ctcp and ctcpreply

Sends a CTCP query or response to the nick(s) or channel(s) which you specify. Takes 3 arguments: the numeric of the client who is sending the command; the numeric or channel to send a message to (use an array reference here to specify multiple recipients), and the plain text of the message to send (the CTCP quoting will be handled for you).

invite

Invites another user onto an invite-only channel. Takes 3 arguments: the numeric of the inviting client, the nick of the user you wish to admit, and the name of the channel to invite them to. Note that the invitee is a nickname and not a numeric.

join

Tells a specified client to join a single channel of your choice. Takes at least two args: the numeric of the client that you want to join, the channel name (required) and the channel key (optional, for password-protected channels).

mode

Request a mode change on a particular channel or user. Takes at least two arguments: the mode changing client's numeric, the mode changes to effect, as a single string (e.g., "+sm-p+o"), and any number of optional operands to the mode changes (numerics, hostmasks, channel keys, whatever.) Or just pass them all as one big string and it'll still work, whatever. Nicks should be specified as numerics.

nick

Allows you to change a client's nickname. Takes two arguments: the numeric of the client who wishes to change nickname and the new username that you'd like to be known as.

notice

Sends a NOTICE message to the nick(s) or channel(s) which you specify. Takes 3 arguments: the numeric of the issuing client, the nick or channel to send a notice to (use an array reference here to specify multiple recipients), and the text of the notice to send.

part

Tell a client to leave the channels which you pass to it. Takes any number of arguments: the numeric of the client followed by the channel names to depart from.

privmsg

Sends a public or private message to the nick(s) or channel(s) which you specify. Takes 3 arguments: the numeric of the issuing client, the numeric or channel to send a message to (use an array reference here to specify multiple recipients), and the text of the message to send.

quit

Tells the IRC service to remove a client. Takes one argument: the numeric of the client to disconnect; and one optional argument: some clever, witty string that other users in your channels will see as you leave. The IRC Service will automatically remove the client from its internal list of clients.

sl_client

Send a raw client command. Exercise extreme caution. Takes one argument, a string representing the raw command that the server will send. Unlike "sl_server" you must specify the full raw command prefixed with the appropriate client numeric. Note, IRC commands must be specified as tokenised equivalents as per P10 specification.

$kernel->post( 'IRC-Service' => sl_client => "AbZAd OM #LameNET +o ZaAAA" );

stats

Returns some information about a server. Kinda complicated and not terribly commonly used, so look it up in the RFC if you're curious. Takes as many arguments as you please, but the first argument must be the numeric of a client. Target servers must be specified by numeric token.

OUTPUT

The events you will receive (or can ask to receive) from your running IRC component. Note that all incoming event names your session will receive are prefixed by "irc_p10_", to inhibit event namespace pollution ( and Dennis had already taken irc_ :p ).

If you wish, you can ask the client to send you every event it generates. Simply register for the event name "all". This is a lot easier than writing a huge list of things you specifically want to listen for.

The module will deal with automatically irc_p10_stats, irc_p10_version, irc_p10_whois and irc_p10_ping. The module will also track all events relating to server joins, nicks and channels.

Miscellaneous events

Events such as join, part, etc. should be same as POE::Component::IRC. See that documentation for details.

All numeric events (see RFC 1459)

Most messages from IRC servers are identified only by three-digit numeric codes with undescriptive constant names like RPL_UMODEIS and ERR_NOTOPLEVEL. (Actually, the list of codes in the RFC is kind of out-of-date... the list in the back of Net::IRC::Event.pm is more complete, and different IRC networks have different and incompatible lists. Ack!) As an example, say you wanted to handle event 376 (RPL_ENDOFMOTD, which signals the end of the MOTD message). You'd register for '376', and listen for 'irc_p10_376' events. Simple, no? ARG0 is the numeric of the server which sent the message. ARG1 is the text of the message.

AUTHOR

Chris Williams, <chris@bingosnet.co.uk<gt>

Based on a hell of lot of POE::Component::IRC written by Dennis Taylor, <dennis@funkplanet.com>

LICENSE

Copyright (c) Dennis Taylor and Chris Williams.

This module may be used, modified, and distributed under the same terms as Perl itself. Please see the license that came with your Perl distribution for details.

MAD PROPS

Greatest of debts to Dennis Taylor, <dennis@funkplanet.com> for letting me "salvage" POE::Component::IRC to write this module.

The wonderful people in #poe @ irc.perl.org for invaluable assistance and putting up with my n00b questions.

And to ^kosh and FozzySon and others from #jeditips @ irc.quakenet.org for allowing me to inflict my coding on them :)

SEE ALSO

RFC 1459, http://www.irchelp.org/, http://poe.perl.org/, http://www.xs4all.nl/~beware3/irc/bewarep10.html