+++ /dev/null
-#! /usr/bin/perl -w
-
-use strict;
-use warnings;
-use utf8;
-
-## IMPORTANT ##
-# When Net::Twitter::Lite encounters a Twitter API error or a network error,
-# it throws a Net::Twitter::Lite::Error object.
-# You can catch and process these exceptions by using eval blocks and testing $@
-## from http://search.cpan.org/perldoc?Net::Twitter::Lite#ERROR_HANDLING
-use Net::Twitter::Lite;
-use FindBin qw($Bin);
-use YAML::Tiny;
-
-my $conf = loadconf("$Bin/config.yml");
-if (! defined $conf) {
- die "$0: cannot parse config file.\n";
-}
-my $stat = loadconf("$Bin/status.yml");
-if (! defined $stat) {
- $stat = {
- # do not set to 0
- since_id => 1,
- };
-}
-
-my $bot = login($conf);
-if (! $bot->authorized) {
- die "$0: this client is not yet authorized.\n";
-}
-
-my %tweets;
-my $tweet;
-
-$tweet = or_search($bot, $conf->{hashtag}, $stat->{since_id});
-if ($tweet) {
- %tweets = (%tweets, %$tweet);
-}
-
-$tweet = mentions_ids($bot, $stat->{since_id});
-if ($tweet) {
- %tweets = (%tweets, %$tweet);
-}
-
-foreach my $id (sort keys %tweets) {
- if ($tweets{$id} eq 'retweet') {
- next;
- }
- sleep($conf->{sleep});
- # retweet found tweet
- # $tweets->{$id} eq 'search' => found by search API
- # eq 'mention' => found by mention API
- my $res;
- eval {
- $res = $bot->retweet($id);
- };
- if ($@) {
- evalrescue($@);
- warn "status_id => $id\n";
- next;
- }
-
- $stat->{since_id} = $id;
-}
-
-if (%tweets) {
- # save last status to yaml file
- YAML::Tiny::DumpFile("$Bin/status.yml", $stat);
-}
-
-
-sub loadconf {
- # load configration data from yaml formatted file
- # param => scalar string of filename
- # ret => hash object of yaml data
-
- my $file = shift @_;
-
- my $yaml = YAML::Tiny->read($file);
-
- if ($!) {
- warn "$0: '$file' $!\n";
- }
-
- return $yaml->[0];
-}
-
-sub login {
- # make Net::Twitter::Lite object and login
- # param => hash object of configration
- # ret => Net::Twitter::Lite object
-
- my $conf = shift @_;
-
- my $bot = Net::Twitter::Lite->new(
- consumer_key => $conf->{consumer_key},
- consumer_secret => $conf->{consumer_secret},
- );
-
- $bot->access_token($conf->{access_token});
- $bot->access_token_secret($conf->{access_token_secret});
-
- return $bot;
-}
-
-sub or_search {
- # search tweets containing keywords
- # param => Net::Twitter::Lite object, ArrayRef of keywords, since_id
- # ret => HashRef of status_id (timeline order is destroyed)
- # or undef (none is found)
-
- my $bot = shift @_;
- my $keywords = shift @_;
- my $since_id = shift @_;
-
- my $key = "";
- foreach my $word (@$keywords) {
- if ($key) {
- $key .= " OR $word";
- }
- else {
- $key = $word;
- }
- }
-
- my $res;
- my $ids = {};
- eval {
- if ($key) {
- $res = $bot->search(
- {
- q => $key,
- since_id => $since_id,
- }
- );
- }
- if ($res->{results}) {
- foreach my $tweet (@{$res->{results}}) {
- my $res = $bot->show_status($tweet->{id});
- if ($res->{retweeted_status}) {
- $ids->{$tweet->{id}} = 'retweet';
- }
- else {
- $ids->{$tweet->{id}} = 'search';
- }
- }
- }
- };
- if ($@) {
- evalrescue($@);
- }
-
- return $ids;
-}
-
-sub mentions_ids {
- # return status_ids mentioned to me
- # param => Net::Twitter::Lite object, since_id
- # ret => HashRef of status_id (timeline order is destroyed)
- # or undef (none is found)
-
- my $bot = shift @_;
- my $since_id = shift @_;
-
- my $res;
- eval {
- $res = $bot->mentions(
- {
- since_id => $since_id,
- }
- );
- };
- if ($@) {
- evalrescue($@);
- }
-
- my $ids;
- if ($res && @{$res}) {
- $ids = {
- map { $_->{id} => 'mention' } @{$res}
- };
- }
-
- return $ids;
-}
-
-sub evalrescue {
- # output error message at eval error
-
- use Scalar::Util qw(blessed);
-
- if (blessed $@ && $@->isa('Net::Twitter::Lite::Error')) {
- warn $@->error;
- if ($@->twitter_error) {
- my %twitter_error = %{$@->twitter_error};
- map {
- $twitter_error{"$_ => "} = $twitter_error{$_} . "\n";
- delete $twitter_error{$_}
- } keys %twitter_error;
- warn join("", %twitter_error);
- }
- }
- else {
- warn $@;
- }
-}