NAME

POE::Component::IRC::Plugin::YouTube::MovieFindStore - plugin for finding, resolving .FLV, and optionally storing YouTube URIs.

SYNOPSIS

use strict;
use warnings;

use POE qw(Component::IRC  Component::IRC::Plugin::YouTube::MovieFindStore);


my $irc = POE::Component::IRC->spawn( 
        nick    => 'TubeBot',
        server  => 'irc.freenode.net',
        port    => 6667,
        ircname => 'YouTube Grabber',
) or die "Oh noes :( $!";

POE::Session->create(
    package_states => [
        main => [
            qw(
                _start
                irc_001
                youtube_got_uri
                youtube_stored
            )
        ],
    ],
);

$poe_kernel->run();

sub _start {
    $irc->yield( register => 'all' );
    
    # register our plugin
    $irc->plugin_add(
        'Tube' => 
            POE::Component::IRC::Plugin::YouTube::MovieFindStore->new(
                where        => '/home/zoffix/Desktop/tube/',
                replace      => [ qr/\s+/, qr/[^\w-]/ ],
                replace_char => [ '-',     '_'        ],
                trigger      => qr/^tube\s+/i,
                banned       => qr/aol\.com$/i,
                users        => qr{unaffiliated/zoffix$},
                root_store   => 1,
                store_users  => qr/^Zoffix!/i,
            ) # all arguments are optional
    );
    
    $irc->yield( connect => { } );
    undef;
}

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

sub youtube_got_uri {
    my ( $kernel, $input ) = @_[ KERNEL, ARG0 ];
    
    my ( $channel, $who ) = @{ $input->{_data} }{ qw( channel who ) };
    my $nick = ( split /!/, $who )[0];
    
    my $message;
    if ( $input->{error} ) {
        $message = "Error: $input->{error}";
    }
    else {
        $message = sprintf "%s, Title: %s URI: %s FLV: %s",
                        $nick, @$input{ qw( title  uri  out ) };
    }
    $poe_kernel->post( $irc => privmsg => $channel => $message );

    undef;
}

sub youtube_stored {
    my ( $kernel, $input ) = @_[ KERNEL, ARG0 ];
    my ( $channel, $who ) = @{ $input->{_data} }{ qw( channel who ) };
    my $nick = ( split /!/, $who )[0];

    my $message;
    if ( $input->{store_error} ) {
        $message =  "$nick, flailed :( $input->{store_error}\n";
    }
    else {
        "$nick, saved as $input->{title} as $input->{where}"
    }
    $poe_kernel->post( $irc => privmsg => $channel => $message );
}

DESCRIPTION

The module is a plugin for POE::Component::IRC. It provides a utility for resolving YouTube's URLs into links pointing to the downloadable .flv file with an option to mirror the file locally.

CONSTRUCTOR

my $tube = POE::Component::IRC::Plugin::YouTube::MovieFindStore->new(
    where        => '/home/zoffix/Desktop/tube/',
    replace      => [ qr/\s+/, qr/[^\w-]/ ],
    replace_char => [ '-',     '_'        ],
    trigger      => qr/^tube\s+/i,
    banned       => qr/aol\.com$/i,
    users        => qr{unaffiliated/zoffix$},
    root_store   => 1,
    store_users  => qr/^Zoffix!/i,
);
$irc->plugin_add( CustomTube => $tube );

my $tube2 = POE::Component::IRC::Plugin::YouTube::MovieFindStore->new;
$irc->plugin_add( PlainTube => $tube2 );

The constructor takes quite a few arguments, all of which are optional with sensible defaults. Returns a plugin object suitable for feeding to POE::Component::IRC's plugin_add() method.

DEFAULT BEHAVIOUR

When no aguments are specified the plugin will behave in the following way:

  • Watch for YouTube links in any channel we are joined in presented by anyone. The messages must be prefixed with the trigger, i.e. must match qr/^youtube\s+/i

  • Resolve the link to .flv file and send 'youtube_got_uri' event.

  • No downloading will be done at all.

ARGUMENTS

The constructor takes several arguments which allow customization if a need arises. This is a short list of accepted arguments and their default values (if any), the description of each is provided afterwards. All of them are optional:

found_uri_event => 'youtube_found_uri',
got_uri_event   => 'youtube_got_flv_uri',
store_event     => 'youtube_stored',
resolve         => 1,
replace         => qr/\W/ ,
replace_char    => '_',
trigger         => qr/^youtube\s+/i,
root_store      => 1,

Also, there are several arguments which by default do not exists():

channels
banned
users
store_users
auto
where
eat

found_uri_event

->new( found_uri_event => 'event_to_send_when_we_see_a_link' );

