summaryrefslogtreecommitdiff
path: root/twitlist.pl
diff options
context:
space:
mode:
Diffstat (limited to 'twitlist.pl')
-rw-r--r--twitlist.pl111
1 files changed, 91 insertions, 20 deletions
diff --git a/twitlist.pl b/twitlist.pl
index 57774a3..fe049a0 100644
--- a/twitlist.pl
+++ b/twitlist.pl
@@ -10,6 +10,8 @@ use Try::Tiny;
use Safe::Isa;
use open ':std',':locale';
+my $WRITING=0;
+
use Data::Printer;
sub get_twitter {
@@ -63,7 +65,7 @@ sub fetch_friends_info {
});
my %friends_info = map {
- $_->{id} => { name => $_->{name} }
+ $_->{id} => { $_->%{qw(name screen_name)} }
} $friends->@*;
return \%friends_info;
@@ -105,24 +107,16 @@ sub print_friends_lists_matrix {
my ($li,$fi) = @_;
my @lists = to_list($li);
- my $list_width = set_display_name(\@lists);
+ 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}}
- ? '*' : '_' );
- }
+ printf '%-*s : ',$friend_width,$f->{dn};
+ print join ', ',
+ map { $_->{dn} }
+ grep { $_->{members}->{$f->{id}} }
+ @lists;
print "\n";
}
}
@@ -131,14 +125,84 @@ 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;
+ $l =~ s{\A.*?\((\d+)\)\s+:}{} or next;
my $friend_id = $1;
-
+ my @lists = map { s{\A\s*(.*?)\s*\z}{$1}r } split ',',$l;
+ for my $list (@lists) {
+ my ($list_name,$list_id) = ($list =~ m{\A(.*?)(?:\s+\((\d+)\))?\z});
+ next unless $list_name;
+ my $list_data = $lists{$list_name}||={};
+ if ($list_id && $list_data->{id}) {
+ if ($list_data->{id} != $list_id) {
+ warn "List $list_name id conflict for friend $friend_id";
+ }
+ }
+ else {
+ $list_data->{id} ||= $list_id;
+ }
+ $list_data->{members}->{$friend_id} = 1;
+ }
+ }
+ return \%lists;
+}
+
+sub make_it_so {
+ my ($tw,$current_lists,$wanted_lists) = @_;
+
+ my @operations;
+ # first, lists to create
+ for my $list (keys $wanted_lists->%*) {
+ if ($current_lists->{$list}) {
+ $wanted_lists->{$list}{id} ||= $current_lists->{$list}{id};
+ if ($wanted_lists->{$list}{id} != $current_lists->{$list}{id}) {
+ warn "list $list has conflicting ids!\n";
+ }
+ }
+ else {
+ warn "creating $list\n";
+ my $list_data;
+ if ($WRITING) {
+ $list_data = $tw->create_list({name=>$list,mode=>'private'});
+ }
+ else {
+ $list_data = { id => int(rand(10000)) };
+ }
+ $current_lists->{$list} = {
+ $list_data->%{id},
+ members => {},
+ };
+ }
+ }
+ # then, set members
+ for my $list (keys $wanted_lists->%*) {
+ warn "operating on $list\n";
+ my %current_members = $current_lists->{$list}->{members}->%*;
+ my %wanted_members = $wanted_lists->{$list}{members}->%*;
+ my %to_add = %wanted_members; delete @to_add{keys %current_members};
+ my %to_remove = %current_members; delete @to_remove{keys %wanted_members};
+ my @to_remove=keys %to_remove;
+ while (my @these = splice @to_remove,0,100) {
+ warn "Removing @these from $list\n";
+ if ($WRITING) {
+ $tw->remove_list_members({
+ list_id => $current_lists->{$list}{id},
+ user_id => \@these,
+ });
+ }
+ }
+ my @to_add=keys %to_add;
+ while (my @these = splice @to_add,0,100) {
+ warn "Adding @these to $list\n";
+ if ($WRITING) {
+ $tw->add_list_members({
+ list_id => $current_lists->{$list}{id},
+ user_id => \@these,
+ });
+ }
+ }
}
}
@@ -155,11 +219,18 @@ try {
$friends_info = fetch_friends_info($tw);
save_info($lists_info,$friends_info);
}
- print_friends_lists_matrix($lists_info,$friends_info);
+ if (@ARGV) {
+ my $wanted_lists = parse_friends_lists_matrix($ARGV[0]);
+ make_it_so($tw,$lists_info,$wanted_lists);
+ }
+ else {
+ print_friends_lists_matrix($lists_info,$friends_info);
+ }
} catch {
if ($_->$_isa('Net::Twitter::Error')) {
my $limit = $tw->rate_limit_status;
p $limit;
+ p $_;
}
else { local $@=$_;die }
};