File Coverage

blib/lib/Tweet/ToDelicious.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package Tweet::ToDelicious;
2              
3 1     1   26605 use v5.14;
  1         4  
  1         41  
4 1     1   1061 use utf8;
  1         8  
  1         4  
5 1     1   28 use warnings;
  1         6  
  1         25  
6 1     1   975 use Getopt::Long;
  1         13634  
  1         7  
7 1     1   562 use Net::Delicious;
  0            
  0            
8             use AnyEvent;
9             use AnyEvent::Twitter::Stream;
10             use AnyEvent::HTTP;
11             use Coro;
12             use Coro::LWP;
13             use Coro::AnyEvent;
14             use Log::Minimal;
15             use Tweet::ToDelicious::Entity;
16             use Sub::Retry;
17              
18             our $VERSION = '0.08';
19              
20             sub new {
21             my $class = shift;
22             my $cfg = shift;
23             my $self = bless { config => $cfg }, $class;
24             return $self;
25             }
26              
27             sub run {
28             my $self = shift;
29              
30             local $| = 1;
31             local $Log::Minimal::AUTODUMP = 1;
32              
33             my $myname = $self->{config}->{t2delicious}->{twitter_screen_name};
34             my $cv = AE::cv;
35             my ($connector, $connect, $stream, $listener);
36              
37             $listener = sub {
38             AnyEvent::Twitter::Stream->new(
39             %{ $self->{config}->{twitter} },
40             method => 'userstream',
41             on_connect => sub {
42             undef $connector;
43             infof( 'Start watching twitter:@%s, delicious:%s',
44             $myname, $self->{config}->{delicious}->{user} );
45             },
46             on_event => sub {
47             my $tweet = shift;
48             my $entry = Tweet::ToDelicious::Entity->new($tweet);
49             if ( $entry->is_favorite && $entry->screen_name ~~ $myname ) {
50             my @posts = $entry->posts;
51             $self->_posts(@posts);
52             }
53             },
54             on_tweet => sub {
55             my $tweet = shift;
56             my $entry = Tweet::ToDelicious::Entity->new($tweet);
57             if ( ( $entry->screen_name ~~ $myname )
58             or ( $entry->in_reply_to_screen_name ~~ $myname ) )
59             {
60             my @posts = $entry->posts;
61             $self->_posts(@posts);
62             }
63             },
64             on_keepalive => sub {
65             debugf("ping received");
66             },
67             on_eof => sub {
68             debugf("eof received");
69             $connect->();
70             },
71             on_error => sub {
72             critf(shift);
73             $connect->();
74             },
75             );
76             };
77             $connect = sub {
78             $connector = AE::timer 0, 2, sub { $stream = $listener->() };
79             };
80              
81             $connect->();
82             $cv->recv;
83              
84             }
85              
86             sub delicious {
87             my $self = shift;
88             state $delicious = Net::Delicious->new( $self->{config}->{delicious} );
89             return $delicious;
90             }
91              
92             sub coro_head {
93             my $self = shift;
94             my $uri = shift;
95             http_head $uri, Coro::rouse_cb;
96             my ( $data, $headers ) = Coro::rouse_wait;
97             if ( $headers->{Status} ~~ [ 200, 301, 302, 304 ] ) {
98             debugf( "expand: %s => %s", $uri, $headers->{URL} );
99             return $headers->{URL};
100             }
101             else {
102             debugf( "Status != 200. headers: %s", ddf($headers) );
103             return $headers->{Redirect}->[0]->{URL}
104             if exists $headers->{Redirect};
105             }
106             }
107              
108             sub _posts {
109             my $self = shift;
110             my $delicious = $self->delicious;
111             my @posts = @_;
112             debugf( "posts: %s", \@posts );
113             if ( @posts > 0 ) {
114             for my $post (@posts) {
115             async {
116             my $done = retry 3, 1, sub {
117             $post->{url} = $self->coro_head( $post->{url} );
118             $delicious->add_post($post);
119             };
120             infof( "Post %s done", $post->{url} )
121             if $done;
122             };
123             }
124             }
125             }
126              
127             1;
128             __END__