From 6c4329d4e4ff25e5afc220bb348323ef312560fc Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 19 Dec 2015 11:48:23 +0000 Subject: first stab --- twitlist.pl | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 twitlist.pl diff --git a/twitlist.pl b/twitlist.pl new file mode 100644 index 0000000..57774a3 --- /dev/null +++ b/twitlist.pl @@ -0,0 +1,165 @@ +#!perl +use strict; +use warnings; +use 5.020; +use experimental 'postderef'; +use Net::Twitter; +use Path::Tiny; +use JSON; +use Try::Tiny; +use Safe::Isa; +use open ':std',':locale'; + +use Data::Printer; + +sub get_twitter { + my $config_file = $0 =~ s{\.[^.]+$}{.json}r; + my $conf = decode_json(path($config_file)->slurp_raw); + return Net::Twitter->new(traits=>[ + 'API::RESTv1_1', + 'AutoCursor', + 'AutoCursor' => { + max_calls => 15, + force_cursor => 1, + array_accessor => 'users', + methods => [qw(friends followers)], + }, + ],%$conf); +} + +sub fetch_lists_info { + my ($tw) = @_; + + my $lists = $tw->list_ownerships({ + count => 200, + }); + my %lists_info = map { + $_->{id} => { + name => $_->{name}, + }, + } $lists->{lists}->@*; + + for my $list_id (sort keys %lists_info) { + my $members = $tw->list_members({ + list_id => $list_id, + count => 2000, + skip_status => 1, + include_entities => 0, + }); + $lists_info{$list_id}->{members}={ + map { $_->{id} => 1 } $members->{users}->@*, + }; + } + return \%lists_info; +} + +sub fetch_friends_info { + my ($tw) = @_; + + my $friends = $tw->friends({ + count => 200, + skip_status => 1, + include_user_entities => 0, + }); + + my %friends_info = map { + $_->{id} => { name => $_->{name} } + } $friends->@*; + + return \%friends_info; +} + +sub cache_file { $0 =~ s{\.[^.]+$}{-cache.json}r }; + +sub load_info { + return try { decode_json(path(cache_file)->slurp_raw) }; +} + +sub save_info { + path(cache_file)->spew_raw(encode_json({ + lists=>$_[0], + friends=>$_[1], + })); + return; +} + +sub to_list { + sort { + $a->{name} cmp $b->{name} + } map { + { id => $_, $_[0]->{$_}->%* } + } keys $_[0]->%* +} + +sub set_display_name { + my $max=0; + for my $e ($_[0]->@*) { + $e->{dn} = sprintf '%s (%d)',$e->@{qw(name id)}; + my $l = length($e->{dn}); + $max = $l if $max<$l; + } + return $max; +} + +sub print_friends_lists_matrix { + my ($li,$fi) = @_; + + my @lists = to_list($li); + my $list_width = set_display_name(\@lists); + my @friends = to_list($fi); + my $friend_width = set_display_name(\@friends); + + print ' ' x ($friend_width+1); + for my $l (@lists) { + print $l->{dn},' '; + } + print "\n"; + + for my $f (@friends) { + printf '%-*s ',$friend_width,$f->{dn}; + for my $l (@lists) { + printf '%-*s ', + length($l->{dn}), + ( $l->{members}->{$f->{id}} + ? '*' : '_' ); + } + print "\n"; + } +} + +sub parse_friends_lists_matrix { + my ($fn) = @_; + + my @lines = path($fn)->lines_utf8; + my @list_ids = $lines[0] =~ m{\((\d+)\)}g; + shift @lines; + + my %lists; + for my $l (@lines) { + $l =~ s{\A.*?\((\d+)\)\s+}{} or next; + my $friend_id = $1; + + } +} + +my $tw = get_twitter; +try { + my $lists_info; + my $friends_info; + my $info = load_info(); + if ($info) { + ($lists_info,$friends_info) = $info->@{qw(lists friends)}, + } + else { + $lists_info = fetch_lists_info($tw); + $friends_info = fetch_friends_info($tw); + save_info($lists_info,$friends_info); + } + print_friends_lists_matrix($lists_info,$friends_info); +} catch { + if ($_->$_isa('Net::Twitter::Error')) { + my $limit = $tw->rate_limit_status; + p $limit; + } + else { local $@=$_;die } +}; -- cgit v1.2.3