Skip to content

Instantly share code, notes, and snippets.

@perigrin
Created February 11, 2012 04:05
Show Gist options
  • Save perigrin/1796064 to your computer and use it in GitHub Desktop.
Save perigrin/1796064 to your computer and use it in GitHub Desktop.
Updating data files for my Twitter interactions
#!/usr/bin/perl
use strict;
use warnings FATAL => qw( all );
use Net::Twitter::Lite;
use Lingua::EN::Inflect qw(NO NUMWORDS);
use HTML::Entities qw(encode_entities_numeric);
use lib '../files/perl/lib';
use Base::Roots qw(get_data data_directory);
use Base::Data qw(get_hash);
use Base::Convert qw(hashtagify);
use Twitter qw(twitter_accounts);
local $\ = "\n";
my @accounts = twitter_accounts();
die "First account is not Lady Aleena" if $accounts[0] ne 'Lady_Aleena';
my @accounts_totals;
my %is_account;
$is_account{$_}++ for @accounts;
my $nt = Net::Twitter::Lite->new(
consumer_key => Twitter::consumer_key,
consumer_secret => Twitter::consumer_key_secret,
);
# Get Lady_Aleena's followers for greetings which will be added later.
my %LA_followers;
print "Are you tweeting this time? ";
my $tweeting = <>;
chomp($tweeting);
print "How many seconds between tweets? ";
my $sleep = <>;
chomp($sleep);
for my $account (@accounts) {
print $account;
$nt->{access_token} = Twitter::access_key($account);
$nt->{access_token_secret} = Twitter::access_key_secret($account);
my $short_account = $account;
$short_account =~ s/LadyAleena_//g;
my $directory = "Twitter/users/$account";
my $full_path = data_directory($directory);
mkdir($full_path) or die unless (-d $full_path);
my %files;
for (qw(followers twitter_friends not_following not_followers friend_tweets lists list_memberships mentions retweets)) {
$files{$_} = get_data($directory,"$_.txt");
}
# Start account totals
my $account_totals = $nt->account_totals;
push @accounts_totals, "$account|".join("|",map($account_totals->{$_},qw(followers friends updates)));;
# End account totals
# Start followers and friends
my %people;
for my $people_type (qw(followers friends)) {
for ( my $cursor = -1; $cursor; ) {
my $type = $nt->$people_type({ cursor => $cursor, });
push @{$people{$_->{screen_name}}}, "$people_type" for @{$type->{users}};
if ($people_type eq 'followers') {
if ($account eq 'Lady_Aleena') {
$LA_followers{$_->{screen_name}}++ for @{$type->{users}};
}
else {
my %followers;
if (-f $files{$people_type}) {
%followers = get_hash(
file => $files{$people_type},
headings => [qw(id screen_name greet)],
);
}
for my $follower (@{$type->{users}}) {
my $id = $follower->{id};
if (!exists($followers{$id})) {
$followers{$id}{greet} = 0;
}
$followers{$id}{id} = $id;
$followers{$id}{screen_name} = $follower->{screen_name};
}
print "\t$account follower greetings";
my @follower_lines;
for my $follower (sort {lc $followers{$a}{screen_name} cmp lc $followers{$b}{screen_name}} keys %followers) {
my $screen_name = $followers{$follower}{screen_name};
my $id = $followers{$follower}{id};
if ($followers{$follower}{greet} == 0) {
my $line = "\@$screen_name: Thank you for following my $short_account account. ";
if (!exists($LA_followers{$screen_name})) {
$line .= "\@Lady_Aleena is my main account.";
}
else {
$line .= "I hope you don't get bored. :)";
}
print "\t\t$line";
$nt->update({ status => $line }) if $tweeting =~ /^y/i;
sleep($sleep);
}
$followers{$follower}{greet} = 1;
my $greet = $followers{$follower}{greet};
push @follower_lines, "$id|$screen_name|$greet";
}
open(my $to_file,'>',$files{$people_type}) or die "Can't open $files{$people_type} $!";
print $to_file join("\n",@follower_lines);
}
}
$cursor = $type->{next_cursor};
}
}
my %groups;
for my $person (sort {lc $a cmp lc $b} keys %people) {
my @statuses = @{$people{$person}};
if (@statuses == 2) {
push @{$groups{twitter_friends}}, $person;
next;
}
push @{$groups{not_following}}, $person if $statuses[0] eq "followers";
push @{$groups{not_followers}}, $person if $statuses[0] eq "friends";
}
for my $group (keys %groups) {
local $\ = undef;
open(my $fh, '>', $files{$group}) or die "Can't open $files{$group} $!";
print $fh join("\n",@{$groups{$group}});
close($fh);
}
my $friend_count = NO('friend',scalar(@{$groups{twitter_friends}}));
print "\t$account has $friend_count on Twitter.";
my $not_following_count = NO('person',scalar(@{$groups{not_following}}));
print "\t$account is not following $not_following_count on Twitter.";
my $not_followers_count = NO('person',scalar(@{$groups{not_followers}}));
print "\t$account is not being followed by $not_followers_count on Twitter.";
my $tweet_tag = '#Friends';
my $space = 140 - length($tweet_tag);
my $friends = '';
my @friend_tweets;
for my $friend (sort { lc $a cmp lc $b } @{$groups{twitter_friends}}) {
if (length($friends) + 1 + length($friend) > $space) {
push @friend_tweets, $tweet_tag . $friends;
$friends = '';
}
$friends .= " \@$friend";
}
push @friend_tweets, $tweet_tag . $friends if length($friends);
my $friend_tweets_count = NO('tweet',scalar(@friend_tweets));
print "\t$account has $friend_tweets_count for her friends.";
open(my $friend_tweets_fh, '>', $files{friend_tweets}) or die "Can't open $files{friend_tweets} $!";
print $friend_tweets_fh join("\n",@friend_tweets);
close($friend_tweets_fh);
# End followers and friends
# Start list updates
# link to lists on tumblr http://tmblr.co/ZZVoswE7_RE1
print "\t$account lists";
my %lists;
if (-s $files{lists}) {
%lists = get_hash(
file => $files{lists},
headings => [qw(list_slug list_name members_count members_change subscribers_count subscribers_change)],
);
}
my $lists = $nt->get_lists({
user => $account,
});
my $lists_directory = "Twitter/users/$account/lists";
my $lists_full_path = data_directory($lists_directory);
mkdir($lists_full_path) or die "Can't make $lists_full_path $!" unless (-d $lists_full_path);
my @list_lines;
for my $list (sort {$a->{name} cmp $b->{name}} @{$lists->{lists}}) {
my $list_slug = $list->{slug};
my $list_name = $list->{name};
my $member_count = $list->{member_count};
my $member_change = $lists{$list_slug}{members_count} ? $member_count - $lists{$list_slug}{members_count} : 0;
my $subscriber_count = $list->{subscriber_count};
my $subscriber_change = $lists{$list_slug}{subscriber_count} ? $subscriber_count - $lists{$list_slug}{subscriber_count} : 0;
my $list_directory = "Twitter/users/$account/lists/$list_slug";
my $list_full_path = data_directory($list_directory);
mkdir($list_full_path) or die "Can't make $list_full_path $!" unless (-d $list_full_path);
push @list_lines, join('|',($list_slug,$list_name,$member_count,$member_change,$subscriber_count,$subscriber_change));
print "\t\t$list_name";
if ($subscriber_count > 0) {
my @subscribers;
for ( my $cursor = -1; $cursor; ) {
my $list_subscribers = $nt->list_subscribers({
user => $account,
list_id => $list_slug,
cursor => $cursor,
});
push @subscribers, map $_->{screen_name}, @{$list_subscribers->{users}};
$cursor = $list_subscribers->{next_cursor};
}
for my $subscriber (sort {lc $a cmp lc $b} @subscribers) {
if (!exists($people{$subscriber}) && $account ne 'Lady_Aleena') {
$nt->create_friend({
screen_name => $subscriber,
follow => 'true',
});
$nt->update_friendship({
screen_name => $subscriber,
retweets => 'false',
});
print "\t\t\t$subscriber subscribed to $list_name so $short_account followed.";
}
}
{ # Print the file for the subscribers.
local $\ = undef;
open(my $subscriber_fh, '>', "$list_full_path/subscribers.txt") or die "Can't open $list_full_path/subscribers.txt $!";
print $subscriber_fh join("\n",@subscribers);
close($subscriber_fh);
}
}
my @members;
for ( my $cursor = -1; $cursor; ) {
my $list_members = $nt->list_members({
user => $account,
list_id => $list_slug,
cursor => $cursor,
});
push @members, map $_->{screen_name}, @{$list_members->{users}};
$cursor = $list_members->{next_cursor};
}
{ # Print the file for members.
local $\ = undef;
open(my $member_fh, '>', "$list_full_path/members.txt") or die "Can't open $list_full_path/members.txt $!";
print $member_fh join("\n",@members);
close($member_fh);
}
}
if (scalar(@list_lines) > 0) {
local $\ = undef;
open(my $al_fh, '>', $files{lists}) or die "Can't open $files{lists} $!";
print $al_fh join("\n",@list_lines);
close($al_fh);
}
# End list updates
# Start list memberships
print "\t$account list memberships";
my @list_memberships;
for ( my $cursor = -1; $cursor; ) {
my $list_memberships = $nt->list_memberships({
user => $account,
cursor => $cursor,
});
for my $list_membership (@{$list_memberships->{lists}}) {
my $list_full_name = $list_membership->{full_name};
my $member_count = $list_membership->{member_count};
my $subscriber_count = $list_membership->{subscriber_count};
my $user_screen_name = $list_membership->{user}{screen_name};
push @list_memberships, "$list_full_name|$member_count|$subscriber_count|$user_screen_name";
print "\t\t$list_full_name";
}
$cursor = $list_memberships->{next_cursor};
}
if (scalar(@list_memberships) > 0) {
open(my $lm_fh, '>', $files{list_memberships}) or die "Can't open $files{list_memberships} $!";
print $lm_fh join("\n",@list_memberships);
close($lm_fh);
}
# End lists memberships
# Start mentions
print "$account mentions";
my $last_mention;
if (-s $files{mentions}) {
open (my $message_fh, '<', $files{mentions}) or die "Can't open $files{mentions}. $!";
my @message_array = <$message_fh>;
chomp(@message_array);
my $last_line = pop @message_array;
my ($last_id,$last_data) = split(/\|/,$last_line,2);
$last_mention = $last_id;
}
my $mentions = $nt->mentions({
count => 200,
include_entities => 1,
since_id => $last_mention || 1,
});
my @new_mentions;
MENTION: for my $mention (@{$mentions}) {
my $tweet_id = $mention->{id};
my $tweet_dt = $mention->{created_at};
my $tweet_text = encode_entities_numeric($mention->{text},'^\n\x20-\x25\x27-\x7e');
$tweet_text =~ s/[\r\n]+//g;
my $tweet_reply_to_screen_name = $mention->{in_reply_to_screen_name} || '';
my $tweet_reply_to_id = $mention->{in_reply_to_status_id} || '';
my $user_id = $mention->{user}{id};
my $user_name = $mention->{user}{screen_name};
if ($tweeting =~ /^y/i && ($tweet_text =~ /^#FF/i || $tweet_text =~ /^#FollowFriday/i)) {
try {
$nt->update({
status => "\@$user_name Thank you for the \#FF.",
in_reply_to_status_id => $tweet_id,
});
} catch { warn $_; next MENTION; };
}
for my $url (@{$mention->{entities}{urls}}) {
my $short_url = quotemeta($url->{url});
my $long_url = $url->{expanded_url} ? $url->{expanded_url} : "http://$short_url";
$tweet_text =~ s/$short_url/$long_url/;
}
if (!exists($is_account{$user_name})) {
push @new_mentions, "$tweet_id|$user_name|$tweet_dt|$tweet_text|$tweet_reply_to_screen_name|$tweet_reply_to_id";
}
}
if (scalar(@new_mentions) > 0) {
local $\ = undef;
open (my $message_fh, '>>', $files{mentions}) or die "Can't open $files{mentions}. $!";
print join("\n",reverse @new_mentions);
print $message_fh "\n".join("\n",reverse @new_mentions);
close($message_fh);
print "\n";
}
# End mentions
# Start retweets
print "$account reweets";
my %stored_retweets;
if (-f $files{retweets}) {
%stored_retweets = get_hash(
file => $files{retweets},
headings => [qw(id tweet retweeters)],
);
}
my $retweets = $nt->retweets_of_me({
count => 100,
include_entities => 1,
});
for my $retweet (@{$retweets}) {
my $id = $retweet->{id};
my $retweet_by = $nt->retweeted_by($id);
if (!exists($stored_retweets{$id})) {
my $retweet_text = encode_entities_numeric($retweet->{text},'^\n\x20-\x25\x27-\x7e');
for my $url (@{$retweet->{entities}{urls}}) {
my $short_url = quotemeta($url->{url});
my $long_url = $url->{expanded_url} ? $url->{expanded_url} : "http://$short_url";
$retweet_text =~ s/$short_url/$long_url/;
}
$stored_retweets{$id}{tweet} = $retweet_text;
my @retweeters_list;
for my $retweeter (@{$retweet_by}) {
my $screen_name = $retweeter->{screen_name};
push @retweeters_list, $screen_name;
}
$stored_retweets{$id}{retweeters} = scalar(@retweeters_list) > 0 ? join(',',@retweeters_list) : '';
}
else {
my @retweeters_list = split(/,/,$stored_retweets{$id}{retweeters});
for my $retweeter (@{$retweet_by}) {
my $screen_name = $retweeter->{screen_name};
push @retweeters_list, $screen_name if !grep($screen_name,@retweeters_list);
}
$stored_retweets{$id}{retweeters} = scalar(@retweeters_list) > 0 ? join(',',@retweeters_list) : '';
}
$stored_retweets{$id}{id} = $id;
}
my @updated_retweets;
for my $tweet (sort {$stored_retweets{$a}{id} <=> $stored_retweets{$b}{id}} keys %stored_retweets) {
my $id = $stored_retweets{$tweet}{id};
my $retweet_text = $stored_retweets{$tweet}{tweet};
my $retweeters = $stored_retweets{$tweet}{retweeters};
push @updated_retweets, "$id|$retweet_text|$retweeters";
}
if (scalar(@updated_retweets) > 0) {
local $\ = undef;
open (my $message_fh, '>', $files{retweets}) or die "Can't open $files{retweets}. $!";
print join("\n",@updated_retweets);
print $message_fh join("\n",@updated_retweets);
close($message_fh);
print "\n";
}
# End retweets
}
open(my $gen_acct_file,'>',get_data('Twitter','account_totals.txt')) or die "Can't open account_totals.txt. $!";
print $gen_acct_file join("\n",@accounts_totals);
close($gen_acct_file);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment