\n([^\n]*)/i) {
+ $witem->command("me $1");
+ }
+ } else {
+ $witem->command("me \cC5Perl Function $data: No Results.");
+ }
+
+ return;
+
+}
+Irssi::command_bind bgperl => \&cmd_bgperl;
+
+# Debian Search Packages
+$FEATURES{'debian'} = "/bgdebian \cC7package name | \cC5Search a package in a Debian stable distribution";
+sub cmd_bgdebian {
+
+ my ($data, $server, $witem) = @_;
+
+ return unless $witem;
+
+
+ use LWP;
+
+ my $Navigator = new LWP::UserAgent({
+ "agent" => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
+ "timeout" => "180",
+ });
+
+ $data =~ s/\ /\+/;
+ my $Page = $Navigator->get('http://packages.debian.org/cgi-bin/search_packages.pl?keywords='.$data.'&searchon=names&subword=1&version=stable&release=all');
+
+ my $content = $Page->content if $Page->is_success;
+ if($Page->is_success && $content =~ /| $data/i) {
+ $witem->command("me Debian \cC2$data\cC package:");
+ $witem->command("me Location: \cC5 http://packages.debian.org/stable/misc/$1.html");
+ if($content =~ / | ([^<]*)command("me Description: $1");
+ }
+ } else {
+ $witem->command("me \cC5Debian $data package: No Results.");
+ }
+
+ return;
+
+}
+Irssi::command_bind bgdebian => \&cmd_bgdebian;
+1;
+
+
diff --git a/scripts/binary.pl b/scripts/binary.pl
new file mode 100644
index 0000000..1eb374a
--- /dev/null
+++ b/scripts/binary.pl
@@ -0,0 +1,114 @@
+# /binary huora
+# tuolostaa k.o. ikkunaan huora:n sijaan 01101001 ....
+#
+# and modified by carl 2004-03-09
+
+# Changelog
+# Version 1: original version by nchip
+# Version 1.1: added unbinary function
+# Verison 1.2: added server truncate detection (requested by Andr, thanks for spotting the problem) and choice to have spaces in the binary or not (reqested by Tapio)
+
+
+use strict;
+use Irssi;
+use Irssi qw(command_bind command signal_add_last signal_stop settings_get_bool settings_add_bool);
+
+use vars qw($VERSION %IRSSI);
+
+#%IRSSI = (
+# authors => "Riku Voipio",
+# contact => "riku.voipio\@iki.fi",
+# name => "binary",
+# description => "adds /binary command that converts what you type into 2-base string representation",
+# license => "GPLv2",
+# url => "http://nchip.ukkosenjyly.mine.nu/irssiscripts/",
+# );
+
+$VERSION = "1.2";
+%IRSSI = (
+ authors => "Carl Fischer",
+ contact => "carl.fischer\@netcourrier.com",
+ name => "binary",
+ description => "adds /binary command that converts what you type into 2-base string representation, also decodes other peoples binary automatically",
+ license => "GPLv2",
+ );
+
+
+sub cmd_binary {
+ $_=join(" ",$_[0]);
+ $_=reverse;
+ my (@r);
+ if (settings_get_bool('binary_spaces')) {
+ $r[0]="/say";
+ } else {
+ $r[0]="/say ";
+ }
+ while ($a = chop($_)) {
+ push (@r,unpack ("B*", $a));}
+
+ my $window = Irssi::active_win();
+ if (settings_get_bool('binary_spaces')) {
+ $window->command(join (" ",@r));
+ } else {
+ $window->command(join ("",@r));
+ }
+ }
+
+# here ends the original code
+# some of the following was strongly inspired by the kenny script
+
+sub cmd_unbinary {
+ pop @_;
+ pop @_;
+ my $window = Irssi::active_win();
+ $window->print(unbinary($_[0]));
+}
+
+sub unbinary {
+ my $r;
+ if (settings_get_bool('binary_spaces')) {
+ $r=pack("B*", join ("", split(" ", @_[0])));
+ } else {
+ $r=pack("B*", @_[0]);
+ }
+ return $r;
+}
+
+sub sig_binary {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ if (($msg=~m/^([01]{8}( [01]{8})*)( [01]{1,7})*$/ and settings_get_bool('binary_spaces')) or ($msg=~m/^([01]{8}([01]{8})*)([01]{1,7})*$/ and not settings_get_bool('binary_spaces'))) {
+ my $leftover="";
+ $leftover="* (truncated by server)" if $3;
+ $target=$nick if $target eq "";
+ # the address may _never_ be emtpy, if it is its own_public
+ $nick=$server->{'nick'} if $address eq "";
+ $server->window_item_find($target)->print("[binary] <$nick> " .
+ unbinary($1) . $leftover, 'MSGLEVEL_CRAP');
+ signal_stop() if not settings_get_bool('show_binary_too');
+ }
+}
+
+signal_add_last('message own_public', 'sig_binary');
+signal_add_last('message public', 'sig_binary');
+signal_add_last('message own_private', 'sig_binary');
+signal_add_last('message private', 'sig_binary');
+
+settings_add_bool('lookandfeel', 'show_binary_too', 0);
+settings_add_bool('lookandfeel', 'binary_spaces', 1);
+
+Irssi::command_bind('binary', 'cmd_binary');
+Irssi::command_bind('unbinary', 'cmd_unbinary');
+
+Irssi::print("binary obfuscator vanity script loaded");
+Irssi::print("written by nchip and updated by carl");
+Irssi::print("--------------------------------------");
+Irssi::print("/binary message");
+Irssi::print("will send binary text to the current channel");
+Irssi::print("");
+Irssi::print("/unbinary obfuscated_text");
+Irssi::print("will print the unobfuscated equivalent to your window (and not to the channel)");
+Irssi::print("");
+Irssi::print("/set show_binary_too on");
+Irssi::print("will make this script print the binary equivalent as well as the translation to your screen whenever someone uses binary on the channel");
+Irssi::print("/set binary_spaces off");
+Irssi::print("will make the binary be printed as a single word with no spaces");
diff --git a/scripts/binary_time.pl b/scripts/binary_time.pl
new file mode 100644
index 0000000..610ae11
--- /dev/null
+++ b/scripts/binary_time.pl
@@ -0,0 +1,70 @@
+###
+#
+# binary_time.pl
+#
+# Description:
+# This script prints the timestamp in binary as follows:
+# 09:25 would be 01001:011001
+# 23:49 would be 10111:110001
+#
+# Bugs:
+# If there are any bugs, please email me at aaron.toponce@gmail.com, and I'll get to them as I can.
+# Please provide the irrsi version that you are using when the bug occurred, as well as a thorough
+# description of how you noticed the bug. This means providing details of other scripts that you
+# are using including themes. Please be as detailed as possible. It is my attempt to recreate the
+# bug. I make no assurance that I will fix the bug, but I will make my best attempt at locating it.
+#
+# Contact:
+# IRC: #irssi on freenode
+# Email: aaron.toponce@gmail.com
+# Jabber: aaron.toponce@gmail.com
+#
+# Change release:
+# - 20060826 : Initial release
+###
+
+use Irssi;
+use strict;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION="20060826";
+%IRSSI = (
+ authors => 'Aaron Toponce, Knut Auvor Grythe',
+ contact => 'aaron.toponce@gmail.com, irssi@auvor.no',
+ name => 'binary_time',
+ description => 'Prints the timestamp in binary format',
+ license => 'GPL',
+);
+
+my $old_timestamp_format = Irssi::settings_get_str('timestamp_format');
+
+sub hour2bin {
+ my $str = unpack("B32", pack("N", shift));
+ $str =~ s/^0{27}(?=\d)//; # remove unecessary leading zeros (we only need 5 digits for the hour)
+ return $str;
+}
+
+sub min2bin {
+ my $str = unpack("B32", pack("N", shift));
+ $str =~ s/^0{26}(?=\d)//; # remove unecessary leading zeros (we only need 6 digits for the minute)
+ return $str;
+}
+
+sub convert_to_binary
+{
+ # Get the hour and minute from the localtime on the users machine.
+ my $hour = (localtime)[2];
+ my $minute = (localtime)[1];
+
+ my $new_time = hour2bin($hour) . "." . min2bin($minute);
+ Irssi::command("^set timestamp_format $new_time");
+}
+
+sub script_unload {
+ my ($script,$server,$witem) = @_;
+ Irssi::command("^set timestamp_format $old_timestamp_format");
+}
+
+Irssi::timeout_add(1000, 'convert_to_binary', undef);
+Irssi::signal_add_first('command script unload', 'script_unload');
diff --git a/scripts/bitlbee_blist.pl b/scripts/bitlbee_blist.pl
new file mode 100644
index 0000000..179b539
--- /dev/null
+++ b/scripts/bitlbee_blist.pl
@@ -0,0 +1,61 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '0.4';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'bitlbee_blist',
+ description => '/blist , greps from blist for bitlbee',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2006-10-27',
+);
+
+my $bitlbee_server_tag = "localhost";
+my $bitlbee_channel = "&bitlbee";
+my ($list, $word);
+
+get_channel();
+
+Irssi::signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ $bitlbee_channel = $channel->{name};
+ }
+};
+
+sub get_channel {
+ my @channels = Irssi::channels();
+ foreach my $channel(@channels) {
+ if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
+ $bitlbee_channel = $channel->{name};
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub blist {
+ my ($args, $server, $winit) = @_;
+ ($list, $word) = split(/ /, $args, 2);
+ if (Irssi::active_win->{'active'}->{'name'} eq $bitlbee_channel) {
+ Irssi::active_win()->command("msg $bitlbee_channel blist $list");
+ Irssi::signal_add('event privmsg', 'grep');
+ } else {
+ print "Only use in $bitlbee_channel.";
+ }
+}
+
+sub grep {
+ my ($server, $data, $nick, $address) = @_;
+ my ($target, $text) = split(/ :/, $data, 2);
+ if ($text =~ /$word/ && $target =~ /$bitlbee_channel/){
+ ##do nothing
+ } else {Irssi::signal_stop();}
+ if ($text =~ /buddies/ && $target =~/$bitlbee_channel/){Irssi::signal_remove('event privmsg', 'grep');}
+}
+
+Irssi::command_bind('blist','blist');
diff --git a/scripts/bitlbee_join_notice-pre-3.0.pl b/scripts/bitlbee_join_notice-pre-3.0.pl
new file mode 100644
index 0000000..a64af60
--- /dev/null
+++ b/scripts/bitlbee_join_notice-pre-3.0.pl
@@ -0,0 +1,95 @@
+#CHANGELOG:
+#
+#28-11-2004:
+#it gives a join message in a query if a user joins &bitlbee and you hve a query open with that person.
+#
+#/statusbar window add join_notice
+#use Data::Dumper;
+
+use strict;
+#use Irssi::TextUI;
+#use Irssi::Themes;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.2';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'Bitlbee_join_notice-pre-3.0',
+ description => ' 1. Adds an item to the status bar wich shows [joined: ] when someone is joining &bitlbee.
+ 2. Shows join messages in the query.
+ (For bitlbee 1.2.x)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2006-10-27',
+);
+my %online;
+my %tag;
+my $bitlbee_channel= "&bitlbee";
+my $bitlbee_server_tag="localhost";
+
+get_channel();
+
+Irssi::signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ $bitlbee_channel = $channel->{name};
+ }
+};
+
+sub get_channel {
+ my @channels = Irssi::channels();
+ foreach my $channel(@channels) {
+ if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
+ $bitlbee_channel = $channel->{name};
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub event_join {
+ my ($server, $channel, $nick, $address) = @_;
+ if ($channel eq ":$bitlbee_channel" && $server->{tag} eq $bitlbee_server_tag){
+ $online{$nick} = 1;
+ Irssi::timeout_remove($tag{$nick});
+ $tag{$nick} = Irssi::timeout_add(7000, 'empty', $nick);
+ Irssi::statusbar_items_redraw('join_notice');
+ my $window = Irssi::window_find_item($nick);
+ if($window){
+ $window->printformat(MSGLEVEL_JOINS, 'join', $nick, $address, $bitlbee_channel);
+ }
+ }
+}
+sub join_notice {
+ my ($item, $get_size_only) = @_;
+ my $line;
+ foreach my $key (keys(%online) )
+ {
+ $line = $line." ".$key;
+ }
+ if ($line ne "" ){
+ $item->default_handler($get_size_only, "{sb joined:$line}", undef, 1);
+ $line = "";
+ }else{
+ $item->default_handler($get_size_only, "", undef, 1);
+ }
+}
+sub empty{
+ my $nick = shift;
+ delete($online{$nick});
+ Irssi::timeout_remove($tag{$nick});
+ Irssi::statusbar_items_redraw('join_notice');
+}
+
+Irssi::signal_add("event join", "event_join");
+Irssi::statusbar_item_register('join_notice', undef, 'join_notice');
+Irssi::statusbars_recreate_items();
+Irssi::theme_register([
+ 'join', '{channick_hilight $0} {chanhost $1} has joined {channel $2}',
+]);
+
+
diff --git a/scripts/bitlbee_join_notice.pl b/scripts/bitlbee_join_notice.pl
new file mode 100644
index 0000000..6644895
--- /dev/null
+++ b/scripts/bitlbee_join_notice.pl
@@ -0,0 +1,108 @@
+# CHANGELOG:
+#
+# 2010-08-10 (version 1.3)
+# * new bitlbee server detection
+#
+# 2004-11-28:
+# * adds join message to query
+#
+# /statusbar window add join_notice
+# use Data::Dumper;
+
+#use strict;
+use Irssi::TextUI;
+#use Irssi::Themes;
+use Data::Dumper;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.3';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'BitlBee_join_notice',
+ description => '1. Adds an item to the status bar wich shows [joined: ] when someone is joining &bitlbee. 2. Shows join messages in the query. (For bitlbee v3.0+)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2010-08-10'
+);
+my %timers;
+my $bitlbee_server; # server object
+my @control_channels; # mostly: &bitlbee, &facebook etc.
+init();
+
+sub init { # if script is loaded after connect
+ my @servers = Irssi::servers();
+ foreach my $server(@servers) {
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ my @channels = $server->channels();
+ foreach my $channel(@channels) {
+ if( $channel->{mode} =~ /C/ ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+ }
+ }
+ }
+}
+# if connect after script is loaded
+Irssi::signal_add_last('event 005' => sub {
+ my( $server ) = @_;
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ }
+});
+# if new control channel is synced after script is loaded
+Irssi::signal_add_last('channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{mode} =~ /C/ && $channel->{server}->{tag} eq $bitlbee_server->{tag} ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+});
+
+# BEGIN bitlbee_join_notice.pl
+
+my %online;
+
+sub event_join {
+ my ($server, $channel, $nick, $address) = @_;
+ $channel =~ s/^://g;
+ if ( (grep $_ eq $channel, @control_channels) && $server->{tag} eq $bitlbee_server->{tag}){
+ $online{$nick} = 1;
+ Irssi::timeout_remove($timers{$nick});
+ delete($timers{$nick});
+ $timers{$nick} = Irssi::timeout_add_once(7000, 'empty', $nick);
+ Irssi::statusbar_items_redraw('join_notice');
+ my $window = Irssi::window_find_item($nick);
+ if($window){
+ $window->printformat(Irssi::MSGLEVEL_JOINS, 'join', $nick, $address, $channel);
+ }
+ }
+}
+sub join_notice {
+ my ($item, $get_size_only) = @_;
+ my $line;
+ foreach my $key (keys(%online) ){
+ $line = $line." ".$key;
+ }
+ if ($line ne "" ){
+ $item->default_handler($get_size_only, "{sb joined:$line}", undef, 1);
+ $line = "";
+ } else {
+ $item->default_handler($get_size_only, "", undef, 1);
+ }
+}
+sub empty {
+ my $nick = shift;
+ delete($online{$nick});
+ Irssi::timeout_remove($timers{$nick});
+ delete($timers{$nick});
+ Irssi::statusbar_items_redraw('join_notice');
+}
+
+Irssi::signal_add('event join', 'event_join' );
+Irssi::statusbar_item_register('join_notice', undef, 'join_notice');
+Irssi::statusbars_recreate_items();
+Irssi::theme_register([ 'join', '{channick_hilight $0} {chanhost $1} has joined {channel $2}', ]);
+
+# END bitlbee_join_notice.pl
diff --git a/scripts/bitlbee_nick_change-pre-3.0.pl b/scripts/bitlbee_nick_change-pre-3.0.pl
new file mode 100644
index 0000000..1742c2a
--- /dev/null
+++ b/scripts/bitlbee_nick_change-pre-3.0.pl
@@ -0,0 +1,64 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.2';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'bitlbee_nick_change-pre-3.0',
+ description => 'Shows an IM nickchange in an Irssi way. (in a query and in the bitlbee channel). (For bitlbee 1.2.x)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2006-10-27',
+);
+
+my $bitlbee_channel = "&bitlbee";
+my $bitlbee_server_tag = "localhost";
+
+Irssi::signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ $bitlbee_channel = $channel->{name};
+ }
+};
+
+get_channel();
+
+sub get_channel {
+ my @channels = Irssi::channels();
+ foreach my $channel(@channels) {
+ if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
+ $bitlbee_channel = $channel->{name};
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub message {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ if($server->{tag} eq $bitlbee_server_tag) {
+ if($msg =~ /User.*changed name to/) {
+ $nick = $msg;
+ $nick =~ s/.* - User `(.*)' changed name to.*/$1/;
+ my $window = $server->window_find_item($nick);
+
+ if ($window) {
+ $window->printformat(MSGLEVEL_CRAP, 'nick_change',$msg);
+ Irssi::signal_stop();
+ } else {
+ my $window = $server->window_find_item($bitlbee_channel);
+ $window->printformat(MSGLEVEL_CRAP, 'nick_change',$msg);
+ Irssi::signal_stop();
+ }
+ }
+ }
+}
+
+Irssi::signal_add_last ('message public', 'message');
+
+Irssi::theme_register([
+ 'nick_change', '$0'
+ ]);
diff --git a/scripts/bitlbee_nick_change.pl b/scripts/bitlbee_nick_change.pl
new file mode 100644
index 0000000..93a01b9
--- /dev/null
+++ b/scripts/bitlbee_nick_change.pl
@@ -0,0 +1,72 @@
+use strict;
+use Data::Dumper;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.3';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'BitlBee_nick_change',
+ description => 'Shows an IM nickchange in an Irssi way. (in a query and in the bitlbee channel). (For bitlbee 3.0+)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2010-07-28'
+);
+
+my $bitlbee_server; # server object
+my @control_channels; # mostly: &bitlbee, &facebook etc.
+init();
+
+sub init { # if script is loaded after connect
+ my @servers = Irssi::servers();
+ foreach my $server(@servers) {
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ my @channels = $server->channels();
+ foreach my $channel(@channels) {
+ if( $channel->{mode} =~ /C/ ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+ }
+ }
+ }
+}
+# if connect after script is loaded
+Irssi::signal_add_last('event 005' => sub {
+ my( $server ) = @_;
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ }
+});
+# if new control channel is synced after script is loaded
+Irssi::signal_add_last('channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{mode} =~ /C/ && $channel->{server}->{tag} eq $bitlbee_server->{tag} ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+});
+
+# BEGIN bitlbee_nick_change.pl
+
+sub event_notice {
+ my ($server, $msg, $nick, $address, $target) = @_;
+ if( $server->{tag} eq $bitlbee_server->{tag} && $msg =~ /.*Changed name to.*/ ){
+ my $friendly_name = $msg;
+ $friendly_name =~ s/.*Changed name to `(.*)'.*/$1/;
+ my $window = $server->window_find_item($nick);
+ if ($window) {
+ $window->printformat(MSGLEVEL_CRAP, 'nick_change', $nick, $address, 'changed name to `'.$friendly_name.'`');
+ Irssi::signal_stop();
+ } else {
+ # TODO find control channel where this user is located and display the notice there
+ #my $window = $server->window_find_item($bitlbee_channel);
+ #$window->printformat(MSGLEVEL_CRAP, 'nick_change', $nick, $address, 'changed name to `'.$friendly_name.'`');
+ #Irssi::signal_stop();
+ }
+ }
+};
+
+Irssi::signal_add_last('message irc notice', 'event_notice');
+Irssi::theme_register(['nick_change', '{channick_hilight $0} [$1] $2']);
+
+# END bitbee_nick_change.pl
diff --git a/scripts/bitlbee_tab_completion.pl b/scripts/bitlbee_tab_completion.pl
new file mode 100644
index 0000000..8d19128
--- /dev/null
+++ b/scripts/bitlbee_tab_completion.pl
@@ -0,0 +1,88 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.3';
+
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal & Wilmer van der Gaast',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'BitlBee_tab_completion',
+ description => 'Intelligent Tab-completion for BitlBee commands.',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2009-08-11',
+);
+
+my $root_nick = 'root';
+my $bitlbee_channel = '&bitlbee';
+my $bitlbee_server_tag = 'localhost';
+my $get_completions = 0;
+
+my @commands;
+
+Irssi::signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ $bitlbee_channel = $channel->{name};
+ request_completions();
+ }
+};
+
+if (get_channel()) {
+ request_completions();
+}
+
+sub request_completions {
+ $get_completions = 1;
+ Irssi::server_find_tag($bitlbee_server_tag)->send_raw( 'COMPLETIONS' );
+}
+
+sub get_channel {
+ my @channels = Irssi::channels();
+ foreach my $channel(@channels) {
+ if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
+ $bitlbee_channel = $channel->{name};
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub irc_notice {
+ return unless $get_completions;
+ my( $server, $msg, $from, $address, $target ) = @_;
+
+ if( $msg =~ s/^COMPLETIONS // ) {
+ $root_nick = $from;
+ if( $msg eq 'OK' ) {
+ @commands = ();
+ }
+ elsif( $msg eq 'END' ) {
+ $get_completions = 0;
+ }
+ @commands = ( @commands, $msg );
+
+ Irssi::signal_stop();
+ }
+}
+
+sub complete_word {
+ my ($complist, $window, $word, $linestart, $want_space) = @_;
+ my $channel = $window->get_active_name();
+ if ($channel eq $bitlbee_channel or $channel eq $root_nick or $linestart =~ /^\/(msg|query) \Q$root_nick\E */i){
+ $linestart =~ s/^\/(msg|query) \Q$root_nick\E *//i;
+ $linestart =~ s/^\Q$root_nick\E[:,] *//i;
+ foreach my $command(@commands) {
+ if ($command =~ /^$word/i) {
+ push @$complist, $command;
+ }
+ }
+ }
+}
+
+
+Irssi::signal_add_last('complete word', 'complete_word');
+Irssi::signal_add_first('message irc notice', 'irc_notice');
+
diff --git a/scripts/bitlbee_timestamp.pl b/scripts/bitlbee_timestamp.pl
new file mode 100644
index 0000000..7957d57
--- /dev/null
+++ b/scripts/bitlbee_timestamp.pl
@@ -0,0 +1,105 @@
+use strict;
+use Data::Dumper;
+use vars qw($VERSION %IRSSI);
+use DateTime;
+
+$VERSION = '0.5';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal',
+ contact => 'tijmen.ruizendaal@gmail.com',
+ name => 'bitlbee_timestamp',
+ description => 'Replace Irssi\'s timestamps with those sent by BitlBee',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee',
+ changed => '2010-05-01',
+);
+
+my $tf = Irssi::settings_get_str('timestamp_format');
+
+my $bitlbee_server; # server object
+my @control_channels; # mostly: &bitlbee, &facebook etc.
+init();
+
+sub init { # if script is loaded after connect
+ my @servers = Irssi::servers();
+ foreach my $server(@servers) {
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ my @channels = $server->channels();
+ foreach my $channel(@channels) {
+ if( $channel->{mode} =~ /C/ ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+ }
+ }
+ }
+}
+# if connect after script is loaded
+Irssi::signal_add_last('event 005' => sub {
+ my( $server ) = @_;
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ }
+});
+# if new control channel is synced after script is loaded
+Irssi::signal_add_last('channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{mode} =~ /C/ && $channel->{server}->{tag} eq $bitlbee_server->{tag} ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+});
+
+my $prev_date = '';
+
+sub privmsg {
+ my ($server, $data, $nick, $address) = @_;
+
+ # What we need to match: ^B[^B^B^B2010-03-21 16:33:41^B]^B
+
+ if( $server->{tag} eq $bitlbee_server->{tag} ){
+
+ my ($target, $text) = split(/ :/, $data, 2);
+
+ #if( $text =~ /^B[^B^B^B[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}^B]^B/ ){
+
+ if( $text =~ /\x02\[\x02\x02\x02.*\x02\]\x02/ ){
+ my $window;
+ my $timestamp = $text;
+ my $time;
+ my $date;
+ $timestamp =~ s/.*\x02\[\x02\x02\x02(.*?)\x02\]\x02.*/$1/g;
+ $text =~ s/\x02\[\x02\x02\x02(.*?)\x02\]\x02 //g;
+
+ ($date, $time) = split(/ /, $timestamp);
+ if( !$time ){ # the timestamp doesn't have a date
+ $time = $date;
+ # use today as date
+ $date = DateTime->now->ymd;
+ }
+
+ if( $date ne $prev_date ){
+ if( $target =~ /#|&/ ){ # find channel window based on target
+ $window = Irssi::window_find_item($target);
+ } else { # find query window based on nick
+ $window = Irssi::window_find_item($nick);
+ }
+ if( $window != undef ){
+ my($year, $month, $day) = split(/-/, $date);
+ my $dt = DateTime->new(year => $year, month => $month, day => $day);
+ my $formatted_date = $day.' '.$dt->month_abbr.' '.$year;
+
+ $window->print('Day changed to '.$formatted_date, MSGLEVEL_NEVER);
+ }
+ }
+ $prev_date = $date;
+
+ Irssi::settings_set_str('timestamp_format', $time);
+ Irssi::signal_continue($server, $target . ' :' . $text, $nick, $address);
+ my $escaped = $tf;
+ $escaped =~ s/%/%%/g;
+ Irssi::settings_set_str('timestamp_format', $tf);
+ }
+ }
+}
+
+Irssi::signal_add('event privmsg', 'privmsg');
diff --git a/scripts/bitlbee_typing_notice-pre-3.0.pl b/scripts/bitlbee_typing_notice-pre-3.0.pl
new file mode 100644
index 0000000..0b21657
--- /dev/null
+++ b/scripts/bitlbee_typing_notice-pre-3.0.pl
@@ -0,0 +1,321 @@
+# INSTALLATION
+# [&bitlbee] set typing_notice true
+# <@root> typing_notice = `true'
+# AND
+# /statusbar window add typing_notice
+#
+# SETTINGS
+# [bitlbee]
+# bitlbee_send_typing = ON
+# -> send typing messages to buddies
+# bitlbee_typing_allwin = OFF
+# -> show typing notifications in all windows
+#
+#
+# Changelog:
+#
+# 2006-11-02 (version 1.6.1_
+# * Sending typing works again.
+#
+# 2006-10-27 (version 1.6)
+# * 'channel sync' re-implemented.
+# * bitlbee_send_typing was a string setting, It's a boolean now, like it should.
+#
+# 2006-10-24 (version 1.5)
+#
+# * Sending notices to online users only.
+# * Using the new get_channel function;
+#
+# 2005-12-15 (version 1.42):
+# * Fixed small bug with typing notices disappearing under certain circumstances
+# in channels
+# * Fixed bug that caused outgoing notifications not to work
+# * root cares not about our typing status.
+#
+# 2005-12-04 (version 1.41):
+# * Implemented stale states in statusbar (shows "(stale)" for OSCAR connections)
+# * Introduced bitlbee_typing_allwin (default OFF). Set this to ON to make
+# typing notifications visible in all windows.
+#
+# 2005-12-03 (version 1.4):
+# * Major code cleanups and rewrites for bitlbee 1.0 with the updated typing
+# scheme. TYPING 0, TYPING 1, and TYPING 2 are now supported from the server.
+# * Stale states (where user has typed in text but has stopped typing) are now
+# recognized.
+# * Bug where user thinks you are still typing if you close the window after
+# typing something and then erasing it quickly.. fixed.
+# * If a user signs off while they are still typing, the notification is removed
+# This update by Matt "f0rked" Sparks
+#
+# 2005-08-26:
+# Some fixes for AIM, Thanks to Dracula.
+#
+# 2005-08-16:
+# AIM supported, for sending notices, using CTCP TYPING 0. (Use the AIM patch from Hanji http://get.bitlbee.org/patches/)
+#
+# 2004-10-31:
+# Sends typing notice to the bitlbee server when typing a message in irssi. bitlbee > 0.92
+#
+# 2004-06-11:
+# shows [typing: ] in &bitlbee with multiple users.
+#
+use strict;
+use Irssi::TextUI;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.6.1';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal, Matt "f0rked" Sparks',
+ contact => 'tijmen.ruizendaal@gmail.com, root@f0rked.com',
+ name => 'Bitlbee_typing_notice-pre-3.0',
+ description => '1. Adds an item to the status bar wich shows [typing] when someone is typing a message on the supported IM-networks
+ 2. Sending typing notices to the supported IM networks (the other way arround)
+ (For bitlbee 1.2.x)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee,
+ http://f0rked.com',
+ changed => '2006-11-02',
+);
+
+my $bitlbee_channel = "&bitlbee";
+my $bitlbee_server_tag = "localhost";
+
+my $KEEP_TYPING_TIMEOUT = 1;
+my $STOP_TYPING_TIMEOUT = 7; # How often to check if we are typing, or on msn,
+ # how long to keep the typing notice up, or check
+ # if the other user is still typing...
+
+my %timer_tag;
+
+my %typing;
+my %tag;
+my $line;
+my %out_typing;
+my $lastkey;
+my $keylog_active = 1;
+my $command_char = Irssi::settings_get_str('cmdchars');
+my $to_char = Irssi::settings_get_str("completion_char");
+
+get_channel();
+
+Irssi::signal_add_last 'channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information." ){
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ $bitlbee_channel = $channel->{name};
+ }
+};
+
+sub get_channel {
+ my @channels = Irssi::channels();
+ foreach my $channel(@channels) {
+ if ($channel->{topic} eq "Welcome to the control channel. Type \x02help\x02 for help information.") {
+ $bitlbee_channel = $channel->{name};
+ $bitlbee_server_tag = $channel->{server}->{tag};
+ return 1;
+ }
+ }
+ return 0;
+}
+
+sub event_ctcp_msg {
+ my ($server, $msg, $from, $address) = @_;
+ #print "CTCP: $msg $from $address";
+ return if $server->{tag} ne $bitlbee_server_tag;
+ if (my($type) = $msg =~ "TYPING ([0-9])") {
+ Irssi::signal_stop();
+ if ($type == 0) {
+ unset_typing($from);
+ }
+ elsif ($type == 1) {
+ $typing{$from}=1;
+ if ($address !~ /\@login\.oscar\.aol\.com/
+ and $address !~ /\@YAHOO/
+ and $address !~ /\@login\.icq\.com/) {
+ Irssi::timeout_remove($tag{$from});
+ $tag{$from}=Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000,"unset_typing",$from);
+ }
+ redraw($from);
+ }
+ elsif ($type == 2) {
+ stale_typing($from);
+ }
+ }
+}
+
+sub unset_typing {
+ my($from,$no_redraw)=@_;
+ delete $typing{$from} if $typing{$from};
+ Irssi::timeout_remove($tag{$from});
+ redraw($from) if !$no_redraw;
+}
+
+sub stale_typing {
+ my($from)=@_;
+ $typing{$from}=2;
+ redraw($from);
+}
+
+sub redraw {
+ my($from)=@_;
+ my $window = Irssi::active_win();
+ my $channel = $window->get_active_name();
+ if ($from eq $channel || $channel eq $bitlbee_channel
+ || $channel =~ /&chat_0/
+ || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
+ Irssi::statusbar_items_redraw('typing_notice');
+ }
+}
+
+sub event_msg {
+ my ($server,$data,$from,$address,$target) = @_;
+ return if $server->{tag} ne $bitlbee_server_tag;
+ my $channel=Irssi::active_win()->get_active_name();
+ unset_typing $from, "no redraw";
+ unset_typing $channel;
+}
+
+sub event_quit {
+ my($server,$nick,$address,$reason)=@_;
+ return if $server->{tag} ne $bitlbee_server_tag;
+ unset_typing $nick;
+}
+
+sub typing_notice {
+ my ($item, $get_size_only) = @_;
+ my $window = Irssi::active_win();
+ my $channel = $window->get_active_name();
+
+ if (exists($typing{$channel})) {
+ my $append=$typing{$channel}==2 ? " (stale)" : "";
+ $item->default_handler($get_size_only, "{sb typing$append}", 0, 1);
+ }
+ else {
+ $item->default_handler($get_size_only, "", 0, 1);
+ Irssi::timeout_remove($tag{$channel});
+ }
+ if ($channel eq $bitlbee_channel || $channel =~ /&chat_0/
+ || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
+ foreach my $key (keys(%typing)) {
+ $line .= " ".$key;
+ if ($typing{$key}==2) { $line .= " (stale)"; }
+ }
+ if ($line ne "") {
+ $item->default_handler($get_size_only, "{sb typing:$line}", 0, 1);
+ $line = "";
+ }
+ }
+}
+
+sub empty {
+ my $from = shift;
+ delete($typing{$from});
+ Irssi::statusbar_items_redraw('typing_notice');
+}
+
+sub window_change {
+ Irssi::statusbar_items_redraw('typing_notice');
+ my $win = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
+ if (ref $win && ($win->{server}->{tag} eq $bitlbee_server_tag)) {
+ if (!$keylog_active) {
+ $keylog_active = 1;
+ Irssi::signal_add_last('gui key pressed', 'key_pressed');
+ #print "Keylog started";
+ }
+ }
+ else {
+ if ($keylog_active) {
+ $keylog_active = 0;
+ Irssi::signal_remove('gui key pressed', 'key_pressed');
+ #print "Keylog stopped";
+ }
+ }
+}
+
+sub key_pressed {
+ return if !Irssi::settings_get_bool("bitlbee_send_typing");
+ my $key = shift;
+ if ($key != 9 && $key != 10 && $lastkey != 27 && $key != 27
+ && $lastkey != 91 && $key != 126 && $key != 127)
+ {
+ my $server = Irssi::active_server();
+ my $window = Irssi::active_win();
+ my $nick = $window->get_active_name();
+ if ($server->{tag} eq $bitlbee_server_tag &&
+ $nick ne "(status)" &&
+ $nick ne "root")
+ {
+ if ($nick eq $bitlbee_channel) {
+ my $input = Irssi::parse_special("\$L");
+ my ($first_word) = split(/ /,$input);
+ if ($input !~ /^$command_char.*/ && $first_word =~ s/$to_char$//){
+ send_typing($first_word);
+ }
+ }
+ else {
+ my $input = Irssi::parse_special("\$L");
+ if ($input !~ /^$command_char.*/ && length($input) > 0){
+ send_typing($nick);
+ }
+ }
+ }
+ }
+ $lastkey = $key;
+}
+
+sub out_empty {
+ my ($a) = @_;
+ my($nick,$tag)=@{$a};
+ delete($out_typing{$nick});
+ #print $winnum."|".$nick;
+ if (my $server=Irssi::server_find_tag($tag)) {
+ $server->command("^CTCP $nick TYPING 0");
+ }
+}
+
+sub send_typing {
+ my $nick = shift;
+ if (!exists($out_typing{$nick}) || time - $out_typing{$nick} > $KEEP_TYPING_TIMEOUT) {
+
+ my @nicks = Irssi::server_find_tag($bitlbee_server_tag)->channel_find($bitlbee_channel)->nicks();
+ my $exists=0;
+ foreach my $nick1(@nicks) { #check if the nickname is in the BitlBee channel
+ if($nick1->{'nick'} eq $nick) {
+ # print "Exists!";
+ $exists=1;
+ }
+ }
+ if (!$exists) {
+ #print "Does not exist";
+ return;
+ }
+
+ #print "Send typing";
+ my $server = Irssi::active_server();
+ $server->command("^CTCP $nick TYPING 1");
+
+ $out_typing{$nick} = time;
+
+ ### Reset 'stop-typing' timer
+ if ($timer_tag{$nick}) {
+ Irssi::timeout_remove($timer_tag{$nick});
+ delete($timer_tag{$nick});
+ }
+ $timer_tag{$nick} = Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000, 'out_empty', ["$nick", $server->{tag}]);
+ }
+}
+
+ #README: Delete the old bitlbee_send_typing string from ~/.irssi/config. A boolean is better.
+
+Irssi::settings_add_bool("bitlbee","bitlbee_send_typing",1);
+Irssi::settings_add_bool("bitlbee","bitlbee_typing_allwin",0);
+
+Irssi::signal_add("ctcp msg", "event_ctcp_msg");
+Irssi::signal_add("message private", "event_msg");
+Irssi::signal_add("message public", "event_msg");
+Irssi::signal_add("message quit", "event_quit");
+Irssi::signal_add_last('window changed', 'window_change');
+Irssi::signal_add_last('gui key pressed', 'key_pressed');
+Irssi::statusbar_item_register('typing_notice', undef, 'typing_notice');
+Irssi::statusbars_recreate_items();
diff --git a/scripts/bitlbee_typing_notice.pl b/scripts/bitlbee_typing_notice.pl
new file mode 100644
index 0000000..50fe47c
--- /dev/null
+++ b/scripts/bitlbee_typing_notice.pl
@@ -0,0 +1,319 @@
+# INSTALLATION
+# [&bitlbee] set typing_notice true
+# <@root> typing_notice = `true'
+# AND
+# /statusbar window add typing_notice
+#
+# SETTINGS
+# [bitlbee]
+# bitlbee_send_typing = ON
+# -> send typing messages to buddies
+# bitlbee_typing_allwin = OFF
+# -> show typing notifications in all windows
+#
+#
+# Changelog:
+#
+# 2010-08-09 (version 1.7.1)
+# * Multiple control channels supported by checking chanmodes
+#
+# 2010-07-27 (version 1.7)
+# * Using new server detection for latest BitlBee support
+#
+# 2010-07-26 (version 1.6.3)
+# * Removed checking if nicks exists in &bitlbee channel, this because BitlBee
+# can be used without control channel from this date
+#
+# 2007-03-03 (version 1.6.2)
+# * Fix: timers weren't deleted correctly. This resulted in huge mem usage.
+#
+# 2006-11-02 (version 1.6.1)
+# * Sending typing works again.
+#
+# 2006-10-27 (version 1.6)
+# * 'channel sync' re-implemented.
+# * bitlbee_send_typing was a string setting, It's a boolean now, like it should.
+#
+# 2006-10-24 (version 1.5)
+# * Sending notices to online users only. ( removed this again at 2010-07-26, see above )
+# * Using the new get_channel function;
+#
+# 2005-12-15 (version 1.42):
+# * Fixed small bug with typing notices disappearing under certain circumstances
+# in channels
+# * Fixed bug that caused outgoing notifications not to work
+# * root cares not about our typing status.
+#
+# 2005-12-04 (version 1.41):
+# * Implemented stale states in statusbar (shows "(stale)" for OSCAR connections)
+# * Introduced bitlbee_typing_allwin (default OFF). Set this to ON to make
+# typing notifications visible in all windows.
+#
+# 2005-12-03 (version 1.4):
+# * Major code cleanups and rewrites for bitlbee 1.0 with the updated typing
+# scheme. TYPING 0, TYPING 1, and TYPING 2 are now supported from the server.
+# * Stale states (where user has typed in text but has stopped typing) are now
+# recognized.
+# * Bug where user thinks you are still typing if you close the window after
+# typing something and then erasing it quickly.. fixed.
+# * If a user signs off while they are still typing, the notification is removed
+# This update by Matt "f0rked" Sparks
+#
+# 2005-08-26:
+# Some fixes for AIM, Thanks to Dracula.
+#
+# 2005-08-16:
+# AIM supported, for sending notices, using CTCP TYPING 0. (Use the AIM patch from Hanji http://get.bitlbee.org/patches/)
+#
+# 2004-10-31:
+# Sends typing notice to the bitlbee server when typing a message in irssi. bitlbee > 0.92
+#
+# 2004-06-11:
+# shows [typing: ] in &bitlbee with multiple users.
+#
+use strict;
+use Irssi::TextUI;
+use Data::Dumper;
+
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.7.1';
+%IRSSI = (
+ authors => 'Tijmen "timing" Ruizendaal, Matt "f0rked" Sparks',
+ contact => 'tijmen.ruizendaal@gmail.com, root@f0rked.com',
+ name => 'BitlBee_typing_notice',
+ description => '1. Adds an item to the status bar wich shows [typing] when someone is typing a message on the supported IM-networks 2. Sends typing notices to the supported IM networks (the other way arround). (For bitlbee 3.0+)',
+ license => 'GPLv2',
+ url => 'http://the-timing.nl/stuff/irssi-bitlbee, http://f0rked.com',
+ changed => '2010-08-09',
+);
+
+my $bitlbee_server; # server object
+my @control_channels; # mostly: &bitlbee, &facebook etc.
+init();
+
+sub init { # if script is loaded after connect
+ my @servers = Irssi::servers();
+ foreach my $server(@servers) {
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ my @channels = $server->channels();
+ foreach my $channel(@channels) {
+ if( $channel->{mode} =~ /C/ ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+ }
+ }
+ }
+}
+# if connect after script is loaded
+Irssi::signal_add_last('event 005' => sub {
+ my( $server ) = @_;
+ if( $server->isupport('NETWORK') eq 'BitlBee' ){
+ $bitlbee_server = $server;
+ }
+});
+# if new control channel is synced after script is loaded
+Irssi::signal_add_last('channel sync' => sub {
+ my( $channel ) = @_;
+ if( $channel->{mode} =~ /C/ && $channel->{server}->{tag} eq $bitlbee_server->{tag} ){
+ push @control_channels, $channel->{name} unless (grep $_ eq $channel->{name}, @control_channels);
+ }
+});
+
+# How often to check if we are typing, or on msn,
+# how long to keep the typing notice up, or check
+# if the other user is still typing...
+my $KEEP_TYPING_TIMEOUT = 1;
+my $STOP_TYPING_TIMEOUT = 7;
+
+my %timer_tag;
+
+my %typing;
+my %tag;
+my $line;
+my %out_typing;
+my $lastkey;
+my $keylog_active = 1;
+my $command_char = Irssi::settings_get_str('cmdchars'); # mostly: /
+my $to_char = Irssi::settings_get_str("completion_char"); # mostly: :
+
+sub event_ctcp_msg {
+ my ($server, $msg, $from, $address) = @_;
+ return if $server->{tag} ne $bitlbee_server->{tag};
+ if ( my($type) = $msg =~ "TYPING ([0-9])" ){
+ Irssi::signal_stop();
+ if( $type == 0 ){
+ unset_typing($from);
+ } elsif( $type == 1 ){
+ $typing{$from}=1;
+ if( $address !~ /\@login\.oscar\.aol\.com/ and $address !~ /\@YAHOO/ and $address !~ /\@login\.icq\.com/ ){
+ Irssi::timeout_remove($tag{$from});
+ delete($tag{$from});
+ $tag{$from}=Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000,"unset_typing",$from);
+ }
+ redraw($from);
+ } elsif( $type == 2 ){
+ stale_typing($from);
+ }
+ }
+}
+
+sub unset_typing {
+ my($from,$no_redraw)=@_;
+ delete $typing{$from} if $typing{$from};
+ Irssi::timeout_remove($tag{$from});
+ delete($tag{$from});
+ redraw($from) if !$no_redraw;
+}
+
+sub stale_typing {
+ my($from)=@_;
+ $typing{$from}=2;
+ redraw($from);
+}
+
+sub redraw {
+ my($from)=@_;
+ my $window = Irssi::active_win();
+ my $name = $window->get_active_name();
+
+ # only redraw if current window equals to the typing person, is a control channel or if allwin is set
+ if( $from eq $name || (grep $_ eq $name, @control_channels) || Irssi::settings_get_bool("bitlbee_typing_allwin") ){
+ Irssi::statusbar_items_redraw('typing_notice');
+ }
+}
+
+sub event_msg {
+ my ($server,$data,$from,$address,$target) = @_;
+ return if $server->{tag} ne $bitlbee_server->{tag};
+ my $channel=Irssi::active_win()->get_active_name();
+ unset_typing $from, "no redraw";
+ unset_typing $channel;
+}
+
+sub event_quit {
+ my $server = shift;
+ return if $server->{tag} ne $bitlbee_server->{tag};
+ my $nick = shift;
+ unset_typing $nick;
+}
+
+sub typing_notice {
+ my ($item, $get_size_only) = @_;
+ my $window = Irssi::active_win();
+ my $channel = $window->get_active_name();
+
+ if (exists($typing{$channel})) {
+ my $append=$typing{$channel}==2 ? " (stale)" : "";
+ $item->default_handler($get_size_only, "{sb typing$append}", 0, 1);
+ } else {
+ $item->default_handler($get_size_only, "", 0, 1);
+ Irssi::timeout_remove($tag{$channel});
+ delete($tag{$channel});
+ }
+ # we check for correct windows again, because the statusbar item is redrawn after window change too.
+ if( (grep $_ eq $channel, @control_channels) || Irssi::settings_get_bool("bitlbee_typing_allwin")) {
+ foreach my $key (keys(%typing)) {
+ $line .= " ".$key;
+ if ($typing{$key}==2) { $line .= " (stale)"; }
+ }
+ if ($line ne "") {
+ $item->default_handler($get_size_only, "{sb typing:$line}", 0, 1);
+ $line = "";
+ }
+ }
+}
+
+sub window_change {
+ Irssi::statusbar_items_redraw('typing_notice');
+ my $win = !Irssi::active_win() ? undef : Irssi::active_win()->{active};
+ if (ref $win && ($win->{server}->{tag} eq $bitlbee_server->{tag})) {
+ if (!$keylog_active) {
+ $keylog_active = 1;
+ Irssi::signal_add_last('gui key pressed', 'key_pressed');
+ }
+ } else {
+ if ($keylog_active) {
+ $keylog_active = 0;
+ Irssi::signal_remove('gui key pressed', 'key_pressed');
+ }
+ }
+}
+
+sub key_pressed {
+ return if !Irssi::settings_get_bool("bitlbee_send_typing");
+ my $key = shift;
+ if ($key != 9 && $key != 10 && $lastkey != 27 && $key != 27
+ && $lastkey != 91 && $key != 126 && $key != 127)
+ {
+ my $server = Irssi::active_server();
+ my $window = Irssi::active_win();
+ my $nick = $window->get_active_name();
+
+ if ($server->{tag} eq $bitlbee_server->{tag} && $nick ne "(status)" && $nick ne "root") {
+ if( grep $_ eq $nick, @control_channels ){ # send typing if in control channel
+ my $input = Irssi::parse_special("\$L");
+ my ($first_word) = split(/ /,$input);
+ if ($input !~ /^$command_char.*/ && $first_word =~ s/$to_char$//){
+ send_typing($first_word);
+ }
+ } else { # or any other channels / query
+ my $input = Irssi::parse_special("\$L");
+ if ($input !~ /^$command_char.*/ && length($input) > 0){
+ send_typing($nick);
+ }
+ }
+ }
+ }
+ $lastkey = $key;
+}
+
+sub out_empty {
+ my ($a) = @_;
+ my($nick,$tag)=@{$a};
+ delete($out_typing{$nick});
+ Irssi::timeout_remove($timer_tag{$nick});
+ delete($timer_tag{$nick});
+ $bitlbee_server->command("^CTCP $nick TYPING 0");
+}
+
+sub send_typing {
+ my $nick = shift;
+ if (!exists($out_typing{$nick}) || time - $out_typing{$nick} > $KEEP_TYPING_TIMEOUT) {
+ $bitlbee_server->command("^CTCP $nick TYPING 1");
+ $out_typing{$nick} = time;
+ ### Reset 'stop-typing' timer
+ Irssi::timeout_remove($timer_tag{$nick});
+ delete($timer_tag{$nick});
+
+ ### create new timer
+ $timer_tag{$nick} = Irssi::timeout_add_once($STOP_TYPING_TIMEOUT*1000, 'out_empty', ["$nick", $bitlbee_server->{tag}]);
+ }
+}
+
+#README: Delete the old bitlbee_send_typing string from ~/.irssi/config. A boolean is better.
+
+sub db_typing {
+ print "Detected channels: ";
+ print Dumper(@control_channels);
+ print "Detected server tag: ".$bitlbee_server->{tag};
+ print "Tag: ".Dumper(%tag);
+ print "Timer Tag: ".Dumper(%timer_tag);
+ print "Typing: ".Dumper(%typing);
+ print "Out Typing: ".Dumper(%out_typing);
+}
+
+Irssi::command_bind('db_typing','db_typing');
+
+Irssi::settings_add_bool("bitlbee","bitlbee_send_typing",1);
+Irssi::settings_add_bool("bitlbee","bitlbee_typing_allwin",0);
+
+Irssi::signal_add("ctcp msg", "event_ctcp_msg");
+Irssi::signal_add("message private", "event_msg");
+Irssi::signal_add("message public", "event_msg");
+Irssi::signal_add("message quit", "event_quit");
+Irssi::signal_add_last('window changed', 'window_change');
+Irssi::signal_add_last('gui key pressed', 'key_pressed');
+Irssi::statusbar_item_register('typing_notice', undef, 'typing_notice');
+Irssi::statusbars_recreate_items();
diff --git a/scripts/blowjob.pl b/scripts/blowjob.pl
new file mode 100644
index 0000000..27e2fcc
--- /dev/null
+++ b/scripts/blowjob.pl
@@ -0,0 +1,558 @@
+#!/usr/bin/perl -w
+use strict;
+
+# BlowJob 0.9.0, a crypto script - ported from xchat
+# was based on rodney mulraney's crypt
+# changed crypting method to Blowfish+Base64+randomness+Z-compression
+# needs :
+# Crypt::CBC,
+# Crypt::Blowfish,
+# MIME::Base64,
+# Compress::Zlib
+#
+# crypted format is :
+# HEX(Base64((paranoia-factor)*(blowfish(RANDOM+Zcomp(string))+RANDOM)))
+#
+# 10-03-2004 Removed seecrypt, fixed two minor bugs
+# 09-03-2004 Supporting multiline messages now.
+# 08-03-2004 Lots of bugfixes on the irssi version by Thomas Reifferscheid
+# 08-03-2004 CONF FILE FORMAT CHANGED
+#
+# from server:channel:key:paranoia
+# to server:channel:paranoia:key
+#
+# /perm /bconf /setkey /showkey working now
+# keys may contain colons ":" now.
+#
+#
+# 06-12-2001 Added default umask for blowjob.keys
+# 05-12-2001 Added paranoia support for each key
+# 05-12-2001 Added conf file support
+# 05-12-2001 Added delkey and now can handle multi-server/channel keys
+# 05-12-2001 permanent crypting to a channel added
+# 05-12-2001 Can now handle multi-channel keys
+# just /setkey on the channel you are to associate a channel with a key
+#
+# --- conf file format ---
+#
+# # the generic key ( when /setkey has not been used )
+# key: generic key value
+# # header that marks a crypted sentance
+# header: {header}
+# # enable wildcards for multiserver entries ( useful for OPN for example )
+# wildcardserver: yes
+#
+# --- end of conf file ---
+#
+# iMil
+# skid
+# Foxmask
+# Thomas Reifferscheid
+
+use Crypt::CBC;
+use Crypt::Blowfish;
+use MIME::Base64;
+use Compress::Zlib;
+
+use Irssi::Irc;
+use Irssi;
+use vars qw($VERSION %IRSSI $cipher);
+
+$VERSION = "0.9.0";
+%IRSSI = (
+ authors => 'iMil,Skid,Foxmask,reiffert',
+ contact => 'imil@gcu-squad.org,blowjob@reifferscheid.org,#blowtest@freenode',
+ name => 'blowjob',
+ description => 'Crypt IRC communication with blowfish encryption. Supports public #channels, !channels, +channel, querys and dcc chat. Roadmap for Version 1.0.0 is to get some feedback and cleanup. Join #blowtest on freenode (irc.debian.org) to get latest stuff available. Note to users upgrading from versions prior to 0.8.5: The blowjob.keys format has changed.',
+ license => 'GNU GPL',
+ url => 'http://ftp.gcu-squad.org/misc/',
+);
+
+
+############# IRSSI README AREA #################################
+#To install this script just do
+#/script load ~/blowjob-irssi.pl
+# and
+#/blowhelp
+# to read all the complete feature of the script :)
+#To uninstall it do
+#/script unload blowjob-irssi
+################################################################
+
+
+my $key = 'very poor key' ; # the default key
+my $header = "{blow}";
+# Crypt loops, 1 should be enough for everyone imho ;)
+# please note with a value of 4, a single 4-letter word can generate
+# a 4 line crypted sentance
+my $paranoia = 1;
+# add a server mask by default ?
+my $enableWildcard="yes";
+
+my $alnum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+my $gkey;
+sub loadconf
+{
+ my $fconf =Irssi::get_irssi_dir()."/blowjob.conf";
+ my @conf;
+ open (CONF, "<$fconf");
+
+ if (!( -f CONF)) {
+ Irssi::print("\00305> $fconf not found, setting to defaults\n");
+ Irssi::print("\00305> creating $fconf with default values\n\n");
+ close(CONF);
+ open(CONF,">$fconf");
+ print CONF "key: $key\n";
+ print CONF "header: $header\n";
+ print CONF "wildcardserver: $enableWildcard\n";
+ close(CONF);
+ return 1;
+ }
+
+ @conf=;
+ close(CONF);
+
+ my $current;
+ foreach(@conf) {
+ $current = $_;
+ $current =~ s/\n//g;
+ if ($current =~ m/key/) {
+ $current =~ s/.*\:[\ \t]*//;
+ $key = $current;
+ $gkey = $key;
+ }
+ if ($current =~ m/header/) {
+ $current =~ s/.*\:[\s\t]*\{(.*)\}.*/{$1}/;
+ $header = $current;
+ }
+ if ($current =~ m/wildcardserver/) {
+ $current =~ s/.*\:[\ \t]*//;
+ $enableWildcard = $current;
+ }
+ }
+ Irssi::print("\00314- configuration file loaded\n");
+ return 1;
+}
+loadconf;
+
+my $kfile ="$ENV{HOME}/.irssi/blowjob.keys";
+my @keys;
+$gkey=$key;
+my $gparanoia=$paranoia;
+
+sub loadkeys
+{
+ if ( -e "$kfile" ) {
+ open (KEYF, "<$kfile");
+ @keys = ;
+ close (KEYF);
+ }
+ Irssi::print("\00314- keys reloaded (Total:\00315 ".scalar @keys."\00314)\n");
+ return 1;
+}
+loadkeys;
+
+sub getkey
+{
+ my ($curserv, $curchan) = @_;
+
+ my $gotkey=0;
+ my $serv;
+ my $chan;
+ my $fkey;
+
+ foreach(@keys) {
+ chomp; # keys can contain ":" now. Note:
+ my ($serv,$chan,$fparanoia,$fkey)=split /:/,$_,4; # place of paranoia has changed!
+ if ( $curserv =~ /$serv/ and $curchan eq $chan ) {
+ $key= $fkey;
+ $paranoia=$fparanoia;
+ $gotkey=1;
+ }
+ }
+ if (!$gotkey) {
+ $key=$gkey;
+ $paranoia=$gparanoia;
+ }
+ $cipher=new Crypt::CBC($key,'Blowfish',undef);
+}
+
+sub setkey
+{
+ my (undef,$server, $channel) = @_;
+ if (! $channel) { return 1; }
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+ # my $key = $data;
+
+ my $fparanoia;
+
+ my $newchan=1;
+ umask(0077);
+ unless ($_[0] =~ /( +\d$)/) {
+ $_[0].= " $gparanoia";
+ }
+ ($key, $fparanoia) = ($_[0] =~ /(.*) +(\d)/);
+
+ if($enableWildcard =~ /[Yy][Ee][Ss]/) {
+ $curserv =~ s/(.*?)\./(.*?)\./;
+ Irssi::print("\00314IRC server wildcards enabled\n");
+ }
+
+ # Note, place of paranoia has changed!
+ my $line="$curserv:$curchan:$fparanoia:$key";
+
+ open (KEYF, ">$kfile");
+ foreach(@keys) {
+ s/\n//g;
+ if (/^$curserv\:$curchan\:/) {
+ print KEYF "$line\n";
+ $newchan=0;
+ } else {
+ print KEYF "$_\n";
+ }
+ }
+ if ($newchan) {
+ print KEYF "$line\n";
+ }
+ close (KEYF);
+ loadkeys;
+ Irssi::active_win()->print("\00314key set to \00315$key\00314 for channel \00315$curchan");
+ return 1 ;
+}
+
+sub delkey
+{
+ my ($data, $server, $channel) = @_;
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+
+ my $serv;
+ my $chan;
+
+ open (KEYF, ">$kfile");
+ foreach(@keys) {
+ s/\n//g;
+ ($serv,$chan)=/^(.*?)\:(.*?)\:/;
+ unless ($curserv =~ /$serv/ and $curchan=~/^$chan$/) {
+ print KEYF "$_\n";
+ }
+ }
+ close (KEYF);
+ Irssi::active_win()->print("\00314key for channel \00315$curchan\00314 deleted");
+ loadkeys;
+ return 1 ;
+}
+
+sub showkey {
+ my (undef, $server, $channel) = @_;
+ if (! $channel) { return 1; }
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+
+ getkey($curserv,$curchan);
+
+ Irssi::active_win()->print("\00314current key is : \00315$key");
+ return 1 ;
+}
+
+sub enc
+{
+ my ($curserv,$curchan, $in) = @_;
+ my $prng1="";
+ my $prng2="";
+
+ # copy & paste from former sub blow()
+
+ for (my $i=0;$i<4;$i++) {
+ $prng1.=substr($alnum,int(rand(61)),1);
+ $prng2.=substr($alnum,int(rand(61)),1);
+ }
+
+
+ getkey($curserv,$curchan);
+
+ $cipher->start('encrypting');
+
+ my $tbout = compress($in);
+ my $i;
+ for ($i=0;$i<$paranoia;$i++) {
+ $tbout = $prng1.$tbout;
+ $tbout = $cipher->encrypt($tbout);
+ $tbout .= $prng2;
+ # don't wan't to see "RandomIV"
+ $tbout =~ s/^.{8}//;
+ }
+
+ $tbout = encode_base64($tbout);
+ $tbout = unpack("H*",$tbout);
+ $tbout = $header." ".$tbout;
+ $tbout =~ s/=+$//;
+
+ $cipher->finish();
+
+ return (length($tbout),$tbout);
+
+}
+
+sub irclen
+{
+ my ($len,$curchan,$nick,$userhost) = @_;
+
+ # calculate length of "PRIVMSG #blowtest :{blow} 4b7257724a ..." does not exceed
+ # it may not exceed 511 bytes
+ # result gets handled by caller.
+
+ return ($len + length($curchan) + length("PRIVMSG : ") + length($userhost) + 1 + length($nick) );
+}
+sub recurs
+{
+ my ($server,$curchan,$in) = @_;
+
+ # 1. devide input line by 2. <--|
+ # into two halfes, called $first and $second. |
+ # 2. try to decrease $first to a delimiting " " |
+ # but only try on the last 8 bytes ^
+ # 3. encrypt $first |
+ # if result too long, call sub recurs($first)----
+ # 4. encrypt $second ^
+ # if result too long, call sub recurs($second)--|
+ # 5. pass back encrypted halfes as reference
+ # to an array.
+
+
+ my $half = length($in)/2-1;
+ my $first = substr($in,0,$half);
+ my $second = substr($in,$half,$half+3);
+ if ( (my $pos = rindex($first," ",length($first)-8) ) != -1)
+ {
+ $second = substr($first,$pos+1,length($first)-$pos) . $second;
+ $first = substr($first,0,$pos);
+ }
+
+ my @a;
+
+ my ($len,$probablyout);
+
+ ($len,$probablyout) = enc($server->{address},$curchan,$first);
+
+ if ( irclen($len,$curchan,$server->{nick},$server->{userhost}) > 510)
+ {
+ my @b=recurs($server,$curchan,$first);
+ push(@a,@{$b[0]});
+ } else {
+ push(@a,$probablyout);
+ }
+
+ ($len,$probablyout) = enc($server->{address},$curchan,$second);
+ if ( irclen($len,$curchan,$server->{nick},$server->{userhost}) > 510)
+ {
+ my @b = recurs($server,$curchan,$second);
+ push(@a,@{$b[0]});
+ } else {
+ push(@a,$probablyout);
+ }
+ return \@a;
+
+}
+
+
+sub printout
+{
+ my ($aref,$server,$curchan) = @_;
+
+ # encrypted lines get stored [ '{blow} yxcvasfd', '{blow} qewrdf', ... ];
+ # in an arrayref
+
+ foreach(@{$aref})
+ {
+ $server->command("/^msg -$server->{tag} $curchan ".$_);
+ }
+}
+
+sub enhanced_printing
+{
+ my ($server,$curchan,$in) = @_;
+
+ # calls the recursing sub recurs ... and
+ my $arref = recurs($server,$curchan,$in);
+ # print out.
+ printout($arref,$server,$curchan);
+
+}
+
+sub blow
+{
+ my ($data, $server, $channel) = @_;
+ if (! $channel) { return 1;}
+ my $in = $data ;
+ my $nick = $server->{nick};
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+
+ my ($len,$encrypted_message) = enc($curserv,$curchan,$in);
+
+ $server->print($channel->{name}, "<$nick|{crypted}> \00311$in",MSGLEVEL_CLIENTCRAP);
+
+ $len = length($encrypted_message); # kept for debugging
+
+ if ( irclen($len,$curchan,$server->{nick},$server->{userhost}) > 510)
+ {
+ # if complete message too long .. see sub irclen
+ enhanced_printing($server,$curchan,$data);
+ } else {
+ # everything is fine, just print out
+ $server->command("/^msg -$server->{tag} $curchan $encrypted_message");
+ }
+
+ return 1 ;
+}
+
+sub infoline
+{
+ my ($server, $data, $nick, $address) = @_;
+
+ my ($channel,$text,$msgline,$msgnick,$curchan,$curserv);
+
+ if ( ! defined($address) ) # dcc chat
+ {
+ $msgline = $data;
+ $curserv = $server->{server}->{address};
+ $channel = $curchan = "=".$nick;
+ $msgnick = $nick;
+ $server = $server->{server};
+ } else
+ {
+ ($channel, $text) = $data =~ /^(\S*)\s:(.*)/;
+ $msgline = $text;
+ $msgnick = $server->{nick};
+ $curchan = $channel;
+ $curserv = $server->{address};
+ }
+
+ if ($msgline =~ m/^$header/) {
+ my $out = $msgline;
+ $out =~ s/\0030[0-9]//g;
+ $out =~ s/^$header\s*(.*)/$1/;
+
+ if ($msgnick eq $channel)
+ {
+ $curchan = $channel = $nick;
+ }
+
+ getkey($curserv,$curchan);
+
+ $cipher->start('decrypting');
+ $out = pack("H*",$out);
+ $out = decode_base64($out);
+
+ my $i;
+ for ($i=0;$i<$paranoia;$i++) {
+ $out = substr($out,0,(length($out)-4));
+ # restore RandomIV
+ $out = 'RandomIV'.$out;
+ $out = $cipher->decrypt($out);
+ $out = substr($out,4);
+ }
+ $out = uncompress($out);
+
+ $cipher->finish;
+
+ if(length($out))
+ {
+ $server->print($channel, "<$nick|{uncrypted}> \00311$out", MSGLEVEL_CLIENTCRAP);
+ Irssi::signal_stop();
+ }
+ return 1;
+
+ }
+ return 0 ;
+}
+
+sub dccinfoline
+{
+ my ($server, $data) = @_;
+ infoline($server,$data,$server->{nick},undef);
+}
+my %permchans={};
+sub perm
+{
+ my ($data, $server, $channel) = @_;
+ if (! $channel) { return 1; }
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+
+ if ( exists($permchans{$curserv}{$curchan}) && $permchans{$curserv}{$curchan} == 1) {
+ delete $permchans{$curserv}{$curchan};
+ Irssi::active_win()->print("\00314not crypting to \00315$curchan\00314 on \00315$curserv\00314 anymore");
+ } else {
+ $permchans{$curserv}{$curchan} = 1;
+ Irssi::active_win()->print("\00314crypting to \00315$curchan on \00315$curserv");
+ }
+ return 1;
+}
+sub myline
+{
+ my ($data, $server, $channel) = @_;
+ if (! $channel) { return 1; }
+ my $curchan = $channel->{name};
+ my $curserv = $server->{address};
+ my $line = shift;
+ chomp($line);
+ if (length($line) == 0)
+ {
+ return;
+ }
+ my $gotchan = 0;
+ foreach(@keys) {
+ s/\n//g;
+ my ($serv,$chan,undef,undef)=split /:/;
+ if ( ($curserv =~ /$serv/ && $curchan =~ /^$chan$/ && exists($permchans{$curserv}{$curchan}) && $permchans{$curserv}{$curchan} == 1) || (exists($permchans{$curserv}{$curchan}) && $permchans{$curserv}{$curchan} == 1))
+ {
+ $gotchan = 1;
+ }
+ }
+ if ($gotchan)
+ {
+
+ blow($line,$server,$channel);
+ Irssi::signal_stop();
+ return 1;
+ }
+}
+
+sub reloadconf
+{
+ loadconf;
+ loadkeys;
+}
+sub help
+{
+ Irssi::print("\00314[\00303bl\003090\00303wjob\00314]\00315 script :\n");
+ Irssi::print("\00315/setkey [] :\00314 new key for current channel\n") ;
+ Irssi::print("\00315/delkey :\00314 delete key for current channel");
+ Irssi::print("\00315/showkey :\00314 show your current key\n") ;
+ Irssi::print("\00315/blow :\00314 send crypted line\n") ;
+ Irssi::print("\00315/perm :\00314 flag current channel as permanently crypted\n") ;
+ Irssi::print("\00315/bconf :\00314 reload blowjob.conf\n") ;
+
+ return 1 ;
+}
+
+Irssi::print("blowjob script $VERSION") ;
+Irssi::print("\n\00314[\00303bl\003090\00303wjob\00314] v$VERSION\00315 script loaded\n\n");
+Irssi::print("\00314- type \00315/blowhelp\00314 for options\n") ;
+Irssi::print("\00314- paranoia level is : \00315$paranoia\n") ;
+Irssi::print("\00314- generic key is : \00315$key\n") ;
+Irssi::print("\n\00314* please read script itself for documentation\n");
+Irssi::signal_add("event privmsg","infoline") ;
+Irssi::signal_add("dcc chat message","dccinfoline");
+Irssi::command_bind("blowhelp","help") ;
+Irssi::command_bind("setkey","setkey") ;
+Irssi::command_bind("delkey","delkey");
+Irssi::command_bind("blow","blow") ;
+Irssi::command_bind("showkey","showkey") ;
+Irssi::command_bind("perm","perm") ;
+Irssi::command_bind("bconf","reloadconf") ;
+Irssi::signal_add("send text","myline") ;
diff --git a/scripts/bmi.pl b/scripts/bmi.pl
new file mode 100644
index 0000000..a8a729d
--- /dev/null
+++ b/scripts/bmi.pl
@@ -0,0 +1,45 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+use Irssi qw(command_bind command_runsub);
+
+$VERSION = '2002121801';
+%IRSSI = (
+ authors => 'Daniel K. Gebhart, Marcus Rckert',
+ contact => 'dkg@con-fuse.org, darix@irssi.org',
+ name => 'BMI Calculator',
+ description => 'a simple body mass index calculator for depression ;)',
+ license => 'GPLv2',
+ url => 'http://dkg.con-fuse.org/irssi/scripts/',
+ changed => $VERSION,
+);
+
+sub bmi_help () {
+ print ( CLIENTCRAP "\nBMI []\n" );
+ print ( CLIENTCRAP "please specify weight in kilograms (10-999kg) and height in cm (10-999cm). you can use decimal places. output precision (0-9).\n" );
+ print ( CLIENTCRAP "The optimal BMI is 19-24 for women and 20-25 for men.\n" );
+}
+
+command_bind 'bmi help' => sub { bmi_help(); };
+
+command_bind 'bmi' => sub {
+ my ($data, $server, $item) = @_;
+ $data =~ s/\s+$//g;
+ $data =~ s/,/./g;
+ if ($data eq '') {
+ bmi_help();
+ }
+ elsif ( $data =~ m/^help/i ) {
+ command_runsub ( 'bmi', $data, $server, $item );
+ }
+ else {
+ if ( $data =~ m/^(\d{2,3}(\.\d+)?)\s+(\d{2,3}(\.\d+)?)(\s+(\d))?$/ ) {
+ my ($kg, $cm) = ($1, $3);
+ my $precision = ( defined ($6) ) ? $6 : 2;
+ print ( CRAP "with $kg kg at $cm cm you have a bmi of " . sprintf("%." . $precision . "f", ( ( $kg/$cm**2 ) *10000 ) ) );
+ }
+ else {
+ print ( CRAP "please specify weight in kilograms (10-999kg) and height in cm (10-999cm). you can use decimal places. output precision (0-9)." );
+ print ( CRAP "params were: $data" );
+ }
+ }
+};
diff --git a/scripts/buf.pl b/scripts/buf.pl
new file mode 100644
index 0000000..43b4b3d
--- /dev/null
+++ b/scripts/buf.pl
@@ -0,0 +1,122 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+
+use Irssi qw(command signal_add signal_add_first active_win
+ settings_get_str settings_get_bool channels windows
+ settings_add_str settings_add_bool get_irssi_dir
+ window_find_refnum signal_stop);
+$VERSION = '2.13';
+%IRSSI = (
+ authors => 'Juerd',
+ contact => 'juerd@juerd.nl',
+ name => 'Scroll buffer restorer',
+ description => 'Saves the buffer for /upgrade, so that no information is lost',
+ license => 'Public Domain',
+ url => 'http://juerd.nl/irssi/',
+ changed => 'Mon May 13 19:41 CET 2002',
+ changes => 'Severe formatting bug removed * oops, I ' .
+ 'exposed Irssi to ircII foolishness * sorry ' .
+ '** removed logging stuff (this is a fix)',
+ note1 => 'This script HAS TO BE in your scripts/autorun!',
+ note2 => 'Perl support must be static or in startup',
+);
+
+# Q: How can I get a very smooth and clean upgrade?
+#
+# A: /set -clear upgrade_separator
+# /set upgrade_suppress_join ON (default)
+# /set channel_sync OFF
+
+# Q: Can I use color in the upgrade_separator?
+# Q: Is it possible to save my command history?
+# Q: Can I prevent the screen from blinking?
+# Q: Can you make it faster?
+#
+# A: Probably not, but if you can do it, tell me how.
+
+use Irssi::TextUI;
+use Data::Dumper;
+
+my %suppress;
+
+sub upgrade {
+ open BUF, sprintf('>%s/scrollbuffer', get_irssi_dir) or die $!;
+ print BUF join("\0", map $_->{server}->{address} . $_->{name}, channels), "\n";
+ for my $window (windows) {
+ next unless defined $window;
+ next if $window->{name} eq 'status';
+ my $view = $window->view;
+ my $line = $view->get_lines;
+ my $lines = 0;
+ my $buf = '';
+ if (defined $line){
+ {
+ $buf .= $line->get_text(1) . "\n";
+ $line = $line->next;
+ $lines++;
+ redo if defined $line;
+ }
+ }
+ printf BUF "%s:%s\n%s", $window->{refnum}, $lines, $buf;
+ }
+ close BUF;
+ unlink sprintf("%s/sessionconfig", get_irssi_dir);
+ command 'layout save';
+ command 'save';
+}
+
+sub restore {
+ open BUF, sprintf('<%s/scrollbuffer', get_irssi_dir) or die $!;
+ my @suppress = split /\0/, ;
+ if (settings_get_bool 'upgrade_suppress_join') {
+ chomp $suppress[-1];
+ @suppress{@suppress} = (2) x @suppress;
+ }
+ active_win->command('^window scroll off');
+ while (my $bla = ){
+ chomp $bla;
+ my ($refnum, $lines) = split /:/, $bla;
+ next unless $lines;
+ my $window = window_find_refnum $refnum;
+ unless (defined $window){
+ for 1..$lines;
+ next;
+ }
+ my $view = $window->view;
+ $view->remove_all_lines();
+ $view->redraw();
+ my $buf = '';
+ $buf .= for 1..$lines;
+ my $sep = settings_get_str 'upgrade_separator';
+ $sep .= "\n" if $sep ne '';
+ $window->gui_printtext_after(undef, MSGLEVEL_CLIENTNOTICE, "$buf\cO$sep");
+ $view->redraw();
+ }
+ active_win->command('^window scroll on');
+ active_win->command('^scrollback end');
+}
+
+sub suppress {
+ my ($first, $second) = @_;
+ return
+ unless scalar keys %suppress
+ and settings_get_bool 'upgrade_suppress_join';
+ my $key = $first->{address} .
+ (grep { (s/^://, /^[#!+&]/) } split ' ', $second)[0];
+ if (exists $suppress{$key} and $suppress{$key}--) {
+ signal_stop();
+ delete $suppress{$key} unless $suppress{$key};
+ }
+}
+
+settings_add_str 'buffer', 'upgrade_separator' => '=Upgrade=';
+settings_add_bool 'buffer', 'upgrade_suppress_join' => 1;
+
+signal_add_first 'session save' => 'upgrade';
+signal_add_first 'session restore' => 'restore';
+signal_add 'event 366' => 'suppress';
+signal_add 'event join' => 'suppress';
+
+unless (-f sprintf('%s/scripts/autorun/buf.pl', get_irssi_dir)) {
+ Irssi::print('PUT THIS SCRIPT IN ~/.irssi/scripts/autorun/ BEFORE /UPGRADING!!');
+}
diff --git a/scripts/calc.pl b/scripts/calc.pl
new file mode 100644
index 0000000..21aa7de
--- /dev/null
+++ b/scripts/calc.pl
@@ -0,0 +1,30 @@
+use strict;
+use vars qw($VERSION %IRSSI);
+
+use Irssi qw(command_bind active_win);
+$VERSION = '1.10';
+%IRSSI = (
+ authors => 'Juerd',
+ contact => 'juerd@juerd.nl',
+ name => 'Calculator',
+ description => 'Simple /calc mechanism',
+ license => 'Public Domain',
+ url => 'http://juerd.nl/irssi/',
+ changed => 'Thu Mar 19 11:00 CET 2002',
+);
+
+command_bind(
+ calc => sub {
+ my ($msg) = @_;
+ for ($msg) {
+ s/,/./g;
+ s/[^*.+0-9&|)(x\/^-]//g;
+ s/\*\*/^/g;
+ s/([*+\\.\/x-])\1*/$1/g;
+ s/\^/**/g;
+ s/(?print($@ ? "$msg = ERROR (${\ (split / at/, $@, 2)[0]})" : "$msg = $answer");
+ }
+);
diff --git a/scripts/callerid.pl b/scripts/callerid.pl
new file mode 100644
index 0000000..8931f6c
--- /dev/null
+++ b/scripts/callerid.pl
@@ -0,0 +1,135 @@
+use strict;
+use Irssi;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = "1.0";
+%IRSSI = (
+ authors => 'Daniel "dubkat" Reidy',
+ contact => 'dubkat@dubkat.org (www.dubkat.org)',
+ name => 'callerid',
+ description => 'Reformats CallerID (+g) Messages
+ (Also known as Server-Side Ignore)
+ on Hybrid & Ratbox IRCDs (EFnet)
+ to be Easier on the Eyes',
+ license => 'GPL',
+ url => 'http://scripts.irssi.org/',
+);
+
+#########################################################################################
+# Thanks to Geert and Senneth for helping me out with my first irssi script! #
+# Hopefully someone will find this useful. #
+# #
+# Callerid is used to block messages from users at the server. #
+# Callerid mode is activated by usermode +g on Hybrid and Ratbox servers (EFnet) #
+# The ircd maintains a list of users that may message you. #
+# To add users to the list, do /quote accept NICK #
+# The IRCD will *NOT* inform you that the user has been added. #
+# To remove a user from the list do /quote accept -NICK #
+# The IRCD will *NOT* inform you that the user has been removed. #
+# To see a list of users on your accept list do /quote accept * #
+# #
+# The following alias may make life easier: #
+# alias accept quote accept #
+#########################################################################################
+
+Irssi::signal_add('event 716', 'callerid_them');
+ sub callerid_them {
+ my ($server, $data) = @_;
+ my (undef, $nick, undef) = split(/ +/, $data, 3);
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'callerid_them', $nick);
+ Irssi::signal_stop();
+ }
+
+Irssi::signal_add('event 717', 'callerid_them_notified');
+ sub callerid_them_notified {
+ my ($server, $data) = @_;
+ my (undef, $nick, undef) = split(/ +/, $data, 3);
+ $server->printformat($nick, MSGLEVEL_CLIENTCRAP, 'callerid_them_notified', $nick);
+ Irssi::signal_stop();
+ }
+
+Irssi::signal_add('event 282', 'callerid_accept_eof');
+ sub callerid_accept_eof { Irssi::signal_stop(); }
+
+Irssi::signal_add('event 718', 'callerid_you');
+ sub callerid_you {
+ my ($server, $data) = @_;
+ my (undef, $nick, $host, undef) = split(/ +/, $data, 4);
+ $server->printformat($nick, MSGLEVEL_CLIENTCRAP, 'callerid_you', $nick, $host);
+ Irssi::signal_stop();
+ }
+
+Irssi::signal_add('event 281', 'callerid_accept_list');
+ sub callerid_accept_list {
+ my ($server, $data) = @_;
+ my (undef, $list, undef) = split(/ +/, $data, 3);
+ $data =~ s/^\S+\s//;
+ $data =~ s/\s+:$//;
+ $server->printformat($data, MSGLEVEL_CLIENTCRAP, 'callerid_accept_list', $data);
+ Irssi::signal_stop();
+ }
+
+
+Irssi::signal_add('event 457', 'callerid_accept_exsists');
+ sub callerid_accept_exsists {
+ my ($server, $data) = @_;
+ my (undef, $nick, undef) = split(/ +/, $data, 3);
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'callerid_accept_exsists', $nick);
+ Irssi::signal_stop();
+ }
+
+
+Irssi::signal_add('event 458', 'callerid_not_on_list');
+ sub callerid_not_on_list {
+ my ($server, $data) = @_;
+ my (undef, $info, undef) = split(/ +/, $data, 3);
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'callerid_not_on_list', $info);
+ Irssi::signal_stop();
+ }
+
+Irssi::signal_add('event 456', 'callerid_full');
+ sub callerid_full {
+ my ($server, $data) = @_;
+ my (undef, $info) = split(/ +/, $data, 2);
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'callerid_full', $info);
+ Irssi::signal_stop();
+ }
+
+Irssi::signal_add('event 401', 'callerid_invalid_nick');
+ sub callerid_invalid_nick{
+ my ($server, $data) = @_;
+ my (undef, $info, undef) = split(/ +/, $data, 3);
+ Irssi::printformat(MSGLEVEL_CLIENTCRAP, 'callerid_invalid_nick', $info);
+ Irssi::signal_stop();
+ }
+
+
+Irssi::theme_register
+ (
+ [
+ 'callerid_them',
+ '%_[%_%RCALLERID%n%_]%_ %W$0%n is in server-side ignore.',
+
+ 'callerid_you',
+ '%_[%_%yCALLERID%n%_]%_ %W$0%n ($1) is attempting to message you.',
+
+ 'callerid_accept_list',
+ '%_[%_%gACCEPTED%n%_]%_ %W$0%n',
+
+ 'callerid_accept_exsists',
+ '%_[%_%BCALLERID%n%_]%_ %W$0%n Is Already On Your Accept List. Do %_/quote accept *%_ for a list :)',
+
+ 'callerid_full',
+ '%_[%_%pCALLERID%n%_]%_ List is full. Do %_/quote accept *%_ for a list',
+
+ 'callerid_not_on_list',
+ '%_[%_%pCALLERID%n%_]%_ $0 is not a user on your accept list.',
+
+ 'callerid_invalid_nick',
+ '%_[%_%pCALLERID%n%_]%_ Cannot add/remove $0. That nick does not exist.',
+
+ 'callerid_them_notified',
+ '%_[%_%rCALLERID%n%_]%_ %_$0%_ has been notified that you attempted to message them. (They will not notified of further messages for 60sec).',
+
+ ]
+ );
diff --git a/scripts/cddb.pl b/scripts/cddb.pl
new file mode 100644
index 0000000..6322313
--- /dev/null
+++ b/scripts/cddb.pl
@@ -0,0 +1,122 @@
+
+#############
+# ZaMz0n 28-Oct-2003
+# ZaMz0n 10-Dec-2003
+#############
+
+use strict;
+use Irssi;
+use LWP::Simple;
+use vars qw($VERSION %IRSSI);
+
+$VERSION = '1.21';
+%IRSSI = (
+ authors => 'ZaMz0n',
+ contact => 'zamzon@freakpower.com',
+ name => 'cddb',
+ description => 'Find CDs by Artist, Disc name or Track name in CDDB.',
+ license => 'Free',
+ url => 'http://www.gracenote.com/music/',
+ changed => 'Wed Oct 29 01:27:00 CET 2003',
+ commands => 'cddb'
+);
+
+# MAIN FUNCTION STARTS HERE
+sub cddb_query {
+
+# Set SEARCH variables
+ my $howto = "\cbUsage:\cb !cddb [] [-d ] [-a ] [-t |