diff options
Diffstat (limited to 'scripts')
85 files changed, 3639 insertions, 1022 deletions
| diff --git a/scripts/adv_windowlist.pl b/scripts/adv_windowlist.pl index ee0219b..66889b4 100644 --- a/scripts/adv_windowlist.pl +++ b/scripts/adv_windowlist.pl @@ -1,13 +1,14 @@  use strict;  use warnings; -our $VERSION = '1.2'; # 762850b0c2c1d5a +our $VERSION = '1.4'; # b46fded611292cb  our %IRSSI = (      authors     => 'Nei',      contact     => 'Nei @ anti@conference.jabber.teamidiot.de',      url         => "http://anti.teamidiot.de/",      name        => 'adv_windowlist',      description => 'Adds a permanent advanced window list on the right or in a status bar.', +    sbitems     => 'awl_shared',      license     => 'GNU GPLv2 or later',     ); @@ -79,6 +80,9 @@ our %IRSSI = (  # * string : Character to use when shortening long names. The second character  #   will be used if two blocks need to be filled.  # +# /format awl_title <string> +# * string : Text to display in the title string or title bar +#  # /format awl_viewer_item_bg <string>  # * string : Format String specifying the viewer's item background colour  # @@ -398,7 +402,19 @@ sub syncLines {  		my ($item, $get_size_only) = @_;  		my $text = $actString[0]; -		my $pat = defined $text ? '{sb '.ucfirst(setc()).': $*}' : '{sb }'; +		my $title = _get_format(set 'title'); +		if (length $title) { +		    $title =~ s{\\(.)|(.)}{ +			defined $2 ? quotemeta $2 +			    : $1 eq 'V' ? '\u' +			    : $1 eq ':' ? quotemeta ':%n' +			    : $1 =~ /^[uUFQE]$/ ? "\\$1" +			    : quotemeta "\\$1" +			}sge; +		    $title = eval qq{"$title"}; +		    $title .= ' '; +		} +		my $pat = defined $text ? "{sb $title\$*}" : '{sb }';  		$text //= '';  		$item->default_handler($get_size_only, $pat, $text, 0);  	    }; @@ -454,6 +470,12 @@ sub awl {    }  } +sub _add_map { +    my ($type, $target, $map) = @_; +    ($type->{$target}) = sort { length $a <=> length $b || $a cmp $b } +	$map, exists $type->{$target} ? $type->{$target} : (); +} +  sub get_keymap {      my ($textDest, undef, $cont_stripped) = @_;      if ($textDest->{level} == 524288 and $textDest->{target} eq '' and !defined $textDest->{server}) { @@ -472,32 +494,32 @@ sub get_keymap {  	    for ($command) {  		last unless length $map;  		if (/^change_window (\d+)/i) { -		    $nummap{$1} = $map; +		    _add_map(\%nummap, $1, $map);  		} -		elsif (/^command window goto (\S+)/i) { +		elsif (/^(?:command window goto|change_window) (\S+)/i) {  		    my $window = $1;  		    if ($window !~ /\D/) { -			$nummap{$window} = $map; +			_add_map(\%nummap, $window, $map);  		    }  		    elsif (lc $window eq 'active') { -			$specialmap{_active} = $map; +			_add_map(\%specialmap, '_active', $map);  		    }  		    else { -			$wnmap{$window} = $map; +			_add_map(\%wnmap, $window, $map);  		    }  		}  		elsif (/^(?:active_window|command (ack))/i) { -		    $specialmap{_active} = $map; +		    _add_map(\%specialmap, '_active', $map);  		    $viewer{use_ack} = !!$1;  		}  		elsif (/^command window last/i) { -		    $specialmap{_last} = $map; +		    _add_map(\%specialmap, '_last', $map);  		}  		elsif (/^(?:upper_window|command window up)/i) { -		    $specialmap{_up} = $map; +		    _add_map(\%specialmap, '_up', $map);  		}  		elsif (/^(?:lower_window|command window down)/i) { -		    $specialmap{_down} = $map; +		    _add_map(\%specialmap, '_down', $map);  		}  		elsif (/^key\s+(\w+)/i) {  		    $custom_key_map{$1} = $map; @@ -726,12 +748,16 @@ sub _format_display {      @ret  } +sub _get_format { +    Irssi::current_theme->get_format(__PACKAGE__, @_) +} +  sub _calculate_items {      my ($wins, $abbrevList) = @_; -    my $display_header = Irssi::current_theme->get_format(__PACKAGE__, set 'display_header'); -    my $name_format = Irssi::current_theme->get_format(__PACKAGE__, set 'name_display'); -    my $abbrev_chars = as_uni(Irssi::current_theme->get_format(__PACKAGE__, set 'abbrev_chars')); +    my $display_header = _get_format(set 'display_header'); +    my $name_format = _get_format(set 'name_display'); +    my $abbrev_chars = as_uni(_get_format(set 'abbrev_chars'));      my %displays; @@ -767,14 +793,14 @@ sub _calculate_items {  	$abbrev2 = $abbrev_chars[1];      }      for my $win (@$wins) { -	my $global_hack_alert_tag_header; +	my $global_tag_header_mode;  	next unless ref $win;  	my $backup_win = Storable::dclone($win);  	delete $backup_win->{active} unless ref $backup_win->{active}; -	$global_hack_alert_tag_header = +	$global_tag_header_mode =  	    $display_header && ($last_net // '') ne ($backup_win->{active}{server}{tag} // '');  	if ($win->{data_level} < abs $S{hide_data} @@ -796,7 +822,7 @@ sub _calculate_items {  	my $number = $win->{refnum};  	my ($name, $display, $cdisplay); -	if ($global_hack_alert_tag_header) { +	if ($global_tag_header_mode) {  	    $display = $display_header;  	    $name = as_uni($backup_win->{active}{server}{tag}) // '';  	    if ($custom_xform) { @@ -818,7 +844,7 @@ sub _calculate_items {  		    grep { !/_visible$/ } @display;  	    }  	    $display = (grep { length $_ } -			       map { $displays{$_} //= Irssi::current_theme->get_format(__PACKAGE__, set $_) } +			       map { $displays{$_} //= _get_format(set $_) }  				   @display)[0];  	    $cdisplay = $name_format;  	    $name = as_uni($win->get_active_name) // ''; @@ -906,7 +932,7 @@ sub _calculate_items {  	    as_tc($key_ent),  	    $win); -	if ($global_hack_alert_tag_header) { +	if ($global_tag_header_mode) {  	    $last_net = $backup_win->{active}{server}{tag};  	    redo;  	} @@ -917,9 +943,9 @@ sub _calculate_items {  sub _spread_items {      my $width = [Irssi::windows]->[0]{width} - $sb_base_width - 1; -    my @separator = Irssi::current_theme->get_format(__PACKAGE__, set 'separator'); +    my @separator = _get_format(set 'separator');      if ($S{block} >= 0) { -	my $sep2 = Irssi::current_theme->get_format(__PACKAGE__, set 'separator2'); +	my $sep2 = _get_format(set 'separator2');  	push @separator, $sep2 if length $sep2 && $sep2 ne $separator[0];      }      $separator[0] .= '%n'; @@ -929,7 +955,7 @@ sub _spread_items {      my $curLine;      my $curLen = 0;      if ($S{shared_sbar}) { -	$curLen += $S{shared_sbar}[0] + 2 + length setc(); +	$curLen += $S{shared_sbar}[0] + 2;  	$width -= $S{shared_sbar}[2];      }      my $mouse_header_check = 0; @@ -1198,13 +1224,25 @@ sub syncViewer {  	       });  	    $viewer{client_env} = 1;  	} -	my $separator = Irssi::current_theme->get_format(__PACKAGE__, set 'separator'); +	my $separator = _get_format(set 'separator');  	my $sepLen = sb_length($separator); -	my $item_bg = Irssi::current_theme->get_format(__PACKAGE__, set 'viewer_item_bg'); +	my $item_bg = _get_format(set 'viewer_item_bg'); +	my $title = _get_format(set 'title'); +	if (length $title) { +	    $title =~ s{\\(.)|(.)}{ +		defined $2 ? quotemeta $2 +		    : $1 eq 'V' ? '\U' +		    : $1 eq ':' ? quotemeta '%N' +		    : $1 =~ /^[uUFQE]$/ ? "\\$1" +		    : quotemeta "\\$1" +		}sge; +	    $title = eval qq{"$title"}; +	}  	$str .= _encode_var(redraw => 1) if delete $viewer{fullRedraw};  	$str .= _encode_var(separator => $separator,  			    seplen => $sepLen,  			    itembg => $item_bg, +			    title => $title,  			    mouse => $mouse_coords{refnum},  			    key2 => \%wnmap_exp,  			    win => \@win_items); @@ -1377,9 +1415,9 @@ return sub {      %banned_channels = map { lc1459(to_uni($_)) => undef }  	split ' ', Irssi::settings_get_str('banned_channels'); -    my @sb_base = split /\177/, sb_format_expand("{sb \177}"), 2; +    my @sb_base = split /\177/, sb_format_expand("{sbstart}{sb \177}{sbend}"), 2;      $sb_base_width_pre = sb_length($sb_base[0]); -    $sb_base_width_post = sb_length($sb_base[1]); +    $sb_base_width_post = max 0, sb_length($sb_base[1])-1;      $sb_base_width = $sb_base_width_pre + $sb_base_width_post;      if ($print_text_activity && $S{line_shade}) { @@ -1602,6 +1640,7 @@ Irssi::signal_register({      set 'separator2'		=> '',      set 'abbrev_chars'		=> "~\x{301c}",      set 'viewer_item_bg'	=> sb_format_expand('{sb_background}'), +    set 'title'			=> '\V'.setc().'\:',     ]);  }  Irssi::settings_add_bool(setc, set 'prefer_name',    0); # @@ -1710,8 +1749,13 @@ sub string_LCSS {      (sort { length $b <=> length $a } $str =~ /(?=(.+).*\0.*\1)/g)[0]  } +# workaround for issue #271  { package Irssi::Nick } +# workaround for issue #572 +@Irssi::UI::Exec::ISA = 'Irssi::Windowitem' +    if Irssi::version >= 20140822 && Irssi::version <= 20161101 && !@Irssi::UI::Exec::ISA; +  UNITCHECK  { package AwlViewer;    use strict; @@ -1971,13 +2015,17 @@ UNITCHECK    }    sub _header { -      my $str = uc ::setc(); -      my $space = int( ((abs $vars{block}) - length $str) / (1 + length $str)); +      my $str = $vars{title} // uc ::setc(); +      my $ccs = qr/%(?:X(?:[1-6][0-9A-Z]|7[A-X])|[0-9BCFGIKMNRUWY_])/i; +      (my $stripstr = $str) =~ s/($ccs)//g; +      my $space = int( ((abs $vars{block}) - length $stripstr) / (1 + length $stripstr));        if ($space > 0) {  	  my $ss = ' ' x $space; -	  $str = join $ss, '', (split //, $str), ''; +	  my @x = $str =~ /((?:$ccs)*\X(?:(?:$ccs)*$)?)/g; +	  $str = join $ss, '', @x, '';        } -      my $pad = (abs $vars{block}) - length $str; +      ($stripstr = $str) =~ s/($ccs)//g; +      my $pad = max 0, (abs $vars{block}) - length $stripstr;        $str = ' ' x ($pad/2) . $str . ' ' x ($pad/2 + $pad%2);        $str    } @@ -2012,7 +2060,7 @@ UNITCHECK        my $j = 0;        my @new_screen;        my @new_mouse; -      $new_screen[0][0] = _header() . ' ' x $vars{seplen} +      $new_screen[0][0] = _header() #. ' ' x $vars{seplen}  	  if $show_title_bar;        unless ($nrows > $ncols) { # line layout  	  ++$j if $show_title_bar; @@ -2388,6 +2436,12 @@ UNITCHECK  # Changelog  # ========= +# 1.4 +# - fix line wrapping in some themes, reported by justanotherbody +# - fix named window key detection, reported by madduck +# - make title (in viewer and shared_sbar) configurable +# +# 1.3 - workaround for irssi issue #572  # 1.2 - new format to choose abbreviation character  # 1.1 - infinite loop on shortening certain window names reported by Kalan  # diff --git a/scripts/apm.pl b/scripts/apm.pl index ec42c66..5ab1b62 100644 --- a/scripts/apm.pl +++ b/scripts/apm.pl @@ -9,6 +9,7 @@ $VERSION = "0.4";      contact     => "formorer\@formorer.de",      name        => "apm",      description => "Shows your battery status in your Statusbar", +    sbitems     => "power",      license     => "GNU Public License",      url         => "http://www.formorer.de/code",  ); diff --git a/scripts/awaybar.pl b/scripts/awaybar.pl index a250db6..7d11ae5 100644 --- a/scripts/awaybar.pl +++ b/scripts/awaybar.pl @@ -12,6 +12,7 @@ $VERSION = "0.1.1";      contact     => 'http://shine.eu.org/',      name        => 'awaybar',      description => 'Provides a menubar item with away message', +    sbitems     => 'awaybar',      license     => 'Public domain',  ); diff --git a/scripts/awaylogcnt.pl b/scripts/awaylogcnt.pl index 4d9bcc7..5c9ec82 100644 --- a/scripts/awaylogcnt.pl +++ b/scripts/awaylogcnt.pl @@ -14,6 +14,7 @@ $VERSION = '0.2';     name         => 'awalogcnt',     description  => 'Displays in statusbar number of messages in awaylog',     modules      => '', +   sbitems      => 'awaylogcnt',     license      => 'GNU GPL v2',     url          => 'http://derwan.irssi.pl',     changed      => 'Wed Oct 27 19:46:28 CEST 2004' diff --git a/scripts/bandwidth.pl b/scripts/bandwidth.pl index a614d17..8c0d0fb 100644 --- a/scripts/bandwidth.pl +++ b/scripts/bandwidth.pl @@ -27,6 +27,7 @@ $VERSION = "1.0";  	contact     => "riku.voipio\@iki.fi",  	name        => "bandwidth",  	description => "shows bandwidth usage in statusbar", +	sbitems     => "stats",          license     => "GPLv2",          url         => "http://nchip.ukkosenjyly.mine.nu/irssiscripts/",      ); diff --git a/scripts/bitlbee_join_notice.pl b/scripts/bitlbee_join_notice.pl index 6a254a7..53bfdfc 100644 --- a/scripts/bitlbee_join_notice.pl +++ b/scripts/bitlbee_join_notice.pl @@ -22,6 +22,7 @@ $VERSION = '1.3';  	contact		=> 'tijmen.ruizendaal@gmail.com',  	name		=> 'BitlBee_join_notice',  	description 	=> '1. Adds an item to the status bar wich shows [joined: <nicks>] when someone is joining &bitlbee. 2. Shows join messages in the query. (For bitlbee v3.0+)', +	sbitems 	=> 'join_notice',  	license 	=> 'GPLv2',  	url		=> 'http://the-timing.nl/stuff/irssi-bitlbee',  	changed 	=> '2010-08-10' diff --git a/scripts/bitlbee_typing_notice.pl b/scripts/bitlbee_typing_notice.pl index e1d1186..806932c 100644 --- a/scripts/bitlbee_typing_notice.pl +++ b/scripts/bitlbee_typing_notice.pl @@ -86,6 +86,7 @@ $VERSION = '1.7.2';  	contact		=> 'tijmen.ruizendaal@gmail.com, root@f0rked.com',  	name		=> 'BitlBee_typing_notice',  	description	=> '1. Adds an item to the status bar wich shows [typing] when someone is typing a message on the supported IM-networks	2. Sends typing notices to the supported IM networks (the other way arround). (For bitlbee 3.0+)', +	sbitems 	=> 'typing_notice',  	license	 	=> 'GPLv2',  	url		=> 'http://the-timing.nl/stuff/irssi-bitlbee, http://f0rked.com',  ); diff --git a/scripts/cap_sasl_fail.pl b/scripts/cap_sasl_fail.pl index 226bc2c..22d0b79 100644 --- a/scripts/cap_sasl_fail.pl +++ b/scripts/cap_sasl_fail.pl @@ -1,7 +1,7 @@  use strict;  use warnings; -our $VERSION = '2.0'; # ed9e98e5d63cfb3 +our $VERSION = '2.1'; # bb62357c61d9e54  our %IRSSI = (      authors     => 'Nei',      name        => 'cap_sasl_fail', @@ -15,8 +15,8 @@ use version;  my %disconnect_next;  my $irssi_version = qv(Irssi::parse_special('v$J') =~ s/-.*//r); -die sprintf "Support for Irssi v%vd has not been written yet.\n", $irssi_version -    if $irssi_version > v0.8.20; +die sprintf "Please use /set sasl_disconnect_on_failure instead of this script.\n" +    if $irssi_version >= v1.0.0;  Irssi::signal_register({'server sasl fail' => [qw[iobject string]]});  Irssi::signal_add_first('server sasl fail' => 'sasl_fail_failed'); diff --git a/scripts/centericq.pl b/scripts/centericq.pl index a1d250b..9b80170 100644 --- a/scripts/centericq.pl +++ b/scripts/centericq.pl @@ -7,6 +7,7 @@ $VERSION = "1.0.0";      contact     => "joost\@carnique.nl",      name        => "centericq",      description => "Staturbar item which indicates how many new messages you have in your centericq", +    sbitems     => "centericq",      license     => "Public Domain",      url         => "http://irssi.org, http://scripts.irssi.org",  ); diff --git a/scripts/chanact.pl b/scripts/chanact.pl index ee6ef3c..4a42364 100644 --- a/scripts/chanact.pl +++ b/scripts/chanact.pl @@ -1,20 +1,25 @@  use Irssi 20020101.0001 (); +  use strict; -# FIXME use warning; +use warnings; +  use Irssi::TextUI;  use vars qw($VERSION %IRSSI); -$VERSION = "0.5.15"; +$VERSION = "0.6.0";  %IRSSI = ( -    authors     => 'BC-bd, Veli', -    contact     => 'bd@bc-bd.org, veli@piipiip.net', +    authors     => 'BC-bd', +    contact     => 'bd@bc-bd.org',      name        => 'chanact',      description => 'Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias). Lets you give alias characters to windows so that you can select those with meta-<char>',      license     => 'GNU GPLv2 or later', -    url         => 'https://bc-bd.org/svn/repos/irssi/chanact' +    url         => 'http://bc-bd.org/blog/irssi/'  ); +# Please send patches / pull requests to the email listed unter contact above +# and not to the irssi/scripts.irssi.org repository on github. +  # Adds new powerful and customizable [Act: ...] item (chanelnames,modes,alias).  # Lets you give alias characters to windows so that you can select those with  # meta-<char>. @@ -27,19 +32,22 @@ $VERSION = "0.5.15";  # Contributors  #########  # -# veli@piipiip.net   /window_alias code -# qrczak@knm.org.pl  chanact_abbreviate_names -# qerub@home.se      Extra chanact_show_mode and chanact_chop_status +# veli@piipiip.net    original /window_alias code +# qrczak@knm.org.pl   chanact_abbreviate_names +# qerub@home.se       Extra chanact_show_mode and chanact_chop_status  # madduck@madduck.net Better channel aliasing (case-sensitive, cross-network)  #                     chanact_filter_windowlist basis -# Jan 'jast' Krueger <jast@heapsort.de>, 2004-06-22 -# Ivo Timmermans <ivo@o2w.nl>	win->{hilight} patch -# Trevor 'tee' Slocum <tslocum@gmail.com> Case-insensitive aliases, bugfix -#  +# jast@heapsort.de    Updated documentation +# ivo@o2w.nl          win->{hilight} patch +# Bazerka             base patch for sorting by level change +#                     updated documentation +# mrtnpaolo@gmail.com rename commands +# tslocum@gmail.com   Case-insensitive aliases +#  #########  # USAGE  ### -#  +#  # copy the script to ~/.irssi/scripts/  #  # In irssi: @@ -61,11 +69,11 @@ $VERSION = "0.5.15";  # aliases to your windows. Go to the window you want to give the alias to  # and say:  # -#		/window_alias <alias char> +#		/chanact_window_alias <alias char>  #  # You can remove the aliases with from an aliased window:  # -#		/window_unalias +#		/chanact_window_unalias  #  # To see a list of your windows use:  # @@ -100,11 +108,11 @@ $VERSION = "0.5.15";  #		    $H : Start highlightning  #		    $S : Stop highlightning  #		* example: -#		 +#  #		      /set chanact_display $H$N:$M.$S$C -#		       +#  #		    will give you on #irssi.de if you have voice -#		     +#  #		      [3:+.#irssi.de]  #  #		    with '3:+.' highlighted and the channel name printed in regular color @@ -113,12 +121,26 @@ $VERSION = "0.5.15";  # 		* ON  : Aliases are case-sensitive  # 		* OFF : Aliases are case-insensitive  # -#		Existing aliases must be reapplied after switching to case-insensitive. +#		Existing aliases must be reapplied after changing this option +# +#		Switching from OFF to ON _after_ aliases have been defined, and +#		then redefining or changing an existing alias will leave some +#		bindings behind, e.g. +# +#			/set chanact_case_sensitive OFF +#			/chanact_window_alias x +# +#				-> window reachable with meta-x/meta-X +# +#			/set chanact_case_sensitive ON +#			/chanact_window_alias y +# +#				-> window reachable with meta-y/meta-X  #  # /set chanact_display_alias <string>  #   as 'chanact_display' but is used if the window has an alias and  #   'chanact_show_alias' is set to on. -#  +#  # /set chanact_show_names <ON|OFF>  #		* ON  : show the channelnames after the number/alias  #		* OFF : don't show the names @@ -141,7 +163,7 @@ $VERSION = "0.5.15";  #  # /set chanact_autorenumber <ON|OFF>  #		* ON  : Move the window automatically to first available slot -#		        starting from "chanact_renumber_start" when assigning  +#		        starting from "chanact_renumber_start" when assigning  #		        an alias to window. Also moves the window back to a  #		        first available slot from refnum 1 when the window  #		        loses it's alias. @@ -160,7 +182,7 @@ $VERSION = "0.5.15";  # 		             beginning of the channel name.  # 		* example  :  # 		    To shorten a lot of debian channels: -# 		     +#  # 			/set chanact_remove_prefix deb(ian.(devel-)?)?  #  # /set chanact_filter <int> @@ -174,7 +196,7 @@ $VERSION = "0.5.15";  #		* <string> : space-separated list of windows for which to use  #			     chanact_filter_windowlist_level instead of  #			     chanact_filter. -#			      +#  #			     Alternatively, an entry can be postfixed with  #			     a comma (',') and the level to use for that  #			     window. @@ -232,15 +254,14 @@ sub expand {  # but we dont need to recreate the item every time so we first  # check if something has changed and only then we recreate the string  # this might just save some cycles -# FIXME implement $get_size_only check, and user $item->{min|max-size}  sub chanact {  	my ($item, $get_size_only) = @_;  	if ($needRemake) {  		remake();  	} -	 -	$item->default_handler($get_size_only, $actString, undef, 1); + +	$item->default_handler($get_size_only, $actString, "", 1);  }  # build a hash to easily access special levels based on @@ -268,13 +289,13 @@ sub calculate_levels(@) {  	my %levels;  	foreach my $win (@windows) { -		# FIXME we could use the next statements to weed out entries in -		# @windows that we will not need later on  		!ref($win) && next;  		my $name = $win->get_active_name; +		# skip nameless windows +		next unless $name; -		if (exists($matches{$name})) { +		if ($name && exists($matches{$name})) {  			$levels{$name} = $matches{$name};  		} else {  			$levels{$name} = $default; @@ -293,7 +314,7 @@ sub calculate_levels(@) {  # this is the real creation method  sub remake() {  	my ($afternumber,$finish,$hilight,$mode,$number,$display,@windows); -	my $separator = Irssi::settings_get_str('chanact_separator');  +	my $separator = Irssi::settings_get_str('chanact_separator');  	my $abbrev = Irssi::settings_get_int('chanact_abbreviate_names');  	my $remove_prefix = Irssi::settings_get_str('chanact_remove_prefix');  	my $remove_hash = Irssi::settings_get_bool('chanact_remove_hash'); @@ -317,6 +338,8 @@ sub remake() {  		$type = $active->{type} if $active;  		my $name = $win->get_active_name; +		# skip windows without a name +		next unless $name;  		my $filter_level =  			$type eq 'QUERY' ? $levels{'@QUERIES'} : $levels{$name}; @@ -334,7 +357,7 @@ sub remake() {  		    && $name eq "(status)") {  			$name = "S";  		} -	 +  		# check if we should show the mode  		$mode = "";  		if ($type eq "CHANNEL") { @@ -346,7 +369,7 @@ sub remake() {  			my $nick = $channel->nick_find($server->{nick});  			!ref($nick) && next; -			 +  			if ($nick->{op}) {  				$mode = "@";  			} elsif ($nick->{voice}) { @@ -377,13 +400,13 @@ sub remake() {  			$name =~ s/^[&#+!=]//;  		} -		if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&  +		if (Irssi::settings_get_bool('chanact_show_alias') == 1 &&  				$win->{name} =~ /^([a-zA-Z+]):(.+)$/) {  			$number = "$1"; -			$display = Irssi::settings_get_str('chanact_display_alias');  +			$display = Irssi::settings_get_str('chanact_display_alias');  		} else {  			$number = $win->{refnum}; -			$display = Irssi::settings_get_str('chanact_display');  +			$display = Irssi::settings_get_str('chanact_display');  		}  		# fixup { and } in nicks, those are used by irssi themes @@ -396,7 +419,7 @@ sub remake() {  	if ($actString ne "") {  		# Remove the last separator  		$actString =~ s/$separator$//; -		 +  		$actString = "{sb ".Irssi::settings_get_str('chanact_header').$actString."}";  	} @@ -429,12 +452,33 @@ sub setup_changed {  	chanactHasChanged();  } +# Remove key binding for current window +sub unbind { +	my ($name, $server) = @_; + +	# chanact'ified windows have a name like this: X:servertag/name. if we +	# can't find anything like this we return and do not unbind nor renumber +	# anything +	my ($key, $tag) = split(/:/, $name); +	return unless $tag; + +	($tag, $name) = split('/', $tag); +	return unless (length($key) == 1); + +	if (Irssi::settings_get_bool('chanact_case_sensitive')) { +		$server->command("/bind -delete meta-$key"); +	} else { +		$server->command("/bind -delete meta-" . lc($key)); +		$server->command("/bind -delete meta-" . uc($key)); +	} +} +  # Remove alias  sub cmd_window_unalias { -	my ($data, $server, $witem, $internal) = @_; +	my ($data, $server, $witem) = @_; -	if ($data ne '' && !$internal) { -		Irssi::print("chanact: /window_unalias does not take any ". +	if ($data ne '') { +		Irssi::print("chanact: /chanact_window_unalias does not take any ".  			"parameters, Run it in the window you want to unalias");  		return;  	} @@ -442,24 +486,7 @@ sub cmd_window_unalias {  	my $win = Irssi::active_win();  	my $name = Irssi::active_win()->{name}; -	# chanact'ified windows have a name like this: X:servertag/name -	my ($key, $tag) = split(/:/, $name); -	($tag, $name) = split('/', $tag); - -	# remove alias only of we have a single character keybinding, if we -	# haven't the name was not set by chanact, so we won't blindly unset -	# stuff -	if (length($key) == 1) { -		if (Irssi::settings_get_bool('chanact_case_sensitive')) { -			$server->command("/bind -delete meta-$data"); -		} else { -			$server->command("/bind -delete meta-" . lc($data)); -			$server->command("/bind -delete meta-" . uc($data)); -		} -	} elsif (!$internal) { -		Irssi::print("chanact: could not determine keybinding. ". -			"Won't unbind anything"); -	} +	unbind($name, $server);  	# set the windowname back to it's old one. We don't bother checking  	# for a vaild name here, as we want to remove the current one and if @@ -472,7 +499,7 @@ sub cmd_window_unalias {  	# we are renumbering, so move the window to the lowest available  	# refnum.  	my $refnum = 1; -	while (Irssi::window_find_refnum($refnum) ne "") { +	while (Irssi::window_find_refnum($refnum)) {  		$refnum++;  	} @@ -480,14 +507,13 @@ sub cmd_window_unalias {  	Irssi::print("chanact: moved wintow to refnum $refnum");  } -# function by veli@piipiip.net  # Make an alias  sub cmd_window_alias {  	my ($data, $server, $witem) = @_;  	my $rn_start = Irssi::settings_get_int('chanact_renumber_start');  	unless ($data =~ /^[a-zA-Z+]$/) { -		Irssi::print("Usage: /window_alias <char>"); +		Irssi::print("Usage: /chanact_window_alias <char>");  		return;  	} @@ -508,23 +534,23 @@ sub cmd_window_alias {  		$winname = $window->{name};  	} -	cmd_window_unalias($data, $server, $witem, 1); +	unbind($window->{name}, $server);  	my $winnum = $window->{refnum}; -	 +  	if (Irssi::settings_get_bool('chanact_autorenumber') == 1 &&  			$window->{refnum} < $rn_start) {  		my $old_refnum = $window->{refnum};  		$winnum = $rn_start; -  +  		# Find the first available slot and move the window -		while (Irssi::window_find_refnum($winnum) ne "") { $winnum++; } +		while (Irssi::window_find_refnum($winnum)) { $winnum++; }  		$window->set_refnum($winnum); -		 +  		Irssi::print("Moved the window from $old_refnum to $winnum");  	} -	 +  	my $winserver = $window->{active_server}->{tag};  	my $winhandle = "$winserver/$winname";  	# cmd_window_unalias relies on a certain format here @@ -543,8 +569,8 @@ sub cmd_window_alias {  $needRemake = 1;  # Window alias command -Irssi::command_bind('window_alias','cmd_window_alias'); -Irssi::command_bind('window_unalias','cmd_window_unalias'); +Irssi::command_bind('chanact_window_alias','cmd_window_alias'); +Irssi::command_bind('chanact_window_unalias','cmd_window_unalias');  # our config item  Irssi::settings_add_str('chanact', 'chanact_display', '$H$N:$M$C$S'); @@ -587,8 +613,15 @@ Irssi::signal_add('nick mode changed', 'chanactHasChanged');  #  # Changelog  # -# 0.5.15 -# 	- fixed unbind error when aliasing a previously un-aliased window +# 0.6.0 +# 	- fixed URL +# 	- now with 'use warnings' +# 	- fix cmd_window_unalias call from cmd_window_alias +# 	- fix Use of uninitialized value $name in hash element warnings +# 	- return from cmd_window_unalias if the window has no valid +# 	  chanact'ified name +#	- rename /window_(un)alias to /chanact_window_(un)alias +#	- fix refnum renumber race  # 	- added setting to allow case-insensitive window aliases  #  # 0.5.14 @@ -645,10 +678,10 @@ Irssi::signal_add('nick mode changed', 'chanactHasChanged');  #  # 0.5.6  # - fixed a bug (#1) reported by Wouter Coekaert -#  +#  # 0.5.5  # - some speedups from David Leadbeater <dgl@dgl.cx> -#  +#  #  # 0.5.4  # - added help for chanact_display_alias @@ -662,7 +695,7 @@ Irssi::signal_add('nick mode changed', 'chanactHasChanged');  # - removed unused chanact_show_name settings (thx to Qerub)  # - fixed $mode display  # - guarded reference operations to (hopefully) fix errors on server disconnect -#  +#  # 0.5.1  # - small typo fixed  # @@ -670,7 +703,7 @@ Irssi::signal_add('nick mode changed', 'chanactHasChanged');  # - changed chanact_show_mode to chanact_display. reversed changes from  #   Qerub through that, but kept funcionality.  # - removed chanact_color_all since it is no longer needed -#  +#  # 0.4.3  # - changes by Qerub  #   + added chanact_show_mode to show the mode just before the channel name diff --git a/scripts/colorkick.pl b/scripts/colorkick.pl index 24b29fd..c28e420 100644 --- a/scripts/colorkick.pl +++ b/scripts/colorkick.pl @@ -13,7 +13,8 @@ use strict;  use Irssi;  use Irssi::Irc; -use vars %IRSSI; +use vars qw/%IRSSI $VERSION/; +$VERSION='0.1';  %IRSSI =  (  	authors		=> "Gabor Nyeki", @@ -22,7 +23,7 @@ use vars %IRSSI;  	description	=> "kicking users for using colors or blinks",  	license		=> "public domain",  	written		=> "Thu Dec 26 00:22:54 CET 2002", -	changed		=> "Fri Jan  2 03:43:10 CET 2004" +	changed		=> "2017-03-07"  );  sub catch_junk @@ -31,15 +32,15 @@ sub catch_junk  	my ($target, $text) = split(/ :/, $data, 2);  	my $valid_channel = 0; -	if ($target[0] != '#' && $target[0] != '!' && $target[0] != '&') -	{ -		return; -	} +	#if ($target[0] != '#' && $target[0] != '!' && $target[0] != '&') +	#{ +	#	return; +	#}  	for my $channel (split(/ /,  		Irssi::settings_get_str('colorkick_channels')))  	{ -		if ($target == $channel) +		if ($target eq $channel)  		{  			$valid_channel = 1;  			last; diff --git a/scripts/connectcmd.pl b/scripts/connectcmd.pl index b2bbdc2..9b5bf38 100644 --- a/scripts/connectcmd.pl +++ b/scripts/connectcmd.pl @@ -1,7 +1,8 @@  use strict;  use Irssi 20020101.0250 (); +  use vars qw($VERSION %IRSSI); -$VERSION = "0.1"; +$VERSION = "0.2";  %IRSSI = (      authors     => "Ian Peters",      contact     => "itp\@ximian.com", @@ -9,7 +10,7 @@ $VERSION = "0.1";      description => "run arbitrary shell commands while [dis]connecting to a server",      license     => "Public Domain",      url         => "http://irssi.org/", -    changed     => "Sun, 10 Mar 2002 17:08:03 -0500" +    changed     => "2017-03-18"  );  my %preconn_actions; @@ -17,39 +18,42 @@ my %postconn_actions;  my %disconn_actions;  sub load_actions { -  open ACTIONS, q{<}, "$ENV{HOME}/.irssi/connectcmd_actions"; +  my $fi; + +  open $fi, '<', "$ENV{HOME}/.irssi/connectcmd_actions"; -  while (<ACTIONS>) { +  while (<$fi>) {      my @lines = split "\n";      foreach my $line (@lines) {        my ($server, $type, $action) = split ":", $line;        if ($type eq "preconn") { -	$preconn_actions{$server} = $action; +	      $preconn_actions{$server} = $action;        } elsif ($type eq "postconn") { -	$postconn_actions{$server} = $action; +	      $postconn_actions{$server} = $action;        } elsif ($type eq "disconn") { -	$disconn_actions{$server} = $action; +	      $disconn_actions{$server} = $action;        }      }    } -  close ACTIONS; +  close $fi;  }  sub save_actions { -  open ACTIONS, q{>}, "$ENV{HOME}/.irssi/connectcmd_actions"; +  my $fa; +  open $fa, q{>}, "$ENV{HOME}/.irssi/connectcmd_actions";    foreach my $server (keys %preconn_actions) { -    print ACTIONS "$server:preconn:$preconn_actions{$server}\n"; +    print $fa "$server:preconn:$preconn_actions{$server}\n";    }    foreach my $server (keys %postconn_actions) { -    print ACTIONS "$server:postconn:$postconn_actions{$server}\n"; +    print $fa "$server:postconn:$postconn_actions{$server}\n";    }    foreach my $server (keys %disconn_actions) { -    print ACTIONS "$server:disconn:$disconn_actions{$server}\n"; +    print $fa "$server:disconn:$disconn_actions{$server}\n";    } -  close ACTIONS; +  close $fa;  }  sub sig_server_looking { @@ -78,7 +82,13 @@ sub sig_server_disconnected {  sub cmd_connectcmd {    my ($data, $server, $witem) = @_; -  my ($op, $type, $server, $action) = split " ", $data; +   +  #my ($op, $type, $server, $action) = split " ", $data; +  $data =~ m/^(\S*)\s+(\S*)\s+(\S*)\s+(.*)$/; +  my $op=$1; +  my $type=$2; +  my $server=$3; +  my $action=$4;    $op = lc $op; @@ -146,7 +156,7 @@ sub cmd_connectcmd {    }  } -load_actions; +load_actions();  Irssi::command_bind ('connectcmd', 'cmd_connectcmd'); diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl new file mode 100644 index 0000000..da39804 --- /dev/null +++ b/scripts/ctrlact.pl @@ -0,0 +1,574 @@ +# ctrlact.pl — Irssi script for fine-grained control of activity indication +# +# © 2017 martin f. krafft <madduck@madduck.net> +# Released under the MIT licence. +# +### Usage: +# +# /script load ctrlact +# +# If you like a busy activity statusbar, this script is not for you. +# +# If, on the other hand, you don't care about most activity, but you do want +# the ability to define per-item and per-window, what level of activity should +# trigger a change in the statusbar, then ctrlact might be for you. +# +# For instance, you might never want to be disturbed by activity in any +# channel, unless someone highlights you. However, you do want all activity +# in queries (except on efnet, as well as an indication about any chatter in +# your company channels. The following ctrlact map would do this for you: +# +#	channel			/^#myco-/	messages +#	channel			*		hilights +#	query		efnet	*		messages +#	query			*		all +# +# These three lines would be interpreted/read as: +#  "only messages or higher in a channel matching /^#myco-/ should trigger act" +#  "in all other channels, only hilights (or higher) should trigger act" +#  "queries on efnet should only trigger act for messages and higher" +#  "messages of all levels should trigger act in queries elsewhere" +# +# The activity level in the third column is thus to be interpreted as +#  "the minimum level of activity that will trigger an indication" +# +# Loading this script per-se should not change anything, except it will create +# ~/.irssi/ctrlact with some informational content, including the defaults and +# some examples. +# +# The four activity levels are, and you can use either the words, or the +# integers in the map. +# +#	all		(data_level: 1) +#	messages	(data_level: 2) +#	hilights	(data_level: 3) +#	none		(data_level: 4) +# +# Note that the name is either matched in full and verbatim, or treated like +# a regular expression, if it starts and ends with the same punctuation +# character. The asterisk ('*') is special and simply gets translated to /.*/ +# internally. No other wildcards are supported. +# +# Once you defined your mappings, please don't forget to /ctrlact reload them. +# You can then use the following commands from Irssi to check out the result: +# +#	# list all mappings +#	/ctrlact list +# +#	# query the applicable activity levels, possibly limited to +#	# windows/channels/queries +#	/ctrlact query name [name, …] [-window|-channel|-query] +# +#	# display the applicable level for each window/channel/query +#	/ctrlact show [-window|-channel|-query] +# +# There's an interplay between window items and windows here, and you can +# specify mininum activity levels for each. Here are the rules: +# +# 1. if the minimum activity level of a window item (channel or query) is not +#    reached, then the window is prevented from indicating activity. +# 2. if traffic in a window item does reach minimum activity level, then the +#    minimum activity level of the window is considered, and activity is only +#    indicated if the window's minimum activity level is lower. +# +# In general, this means you'd have windows defaulting to 'all', but it might +# come in handy to move window items to windows with min.levels of 'hilights' +# or even 'none' in certain cases, to further limit activity indication for +# them. +# +# You can use the Irssi settings activity_msg_level and activity_hilight_level +# to specify which IRC levels will be considered messages and hilights. Note +# that if an activity indication is inhibited, then there also won't be +# a beep (cf. beep_msg_level), unless you toggle ctrlmap_inhibit_beep. +# +### Settings: +# +# /set ctrlact_map_file [~/.irssi/ctrlact] +#   Controls where the activity control map will be read from (and saved to) +# +# /set ctrlact_fallback_(channel|query|window)_threshold [1] +#   Controls the lowest data level that will trigger activity for channels, +#   queries, and windows respectively, if no applicable mapping could be +#   found. +# +# /set ctrlact_inhibit_beep [on] +#   If an activity wouldn't be indicated, also inhibit the beep/bell. Turn +#   this off if you want the bell anyway. +# +# /set ctrlact_debug [off] +#   Turns on debug output. Not that this may itself be buggy, so please don't +#   use it unless you really need it. +# +### To-do: +# +# - figure out interplay with activity_hide_level +# - /ctrlact add/delete/move and /ctrlact save, maybe +# - completion for commands +# +use strict; +use warnings; +use Carp qw( croak ); +use Irssi; +use Text::ParseWords; + +our $VERSION = '1.2'; + +our %IRSSI = ( +    authors     => 'martin f. krafft', +    contact     => 'madduck@madduck.net', +    name        => 'ctrlact', +    description => 'allows per-channel control over activity indication', +    license     => 'MIT', +    changed     => '2017-02-24' +); + +### DEFAULTS AND SETTINGS ###################################################### + +my $debug = 0; +my $map_file = Irssi::get_irssi_dir()."/ctrlact"; +my $fallback_channel_threshold = 1; +my $fallback_query_threshold = 1; +my $fallback_window_threshold = 1; +my $inhibit_beep = 1; + +Irssi::settings_add_str('ctrlact', 'ctrlact_map_file', $map_file); +Irssi::settings_add_bool('ctrlact', 'ctrlact_debug', $debug); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_channel_threshold', $fallback_channel_threshold); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_query_threshold', $fallback_query_threshold); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_window_threshold', $fallback_window_threshold); +Irssi::settings_add_bool('ctrlact', 'ctrlact_inhibit_beep', $inhibit_beep); + +sub sig_setup_changed { +	$debug = Irssi::settings_get_bool('ctrlact_debug'); +	$map_file = Irssi::settings_get_str('ctrlact_map_file'); +	$fallback_channel_threshold = Irssi::settings_get_int('ctrlact_fallback_channel_threshold'); +	$fallback_query_threshold = Irssi::settings_get_int('ctrlact_fallback_query_threshold'); +	$fallback_window_threshold = Irssi::settings_get_int('ctrlact_fallback_window_threshold'); +	$inhibit_beep = Irssi::settings_get_bool('ctrlact_inhibit_beep'); +} +Irssi::signal_add('setup changed', \&sig_setup_changed); +Irssi::signal_add('setup reread', \&sig_setup_changed); +sig_setup_changed(); + +my $changed_since_last_save = 0; + +my @DATALEVEL_KEYWORDS = ('all', 'messages', 'hilights', 'none'); + +### HELPERS #################################################################### + +my $_inhibit_debug_activity = 0; +use constant DEBUGEVENTFORMAT => "%7s %7.7s %-22.22s  %d %s %d → %-7s  (%-8s ← %s)"; +sub debugprint { +	return unless $debug; +	my ($msg, @rest) = @_; +	$_inhibit_debug_activity = 1; +	Irssi::print("ctrlact debug: ".$msg, MSGLEVEL_CRAP); +	$_inhibit_debug_activity = 0; +} + +sub error { +	my ($msg) = @_; +	Irssi::print("ctrlact: ERROR: $msg", MSGLEVEL_CLIENTERROR); +} + +my @window_thresholds; +my @channel_thresholds; +my @query_thresholds; + +sub match { +	my ($pat, $text) = @_; +	my $npat = ($pat eq '*') ? '/.*/' : $pat; +	if ($npat =~ m/^(\W)(.+)\1$/) { +		my $re = qr/$2/; +		$pat = $2 unless $pat eq '*'; +		return $pat if $text =~ /$re/i; +	} +	else { +		return $pat if lc($text) eq lc($npat); +	} +	return 0; +} + +sub to_data_level { +	my ($kw) = @_; +	return $1 if $kw =~ m/^(\d+)$/; +	foreach my $i (2..4) { +		my $matcher = qr/^$DATALEVEL_KEYWORDS[5-$i]$/; +		return 6-$i if $kw =~ m/$matcher/i; +	} +	return 1; +} + +sub from_data_level { +	my ($dl) = @_; +	croak "Invalid numeric data level: $dl" unless $dl =~ m/^([1-4])$/; +	return $DATALEVEL_KEYWORDS[$dl-1]; +} + +sub walk_match_array { +	my ($name, $net, $type, @arr) = @_; +	foreach my $quadruplet (@arr) { +		my $netmatch = $net eq '*' ? '(ignored)' +					: match($quadruplet->[0], $net); +		my $match = match($quadruplet->[1], $name); +		next unless $netmatch and $match; + +		my $result = to_data_level($quadruplet->[2]); +		my $tresult = from_data_level($result); +		$name = '(unnamed)' unless length $name; +		$match = sprintf('line %3d = net:%s name:%s', +			$quadruplet->[3], $netmatch, $match); +		return ($result, $tresult, $match) +	} +	return -1; +} + +sub get_mappings_table { +	my (@arr) = @_; +	my @ret = (); +	for (my $i = 0; $i < @arr; $i++) { +		push @ret, sprintf("%4d: %-10s %-40s %-10s (line: %3d)", +			$i, $arr[$i]->[0], $arr[$i]->[1], $arr[$i]->[2], $arr[$i]->[3]); +	} +	return join("\n", @ret); +} + +sub get_specific_threshold { +	my ($type, $name, $net) = @_; +	$type = lc($type); +	if ($type eq 'window') { +		return walk_match_array($name, $net, $type, @window_thresholds); +	} +	elsif ($type eq 'channel') { +		return walk_match_array($name, $net, $type, @channel_thresholds); +	} +	elsif ($type eq 'query') { +		return walk_match_array($name, $net, $type, @query_thresholds); +	} +	else { +		croak "ctrlact: can't look up threshold for type: $type"; +	} +} + +sub get_item_threshold { +	my ($chattype, $type, $name, $net) = @_; +	my ($ret, $tret, $match) = get_specific_threshold($type, $name, $net); +	return ($ret, $tret, $match) if $ret > 0; +	if ($type eq 'CHANNEL') { +		return ($fallback_channel_threshold, from_data_level($fallback_channel_threshold), '[default]'); +	} +	else { +		return ($fallback_query_threshold, from_data_level($fallback_query_threshold), '[default]'); +	} +} + +sub get_win_threshold { +	my ($name, $net) = @_; +	my ($ret, $tret, $match) = get_specific_threshold('window', $name, $net); +	if ($ret > 0) { +		return ($ret, $tret, $match); +	} +	else { +		return ($fallback_window_threshold, from_data_level($fallback_window_threshold), '[default]'); +	} +} + +sub print_levels_for_all { +	my ($type, @arr) = @_; +	Irssi::print("ctrlact: $type mappings:"); +	for (my $i = 0; $i < @arr; $i++) { +		my $name = $arr[$i]->{'name'}; +		my $net = $arr[$i]->{'server'}->{'tag'} // ''; +		my ($t, $tt, $match) = get_specific_threshold($type, $name, $net); +		my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $arr[$i]->window()->{'refnum'}; +		Irssi::print(sprintf("%4d: %-40.40s → %d (%-8s)  match %s", $c, $name, $t, $tt, $match), MSGLEVEL_CRAP); +	} +} + +### HILIGHT SIGNAL HANDLERS #################################################### + +my $_inhibit_beep = 0; +my $_inhibit_window = 0; + +sub maybe_inhibit_witem_hilight { +	my ($witem, $oldlevel) = @_; +	return unless $witem; +	$oldlevel = 0 unless $oldlevel; +	my $newlevel = $witem->{'data_level'}; +	return if ($newlevel <= $oldlevel); + +	$_inhibit_window = 0; +	$_inhibit_beep = 0; +	my $wichattype = $witem->{'chat_type'}; +	my $witype = $witem->{'type'}; +	my $winame = $witem->{'name'}; +	my $witag = $witem->{'server'}->{'tag'} // ''; +	my ($th, $tth, $match) = get_item_threshold($wichattype, $witype, $winame, $witag); +	my $inhibit = $newlevel > 0 && $newlevel < $th; +	debugprint(sprintf(DEBUGEVENTFORMAT, lc($witype), $witag, $winame, $newlevel, +			$inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), +			$tth, $match)); +	if ($inhibit) { +		Irssi::signal_stop(); +		# the rhval comes from config, so if the user doesn't want the +		# bell inhibited, this is effectively a noop. +		$_inhibit_beep = $inhibit_beep; +		$_inhibit_window = $witem->window(); +	} +} +Irssi::signal_add_first('window item hilight', \&maybe_inhibit_witem_hilight); + +sub inhibit_win_hilight { +	my ($win) = @_; +	Irssi::signal_stop(); +	Irssi::signal_emit('window dehilight', $win); +} + +sub maybe_inhibit_win_hilight { +	my ($win, $oldlevel) = @_; +	return unless $win; +	if ($_inhibit_debug_activity) { +		inhibit_win_hilight($win); +	} +	elsif ($_inhibit_window && $win->{'refnum'} == $_inhibit_window->{'refnum'}) { +		inhibit_win_hilight($win); +	} +	else { +		$oldlevel = 0 unless $oldlevel; +		my $newlevel = $win->{'data_level'}; +		return if ($newlevel <= $oldlevel); + +		my $wname = $win->{'name'}; +		my $wtag = $win->{'server'}->{'tag'} // ''; +		my ($th, $tth, $match) = get_win_threshold($wname, $wtag); +		my $inhibit = $newlevel > 0 && $newlevel < $th; +		debugprint(sprintf(DEBUGEVENTFORMAT, 'window', $wtag, +				$wname?$wname:'(unnamed)', $newlevel, +				$inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), +				$tth, $match)); +		inhibit_win_hilight($win) if $inhibit; +	} +} +Irssi::signal_add_first('window hilight', \&maybe_inhibit_win_hilight); + +sub maybe_inhibit_beep { +	Irssi::signal_stop() if $_inhibit_beep; +} +Irssi::signal_add_first('beep', \&maybe_inhibit_beep); + +### SAVING AND LOADING ######################################################### + +sub get_mappings_fh { +	my ($filename) = @_; +	my $fh; +	if (-e $filename) { +		open($fh, '<', $filename) || croak "Cannot open mappings file: $!"; +	} +	else { +		open($fh, '+>', $filename) || croak "Cannot create mappings file: $!"; + +		my $ftw = from_data_level($fallback_window_threshold); +		my $ftc = from_data_level($fallback_channel_threshold); +		my $ftq = from_data_level($fallback_query_threshold); +		print $fh <<"EOF"; +# ctrlact mappings file (version: $VERSION) +# +# type: window, channel, query +# server: the server tag (chatnet) +# name: full name to match, /regexp/, or * (for all) +# min.level: none, messages, hilights, all, or 1,2,3,4 +# +# type	server	name	min.level + + +# EXAMPLES +# +### only indicate activity in the status window if messages were displayed: +# window	*	(status)	messages +# +### never ever indicate activity for any item bound to this window: +# window	*	oubliette	none +# +### indicate activity on all messages in debian-related channels on OFTC: +# channel	oftc	/^#debian/	messages +# +### display any text (incl. joins etc.) for the '#madduck' channel: +# channel	*	#madduck	all +# +### otherwise ignore everything in channels, unless a hilight is triggered: +# channel	*	*	hilights +# +### make somebot only get your attention if they hilight you: +# query	efnet	somebot	hilights +# +### otherwise we want to see everything in queries: +# query	*	*	all + +# DEFAULTS: +# window	*	*	$ftw +# channel	*	*	$ftc +# query	*	*	$ftq + +# vim:noet:tw=0:ts=16 +EOF +		Irssi::print("ctrlact: created new/empty mappings file: $filename"); +		seek($fh, 0, 0) || croak "Cannot rewind $filename."; +	} +	return $fh; +} + +sub load_mappings { +	my ($filename) = @_; +	@window_thresholds = @channel_thresholds = @query_thresholds = (); +	my $fh = get_mappings_fh($filename); +	my $firstline = <$fh> || croak "Cannot read from $filename.";; +	my $version; +	if ($firstline =~ m/^#+\s+ctrlact mappings file \(version: *([\d.]+)\)/) { +		$version = $1; +	} +	else { +		croak "First line of $filename is not a ctrlact header."; +	} + +	my $nrcols = 4; +	if ($version eq $VERSION) { +		# current version, i.e. no special handling is required. If +		# previous versions require special handling, then massage the +		# data or do whatever is required in the following +		# elsif-clauses: +	} +	elsif ($version eq "1.0") { +		$nrcols = 3; +	} +	my $linesplitter = '^\s*'.join('\s+', ('(\S+)') x $nrcols).'\s*$'; +	my $l = 1; +	while (<$fh>) { +		$l++; +		next if m/^\s*(?:#|$)/; +		my ($type, @matchers) = m/$linesplitter/; +		@matchers = ['*', @matchers] if ($version eq "1.0"); +		push @matchers, $l; +		push @window_thresholds, [@matchers] if match($type, 'window'); +		push @channel_thresholds, [@matchers] if match($type, 'channel'); +		push @query_thresholds, [@matchers] if match($type, 'query'); +	} +	close($fh) || croak "Cannot close mappings file: $!"; +} + +sub cmd_load { +	Irssi::print("ctrlact: loading mappings from $map_file"); +	load_mappings($map_file); +	$changed_since_last_save = 0; +} + +sub cmd_save { +	error("saving not yet implemented"); +	return 1; +} + +sub cmd_list { +	Irssi::print("ctrlact: window mappings"); +	Irssi::print(get_mappings_table(@window_thresholds), MSGLEVEL_CRAP); +	Irssi::print("ctrlact: channel mappings"); +	Irssi::print(get_mappings_table(@channel_thresholds), MSGLEVEL_CRAP); +	Irssi::print("ctrlact: query mappings"); +	Irssi::print(get_mappings_table(@query_thresholds), MSGLEVEL_CRAP); +} + +sub parse_args { +	my (@args) = @_; +	my @words = (); +	my $typewasset = 0; +	my $tag; +	my $max = 0; +	my $type = undef; +	foreach my $arg (@args) { +		if ($arg =~ m/^-(windows?|channels?|quer(?:ys?|ies))/) { +			if ($typewasset) { +				error("can't specify -$1 after -$type"); +				return 1; +			} +			$type = 'window' if $1 =~ m/^w/; +			$type = 'channel' if $1 =~ m/^c/; +			$type = 'query' if $1 =~ m/^q/; +			$typewasset = 1 +		} +		elsif ($arg =~ m/-(\S+)/) { +			$tag = $1; +		} +		else { +			push @words, $arg; +			$max = length $arg if length $arg > $max; +		} +	} +	return ($type, $tag, $max, @words); +} + +sub cmd_query { +	my ($data, $server, $item) = @_; +	my @args = shellwords($data); +	my ($type, $tag, $max, @words) = parse_args(@args); +	$type = $type // 'channel'; +	$tag = $tag // '*'; +	foreach my $word (@words) { +		my ($t, $tt, $match) = get_specific_threshold($type, $word, $tag); +		printf CLIENTCRAP "ctrlact $type map: %s %*s → %d (%s, match:%s)", $tag, $max, $word, $t, $tt, $match; +	} +} + +sub cmd_show { +	my ($data, $server, $item) = @_; +	my @args = shellwords($data); +	my ($type, $max, @words) = parse_args(@args); +	$type = $type // 'all'; + +	if ($type eq 'channel' or $type eq 'all') { +		print_levels_for_all('channel', Irssi::channels()); +	} +	if ($type eq 'query' or $type eq 'all') { +		print_levels_for_all('query', Irssi::queries()); +	} +	if ($type eq 'window' or $type eq 'all') { +		print_levels_for_all('window', Irssi::windows()); +	} +} + +sub autosave { +	cmd_save() if ($changed_since_last_save); +} + +sub UNLOAD { +	autosave(); +} + +Irssi::signal_add('setup saved', \&autosave); +Irssi::signal_add('setup reread', \&cmd_load); + +Irssi::command_bind('ctrlact help',\&cmd_help); +Irssi::command_bind('ctrlact reload',\&cmd_load); +Irssi::command_bind('ctrlact load',\&cmd_load); +Irssi::command_bind('ctrlact save',\&cmd_save); +Irssi::command_bind('ctrlact list',\&cmd_list); +Irssi::command_bind('ctrlact query',\&cmd_query); +Irssi::command_bind('ctrlact show',\&cmd_show); + +Irssi::command_bind('ctrlact' => sub { +		my ( $data, $server, $item ) = @_; +		$data =~ s/\s+$//g; +		if ($data) { +			Irssi::command_runsub('ctrlact', $data, $server, $item); +		} +		else { +			cmd_help(); +		} +	} +); +Irssi::command_bind('help', sub { +		$_[0] =~ s/\s+$//g; +		return unless $_[0] eq 'ctrlact'; +		cmd_help(); +		Irssi::signal_stop(); +	} +); + +cmd_load(); diff --git a/scripts/dau.pl b/scripts/dau.pl index 89a6623..ac8c051 100644 --- a/scripts/dau.pl +++ b/scripts/dau.pl @@ -1417,7 +1417,7 @@ sub switch_create_files {  	} else { -		if (open(FH1, "> $file1")) { +		if (open(FH1, ">", $file1)) {  			print FH1 &fix(<<'			END');  			# dau.pl - http://dau.pl/ @@ -1451,7 +1451,7 @@ sub switch_create_files {  	} else { -		if (open(FH1, "> $file2")) { +		if (open(FH1, ">", $file2)) {  			print FH1 &fix(<<'			END');  			END @@ -1479,7 +1479,7 @@ sub switch_create_files {  	} else { -		if (open(FH1, "> $file3")) { +		if (open(FH1, ">", $file3)) {  			print FH1 &fix(<<'			END');  			END @@ -5736,7 +5736,7 @@ sub time_parse {  ################################################################################  sub debug_message { -        open(DEBUG, ">> $ENV{HOME}/.dau/.debug"); +        open(DEBUG, ">>", "$ENV{HOME}/.dau/.debug");          print DEBUG $_[0]; @@ -5746,5 +5746,5 @@ sub debug_message {  #BEGIN {  #	use warnings;  # -#	open(STDERR, ">> $ENV{HOME}/.dau/.STDERR"); +#	open(STDERR, ">>", $ENV{HOME}/.dau/.STDERR");  #} diff --git a/scripts/dccself.pl b/scripts/dccself.pl index e944133..1a6ccea 100644 --- a/scripts/dccself.pl +++ b/scripts/dccself.pl @@ -1,7 +1,8 @@  use strict; -use vars qw/%IRSSI/; +use vars qw/%IRSSI $VERSION/;  use Irssi qw(command_bind active_server); +$VERSION= "0.1";  %IRSSI = (  	authors     => "David Leadbeater",  	contact     => "dgl\@dgl.cx", diff --git a/scripts/desktop-notify.pl b/scripts/desktop-notify.pl index da25b8c..c41a9f4 100644 --- a/scripts/desktop-notify.pl +++ b/scripts/desktop-notify.pl @@ -24,8 +24,9 @@ use strict;  use Irssi;  use HTML::Entities;  use Glib::Object::Introspection; # Ignore 'late INIT' warning message if autoloading +use Encode; -our $VERSION = '1.0.0'; +our $VERSION = '1.0.1';  our %IRSSI = (  	authors     => 'Felipe F. Tonello',  	contact     => 'eu@felipetonello.com', @@ -38,6 +39,7 @@ our %IRSSI = (  # List of standard icons can be found here:  # http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#names  my $notify_icon; +my $term_charset;  my $help = '  /set notify_icon <icon-name> @@ -60,6 +62,7 @@ sub UNLOAD {  sub setup_changed {  	$notify_icon = Irssi::settings_get_str('notify_icon'); +	$term_charset = Irssi::settings_get_str('term_charset');  }  sub priv_msg { @@ -71,9 +74,9 @@ sub priv_msg {  		return;  	} -	my $msg = HTML::Entities::encode_entities(Irssi::strip_codes($msg)); +	my $msg = HTML::Entities::encode_entities(Irssi::strip_codes($msg), "\<>&'");  	my $network = $server->{tag}; -	my $noti = Notify::Notification->new($nick . '@' . $network, $msg, $notify_icon); +	my $noti = Notify::Notification->new($nick . '@' . $network, decode($term_charset, $msg), $notify_icon);  	$noti->show();  } @@ -94,8 +97,8 @@ sub hilight {  	}  	my $network = $server->{tag}; -	my $msg = HTML::Entities::encode_entities($stripped); -	my $noti = Notify::Notification->new($dest->{target} . '@' . $network, $msg, $notify_icon); +	my $msg = HTML::Entities::encode_entities($stripped, "\'<>&"); +	my $noti = Notify::Notification->new($dest->{target} . '@' . $network, decode($term_charset, $msg), $notify_icon);  	$noti->show();  } diff --git a/scripts/df.pl b/scripts/df.pl index 8b4f086..852cdee 100644 --- a/scripts/df.pl +++ b/scripts/df.pl @@ -10,6 +10,7 @@ $VERSION="0.1.0";  	contact=> 'jochem.meyers@gmail.com',  	name=> 'df',  	description=> 'Adds an item which displays the current disk usage.', +	sbitems=> 'df',  	license=> 'GPL v2 or later',  	url=> 'http://kaede.kicks-ass.net/irssi.html',  ); diff --git a/scripts/dr_who.pl b/scripts/dr_who.pl index cbf3db0..eb66435 100644 --- a/scripts/dr_who.pl +++ b/scripts/dr_who.pl @@ -24,6 +24,7 @@ $VERSION = '1.0';  	contact     => 'lxsfx3h02@sneakemail.com',
  	name        => 'dr_who',
  	description => 'Put a nick list in a statusbar',
 +	sbitems => 'dr_who',
  	license => 'BSD',
  	url     => 'http://beaglebros.com',
  	changed => '1-17-2005'
 diff --git a/scripts/fullrain.pl b/scripts/fullrain.pl new file mode 100644 index 0000000..bac0a62 --- /dev/null +++ b/scripts/fullrain.pl @@ -0,0 +1,98 @@ +# fullrain.pl - Irssi script for colorized fullwidth text +# Copyright (C) 2017 Kenneth B. Jensen <kenneth@jensen.cf> + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 3 as  +# published by the Free Software Foundation. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. + + +use strict; +use warnings; +use Encode qw(decode); +use Irssi qw(command_bind active_win); + +our $VERSION = '1.0.0'; +our %IRSSI = ( +	authors     => 'kjensenxz', +	contact     => 'kenneth@jensen.cf', +	name        => 'fullrain', +	url         => 'http://github.com/kjensenxz', +	description => 'Prints colorized fullwidth text', +	license     => 'GNU GPLv3', + +	# code borrowed from scripts: +	# 'fullwidth' by prussian <genunrest@gmail.com>  +	# http://github.com/GeneralUnRest/ || Apache 2.0 License +	# 'rainbow' by Jakub Jankowski <shasta@atn.pl> +	# http://irssi.atn.pl/ || GNU GPLv2 (or later) License +); +# colors +#  0 white +#  4 light red +#  8 yellow +#  9 light green +# 11 light cyan +# 12 light blue +# 13 light magenta +my @COLORS = (0, 4, 8, 9, 11, 12, 13); + +sub make_fullcolor { +	my $str = decode('UTF-8', $_[0]); +	my $newstr = q(); + +	my $color = 0; +	my $prev = $color; +	foreach my $char (split //xms, $str) { +		if ($char =~ /\s/xms) { +			$newstr .= q( ); +		} +		else { +			my $nchar = ord $char; +			while (($color = int rand scalar @COLORS) == $prev) {}; +			$prev = $color; +			$newstr .= "\003" . $COLORS[$prev]; +			# check if char is printing nonwhite ascii +			if ($nchar > ord ' ' && $nchar <= ord '~') { +				$newstr .= chr $nchar + 65_248; +			} +			else { +				$newstr .= $char . ' '; +			} +		} +	} +	return $newstr; +} + +command_bind(rfsay => sub { +	my $say = make_fullcolor($_[0]); +	active_win->command("say $say"); #say what you want +	# but don't play games with my affection +}); + +command_bind(rfme => sub { +	my $say = make_fullcolor($_[0]); +	active_win->command("/me $say"); +}); + +command_bind(rftopic => sub { +	my $say = make_fullcolor($_[0]); +	active_win->command("/topic $say"); +}); + +command_bind(rfaway => sub { +	my $say = make_fullcolor($_[0]); +	active_win->command("/away $say"); +}); + +1; + +# changelog: +# 2017/03/28 (1.0.0): initial release diff --git a/scripts/fullwidth.pl b/scripts/fullwidth.pl index 261aa5a..4d17b70 100644 --- a/scripts/fullwidth.pl +++ b/scripts/fullwidth.pl @@ -14,8 +14,8 @@  # limitations under the License.  use strict; -use Irssi qw(command_bind active_win); -our $VERSION = '1.1.0'; +use Irssi qw(command_bind active_win signal_stop); +our $VERSION = '1.2.0';  our %IRSSI = (      authors     => 'prussian',      contact     => 'genunrest@gmail.com', @@ -25,7 +25,15 @@ our %IRSSI = (      license     => 'Apache 2.0',  ); -command_bind(fullwidth => sub { +my $help = '/fullwidth your cool text here +-> your cool text here + +you can also use stars to only fullwidth text between them + +/fullwidth do *you* know *the* way *to* San *Jose* +-> do you know the way to San Jose'; + +sub fullwidth {      my $msg = $_[0];      my $say = "";      foreach my $char (split //, $msg) { @@ -39,5 +47,24 @@ command_bind(fullwidth => sub {              }          }      } +    return $say; +} + +command_bind(fullwidth => sub { +    my $arg = $_[0]; +    my $say = ''; +    if ($arg =~ /\*[^*]*\*/) { +        $say = $_[0] =~ s/\*([^*]*)\*/fullwidth($1)/reg; +    } +    else { +        $say = fullwidth($arg); +    }      active_win->command("say $say");  }); + +command_bind(help => sub { +    if ($_[0] eq $IRSSI{name}) { +        Irssi::print($help, MSGLEVEL_CLIENTCRAP); +        signal_stop(); +    } +}); diff --git a/scripts/go.pl b/scripts/go.pl index b656a0f..0b0a2a2 100644 --- a/scripts/go.pl +++ b/scripts/go.pl @@ -7,8 +7,29 @@ use Irssi::Irc;  # /script load go.pl  # If you are in #irssi you can type /go #irssi or /go irssi or even /go ir ...  # also try /go ir<tab> and /go  <tab> (that's two spaces) +# +# The following settings exist: +# +#   /SET go_match_case_sensitive [ON|OFF] +#     Match window/item names sensitively (the default). Turning this off +#     means e.g. "/go foo" would jump to a window named "Foobar", too. +# +#   /SET go_match_anchored [ON|OFF] +#     Match window/names only at the start of the word (the default). Turning +#     this off will mean that strings can match anywhere in the window/names. +#     The leading '#' of channel names is optional either way. +# +#   /SET go_complete_case_sensitive [ON|OFF] +#     When using tab-completion, match case-insensitively (the default). +#     Turning this on means that "/go foo<tab>" will *not* suggest "Foobar". +# +#   /SET go_complete_anchored [ON|OFF] +#     Match window/names only at the start of the word. The default is 'off', +#     which causes completion to match anywhere in the window/names during +#     completion. The leading '#' of channel names is optional either way. +# -$VERSION = '1.01'; +$VERSION = '1.1';  %IRSSI = (      authors     => 'nohar', @@ -16,9 +37,17 @@ $VERSION = '1.01';      name        => 'go to window',      description => 'Implements /go command that activates a window given a name/partial name. It features a nice completion.',      license     => 'GPLv2 or later', -    changed     => '2014-10-19' +    changed     => '2017-02-02'  ); +sub _make_regexp { +	my ($name, $ci, $aw) = @_; +	my $re = "\Q${name}\E"; +	$re = "(?i:$re)" unless $ci; +	$re = "^#?$re" if $aw; +	return $re; +} +  sub signal_complete_go {  	my ($complist, $window, $word, $linestart, $want_space) = @_;  	my $channel = $window->get_active_name(); @@ -26,11 +55,14 @@ sub signal_complete_go {          return unless ($linestart =~ /^\Q${k}\Ego\b/i); +	my $re = _make_regexp($word, +		Irssi::settings_get_bool('go_complete_case_sensitive'), +		Irssi::settings_get_bool('go_complete_anchored'));  	@$complist = ();  	foreach my $w (Irssi::windows) {  		my $name = $w->get_active_name();  		if ($word ne "") { -			if ($name =~ /\Q${word}\E/i) { +			if ($name =~ $re) {  				push(@$complist, $name)  			}  		} else { @@ -45,9 +77,13 @@ sub cmd_go  	my($chan,$server,$witem) = @_;  	$chan =~ s/ *//g; +	my $re = _make_regexp($chan, +		Irssi::settings_get_bool('go_match_case_sensitive'), +		Irssi::settings_get_bool('go_match_anchored')); +  	foreach my $w (Irssi::windows) {  		my $name = $w->get_active_name(); -		if ($name =~ /^#?\Q${chan}\E/) { +		if ($name =~ $re) {  			$w->set_active();  			return;  		} @@ -56,4 +92,14 @@ sub cmd_go  Irssi::command_bind("go", "cmd_go");  Irssi::signal_add_first('complete word', 'signal_complete_go'); +Irssi::settings_add_bool('go', 'go_match_case_sensitive', 1); +Irssi::settings_add_bool('go', 'go_complete_case_sensitive', 0); +Irssi::settings_add_bool('go', 'go_match_anchored', 1); +Irssi::settings_add_bool('go', 'go_complete_anchored', 0); +# Changelog +# +# 2017-02-02  1.1  martin f. krafft <madduck@madduck.net> +#   - made case-sensitivity of match configurable +#   - made anchoring of search strings configurable +# diff --git a/scripts/hddtemp.pl b/scripts/hddtemp.pl index 2690ba4..8563e97 100644 --- a/scripts/hddtemp.pl +++ b/scripts/hddtemp.pl @@ -48,18 +48,19 @@  use strict;  use Irssi; +use Irssi::TextUI;  use IO::Socket::INET;  use POSIX;  use vars qw($VERSION %IRSSI); -$VERSION = "0.14"; +$VERSION = "0.15";  %IRSSI = (      authors     => "Valentin Batz",      contact     => "vb\@g-23.org",      name        => "hddtemp",      description => "adds a statusbar item which shows temperatures of harddisks (with multiple hddtemp-hosts support)",      license     => "GPLv2", -    changed     => "2004-06-21", +    changed     => "2017-03-16",      url         => "http://hurzelgnom.bei.t-online.de/irssi/scripts/hddtemp.pl",      sbitems     => "hddtemp"  ); diff --git a/scripts/hilightwin.pl b/scripts/hilightwin.pl index 7d70317..3bb2863 100644 --- a/scripts/hilightwin.pl +++ b/scripts/hilightwin.pl @@ -5,27 +5,51 @@  # Modded a tiny bit by znx to stop private messages entering the hilighted  # window (can be toggled) and to put up a timestamp.  # +# Changed a little by rummik to optionally show network name. Enable with +# `/set hilightwin_shownetwork on` +#  use strict;  use Irssi;  use POSIX; -use vars qw($VERSION %IRSSI);  +use vars qw($VERSION %IRSSI); -$VERSION = "0.04"; +$VERSION = "1.00";  %IRSSI = ( -    authors     => "Timo \'cras\' Sirainen, Mark \'znx\' Sangster", -    contact     => "tss\@iki.fi, znxster\@gmail.com",  +    authors     => "Timo \'cras\' Sirainen, Mark \'znx\' Sangster, Kimberly \'rummik\' Zick", +    contact     => "tss\@iki.fi, znxster\@gmail.com, git\@zick.kim",      name        => "hilightwin",      description => "Print hilighted messages to window named \"hilight\"",      license     => "Public Domain",      url         => "http://irssi.org/", -    changed     => "Sun May 25 18:59:57 BST 2008" +    changed     => "Thu Apr  6 15:30:25 EDT 2017"  ); +sub is_ignored { +    my ($dest) = @_; + +    my @ignore = split(' ', Irssi::settings_get_str('hilightwin_ignore_targets')); +    return 0 if (!@ignore); + +    my %targets = map { $_ => 1 } @ignore; + +    return 1 if exists($targets{"*"}); +    return 1 if exists($targets{$dest->{target}}); + +    if ($dest->{server}) { +        my $tag = $dest->{server}->{tag}; +        return 1 if exists($targets{$tag . "/*"}); +        return 1 if exists($targets{$tag . "/" . $dest->{target}}); +    } + +    return 0; +} +  sub sig_printtext {      my ($dest, $text, $stripped) = @_;      my $opt = MSGLEVEL_HILIGHT; +    my $shownetwork = Irssi::settings_get_bool('hilightwin_show_network');      if(Irssi::settings_get_bool('hilightwin_showprivmsg')) {          $opt = MSGLEVEL_HILIGHT|MSGLEVEL_MSGS; @@ -33,12 +57,16 @@ sub sig_printtext {      if(          ($dest->{level} & ($opt)) && -        ($dest->{level} & MSGLEVEL_NOHILIGHT) == 0 +        ($dest->{level} & MSGLEVEL_NOHILIGHT) == 0 && +        (!is_ignored($dest))      ) {          my $window = Irssi::window_find_name('hilight');          if ($dest->{level} & MSGLEVEL_PUBLIC) {              $text = $dest->{target}.": ".$text; +            $text = $dest->{server}->{tag} . "/" . $text if ($shownetwork); +        } elsif ($shownetwork) { +            $text = $dest->{server}->{tag} . ": " . $text;          }          $text =~ s/%/%%/g;          $window->print($text, MSGLEVEL_CLIENTCRAP) if ($window); @@ -49,6 +77,8 @@ my $window = Irssi::window_find_name('hilight');  Irssi::print("Create a window named 'hilight'") if (!$window);  Irssi::settings_add_bool('hilightwin','hilightwin_showprivmsg',1); +Irssi::settings_add_str('hilightwin', 'hilightwin_ignore_targets', ''); +Irssi::settings_add_bool('hilightwin','hilightwin_show_network', 0);  Irssi::signal_add('print text', 'sig_printtext'); diff --git a/scripts/hilite_url.pl b/scripts/hilite_url.pl new file mode 100644 index 0000000..11c4b0d --- /dev/null +++ b/scripts/hilite_url.pl @@ -0,0 +1,28 @@ +# Simple script to highlight links in public messages + +use strict; +use vars qw($VERSION %IRSSI); + +# Dev. info ^_^ +$VERSION = "0.1"; +%IRSSI = ( +	authors     => "Stefan Heinemann", +	contact     => "stefan.heinemann\@codedump.ch", +	name        => "hilite url", +	description => "Simple script that highlights URL", +	license     => "GPL", +	url         => "http://senseless.codedump.ch", +); + +sub hilite_url { +	my ($server, $data, $nick, $mask, $target) = @_; + +	# Add Colours +	$data =~ s/(https?:\/\/[^\s]+)/\e[4;34m\1\e[00m/g; + +	# Let it flow +	Irssi::signal_continue($server, $data, $nick, $mask, $target); +} + +# Hook me up +Irssi::signal_add('message public', 'hilite_url'); diff --git a/scripts/hitcount.pl b/scripts/hitcount.pl index 545aee0..19a4d87 100644 --- a/scripts/hitcount.pl +++ b/scripts/hitcount.pl @@ -2,20 +2,23 @@  use strict;  use vars qw($VERSION %IRSSI); -my @rev = split(/ /, "$Revision: 1.3.2.2 $n"); -$VERSION = "1.3"; +my @rev = split(/ /, '$Revision: 1.4 $n'); +$VERSION = "1.4";  %IRSSI = ( -	    authors     => 'Riku "Shrike" Lindblad', -	    contact     => 'shrike\@addiktit.net, Shrike on IRCNet/QNet/EFNet/DALNet', -	    name        => 'hitcount', -	    description => 'Add a apache page hitcounter to statusbar', -	    license     => 'Free', -	    changed     => '$Date: 2002/03/05 18:19:28 $ ', -	  ); +    authors     => 'Riku "Shrike" Lindblad', +    contact     => 'shrike\@addiktit.net, Shrike on IRCNet/QNet/EFNet/DALNet', +    name        => 'hitcount', +    description => 'Add a apache page hitcounter to statusbar', +    sbitems     => 'hitcount', +    license     => 'Free', +    changed     => '$Date: 2017/03/07 $ ', +);  # Changelog:  # -# $Log: hitcount.pl,v $ +# Revision 1.4  2017/03/07 bw1 +# bug fix +#  # Revision 1.3.2.2  2002/03/05 18:19:28  shrike  # Added use vars qw($VERSION %IRSSI);  # @@ -54,59 +57,65 @@ use Irssi::TextUI;  # Debug level - higher levels print out more crap  my $debug_level = 0;  # current hitcount -my ($total_hitcount, $my_hitcount) = (0); +my ($total_hitcount, $my_hitcount) = (0,0);  # change prefixes -my ($my_prefix, $total_prefix) = (""); +my ($my_prefix, $total_prefix) = ("","");  # change from last update -my ($my_change, $total_change) = (0); +my ($my_change, $total_change) = (0,0);  # hitcount on last update -my ($last_total_hitcount, $last_my_hitcount, $last_refresh) = (0); +my ($last_total_hitcount, $last_my_hitcount, $last_refresh) = (0,0,0);  # set default variables -my ($filename, $regexp, $refresh) = ("/var/log/apache/access.log", "/", 60); +my ($filename, $regexp, $refresh) = ("/var/log/httpd/access.log", "/", 60); +# marker for the refresh +my $refresh_tag; +# read the access_log and count rows, regexp matches  sub get_hitcount {      my $filename = Irssi::settings_get_str('hitcount_access_log');      my $regexp = Irssi::settings_get_str('hitcount_regexp'); -    Irssi::print("Finding match for \"".my $regexp."\"", MSGLEVEL_CLIENTERROR) if($debug_level > 2); +    Irssi::print("Finding match for \"$regexp\"", MSGLEVEL_CLIENTERROR) if($debug_level > 2); -    ($total_hitcount, $my_hitcount) = (0); +    ($total_hitcount, $my_hitcount) = (0,0);      # Go through the access log and count matches to the given regexp -    if(open STUFF, "<", $filename) -    { -   	while (<STUFF>)  -	{ -	    $total_hitcount++; -	    if(/$regexp/ois) -	    { -		# DEBUG -		Irssi::print("Matched $_", MSGLEVEL_CLIENTERROR) if($debug_level > 3); -		$my_hitcount++; -	    } -	} -	close STUFF; -    } -    else -    { -	Irssi::print("Failed to open <$filename: $!", MSGLEVEL_CLIENTERROR); +    if(open STUFF, "<", $filename) { +        while (<STUFF>) { +            $total_hitcount++; +            #if(m#$regexp#ois) +            if(m<GET $regexp >) { +                # DEBUG +                Irssi::print("Matched $_", MSGLEVEL_CLIENTERROR) if($debug_level > 3); +                $my_hitcount++; +            } +        } +        close STUFF; +    } else { +        Irssi::print("Failed to open <$filename: $!", MSGLEVEL_CLIENTERROR);      } +      return($my_hitcount,$total_hitcount);  } +# show the result  sub hitcount {      my ($item, $get_size_only) = @_; -    # DEBUG -    Irssi::print("$get_size_only | $last_my_hitcount/$last_total_hitcount | $my_hitcount/$total_hitcount | $my_prefix$my_change $total_prefix$total_change", MSGLEVEL_CLIENTERROR) if($debug_level > 0); +    $item->default_handler($get_size_only,  +        "{sb Hits: $last_my_hitcount/$last_total_hitcount ". +        "$my_prefix$my_change/$total_prefix$total_change}", '', 0); +} + +# repeat refresh by interval time +sub refresh_hitcount {      my ($my_hitcount, $my_total_hitcount) = get_hitcount(); -    if($my_hitcount eq '') { $my_hitcount = 0; } -          # Calculate change since last update -    $my_change = $my_hitcount - $last_my_hitcount; -    $total_change = $total_hitcount - $last_total_hitcount; +    if ($last_total_hitcount >0) { +        $my_change = $my_hitcount - $last_my_hitcount; +        $total_change = $total_hitcount - $last_total_hitcount; +    }      # Get correct prefix for change      $my_prefix = "+" if($my_change > 0); @@ -116,7 +125,14 @@ sub hitcount {      $total_prefix = "-" if($total_change < 0);      $total_prefix = "" if($total_change == 0); -    $item->default_handler($get_size_only, undef, "$last_my_hitcount $last_total_hitcount $my_prefix$my_change $total_prefix$total_change", 1); +    # DEBUG +    Irssi::print( +        "$last_my_hitcount/$last_total_hitcount | $my_hitcount/$total_hitcount ". +        "| $my_prefix$my_change $total_prefix$total_change",  +        MSGLEVEL_CLIENTERROR) if($debug_level > 0); + +    # show it +    Irssi::statusbar_items_redraw('hitcount');      # last hitcount = current hitcount      $last_my_hitcount = $my_hitcount; @@ -128,28 +144,28 @@ sub hitcount {      $my_total_hitcount = 0;  } -sub refresh_hitcount { -    get_hitcount(); -    Irssi::statusbar_items_redraw('hitcount'); -} -  sub read_settings {      my $time = Irssi::settings_get_int('hitcount_refresh');      return if ($time == $last_refresh);      $last_refresh = $time; -    Irssi::timeout_remove(my $refresh_tag) if (my $refresh_tag); +     +    Irssi::timeout_remove($refresh_tag) if ($refresh_tag);      $refresh_tag = Irssi::timeout_add($time*1000, 'refresh_hitcount', undef); + +    refresh_hitcount();  }  # default values  Irssi::settings_add_str('misc', 'hitcount_regexp', $regexp);  Irssi::settings_add_int('misc', 'hitcount_refresh', $refresh);  Irssi::settings_add_str('misc', 'hitcount_access_log', $filename); +  # sub to call, string on statusbar, func on statusbar -Irssi::statusbar_item_register('hitcount', '{sb Hits: $0%K/%N$1 $2%K/%N$3}', 'hitcount'); +Irssi::statusbar_item_register('hitcount', 0, 'hitcount'); + +Irssi::print("Hitcounter version ".$rev[1]." loaded");  read_settings();  Irssi::signal_add('setup changed', 'read_settings'); -Irssi::print("Hitcounter version ".$rev[1]." loaded"); diff --git a/scripts/iMPD.pl b/scripts/iMPD.pl index 6078e55..bf17b93 100644 --- a/scripts/iMPD.pl +++ b/scripts/iMPD.pl @@ -86,6 +86,7 @@ $VERSION = '0.0.0n';  	  contact     => 'starz@antisocial.com',  	  name        => 'iMPD',  	  description => 'This controls Music Player Daemon from the familiar irssi interface', +	  sbitems     => 'mpdbar',  	  license     => 'GPL v2',  	  url         => 'http://www.musicpd.org'  	  ); diff --git a/scripts/ident.pl b/scripts/ident.pl new file mode 100644 index 0000000..a4854f2 --- /dev/null +++ b/scripts/ident.pl @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w + +use strict; +use Irssi; +use POSIX; + +use vars qw($VERSION %IRSSI); + +$VERSION = "1.0"; +%IRSSI = ( +    authors     => 'Isaac Good', +    contact     => "irssi\@isaacgood.com; irc.freenode.net/yitz", +    name        => 'ident', +    description => 'Ident to NickServs', +    name        => "ident", +    description => "Automatically IDENTIFY when prompted", +    license     => 'MIT', +); + + +my %pw; + + +sub LoadPasswords { +    # Load the passwords from file. +    delete @pw{keys %pw}; +    my $filename = Irssi::get_irssi_dir() . '/passwords'; +    my $FH; +    unless(open $FH, "<", $filename) +    { +        print "Can not open $filename"; +        return 0; +    } +    while (my $line = <$FH>) +    { +        chomp $line; +        next unless ($line); +        my ($tag, $password) = split(/  */, $line, 2); +        next unless ($tag and $password); +        $pw{$tag} = $password; +    } +    return 1; +} + + +sub notice { +    my ($server, $data, $nick, $host) = @_; +    my ($channel, $msg) = split(/ :/, $data, 2); +    my $l = 0; + +    # Test the notice. Must be from nickserv and be asking you to identify. +    return undef unless (lc($nick) eq 'nickserv'); +    return undef unless (lc($msg) =~ /msg nickserv identify/); +    # Check it's a direct message and we have a password for this network. +    return undef unless (lc($channel) eq lc($server->{'nick'})); +    return undef unless ($pw{$server->{'chatnet'}}); + +    my $pw = $pw{$server->{'chatnet'}}; +    # Use the /quote nickserv approach to reduce chance of leaking the password to a bad actor, ie someone pretending to be nickserv. +    $server->command("^quote nickserv identify $pw"); + +    return undef; +} + + +if (LoadPasswords()) { +    Irssi::signal_add('event notice', \¬ice); +} diff --git a/scripts/il.pl b/scripts/il.pl index b947c4a..f5a2d89 100644 --- a/scripts/il.pl +++ b/scripts/il.pl @@ -33,6 +33,7 @@ $VERSION = '0.0.5';      contact     => 'darix@irssi.org',      name        => 'inputlength',      description => 'adds a statusbar item which show length of the inputline', +    sbitems     => 'inputlength',      license     => 'BSD License or something more liberal',      url         => 'http://www.irssi.de./',      changed     => '2003-01-13T13:17:44Z' diff --git a/scripts/invitejoin.pl b/scripts/invitejoin.pl index c69ed01..d3b5871 100644 --- a/scripts/invitejoin.pl +++ b/scripts/invitejoin.pl @@ -24,7 +24,7 @@ use strict;  use Irssi;  use vars qw($VERSION %IRSSI); -$VERSION = "0.01"; +$VERSION = '0.02';  %IRSSI = (      authors     => 'Geert Hauwaerts', @@ -32,37 +32,254 @@ $VERSION = "0.01";      name        => 'invitejoin.pl',      description => 'This script will join a channel if somebody invites you to it.',      license     => 'Public Domain', -    url         => 'http://irssi.hauwaerts.be/invitejoin.pl', -    changed     => 'Sun Apr 11 12:38:18 2004', +    url         => 'https://github.com/irssi/scripts.irssi.org/blob/master/scripts/invitejoin.pl', +    changed     => 'Di 17. Jan 19:32:45 CET 2017',  ); -## Comments and remarks. -# -# This script uses settings. -# Use /SET to change the value or /TOGGLE to switch it on or off. -# -#    Setting:     invitejoin -#    Description: If this setting is turned on, you will join the channel -#                 when invite to. -# -## +my $help = <<EOF; + +/SET    invitejoin 0|1 +/TOGGLE invitejoin +          Description: If this setting is turned on, you will join the channel +          when invited to. + +Default is to follow every invite, you can specify a list of allowed nicks. + +/INVITEJOIN [addnick <ircnet> <nick>] +            [delnick <ircnet> <nick>] +            [listnick] +            [help] + +addnick:     Add a new nickname on the given net as allowed autoinvite source. +delnick:     Delete a nickname from the allowed list. +listnick:    Display the contents of the allowed nickname list. +help:        Display this useful little helptext. + +Examples: (all on one line) +/INVITEJOIN addnick Freenode ChanServ + +Note: This script doesn't allow wildcards +EOF +my @allowed_nicks = (); +my $allowed_nicks_file = "invitejoin.nicks"; + +my $irssidir = Irssi::get_irssi_dir();  Irssi::theme_register([ +    'invitejoin_usage', '%R>>%n %_Invitejoin:%_ Insufficient parameters: Use "%_/INVITEJOIN help%_" for further instructions.', +    'invitejoin_help', '$0',      'invitejoin_loaded', '%R>>%n %_Scriptinfo:%_ Loaded $0 version $1 by $2.', -    'invitejoin_invited', '%R>>%n %_Invitejoin:%_ Joined $1 (Invited by $0).' +    'invitejoin_invited', '%R>>%n %_Invitejoin:%_ Joined $1 (Invited by $0).', +    'invitejoin_usage_add_nick', '%R>>%n %_Invitejoin:%_ Insufficient parameters: Usage "%_/INVITEJOIN addnick ircnet ChanServ%_".', +    'invitejoin_no_net', '%R>>%n %_Invitejoin:%_ Unknown Irssi ircnet %_$0%_.', +    'saved_nick', '%R>>%n %_Invitejoin:%_ Added allowed nick "%_$1%_" on %_$0%_.', +    'nick_already_present', '%R>>%n %_Invitejoin:%_ Nick already present.', +    'invitejoin_delusage', '%R>>%n %_Invitejoin:%_ Insufficient parameters: Usage "%_/INVITEJOIN delnick ircnet nick%_".', +    'invitejoin_delled', '%R>>%n %_Invitejoin:%_ Deleted %_$1%_ on %_$0%_ from allowed list.', +    'invitejoin_nfound', '%R>>%n %_Invitejoin:%_ The nick %_$1%_ on %_$0%_ could not be found.', +    'allowed_nicks_info', '%_Ircnet             Nick%_', +    'allowed_nicks_empty', '%R>>%n %_Invitejoin:%_ Your allowed nick list is empty. All invites will be followed.', +    'allowed_nicks_print', '$[18]0 $1', +    'invite_denied', '%R>>%n %_Invitejoin:%_ Invite from nick %_$1%_ on %_$0%_ to %_$2%_ not followed because it is not in the allowed list.',  ]); +sub load_allowed_nicks { +    my ($file) = @_; + +    @allowed_nicks = load_file($file, sub { +        my $new_allowed = new_allowed_nick(@_); + +        return undef if ($new_allowed->{net} eq '' || $new_allowed->{nick} eq ''); +        return $new_allowed; +    }); +} + +sub save_allowed_nicks { +    my ($file) = @_; +    save_file($file, \@allowed_nicks, \&allowed_nick_to_list); +} + +sub allowed_nick_to_list { +    my $allowed_nick = shift; + +    return ( +        $allowed_nick->{net}, +        $allowed_nick->{nick} +    ); +} + +sub new_allowed_nick { +    return { +        net   => shift, +        nick  => shift +    }; +} + +# file: filename to be read +# parse_line_fn: receives array of entries of a single line as input, should +#     return parsed data object or undef in the data is incomplete +# returns: parsed data array +sub load_file { +    my ($file, $parse_line_fn) = @_; +    my @parsed_data = (); + +    if (-e $file) { +        open(my $fh, "<", $file); +        local $/ = "\n"; + +        while (<$fh>) { +            chomp; +            my $data = $parse_line_fn->(split("\t")); +            push(@parsed_data, $data) if $data; +        } + +        close($fh); +    } + +    return @parsed_data; +} + +# file: filename to be written, is created accessable only by the user +# data_ref: array ref of data entries +# serialize_fn: receives a data reference and should return an array or tuples +#     for that data that will be serialized into one line +sub save_file { +    my ($file, $data_ref, $serialize_fn) = @_; + +    create_private_file($file) unless -e $file; + +    open(my $fh, ">", $file) or die "Can't create $file. Reason: $!"; + +    for my $data (@$data_ref) { +        print($fh join("\t", $serialize_fn->($data)), "\n"); +    } + +    close($fh); +} + +sub create_private_file { +    my ($file) = @_; +    my $umask = umask 0077; # save old umask +    open(my $fh, ">", $file) or die "Can't create $file. Reason: $!"; +    close($fh); +    umask $umask; +} + +sub add_allowed_nick { +    my ($network, $nick) = split(" ", $_[0], 2); +    my ($correct_net); + +    if ($network eq '' || $nick eq '') { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_usage_add_nick'); +        return; +    } + +    if ($network) { +        my ($ircnet) = Irssi::chatnet_find($network); +        if (!$ircnet) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_no_net', $network); +            return; +        } else { +            $correct_net = 1; +        } +    } + +    if ($correct_net && $nick) { +        if (is_nick_in_list($network, $nick)) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nick_already_present'); +            return; +        } + +        push(@allowed_nicks, new_allowed_nick($network, $nick)); +        save_allowed_nicks("$irssidir/$allowed_nicks_file"); + +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_nick', $network, $nick); +    } +} + +sub del_allowed_nick { +    my ($ircnet, $nick) = split(" ", $_[0], 2); + +    if ($ircnet eq '' || $nick eq '') { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_delusage'); +        return; +    } + +    my $size_before = scalar(@allowed_nicks); +    @allowed_nicks = grep { ! ($_->{net} eq $ircnet && $_->{nick} eq $nick) } @allowed_nicks; +    my $size_after = scalar(@allowed_nicks); + +    if ($size_after != $size_before) { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_delled', $ircnet, $nick); +        save_allowed_nicks("$irssidir/$allowed_nicks_file"); +    } else { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_nfound', $ircnet, $nick); +    } + +    if ($size_after == 0) { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'allowed_nicks_empty'); +    } +} + +sub list_allowed_nicks { +    if (@allowed_nicks == 0) { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'allowed_nicks_empty'); +    } else { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'allowed_nicks_info'); + +        for my $allowed (@allowed_nicks) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'allowed_nicks_print', $allowed->{net}, $allowed->{nick}); +        } +    } +} + +sub invitejoin_runsub { +    my ($data, $server, $item) = @_; +    $data =~ s/\s+$//g; + +    if ($data) { +        Irssi::command_runsub('invitejoin', $data, $server, $item); +    } else { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_usage'); +    } +} + +sub is_nick_in_list { +    my ($net, $nick) = @_; + +    return (grep { +        $_->{net}  eq $net && +        $_->{nick} eq $nick +    } @allowed_nicks) > 0; +} + +sub is_allowed_nick { +    my ($net, $nick) = @_; + +    # If no allowed nicks are specified (initial configuration) accept +    # all invite requests. +    # # (This mimics previous behavior of this script +    # before there was an allowed list) +    return 1 if @allowed_nicks == 0; + +    return is_nick_in_list($net, $nick); +} +  sub invitejoin { -          my ($server, $channel, $nick, $address) = @_;      my $invitejoin = Irssi::settings_get_bool('invitejoin');      if ($invitejoin) { -        $server->command("join $channel"); -         -        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_invited', $nick, $channel); -        Irssi::signal_stop(); +        if (is_allowed_nick($server->{tag}, $nick)) { +            $server->command("join $channel"); + +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_invited', $nick, $channel); +            Irssi::signal_stop(); +        } +        else { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invite_denied', $server->{tag}, $nick, $channel); +        }      }  } @@ -70,4 +287,12 @@ Irssi::signal_add('message invite', 'invitejoin');  Irssi::settings_add_bool('invitejoin', 'invitejoin' => 1); +load_allowed_nicks("$irssidir/$allowed_nicks_file"); + +Irssi::command_bind('invitejoin',           'invitejoin_runsub'); +Irssi::command_bind('invitejoin addnick',   'add_allowed_nick'); +Irssi::command_bind('invitejoin delnick',   'del_allowed_nick'); +Irssi::command_bind('invitejoin listnick',  'list_allowed_nicks'); +Irssi::command_bind('invitejoin help' => sub { Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_help', $help) }); +  Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'invitejoin_loaded', $IRSSI{name}, $VERSION, $IRSSI{authors}); diff --git a/scripts/iquiz.pl b/scripts/iquiz.pl index 336f569..77e6273 100644 --- a/scripts/iquiz.pl +++ b/scripts/iquiz.pl @@ -1,5 +1,5 @@  ################################################################## -##    irssi Quiz (iQuiz) script (2010-2016) by wilk/xorandor    ## +##    irssi Quiz (iQuiz) script (2010-2017) by wilk/xorandor    ##  ##################################################################  ## Script inspired by classic mIRC scripts: "Dizzy" by Dizzy,   ##  ##   "Mieszacz" & "Familiada" by snajperx (both with my later   ## @@ -12,7 +12,7 @@  # Script works with:  # -# - standard Dizzy/Pomieszany files (also without "pyt"/"odp" prefixes): +# - standard "Dizzy"/"Pomieszany" files (also without "pyt"/"odp" prefixes):  #  # pyt Evaluate: 2+2=?  # odp four @@ -20,7 +20,7 @@  # odp Sun  # ...  # -# - standard Mieszacz files (also without line numbers): +# - standard "Mieszacz" files (also without line numbers):  #  # 1 alpha  # 2 beta @@ -28,7 +28,7 @@  # 4 delta  # ...  # -# - standard Familiada files (can have any number of answers per question, used also for Multi): +# - standard "Familiada" files (can have any number of answers per question, not only 10; used also for "Multi"):  #  # Planets of our Solar System:  # Mercury*Venus*Earth*Mars*Jupiter*Saturn*Uranus*Neptune @@ -36,16 +36,15 @@  # methane*ethane*propane*butane*pentane*hexane  # ... -# >>> To view all available commands and settings type: /quiz +# >>> To review all available commands and settings type: /quiz OR /help quiz  # only core modules  use strict;  use warnings;  use Irssi qw(theme_register current_theme command_bind settings_add_int settings_add_bool settings_add_str settings_get_int settings_get_bool settings_get_str settings_set_int settings_set_bool settings_set_str printformat timeout_add_once timeout_remove signal_add_last signal_remove signal_stop signal_emit active_win);  use Time::HiRes qw(time); -use constant { QT_STD => 1, QT_MIX => 2, QT_FAM => 3, QT_MUL => 4, QT_SCR => 5 }; # QT_MIL => 6, QT_FOR => 7 -our $VERSION = '160919'; +our $VERSION = '170202';  our %IRSSI = (  	authors			=> 'wilk',  	name			=> 'iQuiz', @@ -72,41 +71,54 @@ my $_protect_urls = 1;				# bool; turn off antigoogler if URL is detected in que  my $_round_warn_time = 15;			# sec; seconds before round end to show warning (0 = off)  my $_round_warn_coeff = 1.5;		# float; round duration must be longer than coeff * $_round_warn_time to show warning (protection)  my $_qstats_ranks = 0;				# bool; 0: /qstats param corresponds to number of players, 1: /qstats param corresponds to rank -my $_qstats_records = 5;			# int; number of time/speed record places in /qstats +my $_qstats_records = 5;			# int; number of time/speed record places in /qstats (0 - off) +my $_no_hints_spam = 1;				# bool; do not show fully revealed answer as a hint (except the first)? + +my $_flex_separator = '/';			# char; separator used in quiz_flx_* formats +my $_team_separator = ', ';			# str; team players separator eq. "nick1, nick2, nick3"  my $_next_delay = 10;				# sec; default delay between questions  my $_next_delay_long = 20;			# sec; default delay between questions (fam/mul) (longer delay to prevent flooding and give a breath)  my $_round_duration = 90;			# sec; default round duration +my $_hints_interval = 10;			# sec; default hints interval  my $_hint_alpha = '.';				# char; default substitution symbol for alphabet characters in hints (special characters are left intact)  my $_hint_digit = '.';				# char; default substitution symbol for digit characters in hints (special characters are left intact)  my $_quiz_types = 5;				# (do not change)  ##### Internal stuff ##### +use constant { QT_STD => 1, QT_MIX => 2, QT_FAM => 3, QT_MUL => 4, QT_SCR => 5 }; # QT_MIL => 6, QT_FOR => 7  use constant { T_HMS => 0, T_S => 1, T_MS => 2 }; # 0: h/m/s, 1: s only, 2: s.ms  use constant { INSTANT => 1, PREPDOTS => 1, V_INT => 1, V_BOOL => 2, V_STR => 3 };  my %quiz = (  	chan => undef, file => '',  	type => 0, tcnt => 0, # copies just in case someone modifies settings directly while quiz is running -	ison => 0, inq => 0, standby => 0, +	ison => 0,		# /qon ... /qoff (or error while /qreload) +	inq => 0,		# in question +	standby => 0,	# /qon QT_FAM ... /qon (/qoff or error in /qreload) +	ended => 0,		# after last question till /qoff (or error in /qreload)  	stime => 0, qtime => 0,  	qcnt => 0, qnum => 0, hnum => 0,  	score => 0, answers => 0, -	tnext => undef, tround => undef, thint => undef, tremind => undef, twarn => undef, +	tnext => undef, tround => undef, thint => undef, thinter => undef, tremind => undef, twarn => undef,  	hprot => 0, rprot => 0,  	data => [],		# data[]{question realquestion answer answers{}}  	teams => [],	# teams[]{score answers} -	players => {},	# players{}{nick timestamp score answers team besttime alltime bestspeed allspeed} -	lookup => {}, dcnt => 0, dmax => 0, lmax => 0, dots => [], hwords => [] +	players => {},	# players{}{nick timestamp score answers team joined besttime alltime bestspeed allspeed} +	lookup => {}, +	dcnt => 0,		# total number of currently unrevealed letters +	dmax => 0,		# number of currently unrevealed letters in the "most hidden" word +	dots => [], hwords => []  );  my %settings_int = ( -	'quiz_type' => 1, +	'quiz_type' => QT_STD,  	'quiz_teams' => 2,  	'quiz_delay' => $_next_delay,  	'quiz_delay_long' => $_next_delay_long, -	'quiz_round_duration' => $_round_duration, +	'quiz_timeout' => $_round_duration, +	'quiz_hints_interval' => $_hints_interval,  	'quiz_max_hints' => 0,  	'quiz_words_style' => 0,  	'quiz_anticheat_delay' => 3, @@ -120,6 +132,7 @@ my %settings_int = (  my %settings_bool = (  	'quiz_antigoogler' => 1, +	'quiz_autohinter' => 0,  	'quiz_split_long_lines' => 1,  	'quiz_show_first_hint' => 0,  	'quiz_first_hint_dots' => 0, @@ -134,6 +147,7 @@ my %settings_bool = (  	'quiz_transfer_points' => 0,  	'quiz_limiter' => 0,  	'quiz_keep_scores' => 0, +	'quiz_keep_teams' => 1,  	'quiz_cmd_hint' => 1,  	'quiz_cmd_remind' => 1,  ); @@ -201,7 +215,7 @@ theme_register([  	'quiz_msg_score_other',			"\00304%s\00303 zdobyl(a) jak dotad \00304%d\00303 %s.", # see quiz_msg_score  	'quiz_msg_noscore_other',		"\00304%s\00303 nie zdobyl(a) jeszcze zadnego punktu!", # 1: nick  	'quiz_msg_noscores',			"\00303Tablica wynikow jest jeszcze pusta.", -	'quiz_msg_scores',				"\00303Wyniki quizu po %s i %u %s:", # 1: time_str (hms), 2: question, 3: quiz_flx_questions, 4: questions (total), 5: quiz_flx_questions (total) +	'quiz_msg_scores',				"\00303Wyniki quizu po %s i %u %s:", # 1: time_str (hms), 2: question, 3: quiz_flx_aquestions, 4: questions (total), 5: quiz_flx_fquestions (total)  	'quiz_msg_scores_place',		"\00303%u. miejsce: \00304%s\00303 - \00304%d\00303 %s [%.1f%%] (sr. czas zgadywania: %10\$.3f sek.)", # 1: place, 2: nick, 3: score, 4: quiz_flx_points, 5: score%, 6: answers, 7: quiz_flx_answers, 8: answers%, 9: best time, 10: avg time, 11: best speed, 12: avg speed, 13: spacer  	'quiz_msg_scores_place_full',	"\00303%u. miejsce: \00304%s\00303 - \00304%d\00303 %s [%.1f%%] (%u %s, sr. czas zgadywania: %10\$.3f sek.)", # see quiz_msg_scores_place  	'quiz_msg_team_score',			"\00303Druzyna %u (%s): \00304%d\00303 %s", # 1: team, 2: players (comma separated), 3: score, 4: quiz_flx_points, 5: score%, 6: answers, 7: quiz_flx_answers, 8: answers% @@ -214,6 +228,7 @@ theme_register([  	'quiz_msg_congrats',			"\00303Brawo, \00304%s\00303! Dostajesz %s za odpowiedz \00304%s\00303 podana po czasie %.3f sek. (%.3f zn/s) - suma punktow: \00304%d\00303.", # 1: nick, 2: quiz_inc_got_point*, 3: answer, 4: time (ms), 5: speed (chars/s), 6: total score  	'quiz_inc_got_points',			"\00304%d\00303 %s", # 1: points, 2: quiz_flx_points  	'quiz_inc_got_point',			"\00303%s", # 1: quiz_flx_point +	'quiz_msg_limit',				"\00307Masz juz 50%%+1 punktow - daj pograc innym. ;)",  	'quiz_inc_hours',				'%u godz.',		# 1: hours  	'quiz_inc_minutes',				'%u min.',		# 1: minutes  	'quiz_inc_seconds',				'%u sek.',		# 1: seconds @@ -225,21 +240,13 @@ theme_register([  	'quiz_msg_next_x',				"\00303Nastepne haslo za %u sek...", # 1: time (s)  	'quiz_msg_last',				"\00307Koniec pytan!",  	'quiz_msg_skipped',				"\00303Pytanie zostalo pominiete.", -	# 1 point								/ 1 punkt -	# x points								/ x punktow -	# 2-4, x2-x4 points (x != 1)			/ 2-4, x2-x4 punkty (x != 1) +	# 1 point / x points / 2-4, x2-x4 points (x != 1)	|	1 punkt / x punktow / 2-4, x2-x4 punkty (x != 1)  	'quiz_flx_points',				'punkt/punktow/punkty', -	# 1 answer								/ 1 odpowiedz -	# x answers								/ x odpowiedzi -	# 2-4, x2-x4 answers (x != 1)			/ 2-4, x2-x4 odpowiedzi (x != 1) +	# 1 answer / x answers / 2-4, x2-x4 answers (x != 1)	|	1 odpowiedz / x odpowiedzi / 2-4, x2-x4 odpowiedzi (x != 1)  	'quiz_flx_answers',				'odpowiedz/odpowiedzi/odpowiedzi', -	# after 1 question						/ po 1 pytaniu -	# after x questions						/ po x pytaniach -	# after 2-4, x2-x4 questions (x != 1)	/ po 2-4, x2-x4 pytaniach (x != 1) +	# (after) 1 question / x questions / 2-4, x2-x4 questions (x != 1)	|	(po) 1 pytaniu / x pytaniach / 2-4, x2-x4 pytaniach (x != 1)  	'quiz_flx_aquestions',			'pytaniu/pytaniach/pytaniach', -	# from 1 question						/ z 1 pytania -	# from x questions						/ z x pytan -	# from 2-4, x2-x4 questions (x != 1)	/ z 2-4, x2-x4 pytan (x != 1) +	# (from) 1 question / x questions / 2-4, x2-x4 questions (x != 1)	|	(z) 1 pytania / x pytan / 2-4, x2-x4 pytan (x != 1)  	'quiz_flx_fquestions',			'pytania/pytan/pytan',  ]); @@ -308,7 +315,7 @@ sub send_irc {  		}  		timeout_add_once($_display_delay, 'evt_delayed_show_msg', $msg); # le trick (workaround for chantext showing after owntext)  	} else { -		send_ui_raw($msg); # this helps when we got disconnected not to lose messages like stats +		send_ui_raw($msg); # this helps when we got disconnected not to lose any messages (like stats)  		send_ui('quiz_err_server');  	}  } @@ -324,7 +331,7 @@ sub send_irc_whisper {  		}  		timeout_add_once($_display_delay, 'evt_delayed_show_notc', [$msg, $nick]); # le trick (workaround for chantext showing after owntext)  	} else { -		send_ui_raw($msg); # this helps when we got disconnected not to lose messages like stats +		send_ui_raw($msg); # this helps when we got disconnected not to lose any messages (like stats)  		send_ui('quiz_err_server');  	}  } @@ -421,7 +428,7 @@ sub antigoogle {  		if (!$quiz{inq}) {  			my $suffix = ($quiz{type} == QT_MIX) ? '_x' : ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? '_fm' : '');  			my $answers = keys %{$quiz{lookup}}; -			my $duration = abs(settings_get_int('quiz_round_duration')) || $_round_duration; # abs in case of <0, || in case of ==0 +			my $duration = abs(settings_get_int('quiz_timeout')) || $_round_duration; # abs in case of <0, || in case of ==0  			$msg_crap += length(get_format('quiz_msg_question' . $suffix, [$quiz{qnum}, $quiz{qcnt}, '', $answers, answers_str($answers), $duration]));  		} else {  			$msg_crap += length(get_format('quiz_msg_remind', '')); @@ -483,10 +490,10 @@ sub make_hint {  	my $dots_only = shift;  	my @words = split(/ /, $quiz{data}[$quiz{qnum}]{answer});  	if (!@{$quiz{dots}}) { # make first dots -		@quiz{qw/dcnt dmax lmax/} = (0) x 3; +		@quiz{qw/dcnt dmax/} = (0) x 2; +		$quiz{hwords} = [];  		my ($w, $dmax) = (0) x 2;  		foreach my $word (@words) { -			$quiz{lmax} = length($word) if (length($word) > $quiz{lmax});  			my ($l, $hword, $dcnt) = (0, '', 0);  			foreach my $letter (split(//, $word)) {  				if ($letter =~ /^[a-z0-9]$/i) { @@ -562,12 +569,12 @@ sub time_str {  sub flex {  	my ($value, $format, $flex) = (abs(shift), shift, 0); -	my @flex = split(/\//, get_format($format)); +	my @flex = split(/$_flex_separator/, get_format($format));  	if ($value != 1) {  		$flex++;  		$flex++ if ($value =~ /^[2-4]$|[^1][2-4]$/);  	} -	return defined($flex[$flex]) ? $flex[$flex] : '???'; # just a precaution +	return defined($flex[$flex]) ? $flex[$flex] : '???'; # just a precaution when user messes up  }  sub score_str		{ return flex(shift, 'quiz_flx_points'); }		# X points @@ -589,8 +596,8 @@ sub stop_timer {  }  sub stop_question { -	@quiz{qw/inq hnum hprot rprot dcnt dmax lmax/} = (0) x 7; -	stop_timer($_) foreach (qw/tround thint tremind twarn/); +	@quiz{qw/inq hnum hprot rprot dcnt dmax/} = (0) x 6; +	stop_timer($_) foreach (qw/tround thint thinter tremind twarn/);  	$quiz{dots} = [];  	$quiz{hwords} = [];  	$quiz{lookup} = {}; @@ -598,7 +605,7 @@ sub stop_question {  sub stop_quiz {  	stop_question(); -	@quiz{qw/ison standby/} = (0) x 2; +	@quiz{qw/ison standby ended/} = (0) x 3;  	stop_timer('tnext');  	signal_remove('message public', 'sig_pubmsg');  } @@ -616,9 +623,14 @@ sub init_next_question {  	my ($msg, $instant) = @_;  	if ($quiz{qnum} >= $quiz{qcnt}) {  		send_irc('quiz_msg', $msg . ' ' . get_format('quiz_msg_last'), $instant); +		$quiz{ended} = 1;  	} else { -		my $delay = abs(settings_get_int('quiz_delay' . ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? '_long' : ''))); # abs in case of <0 -		$delay ||= ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? $_next_delay_long : $_next_delay); # in case of ==0 +		my $delay; +		if (($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) { +			$delay = abs(settings_get_int('quiz_delay_long')) || $_next_delay_long; # abs in case of <0, || in case of ==0 +		} else { +			$delay = abs(settings_get_int('quiz_delay')) || $_next_delay; # abs in case of <0, || in case of ==0 +		}  		send_irc('quiz_msg', $msg . ' ' . get_format('quiz_msg_next' . (($quiz{type} == QT_MIX) ? '_x' : ''), $delay), $instant);  		$quiz{tnext} = timeout_add_once($delay * 1000, 'evt_next_question', undef);  	} @@ -682,53 +694,74 @@ sub hvar {  }  sub show_help { -	send_ui_raw("%_$IRSSI{name}%_ v$VERSION by wilk (quiz obecnie: " . ($quiz{ison} ? ($quiz{standby} ? 'oczekuje na uruchomienie' : 'trwa') : 'jest wylaczony') . ')'); +	my $type = settings_get_int('quiz_type'); +	send_ui_raw("%_$IRSSI{name}%_ v$VERSION by wilk (quiz obecnie: " . ($quiz{ison} ? ($quiz{standby} ? 'oczekuje na uruchomienie' : ($quiz{ended} ? 'dobiegl konca' : 'trwa')) : 'jest wylaczony') . ')');  	send_ui_raw('%_Dostepne polecenia:%_');  	send_ui_raw(hcmd("/qtype [1-$_quiz_types/nazwa]") . 'zmiana rodzaju quizu (bez parametru wybiera kolejny)'); -	send_ui_raw(hcmd("/qteams <2-$_max_teams>") . 'zmiana liczby druzyn (tylko Familiada)'); -	send_ui_raw(hcmd("/qon [kanal] <plik> [1-$_quiz_types/nazwa] [0-$_max_teams]") . 'rozpoczecie quizu; mozna podac rodzaj quizu i liczbe druzyn'); -	send_ui_raw(hcmd('/qstats [miejsca]') . 'wyswietla ranking graczy (Familiada: 0 - pokazuje tylko druzyny)'); -	send_ui_raw(hcmd('/qhint') . 'wyswietlenie podpowiedzi (nie w Familiadzie/Multi)'); +	if ($type == QT_FAM) { +		send_ui_raw(hcmd("/qteams <2-$_max_teams>") . 'zmiana liczby druzyn'); +		send_ui_raw(hcmd("/qon [kanal] <plik> [1-$_quiz_types/nazwa] [0-$_max_teams]") . 'rozpoczecie quizu; mozna podac rodzaj quizu i liczbe druzyn'); +		send_ui_raw(hcmd('/qstats [miejsca]') . 'wyswietla ranking graczy (0: pokazuje tylko druzyny)'); +	} else { +		send_ui_raw(hcmd("/qon [kanal] <plik> [1-$_quiz_types/nazwa]") . 'rozpoczecie quizu; mozna podac rodzaj quizu'); +		send_ui_raw(hcmd('/qstats [miejsca]') . 'wyswietla ranking graczy'); +	} +	send_ui_raw(hcmd('/qhint') . 'wyswietlenie podpowiedzi') if (($type != QT_FAM) && ($type != QT_MUL));  	send_ui_raw(hcmd('/qremind') . 'przypomnienie pytania');  	send_ui_raw(hcmd('/qskip') . 'pominiecie biezacego pytania');  	send_ui_raw(hcmd('/qoff') . 'przerwanie lub zakonczenie quizu');  	send_ui_raw(hcmd('/qdelay <sekundy>') . 'zmiana opoznienia miedzy pytaniami'); -	send_ui_raw(hcmd('/qtime <sekundy>') . 'zmiana czasu trwania rundy (tylko Familiada/Multi)'); +	send_ui_raw(hcmd('/qtime <sekundy>') . 'zmiana czasu trwania rundy') if (($type == QT_FAM) || ($type == QT_MUL));  	send_ui_raw(hcmd('/qreload') . 'ponowne wczytanie pliku z pytaniami');  	send_ui_raw(hcmd('/qinit') . 'resetuje wszystkie ustawienia do wartosci poczatkowych');  	send_ui_raw('%_Dostepne ustawienia (/set):%_');  	send_ui_raw(hvar('quiz_type', V_INT) . 'rodzaj quizu (1: Dizzy, 2: Mieszacz/Literaki, 3: Familiada, 4: Multi (Familiada bez druzyn), 5: Pomieszany)'); -	send_ui_raw(hvar('quiz_teams', V_INT) . "liczba druzyn (2-$_max_teams; tylko Familiada)"); +	send_ui_raw(hvar('quiz_teams', V_INT) . "liczba druzyn (2-$_max_teams)") if ($type == QT_FAM);  	send_ui_raw(hvar('quiz_delay', V_INT) . 'opoznienie miedzy pytaniami (sek.)'); -	send_ui_raw(hvar('quiz_delay_long', V_INT) . 'opoznienie miedzy pytaniami (sek.; tylko Familiada/Multi)'); -	send_ui_raw(hvar('quiz_round_duration', V_INT) . 'czas trwania rundy (sek.; tylko Familiada/Multi)'); -	send_ui_raw(hvar('quiz_max_hints', V_INT) . 'maksymalna liczba podpowiedzi (0: bez ograniczen, >0: limit podpowiedzi, <0: limit ukrytych znakow; nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_words_style', V_INT) . 'styl wyrazow (0: bez zmian, 1: male, 2: DUZE, 3: Kapitaliki; tylko Mieszacz/Pomieszany)'); +	if (($type == QT_FAM) || ($type == QT_MUL)) { +		send_ui_raw(hvar('quiz_delay_long', V_INT) . 'opoznienie miedzy pytaniami (sek.)'); +		send_ui_raw(hvar('quiz_timeout', V_INT) . 'czas trwania rundy (sek.)'); +	} else { +		send_ui_raw(hvar('quiz_max_hints', V_INT) . 'limit podpowiedzi (0: bez ogr., >0: limit podp., <0: limit ukrytych znakow)'); +		send_ui_raw(hvar('quiz_autohinter', V_BOOL) . 'automatyczne podpowiedzi co X sek. od poprzedniej?'); +		send_ui_raw(hvar('quiz_hints_interval', V_INT) . 'opoznienie pomiedzy auto-podpowiedziami (sek.)'); +	} +	send_ui_raw(hvar('quiz_words_style', V_INT) . 'styl wyrazow (0: bez zmian, 1: male, 2: DUZE, 3: Kapitaliki)') if (($type == QT_MIX) || ($type == QT_SCR)); +	send_ui_raw(hvar('quiz_antigoogler', V_BOOL) . 'uzywac antygooglera do maskowania pytan?'); +	send_ui_raw(hvar('quiz_split_long_lines', V_BOOL) . 'dzielic dlugie linie na czesci (nowsze irssi potrafi samo)?');  	send_ui_raw(hvar('quiz_anticheat_delay', V_INT) . 'czas trwania ochrony !podp/!przyp (sek.; 0: wylaczone)');  	send_ui_raw(hvar('quiz_first_anticheat_delay', V_INT) . 'czas trwania ochrony pierwszego !podp/!przyp (sek.; 0: wylaczone)'); +	if (($type != QT_FAM) && ($type != QT_MUL)) { +		send_ui_raw(hvar('quiz_show_first_hint', V_BOOL) . 'pokazywac podpowiedz razem z pytaniem?'); +		send_ui_raw(hvar('quiz_first_hint_dots', V_BOOL) . 'pierwsza podpowiedz jako same kropki?'); +		send_ui_raw(hvar('quiz_random_hints', V_BOOL) . 'losowe odslanianie podpowiedzi? albo od lewej do prawej'); +		send_ui_raw(hvar('quiz_nonrandom_first_hint', V_BOOL) . 'losowe odslanianie podpowiedzi, poza pierwsza?'); +		send_ui_raw(hvar('quiz_hint_alpha', V_STR) . 'znak podstawiany w podpowiedziach za litery'); +		send_ui_raw(hvar('quiz_hint_digit', V_STR) . 'znak podstawiany w podpowiedziach za cyfry'); +	} +	send_ui_raw(hvar('quiz_words_mode', V_BOOL) . 'mieszac slowa osobno? albo wszystko razem') if ($type == QT_MIX); +	if ($type == QT_SCR) { +		send_ui_raw(hvar('quiz_smart_mix', V_BOOL) . 'mieszac kotwiczac cyfry i niektore znaki interpunkcyjne?'); +		send_ui_raw(hvar('quiz_smart_mix_chars', V_STR) . 'te znaki beda zakotwiczone (regex)'); +	} +	send_ui_raw(hvar('quiz_mix_on_remind', V_BOOL) . 'mieszac litery przy kazdym !przyp?') if (($type == QT_MIX) || ($type == QT_SCR)); +	if ($type == QT_FAM) { +		send_ui_raw(hvar('quiz_join_anytime', V_BOOL) . 'wchodzenie do druzyn w dowolnej chwili?'); +		send_ui_raw(hvar('quiz_team_play', V_BOOL) . 'graja tylko gracze z druzyn?'); +		send_ui_raw(hvar('quiz_transfer_points', V_BOOL) . 'wraz ze zmiana druzyny przenosic punkty?'); +	} +	send_ui_raw(hvar('quiz_strict_match', V_BOOL) . 'tylko doslowne odpowiedzi? albo *dopasowane*') if (($type != QT_FAM) && ($type != QT_MUL));  	send_ui_raw(hvar('quiz_points_per_answer', V_INT) . 'punkty za poprawna odpowiedz'); -	send_ui_raw(hvar('quiz_min_points', V_INT) . 'minimum punktowe (tylko Familiada/Multi)'); -	send_ui_raw(hvar('quiz_max_points', V_INT) . 'maksimum punktowe (tylko Familiada/Multi)'); -	send_ui_raw(hvar('quiz_scoring_mode', V_INT) . 'tryb punktowania (1: ppa, 2: ppa++, 3: ppa++:max, 4: min++ppa, 5: min++ppa:max, 6: max--ppa:min, 7: max->min; tylko Familiada/Multi)'); +	if (($type == QT_FAM) || ($type == QT_MUL)) { +		send_ui_raw(hvar('quiz_min_points', V_INT) . 'minimum punktowe'); +		send_ui_raw(hvar('quiz_max_points', V_INT) . 'maksimum punktowe'); +		send_ui_raw(hvar('quiz_scoring_mode', V_INT) . 'tryb punktowania (1: ppa, 2: ppa++, 3: ppa++:max, 4: min++ppa, 5: min++ppa:max, 6: max--ppa:min, 7: max->min'); +	} else { +		send_ui_raw(hvar('quiz_limiter', V_BOOL) . 'limitowac najlepsza osobe do 50%+1 punktow?'); +	}  	send_ui_raw(hvar('quiz_ranking_type', V_INT) . 'rodzaj rankingu (1: zwykly "1234", 2: zwarty "1223", 3: turniejowy "1224")'); -	send_ui_raw(hvar('quiz_antigoogler', V_BOOL) . 'uzywac antygooglera do maskowania pytan?'); -	send_ui_raw(hvar('quiz_split_long_lines', V_BOOL) . 'dzielic dlugie linie na czesci (nowsze irssi potrafi samo)?'); -	send_ui_raw(hvar('quiz_show_first_hint', V_BOOL) . 'pokazywac podpowiedz razem z pytaniem? (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_first_hint_dots', V_BOOL) . 'pierwsza podpowiedz jako same kropki? (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_random_hints', V_BOOL) . 'losowe odslanianie podpowiedzi? albo od lewej do prawej (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_nonrandom_first_hint', V_BOOL) . 'losowe odslanianie podpowiedzi, poza pierwsza? (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_hint_alpha', V_STR) . 'znak podstawiany w podpowiedziach za litery (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_hint_digit', V_STR) . 'znak podstawiany w podpowiedziach za cyfry (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_words_mode', V_BOOL) . 'mieszac slowa osobno? albo wszystko razem (tylko Mieszacz)'); -	send_ui_raw(hvar('quiz_smart_mix', V_BOOL) . 'mieszac kotwiczac cyfry i niektore znaki interpunkcyjne? (tylko Pomieszany)'); -	send_ui_raw(hvar('quiz_smart_mix_chars', V_STR) . 'te znaki będą zakotwiczone (regex; tylko Pomieszany)'); -	send_ui_raw(hvar('quiz_mix_on_remind', V_BOOL) . 'mieszac litery przy kazdym !przyp? (tylko Mieszacz/Pomieszany)'); -	send_ui_raw(hvar('quiz_strict_match', V_BOOL) . 'tylko doslowne odpowiedzi? albo *dopasowane* (nie dla Familiady/Multi)'); -	send_ui_raw(hvar('quiz_join_anytime', V_BOOL) . 'wchodzenie do druzyn w dowolnej chwili? (tylko Familiada)' ); -	send_ui_raw(hvar('quiz_team_play', V_BOOL) . 'graja tylko gracze z druzyn? (tylko Familiada)'); -	send_ui_raw(hvar('quiz_transfer_points', V_BOOL) . 'wraz ze zmiana druzyny przenosic punkty? (tylko Familiada)'); -	send_ui_raw(hvar('quiz_limiter', V_BOOL) . 'limitowac najlepsza osobe do 50%+1 punktow? (nie dla Familiady/Multi)');  	send_ui_raw(hvar('quiz_keep_scores', V_BOOL) . 'sumowac punkty z poprzednich quizow?'); +	send_ui_raw(hvar('quiz_keep_teams', V_BOOL) . 'jesli zachowujemy punkty, to pozostawiac zawodnikow w druzynach miedzy quizami?') if ($type == QT_FAM);  	send_ui_raw(hvar('quiz_cmd_hint', V_BOOL) . 'polecenie !podp jest dostepne dla graczy?');  	send_ui_raw(hvar('quiz_cmd_remind', V_BOOL) . 'polecenie !przyp jest dostepne dla graczy?');  } @@ -777,11 +810,14 @@ sub cmd_start {  		$quiz{teams} = [];  		@quiz{qw/score answers/} = (0) x 2;  	} else { -		#delete $quiz{players}{$_}{team} for (keys %{$quiz{players}}); #? unsure... +		if (!settings_get_bool('quiz_keep_teams') && ($type == QT_FAM)) { +			delete $quiz{players}{$_}{team} for (keys %{$quiz{players}}); +		}  	}  	send_irc('quiz_msg_start1', INSTANT);  	send_irc('quiz_msg_start2' . (($type == QT_FAM) ? '_f' : (($type == QT_MUL) ? '_m' : '')), $teams, INSTANT); -	@quiz{qw/stime qnum ison/} = (time(), 0, 1); +	@quiz{qw/stime ison/} = (time(), 1); +	@quiz{qw/qnum inq ended/} = (0) x 3;  	if ($type == QT_FAM) {  		$quiz{standby} = 1;  		@{$quiz{teams}[$_]}{qw/score answers/} = (0) x 2 for (0 .. $teams); @@ -810,12 +846,12 @@ sub cmd_stats {  		((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) && (settings_get_int('quiz_scoring_mode') != 1)));  	if ($quiz{type} == QT_FAM) {  		my @teams; -		push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (keys %{$quiz{players}}); +		push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (sort { $quiz{players}{$a}{joined} <=> $quiz{players}{$b}{joined} } keys %{$quiz{players}});  		foreach my $team (1 .. $quiz{tcnt}) {  			my ($score, $answers) = @{$quiz{teams}[$team]}{qw/score answers/};  			send_irc('quiz_msg_team_score' . $suffix, [  				$team, -				(!defined $teams[$team]) ? '' : join(', ', @{$teams[$team]}), +				(!defined $teams[$team]) ? '' : join($_team_separator, @{$teams[$team]}),  				$score, score_str($score), percents($score, $quiz{score}),  				$answers, answers_str($answers), percents($answers, $quiz{answers})]);  		} @@ -862,8 +898,7 @@ sub cmd_stats {  						$quiz{players}{$a}{timestamp} <=> $quiz{players}{$b}{timestamp}  					} keys %{$quiz{players}}) {  		push(@nicks, get_format('quiz_inc_scores_record', [$place, $quiz{players}{$player}{nick}, $quiz{players}{$player}{besttime}])); -		last if ($place >= $_qstats_records); -		$place++; +		last if (++$place > $_qstats_records);  	}  	send_irc('quiz_msg_scores_times', join(', ', @nicks)) if (@nicks);  	$place = 1; @@ -873,8 +908,7 @@ sub cmd_stats {  						$quiz{players}{$a}{timestamp} <=> $quiz{players}{$b}{timestamp}  					} keys %{$quiz{players}}) {  		push(@nicks, get_format('quiz_inc_scores_record', [$place, $quiz{players}{$player}{nick}, $quiz{players}{$player}{bestspeed}])); -		last if ($place >= $_qstats_records); -		$place++; +		last if (++$place > $_qstats_records);  	}  	send_irc('quiz_msg_scores_speeds', join(', ', @nicks)) if (@nicks);  } @@ -892,7 +926,7 @@ sub cmd_time {  	my $duration = shift;  	#? send_ui('quiz_err_na'), return if (($quiz{type} != QT_FAM) && ($quiz{type} != QT_MUL));  	send_ui('quiz_err_duration'), return if (($duration !~ /^\d+$/) || ($duration < 1)); -	settings_set_int('quiz_round_duration', $duration); +	settings_set_int('quiz_timeout', $duration);  	send_irc('quiz_msg_duration', $duration) if ($quiz{ison});  	send_ui('quiz_inf_duration', $duration);  } @@ -1017,7 +1051,7 @@ sub evt_next_question {  		%{$quiz{lookup}} = map { lc($_) => $_ } keys %{$quiz{data}[$quiz{qnum}]{answers}};  		$suffix = '_fm';  	} -	my $duration = abs(settings_get_int('quiz_round_duration')) || $_round_duration; # abs in case of <0, || in case of ==0 +	my $duration = abs(settings_get_int('quiz_timeout')) || $_round_duration; # abs in case of <0, || in case of ==0  	my @lines = make_remind();  	my $line = 1;  	foreach my $text (@lines) { @@ -1039,17 +1073,21 @@ sub evt_next_question {  		}  	} else {  		send_irc('quiz_msg_hint', make_hint()) if (settings_get_bool('quiz_show_first_hint')); -	} -	$quiz{inq} = 1; -	my $delay = settings_get_int('quiz_first_anticheat_delay'); -	if ($delay > 0) { -		$quiz{hprot} = 1; -		$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef); -		if ((($quiz{type} == QT_MIX) || ($quiz{type} == QT_SCR)) && settings_get_bool('quiz_mix_on_remind')) { -			$quiz{rprot} = 1; -			$quiz{tremind} = timeout_add_once($delay * 1000, sub { $quiz{rprot} = 0 }, undef); +		my $delay = settings_get_int('quiz_first_anticheat_delay'); +		if ($delay > 0) { +			$quiz{hprot} = 1; +			$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef); +			if ((($quiz{type} == QT_MIX) || ($quiz{type} == QT_SCR)) && settings_get_bool('quiz_mix_on_remind')) { +				$quiz{rprot} = 1; +				$quiz{tremind} = timeout_add_once($delay * 1000, sub { $quiz{rprot} = 0 }, undef); +			} +		} +		if (settings_get_bool('quiz_autohinter')) { +			$delay = abs(settings_get_int('quiz_hints_interval')) || $_hints_interval; # abs in case of <0, || in case of ==0 +			$quiz{thinter} = timeout_add_once($delay * 1000, 'evt_show_hint', undef);  		}  	} +	$quiz{inq} = 1;  }  sub evt_round_timeout_warn { @@ -1061,6 +1099,10 @@ sub evt_round_timeout {  	init_next_question(get_format('quiz_msg_timeout')); #? INSTANT?  } +sub evt_show_hint { +	show_hint(); +} +  ##### User interaction - responses / handlers #####  sub show_score {  	my ($nick, $addr, $who) = @_; @@ -1086,7 +1128,8 @@ sub show_score {  sub join_team {  	my ($nick, $addr, $team) = @_;  	return unless (($quiz{type} == QT_FAM) && (settings_get_bool('quiz_join_anytime') || $quiz{standby})); -	return unless (($team >= 1) && ($team <= $quiz{tcnt})); +	return if (($team < 1) || ($team > $quiz{tcnt})); +	my $time = time();  	if (exists $quiz{players}{$addr}) {  		if (settings_get_bool('quiz_transfer_points')) {  			my ($score, $answers) = @{$quiz{players}{$addr}}{qw/score answers/}; @@ -1098,21 +1141,21 @@ sub join_team {  			$quiz{teams}[$team]{score} += $score;  			$quiz{teams}[$team]{answers} += $answers;  		} -		$quiz{players}{$addr}{team} = $team;  	} else { -		@{$quiz{players}{$addr}}{qw/nick timestamp team/} = ($nick, time(), $team); +		@{$quiz{players}{$addr}}{qw/nick timestamp/} = ($nick, $time);  		@{$quiz{players}{$addr}}{qw/score answers besttime alltime bestspeed allspeed/} = (0) x 6;  	} +	@{$quiz{players}{$addr}}{qw/team joined/} = ($team, $time);  	my @teams; -	push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (keys %{$quiz{players}}); -	send_irc_whisper('quiz_msg_team_join', [$team, join(', ', @{$teams[$team]})], $nick) if (defined $teams[$team]); +	push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (sort { $quiz{players}{$a}{joined} <=> $quiz{players}{$b}{joined} } keys %{$quiz{players}}); +	send_irc_whisper('quiz_msg_team_join', [$team, join($_team_separator, @{$teams[$team]})], $nick) if (defined $teams[$team]);  }  sub show_hint { -	return unless (($quiz{type} != QT_FAM) && ($quiz{type} != QT_MUL) && settings_get_bool('quiz_cmd_hint')); -	return if ($quiz{hprot}); +	return if ($quiz{hprot} || ($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL) || !settings_get_bool('quiz_cmd_hint'));  	my $hints_limit = settings_get_int('quiz_max_hints'); -	make_hint(PREPDOTS) if (!@{$quiz{dots}} && ($hints_limit < 0)); +	make_hint(PREPDOTS) if (($quiz{hnum} == 0) && ($hints_limit < 0)); +	return unless (($quiz{hnum} == 0) || !$_no_hints_spam || ($quiz{dcnt} > 0));  	if (($hints_limit == 0) ||  		(($hints_limit > 0) && ($quiz{hnum} < $hints_limit)) ||  		(($hints_limit < 0) && ($quiz{dmax} > abs($hints_limit)))) { @@ -1123,6 +1166,11 @@ sub show_hint {  				$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef);  			}  	} +	if (settings_get_bool('quiz_autohinter')) { +		stop_timer('thinter'); +		my $delay = abs(settings_get_int('quiz_hints_interval')) || $_hints_interval; # abs in case of <0, || in case of ==0 +		$quiz{thinter} = timeout_add_once($delay * 1000, 'evt_show_hint', undef); +	}  }  sub show_remind { @@ -1149,9 +1197,11 @@ sub show_remind {  sub check_answer {  	my ($nick, $addr, $answer) = @_;  	if (($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) { -		return unless (exists($quiz{lookup}{$answer}) && ($quiz{data}[$quiz{qnum}]{answers}{$quiz{lookup}{$answer}} > 0)); -		return unless (($quiz{type} == QT_MUL) || !settings_get_bool('quiz_team_play') || (exists($quiz{players}{$addr}) && exists($quiz{players}{$addr}{team}) && ($quiz{players}{$addr}{team} != 0))); # last condition: for non team players there is no record -		my ($time, $match) = (time(), $quiz{lookup}{$answer}); +		return unless (exists($quiz{lookup}{lc $answer}) && +						($quiz{data}[$quiz{qnum}]{answers}{$quiz{lookup}{lc $answer}} > 0)); +		return unless (($quiz{type} == QT_MUL) || !settings_get_bool('quiz_team_play') || +						(exists($quiz{players}{$addr}) && exists($quiz{players}{$addr}{team}) && ($quiz{players}{$addr}{team} != 0))); # last condition: for non team players there is no record yet // autovivification... +		my ($time, $match) = (time(), $quiz{lookup}{lc $answer});  		my $answers = keys %{$quiz{data}[$quiz{qnum}]{answers}};  		my $id = $quiz{data}[$quiz{qnum}]{answers}{$match};  		my $value = $answers - $id + 1; @@ -1192,11 +1242,12 @@ sub check_answer {  			init_next_question(get_format('quiz_msg_all_answers')); #? not INSTANT  		}  	} else { -		return unless (($answer eq lc($quiz{data}[$quiz{qnum}]{answer})) || -			(!settings_get_bool('quiz_strict_match') && (index($answer, lc $quiz{data}[$quiz{qnum}]{answer}) >= 0))); +		return unless ((lc($answer) eq lc($quiz{data}[$quiz{qnum}]{answer})) || +			(!settings_get_bool('quiz_strict_match') && (index(lc $answer, lc $quiz{data}[$quiz{qnum}]{answer}) >= 0)));  		my ($time, $points) = (time(), settings_get_int('quiz_points_per_answer')); -		return unless (!settings_get_bool('quiz_limiter') || !exists($quiz{players}{$addr}) || -			($quiz{players}{$addr}{score} < int($quiz{qcnt} * 0.5 + 1) * $points)); # 50%+1 +		my $limit = int($quiz{qcnt} * 0.5 + 1) * $points; # 50%+1 +		my $limiter = settings_get_bool('quiz_limiter'); +		return unless (!$limiter || !exists($quiz{players}{$addr}) || ($quiz{players}{$addr}{score} < $limit));  		stop_question();  		correct_answer($addr, $nick, $time, $points, $answer);  		init_next_question(get_format('quiz_msg_congrats', [ @@ -1205,7 +1256,7 @@ sub check_answer {  			$quiz{data}[$quiz{qnum}]{answer},  			$time - $quiz{qtime},  			length($answer) / ($time - $quiz{qtime}), -			$quiz{players}{$addr}{score}]), INSTANT); +			$quiz{players}{$addr}{score}]) . (($limiter && ($quiz{players}{$addr}{score} >= $limit)) ? ' ' . get_format('quiz_msg_limit') : ''), INSTANT);  	}  } @@ -1221,19 +1272,17 @@ sub sig_pubmsg {  		# \002 - bold  \003$fg(,$bg)? - color  \017 - plain  \026 - reverse  \037 - underline  	}  	return if ($msg eq ''); -	my $lmsg = lc $msg; -	if ($lmsg =~ /^!ile(?:\s+([^\s]+))?/) { -		show_score($nick, $addr, $1) -	} elsif ($lmsg =~ /^!join\s+(\d)$/) { -		join_team($nick, $addr, $1); -	} +	show_score($nick, $addr, $1) if ($msg =~ /^!ile(?:\s+([^\s]+))?/i); +	return if ($quiz{ended}); +	join_team($nick, $addr, $1) if ($msg =~ /^!join\s+(\d)$/i);  	return if (!$quiz{inq}); +	my $lmsg = lc $msg;  	if ($lmsg eq '!podp') {  		show_hint();  	} elsif (($lmsg eq '!przyp') || ($lmsg eq '!pyt')) {  		show_remind();  	} -	check_answer($nick, $addr, $lmsg); +	check_answer($nick, $addr, $msg);  }  ##### Bindings ##### diff --git a/scripts/iquiz_en.pl b/scripts/iquiz_en.pl index 14b55f5..883ef65 100644 --- a/scripts/iquiz_en.pl +++ b/scripts/iquiz_en.pl @@ -1,5 +1,5 @@  ################################################################## -##    irssi Quiz (iQuiz) script (2010-2016) by wilk/xorandor    ## +##    irssi Quiz (iQuiz) script (2010-2017) by wilk/xorandor    ##  ##################################################################  ## Script inspired by classic mIRC scripts: "Dizzy" by Dizzy,   ##  ##   "Mieszacz" & "Familiada" by snajperx (both with my later   ## @@ -12,7 +12,7 @@  # Script works with:  # -# - standard Dizzy/Pomieszany files (also without "pyt"/"odp" prefixes): +# - standard "Dizzy"/"Pomieszany" files (also without "pyt"/"odp" prefixes):  #  # pyt Evaluate: 2+2=?  # odp four @@ -20,7 +20,7 @@  # odp Sun  # ...  # -# - standard Mieszacz files (also without line numbers): +# - standard "Mieszacz" files (also without line numbers):  #  # 1 alpha  # 2 beta @@ -28,7 +28,7 @@  # 4 delta  # ...  # -# - standard Familiada files (can have any number of answers per question, used also for Multi): +# - standard "Familiada" files (can have any number of answers per question, not only 10; used also for "Multi"):  #  # Planets of our Solar System:  # Mercury*Venus*Earth*Mars*Jupiter*Saturn*Uranus*Neptune @@ -36,16 +36,15 @@  # methane*ethane*propane*butane*pentane*hexane  # ... -# >>> To view all available commands and settings type: /quiz +# >>> To review all available commands and settings type: /quiz OR /help quiz  # only core modules  use strict;  use warnings;  use Irssi qw(theme_register current_theme command_bind settings_add_int settings_add_bool settings_add_str settings_get_int settings_get_bool settings_get_str settings_set_int settings_set_bool settings_set_str printformat timeout_add_once timeout_remove signal_add_last signal_remove signal_stop signal_emit active_win);  use Time::HiRes qw(time); -use constant { QT_STD => 1, QT_MIX => 2, QT_FAM => 3, QT_MUL => 4, QT_SCR => 5 }; # QT_MIL => 6, QT_FOR => 7 -our $VERSION = '160919_en'; +our $VERSION = '170202_en';  our %IRSSI = (  	authors			=> 'wilk',  	name			=> 'iQuiz', @@ -72,41 +71,54 @@ my $_protect_urls = 1;				# bool; turn off antigoogler if URL is detected in que  my $_round_warn_time = 15;			# sec; seconds before round end to show warning (0 = off)  my $_round_warn_coeff = 1.5;		# float; round duration must be longer than coeff * $_round_warn_time to show warning (protection)  my $_qstats_ranks = 0;				# bool; 0: /qstats param corresponds to number of players, 1: /qstats param corresponds to rank -my $_qstats_records = 5;			# int; number of time/speed record places in /qstats +my $_qstats_records = 5;			# int; number of time/speed record places in /qstats (0 - off) +my $_no_hints_spam = 1;				# bool; do not show fully revealed answer as a hint (except the first)? + +my $_flex_separator = '/';			# char; separator used in quiz_flx_* formats +my $_team_separator = ', ';			# str; team players separator eq. "nick1, nick2, nick3"  my $_next_delay = 10;				# sec; default delay between questions  my $_next_delay_long = 20;			# sec; default delay between questions (fam/mul) (longer delay to prevent flooding and give a breath)  my $_round_duration = 90;			# sec; default round duration +my $_hints_interval = 10;			# sec; default hints interval  my $_hint_alpha = '.';				# char; default substitution symbol for alphabet characters in hints (special characters are left intact)  my $_hint_digit = '.';				# char; default substitution symbol for digit characters in hints (special characters are left intact)  my $_quiz_types = 5;				# (do not change)  ##### Internal stuff ##### +use constant { QT_STD => 1, QT_MIX => 2, QT_FAM => 3, QT_MUL => 4, QT_SCR => 5 }; # QT_MIL => 6, QT_FOR => 7  use constant { T_HMS => 0, T_S => 1, T_MS => 2 }; # 0: h/m/s, 1: s only, 2: s.ms  use constant { INSTANT => 1, PREPDOTS => 1, V_INT => 1, V_BOOL => 2, V_STR => 3 };  my %quiz = (  	chan => undef, file => '',  	type => 0, tcnt => 0, # copies just in case someone modifies settings directly while quiz is running -	ison => 0, inq => 0, standby => 0, +	ison => 0,		# /qon ... /qoff (or error while /qreload) +	inq => 0,		# in question +	standby => 0,	# /qon QT_FAM ... /qon (/qoff or error in /qreload) +	ended => 0,		# after last question till /qoff (or error in /qreload)  	stime => 0, qtime => 0,  	qcnt => 0, qnum => 0, hnum => 0,  	score => 0, answers => 0, -	tnext => undef, tround => undef, thint => undef, tremind => undef, twarn => undef, +	tnext => undef, tround => undef, thint => undef, thinter => undef, tremind => undef, twarn => undef,  	hprot => 0, rprot => 0,  	data => [],		# data[]{question realquestion answer answers{}}  	teams => [],	# teams[]{score answers} -	players => {},	# players{}{nick timestamp score answers team besttime alltime bestspeed allspeed} -	lookup => {}, dcnt => 0, dmax => 0, lmax => 0, dots => [], hwords => [] +	players => {},	# players{}{nick timestamp score answers team joined besttime alltime bestspeed allspeed} +	lookup => {}, +	dcnt => 0,		# total number of currently unrevealed letters +	dmax => 0,		# number of currently unrevealed letters in the "most hidden" word +	dots => [], hwords => []  );  my %settings_int = ( -	'quiz_type' => 1, +	'quiz_type' => QT_STD,  	'quiz_teams' => 2,  	'quiz_delay' => $_next_delay,  	'quiz_delay_long' => $_next_delay_long, -	'quiz_round_duration' => $_round_duration, +	'quiz_timeout' => $_round_duration, +	'quiz_hints_interval' => $_hints_interval,  	'quiz_max_hints' => 0,  	'quiz_words_style' => 0,  	'quiz_anticheat_delay' => 3, @@ -120,6 +132,7 @@ my %settings_int = (  my %settings_bool = (  	'quiz_antigoogler' => 1, +	'quiz_autohinter' => 0,  	'quiz_split_long_lines' => 1,  	'quiz_show_first_hint' => 0,  	'quiz_first_hint_dots' => 0, @@ -134,6 +147,7 @@ my %settings_bool = (  	'quiz_transfer_points' => 0,  	'quiz_limiter' => 0,  	'quiz_keep_scores' => 0, +	'quiz_keep_teams' => 1,  	'quiz_cmd_hint' => 1,  	'quiz_cmd_remind' => 1,  ); @@ -180,7 +194,7 @@ theme_register([  	'quiz_err_na',			'%_iQuiz:%_ %RFeature is not available at this time%n',  	'quiz_msg',						'%s', # custom text -	'quiz_msg_start1',				"\00303>>> \00310iQuiz by wilk - let's start \00303<<<", +	'quiz_msg_start1',				"\00303>>> \00310iQuiz by wilk - let's start! \00303<<<",  	'quiz_msg_start2',				"\00303Commands: !hint, !remind, !score, !score nick",  	'quiz_msg_start2_f',			"\00303Commands: !remind, !score, !score nick, !join 1-%u", # 1: max teams  	'quiz_msg_start2_m',			"\00303Commands: !remind, !score, !score nick", @@ -201,7 +215,7 @@ theme_register([  	'quiz_msg_score_other',			"\00304%s\00303 scored \00304%d\00303 %s so far.", # see quiz_msg_score  	'quiz_msg_noscore_other',		"\00304%s\00303 hasn't scored any point so far!", # 1: nick  	'quiz_msg_noscores',			"\00303Scoreboard is empty.", -	'quiz_msg_scores',				"\00303Quiz scores after %s and %u %s:", # 1: time_str (hms), 2: question, 3: quiz_flx_questions, 4: questions (total), 5: quiz_flx_questions (total) +	'quiz_msg_scores',				"\00303Quiz scores after %s and %u %s:", # 1: time_str (hms), 2: question, 3: quiz_flx_aquestions, 4: questions (total), 5: quiz_flx_fquestions (total)  	'quiz_msg_scores_place',		"\00303%u. place: \00304%s\00303 - \00304%d\00303 %s [%.1f%%] (avg. guessing time: %10\$.3fs)", # 1: place, 2: nick, 3: score, 4: quiz_flx_points, 5: score%, 6: answers, 7: quiz_flx_answers, 8: answers%, 9: best time, 10: avg time, 11: best speed, 12: avg speed, 13: spacer  	'quiz_msg_scores_place_full',	"\00303%u. place: \00304%s\00303 - \00304%d\00303 %s [%.1f%%] (%u %s, avg. guessing time: %10\$.3fs)", # see quiz_msg_scores_place  	'quiz_msg_team_score',			"\00303Team %u (%s): \00304%d\00303 %s", # 1: team, 2: players (comma separated), 3: score, 4: quiz_flx_points, 5: score%, 6: answers, 7: quiz_flx_answers, 8: answers% @@ -214,6 +228,7 @@ theme_register([  	'quiz_msg_congrats',			"\00303Congrats, \00304%s\00303! You get %s for answer \00304%s\00303 given after %.3fs (%.3f chars/s) - total points: \00304%d\00303.", # 1: nick, 2: quiz_inc_got_point*, 3: answer, 4: time (ms), 5: speed (chars/s), 6: total score  	'quiz_inc_got_points',			"\00304%d\00303 %s", # 1: points, 2: quiz_flx_points  	'quiz_inc_got_point',			"\00303a %s", # 1: quiz_flx_point +	'quiz_msg_limit',				"\00307You've just got 50%%+1 points - let others play. ;)",  	'quiz_inc_hours',				'%u hr',			# 1: hours  	'quiz_inc_minutes',				'%u min',			# 1: minutes  	'quiz_inc_seconds',				'%u sec',			# 1: seconds @@ -221,25 +236,17 @@ theme_register([  	'quiz_msg_warn_timeout',		"\00307Warning, only \00304%u\00307s left for answering!", # 1: time (s)  	'quiz_msg_all_answers',			"\00303All answers were guessed!",  	'quiz_msg_timeout',				"\00303Timeout!", -	'quiz_msg_next',				"\00303Next question after %us...", # 1: time (s) -	'quiz_msg_next_x',				"\00303Next word after %us...", # 1: time (s) +	'quiz_msg_next',				"\00303Next question in %us...", # 1: time (s) +	'quiz_msg_next_x',				"\00303Next word in %us...", # 1: time (s)  	'quiz_msg_last',				"\00307No more questions!",  	'quiz_msg_skipped',				"\00303This question has been skipped.", -	# 1 point								/ 1 punkt -	# x points								/ x punktow -	# 2-4, x2-x4 points (x != 1)			/ 2-4, x2-x4 punkty (x != 1) +	# 1 point / x points / 2-4, x2-x4 points (x != 1)	|	1 punkt / x punktow / 2-4, x2-x4 punkty (x != 1)  	'quiz_flx_points',				'point/points/points', -	# 1 answer								/ 1 odpowiedz -	# x answers								/ x odpowiedzi -	# 2-4, x2-x4 answers (x != 1)			/ 2-4, x2-x4 odpowiedzi (x != 1) +	# 1 answer / x answers / 2-4, x2-x4 answers (x != 1)	|	1 odpowiedz / x odpowiedzi / 2-4, x2-x4 odpowiedzi (x != 1)  	'quiz_flx_answers',				'answer/answers/answers', -	# after 1 question						/ po 1 pytaniu -	# after x questions						/ po x pytaniach -	# after 2-4, x2-x4 questions (x != 1)	/ po 2-4, x2-x4 pytaniach (x != 1) +	# (after) 1 question / x questions / 2-4, x2-x4 questions (x != 1)	|	(po) 1 pytaniu / x pytaniach / 2-4, x2-x4 pytaniach (x != 1)  	'quiz_flx_aquestions',			'question/questions/questions', -	# from 1 question						/ z 1 pytania -	# from x questions						/ z x pytan -	# from 2-4, x2-x4 questions (x != 1)	/ z 2-4, x2-x4 pytan (x != 1) +	# (from) 1 question / x questions / 2-4, x2-x4 questions (x != 1)	|	(z) 1 pytania / x pytan / 2-4, x2-x4 pytan (x != 1)  	'quiz_flx_fquestions',			'question/questions/questions',  ]); @@ -308,7 +315,7 @@ sub send_irc {  		}  		timeout_add_once($_display_delay, 'evt_delayed_show_msg', $msg); # le trick (workaround for chantext showing after owntext)  	} else { -		send_ui_raw($msg); # this helps when we got disconnected not to lose messages like stats +		send_ui_raw($msg); # this helps when we got disconnected not to lose any messages (like stats)  		send_ui('quiz_err_server');  	}  } @@ -324,7 +331,7 @@ sub send_irc_whisper {  		}  		timeout_add_once($_display_delay, 'evt_delayed_show_notc', [$msg, $nick]); # le trick (workaround for chantext showing after owntext)  	} else { -		send_ui_raw($msg); # this helps when we got disconnected not to lose messages like stats +		send_ui_raw($msg); # this helps when we got disconnected not to lose any messages (like stats)  		send_ui('quiz_err_server');  	}  } @@ -421,7 +428,7 @@ sub antigoogle {  		if (!$quiz{inq}) {  			my $suffix = ($quiz{type} == QT_MIX) ? '_x' : ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? '_fm' : '');  			my $answers = keys %{$quiz{lookup}}; -			my $duration = abs(settings_get_int('quiz_round_duration')) || $_round_duration; # abs in case of <0, || in case of ==0 +			my $duration = abs(settings_get_int('quiz_timeout')) || $_round_duration; # abs in case of <0, || in case of ==0  			$msg_crap += length(get_format('quiz_msg_question' . $suffix, [$quiz{qnum}, $quiz{qcnt}, '', $answers, answers_str($answers), $duration]));  		} else {  			$msg_crap += length(get_format('quiz_msg_remind', '')); @@ -483,10 +490,10 @@ sub make_hint {  	my $dots_only = shift;  	my @words = split(/ /, $quiz{data}[$quiz{qnum}]{answer});  	if (!@{$quiz{dots}}) { # make first dots -		@quiz{qw/dcnt dmax lmax/} = (0) x 3; +		@quiz{qw/dcnt dmax/} = (0) x 2; +		$quiz{hwords} = [];  		my ($w, $dmax) = (0) x 2;  		foreach my $word (@words) { -			$quiz{lmax} = length($word) if (length($word) > $quiz{lmax});  			my ($l, $hword, $dcnt) = (0, '', 0);  			foreach my $letter (split(//, $word)) {  				if ($letter =~ /^[a-z0-9]$/i) { @@ -562,12 +569,12 @@ sub time_str {  sub flex {  	my ($value, $format, $flex) = (abs(shift), shift, 0); -	my @flex = split(/\//, get_format($format)); +	my @flex = split(/$_flex_separator/, get_format($format));  	if ($value != 1) {  		$flex++;  		$flex++ if ($value =~ /^[2-4]$|[^1][2-4]$/);  	} -	return defined($flex[$flex]) ? $flex[$flex] : '???'; # just a precaution +	return defined($flex[$flex]) ? $flex[$flex] : '???'; # just a precaution when user messes up  }  sub score_str		{ return flex(shift, 'quiz_flx_points'); }		# X points @@ -589,8 +596,8 @@ sub stop_timer {  }  sub stop_question { -	@quiz{qw/inq hnum hprot rprot dcnt dmax lmax/} = (0) x 7; -	stop_timer($_) foreach (qw/tround thint tremind twarn/); +	@quiz{qw/inq hnum hprot rprot dcnt dmax/} = (0) x 6; +	stop_timer($_) foreach (qw/tround thint thinter tremind twarn/);  	$quiz{dots} = [];  	$quiz{hwords} = [];  	$quiz{lookup} = {}; @@ -598,7 +605,7 @@ sub stop_question {  sub stop_quiz {  	stop_question(); -	@quiz{qw/ison standby/} = (0) x 2; +	@quiz{qw/ison standby ended/} = (0) x 3;  	stop_timer('tnext');  	signal_remove('message public', 'sig_pubmsg');  } @@ -616,9 +623,14 @@ sub init_next_question {  	my ($msg, $instant) = @_;  	if ($quiz{qnum} >= $quiz{qcnt}) {  		send_irc('quiz_msg', $msg . ' ' . get_format('quiz_msg_last'), $instant); +		$quiz{ended} = 1;  	} else { -		my $delay = abs(settings_get_int('quiz_delay' . ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? '_long' : ''))); # abs in case of <0 -		$delay ||= ((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) ? $_next_delay_long : $_next_delay); # in case of ==0 +		my $delay; +		if (($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) { +			$delay = abs(settings_get_int('quiz_delay_long')) || $_next_delay_long; # abs in case of <0, || in case of ==0 +		} else { +			$delay = abs(settings_get_int('quiz_delay')) || $_next_delay; # abs in case of <0, || in case of ==0 +		}  		send_irc('quiz_msg', $msg . ' ' . get_format('quiz_msg_next' . (($quiz{type} == QT_MIX) ? '_x' : ''), $delay), $instant);  		$quiz{tnext} = timeout_add_once($delay * 1000, 'evt_next_question', undef);  	} @@ -667,7 +679,7 @@ sub correct_answer {  }  sub hcmd { -	return sprintf(' %-37s - ', shift); +	return sprintf(' %-38s - ', shift);  }  sub hvar { @@ -682,53 +694,74 @@ sub hvar {  }  sub show_help { -	send_ui_raw("%_$IRSSI{name}%_ v$VERSION by wilk (quiz is currently: " . ($quiz{ison} ? ($quiz{standby} ? 'on standby' : 'running') : 'off') . ')'); +	my $type = settings_get_int('quiz_type'); +	send_ui_raw("%_$IRSSI{name}%_ v$VERSION by wilk (quiz currently: " . ($quiz{ison} ? ($quiz{standby} ? 'is on standby' : ($quiz{ended} ? 'has finished' : 'is running')) : 'is off') . ')');  	send_ui_raw('%_Available commands:%_');  	send_ui_raw(hcmd("/qtype [1-$_quiz_types/name]") . 'change quiz type (see quiz_type)'); -	send_ui_raw(hcmd("/qteams <2-$_max_teams>") . 'change number of teams (Familiada only)'); -	send_ui_raw(hcmd("/qon [channel] <file> [1-$_quiz_types/name] [0-$_max_teams]") . 'start the quiz; you can give a type'); -	send_ui_raw(hcmd('/qstats [places]') . 'display scoreboard (Familiada: 0 - teams only)'); -	send_ui_raw(hcmd('/qhint') . 'show next hint (not for Familiada/Multi)'); +	if ($type == QT_FAM) { +		send_ui_raw(hcmd("/qteams <2-$_max_teams>") . 'change number of teams'); +		send_ui_raw(hcmd("/qon [channel] <file> [1-$_quiz_types/name] [0-$_max_teams]") . 'start the quiz; you can give its type and number of teams'); +		send_ui_raw(hcmd('/qstats [places]') . 'display scoreboard (0: teams only)'); +	} else { +		send_ui_raw(hcmd("/qon [channel] <file> [1-$_quiz_types/name]") . 'start the quiz; you can give its type'); +		send_ui_raw(hcmd('/qstats [places]') . 'display scoreboard'); +	} +	send_ui_raw(hcmd('/qhint') . 'show next hint') if (($type != QT_FAM) && ($type != QT_MUL));  	send_ui_raw(hcmd('/qremind') . 'remind a question');  	send_ui_raw(hcmd('/qskip') . 'skip current question');  	send_ui_raw(hcmd('/qoff') . 'stop the quiz');  	send_ui_raw(hcmd('/qdelay <seconds>') . 'change delay between questions'); -	send_ui_raw(hcmd('/qtime <seconds>') . 'change round duration (Familiada/Multi only)'); +	send_ui_raw(hcmd('/qtime <seconds>') . 'change round duration') if (($type == QT_FAM) || ($type == QT_MUL));  	send_ui_raw(hcmd('/qreload') . 'reload questions from file');  	send_ui_raw(hcmd('/qinit') . 'reset settings to defaults');  	send_ui_raw('%_Available settings (/set):%_');  	send_ui_raw(hvar('quiz_type', V_INT) . 'quiz type (1: Dizzy, 2: Mieszacz/Literaki, 3: Familiada, 4: Multi (Familiada w/o teams), 5: Pomieszany)'); -	send_ui_raw(hvar('quiz_teams', V_INT) . "number of teams (2-$_max_teams; Familiada only)"); +	send_ui_raw(hvar('quiz_teams', V_INT) . "number of teams (2-$_max_teams)") if ($type == QT_FAM);  	send_ui_raw(hvar('quiz_delay', V_INT) . 'delay between questions (sec)'); -	send_ui_raw(hvar('quiz_delay_long', V_INT) . 'delay between questions (sec; Familiada/Multi only)'); -	send_ui_raw(hvar('quiz_round_duration', V_INT) . 'round duration (sec; Familiada/Multi only)'); -	send_ui_raw(hvar('quiz_max_hints', V_INT) . 'max. number of hints (0: no limit, >0: number of hints, <0: number of hidden chars; not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_words_style', V_INT) . 'word\'s style (0: no change, 1: l-case, 2: U-case, 3: Caps; Mieszacz/Pomieszany only)'); -	send_ui_raw(hvar('quiz_anticheat_delay', V_INT) . '!hint/!remind protection delay (sec; 0: off)'); -	send_ui_raw(hvar('quiz_first_anticheat_delay', V_INT) . 'first !hint/!remind protection delay (sec; 0: off)'); -	send_ui_raw(hvar('quiz_points_per_answer', V_INT) . 'points per answer'); -	send_ui_raw(hvar('quiz_min_points', V_INT) . 'min. points (Familiada/Multi only)'); -	send_ui_raw(hvar('quiz_max_points', V_INT) . 'max. points (Familiada/Multi only)'); -	send_ui_raw(hvar('quiz_scoring_mode', V_INT) . 'scoring mode (1: ppa, 2: ppa++, 3: ppa++:max, 4: min++ppa, 5: min++ppa:max, 6: max--ppa:min, 7: max->min; Familiada/Multi only)'); -	send_ui_raw(hvar('quiz_ranking_type', V_INT) . 'ranking type (1: ordinal "1234", 2: dense "1223", 3: competition "1224")'); +	if (($type == QT_FAM) || ($type == QT_MUL)) { +		send_ui_raw(hvar('quiz_delay_long', V_INT) . 'delay between questions (sec)'); +		send_ui_raw(hvar('quiz_timeout', V_INT) . 'round duration (sec)'); +	} else { +		send_ui_raw(hvar('quiz_max_hints', V_INT) . 'max. number of hints (0: no limit, >0: number of hints, <0: number of hidden chars)'); +		send_ui_raw(hvar('quiz_autohinter', V_BOOL) . 'show automatic hints?'); +		send_ui_raw(hvar('quiz_hints_interval', V_INT) . 'automatic hints interval (sec)'); +	} +	send_ui_raw(hvar('quiz_words_style', V_INT) . 'word\'s style (0: no change, 1: l-case, 2: U-case, 3: Caps)') if (($type == QT_MIX) || ($type == QT_SCR));  	send_ui_raw(hvar('quiz_antigoogler', V_BOOL) . 'mask questions with antigoogler?');  	send_ui_raw(hvar('quiz_split_long_lines', V_BOOL) . 'split long lines?'); -	send_ui_raw(hvar('quiz_show_first_hint', V_BOOL) . 'show questions along with first hint? (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_first_hint_dots', V_BOOL) . 'first hint as dots only? (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_random_hints', V_BOOL) . 'reveal random chars in hints? otherwise left to right (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_nonrandom_first_hint', V_BOOL) . 'reveal random chars in hints, except first hint? (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_hint_alpha', V_STR) . 'character substitution in place of letters (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_hint_digit', V_STR) . 'character substitution in place of digits (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_words_mode', V_BOOL) . 'scramble with word separation? otherwise all together (Mieszacz only)'); -	send_ui_raw(hvar('quiz_smart_mix', V_BOOL) . 'anchor some characters? (Pomieszany only)'); -	send_ui_raw(hvar('quiz_smart_mix_chars', V_STR) . 'anchor these characters (regex; Pomieszany only)'); -	send_ui_raw(hvar('quiz_mix_on_remind', V_BOOL) . 'scramble letters with each !remind? (Mieszacz/Pomieszany only)'); -	send_ui_raw(hvar('quiz_strict_match', V_BOOL) . 'allow only strict answers? or allow *matching* (not for Familiada/Multi)'); -	send_ui_raw(hvar('quiz_join_anytime', V_BOOL) . 'allow joining teams at any time? (Familiada only)' ); -	send_ui_raw(hvar('quiz_team_play', V_BOOL) . 'allow only team players to answer? (Familiada only)'); -	send_ui_raw(hvar('quiz_transfer_points', V_BOOL) . 'transfer scores when player changes teams? (Familiada only)'); -	send_ui_raw(hvar('quiz_limiter', V_BOOL) . 'limit best person scores to 50%+1 points? (not for Familiada/Multi)'); +	send_ui_raw(hvar('quiz_anticheat_delay', V_INT) . '!hint/!remind protection delay (sec; 0: wylaczone)'); +	send_ui_raw(hvar('quiz_first_anticheat_delay', V_INT) . 'first !hint/!remind protection delay (sec; 0: wylaczone)'); +	if (($type != QT_FAM) && ($type != QT_MUL)) { +		send_ui_raw(hvar('quiz_show_first_hint', V_BOOL) . 'show questions along with first hint?'); +		send_ui_raw(hvar('quiz_first_hint_dots', V_BOOL) . 'first hint as dots only?'); +		send_ui_raw(hvar('quiz_random_hints', V_BOOL) . 'reveal random chars in hints? otherwise left to right'); +		send_ui_raw(hvar('quiz_nonrandom_first_hint', V_BOOL) . 'reveal random chars in hints, except first hint?'); +		send_ui_raw(hvar('quiz_hint_alpha', V_STR) . 'character substitution in place of letters'); +		send_ui_raw(hvar('quiz_hint_digit', V_STR) . 'character substitution in place of digits'); +	} +	send_ui_raw(hvar('quiz_words_mode', V_BOOL) . 'scramble with word separation? otherwise all together') if ($type == QT_MIX); +	if ($type == QT_SCR) { +		send_ui_raw(hvar('quiz_smart_mix', V_BOOL) . 'anchor some characters?'); +		send_ui_raw(hvar('quiz_smart_mix_chars', V_STR) . 'anchor these characters (regex)'); +	} +	send_ui_raw(hvar('quiz_mix_on_remind', V_BOOL) . 'scramble letters with each !remind?') if (($type == QT_MIX) || ($type == QT_SCR)); +	if ($type == QT_FAM) { +		send_ui_raw(hvar('quiz_join_anytime', V_BOOL) . 'allow joining teams at any time?'); +		send_ui_raw(hvar('quiz_team_play', V_BOOL) . 'allow only team players to answer?'); +		send_ui_raw(hvar('quiz_transfer_points', V_BOOL) . 'transfer scores when player changes teams?'); +	} +	send_ui_raw(hvar('quiz_strict_match', V_BOOL) . 'allow only strict answers? or allow *matching*') if (($type != QT_FAM) && ($type != QT_MUL)); +	send_ui_raw(hvar('quiz_points_per_answer', V_INT) . 'points per answer'); +	if (($type == QT_FAM) || ($type == QT_MUL)) { +		send_ui_raw(hvar('quiz_min_points', V_INT) . 'min. points'); +		send_ui_raw(hvar('quiz_max_points', V_INT) . 'max. points'); +		send_ui_raw(hvar('quiz_scoring_mode', V_INT) . 'scoring mode (1: ppa, 2: ppa++, 3: ppa++:max, 4: min++ppa, 5: min++ppa:max, 6: max--ppa:min, 7: max->min'); +	} else { +		send_ui_raw(hvar('quiz_limiter', V_BOOL) . 'limit best person scores to 50%+1 points?'); +	} +	send_ui_raw(hvar('quiz_ranking_type', V_INT) . 'ranking type (1: ordinal "1234", 2: dense "1223", 3: competition "1224")');  	send_ui_raw(hvar('quiz_keep_scores', V_BOOL) . 'keep scores between quizes?'); +	send_ui_raw(hvar('quiz_keep_teams', V_BOOL) . 'keep chosen teams?') if ($type == QT_FAM);  	send_ui_raw(hvar('quiz_cmd_hint', V_BOOL) . '!hint command is enabled?');  	send_ui_raw(hvar('quiz_cmd_remind', V_BOOL) . '!remind command is enabled?');  } @@ -777,11 +810,14 @@ sub cmd_start {  		$quiz{teams} = [];  		@quiz{qw/score answers/} = (0) x 2;  	} else { -		#delete $quiz{players}{$_}{team} for (keys %{$quiz{players}}); #? unsure... +		if (!settings_get_bool('quiz_keep_teams') && ($type == QT_FAM)) { +			delete $quiz{players}{$_}{team} for (keys %{$quiz{players}}); +		}  	}  	send_irc('quiz_msg_start1', INSTANT);  	send_irc('quiz_msg_start2' . (($type == QT_FAM) ? '_f' : (($type == QT_MUL) ? '_m' : '')), $teams, INSTANT); -	@quiz{qw/stime qnum ison/} = (time(), 0, 1); +	@quiz{qw/stime ison/} = (time(), 1); +	@quiz{qw/qnum inq ended/} = (0) x 3;  	if ($type == QT_FAM) {  		$quiz{standby} = 1;  		@{$quiz{teams}[$_]}{qw/score answers/} = (0) x 2 for (0 .. $teams); @@ -810,12 +846,12 @@ sub cmd_stats {  		((($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) && (settings_get_int('quiz_scoring_mode') != 1)));  	if ($quiz{type} == QT_FAM) {  		my @teams; -		push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (keys %{$quiz{players}}); +		push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (sort { $quiz{players}{$a}{joined} <=> $quiz{players}{$b}{joined} } keys %{$quiz{players}});  		foreach my $team (1 .. $quiz{tcnt}) {  			my ($score, $answers) = @{$quiz{teams}[$team]}{qw/score answers/};  			send_irc('quiz_msg_team_score' . $suffix, [  				$team, -				(!defined $teams[$team]) ? '' : join(', ', @{$teams[$team]}), +				(!defined $teams[$team]) ? '' : join($_team_separator, @{$teams[$team]}),  				$score, score_str($score), percents($score, $quiz{score}),  				$answers, answers_str($answers), percents($answers, $quiz{answers})]);  		} @@ -862,8 +898,7 @@ sub cmd_stats {  						$quiz{players}{$a}{timestamp} <=> $quiz{players}{$b}{timestamp}  					} keys %{$quiz{players}}) {  		push(@nicks, get_format('quiz_inc_scores_record', [$place, $quiz{players}{$player}{nick}, $quiz{players}{$player}{besttime}])); -		last if ($place >= $_qstats_records); -		$place++; +		last if (++$place > $_qstats_records);  	}  	send_irc('quiz_msg_scores_times', join(', ', @nicks)) if (@nicks);  	$place = 1; @@ -873,8 +908,7 @@ sub cmd_stats {  						$quiz{players}{$a}{timestamp} <=> $quiz{players}{$b}{timestamp}  					} keys %{$quiz{players}}) {  		push(@nicks, get_format('quiz_inc_scores_record', [$place, $quiz{players}{$player}{nick}, $quiz{players}{$player}{bestspeed}])); -		last if ($place >= $_qstats_records); -		$place++; +		last if (++$place > $_qstats_records);  	}  	send_irc('quiz_msg_scores_speeds', join(', ', @nicks)) if (@nicks);  } @@ -892,7 +926,7 @@ sub cmd_time {  	my $duration = shift;  	#? send_ui('quiz_err_na'), return if (($quiz{type} != QT_FAM) && ($quiz{type} != QT_MUL));  	send_ui('quiz_err_duration'), return if (($duration !~ /^\d+$/) || ($duration < 1)); -	settings_set_int('quiz_round_duration', $duration); +	settings_set_int('quiz_timeout', $duration);  	send_irc('quiz_msg_duration', $duration) if ($quiz{ison});  	send_ui('quiz_inf_duration', $duration);  } @@ -1017,7 +1051,7 @@ sub evt_next_question {  		%{$quiz{lookup}} = map { lc($_) => $_ } keys %{$quiz{data}[$quiz{qnum}]{answers}};  		$suffix = '_fm';  	} -	my $duration = abs(settings_get_int('quiz_round_duration')) || $_round_duration; # abs in case of <0, || in case of ==0 +	my $duration = abs(settings_get_int('quiz_timeout')) || $_round_duration; # abs in case of <0, || in case of ==0  	my @lines = make_remind();  	my $line = 1;  	foreach my $text (@lines) { @@ -1039,17 +1073,21 @@ sub evt_next_question {  		}  	} else {  		send_irc('quiz_msg_hint', make_hint()) if (settings_get_bool('quiz_show_first_hint')); -	} -	$quiz{inq} = 1; -	my $delay = settings_get_int('quiz_first_anticheat_delay'); -	if ($delay > 0) { -		$quiz{hprot} = 1; -		$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef); -		if ((($quiz{type} == QT_MIX) || ($quiz{type} == QT_SCR)) && settings_get_bool('quiz_mix_on_remind')) { -			$quiz{rprot} = 1; -			$quiz{tremind} = timeout_add_once($delay * 1000, sub { $quiz{rprot} = 0 }, undef); +		my $delay = settings_get_int('quiz_first_anticheat_delay'); +		if ($delay > 0) { +			$quiz{hprot} = 1; +			$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef); +			if ((($quiz{type} == QT_MIX) || ($quiz{type} == QT_SCR)) && settings_get_bool('quiz_mix_on_remind')) { +				$quiz{rprot} = 1; +				$quiz{tremind} = timeout_add_once($delay * 1000, sub { $quiz{rprot} = 0 }, undef); +			} +		} +		if (settings_get_bool('quiz_autohinter')) { +			$delay = abs(settings_get_int('quiz_hints_interval')) || $_hints_interval; # abs in case of <0, || in case of ==0 +			$quiz{thinter} = timeout_add_once($delay * 1000, 'evt_show_hint', undef);  		}  	} +	$quiz{inq} = 1;  }  sub evt_round_timeout_warn { @@ -1061,6 +1099,10 @@ sub evt_round_timeout {  	init_next_question(get_format('quiz_msg_timeout')); #? INSTANT?  } +sub evt_show_hint { +	show_hint(); +} +  ##### User interaction - responses / handlers #####  sub show_score {  	my ($nick, $addr, $who) = @_; @@ -1086,7 +1128,8 @@ sub show_score {  sub join_team {  	my ($nick, $addr, $team) = @_;  	return unless (($quiz{type} == QT_FAM) && (settings_get_bool('quiz_join_anytime') || $quiz{standby})); -	return unless (($team >= 1) && ($team <= $quiz{tcnt})); +	return if (($team < 1) || ($team > $quiz{tcnt})); +	my $time = time();  	if (exists $quiz{players}{$addr}) {  		if (settings_get_bool('quiz_transfer_points')) {  			my ($score, $answers) = @{$quiz{players}{$addr}}{qw/score answers/}; @@ -1098,21 +1141,21 @@ sub join_team {  			$quiz{teams}[$team]{score} += $score;  			$quiz{teams}[$team]{answers} += $answers;  		} -		$quiz{players}{$addr}{team} = $team;  	} else { -		@{$quiz{players}{$addr}}{qw/nick timestamp team/} = ($nick, time(), $team); +		@{$quiz{players}{$addr}}{qw/nick timestamp/} = ($nick, $time);  		@{$quiz{players}{$addr}}{qw/score answers besttime alltime bestspeed allspeed/} = (0) x 6;  	} +	@{$quiz{players}{$addr}}{qw/team joined/} = ($team, $time);  	my @teams; -	push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (keys %{$quiz{players}}); -	send_irc_whisper('quiz_msg_team_join', [$team, join(', ', @{$teams[$team]})], $nick) if (defined $teams[$team]); +	push(@{$teams[$quiz{players}{$_}{team}]}, get_format('quiz_inc_team_nick', $quiz{players}{$_}{nick})) for (sort { $quiz{players}{$a}{joined} <=> $quiz{players}{$b}{joined} } keys %{$quiz{players}}); +	send_irc_whisper('quiz_msg_team_join', [$team, join($_team_separator, @{$teams[$team]})], $nick) if (defined $teams[$team]);  }  sub show_hint { -	return unless (($quiz{type} != QT_FAM) && ($quiz{type} != QT_MUL) && settings_get_bool('quiz_cmd_hint')); -	return if ($quiz{hprot}); +	return if ($quiz{hprot} || ($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL) || !settings_get_bool('quiz_cmd_hint'));  	my $hints_limit = settings_get_int('quiz_max_hints'); -	make_hint(PREPDOTS) if (!@{$quiz{dots}} && ($hints_limit < 0)); +	make_hint(PREPDOTS) if (($quiz{hnum} == 0) && ($hints_limit < 0)); +	return unless (($quiz{hnum} == 0) || !$_no_hints_spam || ($quiz{dcnt} > 0));  	if (($hints_limit == 0) ||  		(($hints_limit > 0) && ($quiz{hnum} < $hints_limit)) ||  		(($hints_limit < 0) && ($quiz{dmax} > abs($hints_limit)))) { @@ -1123,6 +1166,11 @@ sub show_hint {  				$quiz{thint} = timeout_add_once($delay * 1000, sub { $quiz{hprot} = 0 }, undef);  			}  	} +	if (settings_get_bool('quiz_autohinter')) { +		stop_timer('thinter'); +		my $delay = abs(settings_get_int('quiz_hints_interval')) || $_hints_interval; # abs in case of <0, || in case of ==0 +		$quiz{thinter} = timeout_add_once($delay * 1000, 'evt_show_hint', undef); +	}  }  sub show_remind { @@ -1149,9 +1197,11 @@ sub show_remind {  sub check_answer {  	my ($nick, $addr, $answer) = @_;  	if (($quiz{type} == QT_FAM) || ($quiz{type} == QT_MUL)) { -		return unless (exists($quiz{lookup}{$answer}) && ($quiz{data}[$quiz{qnum}]{answers}{$quiz{lookup}{$answer}} > 0)); -		return unless (($quiz{type} == QT_MUL) || !settings_get_bool('quiz_team_play') || (exists($quiz{players}{$addr}) && exists($quiz{players}{$addr}{team}) && ($quiz{players}{$addr}{team} != 0))); # last condition: for non team players there is no record -		my ($time, $match) = (time(), $quiz{lookup}{$answer}); +		return unless (exists($quiz{lookup}{lc $answer}) && +						($quiz{data}[$quiz{qnum}]{answers}{$quiz{lookup}{lc $answer}} > 0)); +		return unless (($quiz{type} == QT_MUL) || !settings_get_bool('quiz_team_play') || +						(exists($quiz{players}{$addr}) && exists($quiz{players}{$addr}{team}) && ($quiz{players}{$addr}{team} != 0))); # last condition: for non team players there is no record yet // autovivification... +		my ($time, $match) = (time(), $quiz{lookup}{lc $answer});  		my $answers = keys %{$quiz{data}[$quiz{qnum}]{answers}};  		my $id = $quiz{data}[$quiz{qnum}]{answers}{$match};  		my $value = $answers - $id + 1; @@ -1192,11 +1242,12 @@ sub check_answer {  			init_next_question(get_format('quiz_msg_all_answers')); #? not INSTANT  		}  	} else { -		return unless (($answer eq lc($quiz{data}[$quiz{qnum}]{answer})) || -			(!settings_get_bool('quiz_strict_match') && (index($answer, lc $quiz{data}[$quiz{qnum}]{answer}) >= 0))); +		return unless ((lc($answer) eq lc($quiz{data}[$quiz{qnum}]{answer})) || +			(!settings_get_bool('quiz_strict_match') && (index(lc $answer, lc $quiz{data}[$quiz{qnum}]{answer}) >= 0)));  		my ($time, $points) = (time(), settings_get_int('quiz_points_per_answer')); -		return unless (!settings_get_bool('quiz_limiter') || !exists($quiz{players}{$addr}) || -			($quiz{players}{$addr}{score} < int($quiz{qcnt} * 0.5 + 1) * $points)); # 50%+1 +		my $limit = int($quiz{qcnt} * 0.5 + 1) * $points; # 50%+1 +		my $limiter = settings_get_bool('quiz_limiter'); +		return unless (!$limiter || !exists($quiz{players}{$addr}) || ($quiz{players}{$addr}{score} < $limit));  		stop_question();  		correct_answer($addr, $nick, $time, $points, $answer);  		init_next_question(get_format('quiz_msg_congrats', [ @@ -1205,7 +1256,7 @@ sub check_answer {  			$quiz{data}[$quiz{qnum}]{answer},  			$time - $quiz{qtime},  			length($answer) / ($time - $quiz{qtime}), -			$quiz{players}{$addr}{score}]), INSTANT); +			$quiz{players}{$addr}{score}]) . (($limiter && ($quiz{players}{$addr}{score} >= $limit)) ? ' ' . get_format('quiz_msg_limit') : ''), INSTANT);  	}  } @@ -1221,19 +1272,17 @@ sub sig_pubmsg {  		# \002 - bold  \003$fg(,$bg)? - color  \017 - plain  \026 - reverse  \037 - underline  	}  	return if ($msg eq ''); -	my $lmsg = lc $msg; -	if ($lmsg =~ /^!score(?:\s+([^\s]+))?/) { -		show_score($nick, $addr, $1) -	} elsif ($lmsg =~ /^!join\s+(\d)$/) { -		join_team($nick, $addr, $1); -	} +	show_score($nick, $addr, $1) if ($msg =~ /^!score(?:\s+([^\s]+))?/i); +	return if ($quiz{ended}); +	join_team($nick, $addr, $1) if ($msg =~ /^!join\s+(\d)$/i);  	return if (!$quiz{inq}); +	my $lmsg = lc $msg;  	if ($lmsg eq '!hint') {  		show_hint();  	} elsif ($lmsg eq '!remind') {  		show_remind();  	} -	check_answer($nick, $addr, $lmsg); +	check_answer($nick, $addr, $msg);  }  ##### Bindings ##### diff --git a/scripts/ircgmessagenotify.pl b/scripts/ircgmessagenotify.pl index e3973bd..cb019d1 100644 --- a/scripts/ircgmessagenotify.pl +++ b/scripts/ircgmessagenotify.pl @@ -34,6 +34,7 @@ $VERSION = "0.1b";   contact => "bcow\@iki.fi",   name => "ircgmessagenotify",   description => "Tarkistelee irc-galleria.net:i ja sanoo kun sinulle on uusia viestej.", + sbitems => "ircgcomments",   license => "GPLv2",   url => "http://www.verkonpaino.net/",   changed => "21.01.2004 23:55:00 EET" @@ -214,4 +215,4 @@ Irssi::signal_add("setup changed", "setup_changed");  Irssi::command_bind('ircgcomments', 'check_messages_forced');  # viimeiseksi j statusbar liitos -Irssi::statusbar_item_register('ircgcomments','{sb $0-}', 'statusbar');
