POE::Component::IRC::Plugin::Validator::CSS - non-blocking CSS validator for IRC bots.


    use strict;
    use warnings;

    use POE qw(Component::IRC  Component::IRC::Plugin::Validator::CSS);

    my $irc = POE::Component::IRC->spawn(
        nick    => 'CSSValidator',
        server  => '',
        port    => 6667,
        ircname => 'CSS Validator Bot',
    ) or die "Oh noes :( $!";

        package_states => [
            main => [ qw(_start irc_001) ],


    sub _start {
        $irc->yield( register => 'all' );

        # register our plugin
            'CSSValidator' =>

        $irc->yield( connect => {} );

    sub irc_001 {
        my ( $kernel, $sender ) = @_[ KERNEL, SENDER ];
        $kernel->post( $sender => join => '#zofbot' );

    [18:05:00] <Zoffix> CSSValidator, cssval
    [18:05:01] <CSSValidator> ( Valid  ( )


This module is a POE::Component::IRC plugin which uses POE::Component::IRC::Plugin for its base. It provides access to W3C CSS Validator ( from IRC. It accepts input from public channel events, /notice messages as well as /msg (private messages); although that can be configured at will.



            'CSSValidator' =>

            'CSSValidatorJuicy' =>
                    auto                => 1,
                    trigger             => qr/^cssval\s*/i,
                    addressed           => 1,
                    listen_for_input    => [ qw(public  notice  privmsg) ],
                    response_event      => 'irc_css_validator_response',
                    valid_format        => '([:[uri_short]:]) Valid '
                                            . '( [:[refer_to_uri]:] )',

                    invalid_format      => '([:[uri_short]:]) Invalid, '
                                            . '[:[num_errors]:] error(s), see: '
                                            . '[:[refer_to_uri]:]',

                    banned              => [ qr/Zoffix!/, qr/aol[.]com$/i ],
                    poco_args => {
                        val_uri => 'http://local.validator',
                        ua    => LWP::UserAgent->new( timeout => 15 ),
                        debug => 1,

The new method constructs and returns a new POE::Component::IRC::Plugin::Validator::CSS object which is suitable for consumption by the POE::Component::IRC plugin_add() method. It may take quite a few arguments, although all of them are optional. Possible arguments are as follows:


    ->new( auto => 1 )

Optional. Takes either true or false values. By default the plugin autoresponds the results of validation to wherever the request came from (see listen_for_input argument below). You may wish to disable that feature by setting auto argument to a false value and listen to the event plugin emits (see response_event argument below). Defaults to: 1


    ->new( trigger => qr/^cssval\s+(?=\S)/i );

Optional. Takes a regex as an argument. Messages matching this regex will be considered as requests for validation. See also addressed option below which is enabled by default. Note: the trigger will be removed from the message, therefore make sure your trigger doesn't match the actual URI which needs to be validated. Defaults to: qr/^cssval\s+(?=\S)/i


    ->new( addressed => 1 );

Optional. Takes either true or false values. When set to a true value all the public messages must be addressed to the bot. In other words, if your bot's nickname is CSSBot and your trigger is qr/^val/ you would request the validation by saying CSSBot, val When addressed mode is turned on, the bot's nickname, including any whitespace and common punctuation character will be removed before matching the trigger (see above). When addressed argument it set to a false value, public messages will only have to match trigger regex in order to request validation. Note: this argument has no effect on /notice and /msg validation requests. Defaults to: 1


    ->new( listen_for_input => [ qw(public  notice  privmsg) ] );

Optional. Takes an arrayref as a value which can contain any of the three elements, namely public, notice and privmsg which indicate which kind of input plugin should respond to. When the arrayref contains public element, plugin will respond to requests sent from messages in public channels (see addressed argument above for specifics). When the arrayref contains notice element plugin will respond to validation requests sent to it via /notice messages. When the arrayref contains privmsg element, the plugin will respond to validation requests sent to it via /msg (private messages). You can specify any of these. In other words, setting ( listen_for_input = [ qr(notice privmsg) ] )> will enable validation only via /notice and /msg messages. Defaults to: [ qw(public notice privmsg) ]


    ->new( response_event => 'irc_css_validator_response' );

Optional. Whenever validation results are ready plugin emits an event (see EMITTED EVENTS for details). The value of response_event will specify the name of the event to emit. Defaults to: irc_css_validator_response


    ->new( valid_format => '([:[uri_short]:]) Valid ( [:[refer_to_uri]:] )' );

Optional. It is possible to configure the message which the plugin sends when validation completes. The valid_format takes a scalar string which specifies the format of messages sent when the URI being validated is valid (see also invalid_format below). The valid_format's value may contain several special character sequences which will be replaced by specific data bits. Defaults to: ([:[uri_short]:]) Valid ( [:[refer_to_uri]:] ). The special character sequences are as follows:


Any occurrences of [:[uri]:] in the valid_format string will be replaced by the URI which was validated.


Since it's common that people will be validating pretty long URIs which will clutter the output you may wish to use [:[uri_short]:] instead of [:[uri]:] (see above). The [:[uri_short]:] will contain a specially chopped up version of the URI being validated, just to make it obvious which URI it was (in case of multiple validations done at the same time).


Any occurrences of [:[num_errors]:] will be replaced with the number representing the number of errors... and for valid_format it will (should :) ) always be 0. However, the same code makes the replacement for invalid_format (see below), thus this 0 is at your disposal in valid_format as well ;)


Any occurrences of [:[refer_to_uri]:] will be replaced with the URI pointing to the validator's page with the results of validation.


Any occurrences of [:[num_warnings]:] will be replaced with the number of warnings occurred on the page.


    ->new( invalid_format => '([:[uri_short]:]) Invalid, [:[num_errors]:] error(s), see: [:[refer_to_uri]:]' );

Optional. Exactly the same as valid_format argument (see above) and it takes exactly the same special character sequences, except the invalid_format specifies the format of the output when the URI being validated is invalid (contains some CSS errors). Defaults to: ([:[uri_short]:]) Invalid, [:[num_errors]:] error(s), see: [:[refer_to_uri]:]


    ->new( banned => [ qr/Zoffix!/, qr/aol[.]com$/i ] );

Optional. Takes an arrayref as a value. The elements must be regexes. If the usermask of the person requesting the validation matches any of the regexes specified in banned, the plugin will ignore that user. Defaults to: [] (no bans are set).


    ->new( poco_args => {
            ua      => LWP::UserAgent->new( timeout => 10 ),
            val_uri => 'http://local.validator/',
            debug   => 1,

Optional. Takes a hashref as a value which will be passed to POE::Component::WebService::Validator::CSS::W3C spawn() method. Read POE::Component::WebService::Validator::CSS::W3C's documentation for possible values. The plugin will use all the defaults, however unless you specify the ua argument which takes an LWP::UserAgent object, the LWP::UserAgent object with its default parameters will be used with exception of the timeout argument, which plugin sets to 15 seconds.


    ->new( eat => 0 );

If set to a false value plugin will return a PCI_EAT_NONE after responding. If eat is set to a true value, plugin will return a PCI_EAT_ALL after responding. See POE::Component::IRC::Plugin documentation for more information if you are interested. Defaults to: 1



    $VAR1 = {
        'what' => '',
        'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
        'type' => 'public',
        'channel' => '#zofbot',
        'message' => 'CSSValidator, cssval',
        'result' => '( Valid ( )'

The event handler set up to handle the event, name of which you've specified in the response_event argument to the constructor (it defaults to irc_css_validator_response) will receive input every time validation request is completed. The input will come in the form of a hashref in ARG0. The keys/values of that hashref are as follows:


    { 'what' => '' }

The what key will contain the URI being validated (semantics: what was being validated).


    { 'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix' }

The who key will contain the usermask of the user who requested the validation.

    { 'type' => 'public' }

The type key will contain the "type" of the message sent be the requester. The possible values are: public, notice and privmsg indicating that request was requested in public channel, via /notice and via /msg (private message) respectively.


    { 'channel' => '#zofbot' }

The channel key will contain the name of the channel from which the request came from. This will only make sense when type key (see above) contains public.


    { 'message' => 'CSSValidator, cssval' }

The message key will contain the message which the user has sent to request the validation.


    { 'result' => '( Valid ( )' }

The result key will contain the result of the validation, or more specifically either valid_format or invalid_format strings (see constructor's description) with data bits replaced, in other words what you'd see the plugin say when auto (see constructor arguments) is turned on (that's the default).


Fork this module on GitHub:


To report bugs or request features, please use

If you can't access GitHub, you can email your request to bug-POE-Component-IRC-PluginBundle-WebDevelopment at


Zoffix Znet <zoffix at> (,


You can use and distribute this module under the same terms as Perl itself. See the LICENSE file included in this distribution for complete details.