[twirssi] Upgrade to 2.6.0
Julian C. Dunn
jdunn at fedoraproject.org
Sat Jun 15 03:42:22 UTC 2013
commit c5dc33c2c5025b840a88831cc8d1f2e51603d5bf
Author: Julian C. Dunn <jdunn at aquezada.com>
Date: Fri Jun 14 23:42:07 2013 -0400
Upgrade to 2.6.0
twirssi-2.5.1.pl => twirssi-2.6.0.pl | 588 +++++++++++++++++++++-------------
1 files changed, 357 insertions(+), 231 deletions(-)
---
diff --git a/twirssi-2.5.1.pl b/twirssi-2.6.0.pl
similarity index 88%
rename from twirssi-2.5.1.pl
rename to twirssi-2.6.0.pl
index dfc4b90..4d97a9d 100644
--- a/twirssi-2.5.1.pl
+++ b/twirssi-2.6.0.pl
@@ -17,16 +17,16 @@ $Data::Dumper::Indent = 1;
use vars qw($VERSION %IRSSI);
-$VERSION = sprintf '%s', q$Version: v2.5.1$ =~ /^\w+:\s+v(\S+)/;
+$VERSION = sprintf '%s', q$Version: v2.6.0$ =~ /^\w+:\s+v(\S+)/;
%IRSSI = (
- authors => 'Dan Boger',
+ authors => '@zigdon, @gedge',
contact => 'zigdon at gmail.com',
name => 'twirssi',
description => 'Send twitter updates using /tweet. '
. 'Can optionally set your bitlbee /away message to same',
license => 'GNU GPL v2',
url => 'http://twirssi.com',
- changed => '$Date: 2012-02-07 22:34:25 +0000$',
+ changed => '$Date: 2013-06-08 13:30:00 +0000$',
);
my $twit; # $twit is current logged-in Net::Twitter object (usually one of %twits)
@@ -92,6 +92,7 @@ my @settings_defn = (
[ 'poll_store', 'twirssi_poll_store', 's', Irssi::get_irssi_dir . "/scripts/$IRSSI{name}.polls" ],
[ 'id_store', 'twirssi_id_store', 's', Irssi::get_irssi_dir . "/scripts/$IRSSI{name}.ids" ],
[ 'retweet_format', 'twirssi_retweet_format', 's', 'RT $n: "$t" ${-- $c$}' ],
+ [ 'retweeted_format', 'twirssi_retweeted_format', 's', 'RT $n: $t' ],
[ 'stripped_tags', 'twirssi_stripped_tags', 's', '', 'list{,}' ],
[ 'topic_color', 'twirssi_topic_color', 's', '%r', ],
[ 'timestamp_format', 'twirssi_timestamp_format', 's', '%H:%M:%S', ],
@@ -109,8 +110,10 @@ my @settings_defn = (
[ 'url_args', 'short_url_args', 's', undef ],
[ 'window', 'twitter_window', 's', 'twitter' ],
[ 'debug_win_name', 'twirssi_debug_win_name', 's', '' ],
+ [ 'limit_user_tweets', 'twitter_user_results', 's', '20' ],
[ 'always_shorten', 'twirssi_always_shorten', 'b', 0 ],
+ [ 'rt_to_expand', 'twirssi_retweet_to_expand', 'b', 1 ],
[ 'avoid_ssl', 'twirssi_avoid_ssl', 'b', 0 ],
[ 'debug', 'twirssi_debug', 'b', 0 ],
[ 'notify_timeouts', 'twirssi_notify_timeouts', 'b', 1 ],
@@ -195,7 +198,7 @@ sub cmd_direct_as {
eval {
if ( $twits{$username}
- ->new_direct_message( { user => $target, text => $text } ) ) {
+ ->new_direct_message( { screen_name => $target, text => $text } ) ) {
¬ice( [ "dm", $target_norm ], "DM sent to $target: $text" );
$nicks{$target} = time;
} else {
@@ -254,7 +257,7 @@ sub cmd_retweet_as {
return;
}
- $id = $state{__indexes}{lc $nick} unless $id;
+ $id = $state{__indexes}{lc $nick} unless defined $id;
unless ( $state{__ids}{ lc $nick }[$id] ) {
¬ice( [ "tweet", $username ],
"Can't find a tweet numbered $id from $nick to retweet!" );
@@ -267,16 +270,8 @@ sub cmd_retweet_as {
return;
}
-# Irssi::settings_add_str( $IRSSI{name}, "twirssi_retweet_format", 'RT $n: $t ${-- $c$}' );
- my $text = $settings{retweet_format};
- $text =~ s/\$n/\@$nick/g;
- if ($data) {
- $text =~ s/\${|\$}//g;
- $text =~ s/\$c/$data/;
- } else {
- $text =~ s/\${.*?\$}//;
- }
- $text =~ s/\$t/$state{__tweets}{ lc $nick }[$id]/;
+ my $text = &format_expand(fmt => $settings{retweet_format}, nick => $nick, data => $data,
+ tweet => $state{__tweets}{ lc $nick }[$id]);
my $modified = $data;
$data = &shorten($text);
@@ -323,6 +318,20 @@ sub cmd_retweet_as {
}
+sub format_expand {
+ my %args = @_;
+ $args{fmt} =~ s/\$n/\@$args{nick}/g;
+ if (defined $args{data} and $args{data} ne '') {
+ $args{fmt} =~ s/\${|\$}//g;
+ $args{fmt} =~ s/\$c/$args{data}/g;
+ } else {
+ $args{fmt} =~ s/\${.*?\$}//g;
+ }
+ $args{fmt} =~ s/\$t/$args{tweet}/g;
+ return $args{fmt};
+}
+
+
sub cmd_retweet_to_window {
my ( $data, $server, $win ) = @_;
@@ -337,7 +346,7 @@ sub cmd_retweet_to_window {
return;
}
- $id = $state{__indexes}{lc $nick} unless $id;
+ $id = $state{__indexes}{lc $nick} unless defined $id;
unless ( $state{__ids}{ lc $nick }[$id] ) {
¬ice( [ "tweet" ],
"Can't find a tweet numbered $id from $nick to retweet!" );
@@ -371,16 +380,8 @@ sub cmd_retweet_to_window {
return;
}
- my $text = $settings{retweet_format};
- $text =~ s/\$n/\@$nick/g;
- if ($data) {
- $text =~ s/\${|\$}//g;
- $text =~ s/\$c/$data/;
- } else {
- $text =~ s/\${.*?\$}//;
- }
- my $tweet = &unshorten($state{__tweets}{ lc $nick }[$id]);
- $text =~ s/\$t/$tweet/;
+ my $text = &format_expand(fmt => $settings{retweet_format}, nick => $nick, data => $data,
+ tweet => &post_process_tweet($state{__tweets}{ lc $nick }[$id], not $settings{rt_to_expand}));
Irssi::command("msg $target $text");
@@ -393,6 +394,7 @@ sub cmd_retweet_to_window {
sub cmd_reload {
if ($settings{force_first} and $settings{poll_store}) {
+ &save_state();
&save_polls();
}
Irssi::command("script load $IRSSI{name}");
@@ -517,7 +519,11 @@ sub cmd_info {
my $tweet = $state{__tweets}{$nick}[$id];
my $reply_to_id = $state{__reply_to_ids}{$nick}[$id];
my $reply_to_user = $state{__reply_to_users}{$nick}[$id];
- my $exp_tweet = &unshorten($tweet) if $tweet;
+ my $exp_tweet = $tweet;
+ if ($tweet) {
+ $tweet = &post_process_tweet($tweet, 1);
+ $exp_tweet = &post_process_tweet($exp_tweet);
+ }
my $url = '';
if ( defined $username ) {
@@ -588,7 +594,7 @@ sub cmd_reply_as {
return;
}
- $id = $state{__indexes}{lc $nick} unless $id;
+ $id = $state{__indexes}{lc $nick} unless defined $id;
unless ( $state{__ids}{ lc $nick }[$id] ) {
¬ice( [ "reply", $username ],
"Can't find a tweet numbered $id from $nick to reply to!" );
@@ -664,7 +670,7 @@ sub gen_cmd {
return;
}
- &$post_ref($data) if $post_ref;
+ &$post_ref($data, $server, $win) if $post_ref;
}
}
@@ -810,14 +816,6 @@ sub cmd_login {
} elsif ( @{ $settings{usernames} } and @{ $settings{passwords} } ) {
&debug("autouser login");
- # if a password ends with a '\', it was meant to escape the comma, and
- # it should be concatinated with the next one
- for (my $i = 0; $i+1 < @{ $settings{passwords} }; $i++) {
- while ( $settings{passwords}->[$i] =~ /\\$/ ) {
- $settings{passwords}->[$i] .= "," . delete $settings{passwords}->[$i+1];
- }
- }
-
if ( @{ $settings{usernames} } != @{ $settings{passwords} } ) {
¬ice( ["error"],
"Number of usernames doesn't match "
@@ -861,7 +859,7 @@ sub cmd_login {
} else {
$twit = Net::Twitter->new(
traits =>
- [ 'API::REST', 'OAuth', 'API::Search', 'API::Lists', 'RetryOnError' ],
+ [ 'API::RESTv1_1', 'OAuth', 'RetryOnError' ],
(
grep tr/a-zA-Z/n-za-mN-ZA-M/, map $_,
pbafhzre_xrl => 'OMINiOzn4TkqvEjKVioaj',
@@ -955,7 +953,7 @@ sub cmd_oauth {
};
if ($@) {
- ¬ice( ["error"], "Invalid pin, try again." );
+ ¬ice( ["error"], "Invalid pin, try again: $@" );
return;
}
@@ -1002,12 +1000,19 @@ sub rate_limited {
eval {
$rate_limit = $obj->rate_limit_status();
};
- if ( $rate_limit and $rate_limit->{remaining_hits} < 1 ) {
- ¬ice( [ 'error', $username, $fh ],
- "Rate limit exceeded, try again after $rate_limit->{reset_time}" );
- return 1;
+ my $res = 0;
+ if ( $rate_limit and $rate_limit->{resources} ) {
+ for my $resource (keys %{ $rate_limit->{resources} }) {
+ for my $uri (keys %{ $rate_limit->{resources}->{$resource} }) {
+ if ( $rate_limit->{resources}->{$resource}->{$uri}->{remaining} < 1 ) {
+ ¬ice( [ 'error', $username, $fh ],
+ "Rate limit exceeded for $resource ($uri), try again after $rate_limit->{resources}->{$resource}->{$uri}->{reset}" );
+ $res = 1;
+ }
+ }
+ }
}
- return 0;
+ return $res;
}
sub verify_twitter_object {
@@ -1148,7 +1153,11 @@ sub cmd_add_search {
$state{__last_id}{"$user\@$defservice"}{__search}{$data} = 1;
¬ice( [ "search", $data ], "Added subscription for '$data'" );
- &cmd_set_window("search $data $data", $server, $win) if $want_win;
+ if ($want_win) {
+ my $win_name = $data;
+ $win_name =~ tr/ /+/;
+ &cmd_set_window("search $data $win_name", $server, $win);
+ }
}
sub cmd_del_search {
@@ -1182,11 +1191,11 @@ sub cmd_list_search {
my $found = 0;
foreach my $suser ( sort keys %{ $state{__last_id} } ) {
- my $topics;
+ my $topics = '';
foreach my $topic ( sort keys %{ $state{__last_id}{$suser}{__search} } ) {
- $topics = $topics ? "$topics, $topic" : $topic;
+ $topics .= ($topics ne '' ? ', ' : '') . "'$topic'";
}
- if ($topics) {
+ if ($topics ne '') {
$found = 1;
¬ice( ["search"], "Search subscriptions for $suser: $topics" );
}
@@ -1415,7 +1424,7 @@ sub cmd_set_window {
¬ice("Changing the default twirssi window to $winname");
Irssi::settings_set_str( "twitter_window", $winname );
&ensure_logfile($settings{window} = $winname);
- } elsif ( @words > 2 ) {
+ } elsif ( @words > 2 and $words[0] ne 'search' ) {
¬ice(
"Too many arguments to /twirssi_set_window. '@words'",
"Usage: /twirssi_set_window [type] [account|search_term] [window].",
@@ -1433,7 +1442,7 @@ sub cmd_set_window {
}
my $tag = "default";
- if ( @words == 2 ) {
+ if ( @words >= 2 ) {
$tag = lc $words[1];
if ($type eq 'sender') {
$tag =~ s/^\@//;
@@ -1442,6 +1451,8 @@ sub cmd_set_window {
and ($type ne 'default' or index($tag, '@') >= 0)
and $tag ne 'default') {
$tag = &normalize_username($tag);
+ } elsif ($type eq 'search' and @words > 2) {
+ $tag = lc join(' ', @words[1..$#words]);
}
if (substr($tag, -1, 1) eq '@') {
¬ice(['error'], "Invalid tag '$tag'.");
@@ -1577,7 +1588,7 @@ sub get_lists {
# ensure $new_lists->{$list_name} = $id
my %more_args = ();
my $new_lists = &scan_cursor('lists', $u_twit, $username, $fh,
- { fn=>'get_lists', cp=>'c', set_key=>'lists',
+ { fn=>'get_lists', cp=>'', set_key=>'lists',
args=>{ user=>$userid, %more_args }, item_key=>'name', item_val=>'id', });
return if not defined $new_lists;
@@ -1625,7 +1636,7 @@ sub get_blocks {
my $is_update = shift;
my $new_blocks = &scan_cursor('blocks', $u_twit, $username, $fh,
- { fn=>'blocking', cp=>'p', item_key=>'screen_name', });
+ { fn=>'blocking', cp=>'c', set_key=>'users', item_key=>'screen_name', });
return if not defined $new_blocks;
return $new_blocks if not $is_update;
@@ -1707,7 +1718,11 @@ sub cmd_wipe {
sub cmd_user {
my $target = shift;
+ my $server = shift;
+ my $win = shift;
$target =~ s/(?::\d+)?\s*$//;
+ &cmd_set_window("sender $target $target", $server, $win)
+ if $target =~ s/^\s*-w\s+// and $target ne '';
&get_updates([ 0, [
[ "$user\@$defservice", { up_user => $target } ],
],
@@ -1724,8 +1739,7 @@ sub tweet_to_meta {
username => $username,
type => $type,
nick => ($type eq 'dm' ? $t->{sender_screen_name}
- : ($type =~ /^search/ ? $t->{from_user}
- : $t->{user}{screen_name})),
+ : $t->{user}{screen_name}),
);
($meta{account}, $meta{service}) = split('@', $username, 2);
foreach my $meta_key (keys %meta_to_twit) {
@@ -1791,7 +1805,7 @@ sub background_setup {
if ($child_pid) { # parent
Irssi::timeout_add_once( $pause_monitor, 'monitor_child',
- [ $done_filename, $max_pauses, $pause_monitor, $is_update ] );
+ [ $done_filename, $max_pauses, $pause_monitor, $is_update, $filename . '.' . $child_pid, 0 ] );
Irssi::pidwait_add($child_pid);
} elsif ( defined $child_pid ) { # child
my $pid_filename = $filename . '.' . $$;
@@ -1876,6 +1890,7 @@ sub get_updates_child {
my $time_before_update = time;
my $error = 0;
+ my @error_types = ();
my %context_cache;
foreach my $update_tuple ( @$to_be_updated ) {
@@ -1885,14 +1900,20 @@ sub get_updates_child {
if (0 == keys(%$what_to_update)
or defined $what_to_update->{up_tweets}) {
- $error++ unless &get_tweets( $fh, $username, $twits{$username}, \%context_cache );
+ unless (&get_tweets( $fh, $username, $twits{$username}, \%context_cache )) {
+ $error++;
+ push @error_types, 'tweets';
+ }
if ( exists $state{__last_id}{$username}{__extras}
and keys %{ $state{__last_id}{$username}{__extras} } ) {
my @frusers = sort keys %{ $state{__last_id}{$username}{__extras} };
- $error++ unless &get_timeline( $fh, $frusers[ $fix_replies_index{$username} ],
- $username, $twits{$username}, \%context_cache, $is_regular );
+ unless (&get_timeline( $fh, $frusers[ $fix_replies_index{$username} ],
+ $username, $twits{$username}, \%context_cache, $is_regular )) {
+ $error++;
+ push @error_types, 'replies';
+ }
$fix_replies_index{$username}++;
$fix_replies_index{$username} = 0
@@ -1904,27 +1925,39 @@ sub get_updates_child {
next if $error > $errors_beforehand;
if (defined $what_to_update->{up_user}) {
- $error++ unless &get_timeline( $fh, $what_to_update->{up_user},
- $username, $twits{$username}, \%context_cache, $is_regular );
+ unless (&get_timeline( $fh, $what_to_update->{up_user},
+ $username, $twits{$username}, \%context_cache, $is_regular )) {
+ $error++;
+ push @error_types, 'tweets';
+ }
}
next if $error > $errors_beforehand;
if (0 == keys(%$what_to_update)
or defined $what_to_update->{up_dms}) {
- $error++ unless &do_dms( $fh, $username, $twits{$username}, $is_regular );
+ unless (&do_dms( $fh, $username, $twits{$username}, $is_regular )) {
+ $error++;
+ push @error_types, 'dms';
+ }
}
next if $error > $errors_beforehand;
if (0 == keys(%$what_to_update)
or defined $what_to_update->{up_subs}) {
- $error++ unless &do_subscriptions( $fh, $username, $twits{$username}, $what_to_update->{up_subs} );
+ unless (&do_subscriptions( $fh, $username, $twits{$username}, $what_to_update->{up_subs} )) {
+ $error++;
+ push @error_types, 'subs';
+ }
}
next if $error > $errors_beforehand;
if (0 == keys(%$what_to_update)
or defined $what_to_update->{up_searches}) {
- $error++ unless &do_searches( $fh, $username, $twits{$username}, $what_to_update->{up_searches} );
+ unless (&do_searches( $fh, $username, $twits{$username}, $what_to_update->{up_searches} )) {
+ $error++;
+ push @error_types, 'searches';
+ }
}
next if $error > $errors_beforehand;
@@ -1990,6 +2023,7 @@ sub get_updates_child {
if (not defined &get_lists($twits{$username}, $username, $fh, 0, @{ $what_to_update->{up_lists} })) {
&debug($fh, "%G$username%n Polling for lists failed.");
$error++;
+ push @error_types, 'lists';
}
}
if (not defined $state{__lists}{$list_account}) {
@@ -2014,7 +2048,8 @@ sub get_updates_child {
&put_unshorten_urls($fh, $time_before_update);
if ($error) {
- ¬ice( [ 'error', undef, $fh ], "Update encountered errors. Aborted");
+ ¬ice( [ 'error', undef, $fh ], "Update encountered errors (@error_types). Aborted");
+ ¬ice( [ 'error', undef, $fh ], "For recurring DMs errors, please re-auth (delete $settings{oauth_store})") if grep { $_ eq 'dms' } @error_types;
} elsif ($is_regular) {
print $fh "t:last_poll poll_type:__poll epoch:$time_before_update\n";
}
@@ -2050,15 +2085,14 @@ sub get_tweets {
return if &rate_limited($obj, $username, $fh);
&debug($fh, "%G$username%n Polling for tweets");
- my $tweets;
- my $new_poll_id = 0;
+ my $tweets = [];
eval {
my %call_attribs = ( page => 1 );
$call_attribs{count} = $settings{track_replies} if $settings{track_replies};
- # $call_attribs{since_id} = $state{__last_id}{$username}{timeline}
- # if defined $state{__last_id}{$username}{timeline};
+ $call_attribs{since_id} = $state{__last_id}{$username}{timeline}
+ if defined $state{__last_id}{$username}{timeline};
for ( ; $call_attribs{page} < 2 ; $call_attribs{page}++) {
- &debug($fh, "%G$username%n timeline pg=" . $call_attribs{page});
+ &debug($fh, "%G$username%n timeline " . join(' ', map { $_ . '=' . $call_attribs{$_} } sort keys %call_attribs));
my $page_tweets = $obj->home_timeline( \%call_attribs );
last if not defined $page_tweets or @$page_tweets == 0;
unshift @$tweets, @$page_tweets;
@@ -2071,6 +2105,9 @@ sub get_tweets {
return;
}
+
+=pod
+
unless ( ref $tweets ) {
if ( $obj->can("get_error") ) {
my $error = "Unknown error";
@@ -2082,15 +2119,22 @@ sub get_tweets {
} else {
¬ice([ 'error', $username, $fh],
- "$username: API Error during home_timeline call. Aborted.");
+ "$username: API Error in home_timeline call. Aborted.");
}
return;
}
- print $fh "t:debug %G$username%n got ", scalar(@$tweets), " tweets, first/last: ",
- (sort {$a->{id} <=> $b->{id}} @$tweets)[0]->{id}, "/",
- (sort {$a->{id} <=> $b->{id}} @$tweets)[$#{$tweets}]->{id}, "\n";
+=cut
+
+ print $fh "t:debug %G$username%n got ", scalar(@$tweets), ' tweets',
+ (@$tweets ? ', first/last: ' . join('/',
+ (sort {$a->{id} <=> $b->{id}} @$tweets)[0]->{id},
+ (sort {$a->{id} <=> $b->{id}} @$tweets)[$#{$tweets}]->{id}
+ )
+ : ''),
+ "\n";
+ my $new_poll_id = 0;
my @own_ids = ();
foreach my $t ( reverse @$tweets ) {
my $text = &get_text( $t, $obj );
@@ -2110,10 +2154,9 @@ sub get_tweets {
$new_poll_id = $t->{id} if $new_poll_id < $t->{id};
}
&debug($fh, "%G$username%n skip own " . join(', ', @own_ids) . "\n") if @own_ids;
- printf $fh "t:last_id id:%s ac:%s id_type:timeline\n", $new_poll_id, $username;
+ printf $fh "t:last_id id:%s ac:%s id_type:timeline\n", $new_poll_id, $username if $new_poll_id;
&debug($fh, "%G$username%n Polling for replies since " . $state{__last_id}{$username}{reply});
- $new_poll_id = 0;
eval {
if ( $state{__last_id}{$username}{reply} ) {
$tweets = $obj->replies( { since_id => $state{__last_id}{$username}{reply} } )
@@ -2125,9 +2168,11 @@ sub get_tweets {
if ($@) {
print $fh "t:debug %G$username%n Error during replies call. Aborted.\n";
+ &debug($fh, "%G$username%n Error: " . $@);
return;
}
+ $new_poll_id = 0;
foreach my $t ( reverse @$tweets ) {
next if exists $friends{$username}{ $t->{user}{screen_name} };
@@ -2141,7 +2186,7 @@ sub get_tweets {
$t->{id}, $username, $ign, &get_reply_to($t), $t->{user}{screen_name},
&encode_for_file($t->{created_at}), $text;
}
- printf $fh "t:last_id id:%s ac:%s id_type:reply\n", $new_poll_id, $username;
+ printf $fh "t:last_id id:%s ac:%s id_type:reply\n", $new_poll_id, $username if $new_poll_id;
return 1;
}
@@ -2166,6 +2211,7 @@ sub do_dms {
};
if ($@) {
&debug($fh, "%G$username%n Error during direct_messages call. Aborted.");
+ &debug($fh, "%G$username%n Error: " . $@);
return;
}
&debug($fh, "%G$username%n got DMs: " . (0+@$tweets));
@@ -2178,7 +2224,7 @@ sub do_dms {
&encode_for_file($t->{created_at}), $text;
$new_poll_id = $t->{id} if $new_poll_id < $t->{id};
}
- printf $fh "t:last_id id:%s ac:%s id_type:dm\n", $new_poll_id, $username;
+ printf $fh "t:last_id id:%s ac:%s id_type:dm\n", $new_poll_id, $username if $new_poll_id;
return 1;
}
@@ -2204,28 +2250,29 @@ sub do_subscriptions {
if ($@) {
print $fh
"t:debug %G$username%n Error during search($topic) call. Aborted.\n";
+ &debug($fh, "%G$username%n Error: " . $@);
return;
}
- unless ( $search->{max_id} ) {
+ unless ( $search->{search_metadata}->{max_id} ) {
print $fh "t:debug %G$username%n Invalid search results when searching",
- " for $topic. Aborted.\n";
+ " for '$topic'. Aborted.\n";
return;
}
- $state{__last_id}{$username}{__search}{$topic} = $search->{max_id};
+ $state{__last_id}{$username}{__search}{$topic} = $search->{search_metadata}->{max_id};
printf $fh "t:searchid id:%s ac:%s topic:%s\n",
- $search->{max_id}, $username, &encode_for_file($topic);
+ $search->{search_metadata}->{max_id}, $username, &encode_for_file($topic);
- foreach my $t ( reverse @{ $search->{results} } ) {
- next if exists $blocks{$username}{ $t->{from_user} };
+ foreach my $t ( reverse @{ $search->{statuses} } ) {
+ next if exists $blocks{$username}{ $t->{user}->{screen_name} };
my $text = &get_text( $t, $obj );
$text = &remove_tags($text);
- my $ign = &is_ignored($text, $t->{from_user});
+ my $ign = &is_ignored($text, $t->{user}->{screen_name});
&get_unshorten_urls($text, $fh);
$ign = (defined $ign ? 'ign:' . &encode_for_file($ign) . ' ' : '');
printf $fh "t:search id:%s ac:%s %snick:%s topic:%s created_at:%s %s\n",
- $t->{id}, $username, $ign, $t->{from_user}, $topic,
+ $t->{id}, $username, $ign, $t->{user}->{screen_name}, &encode_for_file($topic),
&encode_for_file($t->{created_at}), $text;
}
}
@@ -2243,16 +2290,20 @@ sub do_searches {
next if defined $search_limit and @$search_limit and not grep { $topic eq $_ } @$search_limit;
my $max_results = $search_once{$username}->{$topic};
+ $topic = &make_utf8($topic);
+
print $fh
"t:debug %G$username%n search $topic once (max $max_results)\n";
eval { $search = $obj->search( { 'q' => $topic } ); };
- if ($@) {
+ if (my $err = $@) {
+ $err = $err->error . ' (' . $err->code . ' ' . $err->message . ')' if ref($err) eq 'Net::Twitter::Error';
print $fh "t:debug %G$username%n Error during search_once($topic) call. Aborted.\n";
+ &debug($fh, "%G$username%n Error: $err");
return;
}
- unless ( $search->{max_id} ) {
+ unless ( $search->{search_metadata}->{max_id} ) {
print $fh "t:debug %G$username%n Invalid search results when searching once",
" for $topic. Aborted.\n";
return;
@@ -2260,9 +2311,9 @@ sub do_searches {
# TODO: consider applying ignore-settings to search results
my @results = ();
- foreach my $res (@{ $search->{results} }) {
- if (exists $blocks{$username}{ $res->{from_user} }) {
- print $fh "t:debug %G$username%n blocked $topic: $res->{from_user}\n";
+ foreach my $res (@{ $search->{statuses} }) {
+ if (exists $blocks{$username}{ $res->{user}->{screen_name} }) {
+ print $fh "t:debug %G$username%n blocked $topic: $res->{user}->{screen_name}\n";
next;
}
push @results, $res;
@@ -2274,10 +2325,10 @@ sub do_searches {
my $text = &get_text( $t, $obj );
$text = &remove_tags($text);
&get_unshorten_urls($text, $fh);
- my $ign = &is_ignored($text, $t->{from_user});
+ my $ign = &is_ignored($text, $t->{user}->{screen_name});
$ign = (defined $ign ? 'ign:' . &encode_for_file($ign) . ' ' : '');
printf $fh "t:search_once id:%s ac:%s %s%snick:%s topic:%s created_at:%s %s\n",
- $t->{id}, $username, $ign, &get_reply_to($t), $t->{from_user}, &encode_for_file($topic),
+ $t->{id}, $username, $ign, &get_reply_to($t), $t->{user}->{screen_name}, &encode_for_file($topic),
&encode_for_file($t->{created_at}), $text;
}
}
@@ -2297,6 +2348,8 @@ sub get_timeline {
if ($is_update) {
$arg_ref->{since_id} = $last_id if $last_id;
$arg_ref->{include_rts} = 1 if $settings{retweet_show};
+ } elsif ($settings{limit_user_tweets} and $settings{limit_user_tweets} =~ /\b(\d+)\b/) {
+ $arg_ref->{count} = $1;
}
eval {
$tweets = $obj->user_timeline($arg_ref);
@@ -2313,7 +2366,9 @@ sub get_timeline {
return 1;
}
+ my $not_before = time - $1*86400 if not $is_update and $settings{limit_user_tweets} and $settings{limit_user_tweets} =~ /\b(\d+)d\b/;
foreach my $t ( reverse @$tweets ) {
+ next if defined $not_before and &date_to_epoch($t->{created_at}) < $not_before;
my $text = &get_text( $t, $obj );
my $reply = &tweet_or_reply($obj, $t, $username, $cache, $fh);
printf $fh "t:%s id:%s ac:%s %snick:%s created_at:%s %s\n",
@@ -2378,7 +2433,7 @@ sub meta_to_line {
level => MSGLEVEL_PUBLIC,
);
- if ($meta->{type} eq 'dm' or $meta->{type} eq 'error') {
+ if ($meta->{type} eq 'dm' or $meta->{type} eq 'error' or $meta->{type} eq 'deerror') {
$line_attribs{level} = MSGLEVEL_MSGS;
}
@@ -2388,6 +2443,10 @@ sub meta_to_line {
$line_attribs{level} |= MSGLEVEL_HILIGHT;
$line_attribs{hi_nick} = "\cC$hilight_color$meta->{nick}\cO";
}
+ elsif ($settings{nick_color} eq 'rotate') {
+ my $c = get_nick_color($meta->{nick});
+ $line_attribs{hi_nick} = "\cC$c$meta->{nick}\cO";
+ }
if (defined $meta->{ign}) {
$line_attribs{ignoring} = 1;
@@ -2449,8 +2508,16 @@ sub monitor_child {
my $attempts_to_go = $args->[1];
my $wait_time = $args->[2];
my $is_update = $args->[3];
+ my $filename_tmp = $args->[4];
+ my $prev_mtime = $args->[5];
- &debug("checking child log at $filename ($attempts_to_go)");
+ my $file_progress = 'no ' . $filename_tmp;
+ my $this_mtime = $prev_mtime;
+ if (-f $filename_tmp) {
+ $this_mtime = (stat(_))[9];
+ $file_progress = 'mtime=' . $this_mtime;
+ }
+ &debug("checking child log at $filename [$file_progress v $prev_mtime] ($attempts_to_go)");
# reap any random leftover processes - work around a bug in irssi on gentoo
waitpid( -1, WNOHANG );
@@ -2468,32 +2535,92 @@ sub monitor_child {
if ( -e $filename and open $fh, '<', $filename ) {
binmode $fh, ":" . &get_charset();
} else {
- undef $fh;
+ # file not ready yet
+
+ if ( $attempts_to_go > 0 ) {
+ Irssi::timeout_add_once( $wait_time, 'monitor_child',
+ [ $filename, $attempts_to_go - 1, $wait_time, $is_update, $filename_tmp, $this_mtime ] );
+ } else {
+ &debug("Giving up on polling $filename");
+ Irssi::pidwait_remove($child_pid);
+ waitpid( -1, WNOHANG );
+ unlink $filename unless &debug();
+
+ if (not $is_update) {
+ ¬ice([ 'error' ], "Failed to get response. Giving up.");
+ return;
+ }
+
+ $update_is_running = 0 if $is_update;
+
+ return unless $settings{notify_timeouts};
+
+ my $since;
+ if ( time - $last_poll{__poll} < 24 * 60 * 60 ) {
+ my @time = localtime($last_poll{__poll});
+ $since = sprintf( "%d:%02d", @time[ 2, 1 ] );
+ } else {
+ $since = scalar localtime($last_poll{__poll});
+ }
+
+ if ( $failstatus < 2 and time - $last_poll{__poll} > 60 * 60 ) {
+ ¬ice([ 'error' ],
+ $settings{mini_whale}
+ ? 'FAIL WHALE'
+ : q{ v v v},
+ q{ | | v | v},
+ q{ | .-, | | |},
+ q{ .--./ / | _.---.| },
+ q{ '-. (__..-" \\},
+ q{ \\ a |},
+ q{ ',.__. ,__.-'/},
+ q{ '--/_.'----'`}
+ );
+ $failstatus = 2;
+ }
+
+ if ( $failstatus == 0 and time - $last_poll{__poll} < 600 ) {
+ ¬ice([ 'error' ],"Haven't been able to get updated tweets since $since");
+ $failstatus = 1;
+ }
+ }
+
+ return;
}
- while (defined $fh and defined ($_ = <$fh>)) {
+
+ # make sure we're not in slurp mode
+ local $/ = "\n";
+ while (<$fh>) {
unless (/\n$/) { # skip partial lines
&debug($fh, "Skipping partial line: $_");
next;
}
chomp;
- if (s/^t:debug\s+//) {
+ my $type;
+ if (s/^t:(\w+)\s+//) {
+ $type = $1;
+ } else {
+ ¬ice(['error'], "invalid: $_");
+ next;
+ }
+
+ if ($type eq 'debug') {
&debug($_);
- } elsif (s/^t:(error|info)\s+//) {
- my $type = $1;
+ } elsif ($type =~ /^(error|info|deerror)$/) {
$got_errors++ if $type eq 'error';
¬ice([$type], $_);
- } elsif (s/^t:(url)\s+//) {
- my %meta = &cache_to_meta($_, $1, [ qw/epoch https site uri/ ]);
+ } elsif ($type eq 'url') {
+ my %meta = &cache_to_meta($_, $type, [ qw/epoch https site uri/ ]);
$expanded_url{$meta{site}}{$meta{https} ? 1 : 0}{$meta{uri}} = {
url => $meta{text},
epoch => $meta{epoch},
};
- } elsif (s/^t:(last_poll)\s+//) {
- my %meta = &cache_to_meta($_, $1, [ qw/ac poll_type epoch/ ]);
+ } elsif ($type eq 'last_poll') {
+ my %meta = &cache_to_meta($_, $type, [ qw/ac poll_type epoch/ ]);
if ( not defined $meta{ac} and $meta{poll_type} eq '__poll' ) {
$last_poll{$meta{poll_type}} = $meta{epoch};
@@ -2506,13 +2633,13 @@ sub monitor_child {
$got_errors++;
}
- } elsif (s/^t:(fix_replies_index)\s+//) {
- my %meta = &cache_to_meta($_, $1, [ qw/idx ac topic id_type/ ]);
+ } elsif ($type eq 'fix_replies_index') {
+ my %meta = &cache_to_meta($_, $type, [ qw/idx ac topic id_type/ ]);
$fix_replies_index{ $meta{username} } = $meta{idx};
&debug("%G$meta{username}%n fix_replies_index set to $meta{idx}");
- } elsif (s/^t:(searchid|last_id|last_id_fixreplies)\s+//) {
- my %meta = &cache_to_meta($_, $1, [ qw/id ac topic id_type/ ]);
+ } elsif ($type eq 'searchid' or $type eq 'last_id_fixreplies' or $type eq 'last_id') {
+ my %meta = &cache_to_meta($_, $type, [ qw/id ac topic id_type/ ]);
if ( $meta{type} eq 'searchid' ) {
&debug("%G$meta{username}%n Search '$meta{topic}' got id $meta{id}");
if (not exists $state{__last_id}{ $meta{username} }{__search}{ $meta{topic} }
@@ -2530,8 +2657,8 @@ sub monitor_child {
if $state{__last_id}{ $meta{username} }{__extras}{ $meta{id_type} } < $meta{id};
}
- } elsif (s/^t:(tweet|dm|reply|search|search_once)\s+//x) {
- my %meta = &cache_to_meta($_, $1, [ qw/id ac ign reply_to_user reply_to_id nick topic created_at/ ]);
+ } elsif ($type eq 'tweet' or $type eq 'dm' or $type eq 'reply' or $type eq 'search' or $type eq 'search_once') { # cf theme_register
+ my %meta = &cache_to_meta($_, $type, [ qw/id ac ign reply_to_user reply_to_id nick topic created_at/ ]);
if (exists $new_cache{ $meta{id} }) {
&debug("SKIP newly-cached $meta{id}");
@@ -2556,8 +2683,8 @@ sub monitor_child {
delete $search_once{ $meta{username} }->{ $meta{topic} };
}
- } elsif (s/^t:(friend|block|list)\s+//) {
- my %meta = &cache_to_meta($_, $1, [ qw/ac list id nick epoch/ ]);
+ } elsif ($type eq 'friend' or $type eq 'block' or $type eq 'list') {
+ my %meta = &cache_to_meta($_, $type, [ qw/ac list id nick epoch/ ]);
if ($is_update and not defined $types_per_user{$meta{username}}{$meta{type}}) {
if ($meta{type} eq 'friend') {
$friends{$meta{username}} = ();
@@ -2583,120 +2710,67 @@ sub monitor_child {
}
} else {
- ¬ice(['error'], "invalid: $_");
+ ¬ice(['error'], "invalid type ($type): $_");
}
}
- if (defined $fh) {
- # file was opened, so we tried to parse...
- close $fh;
+ # file was opened, so we tried to parse...
+ close $fh;
- # make sure the pid is removed from the waitpid list
- Irssi::pidwait_remove($child_pid);
+ # make sure the pid is removed from the waitpid list
+ Irssi::pidwait_remove($child_pid);
- # and that we don't leave any zombies behind, somehow
- waitpid( -1, WNOHANG );
+ # and that we don't leave any zombies behind, somehow
+ waitpid( -1, WNOHANG );
- &debug("new last_poll = $last_poll{__poll}",
- "new last_poll_id = " . Dumper( $state{__last_id} )) if $is_update;
- if ($is_update and $first_call and not $settings{force_first}) {
- &debug("First call, not printing updates");
- } else {
+ &debug("new last_poll = $last_poll{__poll}",
+ "new last_poll_id = " . Dumper( $state{__last_id} )) if $is_update;
+ if ($is_update and $first_call and not $settings{force_first}) {
+ &debug("First call, not printing updates");
+ } else {
- if (exists $show_now{lists}) {
- for my $list_account (keys %{ $show_now{lists} }) {
- my $list_ac = ($list_account eq "$user\@$defservice" ? '' : "$list_account/");
- for my $list_name (keys %{ $show_now{lists}{$list_account} }) {
- if (0 == @{ $state{__lists}{$list_account}{$list_name}{members} }) {
- ¬ice(['info'], "List $list_ac$list_name is empty.");
- } else {
- ¬ice("List $list_ac$list_name members: " .
- join(', ', @{ $state{__lists}{$list_account}{$list_name}{members} }));
- }
+ if (exists $show_now{lists}) {
+ for my $list_account (keys %{ $show_now{lists} }) {
+ my $list_ac = ($list_account eq "$user\@$defservice" ? '' : "$list_account/");
+ for my $list_name (keys %{ $show_now{lists}{$list_account} }) {
+ if (0 == @{ $state{__lists}{$list_account}{$list_name}{members} }) {
+ ¬ice(['info'], "List $list_ac$list_name is empty.");
+ } else {
+ ¬ice("List $list_ac$list_name members: " .
+ join(', ', @{ $state{__lists}{$list_account}{$list_name}{members} }));
}
}
}
-
- &write_lines(\@lines, $is_update);
- }
-
- unlink $filename or warn "Failed to remove $filename: $!" unless &debug();
-
- # commit the pending cache lines to the actual cache, now that
- # we've printed our output
- for my $updated_id (keys %new_cache) {
- $tweet_cache{$updated_id} = $new_cache{$updated_id};
- }
-
- # keep enough cached tweets, to make sure we don't show duplicates
- for my $loop_id ( keys %tweet_cache ) {
- next if $tweet_cache{$loop_id} >= $last_poll{__poll} - 3600;
- delete $tweet_cache{$loop_id};
- }
-
- if (not $got_errors) {
- &save_state();
}
- if ($is_update) {
- if ($failstatus and not $got_errors) {
- ¬ice([ 'error' ], "Update succeeded.");
- $failstatus = 0;
- }
- $first_call = 0;
- $update_is_running = 0;
- }
- return;
+ &write_lines(\@lines, $is_update);
}
- # get here only if failed
+ unlink $filename or warn "Failed to remove $filename: $!" unless &debug();
- if ( $attempts_to_go > 0 ) {
- Irssi::timeout_add_once( $wait_time, 'monitor_child',
- [ $filename, $attempts_to_go - 1, $wait_time, $is_update ] );
- } else {
- &debug("Giving up on polling $filename");
- Irssi::pidwait_remove($child_pid);
- waitpid( -1, WNOHANG );
- unlink $filename unless &debug();
-
- if (not $is_update) {
- ¬ice([ 'error' ], "Failed to get response. Giving up.");
- return;
- }
-
- $update_is_running = 0 if $is_update;
+ # commit the pending cache lines to the actual cache, now that
+ # we've printed our output
+ for my $updated_id (keys %new_cache) {
+ $tweet_cache{$updated_id} = $new_cache{$updated_id};
+ }
- return unless $settings{notify_timeouts};
+ # keep enough cached tweets, to make sure we don't show duplicates
+ for my $loop_id ( keys %tweet_cache ) {
+ next if $tweet_cache{$loop_id} >= $last_poll{__poll} - 3600;
+ delete $tweet_cache{$loop_id};
+ }
- my $since;
- if ( time - $last_poll{__poll} < 24 * 60 * 60 ) {
- my @time = localtime($last_poll{__poll});
- $since = sprintf( "%d:%02d", @time[ 2, 1 ] );
- } else {
- $since = scalar localtime($last_poll{__poll});
- }
-
- if ( $failstatus < 2 and time - $last_poll{__poll} > 60 * 60 ) {
- ¬ice([ 'error' ],
- $settings{mini_whale}
- ? 'FAIL WHALE'
- : q{ v v v},
- q{ | | v | v},
- q{ | .-, | | |},
- q{ .--./ / | _.---.| },
- q{ '-. (__..-" \\},
- q{ \\ a |},
- q{ ',.__. ,__.-'/},
- q{ '--/_.'----'`}
- );
- $failstatus = 2;
- }
+ if (not $got_errors) {
+ &save_state();
+ }
- if ( $failstatus == 0 and time - $last_poll{__poll} < 600 ) {
- ¬ice([ 'error' ],"Haven't been able to get updated tweets since $since");
- $failstatus = 1;
+ if ($is_update) {
+ if ($failstatus and not $got_errors) {
+ ¬ice([ 'deerror' ], "Update succeeded.");
+ $failstatus = 0;
}
+ $first_call = 0;
+ $update_is_running = 0;
}
}
@@ -2726,7 +2800,7 @@ sub write_lines {
);
push @print_opts, (lc $line->{topic} ne lc $win_name ? $line->{topic} . ':' : '')
if $line->{type} =~ /search/;
- push @print_opts, $line->{hi_nick} if $line->{type} ne 'error';
+ push @print_opts, $line->{hi_nick} if $line->{type} ne 'error' and $line->{type} ne 'deerror';
push @print_opts, $line->{marker} if defined $line->{marker};
# set timestamp
@@ -2755,7 +2829,7 @@ sub write_lines {
if (not defined $old_tf) {
$old_tf = Irssi::settings_get_str('timestamp_format');
}
- $line->{text} = &unshorten($line->{text});
+ $line->{text} = &post_process_tweet($line->{text});
Irssi::command("^set timestamp_format $ts");
Irssi::window_find_name($win_name)->printformat(
@print_opts, &hilight( $line->{text} ) . $ymd_suffix
@@ -2910,9 +2984,10 @@ sub debug {
}
sub notice {
- my ( $type, $tag, $fh );
+ my ( $type, $tag, $fh, $theme );
if ( ref $_[0] ) {
( $type, $tag, $fh ) = @{ shift @_ };
+ $theme = 'twirssi_' . $type;
}
foreach my $msg (@_) {
if (defined $fh) {
@@ -2933,8 +3008,8 @@ sub notice {
$win = Irssi::window_find_name(&window( $type, $tag ));
}
- if ($type =~ /^(error|info)$/) {
- $win->printformat(MSGLEVEL_PUBLIC, 'twirssi_'.$type, $msg); # theme
+ if ($type =~ /^(error|info|deerror)$/) {
+ $win->printformat(MSGLEVEL_PUBLIC, $theme, $msg); # theme
} else {
$win->print("${col}***%n $msg", $win_level );
}
@@ -3168,6 +3243,14 @@ sub event_setup_changed {
$settings{$setting->[0]} = [ ];
} else {
$settings{$setting->[0]} = [ split($re, $settings{$setting->[0]}) ];
+ if (grep { $_ eq $setting->[0] } ('passwords')) {
+ # ends '\', unescape separator: concatenate with next
+ for (my $i = 0; $i+1 < @{ $settings{$setting->[0]} }; $i++) {
+ while ( $settings{$setting->[0]}->[$i] =~ /\\$/ ) {
+ $settings{$setting->[0]}->[$i] .= "," . delete $settings{$setting->[0]}->[$i+1];
+ }
+ }
+ }
}
$is_list = 1;
} elsif ($pre_proc =~ s/^norm_user(?:,|$)//) {
@@ -3181,7 +3264,7 @@ sub event_setup_changed {
my @normed = ();
for my $to_norm ($is_list ? @{ $settings{$setting->[0]} } : $settings{$setting->[0]} ) {
next if $to_norm eq '';
-&debug($setting->[0] . ' to_norm {' . $to_norm . '}');
+ &debug($setting->[0] . ' to_norm {' . $to_norm . '}');
push @normed, &normalize_username($to_norm, 1);
}
$is_list = 1;
@@ -3287,13 +3370,52 @@ sub get_charset {
return $charset;
}
+my @available_nick_colors =(
+ 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ '0,2', '0,3', '0,5', '0,6',
+ '1,0', '1,3', '1,5', '1,6', '1,7', '1,10', '1,15',
+ '2,3', '2,7', '2,10', '2,15',
+ '3,2', '3,5', '3,10',
+ '4,2', '4,7',
+ '5,2', '5,3', '5,7', '5,10', '5,15',
+ '6,2', '6,7', '6,10', '6,15',
+ '8,2', '8,5', '8,6',
+ '9,2', '9,5', '9,6',
+ '10,2', '10,5', '10,6',
+ '11,2', '11,5', '11,6',
+ '12,2', '12,5',
+ '13,2', '13,15',
+ '14,2', '14,5', '14,6',
+ '15,2', '15,5', '15,6'
+);
+my %nick_colors;
+
+sub get_nick_color {
+ if ($settings{nick_color} eq 'rotate') {
+ my $nick = shift;
+
+ if (!defined $nick_colors{$nick}) {
+ my @chars = split //, lc $nick;
+ my $value = 0;
+ foreach my $char (@chars) {
+ $value += ord $char;
+ }
+ $nick_colors{$nick} = $available_nick_colors[$value % @available_nick_colors];
+ }
+ return $nick_colors{$nick};
+ } else {
+ return $irssi_to_mirc_colors{$settings{nick_color}};
+ }
+}
+
sub hilight {
my $text = shift;
if ( $settings{nick_color} ) {
- my $c = $settings{nick_color};
- $c = $irssi_to_mirc_colors{$c};
- $text =~ s/(^|\W)\@(\w+)/$1\cC$c\@$2\cO/g if $c;
+ $text =~ s[(^|\W)\@(\w+)] {
+ my $c = get_nick_color($2);
+ qq[$1\cC$c\@$2\cO];
+ }eg;
}
if ( $settings{topic_color} ) {
my $c = $settings{topic_color};
@@ -3418,15 +3540,17 @@ sub put_unshorten_urls {
}
-sub unshorten {
+sub post_process_tweet {
my $data = shift;
- return $data unless @{ $settings{url_unshorten} };
- for my $site (keys %expanded_url) {
- for my $https (keys %{ $expanded_url{$site} }) {
- my $url = ($https ? 'https' : 'http') . '://' . $site . '/';
- next if -1 == index($data, $url);
- for my $uri (keys %{ $expanded_url{$site}{$https} }) {
- $data =~ s/\Q$url$uri\E/$& \cC$irssi_to_mirc_colors{$settings{unshorten_color}}<$expanded_url{$site}{$https}{$uri}{url}>\cO/g;
+ my $skip_unshorten = shift;
+ if (@{ $settings{url_unshorten} } and not $skip_unshorten) {
+ for my $site (keys %expanded_url) {
+ for my $https (keys %{ $expanded_url{$site} }) {
+ my $url = ($https ? 'https' : 'http') . '://' . $site . '/';
+ next if -1 == index($data, $url);
+ for my $uri (keys %{ $expanded_url{$site}{$https} }) {
+ $data =~ s/\Q$url$uri\E/$& \cC$irssi_to_mirc_colors{$settings{unshorten_color}}<$expanded_url{$site}{$https}{$uri}{url}>\cO/g;
+ }
}
}
}
@@ -3466,14 +3590,13 @@ sub get_text {
my $tweet = shift;
my $object = shift;
my $text = decode_entities( $tweet->{text} );
- if ( $tweet->{truncated} ) {
- if ( exists $tweet->{retweeted_status} ) {
- $text = "RT \@$tweet->{retweeted_status}{user}{screen_name}: "
- . "$tweet->{retweeted_status}{text}";
- } elsif ( $object->isa('Net::Twitter') ) {
- $text .= " -- http://twitter.com/$tweet->{user}{screen_name}"
- . "/status/$tweet->{id}";
- }
+ if ( exists $tweet->{retweeted_status} ) {
+ $text = &format_expand(fmt => $settings{retweeted_format} || $settings{retweet_format},
+ nick => $tweet->{retweeted_status}{user}{screen_name}, data => '',
+ tweet => decode_entities( $tweet->{retweeted_status}{text} ));
+ } elsif ( $tweet->{truncated} and $object->isa('Net::Twitter') ) {
+ $text .= " -- http://twitter.com/$tweet->{user}{screen_name}"
+ . "/status/$tweet->{id}";
}
$text =~ s/[\n\r]/ /g;
@@ -3488,6 +3611,7 @@ sub window {
my $topic = lc(shift || '');
$type = "search" if $type eq 'search_once';
+ $type = "error" if $type eq 'deerror';
my $win;
my @all_priorities = qw/ account sender list /;
@@ -3596,6 +3720,7 @@ Irssi::theme_register( # theme
'twirssi_reply', '[$0\--> %B@$1%n$2] $3',
'twirssi_dm', '[$0%r@$1%n (%WDM%n)] $2',
'twirssi_error', '%RERROR%n: $0',
+ 'twirssi_deerror', '%RUPDATE%n: $0',
'twirssi_info', '%CINFO:%N $0',
'twirssi_new_day', '%CDay changed to $0%N',
]
@@ -3741,6 +3866,7 @@ if ( Irssi::window_find_name(window()) ) {
¬ice( ["tweet", "$user\@$defservice"],
"Following $_[0]" );
$nicks{ $_[0] } = time;
+ &cmd_user(@_);
},
sub {
&cmd_set_window("sender $_[0] $_[0]", $_[1], $_[2])
More information about the scm-commits
mailing list