diff options
31 files changed, 2725 insertions, 651 deletions
| diff --git a/_data/scripts.yaml b/_data/scripts.yaml index 4135141..512e454 100644 --- a/_data/scripts.yaml +++ b/_data/scripts.yaml @@ -99,11 +99,11 @@    description: 'Adds a permanent advanced window list on the right or in a status bar.'    filename: adv_windowlist.pl    license: 'GNU GPLv2 or later' -  modified: '2016-02-15 11:38:04' +  modified: '2016-11-01 17:15:32'    modules: Text::CharWidth    name: adv_windowlist    url: http://anti.teamidiot.de/ -  version: '1.2' +  version: '1.3'  -    authors: BC-bd    contact: bd@bc-bd.org @@ -230,10 +230,10 @@    description: 'ASpell spellchecking system for Irssi'    filename: aspell.pl    license: MIT -  modified: '2015-11-16 19:36:52' +  modified: '2016-10-06 17:55:58'    modules: Text::Aspell    name: aspell -  version: 1.6.1 +  version: 1.6.2  -    authors: 'Philipp Haegi'    commands: rotate_dict @@ -837,9 +837,9 @@    description: 'Disconnect from server if SASL authentication fails.'    filename: cap_sasl_fail.pl    license: 'GNU GPLv2 or later' -  modified: '2016-03-24 11:01:05' +  modified: '2017-01-16 16:43:50'    name: cap_sasl_fail -  version: '2.0' +  version: '2.1'  -    authors: ZaMz0n    commands: cddb @@ -873,15 +873,15 @@    url: http://pieter-bas.ijdens.com/irssi/    version: 1.0.0  - -  authors: 'BC-bd, Veli' -  contact: 'bd@bc-bd.org, veli@piipiip.net' +  authors: BC-bd +  contact: bd@bc-bd.org    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>'    filename: chanact.pl    license: 'GNU GPLv2 or later' -  modified: '2016-04-25 18:46:30' +  modified: '2017-02-13 17:21:07'    name: chanact -  url: https://bc-bd.org/svn/repos/irssi/chanact -  version: 0.5.15 +  url: http://bc-bd.org/blog/irssi/ +  version: 0.6.0  -    authors: "Joern 'Wulf' Heissler"    contact: wulf@wulf.eu.org @@ -1068,8 +1068,9 @@    description: 'kicking users for using colors or blinks'    filename: colorkick.pl    license: 'public domain' -  modified: '2014-10-17 20:34:00' +  modified: '2017-03-07 22:28:22'    name: colorkick +  version: '0.1'  -    authors: "Timo 'cras' Sirainen"    contact: tss@iki.fi @@ -1167,6 +1168,15 @@    url: http://www.krukowiecki.net/code/irssi/    version: '0.12'  - +  authors: 'martin f. krafft' +  contact: madduck@madduck.net +  description: 'allows per-channel control over activity indication' +  filename: ctrlact.pl +  license: MIT +  modified: '2017-02-24 07:41:29' +  name: ctrlact +  version: '1.2' +-    authors: "Maciek 'fahren' Freudenheim"    contact: fahren@bochnia.pl    description: 'Usage: /CWHO [-a | -l | -o | -v ] [ mask ]' @@ -1242,8 +1252,9 @@    description: "/dccself ip port, starts a dcc chat with yourself on that \n\t                host/port, best used with /set dcc_autochat_masks."    filename: dccself.pl    license: GPL -  modified: '2008-05-17 17:39:11' +  modified: '2017-03-05 13:58:24'    name: dccself +  version: '0.1'  -    authors: "Matti 'qvr' Hiljanen"    contact: matti\@hiljanen.com @@ -1291,10 +1302,10 @@    description: 'Sends notification using the Desktop Notifications Specification.'    filename: desktop-notify.pl    license: 'GPL v3+' -  modified: '2016-08-04 19:09:35' +  modified: '2017-01-23 21:52:29'    modules: 'Glib::Object::Introspection HTML::Entities'    name: desktop-notify -  version: 1.0.0 +  version: 1.0.1  -    authors: 'Jochem Meyers'    contact: jochem.meyers@gmail.com @@ -1759,9 +1770,9 @@    description: 'Implements /go command that activates a window given a name/partial name. It features a nice completion.'    filename: go.pl    license: 'GPLv2 or later' -  modified: '2014-10-19 15:12:04' +  modified: '2017-02-02 02:40:44'    name: 'go to window' -  version: '1.01' +  version: '1.1'  -    authors: cxreg    contact: cxreg@pobox.com @@ -1939,10 +1950,20 @@    description: 'Print hilighted messages to window named "hilight"'    filename: hilightwin.pl    license: 'Public Domain' -  modified: '2015-11-07 14:09:15' +  modified: '2017-02-10 17:59:58'    name: hilightwin    url: http://irssi.org/ -  version: '0.04' +  version: '0.05' +- +  authors: 'Stefan Heinemann' +  contact: stefan.heinemann@codedump.ch +  description: 'Simple script that highlights URL' +  filename: hilite_url.pl +  license: GPL +  modified: '2017-01-12 12:37:37' +  name: 'hilite url' +  url: http://senseless.codedump.ch +  version: '0.1'  -    authors: 'John Morrissey'    contact: jwm@horde.net @@ -2024,6 +2045,15 @@    url: http://www.musicpd.org    version: 0.0.0n  - +  authors: 'Isaac Good' +  contact: 'irssi@isaacgood.com; irc.freenode.net/yitz' +  description: 'Automatically IDENTIFY when prompted' +  filename: ident.pl +  license: MIT +  modified: '2016-12-06 18:45:34' +  name: ident +  version: '1.0' +-    authors: 'Eric Jansen'    contact: chaos@sorcery.net    description: 'MD5 NickServ identification script for SorceryNet' @@ -2143,10 +2173,10 @@    description: 'This script will join a channel if somebody invites you to it.'    filename: invitejoin.pl    license: 'Public Domain' -  modified: '2004-04-11 12:38:18' +  modified: '2017-01-17 20:26:41'    name: invitejoin.pl -  url: http://irssi.hauwaerts.be/invitejoin.pl -  version: '0.01' +  url: https://github.com/irssi/scripts.irssi.org/blob/master/scripts/invitejoin.pl +  version: '0.02'  -    authors: xlony    contact: anderfdez@yahoo.es @@ -2158,6 +2188,26 @@    name: IPupdate    version: '1.2'  - +  authors: wilk +  contact: http://mail.quizpl.net +  description: 'irssi quiz script' +  filename: iquiz.pl +  license: 'GNU GPL v3 or any later version' +  modified: '2016-10-03 18:26:38' +  name: iQuiz +  url: http://iquiz.quizpl.net +  version: '160919' +- +  authors: wilk +  contact: http://mail.quizpl.net +  description: 'irssi quiz script' +  filename: iquiz_en.pl +  license: 'GNU GPL v3 or any later version' +  modified: '2016-10-03 18:26:38' +  name: iQuiz +  url: http://iquiz.quizpl.net +  version: 160919_en +-    authors: DonRumata    commands: none    contact: rumata@dragons.ru @@ -2532,6 +2582,15 @@    name: listen    version: '0.2'  - +  authors: 'Isaac Good' +  contact: irssi@isaacgood.com +  filename: listsort.pl +  license: BSD +  modified: '2016-12-07 11:32:54' +  name: listsort +  url: https://github.com/IsaacG/irssi-scripts +  version: '0.1' +-    authors: aki    contact: aki@evilbsd.info    description: 'display a loadavg statusbar item using vm.loadavg mib or /proc/loadavg' @@ -2578,10 +2637,10 @@    description: "compress logfiles then they're rotated, modified from original logcompress.pl to use perl modules instead"    filename: logcompress_perl.pl    license: 'Public Domain' -  modified: '2016-01-31 01:51:39' +  modified: '2017-01-07 11:52:46'    name: logcompress_perl    url: http://irssi.org/ -  version: '0.01' +  version: '0.02'  -    authors: ferret    commands: 'logtail, logview' @@ -2747,10 +2806,10 @@    description: 'statusbar item that shows users and limit info in channels'    filename: mh_sbuserinfo.pl    license: BSD -  modified: '2016-01-23 00:22:49' +  modified: '2016-11-07 14:57:43'    name: mh_sbuserinfo    url: 'http://scripts.irssi.org / https://github.com/mh-source/irssi-scripts' -  version: '1.04' +  version: '1.05'  -    authors: 'Michael Hansen'    contact: 'mh on IRCnet #help' @@ -3142,10 +3201,10 @@    description: 'This script will authorize you into NickServ.'    filename: nickserv.pl    license: 'GNU General Public License' -  modified: '2016-04-06 16:03:28' +  modified: '2017-01-17 00:18:42'    name: nickserv.pl -  url: http://irssi.hauwaerts.be/nickserv.pl -  version: '1.10' +  url: https://github.com/irssi/scripts.irssi.org/blob/master/scripts/nickserv.pl +  version: '1.11'  -    authors: BC-bd    contact: bd@bc-bd.org @@ -3461,9 +3520,9 @@    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'    filename: pager.pl    license: BSD -  modified: '2014-10-19 11:54:16' +  modified: '2017-03-06 20:58:29'    name: pager -  version: '1.1' +  version: '1.2'  -    authors: fprintf    contact: fprintf@github.com @@ -3543,6 +3602,15 @@    url: http://wouter.coekaerts.be/irssi/    version: '1.1'  - +  authors: aquanight +  contact: aquanight@gmail.com +  description: 'Quickly create commands from short perl blocks' +  filename: perlalias.pl +  license: 'public domain' +  modified: '2017-02-19 12:53:47' +  name: perlalias +  version: '1.2' +-    authors: 'Adam Duck'    contact: duck@cs.uni-frankfurt.de    description: 'does CTCP SOUNDs and other similar things.' @@ -3570,9 +3638,9 @@    description: 'Postpones messages sent to a splitted user and resends them when the nick rejoins'    filename: postpone.pl    license: GPLv2 -  modified: '2008-05-17 17:39:11' +  modified: '2017-02-04 02:11:54'    name: postpone -  version: '20030208' +  version: '20170204'  -    authors: "Maciek Freudenheim, Marco d'Itri"    contact: 'fahren@bochnia.pl, md@linux.it' @@ -3584,6 +3652,15 @@    url: http://www.linux.it/~md/irssi/    version: '20020128'  - +  authors: 'martin f. krafft' +  contact: madduck@madduck.net +  description: 'hooks into every signal and writes the information provided to a file' +  filename: print_signals.pl +  license: MIT +  modified: '2017-02-03 11:47:17' +  name: 'print signals debugger' +  version: '1.0' +-    authors: 'Cyprien Debu'    contact: frey@notk.org    description: 'Gets new mails from procmail.log file' @@ -3751,13 +3828,14 @@    url: http://irssi.dgl.cx/    version: '1'  - -  authors: 'Isaac G' -  contact: irssi@isaac.otherinbox.com +  authors: 'Isaac Good' +  contact: irssi@isaacgood.com    description: 'Reordering windows based on a textfile.'    filename: reorder.pl    license: GPL -  modified: '2010-02-12 22:42:13' +  modified: '2016-12-06 18:47:28'    name: reorder +  version: '1.0'  -    authors: BC-bd    contact: bd@bc-bd.org @@ -3853,9 +3931,9 @@    description: 'Replaces :emote_name: text in your sent messages into pre-defined emotes (unicode mostly).'    filename: rud_emotes.pl    license: GPLv3 -  modified: '2016-09-17 10:03:31' +  modified: '2016-11-07 15:43:52'    name: 'emotes script' -  version: '1.00' +  version: '1.10'  -    authors: "Johan \"Ion\" Kiviniemi, idea taken from Riku Voipio's sana.pl"    contact: 'ion at hassers.org' @@ -4459,11 +4537,11 @@    description: 'Shows a bar where you have last read a window.'    filename: trackbar22.pl    license: 'GNU General Public License' -  modified: '2015-11-16 19:36:52' +  modified: '2017-01-09 14:35:07'    modules: Text::CharWidth    name: trackbar    url: http://www.pfoe.be/~peter/trackbar/ -  version: '2.2' +  version: '2.3'  -    authors: 'Timo Sirainen'    contact: tss@iki.fi @@ -4480,8 +4558,9 @@    description: translitiratar    filename: translit.pl    license: GPL -  modified: '2008-05-17 17:39:11' +  modified: '2017-03-05 14:29:01'    name: translit +  version: '0.1'  -    authors: 'Wouter Coekaerts'    contact: wouter@coekaerts.be @@ -4937,10 +5016,10 @@    description: 'XDCC Autoget, for automated searching and downloading of xdcc packs'    filename: xdcc_autoget.pl    license: 'BeerWare Version 42' -  modified: '2016-02-09 01:27:46' +  modified: '2016-10-26 19:23:08'    modules: 'File::HomeDir Try::Tiny'    name: autoget -  version: '2.0' +  version: '2.1'  -    authors: "Stefan 'tommie' Tomanek, Obfuscoder"    commands: xdccget diff --git a/_testing/config.yml b/_testing/config.yml index 2b96a25..8764417 100644 --- a/_testing/config.yml +++ b/_testing/config.yml @@ -36,12 +36,10 @@ cpan:  whitelist:    - amaroknp    - babelirc +  - cap_sasl_fail    - cap_sasl -  - cgrep -  - colorkick    - connectcmd    - dau -  - dccself    - dnsspam    - hddtemp    - hitcount @@ -63,19 +61,16 @@ whitelist:    - 'on'    - osd    - page-c0ffee -  - pager    - query    - quizgr    - quizmaster-fr    - quizmaster    - quiz    - randaway -  - reorder    - scroller    - stocks    - sysinfoplus    - topicsed -  - translit    - tvmusor    - wordcompletition    - xetra diff --git a/assets/css/style.css b/assets/css/style.css index fe72819..302d311 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -23,3 +23,12 @@ table.sortable thead {  table.sortable thead th:hover {      opacity: 0.8;  } + +div.instructions input { +    opacity: 0; +    position: fixed; +} +div.instructions label { display: inline; } +input#manual-instructions:checked ~ dl.automatic-instructions, +input#automatic-instructions:checked ~ dl.manual-instructions +{ display: none; } diff --git a/assets/js/votes.js b/assets/js/votes.js index 4fb585d..2fa9097 100644 --- a/assets/js/votes.js +++ b/assets/js/votes.js @@ -1,75 +1,153 @@  (function(document, $){      'use strict';      var jsonpRe = /^\/\*[\s\S]*?\*\/jsonp\(([\s\S]*)\)$/m; +    var ghLimits = {search: {}, core: {}}; +    var stopId = 0; +    var queue = {search: [], core: []}; +    var todo = 1; -    function requestAll(start) { -	$.ajax({ +    function requestLater(what, how, arg) { +	var when = rateTimeout(what); +	if (when >= 0) { +	    var empty = queue[what].length == 0; +	    queue[what].push([how, arg]); +	    if (empty) window.setTimeout(function(){reQueue(what);}, when); +	} else { +	    ghLimits[what].remaining--; +	    how(arg); +	} +    } + +    function reQueue(what) { +	limitsThen(what, function(q) { +	    q.forEach(function(e) { +		requestLater(what, e[0], e[1]); +	    }); +	}, queue[what].splice(0, queue[what].length)); +    } + +    function signalDone() { +	if (!todo) $("#th-votes").html("Votes"); +    } + +    function _jsonpToJson(dta, typ) { +	if (typ == "json") { +	    return dta.replace(jsonpRe, "$1"); +	} +	return dta; +    } + +    function jj(url) { +	return $.ajax({  	    accepts: { json: 'application/vnd.github.squirrel-girl-preview' },  	    dataType: 'json', -	    url: start, +	    url: url + (url.indexOf('callback=') === -1 +			? (url.indexOf('?') === -1 ? '?' : ';') + 'callback=jsonp' +			: ''),  	    jsonp: false,  	    jsonpCallback: 'jsonp', -	    dataFilter: function(dta, typ) { -		if (typ == "json") { -		    return dta.replace(jsonpRe, "$1"); -		} -		return dta; -	    } -	}) -	    .done(function(r) { -		var remaining = r.meta['X-RateLimit-Remaining']; -		var rateReset = r.meta['X-RateLimit-Reset']; -		var timeOut = 0; -		var hasMore = false; -		if (remaining < 10) { -		    timeOut = 1000 + rateReset * 1000 - (new Date() / 1); -		} -		if (timeOut < 0) timeOut = 0; -		if (r.meta.Link) { -		    r.meta.Link.forEach(function(l) { -			if (l[1].rel == "next") { -			    window.setTimeout(function(){requestAll(l[0]);}, timeOut); -			    hasMore = true; -			    return; -			} -		    }); -		} -		if (timeOut > 0) { -		    timeOut += 1000; +	    dataFilter: _jsonpToJson +	}); +    } + +    function searchVotes(url) { +	var start = url.indexOf("//") !== -1 ? url +		: 'https://api.github.com/search/issues?q=votes+in:title+state:closed+type:issue+' +		+ 'repo:' + url + ';sort=updated'; +	jj(start).done(function(r) { +	    var hasMore = fetchNext('search', r.meta, searchVotes); +	    if (hasMore) todo++; +	    r.data.items.forEach(function(e) { +		if (stopId && e.number > stopId) return; +		if (e.title != "votes") return; +		if (e.locked) { stopId = e.number; return; } +		todo++; +		requestLater('core', requestComments, e.comments_url); +		todo++; +		requestLater('core', requestComments, e.comments_url + '?page=2'); +		todo++; +		requestLater('core', requestComments, e.comments_url + '?page=3'); +		//todo++; +		//requestLater('core', requestComments, e.comments_url + '?page=4'); +	    }); +	    todo--; +	    signalDone(); +	}); +    } + +    function rateTimeout(what) { +	if ($.isEmptyObject(ghLimits[what])) return -1; + +	var remaining = ghLimits[what].remaining; +	var rateReset = ghLimits[what].reset; +	var limit = ghLimits[what].limit; + +	var timeOut = -1; +	if (remaining < Math.log(limit) + Math.sqrt(limit)) { +	    timeOut = 1000 + rateReset * 1000 - (new Date() / 1); +	    if (timeOut < -1) timeOut = 0; +	} +	return timeOut; +    } + +    function updateLimits(what, meta) { +	ghLimits[what].remaining = meta['X-RateLimit-Remaining']; +	ghLimits[what].reset = meta['X-RateLimit-Reset']; +    } + +    function fetchNext(what, meta, how) { +	var hasMore = false; +	updateLimits(what, meta); +	if (meta.Link) { +	    meta.Link.forEach(function(l) { +		if (l[1].rel == "next") { +		    hasMore = true; +		    requestLater(what, how, l[0]); +		    return;  		} +	    }); +	} +	return hasMore; +    } -		r.data.forEach(function(e) { -		    e.body = e.body.replace(/\r/g, ""); -		    var redir = e.body.match(/^#(\d+)$/); -		    if (redir) { -			var l = start.replace(/(\/issues\/)\d+(\/comments\?)/, "$1" + redir[1] + "$2").replace(/&.*/, ""); -			window.setTimeout(function(){requestAll(l);}, timeOut); -			hasMore = true; -			return; -		    } -			 -		    var lines = e.body.split("\n"); -		    var script = lines[0].replace(/[^-a-zA-Z0-9_]/g, "_"); -		    if (script == "comment") { -			script = "adv_windowlist_pl"; -		    } -		    var st = "#script-" + script + " .votes"; -		    var row = $(st); -		    if (row.length) { -			var votes = 1+ e.reactions['+1'] - e.reactions['-1']; -			var link = "๏ผ"; -			if (e.reactions['heart'] >= votes) { -			    link = "๐"; -			} -			row.html( "" + votes ); -			 -			row.append("<span><a data-toggle=\"tooltip\" title=\"vote on github\" href=\"" + e.html_url + "\">"+link+"</a></span>"); -		    } -		}); -		if (!hasMore) { -		    $("#th-votes").html("Votes"); +    function requestComments(start) { +	jj(start).done(function(r) { +	    updateLimits('core', r.meta); +	    if (r.meta.status == 403 && !r.meta['X-RateLimit-RateLimit']) { +		requestLater('core', requestComments, start); +		return; +	    } +	    //var hasMore = fetchNext('core', r.meta, requestComments); +	    //if (hasMore) todo++; +	    r.data.some(function(e) { +		e.body = e.body.replace(/\r/g, ""); +		var lines = e.body.split("\n"); +		var redir = e.body.match(/^#(\d+)$/); +		if (redir) return true; +		var script = lines[0].replace(/^## /, "").replace(/[^-a-zA-Z0-9_]/g, "_"); +		var row = $("#script-" + script + " .votes"); +		if (row.length) { +		    var votes = 1+ e.reactions['+1'] - e.reactions['-1']; +		    var link = "๏ผ"; +		    if (e.reactions['heart'] >= votes) link = "๐"; +		    row.html( "" + votes ); +		    row.append("<span><a data-toggle=\"tooltip\" title=\"vote on github\" href=\"" +			       + e.html_url + "\">"+link+"</a></span>");  		} +		return false;  	    }); +	    todo--; +	    signalDone(); +	});      } -    requestAll('https://api.github.com/repos/ailin-nemui/scripts.irssi.org/issues/2/comments?callback=jsonp'); + +    function limitsThen(what, how, arg) { +	jj('https://api.github.com/rate_limit').done(function(r) { +	    ghLimits = r.data.resources; +	    requestLater(what, how, arg); +	}); +    } + +    limitsThen('search', searchVotes, 'ailin-nemui/scripts.irssi.org'); +  })(document, $); @@ -10,7 +10,31 @@ layout: default      </div>      <div class="row"> -        <dl> +      <div class="instructions"> +        <input id="automatic-instructions" type="radio" checked="checked" name="instructions" /> +	<input id="manual-instructions" type="radio" name="instructions" /> +        <dl class="automatic-instructions"> +            <dt>How do I install scripts?</dt> +            <dd>In Irssi, do <code>/run scriptassist</code> (only once per session), then +            <code>/script install <i>scriptname</i></code> . + +            <dt>How do I rerun scripts?</dt> +            <dd>Just do <code>/script load <i>scriptname</i></code> .</dd> + +            <dt>How do I unload scripts?</dt> +            <dd>Just do <code>/script unload <i>scriptname</i></code> .</dd> + +            <dt>How do I run scripts automatically at startup?</dt> +            <dd>Just do <code>/script autorun <i>scriptname</i></code> .</dd> + +	    <dt>Scriptassist does not work for me / I want to do it myself?</dt> +	    <dd><label for="manual-instructions" class="btn-link"> +		View manual instructions.</label></dd> + +            <dt>How do I submit a script to this page?</dt> +            <dd>See information on how to contribute <a href="https://github.com/irssi/scripts.irssi.org">here</a>.</dd> +        </dl> +        <dl class="manual-instructions">              <dt>How do I run scripts?</dt>              <dd>Put them into <code>~/.irssi/scripts/</code> and in irssi do              <code>/script load script.pl</code> . There is a default alias for @@ -32,15 +56,17 @@ layout: default              <dt>Is there an easy way of managing scripts?</dt> <dd>Try              <code>scriptassist.pl</code>, it can update and manage your scripts -            as well as install new ones and search the database.</dd> +            as well as install new ones and search the database. +	    <label for="automatic-instructions" class="btn-link"> +		View instructions when using scriptassist.pl .</label></dd>              <dt>How do I submit a script to this page?</dt>              <dd>See information on how to contribute <a href="https://github.com/irssi/scripts.irssi.org">here</a>.</dd>          </dl> -	 +      </div>          <hr> -        <input type="search" class="light-table-filter form-control" data-table="sortable" data-name="q" placeholder="Filter" style="width: 100%"> +        <input type="search" class="light-table-filter form-control" data-table="sortable" data-name="q" placeholder="Filter" style="width: 100%" autocorrect="off" spellcheck="false">          <table class="table table-striped table-condensed sortable">              <thead>                  <tr> @@ -50,7 +76,7 @@ layout: default                      <th class="sorttable_alpha">Description</th>                      <th class="sorttable_alpha">Authors</th>                      <th class="sorttable_alpha">Modified</th> -                    <th class="sorttable_numeric" id="th-votes">…</th> +                    <th class="sorttable_numeric" id="th-votes">……</th>                  </tr>              </thead>              <tbody> diff --git a/scripts/adv_windowlist.pl b/scripts/adv_windowlist.pl index ee0219b..6285786 100644 --- a/scripts/adv_windowlist.pl +++ b/scripts/adv_windowlist.pl @@ -1,7 +1,7 @@  use strict;  use warnings; -our $VERSION = '1.2'; # 762850b0c2c1d5a +our $VERSION = '1.3'; # 463402cffae35e5  our %IRSSI = (      authors     => 'Nei',      contact     => 'Nei @ anti@conference.jabber.teamidiot.de', @@ -1710,8 +1710,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; @@ -2388,6 +2393,7 @@ UNITCHECK  # Changelog  # ========= +# 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/aspell.pl b/scripts/aspell.pl index b6a254e..71369f3 100644 --- a/scripts/aspell.pl +++ b/scripts/aspell.pl @@ -85,6 +85,7 @@ See README file.  use warnings;  use strict;  use Data::Dumper; +use Encode 'decode';  use Irssi;  use Irssi::Irc;  use Irssi::TextUI; @@ -107,7 +108,7 @@ if ($@ && $@ =~ m/Can't locate/) {  } -our $VERSION = '1.6.1'; +our $VERSION = '1.6.2';  our %IRSSI = (                authors     => 'Isaac Good (yitz_), Tom Feist (shabble)',                contact     => 'irssi@isaacgood.com, shabble+irssi@metavore.org', @@ -306,6 +307,7 @@ sub process_word {          } else {              print_suggestions(); +            highlight_incorrect_word($word_obj);          }      } else { @@ -391,7 +393,8 @@ sub spellcheck_finish {      # stick the cursor at the end of the input line?      my $input = _input(); -    my $end = length($input); +    my $charset = lc Irssi::settings_get_str('term_charset'); +    my $end = length(decode $charset=>$input);      Irssi::gui_input_set_pos($end);  } 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/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/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/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/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/hilightwin.pl b/scripts/hilightwin.pl index 7d70317..2e407fa 100644 --- a/scripts/hilightwin.pl +++ b/scripts/hilightwin.pl @@ -11,7 +11,7 @@ use Irssi;  use POSIX;  use vars qw($VERSION %IRSSI);  -$VERSION = "0.04"; +$VERSION = "0.05";  %IRSSI = (      authors     => "Timo \'cras\' Sirainen, Mark \'znx\' Sangster",      contact     => "tss\@iki.fi, znxster\@gmail.com",  @@ -22,6 +22,26 @@ $VERSION = "0.04";      changed     => "Sun May 25 18:59:57 BST 2008"  ); +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) = @_; @@ -33,7 +53,8 @@ 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'); @@ -49,6 +70,7 @@ 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::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/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/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/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/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/mh_sbuserinfo.pl b/scripts/mh_sbuserinfo.pl index fde7ebc..c9ee211 100644 --- a/scripts/mh_sbuserinfo.pl +++ b/scripts/mh_sbuserinfo.pl @@ -1,8 +1,8 @@  ##############################################################################  # -# mh_sbuserinfo.pl v1.04 (20151225) +# mh_sbuserinfo.pl v1.05 (20161106)  # -# Copyright (c) 2015  Michael Hansen +# Copyright (c) 2015, 2016  Michael Hansen  #  # Permission to use, copy, modify, and distribute this software  # for any purpose with or without fee is hereby granted, provided @@ -25,23 +25,41 @@  # displays in the statusbar the number of users and the limit of the channel,  # with several settings for finetuning:  # -# default settings: [Users: <users>(@<users_op>:+<users_voice>:<users_rest>)/<limit>(<limitusers>)] +# default settings: [Users: <users>(*<users_oper>:@<users_op>:+<users_voice>:<users_rest>)/<limit>(<limitusers>)]  # "/<limit>(<limitusers>)" will only show when there is a limit set.  # "(<limitusers>)" shows the difference between the limit and current  # users (this can be negative if the limit is lower than users)  # +# setting mh_sbuserinfo_format_group_begin (default '(') and +# setting mh_sbuserinfo_format_group_end'  (default ')'); change the characters grouping +# details +# +# setting mh_sbuserinfo_format_sep (default ':'): change the : seperator to another string +# +# setting mh_sbuserinfo_format_div (default '/'): change the / divider to another string +#  # setting mh_sbuserinfo_show_prefix (default 'Users: '): set/unset the prefix  # in the window item  #  # setting mh_sbuserinfo_show_details (default ON): enable/disable showing a -# detailed breakout of users into ops, halfops, voice and normal +# detailed breakout of users into opers, ops, halfops, voice and normal  #  # setting mh_sbuserinfo_show_details_mode (default ON): enable/disable -# prefixing ops, halfops and voice with @%+ when details are enabled +# prefixing opers, ops, halfops and voice with *@%+ when details are enabled +# +# setting mh_sbuserinfo_format_mode_oper  (default '*'), +# setting mh_sbuserinfo_format_mode_op    (default '@'), +# setting mh_sbuserinfo_format_mode_ho    (default '%%'), +# setting mh_sbuserinfo_format_mode_vo    (default '+') and +# setting mh_sbuserinfo_format_mode_other (default ''): change the mode prefix +# for each of oper, op, halfdop, voice and others  #  # setting mh_sbuserinfo_show_details_halfop (default OFF): enable/disable  # showing halfops when details are enabled  # +# setting mh_sbuserinfo_show_details_oper (default ON): enable/disable +# showing opers when details are enabled +#  # setting mh_sbuserinfo_show_details_difference (default ON): enable/disable  # showing the "(<limitusers>)"  # @@ -51,9 +69,13 @@  # setting mh_sbuserinfo_show_warning_limit (default ON): change the colour  # of "<limit>" if channel is above, at or close to the limited amount of users  # -# setting mh_sbuserinfo_show_warning_limit_percent (default 95): number in +# setting mh_sbuserinfo_show_warning_limit_percent (default 0): number in  # percent (0-100) of users relative to the limit before a limit warning is -# triggered +# triggered (if set to 0 see mh_sbuserinfo_show_warning_limit_difference) +# +# setting mh_sbuserinfo_show_warning_limit_difference (default 5): when +# mh_sbuserinfo_show_warning_limit_percent is 0, use this absolute value +# as the difference warning trigger instead of percentage  #  # setting mh_sbuserinfo_warning_format (default '%Y'): the colour used for  # warnings. see http://www.irssi.org/documentation/formats @@ -63,6 +85,15 @@  # see '/help statusbar' for more details and do not forget to '/save'  #  # history: +# +#	v1.05 (20161106) +#		added setting _show_details_oper and supporting code +#		added setting _format_sep and supportingf code +#		added setting _format_div and supporting code +#		added setting _group_begin and _format_group_end and supporting code +#		added setting _format_mode_oper, _format_mode_op, _format_mode_ho, _format_mode_vo and _format_mode_other, and supporting code +#		added settting _show_warning_limit_difference and supporting code (changing _show_warning_limit_percent behavior) +#		changed default of _show_warning_limit_percent from 95 to 0  #	v1.04 (20151225)  #		added setting _show_details_difference and supporting code  #		changed _show_warning_limit_percent default from 90 to 95 @@ -96,7 +127,7 @@ use strict;  use Irssi 20100403;  use Irssi::TextUI; -our $VERSION = '1.04'; +our $VERSION = '1.05';  our %IRSSI   =  (  	'name'        => 'mh_sbuserinfo', @@ -105,7 +136,7 @@ our %IRSSI   =  	'authors'     => 'Michael Hansen',  	'contact'     => 'mh on IRCnet #help',  	'url'         => 'http://scripts.irssi.org / https://github.com/mh-source/irssi-scripts', -	'changed'     => 'Fri Dec 25 17:14:34 CET 2015', +	'changed'     => 'Sun Nov  6 20:37:05 CET 2016',  );  ############################################################################## @@ -183,6 +214,7 @@ sub statusbar_userinfo  			my $users_op       = 0;  			my $users_ho       = 0;  			my $users_vo       = 0; +			my $users_oper     = 0;  			my $warning_format = Irssi::settings_get_str('mh_sbuserinfo_warning_format');  			for my $nick ($channel->nicks()) @@ -201,56 +233,84 @@ sub statusbar_userinfo  				{  					$users_vo++;  				} + +				if ($nick->{'serverop'}) +				{ +					$users_oper++; +				}  			} -			$format = $format . $users; +			$format .= $users; + +			my $format_sep = Irssi::settings_get_str('mh_sbuserinfo_format_sep'); +			my $format_div = Irssi::settings_get_str('mh_sbuserinfo_format_div'); + +			my $format_group_begin = Irssi::settings_get_str('mh_sbuserinfo_format_group_begin'); +			my $format_group_end   = Irssi::settings_get_str('mh_sbuserinfo_format_group_end');  			if (Irssi::settings_get_bool('mh_sbuserinfo_show_details'))  			{ -				$format = $format . '('; +				$format .= $format_group_begin;  				my $showmode = Irssi::settings_get_bool('mh_sbuserinfo_show_details_mode'); +				if (Irssi::settings_get_bool('mh_sbuserinfo_show_details_oper')) +				{ +					if ($showmode) +					{ +						$format .= Irssi::settings_get_str('mh_sbuserinfo_format_mode_oper'); +					} + +					$format .= $users_oper . $format_sep +				} +  				if (Irssi::settings_get_bool('mh_sbuserinfo_show_warning_opless') and (not $users_op))  				{ -					$format = $format . $warning_format; +					$format .= $warning_format;  				}  				if ($showmode)  				{ -					$format = $format . '@'; +					$format .= Irssi::settings_get_str('mh_sbuserinfo_format_mode_op');  				} -				$format = $format . $users_op . '%n:'; +				$format .= $users_op . '%n' . $format_sep;  				if (Irssi::settings_get_bool('mh_sbuserinfo_show_details_halfop'))  				{  					#  					# add halfops to ops so users calculation below matches  					# -					$users_op = $users_op + $users_ho; +					$users_op += $users_ho;  					if ($showmode)  					{ -						$format = $format . '%%'; +						$format .= Irssi::settings_get_str('mh_sbuserinfo_format_mode_ho');  					} - 					$format = $format . $users_ho . ':'; + 					$format .= $users_ho . $format_sep; +				} + +				if ($showmode) +				{ +					$format .= Irssi::settings_get_str('mh_sbuserinfo_format_mode_vo');;  				} +				$format .= $users_vo . $format_sep; +  				if ($showmode)  				{ -					$format = $format . '+'; +					$format .= Irssi::settings_get_str('mh_sbuserinfo_format_mode_other');;  				} -				$format = $format . $users_vo . ':' . ($users - ($users_op + $users_vo)) . ')'; +				$format .= ($users - ($users_op + $users_vo)) . $format_group_end;  			}  			my $limit = $channel->{'limit'};  			if ($limit)  			{ -				$format = $format . '/'; +				$format .= $format_div;  				if (Irssi::settings_get_bool('mh_sbuserinfo_show_warning_limit'))  				{ @@ -265,20 +325,39 @@ sub statusbar_userinfo  						$setting_percent = 0;  					} -					my $percent = int(($users / $limit) * 100); +					if ($setting_percent) +					{ + +						my $percent = int(($users / $limit) * 100); -					if ($percent >= $setting_percent) +						if ($percent >= $setting_percent) +						{ +							$format .= $warning_format; +						} +					} else  					{ -						$format = $format . $warning_format; +						my $setting_percent = Irssi::settings_get_int('mh_sbuserinfo_show_warning_limit_difference'); + +						my $difference = ($limit - $users); + +						if ($setting_percent < 0) +						{ +							$setting_percent = 0; +						} + +						if ($difference < $setting_percent) +						{ +							$format .= $warning_format; +						}  					}  				}  				if (Irssi::settings_get_bool('mh_sbuserinfo_show_details_difference'))  				{ -					$limit = $limit . '(' . ($limit - $users) . ')'; +					$limit .= $format_group_begin . ($limit - $users) . $format_group_end;  				} -				$format = $format . $limit . '%n'; +				$format .= $limit . '%n';  			}  		}  	} @@ -292,17 +371,26 @@ sub statusbar_userinfo  #  ############################################################################## -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details',               1); -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_mode',          1); -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_halfop',        0); -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_warning_opless',        1); -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_warning_limit',         1); -Irssi::settings_add_int( 'mh_sbuserinfo', 'mh_sbuserinfo_show_warning_limit_percent', 95); -Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_warning_format',             '%Y'); -Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_show_prefix',                'Users: '); -Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_difference',    1); - -Irssi::statusbar_item_register('mh_sbuserinfo', '', 'statusbar_userinfo'); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details',                  1); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_mode',             1); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_halfop',           0); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_warning_opless',           1); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_warning_limit',            1); +Irssi::settings_add_int( 'mh_sbuserinfo', 'mh_sbuserinfo_show_warning_limit_percent',    0); +Irssi::settings_add_int( 'mh_sbuserinfo', 'mh_sbuserinfo_show_warning_limit_difference', 5); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_warning_format',                '%Y'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_show_prefix',                   'Users: '); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_difference',       1); +Irssi::settings_add_bool('mh_sbuserinfo', 'mh_sbuserinfo_show_details_oper',             1); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_sep',                    ':'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_div',                    '/'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_group_begin',            '('); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_group_end',              ')'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_mode_oper',              '*'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_mode_op',                '@'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_mode_ho',                '%%'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_mode_vo',                '+'); +Irssi::settings_add_str( 'mh_sbuserinfo', 'mh_sbuserinfo_format_mode_other',             '');  Irssi::signal_add_last('channel sync',         'statusbar_redraw');  Irssi::signal_add_last('channel mode changed', 'statusbar_redraw'); @@ -312,6 +400,8 @@ Irssi::signal_add_last('nicklist remove',      'statusbar_redraw');  Irssi::signal_add_last('setup changed',        'signal_setup_changed_last');  Irssi::signal_add_last('window changed',       'signal_window_changed_last'); +Irssi::statusbar_item_register('mh_sbuserinfo', '', 'statusbar_userinfo'); +  1;  ############################################################################## 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/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/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/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/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/xdcc_autoget.pl b/scripts/xdcc_autoget.pl index 16f4639..57bcf65 100644 --- a/scripts/xdcc_autoget.pl +++ b/scripts/xdcc_autoget.pl @@ -50,7 +50,7 @@ use File::Copy;  use Try::Tiny;  use vars qw($VERSION %IRSSI); -$VERSION = "2.0"; +$VERSION = "2.1";  %IRSSI = (  	name => "autoget",   	description => "XDCC Autoget, for automated searching and downloading of xdcc packs", @@ -143,7 +143,7 @@ sub ag_list  sub ag_initserver	#init server  { -	Irssi::signal_remove("server connected", "ag_server"); +	Irssi::signal_remove("server connected", "ag_initserver");  	$statusbarmessage = "Connected";  	$server = $_[0];  	if (!$runningflag) {Irssi::timeout_add_once(5000, sub { &ag_run; }, []);} @@ -270,11 +270,11 @@ sub ag_search		#searches bots for packs  	$msgflag[$botcounter] = 0;	#unset message flag so that ag_skip knows no important message has arrived  	if($episodicflag)	  	{ -		my $searchterm; +		my $searchterm = $terms[$termcounter[$botcounter]];  		my @words = split(/#/, $terms[$termcounter[$botcounter]]);  		my $ep = sprintf("%.2d", $episode[$botcounter]);  		if ($#words > 0){$searchterm = "$words[0]$ep$words[1]";} -		else {$searchterm = "$words[0] $ep";} +		elsif ($words[0] ne $searchterm) {$searchterm = "$words[0] $ep";}  		ag_message("msg $bots[$botcounter] $findprefix $searchterm" );  		push(@{$totags[$botcounter]}, Irssi::timeout_add_once($botdelay * 1000, sub { ag_skip($botcounter); } , [])); @@ -323,9 +323,9 @@ sub ag_getpacks			#if ($m =~ m{#(\d+):})  	my @temp = split(/[#,]/, $message);	#split up the message into 'words'  	my $timeoutscleared = 0; -	my $newpackflag = 1;  	foreach my $m (@temp)		#find packs (#[NUMBER]: format)  	{  +		my $newpackflag = 1;  		if ($m =~ m/(\d+):(.+)/)  		{  			if (!$timeoutscleared)	#reset timeouts if any packs are found @@ -339,7 +339,7 @@ sub ag_getpacks			#if ($m =~ m{#(\d+):})  				my $filename = $2;  				$filename =~ tr/[ ']/[__]/;  				if ($n eq "$bots[$botcounter] $1" or $n eq $filename) {$newpackflag = 0;} -				last if ($n eq "$bots[$botcounter] $1"); +				last if ($n eq "$bots[$botcounter] $1" or $n eq $filename);  			}  			if($newpackflag){push(@{$packs[$botcounter]}, $1);}	#push all new pack numbers to list of packs  		} @@ -650,7 +650,6 @@ sub ag_parserem		#parses remove arguments for deletion from file  sub ag_add	#add search terms  { -	ag_server;  	my @args = quotewords('\s+', 0, $_[0]);	#split arguments (words in brackets not seperated)  	if ($#args < 0)  	{ @@ -664,7 +663,6 @@ sub ag_add	#add search terms  sub ag_rem	#remove ssearch terms  { -	ag_server;  	my @args = quotewords('\s+', 0, $_[0]);  	if ($#args < 0)  	{ @@ -678,7 +676,6 @@ sub ag_rem	#remove ssearch terms  sub ag_botadd	#add bots  { -	ag_server;  	my @args = quotewords('\s+', 0, $_[0]);  	if ($#args < 0)  	{ @@ -692,7 +689,6 @@ sub ag_botadd	#add bots  sub ag_botrem	#remove bots  { -	ag_server;  	my @args = quotewords('\s+', 0, $_[0]);  	if ($#args < 0)  	{ | 