The event name of the event to send when matching users in matching channels with matching trigger (if set, see below) send a URI which resembles YouTube URI. In most cases you probably wouldn't even want to set up a handler for this one. Defaults to: youtube_found_uri

got_uri_event

->new( got_uri_event => 'event_to_send_when_flv_is_resolved' );

This argument specifies the event name of the event to send when the direct link to .flv is resolved. Defaults to: youtube_got_flv_uri

store_event

->new( store_event => 'event_to_send_when_flv_is_downloaded' );

Specifies the event name of the event to send when .flv file has been downloaded (provided downloading is enabled, see where option below). Defaults to: youtube_stored

resolve

->new( resolve => 0 );

Setting this argument to a false value will disable resolving of direct links to .flv files. Plugin will be only sending events when matching users in matching channels with matching trigger send a URI which resembles YouTube URI. Defaults to: 1

replace

->new( replace => qr/\W/, replace_char => '_' );

->new(
    replace      => [ qr/-/, qr/\W/ ],
    replace_char => [ '_',   '.'    ],
);

When .flv downloading is turned on, the title of the movie will be used as the filename (with .flv extension appended). The replace argument may be either a regex, or an arrayref of regexes. The matching characters will be replaced with whatever you set in the replace_char option (see below). When argument is an arrayref, the argument to replace_char must also be an arrayref as each matching regex will be replaced with corresponding element from the replace_char arrayref. Defaults to: qr/\W/

replace_char

->new( replace => qr/\W/, replace_char => '_' );

->new(
    replace      => [ qr/-/, qr/\W/ ],
    replace_char => [ '_',   '.'    ],
);

See description of replace option above. Value may be either a regex or an arrayref of regexes. Defaults to underscore character: _

trigger

->new( trigger => qr/^ (?:you)? tube\s+/i );

If the line posted in the channel matches the regex, which is the value of the trigger argument, the plugin will scan it for any YouTube links and act approprietely on them (such as resolving .flv, etc). Note: when auto option (see below) is set, trigger has no effect. Defaults to: qr/^youtube\s+/i

root_store

->new( root_store => 0 );

Specifies whether or not downloading of movies should be done when the link was posted by the user who doesn't match the regex of store_users option (see below), (if downloading is turned on, see where option below). Defaults to: 1

channels

->new( channels => [ '#tubes', '#moar_tubes' ] );

Specifies the channels on which the plugin is active. Argument must be an arrayref. By default plugin is active on all joined channels.

banned

->new( banned => qr/Evil!spammer@spam.net/ );

Takes a regex as a value. Plugin will ignore any user masks matching the regex. By default no bans are set.

users

->new( users => qr/Only!me@home.net | my!friend@neighbour.net/x );

Takes a regex as a value. If set, plugin will listen only to users with masks matching this regex. By default plugin listens to all users.

store_users

->new( store_users => qr/Only!me@home.net | my!friend@neighbour.net/x );

Takes a regex as a value. If downloading of movies is turned on (see where option below) the users with masks matching this regex will trigger the download of the movie. Unless you have a really large hard drive you'd probably want to only specify trusted people in here. Note: if root_store option (see above) is set to a false value, store_users will not have any effect and everybody will trigger downloading. By default store_users does not exists() and root_store option is set to a true value, effectively disabling the download option for everyone. Note: you'll need to set the where option (see below) to enable any downloading.

auto

->new( auto => 1 )

Takes true and false values. When set to a true value, the plugin will parse every line of input for YouTube URIs, effectively disabling the trigger option (see above). By default auto does not exists() and only lines matching trigger will be scanned for YouTube URIs.

where

->new( where => '/home/zoffix/tube_movies/' );

This is the key argument to enable downloading of movies. It takes a scalar as an argument specifying the path of the directory to store the movies in. Unless it's set, no downloading will be performed irrelevant of values of root_store and store_users options. By default where doesn't exists(), thus plugin doesn't download anything at all.

eat

->new( eat => 1 );

If you are familiar with POE::Component::IRC::Plugin, setting eat to a true value will return PCI_EAT_ALL from component's public message event handler, otherwise it will return PCI_EAT_NONE. For the rest of you, this means this if you set eat to a true value, plugin will "eat" the public events if they contain YouTube URIs, thus anything listening to the events after the plugin won't get them. Refer to POE::Component::IRC::Plugin documentation for more information. By default eat does not exists() (i.e. plugin returns PCI_EAT_NONE).

OUTPUT

The events which you have registered with found_uri_event, got_uri_event and store_event, which by default are youtube_found_uri, youtube_got_flv_uri and youtube_stored respectively, will recieve output in ARG0.

found_uri_event

