fix evalrescue fuction
[lab.git] / Dev / twitter / dump_timeline.pl
1 #! /usr/bin/perl -w
2
3 use strict;
4 use warnings;
5 use utf8;
6
7 ## IMPORTANT ##
8 # When Net::Twitter::Lite encounters a Twitter API error or a network error, 
9 # it throws a Net::Twitter::Lite::Error object. 
10 # You can catch and process these exceptions by using eval blocks and testing $@
11 ## from http://search.cpan.org/perldoc?Net::Twitter::Lite#ERROR_HANDLING
12 use Net::Twitter::Lite;
13 use FindBin qw($Bin);
14 use YAML::Tiny;
15 use Data::Dumper;
16 use Encode;
17
18 my $help = sub {
19     die <<EOM;
20 usage: $0
21     [{u}ser_timeline(default)|{r}etweeted_by_me|{m}sentions|{s}earch
22         [screen_name
23             [number_of_pages|all
24                 [dump]
25             ]
26         ]
27     ]
28 EOM
29 };
30 if ($ARGV[0] && ($ARGV[0] eq '--help' || $ARGV[0] eq '-h') ) {
31     &{$help};
32 }
33
34 my $method = $ARGV[0] || 'user_timeline';
35 my $screen_name = $ARGV[1] || '';
36 my $pages = $ARGV[2] || 1;
37 if ($pages eq 'all') {
38     $pages = -1;
39 }
40 my $dump = $ARGV[3] || 0;
41
42 my $conf = loadconf("$Bin/config.yml");
43 if (! defined $conf) {
44     die "$0: cannot parse config file.";
45 }
46
47 my $bot = login($conf);
48 if (! $bot->authorized) {
49     die "$0: this client is not yet authorized.";
50 }
51
52
53 eval {
54     my $page = 0;
55     while ($pages - $page && $page <= 20) {
56         $page++;
57         
58         my $param = ($screen_name)
59             ? { page => $page, screen_name => $screen_name, count => 200, }
60             : { page => $page, count => 200, }
61         ;
62     
63         my $res;
64         if ($method eq 'user_timeline' || $method eq 'u') {
65             $res = $bot->user_timeline($param);
66         }
67         elsif ($method eq 'retweeted_by_me' || $method eq 'r') {
68             $res = $bot->retweeted_by_me($param);
69         }
70         elsif ($method eq 'mentions' || $method eq 'm') {
71             $res = $bot->mentions($param);
72         }
73         elsif ($method eq 'search' || $method eq 's') {
74             my $key;
75             foreach my $word (@{ $conf->{hashtag} }) {
76                 if ($key) {
77                     $key .= " OR $word";
78                 }
79                 else {
80                     $key = $word;
81                 }
82             }
83             $param->{q} = $key;
84             $res = $bot->search($param)->{results};
85         }
86         else {
87             warn "$0: unknown method '$method'";
88             &{$help};
89         }
90         
91         if ($dump) {
92             foreach my $line (split /\n/, Dumper $res) {
93                 if ($line =~ /undef/) { next; }
94                 print $line, "\n";
95             }
96         }
97         else {
98             foreach my $status (@{$res}) {
99                 my $text = "";
100                 $text .= "(". $status->{id} . ") ";
101                 $text .= ($status->{user}{screen_name}) ?
102                     $status->{user}{screen_name} : $status->{from_user};
103                 $text .= "|";
104                 $text .= ($status->{user}{name}) ?
105                     $status->{user}{name} : $status->{from_user_name};
106                 $text .= " [" . $status->{created_at} . "]";
107                 $text .= " ".  $status->{text};
108                 $text =~ s/\n//;
109                 print encode('utf8', $text), "\n";
110             }
111         }
112     }
113 };
114 if ($@) {
115     evalrescue($@);
116 }
117
118
119 sub loadconf {
120     # load configration data from yaml formatted file
121     #   param   => scalar string of filename
122     #   ret     => hash object of yaml data
123     
124     my $file = shift @_;
125     
126     my $yaml = YAML::Tiny->read($file);
127     
128     if ($!) {
129         warn "$0: '$file' $!";
130     }
131     
132     return $yaml->[0];
133 }
134
135 sub login {
136     # make Net::Twitter::Lite object and login
137     #   param   => hash object of configration
138     #   ret     => Net::Twitter::Lite object
139     
140     my $conf = shift @_;
141     
142     my $bot = Net::Twitter::Lite->new(
143         consumer_key    => $conf->{consumer_key},
144         consumer_secret => $conf->{consumer_secret},
145         legacy_lists_api => 0,
146     );
147     
148     $bot->access_token($conf->{access_token});
149     $bot->access_token_secret($conf->{access_token_secret});
150     
151     return $bot;
152 }
153
154 sub evalrescue {
155     # output error message at eval error
156     
157     use Scalar::Util qw(blessed);
158     
159     if (blessed $@ && $@->isa('Net::Twitter::Lite::Error')) {
160         warn $@->error;
161         if ($@->twitter_error) {
162             my $twitter_error = $@->twitter_error;
163             if (defined $twitter_error->{errors}) {
164                 foreach my $error (@{$twitter_error->{errors}}) {
165                     warn "code => "   , $error->{code}, "\n";
166                     warn "message => ", $error->{message}, "\n";
167                 }
168             }
169             else {
170                 # unknown HASH structure
171                 use Data::Dumper;
172                 warn Dumper $twitter_error;
173             }
174         }
175     }
176     else {
177         warn $@;
178     }
179 }