summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorJari Matilainen2015-11-24 16:06:16 +0100
committerJari Matilainen2015-11-24 16:06:16 +0100
commit4775c0a652fab0608acc57788a060f390dacea60 (patch)
treedde5002e5903f1fc49aff1dcec27049dc76554b7 /scripts
parent1d85c4160eb53dfe2293dbc09926679d9b9d4b19 (diff)
downloadscripts.irssi.org-4775c0a652fab0608acc57788a060f390dacea60.tar.bz2
Initial commit
Diffstat (limited to 'scripts')
-rw-r--r--scripts/intercept.pl169
-rw-r--r--scripts/notifyquit.pl485
-rw-r--r--scripts/tabcompletenick.pl173
-rw-r--r--scripts/timezones.pl23
4 files changed, 843 insertions, 7 deletions
diff --git a/scripts/intercept.pl b/scripts/intercept.pl
new file mode 100644
index 0000000..edb882a
--- /dev/null
+++ b/scripts/intercept.pl
@@ -0,0 +1,169 @@
+# Some elements borrowed from ideas developed by shabble@freenode(https://github.com/shabble/irssi-docs/wiki )
+
+use strict;
+use warnings;
+use Data::Dumper;
+use Irssi;
+
+our $VERSION = "0.1";
+our %IRSSI = (
+ authors => "Jari Matilainen",
+ contact => 'vague!#irssi@freenode on irc',
+ name => "intercept",
+ description => "Intercept misprinted commands and offer to remove the first character before sending it on",
+ license => "Public Domain",
+ url => "http://gplus.to/vague",
+ changed => "24 Nov 16:00:00 CET 2015",
+ );
+
+my $active = 0;
+my $permit_pending = 0;
+my $pending_input = {};
+my $verbose = 0;
+
+sub script_is_loaded {
+ return exists($Irssi::Script::{$_[0] . '::'});
+}
+
+if (script_is_loaded('uberprompt')) {
+ app_init();
+}
+else {
+ print "This script requires 'uberprompt.pl' in order to work. "
+ . "Attempting to load it now...";
+
+ Irssi::signal_add('script error', 'load_uberprompt_failed');
+ Irssi::command("script load uberprompt.pl");
+
+ unless(script_is_loaded('uberprompt')) {
+ load_uberprompt_failed("File does not exist");
+ }
+ app_init();
+}
+
+sub load_uberprompt_failed {
+ Irssi::signal_remove('script error', 'load_uberprompt_failed');
+
+ print "Script could not be loaded. Script cannot continue. "
+ . "Check you have uberprompt.pl installed in your scripts directory and "
+ . "try again. Otherwise, it can be fetched from: ";
+ print "https://github.com/shabble/irssi-scripts/raw/master/"
+ . "prompt_info/uberprompt.pl";
+
+ die "Script Load Failed: " . join(" ", @_);
+}
+
+sub sig_send_text {
+ my ($data, $server, $witem) = @_;
+
+ if($permit_pending == 1) {
+ $pending_input = {};
+ $permit_pending = 0;
+ Irssi::signal_continue(@_);
+ }
+ elsif($permit_pending == 2) {
+ my $regexp = Irssi::settings_get_str('intercept_linestart');
+ $pending_input = {};
+ $permit_pending = 0;
+ Irssi::signal_stop();
+ $data =~ s/^$regexp//;
+
+ if(ref $witem && $witem->{type} eq 'CHANNEL') {
+ $witem->command($data);
+ }
+ else {
+ $server->command($data);
+ }
+ }
+ else {
+ (my $cmdchars = Irssi::settings_get_str('cmdchars')) =~ s/(.)(.)/$1|$2/;
+ my @exceptions = split / /, Irssi::settings_get_str('intercept_exceptions');
+
+ foreach(@exceptions) {
+ return if($data =~ m{$_}i);
+ }
+
+ my $regexp = Irssi::settings_get_str('intercept_linestart');
+ $regexp =~ s/(^[\^])|([\$]$)//g;
+ if($data =~ /^($regexp)($cmdchars)/i) {
+ my $text = "You have " . ($1 eq ' '?'a space':$1) . " infront of your cmdchar '$2', is this what you wanted? [y/F/c]";
+ $pending_input = {
+ text => $data,
+ server => $server,
+ win_item => $witem,
+ };
+
+ Irssi::signal_stop();
+ require_confirmation($text);
+ }
+ }
+}
+
+sub sig_gui_keypress {
+ my ($key) = @_;
+
+ return if not $active;
+
+ my $char = chr($key);
+
+ # we support f, F, enter for Fix.
+ if($char =~ m/^f?$/i) {
+ $permit_pending = 2;
+ Irssi::signal_stop();
+ Irssi::signal_emit('send text',
+ $pending_input->{text},
+ $pending_input->{server},
+ $pending_input->{win_item});
+ $active = 0;
+ set_prompt('');
+ }
+ elsif($char =~ m/^y$/i) {
+ # y or Y for send as is
+ $permit_pending = 1;
+ Irssi::signal_stop();
+ Irssi::signal_emit('send text',
+ $pending_input->{text},
+ $pending_input->{server},
+ $pending_input->{win_item});
+ $active = 0;
+ set_prompt('');
+ }
+ elsif ($char =~ m/^c$/i or $key == 3 or $key == 7) {
+ # we support c, C, Ctrl-C, and Ctrl-G for don't send
+ Irssi::signal_stop();
+ set_prompt('');
+ $permit_pending = 0;
+ $active = 0;
+ $pending_input = {};
+ }
+ else {
+ Irssi::signal_stop();
+ return;
+ }
+}
+
+sub app_init {
+ Irssi::signal_add_first("send text" => \&sig_send_text);
+ Irssi::signal_add_first('gui key pressed' => \&sig_gui_keypress);
+ Irssi::settings_add_str('Intercept', 'intercept_exceptions', 's/\w+/[\w\s\d]+/');
+ Irssi::settings_add_str('Intercept', 'intercept_linestart', '\s');
+}
+
+sub require_confirmation {
+ $active = 1;
+ set_prompt(shift);
+}
+
+sub set_prompt {
+ my ($msg) = @_;
+ $msg = ': ' . $msg if length $msg;
+ Irssi::signal_emit('change prompt', $msg, 'UP_INNER');
+}
+
+sub _debug {
+ return unless $verbose;
+
+ my ($msg, @params) = @_;
+ my $str = sprintf($msg, @params);
+ print $str;
+}
diff --git a/scripts/notifyquit.pl b/scripts/notifyquit.pl
new file mode 100644
index 0000000..087ee57
--- /dev/null
+++ b/scripts/notifyquit.pl
@@ -0,0 +1,485 @@
+=pod
+
+=head1 NAME
+
+notifyquit.pl
+
+=head1 DESCRIPTION
+
+A script intended to alert people to the fact that their conversation partners
+have quit or left the channel, especially useful in high-traffic channels, or
+where you have C<JOINS PARTS QUITS> ignored.
+
+=head1 INSTALLATION
+
+This script requires that you have first installed and loaded F<uberprompt.pl>
+
+Uberprompt can be downloaded from:
+
+L<https://github.com/shabble/irssi-scripts/raw/master/prompt_info/uberprompt.pl>
+
+and follow the instructions at the top of that file or its README for installation.
+
+If uberprompt.pl is available, but not loaded, this script will make one
+attempt to load it before giving up. This eliminates the need to precisely
+arrange the startup order of your scripts.
+
+Copy into your F<~/.irssi/scripts/> directory and load with
+C</SCRIPT LOAD F<notifyquit.pl>>.
+
+=head1 SETUP
+
+This script provides a single setting:
+
+C</SET notifyquit_exceptions>, which defaults to "C</^https?/ /^ftp/>"
+
+The setting is a space-separated list of regular expressions in the format
+C</EXPR/>. If the extracted nickname matches any of these patterns, it isa
+assumed to be a false-positive match, and is sent to the channel with no
+further confirmation.
+
+=head1 USAGE
+
+When responding to users in a channel in the format C<$theirnick: some message>
+(where the C<:> is not necessarily a colon, but the value of your
+C<completion_char> setting), this script will check that the nickname still
+exists in the channel, and will prompt you for confirmation if they have
+since left.
+
+It is intended for use for people who ignore C<JOINS PARTS QUITS>, etc, and
+try to respond to impatient people, or those with a bad connection.
+
+To send the message once prompted, either hit C<enter>, or C<y>. Pressing C<n>
+will abort sending, but leave the message in your input buffer just in case
+you want to keep it.
+
+=head1 AUTHORS
+
+Original Copyright E<copy> 2011 Jari Matilainen C<E<lt>vague!#irssi@freenodeE<gt>>
+
+Some extra bits
+Copyright E<copy> 2011 Tom Feist C<E<lt>shabble+irssi@metavore.orgE<gt>>
+
+=head1 LICENCE
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+=head1 BUGS
+
+I<None known.>
+
+Please report any problems to L<https://github.com/shabble/irssi-scripts/issues/new>
+or moan about it in C<#irssi@Freenode>.
+
+=head1 TODO
+
+=over 4
+
+=item * Keep a watchlist of nicks in the channel, and only act to confirm if
+they quit shortly before/during you typing a response.
+
+keep track of the most recent departures, and upon sending, see if one of them
+is your target. If so, prompt for confirmation.
+
+So, add them on quit/kick/part, and remove them after a tiemout.
+
+=back
+
+=cut
+
+###
+#
+# Parts of the script pertaining to uberprompt borrowed from
+# shabble (shabble!#irssi/@Freenode), thanks for letting me steal from you :P
+#
+###
+
+use strict;
+use warnings;
+use Data::Dumper;
+
+our $VERSION = "0.3";
+our %IRSSI = (
+ authors => "Jari Matilainen",
+ contact => 'vague!#irssi@freenode on irc',
+ name => "notifyquit",
+ description => "Notify if user has left the channel",
+ license => "Public Domain",
+ url => "http://gplus.to/vague",
+ changed => "24 Nov 16:00:00 CET 2015",
+ );
+
+my $active = 0;
+my $permit_pending = 0;
+my $pending_input = {};
+my $verbose = 0;
+my @match_exceptions;
+my $watchlist = {};
+
+sub script_is_loaded {
+ return exists($Irssi::Script::{$_[0] . '::'});
+}
+
+if (script_is_loaded('uberprompt')) {
+ app_init();
+} else {
+ print "This script requires 'uberprompt.pl' in order to work. "
+ . "Attempting to load it now...";
+
+ Irssi::signal_add('script error', 'load_uberprompt_failed');
+ Irssi::command("script load uberprompt.pl");
+
+ unless(script_is_loaded('uberprompt')) {
+ load_uberprompt_failed("File does not exist");
+ }
+ app_init();
+}
+
+sub load_uberprompt_failed {
+ Irssi::signal_remove('script error', 'load_uberprompt_failed');
+
+ print "Script could not be loaded. Script cannot continue. "
+ . "Check you have uberprompt.pl installed in your scripts directory and "
+ . "try again. Otherwise, it can be fetched from: ";
+ print "https://github.com/shabble/irssi-scripts/raw/master/"
+ . "prompt_info/uberprompt.pl";
+
+ die "Script Load Failed: " . join(" ", @_);
+}
+
+sub extract_nick {
+ my ($str) = @_;
+
+ my $completion_char
+ = quotemeta(Irssi::settings_get_str("completion_char"));
+
+ # from BNF grammar at http://www.irchelp.org/irchelp/rfc/chapter2.html
+ # special := '-' | '[' | ']' | '\' | '`' | '^' | '{' | '}'
+
+ my $pattern = qr/^( [[:alpha:]] # starts with a letter
+ (?: [[:alpha:]] # then letter
+ | \d # or number
+ | [\[\]\\`^\{\}-]) # or special char
+ *? ) # any number of times
+ $completion_char/x; # followed by completion char.
+
+ if ($str =~ m/$pattern/) {
+ return $1;
+ } else {
+ return undef;
+ }
+
+}
+
+sub check_nick_exemptions {
+ my ($nick) = @_;
+ foreach my $except (@match_exceptions) {
+ _debug("Testing nick $nick against $except");
+ if ($nick =~ $except) {
+ _debug( "Failed match $except");
+ return 0; # fail
+ }
+ }
+ _debug("match ok");
+
+ return 1;
+}
+
+sub sig_send_text {
+ my ($data, $server, $witem) = @_;
+
+ return unless($witem);
+
+ return unless ref $witem && $witem->{type} eq 'CHANNEL';
+
+ # shouldn't need escaping, but it doesn't hurt to be paranoid.
+ my $target_nick = extract_nick($data);
+
+ if ($target_nick) {
+ if (check_watchlist($target_nick, $witem->{name}, $server)
+ and not $witem->nick_find($target_nick)) {
+
+ return unless check_nick_exemptions($target_nick);
+
+ if ($permit_pending) {
+ $pending_input = {};
+ $permit_pending = 0;
+ Irssi::signal_continue(@_);
+ } else {
+ return unless check_watchlist($target_nick, $witem->{name}, $server);
+ return unless check_watchlist($target_nick, '***', $server);
+
+ my $text
+ = "$target_nick isn't in this channel, send anyway? [Y/n]";
+ $pending_input
+ = {
+ text => $data,
+ server => $server,
+ win_item => $witem,
+ };
+
+ Irssi::signal_stop;
+ require_confirmation($text);
+ }
+ }
+ }
+}
+
+sub sig_gui_keypress {
+ my ($key) = @_;
+
+ return if not $active;
+
+ my $char = chr($key);
+
+ # Enter, y, or Y.
+ if ($char =~ m/^y?$/i) {
+ $permit_pending = 1;
+ Irssi::signal_stop;
+ Irssi::signal_emit('send text',
+ $pending_input->{text},
+ $pending_input->{server},
+ $pending_input->{win_item});
+ $active = 0;
+ set_prompt('');
+
+ } elsif ($char =~ m/^n?$/i or $key == 3 or $key == 7) {
+ # we support n, N, Ctrl-C, and Ctrl-G for no.
+
+ Irssi::signal_stop;
+ set_prompt('');
+
+ $permit_pending = 0;
+ $active = 0;
+ $pending_input = {};
+
+ } else {
+ Irssi::signal_stop;
+ return;
+ }
+}
+
+
+sub add_to_watchlist {
+ my ($nick, $channel, $server, $type, $opts) = @_;
+ my $tag = $server->{tag};
+ _debug("Adding $nick to $channel/$tag");
+
+ $watchlist->{$tag}->{$channel}->{$nick} = {
+ timestamp => time(),
+ type => $type,
+ options => $opts,
+ };
+}
+
+sub check_watchlist {
+ my ($nick, $channel, $server) = @_;
+ my $tag = $server->{tag};
+
+ my $check = exists ($watchlist->{$tag}->{$channel}->{$nick});
+ _debug("Check for $nick in $channel/$tag is " .( $check ? 'true' : 'false'));
+
+ # check the server-wide list if the channel-specific one fails.
+ if (not $check) {
+ $check = exists ($watchlist->{$tag}->{'***'}->{$nick});
+ _debug("Check for $nick in ***/$tag is " .( $check ? 'true' : 'false'));
+ }
+
+ return $check;
+}
+
+sub remove_from_watchlist {
+ my ($nick, $channel, $server) = @_;
+ my $tag = $server->{tag};
+
+ if (exists($watchlist->{$tag}->{$channel}->{$nick})) {
+ delete($watchlist->{$tag}->{$channel}->{$nick});
+ _debug("Deleted $nick from $channel/$tag");
+ }
+}
+
+sub cleanup_watchlist {
+ my ($channel, $server) = @_;
+ my $tag = $server->{tag};
+
+ if(!keys %{$watchlist->{$tag}->{$channel}}) {
+ delete($watchlist->{$tag}->{$channel});
+ _debug("Cleanup $channel/$tag");
+ }
+ if(!keys %{$watchlist->{$tag}}) {
+ delete($watchlist->{$tag});
+ _debug("Cleanup $tag");
+ }
+}
+
+sub start_watchlist_expire_timer {
+ my ($nick, $channel, $server, $callback) = @_;
+
+ my $tag = $server->{tag};
+ my $timeout = Irssi::settings_get_time('notifyquit_timeout');
+
+ Irssi::timeout_add_once($timeout,
+ $callback,
+ { nick => $nick,
+ channel => $channel,
+ server => $server,
+ });
+}
+
+sub sig_message_quit {
+ my ($server, $nick, $address, $reason) = @_;
+
+ my $tag = $server->{tag};
+
+ _debug( "$nick quit from $tag");
+ add_to_watchlist($nick, "***", $server, 'quit', undef);
+
+ my $quit_cb = sub {
+
+ # remove from all channels.
+ foreach my $chan (keys %{ $watchlist->{$tag} }) {
+ # if (exists $chan->{$nick}) {
+ # delete $watchlist->{$tag}->{$chan}->{$nick};
+ # }
+ remove_from_watchlist($nick, $chan, $server);
+ cleanup_watchlist($chan, $server);
+ }
+ };
+
+ start_watchlist_expire_timer($nick, '***', $server, $quit_cb);
+}
+
+sub sig_message_part {
+ my ($server, $channel, $nick, $address, $reason) = @_;
+
+ my $tag = $server->{tag};
+
+ _debug( "$nick parted from $channel/$tag");
+ add_to_watchlist($nick, $channel, $server, 'part', undef);
+ my $part_cb = sub {
+ remove_from_watchlist($nick, $channel, $server);
+ cleanup_watchlist($channel, $server);
+ };
+
+ start_watchlist_expire_timer($nick, $channel, $server, $part_cb);
+}
+
+sub sig_message_kick {
+ my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
+ _debug( "$nick kicked from $channel by $kicker");
+
+ my $tag = $server->{tag};
+ add_to_watchlist($nick, $channel, $server, 'kick', undef);
+
+ my $kick_cb = sub {
+ remove_from_watchlist($nick, $channel, $server);
+ cleanup_watchlist($channel, $server);
+ };
+
+ start_watchlist_expire_timer($nick, $channel, $server, $kick_cb);
+}
+
+sub sig_message_nick {
+ my ($server, $newnick, $oldnick, $address) = @_;
+ my $tag = $server->{tag};
+
+ _debug("$oldnick changed nick to $newnick ($tag)");
+ #_debug( "Not bothering with this for now.");
+ add_to_watchlist($oldnick, '***', $server, 'nick', $newnick);
+
+ my $nick_cb = sub {
+ remove_from_watchlist($oldnick, '***', $server);
+ cleanup_watchlist('***', $server);
+ };
+
+ start_watchlist_expire_timer($oldnick, '***', $server, $nick_cb);
+}
+
+sub app_init {
+ Irssi::signal_add('setup changed' => \&sig_setup_changed);
+ Irssi::signal_add_first('message quit' => \&sig_message_quit);
+ Irssi::signal_add_first('message part' => \&sig_message_part);
+ Irssi::signal_add_first('message kick' => \&sig_message_kick);
+ Irssi::signal_add_first('message nick' => \&sig_message_nick);
+ Irssi::signal_add_first("send text" => \&sig_send_text);
+ Irssi::signal_add_first('gui key pressed' => \&sig_gui_keypress);
+ Irssi::settings_add_str($IRSSI{name}, 'notifyquit_exceptions', '/^https?/ /^ftp/');
+ Irssi::settings_add_bool($IRSSI{name}, 'notifyquit_verbose', 0);
+ Irssi::settings_add_time($IRSSI{name}, 'notifyquit_timeout', '30s');
+
+ # horrible name, but will serve.
+ Irssi::command_bind('notifyquit_show_exceptions', \&cmd_show_exceptions);
+ Irssi::command_bind('notifyquit_show_watchlist', \&cmd_show_watchlist);
+
+ sig_setup_changed();
+}
+
+sub cmd_show_exceptions {
+
+ foreach my $e (@match_exceptions) {
+ print "Exception: $e";
+ }
+}
+
+sub cmd_show_watchlist {
+ Irssi::print Dumper($watchlist);
+}
+
+sub sig_setup_changed {
+
+ my $except_str = Irssi::settings_get_str('notifyquit_exceptions');
+ $verbose = Irssi::settings_get_bool('notifyquit_verbose');
+ my @except_list = split( m{(?:^|(?<=/))\s+(?:(?=/)|$)}, $except_str);
+
+ @match_exceptions = ();
+
+ foreach my $except (@except_list) {
+
+ _debug("Exception regex str: $except");
+ $except =~ s|^/||;
+ $except =~ s|/$||;
+
+ next if $except =~ m/^\s*$/;
+
+ my $regex;
+
+ eval {
+ $regex = qr/$except/i;
+ };
+
+ if ($@ or not defined $regex) {
+ print "Regex failed to parse: \"$except\": $@";
+ } else {
+ _debug("Adding match exception: $regex");
+ push @match_exceptions, $regex;
+ }
+ }
+}
+
+
+sub require_confirmation {
+ $active = 1;
+ set_prompt(shift);
+}
+
+sub set_prompt {
+ my ($msg) = @_;
+ $msg = ': ' . $msg if length $msg;
+ Irssi::signal_emit('change prompt', $msg, 'UP_INNER');
+}
+
+sub _debug {
+
+ return unless $verbose;
+
+ my ($msg, @params) = @_;
+ my $str = sprintf($msg, @params);
+ print $str;
+
+}
diff --git a/scripts/tabcompletenick.pl b/scripts/tabcompletenick.pl
new file mode 100644
index 0000000..deca5af
--- /dev/null
+++ b/scripts/tabcompletenick.pl
@@ -0,0 +1,173 @@
+# - Lets you tab over a number of people who've recently spoken in channel
+# - Removes people from the list who leave the channel
+# - Tabcomplete works only from an empty input line and will complete to
+# the person who last spoke
+# - The same nick is only included once in the list
+# - When at the end of the list, empties the input line and lets you begin
+# from the start again
+# - /set completion_keep_publics decides how many nicks to remember
+
+use Irssi;
+use Data::Dumper;
+
+my $VERSION = '1.0';
+my %IRSSI = (
+ authors => 'vague',
+ contact => 'vague!#irssi@freenode on irc',
+ name => 'tabcompletenick',
+ description => 'tabcomplete, on an empty input buffer, over /set completion_keep_publics nicks in channel, parts for any reason(kick, part, quit) are removed from the tabcomplete list',
+ license => 'GPL2',
+ url => "http://gplus.to/vague",
+ changed => "24 Nov 16:00:00 CET 2015",
+);
+
+my $lastspokehash = {};
+my $expand_next = 0;
+
+Irssi::signal_add_first('gui key pressed', sub {
+ my ($key) = @_;
+ my $prompt = Irssi::parse_special('$L');
+ my $pos = Irssi::gui_input_get_pos();
+
+ $server = Irssi::active_server();
+ $witem = Irssi::active_win()->{active};
+
+ return unless $witem->{type} eq "CHANNEL";
+
+ my $arr = $lastspokehash{$server->{tag}}->{$witem->{name}};
+
+ if(!$expand_next) {
+ return unless $key == 9;
+ return unless $pos == 0;
+ return unless @{$arr};
+
+ $expand_next++;
+ }
+ else {
+ if($key != 9) {
+ $expand_next = 0;
+ return;
+ }
+
+ if($expand_next < scalar @{$arr}) {
+ $expand_next++;
+ } else {
+ $expand_next = 0;
+ }
+ }
+
+ my $last = Irssi::parse_special('$LASTSPOKE');
+
+ if($last ne '') {
+ $prompt = $last . Irssi::settings_get_str('completion_char') . " ";
+ } else {
+ $prompt = $last;
+ }
+
+ Irssi::gui_input_set($prompt);
+ Irssi::gui_input_set_pos(length($prompt));
+ Irssi::signal_stop();
+});
+
+sub expando_lastspoke {
+ my ($server, $witem) = @_;
+ $server = Irssi::active_server();
+ $witem = Irssi::active_win()->{active};
+
+ return '' if $expand_next == 0;
+ return '' unless ref($witem) eq 'Irssi::Irc::Channel';
+ my $arr = $lastspokehash{$server->{tag}}->{$witem->{name}};
+ return '' unless @{$arr};
+ return '' unless $expand_last <= $arr;
+
+ return @{$lastspokehash{$server->{tag}}->{$witem->{name}}}[$expand_next - 1];
+}
+
+sub act_public {
+ my ($server, $msg, $nick, $address, $witem) = @_;
+
+ return if $witem eq '';
+
+ my $i = 0;
+ my $arr = $lastspokehash{$server->{tag}}->{$witem};
+ foreach(@{$arr}) {
+ if($_ eq $nick) {
+ splice @{$arr}, $i, 1;
+ last;
+ }
+ $i++;
+ }
+
+ unshift @{$lastspokehash{$server->{tag}}->{$witem}}, $nick;
+ splice @{$lastspokehash{$server->{tag}}->{$witem}}, Irssi::settings_get_int('completion_keep_publics');
+}
+
+sub _part {
+ my ($server, $channel, $nick) = @_;
+
+ if(!$channel) {
+ foreach my $chan (keys %{$lastspokehash{$server->{tag}}}) {
+ my $arr = $lastspokehash{$server->{tag}}->{$chan};
+ my $i = 0;
+ foreach(@{$arr}) {
+ if($_ eq $nick) {
+ splice @{$arr}, $i, 1;
+ last;
+ }
+
+ $i++;
+ }
+ }
+ }
+ else {
+ my $arr = $lastspokehash{$server->{tag}}->{$channel};
+ my $i = 0;
+ foreach(@{$arr}) {
+ if($_ eq $nick) {
+ splice @{$arr}, $i, 1;
+ last;
+ }
+
+ $i++;
+ }
+ }
+
+ delete $lastspokehash{$server->{tag}}->{$channel} unless @{$lastspokehash{$server->{tag}}->{$channel}};
+ delete $lastspokehash{$server->{tag}} unless keys %{$lastspokehash{$server->{tag}}};
+}
+
+Irssi::signal_add_first('message quit', sub {
+ my ($server, $nick, $address, $reason) = @_;
+ _part($server, undef, $nick);
+});
+
+Irssi::signal_add_first('message part', sub {
+ my ($server, $channel, $nick, $address, $reason) = @_;
+ _part($server, $channel, $nick);
+});
+
+Irssi::signal_add_first('message kick', sub {
+ my ($server, $channel, $nick, $kicker, $address, $reason) = @_;
+ _part($server, $channel, $nick);
+});
+
+Irssi::signal_add_first('message nick', sub {
+ my ($server, $newnick, $oldnick, $address) = @_;
+
+ foreach my $chan (keys %{$lastspokehash{$server->{tag}}}) {
+ my $arr = $lastspokehash{$server->{tag}}->{$chan};
+ my $i = 0;
+ foreach(@{$arr}) {
+ if($_ eq $oldnick) {
+ @{$arr}[$i] = $newnick;
+ last;
+ }
+
+ $i++;
+ }
+ }
+});
+
+Irssi::signal_add('message public', \&act_public);
+Irssi::signal_add('message irc action', \&act_public);
+Irssi::expando_create('LASTSPOKE', \&expando_lastspoke, {});
diff --git a/scripts/timezones.pl b/scripts/timezones.pl
index 9b383d8..65e9ebe 100644
--- a/scripts/timezones.pl
+++ b/scripts/timezones.pl
@@ -8,18 +8,18 @@
# or add it to an existing one with
# /statusbar window add timezones (window is an exaple, see /statusbar and /help statusbar for comprehensive help)
-use strict;
-use vars qw($VERSION %IRSSI);
-$VERSION = "0.1";
+$VERSION = "0.2";
%IRSSI = (
authors => "Jari Matilainen",
- contact => "irc: vague`\@freenode",
+ contact => 'vague!#irssi@freenode on irc',
name => "timezones",
description => "timezones displayer",
license => "Public Domain",
- url => "http://vague.se"
+ url => "http://gplus.to/vague",
+ changed => "Tue 24 November 16:00:00 CET 2015",
);
+use strict;
use Irssi::TextUI;
use DateTime;
@@ -36,8 +36,17 @@ sub timezones {
foreach(@timezones) {
if(length($result)) { $result .= $div; }
my ($nick, $timezone) = split /:/, $_;
- my $now = DateTime->now(time_zone => $timezone);
- $result .= $nick . ": " . $now->strftime("$datetime");
+ my $now;
+ eval {
+ $now = DateTime->now(time_zone => "$timezone") or die $!;
+ };
+
+ if($@) {
+ $result .= $nick . ": INVALID";
+ }
+ else {
+ $result .= $nick . ": " . $now->strftime("$datetime");
+ }
}
$item->default_handler($get_size_only, undef, $result, 1);