\ No newline at end of file +Irssi::statusbar_item_register('ircgcomments','{sb $0-}', 'statusbar'); diff --git a/scripts/irssiBlaster.pl b/scripts/irssiBlaster.pl index 6d06a30..1775763 100644 --- a/scripts/irssiBlaster.pl +++ b/scripts/irssiBlaster.pl @@ -96,6 +96,7 @@ $VERSION = '1.6';  	contact		=> 'a.lepore@email.it',  	name		=> 'irssiBlaster',  	description	=> 'Display the song played by mp3blaster in channels and statusbar. See the top of the file for usage.', +	sbitems		=> 'blaster',  	license		=> 'GNU GPLv2 or later',  	changed		=> 'Fri Oct 31 12:22:08 CET 2003',  ); diff --git a/scripts/itime.pl b/scripts/itime.pl index 3f63f8c..8483a59 100644 --- a/scripts/itime.pl +++ b/scripts/itime.pl @@ -15,6 +15,7 @@ $VERSION = '0.9';      name        => 'itime',      description =>  'Internet Time statusbar item. See http://www.timeanddate.com/time/internettime.html', +    sbitems => 'itime',      license => 'Public Domain',      url     => 'http://ion.amigafin.org/scripts/',      changed => 'Tue Mar 12 22:20 EET 2002', diff --git a/scripts/kicks.pl b/scripts/kicks.pl index 9df9314..76e87ea 100644 --- a/scripts/kicks.pl +++ b/scripts/kicks.pl @@ -4,76 +4,77 @@  #    - http://www.penguin-breeder.org/irssi/  #<scriptinfo> +use strict;  use vars qw($VERSION %IRSSI);  use Irssi 20020120; -$VERSION = "0.26"; +$VERSION = "0.27";  %IRSSI = ( -    authors	=> "c0ffee", -    contact	=> "c0ffee\@penguin-breeder.org", -    name	=> "Various kick and ban commands", -    description	=> "Enhances /k /kb and /kn with some nice options.", -    license	=> "Public Domain", -    url		=> "http://www.penguin-breeder.org/irssi/", -    changed	=> "Tue Nov 14 23:19:19 CET 2006", +    authors => "c0ffee", +    contact => "c0ffee\@penguin-breeder.org", +    name    => "Various kick and ban commands", +    description => "Enhances /k /kb and /kn with some nice options.", +    license => "Public Domain", +    url     => "http://www.penguin-breeder.org/irssi/", +    changed => "2017-03-31",  );  #</scriptinfo>  my %kickreasons  = ( -	default => ["random kick victim", -		    "no", -		    "are you stupid?", -		    "i don't like you, go away!", -		    "oh, fsck off", -		    "waste other ppls time, elsewhere", -		    "get out and STAY OUT", -		    "don't come back", -		    "no thanks", -		    "on popular demand, you are now leaving the channel", -		    "\$N", -		    "*void*", -		    "/part is the command you're looking for", -		    "this is the irssi of borg. your mIRC will be assimilated. resistance is futile.", -		    "Autokick! mwahahahah!" -		   ], -	none	=> [""], -	topic	=> ["\$topic"], +    default => ["random kick victim", +            "no", +            "are you stupid?", +            "i don't like you, go away!", +            "oh, fsck off", +            "waste other ppls time, elsewhere", +            "get out and STAY OUT", +            "don't come back", +            "no thanks", +            "on popular demand, you are now leaving the channel", +            "\$N", +            "*void*", +            "/part is the command you're looking for", +            "this is the irssi of borg. your mIRC will be assimilated. resistance is futile.", +            "Autokick! mwahahahah!" +           ], +    none    => [""], +    topic   => ["\$topic"],  );  # fine tune the script for different chatnets -#    cmdline_k		regular expr that matches a correct cmdline for /k -#    req_chan		0/1 whether the channel is always part of the cmdline -#    num_nicks		number of nicks ... (-1 = inf) -#    start_with_dash	0/1 whether the normal cmdline may start with a dash -#    match_chn		matches channels -#    match_n		match nicks -#    match_reason	matches reasons -#    default_reason	reason to give as "no reason" +#    cmdline_k      regular expr that matches a correct cmdline for /k +#    req_chan       0/1 whether the channel is always part of the cmdline +#    num_nicks      number of nicks ... (-1 = inf) +#    start_with_dash    0/1 whether the normal cmdline may start with a dash +#    match_chn      matches channels +#    match_n        match nicks +#    match_reason   matches reasons +#    default_reason reason to give as "no reason"  my %cfg = ( -	IRC	=> { -			cmdline_k       => '\s*([!#+&][^\x0\a\n\r ]*)\s+[-\[\]\\\\\`{}\w_|^\'~]+(,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+\S.*', -			req_chan        => 0, -			num_nicks       => 3, # actually, /k takes more, but -			                      # normal irc servers only take -					      # three in a row -			start_with_dash => 1, -			match_chn       => '([!#+&][^\x0\a\n\r ]*)\s', -			match_n         => '(?:^|\s+)([-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\']+)*)', -			match_reason    => '^\s*[!#+&][^\x0\a\n\r ]*\s+[-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+(\S.*)$', -			default_reason  => '$N' -		}, - -	SILC	=> { -			cmdline_k	=> '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+\s+\S.*', -			req_chan	=> 1, -			num_nicks	=> 1, -			start_with_dash => 0, -			match_chn	=> '\s*([^\x0-\x20\*\?,@!]+)\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*', -			match_n		=> '\s*(?:[^\x0-\x20\*\?,@!]+\s+)?([^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*)', -			match_reason	=> '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*\s+(\S.*)', -			default_reason	=> '$N' -		} +    IRC => { +            cmdline_k       => '\s*([!#+&][^\x0\a\n\r ]*)\s+[-\[\]\\\\\`{}\w_|^\'~]+(,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+\S.*', +            req_chan        => 0, +            num_nicks       => 3, # actually, /k takes more, but +                                  # normal irc servers only take +                          # three in a row +            start_with_dash => 1, +            match_chn       => '([!#+&][^\x0\a\n\r ]*)\s', +            match_n         => '(?:^|\s+)([-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\']+)*)', +            match_reason    => '^\s*[!#+&][^\x0\a\n\r ]*\s+[-\[\]\\\\\`{}\w_|^\'~]+(?:,[-\[\]\\\\\`{}\w_|^\'~]+)*\s+(\S.*)$', +            default_reason  => '$N' +        }, + +    SILC    => { +            cmdline_k   => '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+\s+\S.*', +            req_chan    => 1, +            num_nicks   => 1, +            start_with_dash => 0, +            match_chn   => '\s*([^\x0-\x20\*\?,@!]+)\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*', +            match_n     => '\s*(?:[^\x0-\x20\*\?,@!]+\s+)?([^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*)', +            match_reason    => '\s*[^\x0-\x20\*\?,@!]+\s+[^\x0-\x20\*\?,@!]+(?:,[^\x0-\x20\*\?,@!]+)*\s+(\S.*)', +            default_reason  => '$N' +        }  );  sub initialize { @@ -83,51 +84,53 @@ sub initialize {      my ($basedir) = $conf_file =~ /^(.*\/).*?/;      if (-f $conf_file) { -	open CONF, $conf_file; -	 -	while (<CONF>) { -	    $line++; - -	    next if /^\s*#/; - -	    chomp; -	    ($key, $reasons) = /^(\S+)\s+(.+)\s*$/ or next; - -	    if ($reasons =~ /\`([^\s]+).*?\`/) { -		$kickreasons{$key} = "$reasons"; -		Irssi::print("Added executable $1 as $key..."); -		next; -	    } - -	    $reasons =~ s/^"(.*)"$/$1/; -	    $reasons =~ s/~/$ENV{HOME}/; -	    $reasons =~ s/^([^\/])/$basedir$1/; -	     -	    if (-f $reasons) { - -		$kickreasons{$key} = []; - -		open REASON, $reasons; - -		while (<REASON>) { -		    chomp; -		    push @{$kickreasons{$key}}, $_; -		} - -		close REASON; -		Irssi::print("Loaded $reasons as $key..."); -	    } else { -		Irssi::print("can't parse config line $line..."); -	    } -	} -	close CONF; +        open CONF, '<', $conf_file; + +        my $line=0; +         +        while (<CONF>) { +            $line++; + +            next if /^\s*#/; + +            chomp; +            my ($key, $reasons) = /^(\S+)\s+(.+)\s*$/ or next; + +            if ($reasons =~ /\`([^\s]+).*?\`/) { +                $kickreasons{$key} = "$reasons"; +                Irssi::print("Added executable $1 as $key..."); +                next; +            } + +            $reasons =~ s/^"(.*)"$/$1/; +            $reasons =~ s/~/$ENV{HOME}/; +            $reasons =~ s/^([^\/])/$basedir$1/; +             +            if (-f $reasons) { + +                $kickreasons{$key} = []; + +                open REASON, '<',  $reasons; + +                while (<REASON>) { +                    chomp; +                    push @{$kickreasons{$key}}, $_; +                } + +                close REASON; +                Irssi::print("Loaded $reasons as $key..."); +            } else { +                Irssi::print("can't parse config line $line..."); +            } +        } +        close CONF;      } else {          Irssi::print("Could not find configuration file for kicks..."); -	Irssi::print("... use /set kicks_configuration <file>"); +        Irssi::print("... use /set kicks_configuration <file>");      }  } -			 +              sub get_a_reason {      my ($topic) = @_; @@ -147,15 +150,17 @@ sub cmd_realkick {      return if not $server                or not defined $cfg{$server->{chat_type}} -	      or not $channel -    	      or $data =~ /^$cfg{$server->{chat_type}}{cmdline_k}$/; +          or not $channel +              or $data =~ /^$cfg{$server->{chat_type}}{cmdline_k}$/;      Irssi::signal_stop();      # let's see whether some options where supplied -    $default = Irssi::settings_get_str("default_kick_options"); +    my $default = Irssi::settings_get_str("default_kick_options");      $data = "$default $data" if not $default =~ /^\s*$/; -    @opts = split /\s+/, $data; +    my @opts = split /\s+/, $data; +    my $opt; +    my $fail=0;      while (($opt) = (shift @opts) =~ /^\s*-(\S+)/) { @@ -163,18 +168,18 @@ sub cmd_realkick {          $data =~ s/^\s*-$opt\s+//,               $reasons = lc $opt, -	    next if defined $kickreasons{lc $opt}; +        next if defined $kickreasons{lc $opt};          last if $cfg{$server->{chat_type}}{start_with_dash};          Irssi::print("Unknown option -$opt"); -        $fail = true; +        $fail = 1;      }      return if $fail; -    $chn = ""; +    my $chn = "";      ($chn) = $data =~ /^$cfg{$server->{chat_type}}{match_chn}/;      if ($cfg{$server->{chat_type}}{req_chan} && ($chn eq "")) { @@ -184,37 +189,39 @@ sub cmd_realkick {      # do we need to add a channel?      if ($chn eq "") { -	Irssi::print("Not joined to any channel"), return  -	    if $channel->{type} ne "CHANNEL"; +    Irssi::print("Not joined to any channel"), return  +        if $channel->{type} ne "CHANNEL";          $chn = $channel->{name}; -	$data = "$chn $data"; +    $data = "$chn $data";      }      # is a reason already supplied? +    my $reason;      $reason = get_a_reason($reasons)          if not (($reason) = $data =~ /$cfg{$server->{chat_type}}{match_reason}/);      $reason = $cfg{$server->{chat_type}}{default_reason}          if $reason =~ /^\s*$/; -    @nicks = split /,/, ($data =~ /$cfg{$server->{chat_type}}{match_n}/)[0]; -    $num_nicks = $cfg{$server->{chat_type}}{num_nicks}; +    my @nicks = split /,/, ($data =~ /$cfg{$server->{chat_type}}{match_n}/)[0]; +    my $num_nicks = $cfg{$server->{chat_type}}{num_nicks};      $num_nicks = @nicks if $num_nicks <= 0; +    my @commands;      undef @commands;      while (@nicks) { -        $tmp = ($chn ne "" ? "$chn " : "") . +        my $tmp = ($chn ne "" ? "$chn " : "") .                 join ",", (splice @nicks,0,$num_nicks); -	$tmp =~ s/([;\\\$])/\\$1/g; -	push @commands, "$tmp $reason"; +        $tmp =~ s/([;\\\$])/\\$1/g; +        push @commands, "$tmp $reason";      }      foreach (@commands) {        if ($_ =~ /^$cfg{$server->{chat_type}}{cmdline_k}$/) {          s/\s+$//; -        $channel->command("EVAL $cmd $_")  +        $channel->command("EVAL $cmd $_");        } else {          Irssi::print("BUG: generated invalid $cmd command: $_");        } @@ -237,7 +244,7 @@ sub cmd_kickban {  Irssi::settings_add_str("misc", "default_kick_options", "");  Irssi::settings_add_str("misc", "kicks_configuration", -				Irssi::get_irssi_dir() . "/kicks.conf"); +                Irssi::get_irssi_dir() . "/kicks.conf");  Irssi::command_bind("kick", "cmd_kick");  Irssi::command_bind("kickban", "cmd_kickban"); diff --git a/scripts/licq.pl b/scripts/licq.pl index 92a83a1..2f747fe 100644 --- a/scripts/licq.pl +++ b/scripts/licq.pl @@ -6,6 +6,7 @@ $VERSION = "0.5";      contact     => "jmn98015\@student.mdh.se",      name        => "licq",      description => "Licq statusbar thingy", +    sbitems     => "licq",      license     => "Public Domain",      url         => "http://jari.cjb.net,http://irssi.org,http://scripts.irssi.de",  ); diff --git a/scripts/listsort.pl b/scripts/listsort.pl new file mode 100644 index 0000000..81b9ab9 --- /dev/null +++ b/scripts/listsort.pl @@ -0,0 +1,60 @@ +use strict; +use warnings; +use Irssi; +use vars qw/$VERSION %IRSSI/; + +$VERSION = '0.1'; +%IRSSI = ( +    authors     => 'Isaac Good', +    name        => 'listsort', +    contact     => 'irssi@isaacgood.com', +    decsription => 'Sort the /list output by channel size', +    license     => 'BSD', +    url         => 'https://github.com/IsaacG/irssi-scripts', +    created     => '2013/02/23', +); + +# Bindings. Start of channel list, end of list, list item. +Irssi::signal_add_last('event 322', \&list_event); +Irssi::signal_add_last('event 323', \&list_end); + +# Store the channel list between IRC messages +my %list; + +# Store list info in the hash. +sub list_event { +    my ($server, $data, $server_name) = @_; +    my ($meta, $more) = split (/ :/, $data, 2); +    my ($nick, $name, $size) = split (/ /, $meta, 3); +    $list{$name}{'size'} = $size; + +    my $modes = ''; +    $list{$name}{'desc'} = ''; +    if ($more =~ /^[^[]*\[([^]]*)\][^ ]* *([^ ].*)$/) { +        $modes = $1; +        $list{$name}{'desc'} = $2; +    } + +    $modes =~ s/ +$//; +    $list{$name}{'modes'} = $modes; +} + +# Print out the whole list in sorted order. +sub list_end { +    for my $name (sort {$list{$a}{'size'} <=> $list{$b}{'size'}} keys %list) { +        my $mode = $list{$name}{'modes'}; +        $mode = " ($mode)" if ($mode); +        my $msg = sprintf ( +            "%d %s: %s%s", +            $list{$name}{'size'}, +            $name, +            $list{$name}{'desc'}, +            $mode +        ); + +        Irssi::print($msg, MSGLEVEL_CRAP); +    } +    # Drop the hash values; no point in holding them in memory. +    %list = (); +} + diff --git a/scripts/loadavg.pl b/scripts/loadavg.pl index e9509ed..44e7ac4 100644 --- a/scripts/loadavg.pl +++ b/scripts/loadavg.pl @@ -15,6 +15,7 @@ $VERSION="0.4";  	contact	    => 'aki@evilbsd.info',  	name	    => 'loadavg',  	description => 'display a loadavg statusbar item using vm.loadavg mib or /proc/loadavg', +	sbitems	    => 'loadavg',  	license	    => 'public domain',  ); diff --git a/scripts/localize.pl b/scripts/localize.pl index 7aabe9f..b836c92 100644 --- a/scripts/localize.pl +++ b/scripts/localize.pl @@ -60,7 +60,7 @@  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = "2014112501"; +$VERSION = "2017040101";  %IRSSI = (      authors     => "Stefan 'tommie' Tomanek",      contact     => "stefan\@pico.ruhr.de", @@ -511,7 +511,7 @@ sub save_cache {      my $filename = Irssi::settings_get_str('localize_cache_filename');      my $data = Dumper(\%cache);      local *F; -    open(F, '>'.$filename); +    open(F, '>',$filename);      print(F $data);      close(F);      print CLIENTCRAP "%R>>%n localize cache (".scalar(keys(%cache))." entries/".length($data)." bytes) saved to ".$filename; @@ -522,7 +522,7 @@ sub load_cache {      my $filename = Irssi::settings_get_str('localize_cache_filename');      my (%new_cache, $text);      local *F; -    open F, "<".$filename || return; +    open F, "<",$filename || return;      $text .= $_ foreach (<F>);      close(F);      eval { %new_cache = %{ eval "$text" }; }; @@ -561,7 +561,7 @@ sub show_map ($$$) {      my $cmd = Irssi::settings_get_str('localize_xplanet_cmd');      my $file = Irssi::settings_get_str('localize_xplanet_temp_file');      local *F; -    open F, '>'.$file; +    open F, '>',$file;      print F $lat.'	'.$long.'	"'.$nick.'"';      close F;      system("$cmd -markerf $file &"); diff --git a/scripts/logcompress_perl.pl b/scripts/logcompress_perl.pl index 062331e..d75755a 100644 --- a/scripts/logcompress_perl.pl +++ b/scripts/logcompress_perl.pl @@ -4,7 +4,7 @@ use Irssi;  use IO::Compress::Gzip qw(gzip $GzipError);  use vars qw($VERSION %IRSSI); -$VERSION = "0.01"; +$VERSION = "0.02";  %IRSSI = (      authors	=> 'vague',      contact	=> 'vague!#irssi@fgreenode', @@ -12,12 +12,13 @@ $VERSION = "0.01";      description	=> "compress logfiles then they're rotated, modified from original logcompress.pl to use perl modules instead",      license	=> "Public Domain",      url		=> "http://irssi.org/", -    changed	=> "2016-01-31T01:45+0100" +    changed	=> "2017-01-07T12:00+0100"  );  sub sig_rotate {      my $input = $_[0]->{real_fname};      gzip $input => "$input.gz" or Irssi::print(MSGLEVEL_CLIENTERROR, "gzip failed: $GzipError\n"); +    unlink $input if -e "$input.gz";  }  Irssi::signal_add('log rotated', 'sig_rotate'); diff --git a/scripts/mail.pl b/scripts/mail.pl index ded0212..23f99c0 100644 --- a/scripts/mail.pl +++ b/scripts/mail.pl @@ -6,6 +6,7 @@ $VERSION = "2.92";      contact     => "tss\@iki.fi, matti\@hiljanen.com, joost\@carnique.nl, bart\@dreamflow.nl",      name        => "mail",      description => "Fully customizable mail counter statusbar item with multiple mailbox and multiple Maildir support", +    sbitems     => "mail",      license     => "Public Domain",      url         => "http://irssi.org, http://scripts.irssi.de",  ); diff --git a/scripts/mailcheck_imap.pl b/scripts/mailcheck_imap.pl index 868734b..b1ee937 100644 --- a/scripts/mailcheck_imap.pl +++ b/scripts/mailcheck_imap.pl @@ -11,6 +11,7 @@ $VERSION = "0.5";      contact     => "irssi\@icmfp.com",      name        => "mailcheck_imap",      description => "Staturbar item which indicates how many new emails you have in the specified IMAP[S] mailbox", +    sbitems     => "mailcheck_imap",      license     => "GNU GPLv2",      url         => "http://icmfp.com/irssi",  ); diff --git a/scripts/mailcount.pl b/scripts/mailcount.pl index 26977a2..523a463 100644 --- a/scripts/mailcount.pl +++ b/scripts/mailcount.pl @@ -50,6 +50,7 @@ $VERSION = '1.4.5';    contact      => 'derwan@irssi.pl',    name         => 'mailcount',    description  => 'Adds statusbar item mailcount and displays info about new mails', +  sbitems      => 'mailcount',    modules      => 'Mail::MboxParser Digest::MD5',    license      => 'GNU GPL v2',    url          => 'http://derwan.irssi.pl', diff --git a/scripts/mangle.pl b/scripts/mangle.pl index 00158a5..54ff2cc 100644 --- a/scripts/mangle.pl +++ b/scripts/mangle.pl @@ -7,18 +7,21 @@  use strict;  use locale;  use Irssi 20020324; +use Irssi::TextUI;  use POSIX;  use Data::Dumper;  use vars qw($VERSION %IRSSI %HELP %channels %translations); -$VERSION = '2004031701'; +$VERSION = '2017031701';  %IRSSI = (      authors     => 'Szymon Sokol',      contact     => 'szymon@hell.pl',      name        => 'mangle',      description => 'translates your messages into Morse code, rot13 and other sillinesses.', +    sbitems     => 'mangle_sb',      license     => 'GPLv2', -    url         => 'http://irssi.org/scripts/',                                     changed     => $VERSION, +    url         => 'http://irssi.org/scripts/', +    changed     => $VERSION,      modules     => 'Data::Dumper'  );   @@ -192,23 +195,25 @@ sub add_channel ($$) {  sub save_channels {      my $filename = Irssi::settings_get_str('mangle_filename'); -    local *F; -    open F, '>'.$filename; +	my $fo; +    open $fo, '>',$filename;      my $data = Dumper(\%channels); -    print F $data; -    close F; +    print $fo $data; +    close $fo;      print CLIENTCRAP "%R>>%n Mangle channels saved";  }  sub load_channels {      my $filename = Irssi::settings_get_str('mangle_filename');      return unless (-e $filename); -    local *F; -    open F, '<'.$filename; +    my $fi; +    open $fi, '<',$filename;      my $text; -    $text .= $_ foreach <F>; -    no strict "vars"; -    %channels = %{ eval "$text" }; +    $text .= $_ foreach <$fi>; +    #no strict "vars"; +    my $VAR1; +    eval "$text"; +    %channels = %$VAR1;  }  sub mangle_show ($$) { diff --git a/scripts/mirc_colour_popup.pl b/scripts/mirc_colour_popup.pl index c7e3ac7..62ccb10 100644 --- a/scripts/mirc_colour_popup.pl +++ b/scripts/mirc_colour_popup.pl @@ -21,6 +21,7 @@ $VERSION = "1.1"; # 6c78efbfcb07c71      contact     => "michael.kowalchuk\@gmail.com",      name        => "mirc_colour_popup",      description => "Shows a mIRC-style colour popup when you hit ^C.", +    sbitems     => "colours",      license     => "Public Domain",  ); diff --git a/scripts/modelist-r.pl b/scripts/modelist-r.pl index 5834e5e..cce6059 100644 --- a/scripts/modelist-r.pl +++ b/scripts/modelist-r.pl @@ -57,6 +57,7 @@ $VERSION = '0.8.0-rc4';     'name'         => 'modelist-r',     'description'  => 'Cache of invites, ban exceptions and reops in channel. Script commands: '.                       '/si, /se, /sr, /unexcept, /uninvite, /unreop (version only for ircd >= 2.11.0).', +   'sbitems'      => 'modelist',     'license'      => 'GNU GPL v2',     'modules'      => '',     'url'          => 'http://derwan.irssi.pl', diff --git a/scripts/nact.pl b/scripts/nact.pl index f814fb3..7f4cfab 100644 --- a/scripts/nact.pl +++ b/scripts/nact.pl @@ -10,6 +10,7 @@ $VERSION="0.2.6";  	contact=> 'bd@bc-bd.org',  	name=> 'nact',  	description=> 'Adds an item which displays the current network activity. Needs /proc/net/dev.', +	sbitems=> 'nact',  	license=> 'GPL v2 or later',  	url=> 'https://bc-bd.org/svn/repos/irssi/trunk/',  ); diff --git a/scripts/newsline.pl b/scripts/newsline.pl index 0f54eee..b37cfcc 100644 --- a/scripts/newsline.pl +++ b/scripts/newsline.pl @@ -3,7 +3,7 @@  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = '2003021101'; +$VERSION = '2017040101';  %IRSSI = (      authors     => 'Stefan \'tommie\' Tomanek',      contact     => 'stefan@pico.ruhr.de', @@ -287,10 +287,10 @@ sub call_openurl ($) {      my ($url) = @_;      no strict "refs";      # check for a loaded openurl -    if (defined %{ "Irssi::Script::openurl::" }) { -	&{ "Irssi::Script::openurl::launch_url" }($url); +    if (my $code = Irssi::Script::openurl::->can('launch_url')) { +        $code->($url);      } else { -	print CLIENTCRAP "%R>>%n Please install openurl.pl"; +        print CLIENTCRAP "%R>>%n Please install openurl.pl";      }      use strict "refs";  } @@ -377,7 +377,7 @@ sub reload_config() {      my $text;      if (-e $filename) {  	local *F; -	open F, "<".$filename; +	open F, "<",$filename;  	$text .= $_ foreach (<F>);  	close F;  	if ($text) { @@ -402,7 +402,7 @@ sub reload_config() {  sub save_config() {      local *F;      my $filename = Irssi::settings_get_str('newsline_sites_file'); -    open(F, ">$filename"); +    open(F, '>',$filename);      my $dumper = Data::Dumper->new([\%sites], ['sites']);      $dumper->Purity(1)->Deepcopy(1);      my $data = $dumper->Dump; diff --git a/scripts/nicklist.pl b/scripts/nicklist.pl index 0317ba3..477ee2c 100755 --- a/scripts/nicklist.pl +++ b/scripts/nicklist.pl @@ -5,7 +5,7 @@ use strict;  use IO::Handle; # for (auto)flush  use Fcntl; # for sysopen  use vars qw($VERSION %IRSSI); -$VERSION = '0.4.6'; +$VERSION = '0.4.7';  %IRSSI = (  	authors     => 'Wouter Coekaerts',  	contact     => 'coekie@irssi.org', @@ -13,7 +13,7 @@ $VERSION = '0.4.6';  	description => 'draws a nicklist to another terminal, or at the right of your irssi in the same terminal',  	license     => 'GPLv2',  	url         => 'http://wouter.coekaerts.be/irssi', -	changed     => '29/06/2004' +	changed     => '20/03/2017'  );  sub cmd_help { @@ -193,7 +193,7 @@ sub screen_size {  		unless (defined &TIOCGWINSZ) {  			die "Term::ReadKey not found, and ioctl 'workaround' failed. Install the Term::ReadKey perl module to use screen mode.\n";  		} -		open(TTY, "+</dev/tty") or die "No tty: $!"; +		open(TTY, "+<","/dev/tty") or die "No tty: $!";  		unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {  			die "Term::ReadKey not found, and ioctl 'workaround' failed ($!). Install the Term::ReadKey perl module to use screen mode.\n";  		} diff --git a/scripts/nickserv.pl b/scripts/nickserv.pl index c1d9ce8..ff2738d 100644 --- a/scripts/nickserv.pl +++ b/scripts/nickserv.pl @@ -24,7 +24,7 @@ use strict;  use Irssi;  use vars qw($VERSION %IRSSI); -$VERSION = "1.10"; +$VERSION = "1.11";  %IRSSI = (      authors     => 'Geert Hauwaerts', @@ -32,37 +32,47 @@ $VERSION = "1.10";      name        => 'nickserv.pl',      description => 'This script will authorize you into NickServ.',      license     => 'GNU General Public License', -    url         => 'http://irssi.hauwaerts.be/nickserv.pl', +    url         => 'https://github.com/irssi/scripts.irssi.org/blob/master/scripts/nickserv.pl', +    changed     => 'Di 17. Jan 19:32:45 CET 2017',  ); +my $irssidir = Irssi::get_irssi_dir(); +  my @nickservnet = (); -my $nickservnet_file = "nickserv.networks"; +my $nickservnet_file = "$irssidir/nickserv.networks";  my @nickservauth = (); -my $nickservauth_file = "nickserv.auth"; +my $nickservauth_file = "$irssidir/nickserv.auth"; -my $irssidir = Irssi::get_irssi_dir(); +my @nickservpostcmd = (); +my $nickservpostcmd_file = "$irssidir/nickserv.postcmd";  my $help = <<EOF;  Usage: (all on one line)  /NICKSERV [addnet <ircnet> <services\@host>]            [addnick <ircnet> <nickname> <password>] +          [addpostcmd <ircnet> <nickname> <command>]            [delnet <ircnet>]            [delnick <ircnet> <nick>] -          [help listnet listnick] - -addnet:     Add a new network into the NickServ list. -addnick:    Add a new nickname into the NickServ list. -delnet:     Delete a network from the NickServ list. -delnick:    Delete a nickname from the NickServ list. -listnet:    Display the contents of the NickServ network list. -listnick:   Display the contents of the NickServ nickname list. -help:       Display this useful little helptext. +          [delpostcmd <ircnet> <nick>] +          [help listnet listnick listpostcmd] + +addnet:      Add a new network into the NickServ list. +addnick:     Add a new nickname into the NickServ list. +addpostcmd:  Add a new post auth command for nickname into the NickServ list. +delnet:      Delete a network from the NickServ list. +delnick:     Delete a nickname from the NickServ list. +delpostcmd:  Deletes all post auth commands for the given nickame. +listnet:     Display the contents of the NickServ network list. +listnick:    Display the contents of the NickServ nickname list. +listpostcmd: Display the contents of the NickServ postcmd list. +help:        Display this useful little helptext.  Examples: (all on one line)  /NICKSERV addnet Freenode NickServ\@services.  /NICKSERV addnick Freenode Geert mypass +/NICKSERV addpostcmd Freenode Geert ^MSG ChanServ invite #heaven  /NICKSERV delnet Freenode  /NICKSERV delnick Freenode Geert @@ -74,19 +84,25 @@ EOF  Irssi::theme_register([      'nickserv_usage_network', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV addnet ircnet services@host%_".',      'nickserv_usage_nickname', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV addnick ircnet nickname password%_".', +    'nickserv_usage_postcmd', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV addpostcmd ircnet nickname command%_".',      'nickserv_delusage', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV delnet ircnet%_".',      'nickserv_delnickusage', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV delnick ircnet nickname%_".', -    'nickserv_delled', '%R>>%n %_NickServ:%_ Deleted %_$0%_ and his nicknames from the NickServ ircnet list.', -    'nickserv_delled_nick', '%R>>%n %_NickServ:%_ Deleted %_$1%_ from the NickServ list on $0.', +    'nickserv_delpostcmdusage', '%R>>%n %_NickServ:%_ Insufficient parameters: Usage "%_/NICKSERV delpostcmd ircnet nickname%_".', +    'nickserv_delled', '%R>>%n %_NickServ:%_ Deleted %_$0%_ and it\'s nicknames and post commands from the NickServ ircnet list.', +    'nickserv_delled_nick', '%R>>%n %_NickServ:%_ Deleted %_$1%_ and it\'s post commands from the NickServ list on $0.', +    'nickserv_delled_postcmd', '%R>>%n %_NickServ:%_ Deleted all entries for %_$1%_ from the NickServ postcmd list on $0.',      'nickserv_nfound', '%R>>%n %_NickServ:%_ The NickServ ircnet %_$0%_ could not be found.',      'nickserv_nfound_nick', '%R>>%n %_NickServ:%_ The NickServ nickname %_$0%_ could not be found on $1.', +    'nickserv_nfound_postcmd', '%R>>%n %_NickServ:%_ The NickServ post commands for nickname %_$1%_ could not be found on $0.',      'nickserv_usage', '%R>>%n %_NickServ:%_ Insufficient parameters: Use "%_/NICKSERV help%_" for further instructions.',      'nickserv_no_net', '%R>>%n %_NickServ:%_ Unknown Irssi ircnet %_$0%_.',      'nickserv_wrong_host', '%R>>%n %_NickServ:%_ Malformed services hostname %_$0%_.',      'already_loaded_network', '%R>>%n %_NickServ:%_ The ircnet %_$0%_ already exists in the NickServ ircnet list, please remove it first.',      'nickserv_loaded_nick', '%R>>%n %_NickServ:%_ The nickname %_$0%_ already exists in the NickServ authlist on %_$1%_, please remove it first.',      'nickserv_not_loaded_net', '%R>>%n %_NickServ:%_ The ircnet %_$0%_ doesn\'t exists in the NickServ ircnet list, please add it first.', +    'nickserv_not_loaded_nick', '%R>>%n %_NickServ:%_ The nickname %_$0%_ doesn\'t exists in the NickServ authlist on %_$1%_, please add it first.',      'saved_nickname', '%R>>%n %_NickServ:%_ Added nickname %_$1%_ on %_$0%_.', +    'saved_postcmd', '%R>>%n %_NickServ:%_ Added postcmd %_$1%_ on %_$0%_: %_%2%_.',      'network_print', '$[!-2]0 $[20]1 $2',      'password_request', '%R>>%n %_NickServ:%_ Auth Request from NickServ on %_$0%_.',      'password_accepted', '%R>>%n %_NickServ:%_ Password accepted on %_$0%_.', @@ -96,6 +112,9 @@ Irssi::theme_register([      'nickname_print', '$[!-2]0 $[20]1 $[18]2 $3',      'nickname_info', '%_ # Ircnet               Nickname           Password%_',      'nickname_empty', '%R>>%n %_NickServ:%_ Your NickServ authlist is empty.', +    'postcmd_print', '$[!-2]0 $[20]1 $[18]2 $3', +    'postcmd_info', '%_ # Ircnet               Nickname           Postcmd%_', +    'postcmd_empty', '%R>>%n %_NickServ:%_ Your NickServ postcmd list is empty.',      'nickserv_help', '$0',      'saved_network', '%R>>%n %_NickServ:%_ Added services mask "%_$1%_" on %_$0%_.',      'nickserv_loaded', '%R>>%n %_Scriptinfo:%_ Loaded $0 version $1 by $2.' @@ -105,139 +124,171 @@ sub load_nickservnet {      my ($file) = @_; -    @nickservnet = (); +    @nickservnet = load_file($file, sub { +        my $new_nsnet = new_nickserv_network(@_); +        return undef if ($new_nsnet->{name} eq "" || $new_nsnet->{host} eq ""); +        return $new_nsnet; +    }); +} -    if (-e $file) { -        local *F; -        open(F, "<", $file); -        local $/ = "\n"; +sub save_nickservnet { -        while (<F>) { -            chop; -            my $new_nsnet = new_nickserv_network(split("\t")); -   -            if (($new_nsnet->{name} ne "") && ($new_nsnet->{host} ne "")) { -                push(@nickservnet, $new_nsnet); -            } -        } -         -        close(F); -    } +    save_file($nickservnet_file, \@nickservnet, \&nickservnet_as_list);  } -sub save_nickservnet { +sub new_nickserv_network { -    my ($file) = @_; +    return { +        name => shift, +        host => shift +    }; +} -    return unless scalar @nickservnet; # there's nothing to save +sub nickservnet_as_list { -    if (-e $file) { -        local *F; -        open(F, ">", $file); +    my $nickserv_net = shift; -        for (my $n = 0; $n < @nickservnet; ++$n) { -            print(F join("\t", $nickservnet[$n]->{name}, $nickservnet[$n]->{host}) . "\n"); -        } -     -        close(F); -    } else { -        create_network_file($file); -        save_nickservnet($file); -    } +    return ( +      $nickserv_net->{name}, +      $nickserv_net->{host} +    );  } -sub create_network_file { -     +sub load_nickservnick { +      my ($file) = @_; -     -    open(F, ">", $file) or die "Can't create $file. Reason: $!"; + +    @nickservauth = load_file($file, sub { +        my $new_nsnick = new_nickserv_nick(@_); + +        return undef if ($new_nsnick->{ircnet} eq "" || $new_nsnick->{nick} eq "" || $new_nsnick->{pass} eq ""); +        return $new_nsnick; +    });  } -sub new_nickserv_network { +sub save_nickservnick { -    my $nsnet = {}; +    save_file($nickservauth_file, \@nickservauth, \&nickserv_nick_as_list); +} -    $nsnet->{name} = shift; -    $nsnet->{host} = shift; +sub new_nickserv_nick { -    return $nsnet; +    return { +        ircnet    => shift, +        nick      => shift, +        pass      => shift +    };  } -sub load_nickservnick { +sub nickserv_nick_as_list { + +    my $nickserv_nick = shift; +    return ( +        $nickserv_nick->{ircnet}, +        $nickserv_nick->{nick}, +        $nickserv_nick->{pass} +    ); +} + +sub load_nickservpostcmd {      my ($file) = @_; -    @nickservauth = (); +    @nickservpostcmd = load_file($file, sub { +        my $new_postcmd = new_postcmd(@_); -    if (-e $file) { -        local *F; -        open(F, "<" ,$file); -        local $/ = "\n"; +        return undef if ($new_postcmd->{ircnet} eq "" || $new_postcmd->{nick} eq "" || $new_postcmd->{postcmd} eq ""); +        return $new_postcmd; +    }); +} -        while (<F>) { -            chop; -            my $new_nsnick = new_nickserv_nick(split("\t")); -   -            if (($new_nsnick->{ircnet} ne "") && ($new_nsnick->{nick} ne "") && ($new_nsnick->{pass} ne "")) { -                push(@nickservauth, $new_nsnick); -            } -        } -         -        close(F); -    } +sub save_nickservpostcmd { + +    save_file($nickservpostcmd_file, \@nickservpostcmd, \&postcmd_as_list);  } -sub save_nickservnick { +sub new_postcmd { -    my ($file) = @_; +    return { +        ircnet    => shift, +        nick      => shift, +        postcmd   => shift +    }; +} -    return unless scalar @nickservauth; # there's nothing to save +sub postcmd_as_list { +    my $postcmd = shift; -    if (-e $file) { -        local *F; -        open(F, ">", $file); +    return ( +        $postcmd->{ircnet}, +        $postcmd->{nick}, +        $postcmd->{postcmd} +    ); +} -        for (my $n = 0; $n < @nickservauth; ++$n) { -            print(F join("\t", $nickservauth[$n]->{ircnet}, $nickservauth[$n]->{nick}, $nickservauth[$n]->{pass}) . "\n"); -        } -     -        close(F); -    } else { -        create_nick_file($file); -        save_nickservnick($file); +# file: filename to be read +# parse_line_fn: receives array of entries of a single line as input, should +#     return parsed data object or undef in the data is incomplete +# returns: parsed data array +sub load_file { + +  my ($file, $parse_line_fn) = @_; +  my @parsed_data = (); + +  if (-e $file) { +    open(my $fh, "<", $file); +    local $/ = "\n"; + +    while (<$fh>) { +      chomp; +      my $data = $parse_line_fn->(split("\t")); +      push(@parsed_data, $data) if $data;      } -} -sub create_nick_file { -     -    my ($file) = @_; -     -    my $umask = umask 0077; # save old umask -    open(F, ">", $file) or die "Can't create $file. Reason: $!"; -    umask $umask; +    close($fh); +  } + +  return @parsed_data;  } -sub new_nickserv_nick { +# file: filename to be written, is created accessable only by the user +# data_ref: array ref of data entries +# serialize_fn: receives a data reference and should return an array or tuples +#     for that data that will be serialized into one line +sub save_file { + +    my ($file, $data_ref, $serialize_fn) = @_; + +    create_private_file($file) unless -e $file; -    my $nsnick = {}; +    open(my $fh, ">", $file) or die "Can't create $file. Reason: $!"; -    $nsnick->{ircnet} = shift; -    $nsnick->{nick} = shift; -    $nsnick->{pass} = shift; +    for my $data (@$data_ref) { +        print($fh join("\t", $serialize_fn->($data)), "\n"); +    } + +    close($fh); +} -    return $nsnick; +sub create_private_file { + +    my ($file) = @_; +    my $umask = umask 0077; # save old umask +    open(my $fh, ">", $file) or die "Can't create $file. Reason: $!"; +    close($fh); +    umask $umask;  }  sub add_nickname { -     +      my ($network, $nickname, $password) = split(" ", $_[0], 3); -    my ($correct_network, $correct_nickname, $correct_password); +    my ($correct_network, $correct_nickname);      if ($network eq "" || $nickname eq "" || $password eq "") {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage_nickname');          return;      } -     +      if ($network) {          if (!already_loaded_net($network)) {              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_not_loaded_net', $network); @@ -246,7 +297,7 @@ sub add_nickname {              $correct_network = 1;          }      } -     +      if ($nickname) {          if (already_loaded_nick($nickname, $network)) {              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_loaded_nick', $nickname, $network); @@ -255,28 +306,64 @@ sub add_nickname {              $correct_nickname = 1;          }      } -     +      if ($correct_network && $correct_nickname) {          push(@nickservauth, new_nickserv_nick($network, $nickname, $password)); -        save_nickservnick("$irssidir/$nickservauth_file"); -             +        save_nickservnick(); +          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_nickname', $network, $nickname);      }  } +sub add_postcmd { + +    my ($network, $nickname, $postcmd) = split(" ", $_[0], 3); +    my ($correct_network, $correct_nickname); + +    if ($network eq "" || $nickname eq "" || $postcmd eq "") { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage_postcmd'); +        return; +    } + +    if ($network) { +        if (!already_loaded_net($network)) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_not_loaded_net', $network); +            return; +        } else { +            $correct_network = 1; +        } +    } + +    if ($nickname) { +        if (!already_loaded_nick($nickname, $network)) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_not_loaded_nick', $nickname, $network); +            return; +        } else { +            $correct_nickname = 1; +        } +    } + +    if ($correct_network && $correct_nickname) { +        push(@nickservpostcmd, new_postcmd($network, $nickname, $postcmd)); +        save_nickservpostcmd(); + +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_postcmd', $network, $nickname, $postcmd); +    } +} +  sub add_network { -     +      my ($network, $hostname) = split(" ", $_[0], 2);      my ($correct_net, $correct_host); -     +      if ($network eq "" || $hostname eq "") {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_usage_network');          return;      } -     +      if ($network) {          my ($ircnet) = Irssi::chatnet_find($network); -         +          if (!$ircnet) {              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_no_net', $network);              return; @@ -287,7 +374,7 @@ sub add_network {              $correct_net = 1;          }      } -  +      if ($hostname) {          if ($hostname !~ /^[.+a-zA-Z0-9_-]{1,}@[.+a-zA-Z0-9_-]{1,}$/) {              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_wrong_host', $hostname); @@ -296,11 +383,11 @@ sub add_network {              $correct_host = 1;          }      } -     +      if ($correct_net && $correct_host) {          push(@nickservnet, new_nickserv_network($network, $hostname)); -        save_nickservnet("$irssidir/$nickservnet_file"); -             +        save_nickservnet(); +          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'saved_network', $network, $hostname);      }  } @@ -308,56 +395,32 @@ sub add_network {  sub already_loaded_net {      my ($ircnet) = @_; -    my $loaded = check_loaded_net($ircnet); - -    if ($loaded > -1) { -        return 1; -    } -     -    return 0; -} - -sub check_loaded_net { - -    my ($ircnet) = @_;      $ircnet = lc($ircnet); -    for (my $loaded = 0; $loaded < @nickservnet; ++$loaded) { -        return $loaded if (lc($nickservnet[$loaded]->{name}) eq $ircnet); +    for my $loaded (@nickservnet) { +        return 1 if (lc($loaded->{name}) eq $ircnet);      } -     -    return -1; + +    return 0;  }  sub already_loaded_nick { -          my ($nickname, $network) = @_; -    my $loaded = check_loaded_nick($nickname, $network); -     -    if ($loaded > -1) { -        return 1; -    } -     -    return 0 -} -sub check_loaded_nick { -     -    my ($nickname, $network) = @_; -          $nickname = lc($nickname);      $network = lc($network); -     -    for (my $loaded = 0; $loaded < @nickservauth; ++$loaded) { -        return $loaded if (lc($nickservauth[$loaded]->{nick}) eq $nickname && lc ($nickservauth[$loaded]->{ircnet}) eq $network); + +    for my $loaded (@nickservauth) { +        return 1 if (lc($loaded->{nick}) eq $nickname && +                     lc($loaded->{ircnet}) eq $network);      } -     -    return -1; + +    return 0;  }  sub list_net { -     +      if (@nickservnet == 0) {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'network_empty');      } else { @@ -370,7 +433,7 @@ sub list_net {  }  sub list_nick { -     +      if (@nickservauth == 0) {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickname_empty');      } else { @@ -382,8 +445,21 @@ sub list_nick {      }  } +sub list_postcmd { + +    if (@nickservpostcmd == 0) { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'postcmd_empty'); +    } else { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'postcmd_info'); + +        for (my $n = 0; $n < @nickservpostcmd ; ++$n) { +            Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'postcmd_print', $n, $nickservpostcmd[$n]->{ircnet}, $nickservpostcmd[$n]->{nick}, $nickservpostcmd[$n]->{postcmd}); +        } +    } +} +  sub nickserv_notice { -     +      my ($server, $data, $nick, $address) = @_;      my ($target, $text) = $data =~ /^(\S*)\s:(.*)/; @@ -392,14 +468,14 @@ sub nickserv_notice {          if ($text =~ /^(?:If this is your nickname, type|Please identify via|Type) \/msg NickServ (?i:identify)/ || $text =~ /^This nickname is registered and protected.  If it is your/ || $text =~ /This nickname is registered\. Please choose a different nickname/) {              my $password = get_password($server->{tag}, $server->{nick}); -             +              if ($password == -1) {                  Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});                  Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $server->{nick}, $server->{tag});                  Irssi::signal_stop();                  return;              } -             +              Irssi::signal_stop();              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_request', $server->{tag});              $server->command("^MSG NickServ IDENTIFY $password"); @@ -442,6 +518,7 @@ sub nickserv_notice {          } elsif ($text =~ /^Password accepted - you are now recognized/ || $text =~ /^You are now identified for/) {              Irssi::signal_stop();              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_accepted', $server->{tag}); +            run_postcmds($server, $server->{tag}, $server->{nick})          } elsif ($text =~ /^Password Incorrect/ || $text =~ /^Password incorrect./) {              Irssi::signal_stop();              Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'password_wrong', $server->{tag}); @@ -449,24 +526,39 @@ sub nickserv_notice {      }  } +sub run_postcmds { +	my ($server, $ircnet, $nick) = @_; +	return if @nickservpostcmd == 0; + +	for my $cmd (@nickservpostcmd) { +		if ($ircnet eq $cmd->{ircnet} && +        $nick   eq $cmd->{nick} && +        $cmd->{postcmd}) { +			$server->command($cmd->{postcmd}); +		} +	} +} +  sub is_nickserv { -     +      my ($net, $host) = @_;      for (my $loaded = 0; $loaded < @nickservnet; ++$loaded) { -        return 1 if (lc($nickservnet[$loaded]->{name}) eq lc($net) && lc($nickservnet[$loaded]->{host}) eq lc($host)); +        return 1 if (lc($nickservnet[$loaded]->{name}) eq lc($net) && +                     lc($nickservnet[$loaded]->{host}) eq lc($host));      }      return 0;  }  sub get_password { -     +      my ($ircnet, $nick) = @_; -     +      for (my $loaded = 0; $loaded < @nickservauth; ++$loaded) { -        return $nickservauth[$loaded]->{pass} if (lc($nickservauth[$loaded]->{ircnet}) eq lc($ircnet) && lc($nickservauth[$loaded]->{nick}) eq lc($nick)); +        return $nickservauth[$loaded]->{pass} if (lc($nickservauth[$loaded]->{ircnet}) eq lc($ircnet) && +                                                  lc($nickservauth[$loaded]->{nick}) eq lc($nick));      } -     +      return -1;  } @@ -485,47 +577,76 @@ sub del_network {              $ircnetindex = 1;          }      } -     +      if ($ircnetindex) {          @nickservnet = grep {lc($_->{name}) ne lc($ircnet)} @nickservnet;          @nickservauth = grep {lc($_->{ircnet}) ne lc($ircnet)} @nickservauth; +        @nickservpostcmd = grep {lc($_->{ircnet}) ne lc($ircnet)} @nickservpostcmd;          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delled', $ircnet); -        save_nickservnet("$irssidir/$nickservnet_file"); -        save_nickservnick("$irssidir/$nickservauth_file"); +        save_nickservnet(); +        save_nickservnick(); +        save_nickservpostcmd();      } else {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound', $ircnet);      }  }  sub del_nickname { -     +      my ($ircnet, $nickname) = split(" ", $_[0], 2);      my ($nickindex); -     +      if ($ircnet eq "" || $nickname eq "") {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delnickusage');          return;      }      for (my $index = 0; $index < @nickservauth; ++$index) { -        if (lc($nickservauth[$index]->{ircnet}) eq lc($ircnet) && lc($nickservauth[$index]->{nick}) eq lc($nickname)) { +        if (lc($nickservauth[$index]->{ircnet}) eq lc($ircnet) && +            lc($nickservauth[$index]->{nick}) eq lc($nickname)) {              $nickindex = splice(@nickservauth, $index, 1); -        }    +        }      }      if ($nickindex) { +        @nickservpostcmd = grep {lc($_->{ircnet}) ne lc($ircnet) || +                                 lc($_->{nick}) ne lc($nickname)} +                           @nickservpostcmd; +          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delled_nick', $ircnet, $nickname); -        save_nickservnick("$irssidir/$nickservauth_file"); +        save_nickservnick(); +        save_nickservpostcmd();      } else {          Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_nick', $ircnet, $nickname);      }  } +sub del_postcmd { + +    my ($ircnet, $nickname) = split(" ", $_[0], 2); + +    if ($ircnet eq "" || $nickname eq "") { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delpostcmdusage'); +        return; +    } + +    my $size_before = scalar(@nickservpostcmd); +    @nickservpostcmd = grep { !( lc($_->{ircnet}) eq lc($ircnet) && lc($_->{nick}) eq lc($nickname) )} @nickservpostcmd; +    my $size_after = scalar(@nickservpostcmd); + +    if ($size_before != $size_after) { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_delled_postcmd', $ircnet, $nickname); +        save_nickservpostcmd(); +    } else { +        Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_nfound_postcmd', $ircnet, $nickname); +    } +} +  sub nickserv_runsub { -     +      my ($data, $server, $item) = @_;      $data =~ s/\s+$//g; -     +      if ($data) {          Irssi::command_runsub('nickserv', $data, $server, $item);      } else { @@ -533,32 +654,31 @@ sub nickserv_runsub {      }  } -load_nickservnet("$irssidir/$nickservnet_file"); -load_nickservnick("$irssidir/$nickservauth_file"); +load_nickservnet($nickservnet_file); +load_nickservnick($nickservauth_file); +load_nickservpostcmd($nickservpostcmd_file);  Irssi::command_bind('nickserv', 'nickserv_runsub');  Irssi::command_bind('ns', 'nickserv_runsub'); -Irssi::command_bind('nickserv addnet', 'add_network'); -Irssi::command_bind('ns addnet', 'add_network'); - -Irssi::command_bind('nickserv addnick', 'add_nickname'); -Irssi::command_bind('ns addnick', 'add_nickname'); - -Irssi::command_bind('nickserv listnet', 'list_net'); -Irssi::command_bind('ns listnet', 'list_net'); - -Irssi::command_bind('nickserv listnick', 'list_nick'); -Irssi::command_bind('ns listnick', 'list_nick'); - -Irssi::command_bind('nickserv delnet', 'del_network'); -Irssi::command_bind('ns delnet', 'del_network'); - -Irssi::command_bind('nickserv delnick', 'del_nickname'); -Irssi::command_bind('ns delnick', 'del_nickname'); -  Irssi::command_bind('nickserv help' => sub { Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_help', $help) });  Irssi::command_bind('ns help' => sub { Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_help', $help) }); +# "command binding" -> "function name" mapping +for my $cmd (( +  ['addnet'       => 'add_network'], +  ['addnick'      => 'add_nickname'], +  ['addpostcmd'   => 'add_postcmd'], +  ['listnet'      => 'list_net'], +  ['listnick'     => 'list_nick'], +  ['listpostcmd'  => 'list_postcmd'], +  ['delnet'       => 'del_network'], +  ['delnick'      => 'del_nickname'], +  ['delpostcmd'   => 'del_postcmd'], +)) { +  Irssi::command_bind("nickserv $cmd->[0]", $cmd->[1]); +  Irssi::command_bind("ns $cmd->[0]",       $cmd->[1]); +} +  Irssi::signal_add('event notice', 'nickserv_notice');  Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'nickserv_loaded', $IRSSI{name}, $VERSION, $IRSSI{authors}); diff --git a/scripts/niq.pl b/scripts/niq.pl index 479ffcc..ffc71f8 100644 --- a/scripts/niq.pl +++ b/scripts/niq.pl @@ -126,6 +126,7 @@ $VERSION="0.5.7";  	contact=> 'bd@bc-bd.org',  	name=> 'niq',  	description=> 'BitchX like Nickcompletion at line start plus statusbar', +	sbitems=> 'niq',  	license=> 'GPL v2',  	url=> 'https://bc-bd.org/cgi-bin/gitweb.cgi?p=irssi.git;a=summary',  ); diff --git a/scripts/ogg123.pl b/scripts/ogg123.pl index 274ebbd..85a6700 100644 --- a/scripts/ogg123.pl +++ b/scripts/ogg123.pl @@ -64,7 +64,7 @@ sub cmd_ogg123 {  			}  		} -		open (f, $ogg123file) || return; +		open (f,'<', $ogg123file) || return;  		while ($ogg123linha=<f>) {		 diff --git a/scripts/operview.pl b/scripts/operview.pl index 355f14d..6690851 100644 --- a/scripts/operview.pl +++ b/scripts/operview.pl @@ -30,7 +30,8 @@ $rcsid = '$Id: operview.pl,v 1.11 2002/03/30 21:16:06 pasky Exp pasky $';            contact     => 'pasky@ji.cz',            url         => 'http://pasky.ji.cz/~pasky/dev/irssi/',            license     => 'GPLv2, not later', -          description => 'Reformats some server notices, which may come i.e. from &clients or &servers at IRCnet. You can turn the script on/off bytoggling variable mangle_server_notices.' +          description => 'Reformats some server notices, which may come i.e. from &clients or &servers at IRCnet. You can turn the script on/off bytoggling variable mangle_server_notices.', +          sbitems     => 'sclientcount kills',           );  my $mangle_stats_output; diff --git a/scripts/page-c0ffee.pl b/scripts/page-c0ffee.pl index e5ae7da..aa6fe0c 100644 --- a/scripts/page-c0ffee.pl +++ b/scripts/page-c0ffee.pl @@ -2,7 +2,7 @@ use strict;  use vars qw($VERSION %IRSSI);  use Irssi 20020120; -$VERSION = "0.02"; +$VERSION = "0.03";  %IRSSI = (      authors	=> "c0ffee",      contact	=> "c0ffee\@penguin-breeder.org", @@ -10,7 +10,7 @@ $VERSION = "0.02";      description	=> "Adds the /PAGE command to page a nick (use /page nick <text>)... to ignore pages /set pager_mode off",      license	=> "Public Domain",      url		=> "http://www.penguin-breeder.org/?page=irssi", -    changed	=> "Sun Feb 16 11:32 CET 2003", +    changed	=> "2017-03-12",  );  use Irssi::Irc; @@ -45,7 +45,7 @@ sub signal_ctcpmsg {  	my ($server, $data, $nick, $addr, $target) = @_;  	my $pm = Irssi::settings_get_bool('pager_mode');  	my $cmd = Irssi::settings_get_str('pager_cmd'); -	my $answer = 0, $pid; +	my $answer = 0;   	my $rnd = int(rand(65535));  	if ($pm) { @@ -98,7 +98,7 @@ sub cmd_page {  Irssi::signal_add('ctcp msg page', 'signal_ctcpmsg');  Irssi::signal_add('ctcp reply page', 'signal_ctcpmsg_reply');  Irssi::command_bind('page','cmd_page'); -Irssi::settings_add_bool('misc','pager_mode',true); +Irssi::settings_add_bool('misc','pager_mode',1);  Irssi::settings_add_str('misc', 'pager_cmd', "");  # ok, here for the pager_cmd syntax:  # "command [parameters]+" diff --git a/scripts/pager.pl b/scripts/pager.pl index 32f0902..50d7899 100644 --- a/scripts/pager.pl +++ b/scripts/pager.pl @@ -2,14 +2,16 @@  use strict;  use Irssi 20020121.2020 (); -$VERSION = "1.1"; + +use vars qw/$VERSION %IRSSI/; +$VERSION = "1.2";  %IRSSI = (  	  authors     => 'Jean-Yves Lefort',  	  contact     => 'jylefort\@brutele.be',  	  name        => 'pager',  	  description => 'Notifies people if they send you a private message or a DCC chat offer while you are away; runs a shell command configurable via /set if they page you',  	  license     => 'BSD', -	  changed     => '$Date: 2003/01/27 09:45:16 $ ', +	  changed     => '$Date: 2017/03/06 $ ',  );  # note: @@ -33,6 +35,9 @@ $VERSION = "1.1";  #  # changes:  # +#	2017-03-06	release 1.2 +#			* declaration $VERSION %IRSSI +#  #	2003-01-27	release 1.1  #			* notices and commands are now optional  # diff --git a/scripts/perlalias.pl b/scripts/perlalias.pl new file mode 100644 index 0000000..b546688 --- /dev/null +++ b/scripts/perlalias.pl @@ -0,0 +1,288 @@ +=head1 perlalias.pl - Perl-based command aliases for irssi + +This script provides an /alias-like function that uses small pieces of perl code to carry out the commands. + +=head2 Usage + +Install into irssi script directory and /run perlalias and/or put into autorun. + +=head2 Commands + +=over + +=item /perlalias + +Syntax: /perlalias [[[-]<alias>] [<code>]] + +Parameters: A name of the alias and the perl code to execute. + +If you prepend the alias with -, it will remove the alias. + +If you give no arguments, the list of defined aliases will be displayed. + +Description: + +Creates or updates an alias. Like any perl code, multiple statements must be separated using ; characters. +No replacement of parameter values is done: any $text is a perl variable. + +The arguments given to the /alias when typed are put into $_ and are also split on whitespace and put into @_. +In addition, the variables $server and $witem will refer to the active server and window item respectively. + +Examples: + +/PERLALIAS UNACT foreach my $w (Irssi::windows) { $w->activity(0); } + +=back + +=over + +=item /perlunalias + +Syntax: /perlunalias <alias> + +Parameters: The alias to remove. + +Description: + +Removes the given alias. + +=back + +Additionally, all aliases added are linked to perlalias.pl: if it is unloaded, the aliases will be removed. + +Aliases can be saved and reloaded with the usual /save and /reload (including autosave). Saved aliases are loaded at script load. + +=head2 ChangeLog + +=over + +=item 1.0 + +First version. + +=back + +=cut + +use strict; +use warnings FATAL => qw(all); +use Irssi; +use Irssi::Irc; +use Carp (); + +#use Cwd; +use POSIX qw(strftime); + +{ package Irssi::Nick; } # Keeps trying to look for this package but for some reason it doesn't get loaded. + +our $VERSION = '1.2'; +our %IRSSI = ( +	authors => 'aquanight', +	contact => 'aquanight@gmail.com', +	name => 'perlalias', +	description => 'Quickly create commands from short perl blocks', +	license => 'public domain' +	); + +# Bound commands +my %cmds; # Contains command entries. The entry has three items: +	# textcmd => Plaintext of the command to execute, which is used for loading/saving +	# cmpcmd => Compiled command, for executing. +	# tag => Our tag which we need to remove the command + +# Package we execute all the commands within, to keep them away from our bits. +package Irssi::Script::perlalias::aliaspkg { +} + +sub DESTROY { +	Symbol::delete_package("Irssi::Script::perlalias::aliaspkg::"); +} + +# Alias executor +sub exec_perlalias { +	my ($cmd, $data, $server, $witem) = @_; +	exists $cmds{$cmd} or return; +	defined $cmds{$cmd}->{cmpcmd} or return; +	local $_ = $data; +	$cmds{$cmd}->{cmpcmd}->($server, $witem, split / +/, $data); +} + +# Bind a command +sub setup_command { +	my ($cmd, $data) = @_; +	# Compile the script. +	my $code = qq{package Irssi::Scripts::perlalias::aliaspkg;\nno warnings;\nsub {my \$server = shift; my \$witem = shift;\n#line 1 "perlalias $cmd"\n$data}\n}; +	my $proc = eval $code; +	if ($@) { +		Irssi::printformat(MSGLEVEL_CLIENTERROR, perlalias_compile_error => $cmd); +		Irssi::print(MSGLEVEL_CLIENTERROR, $@); +		return ""; +	} +	if (exists($cmds{$cmd})) { +		my $entry = $cmds{$cmd}; +		$entry->{textcmd} = $data; +		$entry->{cmpcmd} = $proc; +	} +	else { +		my $entry = {}; +		my $tag = sub { exec_perlalias $cmd, @_; }; +		foreach my $existing_cmd (Irssi::commands()) { +			if ($existing_cmd->{cmd} eq $cmd) { +				Irssi::print_format(MSGLEVEL_CLIENTERROR, perlalias_cmd_in_use => $cmd); +				return ""; +			} +		} +		$entry->{textcmd} = $data; +		$entry->{cmpcmd} = $proc; +		$entry->{tag} = sub { exec_perlalias $cmd, @_; }; +		Irssi::command_bind($cmd, $entry->{tag}); +		$cmds{$cmd} = $entry; +	} +	return 1; +} + +sub remove_command { +	my ($cmd) = @_; +	if (exists($cmds{$cmd})) { +		my $entry = $cmds{$cmd}; +		$entry->{tag}//die "Missing the tag we need to remove the alias!!!"; +		Irssi::command_unbind($cmd, $entry->{tag}); +		delete $cmds{$cmd}; +		return 1; +	} +	else { +		Irssi::printformat(MSGLEVEL_CLIENTERROR, perlalias_not_found => $cmd); +		return ""; +	} +} + +sub list_commands { +	my ($prefix) = @_; +	my @whichones = sort grep /^\Q$prefix\E/, keys %cmds; +	Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'perlaliaslist_header'); +	for my $name (@whichones) { +		my $entry = $cmds{$name}; +		Irssi::printformat(MSGLEVEL_CLIENTCRAP, perlaliaslist_line => $name, $entry->{textcmd}); +	} +} + +sub cmd_perlalias { +	my ($data, $server, $witem) = @_; +	my ($command, $script) = split /\s+/, $data, 2; +	if (($command//"") eq "") { +		list_commands ""; +	} +	elsif ($command =~ m/^-/) { +		$command = substr($command, 1); +		if (remove_command($command)) { Irssi::printformat(MSGLEVEL_CLIENTNOTICE, perlalias_removed => $command); } +	} +	elsif (($script//"") eq "") { +		list_commands $command; +	} +	else { +		if (setup_command($command, $script)) { Irssi::printformat(MSGLEVEL_CLIENTNOTICE, perlalias_added => $command); } +	} + +} + +sub cmd_perlunalias { +	my ($data, $server, $witem) = @_; +	if (remove_command $data) { Irssi::printformat(MSGLEVEL_CLIENTNOTICE, perlalias_removed => $data); } +} + +sub sig_setup_saved { +	my ($main, $auto) = @_; +	my $file = Irssi::get_irssi_dir() . "/perlalias"; +	open my $fd, '>', $file or return; +	for my $cmd (keys %cmds) { +		my $entry = $cmds{$cmd}; +		printf $fd "%s\t%s\n", $cmd, $entry->{textcmd}; +	} +	close $fd; +} + +sub sig_setup_reread { +	my $file = Irssi::get_irssi_dir() . "/perlalias"; +	open my $fd, "<", $file or return; +	my $ln; +	my %newcmds; +	while (defined($ln = <$fd>)) { +		chomp $ln; +		my ($cmd, $script) = split /\t/, $ln, 2; +		if (exists $newcmds{$cmd}) { +			Irssi::print(MSGLEVEL_CLIENTERROR, "There is a duplicate record in the PerlAlias save file."); +			Irssi::print(MSGLEVEL_CLIENTERROR, "Offending alias: $cmd"); +			Irssi::print(MSGLEVEL_CLIENTERROR, "Previous definition: " . $newcmds{$cmd}); +			Irssi::print(MSGLEVEL_CLIENTERROR, "Duplicate definition: $script"); +		} +		$newcmds{$cmd} = $script; +	} +	# Scrub the existing list. Update existings, remove any that aren't in the config, then we'll add any that's new. +	my @currentcmds = keys %cmds; +	for my $cmd (@currentcmds) { +		if (exists $newcmds{$cmd}) { +			setup_command($cmd, $newcmds{$cmd}); +		} +		else { +			remove_command($cmd); +		} +		delete $newcmds{$cmd}; +	} +	# By this point all that should be in newcmds is any ... new commands. +	for my $cmd (keys %newcmds) { +		setup_command($cmd, $newcmds{$cmd}); +	} +	close $fd; +} + +sub sig_complete_perlalias { +	my ($lst, $win, $word, $line, $want_space) = @_; +	$word//return; +	$line//return; +	$lst//return; +	if ($line ne '') { +		my $def = $cmds{$line}; +		$def//return; +		push @$lst, $def->{textcmd}; +		Irssi::signal_stop(); +	} +	else { +		push @$lst, (grep /^\Q$word\E/i, keys %cmds); +		Irssi::signal_stop(); +	} +} + +sub sig_complete_perlunalias { +	my ($lst, $win, $word, $line, $want_space) = @_; +	$lst//return; +	$word//return; +	push @$lst, (grep /^\Q$word\E/i, keys %cmds); +} + +Irssi::signal_register({"complete command " => [qw(glistptr_char* Irssi::UI::Window string string intptr)]}); +Irssi::signal_add("complete command perlalias" => \&sig_complete_perlalias); +Irssi::signal_add("complete command perlunalias" => \&sig_complete_perlunalias); + +Irssi::signal_add("setup saved" => \&sig_setup_saved); +Irssi::signal_add("setup reread" => \&sig_setup_reread); + +Irssi::command_bind(perlalias => \&cmd_perlalias); +Irssi::command_bind(perlunalias => \&cmd_perlunalias); + +my %formats = ( +	# $0 Name of alias +	'perlalias_compile_error' => '{error Error compiling alias {hilight $0}:}', +	# $0 Name of alias +	'perlalias_exec_error' => '{error Error executing alias {hilight $0}:}', +	'perlalias_cmd_in_use' => 'Command {hilight $0} is already in use', +	'perlalias_added' => 'PerlAlias {hilight $0} added', +	'perlalias_removed' => 'PerlAlias {hilight $0} removed', +	'perlalias_not_found' => 'PerlAlias {hilight $0} not found', +	'perlaliaslist_header' => '%#PerlAliases:', +	# $0 Name of alias, $1 alias text +	'perlaliaslist_line' => '%#$[10]0 $1', +); + +Irssi::theme_register([%formats]); + +sig_setup_reread; diff --git a/scripts/postpone.pl b/scripts/postpone.pl index 72e0a90..11011f2 100644 --- a/scripts/postpone.pl +++ b/scripts/postpone.pl @@ -5,7 +5,7 @@  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = "20030208"; +$VERSION = "20170204";  %IRSSI = (      authors     => "Stefan 'tommie' Tomanek",      contact     => "stefan\@pico.ruhr.de", @@ -37,6 +37,8 @@ sub show_help() {      Display this help  /postpone flush <nick>      Flush postponed messages to <nick> +/postpone discard <nick> +    Discard postponed messages to <nick>  /postpone list      List postponed messages  "; @@ -85,11 +87,11 @@ sub cmd_postpone ($$$) {      my @arg = split(/ /, $args);      if (scalar(@arg) < 1) {  	#foo -    } elsif ($arg[0] eq 'flush' && defined $arg[1]) { +    } elsif (($arg[0] eq 'discard' || $arg[0] eq 'flush') && defined $arg[1]) {  	return unless ($witem && $witem->{type} eq "CHANNEL");  	while (scalar(@{$messages{$server->{tag}}{$witem->{name}}{$arg[1]}}) > 0) {  	    my $msg = pop @{$messages{$server->{tag}}{$witem->{name}}{$arg[1]}}; -	    $server->command('MSG '.$witem->{name}.' '.$msg); +	    $server->command('MSG '.$witem->{name}.' '.$msg) if $arg[0] eq 'flush';  	}      } elsif ($arg[0] eq 'list') {  	my $text; diff --git a/scripts/print_signals.pl b/scripts/print_signals.pl new file mode 100644 index 0000000..dadd9eb --- /dev/null +++ b/scripts/print_signals.pl @@ -0,0 +1,280 @@ +# print_signals.pl — Irssi script to help with inspecting signals +# +# © 2017 martin f. krafft <madduck@madduck.net> +# Released under the MIT licence. +# +### Usage: +# +# /script load print_signals +# +# and then use e.g. tail -F /tmp/irssi_signals.log outside of irssi. +# +### Settings: +# +# /set print_signals_to_file ["/tmp/irssi_signals.log"] +#   Set the file to which to log all signals and their data +# +# /set print_signals_limit_regexp [""] +#   Specify a regexp to limit the signals being captured, e.g. "^window". +#   Default is no limit. +# +# # Please note that exclude takes precedence over limit: +# +# /set print_signals_exclude_regexp ["print text|key press|textbuffer"] +#   Specify a regexp to exclude signals from being captured. Default is not to +#   fire on signals about printing text or key presses. +# + +use strict; +use warnings; +use vars qw($VERSION %IRSSI); +use Irssi; +use Data::Dumper; + +$VERSION = '1.0'; + +%IRSSI = ( +    authors     => 'martin f. krafft', +    contact     => 'madduck@madduck.net', +    name        => 'print signals debugger', +    description => 'hooks into every signal and writes the information provided to a file', +    license     => 'MIT', +    changed     => '2017-02-03' +); + +Irssi::settings_add_str('print_signals', 'print_signals_to_file', '/tmp/irssi_signals.log'); +Irssi::settings_add_str('print_signals', 'print_signals_limit_regexp', ''); +Irssi::settings_add_str('print_signals', 'print_signals_exclude_regexp', +	'print text|key press|textbuffer|rawlog|log written'); + +$Data::Dumper::Sortkeys = 1; +$Data::Dumper::Pad = '     '; + +sub signal_handler { +	my $signal = shift(@_); +	my $limitre = Irssi::settings_get_str('print_signals_limit_regexp'); +	return unless $signal =~ qr/$limitre/; +	my $excludere = Irssi::settings_get_str('print_signals_exclude_regexp'); +	return if $signal =~ qr/$excludere/; +	my @names = shift(@_); +	my @data = shift(@_); +	my $outfile = Irssi::settings_get_str('print_signals_to_file'); +	my $fh; +	if (!open($fh, '>>', $outfile)) { +		Irssi::print("cannot append to log file $outfile while handling signal '$signal'"); +		return; +	}; +	print $fh "\n== $signal ==\n"; +	print $fh Data::Dumper->Dump(@data, @names); +	close($fh); +} + +# TODO: a programmatic way to extract the list of all signals from Irssi +# itself, along with descriptive names of the arguments. +my $signals = <<_END; +# curl -s https://raw.githubusercontent.com/irssi/irssi/master/docs/signals.txt | sed -rne 's,^ ",",p' +"gui exit" +"gui dialog", char *type, char *text +"send command", char *command, SERVER_REC, WI_ITEM_REC +"chat protocol created", CHAT_PROTOCOL_REC +"chat protocol updated", CHAT_PROTOCOL_REC +"chat protocol destroyed", CHAT_PROTOCOL_REC +"channel created", CHANNEL_REC, int automatic +"channel destroyed", CHANNEL_REC +"chatnet created", CHATNET_REC +"chatnet destroyed", CHATNET_REC +"commandlist new", COMMAND_REC +"commandlist remove", COMMAND_REC +"error command", int err, char *cmd +"send command", char *args, SERVER_REC, WI_ITEM_REC +"send text", char *line, SERVER_REC, WI_ITEM_REC +"command "<cmd>, char *args, SERVER_REC, WI_ITEM_REC +"default command", char *args, SERVER_REC, WI_ITEM_REC +"ignore created", IGNORE_REC +"ignore destroyed", IGNORE_REC +"ignore changed", IGNORE_REC +"log new", LOG_REC +"log remove", LOG_REC +"log create failed", LOG_REC +"log locked", LOG_REC +"log started", LOG_REC +"log stopped", LOG_REC +"log rotated", LOG_REC +"log written", LOG_REC, char *line +"module loaded", MODULE_REC, MODULE_FILE_REC +"module unloaded", MODULE_REC, MODULE_FILE_REC +"module error", int error, char *text, char *rootmodule, char *submodule +"tls handshake finished", SERVER_REC, TLS_REC +"nicklist new", CHANNEL_REC, NICK_REC +"nicklist remove", CHANNEL_REC, NICK_REC +"nicklist changed", CHANNEL_REC, NICK_REC, char *old_nick +"nicklist host changed", CHANNEL_REC, NICK_REC +"nicklist gone changed", CHANNEL_REC, NICK_REC +"nicklist serverop changed", CHANNEL_REC, NICK_REC +"pidwait", int pid, int status +"query created", QUERY_REC, int automatic +"query destroyed", QUERY_REC +"query nick changed", QUERY_REC, char *orignick +"window item name changed", WI_ITEM_REC +"query address changed", QUERY_REC +"query server changed", QUERY_REC, SERVER_REC +"rawlog", RAWLOG_REC, char *data +"server looking", SERVER_REC +"server connected", SERVER_REC +"server connecting", SERVER_REC, ulong *ip +"server connect failed", SERVER_REC +"server disconnected", SERVER_REC +"server quit", SERVER_REC, char *msg +"server sendmsg", SERVER_REC, char *target, char *msg, int target_type +"setup changed" +"setup reread", char *fname +"setup saved", char *fname, int autosaved +"ban type changed", char *bantype +"channel joined", CHANNEL_REC +"channel wholist", CHANNEL_REC +"channel sync", CHANNEL_REC +"channel topic changed", CHANNEL_REC +"ctcp msg", SERVER_REC, char *args, char *nick, char *addr, char *target +"ctcp msg "<cmd>, SERVER_REC, char *args, char *nick, char *addr, char *target +"default ctcp msg", SERVER_REC, char *args, char *nick, char *addr, char *target +"ctcp reply", SERVER_REC, char *args, char *nick, char *addr, char *target +"ctcp reply "<cmd>, SERVER_REC, char *args, char *nick, char *addr, char *target +"default ctcp reply", SERVER_REC, char *args, char *nick, char *addr, char *target +"ctcp action", SERVER_REC, char *args, char *nick, char *addr, char *target +"awaylog show", LOG_REC, int away_msgs, int filepos +"server nick changed", SERVER_REC +"event connected", SERVER_REC +"server cap ack "<cmd>, SERVER_REC +"server cap nak "<cmd>, SERVER_REC +"server cap end", SERVER_REC +"server sasl failure", SERVER_REC, char *reason +"server sasl success", SERVER_REC +"server event", SERVER_REC, char *data, char *sender_nick, char *sender_address +"event "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address +"default event", SERVER_REC, char *data, char *sender_nick, char *sender_address +"whois default event", SERVER_REC, char *args, char *sender_nick, char *sender_address +"server incoming", SERVER_REC, char *data +"redir "<cmd>, SERVER_REC, char *args, char *sender_nick, char *sender_address +"server lag", SERVER_REC +"server lag disconnect", SERVER_REC +"massjoin", CHANNEL_REC, GSList of NICK_RECs +"ban new", CHANNEL_REC, BAN_REC +"ban remove", CHANNEL_REC, BAN_REC, char *setby +"channel mode changed", CHANNEL_REC, char *setby +"nick mode changed", CHANNEL_REC, NICK_REC, char *setby, char *mode, char *type +"user mode changed", SERVER_REC, char *old +"away mode changed", SERVER_REC +"netsplit server new", SERVER_REC, NETSPLIT_SERVER_REC +"netsplit server remove", SERVER_REC, NETSPLIT_SERVER_REC +"netsplit new", NETSPLIT_REC +"netsplit remove", NETSPLIT_REC +"dcc ctcp "<cmd>, char *args, DCC_REC +"default dcc ctcp", char *args, DCC_REC +"dcc unknown ctcp", char *args, char *sender, char *sendaddr +"dcc reply "<cmd>, char *args, DCC_REC +"default dcc reply", char *args, DCC_REC +"dcc unknown reply", char *args, char *sender, char *sendaddr +"dcc chat message", DCC_REC, char *msg +"dcc created", DCC_REC +"dcc destroyed", DCC_REC +"dcc connected", DCC_REC +"dcc rejecting", DCC_REC +"dcc closed", DCC_REC +"dcc request", DCC_REC, char *sendaddr +"dcc request send", DCC_REC +"dcc chat message", DCC_REC, char *msg +"dcc transfer update", DCC_REC +"dcc get receive", DCC_REC +"dcc error connect", DCC_REC +"dcc error file create", DCC_REC, char *filename +"dcc error file open", char *nick, char *filename, int errno +"dcc error get not found", char *nick +"dcc error send exists", char *nick, char *filename +"dcc error unknown type", char *type +"dcc error close not found", char *type, char *nick, char *filename +"autoignore new", SERVER_REC, AUTOIGNORE_REC +"autoignore remove", SERVER_REC, AUTOIGNORE_REC +"flood", SERVER_REC, char *nick, char *host, int level, char *target +"notifylist new", NOTIFYLIST_REC +"notifylist remove", NOTIFYLIST_REC +"notifylist joined", SERVER_REC, char *nick, char *user, char *host, char *realname, char *awaymsg +"notifylist away changed", SERVER_REC, char *nick, char *user, char *host, char *realname, char *awaymsg +"notifylist left", SERVER_REC, char *nick, char *user, char *host, char *realname, char *awaymsg +"proxy client connecting", CLIENT_REC +"proxy client connected", CLIENT_REC +"proxy client disconnected", CLIENT_REC +"proxy client command", CLIENT_REC, char *args, char *data +"proxy client dump", CLIENT_REC, char *data +"gui print text", WINDOW_REC, int fg, int bg, int flags, char *text, TEXT_DEST_REC +"gui print text finished", WINDOW_REC +"complete word", GList * of char*, WINDOW_REC, char *word, char *linestart, int *want_space +"irssi init read settings" +"exec new", PROCESS_REC +"exec remove", PROCESS_REC, int status +"exec input", PROCESS_REC, char *text +"message public", SERVER_REC, char *msg, char *nick, char *address, char *target +"message private", SERVER_REC, char *msg, char *nick, char *address, char *target +"message own_public", SERVER_REC, char *msg, char *target +"message own_private", SERVER_REC, char *msg, char *target, char *orig_target +"message join", SERVER_REC, char *channel, char *nick, char *address +"message part", SERVER_REC, char *channel, char *nick, char *address, char *reason +"message quit", SERVER_REC, char *nick, char *address, char *reason +"message kick", SERVER_REC, char *channel, char *nick, char *kicker, char *address, char *reason +"message nick", SERVER_REC, char *newnick, char *oldnick, char *address +"message own_nick", SERVER_REC, char *newnick, char *oldnick, char *address +"message invite", SERVER_REC, char *channel, char *nick, char *address +"message topic", SERVER_REC, char *channel, char *topic, char *nick, char *address +"keyinfo created", KEYINFO_REC +"keyinfo destroyed", KEYINFO_REC +"print text", TEXT_DEST_REC *dest, char *text, char *stripped +"theme created", THEME_REC +"theme destroyed", THEME_REC +"window hilight", WINDOW_REC +"window dehilight", WINDOW_REC +"window activity", WINDOW_REC, int old_level +"window item hilight", WI_ITEM_REC +"window item activity", WI_ITEM_REC, int old_level +"window item new", WINDOW_REC, WI_ITEM_REC +"window item remove", WINDOW_REC, WI_ITEM_REC +"window item moved", WINDOW_REC, WI_ITEM_REC, WINDOW_REC +"window item changed", WINDOW_REC, WI_ITEM_REC +"window item server changed", WINDOW_REC, WI_ITEM_REC +"window created", WINDOW_REC +"window destroyed", WINDOW_REC +"window changed", WINDOW_REC, WINDOW_REC old +"window changed automatic", WINDOW_REC +"window server changed", WINDOW_REC, SERVER_REC +"window refnum changed", WINDOW_REC, int old +"window name changed", WINDOW_REC +"window history changed", WINDOW_REC, char *oldname +"window level changed", WINDOW_REC +"default event numeric", SERVER_REC, char *data, char *nick, char *address +"message irc op_public", SERVER_REC, char *msg, char *nick, char *address, char *target +"message irc own_wall", SERVER_REC, char *msg, char *target +"message irc own_action", SERVER_REC, char *msg, char *target +"message irc action", SERVER_REC, char *msg, char *nick, char *address, char *target +"message irc own_notice", SERVER_REC, char *msg, char *target +"message irc notice", SERVER_REC, char *msg, char *nick, char *address, char *target +"message irc own_ctcp", SERVER_REC, char *cmd, char *data, char *target +"message irc ctcp", SERVER_REC, char *cmd, char *data, char *nick, char *address, char *target +"message irc mode", SERVER_REC, char *channel, char *nick, char *addr, char *mode +"message dcc own", DCC_REC *dcc, char *msg +"message dcc own_action", DCC_REC *dcc, char *msg +"message dcc own_ctcp", DCC_REC *dcc, char *cmd, char *data +"message dcc", DCC_REC *dcc, char *msg +"message dcc action", DCC_REC *dcc, char *msg +"message dcc ctcp", DCC_REC *dcc, char *cmd, char *data +"gui key pressed", int key +"beep" +"gui print text after finished", WINDOW_REC, LINE_REC *line, LINE_REC *prev_line +"gui textbuffer line removed", TEXTBUFFER_VIEW_REC *view, LINE_REC *line, LINE_REC *prev_line +_END + +foreach my $sigline (split(/\n/, $signals)) { +	my ($sig, @args) = split(/, /, $sigline); +	$sig =~ y/"//d; +	Irssi::signal_add_first($sig, sub { +			signal_handler($sig, \@args, \@_); +		} +	); +}; diff --git a/scripts/pushsafer.pl b/scripts/pushsafer.pl new file mode 100644 index 0000000..584f19c --- /dev/null +++ b/scripts/pushsafer.pl @@ -0,0 +1,312 @@ +use strict; +use warnings; + +use Irssi; +use vars qw($VERSION %IRSSI %config); +use LWP::UserAgent; +use Scalar::Util qw(looks_like_number); + +$VERSION = '0.0.1'; + +%IRSSI = ( +    authors => 'Kevin Siml', +    contact => 'kevinsiml@googlemail.com', +    name => 'pushsafer', +    description => 'Push hilights and private messages when away by the pushsafer.com API', +    license => 'BSD', +    url => 'https://www.pushsafer.com', +    changed => "2017-03-31" +); + +my $pushsafer_ignorefile; + + +sub cmd_help { +    my $out = <<'HELP_EOF'; +PUSHIGNORE LIST +PUSHIGNORE ADD <hostmask> +PUSHIGNORE REMOVE <number> + +The mask matches in the format ident@host. Notice that no-ident responses puts +a tilde in front of the ident. + +Examples: +  Will match foo@test.bar.de but *not* ~foo@test.bar.se. +    /PUSHIGNORE ADD foo@*.bar.de   +  Use the list-command to show a list of ignores and the number in front +  combined with remove to delete that mask. +    /PUSHIGNORE REMOVE 2 + +For a list of available settings, run: +  /set pushsafer +HELP_EOF +    chomp $out; +    Irssi::print($out, MSGLEVEL_CLIENTCRAP); +} +sub read_settings { +    $pushsafer_ignorefile = Irssi::settings_get_str('pushsafer_ignorefile'); +} + +sub debug { +    return unless Irssi::settings_get_bool('pushsafer_debug'); +    my $text = shift; +    my @caller = caller(1); +    Irssi::print('From '.$caller[3].': '.$text); +} + +sub send_push { +    my $private_key = Irssi::settings_get_str('pushsafer_key'); +    if (!$private_key) { +        debug('Missing Pushsafer.com private or alias_key.'); +        return; +    } + +    debug('Sending notification.'); +    my ($channel, $text) = @_; +    my $resp = LWP::UserAgent->new()->post( +        'https://www.pushsafer.com/api', [ +            k => $private_key, +            m => $text, +            d => Irssi::settings_get_str('pushsafer_device'), +            s => Irssi::settings_get_str('pushsafer_sound'), +            i => Irssi::settings_get_str('pushsafer_icon'), +            v => Irssi::settings_get_str('pushsafer_vibration'), +            u => Irssi::settings_get_str('pushsafer_url'), +            ut => Irssi::settings_get_str('pushsafer_urltitle'), +            l => Irssi::settings_get_str('pushsafer_time2live'), +            t => $channel +        ] +    ); + +    if ($resp->is_success) { +        debug('Notification successfully sent.'); +    } +    else { +        debug('Notification not sent: '.$resp->decoded_content); +    } +} + +sub msg_pub { +    my ($server, $data, $nick, $address, $target) = @_; +    my $safeNick = quotemeta($server->{nick}); + +    if(check_ignore_channels($target)) { +        return; +    } + +    if(check_ignore($address) || check_away($server)) { +        return; +    } + +    if ($data =~ /$safeNick/i) { +        debug('Got pub msg.'); +        send_push($target, $nick.': '.Irssi::strip_codes($data)); +    } +} + +sub msg_print_text { +    my ($dest, $text, $stripped) = @_; +    my $server = $dest->{server}; +    my $target = $dest->{target}; + +    return if (!$server || !($dest->{level} & MSGLEVEL_HILIGHT)); + +    if(check_ignore_channels($target)) { +        return; +    } + +    if(check_away($server)) { +        return; +    } + +    debug('Got nick highlight'); +    $stripped =~ s/^\s+|\s+$//g; +    send_push($target, $stripped); +} + +sub msg_pri { +    my ($server, $data, $nick, $address) = @_; + +    if(check_ignore($address) || check_away($server)) { +        return; +    } +    debug('Got priv msg.'); +    send_push('Priv, '.$nick, Irssi::strip_codes($data)); +} + +sub msg_kick { +    my ($server, $channel, $nick, $kicker, $address, $reason) = @_; + +    if(check_ignore($address) || check_away($server)) { +        return; +    } + +    if ($nick eq $server->{nick}) { +        debug('Was kicked.'); +        send_push('Kicked: '.$channel, 'Was kicked by: '.$kicker.'. Reason: '.Irssi::strip_codes($reason)); +    } +} + +sub msg_test { +   my ($data, $server, $item) = @_; +   $data =~ s/^([\s]+).*$/$1/; +   my $orig_debug = Irssi::settings_get_bool('pushsafer_debug'); +   Irssi::settings_set_bool('pushsafer_debug', 1); +   debug("Sending test message :" . $data); +   send_push("Test Message", Irssi::strip_codes($data)); +   Irssi::settings_set_bool('pushsafer_debug', $orig_debug); +} + +# check our away status & pushsafer_only_if_away. returns 0 if it's ok to send a message.  +sub check_away { +    my ($server) = @_; +    my $msg_only_if_away = Irssi::settings_get_bool('pushsafer_only_if_away'); +    if ($msg_only_if_away && $server->{usermode_away} != '1') { +        debug("Only sending messages if we're marked as away, and we're not"); +        return 1; +    } +    return 0; +} + +sub check_ignore { +    return 0 unless(Irssi::settings_get_bool('pushsafer_ignore')); +    my @ignores = read_file(); +    return 0 unless(@ignores); +    my ($mask) = @_; + +    foreach (@ignores) { +        $_ =~ s/\./\\./g; +        $_ =~ s/\*/.*?/g; +        if ($mask =~ m/^$_$/i) { +            debug('Ignore matches, not pushing.'); +            return 1; +        } +    } +    return 0; +} + +sub check_ignore_channels { +    my ($target) = @_; +    my @ignore_channels = split(' ', Irssi::settings_get_str('pushsafer_ignorechannels')); +    return 0 unless @ignore_channels; +    if (grep {lc($_) eq lc($target)} @ignore_channels) { +        debug("$target set as ignored channel."); +        return 1; +    } +    return 0; +} + +sub ignore_handler { +    my ($data, $server, $item) = @_; +    $data =~ s/\s+$//g; +    Irssi::command_runsub('pushignore', $data, $server, $item); +} + +sub ignore_unknown { +    cmd_help(); +    Irssi::signal_stop(); # Don't print 'no such command' error. +} + +sub ignore_list { +    my @data = read_file(); +    if (@data) { +        my $i = 1; +        my $out; +        foreach(@data) { +            $out .= $i++.". $_\n"; +        } +        chomp $out; +        Irssi::print($out, MSGLEVEL_CLIENTCRAP); +    } +} + +sub ignore_add { +    my ($data, $server, $item) = @_; +    $data =~ s/^([\s]+).*$/$1/; +    return Irssi::print("No hostmask given.", MSGLEVEL_CLIENTCRAP) unless($data ne ""); + +    my @ignores = read_file(); +    push(@ignores, $data); +    write_file(@ignores); +    Irssi::print("Successfully added '$data'.", MSGLEVEL_CLIENTCRAP); +} + +sub ignore_remove { +    my($num, $server, $item) = @_; +    $num =~ s/^(\d+).*$/$1/; +    return Irssi::print("List-number is needed when removing", MSGLEVEL_CLIENTCRAP) unless(looks_like_number($num)); +    my @ignores = read_file(); +     +    # Index out of range +    return Irssi::print("Number was out of range.", MSGLEVEL_CLIENTCRAP) unless(scalar(@ignores) >= $num); +    delete $ignores[$num-1]; +    write_file(@ignores);  +} + +sub write_file { +    read_settings(); +    my $fp; +    if (!open($fp, ">", $pushsafer_ignorefile)) { +        Irssi::print("Error opening ignore file", MSGLEVEL_CLIENTCRAP); +        return; +    } +    print $fp join("\n", @_); +    close $fp; +} + +sub read_file { +    read_settings(); +    my $fp; +    if (-e $pushsafer_ignorefile) { +        if (!open($fp, "<", $pushsafer_ignorefile)) { +            Irssi::print("Error opening ignore file", MSGLEVEL_CLIENTCRAP); +            return; +        } +    } + +    my @out; +    while (<$fp>) { +        chomp; +        next if $_ eq ''; +        push(@out, $_); +    } +    close $fp; + +    return @out; +} + +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_key', ''); +Irssi::settings_add_bool($IRSSI{'name'}, 'pushsafer_debug', 0); +Irssi::settings_add_bool($IRSSI{'name'}, 'pushsafer_ignore', 1); +Irssi::settings_add_bool($IRSSI{'name'}, 'pushsafer_only_if_away', 0); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_ignorefile', Irssi::get_irssi_dir().'/pushsafer_ignores'); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_ignorechannels', ''); + +# Check the Pushsafer.com API > https://www.pushsafer.com/en/pushapi for replacing params +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_sound', '21'); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_device', ''); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_icon', '25'); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_vibration', '0'); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_url', ''); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_urltitle', ''); +Irssi::settings_add_str($IRSSI{'name'}, 'pushsafer_time2live', ''); + +Irssi::command_bind('help pushignore', \&cmd_help); +Irssi::command_bind('pushignore help', \&cmd_help); +Irssi::command_bind('pushignore add', \&ignore_add); +Irssi::command_bind('pushignore remove', \&ignore_remove); +Irssi::command_bind('pushignore list', \&ignore_list); +Irssi::command_bind('pushignore', \&ignore_handler); +Irssi::command_bind('pushtest', \&msg_test); +Irssi::signal_add_first("default command pushignore", \&ignore_unknown); + + +#Irssi::signal_add_last('message public', 'msg_pub'); +Irssi::signal_add_last('print text', 'msg_print_text'); +Irssi::signal_add_last('message private', 'msg_pri'); +Irssi::signal_add_last('message kick', 'msg_kick'); + +Irssi::print('%Y>>%n '.$IRSSI{name}.' '.$VERSION.' loaded.'); +if (!Irssi::settings_get_str('pushsafer_key')) { +    Irssi::print('%Y>>%n '.$IRSSI{name}.' Pushsafer.com private or alias key is not set, set it with /set pushsafer_key YourPrivateOrAliasKey'); +} diff --git a/scripts/query.pl b/scripts/query.pl index 1d472ea..9d69aad 100644 --- a/scripts/query.pl +++ b/scripts/query.pl @@ -16,7 +16,7 @@ use POSIX;  # ======[ Script Header ]===============================================  use vars qw{$VERSION %IRSSI}; -($VERSION) = '$Revision: 1.24 $' =~ / (\d+\.\d+) /; +($VERSION) = '$Revision: 1.25 $' =~ / (\d+\.\d+) /;  %IRSSI = (  	  name	      => 'query',  	  authors     => 'Peder Stray', @@ -44,7 +44,7 @@ sub load_defaults {      local *FILE;      %defaults = (); -    open FILE, "< $file"; +    open FILE, '<',$file;      while (<FILE>) {  	my($mask,$maxage,$immortal) = split;  	$defaults{$mask}{maxage}   = $maxage; @@ -59,7 +59,7 @@ sub save_defaults {      my $file = Irssi::get_irssi_dir."/query";      local *FILE; -    open FILE, "> $file"; +    open FILE, '>', $file;      for (keys %defaults) {  	my $d = $defaults{$_};  	print FILE join("\t", $_,  diff --git a/scripts/quiz.pl b/scripts/quiz.pl index 09ae726..46e34d8 100644 --- a/scripts/quiz.pl +++ b/scripts/quiz.pl @@ -26,7 +26,7 @@ use strict;  use vars qw($VERSION %IRSSI);  use Irssi 20020217.1542 (); # Version 0.8.1 -$VERSION = "0.7"; +$VERSION = "0.8";  %IRSSI = (  authors     => "Simon Huggins",  contact     => "huggie-irssi\@earth.li", @@ -34,7 +34,7 @@ name        => "Quiz",  description => "Turns irssi into a quiz bot",  license     => "GPLv2",  url         => "http://the.earth.li/~huggie/irssi/", -changed     => "Wed Apr 24 01:12:01 BST 2002", +changed     => "2017-04-03",  );  use Irssi::Irc; @@ -69,7 +69,7 @@ sub load_questions($$) {  	return if $game->{'questions'} and not $force;  	my $file = Irssi::settings_get_str("quiz_file"); -	if (open(QS, "<$file")) { +	if (open(QS, '<',$file)) {  		@{$game->{'questions'}}=<QS>;  		close(QS);  		Irssi::print("Loaded questions"); diff --git a/scripts/quizgr.pl b/scripts/quizgr.pl index 902f435..a2d36df 100644 --- a/scripts/quizgr.pl +++ b/scripts/quizgr.pl @@ -41,7 +41,7 @@ use strict;  use vars qw($VERSION %IRSSI);  use Irssi 20020217.1542 (); # Version 0.8.1 or perhaps get the most up to date irssi version -$VERSION = "0.7GR02"; +$VERSION = "0.7GR03";  %IRSSI = (  authors     => "Athanasius Emilius Arvanitis based on Simon Huggins quiz 0.7",  contact     => "arvan", @@ -77,6 +77,8 @@ sub load_questions($$) {  	my $tag = $game->{'tag'};  	my $channel = $game->{'channel'}; +	$game->{'used_questions'}=[]; +  	my $server = Irssi::server_find_tag($tag);  	if (!defined $server) { @@ -540,7 +542,7 @@ sub check_answer($$$$) {          			#putting it in used  				if (@{$game->{'used_questions'}}){          			${$game->{'usedCounter'}} = @{$game->{'used_questions'}}; -				} else {my ${$game->{'usedCounter'}}=0;} +				} else {${$game->{'usedCounter'}}=0;}          			${$game->{'used_questions'}}[${$game->{'usedCounter'}}]=${$game->{'the_question'}}; @@ -566,7 +568,7 @@ sub check_answer($$$$) {          			#putting it in used  				if (@{$game->{'used_questions'}}){          			${$game->{'usedCounter'}} = @{$game->{'used_questions'}}; -				} else {my ${$game->{'usedCounter'}} =0;} +				} else {${$game->{'usedCounter'}} =0;}          			${$game->{'used_questions'}}[${$game->{'usedCounter'}}]=${$game->{'the_question'}}; diff --git a/scripts/quizmaster-fr.pl b/scripts/quizmaster-fr.pl index 1f5bd7b..c143a09 100644 --- a/scripts/quizmaster-fr.pl +++ b/scripts/quizmaster-fr.pl @@ -3,7 +3,7 @@  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = '20030208+fr'; +$VERSION = '20170403+fr';  %IRSSI = (  	   authors     => 'Stefan \'tommie\' Tomanek',  	   contact     => 'stefan@pico.ruhr.de', @@ -60,7 +60,7 @@ sub draw_box ($$$$) {  sub save_quizfile {      local *F;      my $filename = Irssi::settings_get_str("quizmaster_questions_file"); -    open(F, ">".$filename); +    open(F, '>',$filename);      my $dumper = Data::Dumper->new([\%questions], ['quest']);      $dumper->Purity(1)->Deepcopy(1);      my $data = $dumper->Dump; @@ -75,7 +75,7 @@ sub load_quizfile ($) {      return unless -e $file;      my $text;      local *F; -    open F, $file; +    open F,'<', $file;      $text .= $_ foreach (<F>);      close F;      return unless "$text"; @@ -85,7 +85,7 @@ sub load_quizfile ($) {  sub import_quizfile ($$) {      my ($name, $file) = @_;      local *F; -    open(F, $file); +    open(F,'<', $file);      my @data = <F>;      my @questions;      my $quest = {}; diff --git a/scripts/quizmaster.pl b/scripts/quizmaster.pl index 5aec557..e226075 100644 --- a/scripts/quizmaster.pl +++ b/scripts/quizmaster.pl @@ -2,7 +2,7 @@  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = '20030208'; +$VERSION = '20170403';  %IRSSI = (  	   authors     => 'Stefan \'tommie\' Tomanek',  	   contact     => 'stefan@pico.ruhr.de', @@ -59,7 +59,7 @@ sub draw_box ($$$$) {  sub save_quizfile {      local *F;      my $filename = Irssi::settings_get_str("quizmaster_questions_file"); -    open(F, ">".$filename); +    open(F, ">",$filename);      my $dumper = Data::Dumper->new([\%questions], ['quest']);      $dumper->Purity(1)->Deepcopy(1);      my $data = $dumper->Dump; @@ -74,7 +74,7 @@ sub load_quizfile ($) {      return unless -e $file;      my $text;      local *F; -    open F, $file; +    open F,'<', $file;      $text .= $_ foreach (<F>);      close F;      return unless "$text"; @@ -84,7 +84,7 @@ sub load_quizfile ($) {  sub import_quizfile ($$) {      my ($name, $file) = @_;      local *F; -    open(F, $file); +    open(F,'<', $file);      my @data = <F>;      my @questions;      my $quest = {}; diff --git a/scripts/randaway.pl b/scripts/randaway.pl index 6f63c00..91c8d38 100644 --- a/scripts/randaway.pl +++ b/scripts/randaway.pl @@ -19,7 +19,7 @@ use Irssi 20011116;  use Irssi::Irc;  use vars qw($VERSION %IRSSI); -$VERSION = '1.13'; +$VERSION = '1.14';  %IRSSI = (      authors	=> "Lasse Karstensen",      contact	=> "lkarsten\@stud.ntnu.no", @@ -32,7 +32,7 @@ $VERSION = '1.13';  # file to read random reasons from. It should contain one  # reason at each line, empty lines and lines starting with # is   # skipped. -$reasonfile = Irssi::get_irssi_dir() . "/awayreasons"; +my $reasonfile = Irssi::get_irssi_dir() . "/awayreasons";  my @awayreasons; @@ -46,7 +46,7 @@ sub readreasons {  		# like a read() .. ie, stopping at each \n.  		local $/ = "\n";                  while (<F>) { -		    $reason = $_; +		    my $reason = $_;  		    # remove any naughty linefeeds.  		    chomp($reason); @@ -94,8 +94,8 @@ sub add_reason {  	# adding to current environment.  	push(@awayreasons, $reason);  	# and also saving it for later.   -	open(F, ">>", $reasonsfile); -	print F $reason; +	open(F, ">>", $reasonfile); +	print F $reason,"\n";  	close F;  	Irssi::print("Added: $reason");      } @@ -103,7 +103,7 @@ sub add_reason {  sub reasons {      Irssi::print("Listing current awayreasons"); -    foreach $var (@awayreasons) { +    foreach my $var (@awayreasons) {          Irssi::print("=> \"$var\"");       }  } diff --git a/scripts/reorder.pl b/scripts/reorder.pl index 7bec6b8..ce82fa4 100644 --- a/scripts/reorder.pl +++ b/scripts/reorder.pl @@ -1,150 +1,161 @@ -# Save window layout to an arbitrary file and load layouts upon demand
 -# Useful for being able to temporarily reorder your windows and then reverting to your "normal" layout
 -# Also useful as an easy way to reorder your windows
 -#
 -# A special thanks to billnye, Zed` and Bazerka for their help
 -#
 -# Usage:
 -#  /layout_save filename
 -#    Saves the layout to the textfile "filename.layout"
 -#  /layout_load filename
 -#    Loads the layout from the textfile "filename.layout"
 -#  /set layout_savepath path
 -#    Use to set a default path for layouts
 -#
 -# TODO:
 -#   Check the layout file for a number used twice
 -#
 -
 -use strict;
 -use Irssi;
 -use Data::Dumper;
 -use vars qw($VERSION %IRSSI);
 -
 -%IRSSI = (
 -	authors     => "Isaac G",
 -	contact     => "irssi\@isaac.otherinbox.com",
 -	name        => "reorder",
 -	description => "Reordering windows based on a textfile.",
 -	license     => "GPL",
 -);
 -
 -sub doFilenameFixing
 -{
 -	my ($filename) = @_;
 -	unless ($filename)
 -	{
 -		print "No filename specified!";
 -		return;
 -	}
 -
 -	$filename = glob($filename);
 -
 -	if ($filename =~ /\//)
 -	{
 -		unless ($filename =~ /^\//)
 -		{
 -			print "I don't like /'s in filenames. Unless you want to specify an absolute path.";
 -			return;
 -		}
 -		# Let it go?
 -	}
 -
 -	$filename .= '.layout' unless ($filename =~ /.layout$/);
 -
 -	my $path = Irssi::settings_get_str('layout_savepath');
 -	$path .= '/' unless ($path =~ /\/$/);
 -	$filename = $path . $filename unless ($filename =~ /\//);
 -
 -	return $filename;
 -}
 -
 -sub canReadFile
 -{
 -	my ($filename) = @_;
 -	unless (-f $filename)
 -	{
 -		print "No such file $filename";
 -		return;
 -	}
 -	unless (-r $filename)
 -	{
 -		print "Can not read file $filename";
 -		return;
 -	}
 -	return 1;
 -}
 -
 -# Save a list of refnum and window info to file
 -sub cmd_layout_save
 -{
 -	my ($filename, $data, $more) = @_;
 -	my $FH;
 -
 -	$filename = doFilenameFixing($filename);
 -	return unless ($filename);
 -
 -	unless(open $FH, ">", $filename)
 -	{
 -		print "Can not open $filename";
 -		return;
 -	}
 -
 -	# Order by ref. Print ref and an id tag
 -	for my $win (sort {$a->{'refnum'} <=> $b->{'refnum'}} Irssi::windows())
 -	{
 -		my $id = $win->{'name'} ? $win->{'name'} : $win->{'active'}->{'name'} . ":" . $win->{'active'}->{'server'}->{'tag'};
 -		printf $FH "%d\t%s\n", $win->{'refnum'}, $id;
 -	}
 -	close $FH;
 -	print "Layout saved to $filename";
 -}
 -
 -# Load a list and use it to reorder
 -sub cmd_layout_load
 -{
 -	# Check filename supplied, exists and readable
 -	my ($filename, $data, $more) = @_;
 -	$filename = doFilenameFixing($filename);
 -	return unless ($filename);
 -
 -	return unless canReadFile($filename);
 -
 -	my @layout;
 -	my ($ref, $id, $FH);
 -
 -	# Pull the refnum and id
 -	unless(open $FH, "<", $filename)
 -	{
 -		print "Can not open file $filename.";
 -		return;
 -	}
 -	while (my $line = <$FH>)
 -	{
 -		chomp $line;
 -		my ($ref, $id) = split(/\t/, $line, 2);
 -		next unless ($ref and $id);
 -
 -		push @layout, {refnum => $ref, id => $id};
 -	}
 -	close $FH;
 -
 -	# For each layout item from the file, find the window and set it's ref to that number
 -	for my $position (sort {$a->{'refnum'} <=> $b->{'refnum'}} @layout)
 -	{
 -		for my $win (Irssi::windows())
 -		{
 -			$id = $win->{'name'} ? $win->{'name'} : $win->{'active'}->{'name'} . ":" . $win->{'active'}->{'server'}->{'tag'};
 -			if ($id eq $position->{'id'})
 -			{
 -				$win->set_refnum($position->{'refnum'});
 -				last;
 -			}
 -		}
 -	}
 -}
 -
 -Irssi::settings_add_str('misc', 'layout_savepath', Irssi::get_irssi_dir());
 -
 -Irssi::command_bind( 'layout_save', 'cmd_layout_save' );
 -Irssi::command_bind( 'layout_load', 'cmd_layout_load' );
\ No newline at end of file +# Save window layout to an arbitrary file and load layouts upon demand +# Useful for being able to temporarily reorder your windows and then reverting to your "normal" layout +# Also useful as an easy way to reorder your windows +# +# A special thanks to billnye, Zed` and Bazerka for their help +# +# Usage: +#  /layout_save filename +#    Saves the layout to the textfile "filename.layout" +#  /layout_load filename +#    Loads the layout from the textfile "filename.layout" +# +# TODO: +#   Check the layout file for a number used twice +#   On script load, run a layout_load +#   On channel join, run load: channel joined +# + +use strict; +use Irssi; +use Data::Dumper; +use vars qw($VERSION %IRSSI); +use POSIX 'strftime'; + +%IRSSI = ( +    authors     => "Isaac Good", +    contact     => "irssi\@isaacgood.com", +    name        => "reorder", +    description => "Reordering windows based on a textfile.", +    license     => "GPL", +); +$VERSION = '1.0'; + +# Map user input to a valid filename +sub GetFilename +{ +    my ($filename) = @_; + +    # On no input, use a default filename. +    unless (length($filename)) +    { +        my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +        $filename = POSIX::strftime("%y%m%d", $sec, $min, $hour, $mday, $mon, $year); +        # If you prefer not having datestamped filenames, uncomment: +        # $filename = "default"; +    } + +    # Use glob expansion to match things like ~/ +    my $glob = glob($filename); +    $filename = $glob if $glob; + +    # Only handle directories when using an absolute path. +    if ($filename =~ /\// and $filename !~ /^\//) +    { +        print "I don't like /'s in filenames. Unless you want to specify an absolute path."; +        return; +    } + +    # Add a file extension +    $filename .= '.layout' unless ($filename =~ /\.layout$/); + +    # Use get_irssi_dir() unless using an absolute path +    if ($filename !~ /\//) { +        my $path = Irssi::get_irssi_dir(); +        $path .= '/' unless ($path =~ /\/$/); +        $filename = $path . $filename; +    } + +    return $filename; +} + +# Check a filename exists and can be read. +sub CanReadFile +{ +    my ($filename) = @_; +    unless (-f $filename) +    { +        print "No such file $filename"; +        return 0; +    } +    unless (-r $filename) +    { +        print "Can not read file $filename"; +        return 0; +    } +    return 1; +} + +# Save the current layout to file +sub CmdLayoutSave +{ +    my ($filename, $data, $more) = @_; +    my $FH; + +    $filename = GetFilename($filename); +    return unless ($filename); + +    unless(open $FH, ">", $filename) +    { +        print "Can not open $filename"; +        return; +    } + +    # Order by ref. Print ref and an id tag +    for my $win (sort {$a->{'refnum'} <=> $b->{'refnum'}} Irssi::windows()) +    { +        my $id = $win->{'name'} ? $win->{'name'} : $win->{'active'}->{'name'}; +        my $tag = $win->{'active'}->{'server'}->{'tag'}; +        printf $FH "%d\t%s:%s\n", $win->{'refnum'}, $id, $tag; +    } +    close $FH; +    print "Layout saved to $filename"; +} + +# Load a list and use it to reorder +sub CmdLayoutLoad +{ +    my ($filename, $data, $more) = @_; +    $filename = GetFilename($filename); + +    return unless ($filename); +    return unless CanReadFile($filename); + +    my @layout; +    my ($ref, $id, $tag, $FH); + +    # Pull the refnum and id +    unless(open $FH, "<", $filename) +    { +        print "Can not open file $filename."; +        return; +    } +    while (my $line = <$FH>) +    { +        chomp $line; +        my ($ref, $id) = split(/\t/, $line, 2); +        next unless ($ref and $id); + +        push @layout, {refnum => $ref, id => $id}; +    } +    close $FH; + +    # For each layout item from the file, find the window and set it's ref to that number +    for my $position (sort {$a->{'refnum'} <=> $b->{'refnum'}} @layout) +    { +        for my $win (Irssi::windows()) +        { +            $id = $win->{'name'} ? $win->{'name'} : $win->{'active'}->{'name'}; +            $tag = $win->{'active'}->{'server'}->{'tag'}; +            $id .= ":" . $tag; +            if ($id eq $position->{'id'}) +            { +                $win->set_refnum($position->{'refnum'}); +                last; +            } +        } +    } +} + +Irssi::command_bind( 'layout_save', 'CmdLayoutSave' ); +Irssi::command_bind( 'layout_load', 'CmdLayoutLoad' ); diff --git a/scripts/romajibind.pl b/scripts/romajibind.pl index 36a8276..87aafd7 100644 --- a/scripts/romajibind.pl +++ b/scripts/romajibind.pl @@ -33,6 +33,7 @@ $VERSION = "1.0b";      contact	=> 'v0rbiz@yahoo.com',      name	=> 'romajibind',      description	=> 'Dynamic romaji binds', +    sbitems     => 'ro1_sb',      license	=> 'BSD 2-clause',      url		=> 'http://irssi.org/scripts/'  ); diff --git a/scripts/rotator.pl b/scripts/rotator.pl index 71a0522..905293c 100644 --- a/scripts/rotator.pl +++ b/scripts/rotator.pl @@ -10,6 +10,7 @@ $VERSION="0.2.1";  	contact=> 'bd@bc-bd.org',  	name=> 'rotator',  	description=> 'Displaye a small, changeing statusbar item to show irssi is still running', +	sbitems=> 'rotator',  	license=> 'GPL v2',  	url=> 'https://bc-bd.org/svn/repos/irssi/trunk/',  ); diff --git a/scripts/rud_emotes.pl b/scripts/rud_emotes.pl index e783d75..de55cba 100644 --- a/scripts/rud_emotes.pl +++ b/scripts/rud_emotes.pl @@ -1,4 +1,4 @@ -#    Copyright (C) 2015  Dawid Lekawski +#    Copyright (C) 2016  Dawid Lekawski  #      contact: xxrud0lf@gmail.com  #  #       --- INFORMATION --- @@ -33,7 +33,7 @@  #   notes:  #  #   - script doesn't work with /msg target text; must be typed in a channel -#     or query window +#     or query window (from version 1.10 it works with /me command too)  #  #   - Ctrl+O (ascii 15) at the beggining of your text turns off emote replacing   #     for this text @@ -41,20 +41,31 @@  #   - remeber to escape "\" characters in emotes (just type it twice -> "\\"),  #       take a look at 'shrug' emote for reference  # +# +# +#   -- CHANGES: -- +# +#   - script now works with /me command (action) +# +#   - moved text output messages into nice and clean theme_register +# +#  use strict;  use warnings;  use utf8; -use Irssi qw(signal_add signal_continue command_bind); +use Irssi qw(signal_add signal_continue command_bind theme_register +	printformat); -our $VERSION = "1.00"; +our $VERSION = "1.10";  our %IRSSI = (  	authors		=> "Dawid 'rud0lf' Lekawski",  	contact		=> 'rud0lf/IRCnet; rud0lf/freenode; xxrud0lf@gmail.com',  	name		=> 'emotes script',  	description	=> 'Replaces :emote_name: text in your sent messages into pre-defined emotes (unicode mostly).', -	license		=> 'GPLv3' +	license		=> 'GPLv3', +	changed		=> 'Mon Nov 07 14:54:38 2016'  );  my $pattern = ''; @@ -94,10 +105,18 @@ my %emotes = (      'wink', '◕‿↼',  	'gift', '(´・ω・)っ由',      'success', '(•̀ᴗ•́)و', -	'whatever', '◔_◔' +	'whatever', '◔_◔', +	'run', 'ᕕ(⚆ ʖ̯⚆)ᕗ', +	'rock', '(ツ)\m/'  );  sub init { +	theme_register([ +		'rud_emotes_list', 'List of emotes:', +		'rud_emotes_emote', '* $[!15]0 : $1', +		'rud_emotes_total', 'Total of $0 emotes.' +]);   +    	$pattern = join('|', keys %emotes);  	if ($pattern eq '') {  		$pattern = '!?'; @@ -127,31 +146,28 @@ sub sig_send_text {  	signal_continue($newline, $server, $witem);  } -sub pad { -	my ($txt, $cnt) = @_; +sub sig_command_me { +	my ($line, $server, $witem) = @_; -	if (length($txt) >= $cnt) { -		return $txt; -	}	 -	 -	$txt .= " " x ($cnt - length($txt)); -	return $txt; +	return unless ($witem); +	return unless ($witem->{type} eq "CHANNEL" or $witem->{type} eq "QUERY"); + +	my $newline = process_emotes($line); +	signal_continue($newline, $server, $witem);	  }  sub cmd_emotes {  	my ($data, $server, $witem) = @_; -	 -	Irssi::print('List of emotes:', MSGLEVEL_CLIENTCRAP); + +	printformat(MSGLEVEL_CLIENTCRAP, 'rud_emotes_list');  	foreach my $key (sort(keys %emotes)) { -		my $emote = $emotes{$key}; -		Irssi::print('* '. pad($key, 15) . ' : ' . $emote, MSGLEVEL_CLIENTCRAP); +		printformat(MSGLEVEL_CLIENTCRAP, 'rud_emotes_emote', $key, $emotes{$key});  	}	 -	Irssi::print('Total of '.scalar(keys %emotes).' emotes.', MSGLEVEL_CLIENTCRAP); +	printformat(MSGLEVEL_CLIENTCRAP, 'rud_emotes_total', scalar(keys %emotes));  }  init();  signal_add("send text", "sig_send_text"); +signal_add("command me", "sig_command_me");  command_bind("emotes", "cmd_emotes"); - - diff --git a/scripts/sb_position.pl b/scripts/sb_position.pl index a578094..b362dfe 100644 --- a/scripts/sb_position.pl +++ b/scripts/sb_position.pl @@ -32,6 +32,7 @@ our %IRSSI = (      contact     => 'simon@ruderich.org, shabble+irssi@metavore.org',      name        => 'sb_position',      description => 'Displays current position in scrollback.', +    sbitems     => 'position',      license     => 'GPLv3 or later',      changed     => '2010-12-02'  ); diff --git a/scripts/scroller.pl b/scripts/scroller.pl index 5bc4abb..fbed9c8 100644 --- a/scripts/scroller.pl +++ b/scripts/scroller.pl @@ -28,16 +28,18 @@  use Irssi; +use Irssi::TextUI;  use strict;  use vars qw($VERSION %IRSSI); -$VERSION="0.01"; +$VERSION="0.02";  %IRSSI = (  	authors=> 'Demonen',  	contact=> 'demmydemon@gmail.com',  	name=> 'scroller',  	description=> 'Scrolls specified text on the status bar', +	sbitems=> 'scroller',  	license=> 'Public Domain',  ); @@ -84,7 +86,7 @@ sub scrollerStart() {      Irssi::settings_add_int('misc', 'scrollerSpeed', 200);      $timeout = Irssi::timeout_add(Irssi::settings_get_int('scrollerSpeed'), 'scrollerTimeout' , undef);      Irssi::statusbar_item_register('scroller', '$0', 'scrollerStatusbar'); -    Irssi::command_bind scrollthis => \&scrollthis; +	#Irssi::command_bind scrollthis => \&scrollthis;      Irssi::signal_add('setup changed', 'scrollerUpdate');      &scrollerUpdate();  } diff --git a/scripts/securemsg.pl b/scripts/securemsg.pl index 8557107..bd700bd 100644 --- a/scripts/securemsg.pl +++ b/scripts/securemsg.pl @@ -52,6 +52,7 @@ my $APPVERSION = "Securemsg v2.1";  	  contact	=> "vague`!#irssi\@freenode on irc ",  	  name		=> "securemsg",  	  description	=> "An irssi adaptation of securequery.mrc found in the Acidmax mIRC script. :), now with multiserver support", +	  sbitems       => "securemsg",  	  license	=> "GPLv2",  	  changed	=> "10.09.2007 11:30pm GST"  ); diff --git a/scripts/signal_hilight.pl b/scripts/signal_hilight.pl new file mode 100644 index 0000000..30b7efc --- /dev/null +++ b/scripts/signal_hilight.pl @@ -0,0 +1,140 @@ +# signal_hilight.pl - (c) 2017 John Morrissey <jwm@horde.net> +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +#    * Redistributions of source code must retain the above copyright +#      notice, this list of conditions and the following disclaimer. +#    * Redistributions in binary form must reproduce the above copyright +#      notice, this list of conditions and the following disclaimer in the +#      documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# About +# ===== +# +# When you're away, sends highlighted messages to you via Signal. +# +# +# To use +# ====== +# +# 1. Install signal-cli (https://github.com/AsamK/signal-cli). +# +# 2. Register a new Signal account for this device, or link to an existing +#    one. +# +#    It's better to create a dedicated Signal account to have this script +#    send messages from. This requires a dedicated phone number to receive +#    the verification code text message for the new Signal account. Google +#    Voice numbers are useful here. +# +#    Linking gives the host running irssi the same access to the account +#    (such as reading messages, changing account settings, and more) as the +#    Signal app has on your phone or computer. +# +#    - Register a new account: +#      - signal-cli -u +12128675309 register +#      - Retrieve verification +#      - signal-cli -u +12128675309 verify VERIFICATION-CODE-FROM-SMS +# +#    - Link to an existing account: +#      - signal-cli link -n $(hostname) +#      - qrencode -o device-link-qrcode.png 'tsdevice:/?uuid=...' +#      - View device-link-qrcode.png. +#      - Scan the QR code with the Signal app +#        (Settings -> Linked Devices -> Link New Device). +# +# 3. Load the script and configure: +#    - /script load signal_hilight.pl +#    - /set signal_phonenumber_from +12128675309 +#    - /set signal_phonenumber_to +12128675309 + +use strict; +use warnings; + +use POSIX; + +use Irssi; + +our $VERSION = '1.0'; +our %IRSSI = ( +	author => 'John Morrissey', +	contact => 'jwm@horde.net', +	name => 'signal_hilight', +	description => 'Send highlighted messages via Signal', +	licence => 'BSD', +); + +my $IS_AWAY = 0; + +sub send_notification { +	my ($message) = @_; + +	my $pid = fork(); +	if ($pid > 0) { +		Irssi::pidwait_add($pid); +	} else { +		eval { +			my $from = Irssi::settings_get_str('signal_phonenumber_from'); +			my $to = Irssi::settings_get_str('signal_phonenumber_to'); + +			if ($from && $to && +			    open(SIGNAL_CLI, '|-', "signal-cli -u $from send $to")) { + +				print SIGNAL_CLI "$message"; +				close(SIGNAL_CLI); +			} +		}; +		POSIX::_exit(0); +	} +} + +sub sig_print_text { +	my ($dest, $text, $stripped) = @_; + +	if ($IS_AWAY && +	    ($dest->{level} & MSGLEVEL_PUBLIC) && +	    ($dest->{level} & (MSGLEVEL_HILIGHT|MSGLEVEL_MSGS)) && +	    ($dest->{level} & MSGLEVEL_NOHILIGHT) == 0) { + +		send_notification($dest->{target} . ": $stripped"); +	} +} + +sub sig_message_public { +	my ($server, $msg, $nick, $address, $target) = @_; + +	if ($server->{usermode_away}) { +		$IS_AWAY = 1; +	} else { +		$IS_AWAY = 0; +	} +} + +sub sig_message_private { +	my ($server, $msg, $nick, $address, $target) = @_; + +	if ($server->{usermode_away}) { +		send_notification("$nick: $msg"); +	} +} + +Irssi::signal_add('print text', \&sig_print_text); +Irssi::signal_add_last('message public', \&sig_message_public); +Irssi::signal_add_last('message private', \&sig_message_private); + +Irssi::settings_add_str('misc', 'signal_phonenumber_from', ''); +Irssi::settings_add_str('misc', 'signal_phonenumber_to', ''); diff --git a/scripts/sysinfoplus.pl b/scripts/sysinfoplus.pl index cc82d0d..fc0cff0 100644 --- a/scripts/sysinfoplus.pl +++ b/scripts/sysinfoplus.pl @@ -16,8 +16,10 @@  # -Total amount of memory counts (not the used amount, as before)  # Changelog 2.10 -> 2.20: memory/swap info is displayed now (it was broken previously) and code is properly indented +use strict; +use vars qw/$VERSION %IRSSI/; -$VERSION = "2.20"; +$VERSION = "2.21";  %IRSSI = (  	  authors     => "Juerd, Tronic",  	  contact     => "trn\@iki.fi", @@ -25,7 +27,7 @@ $VERSION = "2.20";  	  description => "Linux system information (with vPenis and other stuff)",  	  license     => "Public Domain",  	  url         => "http://juerd.nl/irssi/", -	  changed     => "Mon Nov 04 15:17:30 EET 2002" +	  changed     => "2017-04-02"  	  );  BEGIN{ @@ -37,7 +39,6 @@ BEGIN{      $console = !!$@;  } -use strict;  # Tronic has no time for maintaining this and Juerd hates braces, so it might be better  # not to expect any new versions ... @@ -51,7 +52,7 @@ sub sysinfo{      $ret = "Host '@uname[1]', running @uname[0] @uname[2] - "; -    open FOO, '/proc/cpuinfo'; +    open FOO,'<', '/proc/cpuinfo';      while (<FOO>){  	/^processor\s*:\s*(\d+)/         ? $ret .= "Cpu$1: "  	  : /^model name\s*:\s*(\w+[ A-Za-z]*)/ ? do { my $t = $1; $t =~ s/\s+$//; $ret .= "$t " } @@ -60,7 +61,7 @@ sub sysinfo{      }      close FOO;      $ret =~ s/( ?)$/;$1/; -    open FOO, '/proc/pci'; +    open FOO,'<', '/proc/pci';      while (<FOO>){  	/^\s*(?:multimedia )?(.*?)( storage| compatible)? controller/i and push @pci, $1;      } diff --git a/scripts/timezones.pl b/scripts/timezones.pl index 74cbd39..eb6d45f 100644 --- a/scripts/timezones.pl +++ b/scripts/timezones.pl @@ -22,6 +22,7 @@ $VERSION = "0.2";      contact     => 'vague!#irssi@freenode on irc',      name        => "timezones",      description => "timezones displayer", +    sbitems     => "timezones",      license     => "Public Domain",      url         => "http://gplus.to/vague",      changed     => "Tue 24 November 16:00:00 CET 2015", diff --git a/scripts/topicsed.pl b/scripts/topicsed.pl index d56ed3d..58d0143 100644 --- a/scripts/topicsed.pl +++ b/scripts/topicsed.pl @@ -4,17 +4,18 @@  # Thanks to Mikael Magnusson for the idea and patch to implement a  # preview functionality. ;]  # - +use strict;  use Irssi; -use vars %IRSSI; +use vars qw/%IRSSI $VERSION/; +$VERSION="0.1";  %IRSSI = (  	authors		=> "Gabor Nyeki",  	contact		=> "bigmac\@vim.hu",  	name		=> "topicsed",  	description	=> "editing channel topics by regexps",  	license		=> "public domain", -	changed		=> "Fri Aug 13 19:27:38 CEST 2004" +	changed		=> "2017-03-18"  ); @@ -32,7 +33,7 @@ sub topicsed {  		return;  	}  	return if (!$server || !$server->{connected} || -		!$winit || $winit->{type} != 'CHANNEL'); +		!$winit || $winit->{type} ne 'CHANNEL');  	my $topic = $winit->{topic};  	my $x = $topic; diff --git a/scripts/trackbar22.pl b/scripts/trackbar22.pl index 30015a2..6c899b6 100644 --- a/scripts/trackbar22.pl +++ b/scripts/trackbar22.pl @@ -96,7 +96,7 @@ use Encode;  use POSIX qw(strftime);  use vars qw($VERSION %IRSSI); -$VERSION = "2.2"; # cb3189a33c8e5f9 +$VERSION = "2.3"; # 45c0adad4366edd  %IRSSI = (      authors     => 'Peter Leurs and Geert Hauwaerts', @@ -106,7 +106,6 @@ $VERSION = "2.2"; # cb3189a33c8e5f9      description => 'Shows a bar where you have last read a window.',      license     => 'GNU General Public License',      url         => 'http://www.pfoe.be/~peter/trackbar/', -    changed     => 'Fri Jan 23 23:59:11 2004',      commands    => 'trackbar',  ); @@ -234,6 +233,7 @@ sub add_one_trackbar {      $win->print(line($win->{width}), MSGLEVEL_NEVER);      $view->set_bookmark_bottom('trackbar');      $unseen_trackbar{ $win->{_irssi} } = 1; +    Irssi::signal_emit("window trackbar added", $win);      $view->redraw;  } @@ -253,6 +253,7 @@ sub win_ignored {      my $view = shift || $win->view;      return 1 unless $view->{buffer}{lines_count};      return 1 if $win->{name} eq '(status)' && !$config{use_status_window}; +    no warnings 'uninitialized';      return 1 if grep { $win->{name} eq $_ || $win->{refnum} eq $_  			   || $win->get_active_name eq $_ } @{ $config{ignore_windows} };      return 0; @@ -271,10 +272,13 @@ sub sig_window_changed {  sub trackbar_update_seen {      my $win = shift;      return unless $win; +    return unless $unseen_trackbar{ $win->{_irssi} }; +      my $view = $win->view;      my $line = $view->get_bookmark('trackbar');      unless ($line) {          delete $unseen_trackbar{ $win->{_irssi} }; +        Irssi::signal_emit("window trackbar seen", $win);          return;      }      my $startline = $view->{startline}; @@ -283,6 +287,7 @@ sub trackbar_update_seen {      if ($startline->{info}{time} < $line->{info}{time}              || $startline->{_irssi} == $line->{_irssi}) {          delete $unseen_trackbar{ $win->{_irssi} }; +        Irssi::signal_emit("window trackbar seen", $win);      }  } @@ -477,6 +482,8 @@ update_config();  Irssi::signal_add_last( 'mainwindow resized' => 'redraw_trackbars')      unless $old_irssi; +Irssi::signal_register({'window trackbar added' => [qw/Irssi::UI::Window/]}); +Irssi::signal_register({'window trackbar seen' => [qw/Irssi::UI::Window/]});  Irssi::signal_register({'gui page scrolled' => [qw/Irssi::UI::Window/]});  Irssi::signal_add_last('gui page scrolled' => 'trackbar_update_seen'); diff --git a/scripts/translit.pl b/scripts/translit.pl index 478dd50..0a01506 100644 --- a/scripts/translit.pl +++ b/scripts/translit.pl @@ -1,7 +1,8 @@  use strict; -use vars qw(%IRSSI); +use vars qw(%IRSSI $VERSION);  use Irssi; +$VERSION = "0.1";  %IRSSI = (    authors     => 'dreg',    contact     => 'dreg@fine.lv', diff --git a/scripts/twprompt.pl b/scripts/twprompt.pl index 0fc490a..30e6e35 100644 --- a/scripts/twprompt.pl +++ b/scripts/twprompt.pl @@ -32,6 +32,7 @@ $VERSION = '1.00';     contact	=> 'jengelbr@yahoo.com',     name	        => 'twprompt.pl',     description	=> 'BitchX\'s CrackRock3 animated prompt bar.', +   sbitems      => 'twprompt',     license	=> 'Public Domain',     changed	=> 'Wed Sep 29 02:58:28 CDT 2004',     url		=> 'http://irssi.darktalker.net'."\n", diff --git a/scripts/twtopic.pl b/scripts/twtopic.pl index 1fbb47f..cea00ee 100644 --- a/scripts/twtopic.pl +++ b/scripts/twtopic.pl @@ -10,6 +10,7 @@ $VERSION = '1.01';     contact	=> 'jengelbr@yahoo.com',     name	        => 'twtopic.pl',     description	=> 'Animated Topic bar.', +   sbitems      => 'twtopic',     license	=> 'Public Domain',     changed	=> 'Sat Nov 20 14:15:18 CST 2004',     url		=> 'http://irssi.darktalker.net'."\n", diff --git a/scripts/usercount.pl b/scripts/usercount.pl index 613da1d..650f9f3 100644 --- a/scripts/usercount.pl +++ b/scripts/usercount.pl @@ -7,6 +7,7 @@ $VERSION = "1.19";      contact     => 'dgl@dgl.cx, tss@iki.fi, georg@boerde.de',      name        => 'usercount',      description => 'Adds a usercount for a channel as a statusbar item', +    sbitems     => 'usercount',      license     => 'GNU GPLv2 or later',      url         => 'http://irssi.dgl.cx/',      changes     => 'Only show halfops if server supports them', diff --git a/scripts/window_switcher.pl b/scripts/window_switcher.pl index 3c4d805..c3e4780 100644 --- a/scripts/window_switcher.pl +++ b/scripts/window_switcher.pl @@ -35,6 +35,7 @@ $VERSION = '1.0';      contact     => 'coekie@irssi.org',      name        => 'window_switcher',      description => 'makes switching windows easy', +    sbitems     => 'window_switcher',      license     => 'GPLv2 or later',      url         => 'http://wouter.coekaerts.be/irssi/',      changed     => '29/07/07' diff --git a/scripts/wordcompletition.pl b/scripts/wordcompletition.pl index 0aa5e52..6dfeb4a 100644 --- a/scripts/wordcompletition.pl +++ b/scripts/wordcompletition.pl @@ -1,9 +1,10 @@  #!/usr/bin/perl  use Irssi;  use DBI; +use DBD::SQLite;  use strict;  use vars qw($VERSION %IRSSI); -$VERSION = "0.1"; +$VERSION = "0.2";  %IRSSI = (      authors     => "Jesper Lindh",      contact     => "rakblad\@midgard.liu.se", @@ -11,28 +12,35 @@ $VERSION = "0.1";      description => "Adds words from IRC to your tab-completion list",      license     => "Public Domain",      url         => "http://midgard.liu.se/~n02jesli/perl/", -    changed     => "2004-03-12" +    changed     => "2017-03-19", +	modules     => "DBD::SQLite"  ); -my ($dsn) = "DBI:mysql:yourdatabase:databashostname"; -my ($user_name) = "yourusername"; -my ($password) = "yourpassword"; + +my $bd= Irssi::get_irssi_dir(); +my $fndb="wordcompletition.db"; +#my ($dsn) = "DBI:mysql:yourdatabase:databashostname"; +my ($dsn) = "DBI:SQLite:dbname=$bd/$fndb"; +my ($user_name) = ""; +my ($password) = "";  my ($dbh, $sth);  my (@ary);  my $query;  my $connect = 1;  $dbh = DBI->connect ($dsn, $user_name, $password, { RaiseError => 1 }); +$dbh->do("create table if not exists words (word varchar(30), prio int)"); +  sub wordsearch  {  	my $sw = shift;  	my @retar;  	my $i = 0; -	$query = qq{ select word from words where word like "$sw%" order by prio desc }; +	$query = qq{ select word from words where word like ? order by prio desc };  	$sth = $dbh->prepare ( $query ); -	$sth->execute(); +	$sth->execute($sw.'%');  	while (@ary = $sth->fetchrow_array ())  	{ -        	$retar[$i++] = join ("", @ary), "\n"; +		push @retar,$ary[0];  	}  	$sth->finish();  	return @retar; @@ -41,9 +49,9 @@ sub wordfind  {  	my $sw = shift;  	my $ret; -	$query = qq{ select word from words where word = "$sw" }; +	$query = qq{ select word from words where word = ? };          $sth = $dbh->prepare ( $query ); -        $sth->execute(); +        $sth->execute($sw);          @ary = $sth->fetchrow_array;          $ret = join ("", @ary), "\n";          $sth->finish(); @@ -53,32 +61,32 @@ sub wordfind  sub wordupdate  {  	my $sw = shift; -	$query = qq { update words set prio = prio + 1 where word = "$sw" }; +	$query = qq { update words set prio = prio + 1 where word = ? };          $sth = $dbh->prepare ( $query ); -        $sth->execute(); +        $sth->execute($sw);          $sth->finish();  };  sub delword  {  	my $sw = shift; -	$query = qq { delete from words where word = "$sw" }; +	$query = qq { delete from words where word = ? };          $sth = $dbh->prepare ( $query ); -        $sth->execute(); +        $sth->execute($sw);          $sth->finish();  };  sub addword  {  	my $sw = shift; -	$query = qq { insert into words values ('$sw', 1) }; +	$query = qq { insert into words values (?, 1) };          $sth = $dbh->prepare ( $query ); -        $sth->execute(); +        $sth->execute($sw);          $sth->finish();  };  sub word_complete  {  	my ($complist, $window, $word, $linestart, $want_space) = @_;          $word =~ s/([^a-zA-Z0-9])//g; -	@$complist = wordsearch($word);	 +		push @$complist , wordsearch($word);	  };  sub word_message  { diff --git a/scripts/xdcc_autoget.pl b/scripts/xdcc_autoget.pl index 57bcf65..dc75716 100644 --- a/scripts/xdcc_autoget.pl +++ b/scripts/xdcc_autoget.pl @@ -54,6 +54,7 @@ $VERSION = "2.1";  %IRSSI = (  	name => "autoget",   	description => "XDCC Autoget, for automated searching and downloading of xdcc packs", +	sbitems => "ag_statusbar",  	license => "BeerWare Version 42",  	changed => "$VERSION",  	authors => "MarshalMeatball", diff --git a/scripts/xetra.pl b/scripts/xetra.pl index 255329a..ae28266 100644 --- a/scripts/xetra.pl +++ b/scripts/xetra.pl @@ -10,6 +10,7 @@ $VERSION = "20030208";      description => "brings the stock exchanges of the world to your irssi",      license     => "GPLv2",      changed     => "$VERSION", +    sbitems     => "xetra",      commands	=> "xetra"  ); | 