$VAR1 = {
      'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw',
      'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
      'channel' => '#zofbot',
      'links' => [
                   'http://www.youtube.com/watch?v=KVMGdFa90iw'
                 ]
    };

This event will be sent whenever plugin spots YouTube URIs in the channel, (providing the requirements are met, see channels, auto, trigger and the rest of option in the contructor). ARG0 will be a hashref with four keys:

what

{ 'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw' }

The what key will contain the text of the message sent by the user which contained YouTube URI.

who

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

The who key will contain the mask of the user who sent the message with YouTube URI.

channel

{ 'channel' => '#zofbot' }

The channel key will contain the channel where the message with YouTube URI appeared.

{
    'links' => [
            'http://www.youtube.com/watch?v=KVMGdFa90iw'
    ]
}

The links key will contain an arrayref with YouTube links spotted in the message. The reason it is an arrayref is because one message may contain several URIs.

got_uri_event

$VAR1 = {
      'out' => 'http://www.youtube.com/get_video.php?video_id=KVMGdFa90iw&t=OEgsToPDskKPgFOUMl4o_AN7jGxiOK-c',
      '_data' => {
                   'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw',
                   'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
                   'channel' => '#zofbot'
                 },
      'title' => 'Julie Louise Gerberding, MD answers the Davos question',
      'uri' => 'http://www.youtube.com/watch?v=KVMGdFa90iw'
    };

This event will be sent when plugin successfully resolves a .flv URI. ARG0 will contain a hashref with the following keys:

out

{  'out' => 'http://www.youtube.com/get_video.php?video_id=KVMGdFa90iw&t=OEgsToPDskKPgFOUMl4o_AN7jGxiOK-c' }

The out key will contain the URI to the .flv file (yes it won't actually have a .flv extension).

title

{ 'title' => 'Julie Louise Gerberding, MD answers the Davos question' }

The title key will contain the title of the movie.

uri

{ 'uri' => 'http://www.youtube.com/watch?v=KVMGdFa90iw' }

The uri key will contain the original YouTube URI of the page with the movie.

_data

{
    '_data' => {
            'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw',
            'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
            'channel' => '#zofbot'
            },
}

The _data key will contain the data of where we got the URI from. This is basically the ARG0 from found_uri_event (see above) without the links key.

error

If an error occured while resolving .flv URI, error key will contain the reason... with garbage from croak() appended (don't blame me for that, see WWW::YouTube::VideoLink)

store_event

$VAR1 = {
      'flv_uri' => 'http://www.youtube.com/get_video.php?video_id=KVMGdFa90iw&t=OEgsToPDskKPgFOUMl4o_AN7jGxiOK-c',
      '_data' => {
                   'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw',
                   'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
                   'channel' => '#zofbot'
                 },
      'response' => bless( { blah blah }, 'HTTP::Response' ),
      'title' => 'Julie Louise Gerberding, MD answers the Davos question',
      'where' => '/tmp/Julie-Louise-Gerberding_-MD-answers-the-Davos-question.flv'
    };

This event will be sent after the download of .flv file is completed (if such functionality is enabled of course). The ARG0 will contain a hashref with the following keys:

flv_uri

{ 'flv_uri' => 'http://www.youtube.com/get_video.php?video_id=KVMGdFa90iw&t=OEgsToPDskKPgFOUMl4o_AN7jGxiOK-c' }

The key flv_uri will contain the URI of the .flv file that we downloaded.

_data

{
      '_data' => {
                   'what' => 'youtube http://www.youtube.com/watch?v=KVMGdFa90iw',
                   'who' => 'Zoffix!n=Zoffix@unaffiliated/zoffix',
                   'channel' => '#zofbot'
                 },
}

The _data key will contain the information about where we got the YouTube link from. It's identical to the _data key from the got_uri_event event (see above).

response

{ 'response' => bless( { blah blah }, 'HTTP::Response' ), }

In case you'd want to inspect it. The response key will contain the HTTP::Response object, which was obtained when we were downloading the movie.

title

{ 'title' => 'Julie Louise Gerberding, MD answers the Davos question' }

The title key will contain the title of the movie.

where

{ 'where' => '/tmp/Julie-Louise-Gerberding_-MD-answers-the-Davos-question.flv' }

The where key will contain the path to the movie file.

store_error

{ 'store_error' => '304 Not Modified' }

In case of an error, store_erro key will be present and will contain the explanation of why we failed.

SEE ALSO

POE::Component::IRC, POE::Component::IRC::Plugin, POE::Component::WWW::YouTube::VideoURI

BUGS

None known.

AUTHOR

Zoffix Znet, <zoffix@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2008 by Zoffix Znet

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.