From 0ffb46aaea4cb56c3b46a4d3fe5930bd66f4b1b0 Mon Sep 17 00:00:00 2001 From: Rich Healey Date: Fri, 7 Jan 2011 10:40:27 +1100 Subject: Merged changes from master Shabble, you can now unmerge them if you want. --- auto-server/auto_server-ng.pl | 224 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 auto-server/auto_server-ng.pl (limited to 'auto-server') diff --git a/auto-server/auto_server-ng.pl b/auto-server/auto_server-ng.pl new file mode 100644 index 0000000..b54ca26 --- /dev/null +++ b/auto-server/auto_server-ng.pl @@ -0,0 +1,224 @@ +# This script was initially written by shabble, this fork (and molestation) is +# built upon his original work. +# +# USAGE: +# +# the primary command used is /join+ #channelname +# +# Mappings for channels to servers is accomplished with the +# joinplus_server_maps setting. +# +# Within this setting, space separated pairs denote channel, server pairs. +# Spaces also separate individual pairs, for example: +# +# /set joinplus_server_maps #foo Freenode #bar irc.somewhere.tld #meep DALNet +# +# Then use /join+ #foo, and if you are not already connected to freenode, it +# will connect you, and then join that channel. + +# TODO: +# Autocompletion for channel names +# address conflict resolution +# fix that disgusting race condition + +use strict; +use warnings; + + +use Irssi; +use Irssi::Irc; +use Irssi::TextUI; + +use Data::Dumper; + + +my $DEBUG_ENABLED = 0; +sub DEBUG () { $DEBUG_ENABLED } + +sub _debug_print { + return unless DEBUG; + return unless scalar (grep { defined && length } @_) == @_; + my $win = Irssi::active_win; + my $str = join('', @_); + $win->print($str, Irssi::MSGLEVEL_CLIENTCRAP); +} + +our $VERSION = '0.0.' . (split(/ /, '$Rev: 362 $'))[1]; + +our %IRSSI = ( + authors => 'shabble, richo', + contact => 'richo@psych0tik.net', + name => 'auto-join-ng', + description => 'connects to a specified server in order to connect' . + ' to a channel there, without having first to' . + ' connect to the server', + license => 'Public Domain', + ); + +my $channel_map = {}; +my @hack_channels; +my $pending_joins; + +sub auto_server_init { + Irssi::command_bind('join+', \&join_plus); + Irssi::settings_add_str('join_plus', 'joinplus_server_maps', ''); + Irssi::signal_add_last('setup changed', \&setup_changed); + Irssi::settings_add_bool('join_plus', 'join_plus_debug', 0); + + setup_changed(); + $pending_joins = {}; + +} + +sub setup_changed { + $DEBUG_ENABLED = Irssi::settings_get_bool('join_plus_debug'); + parse_channel_map(); +} + +# This is a tremendous kludge. +# If anyone knows a better way to get this listing, I'd like to hear it. +# This has so many race condition bugs I just don't even know where to start. +sub retrieve_channels { + @hack_channels = (); + Irssi::signal_add_first('print text', 'haxy_print_hook'); + Irssi::command("CHANNEL LIST"); + Irssi::signal_remove('print text', 'haxy_print_hook'); + return join(" ", @hack_channels); +} + + +# The idea for how to do this courtesy of http://wouter.coekaerts.be/site/irssi/aliases +sub haxy_print_hook { + Irssi::signal_remove('print text', 'haxy_print_hook'); + Irssi::signal_stop(); + my $data = $_[1]; + # Hose control characters + $data =~ s/\x04.//g; + if ($data =~ m/^#/) { + my @items = split /\s+/, $data; + push(@hack_channels, $items[0]); + push(@hack_channels, $items[1]); + } + Irssi::signal_add_first('print text', 'haxy_print_hook'); +} + +sub parse_channel_map { + #my $data = Irssi::settings_get_str('joinplus_server_maps'); + my $data = retrieve_channels(); + unbind_completion(); + my @items = split /\s+/, $data; + if (@items % 2 == 0) { + $channel_map = { @items }; # risky? + } else { + Irssi::active_win->print("Could not process channel => server mappings"); + $channel_map = {}; + } + _debug_print Dumper($channel_map); + bind_completion(); +} + +# Bind a stack of commands so that irssi knows to complete them. +sub bind_completion { + foreach(%$channel_map) { + Irssi::command_bind("join+ $_", \&join_plus); + } +} + +sub unbind_completion { + foreach(%$channel_map) { + Irssi::command_unbind("join+ $_", \&join_plus); + } +} + + +sub join_plus { + my ($args, $cmd_server, $witem) = @_; + #print Dumper($cmd, "moo", $win); + + # parse out channel name from args: + my $channel; + if ($args =~ m/^(#?[#a-zA-Z0-9]+)/) { + $channel = $1; + _debug_print ("Channel is: $channel"); + } + + unless ($channel) { + Irssi::active_win()->print("Channel $args not recognised"); + return; + } + + # lookup server + my $server_id = $channel_map->{$channel}; + _debug_print($server_id); + + unless ($server_id) { + Irssi::active_win()->print("Channel $channel does not have an" + . " appropriate server mapping"); + return; + } + # TODO: search values() and give a 'did you mean' for closest channel + + # check if we're connected to that server + my $server = Irssi::server_find_tag($server_id); + + if (not defined $server) { + $server = Irssi::server_find_chatnet($server_id); + } + + if (not defined $server) { + # still no server, walk the server list looking for address matches. + my @servers = Irssi::servers(); + foreach my $srv (@servers) { + if (($srv->{address} eq $server_id) or + ($srv->{real_address} eq $server_id)) { + $server = $srv; + last; + } + } + } + + if (defined $server) { + + _debug_print ("Already connected to server: " . $server->{tag} ); + + # check if we're already on the required channel + my $on_channel = $server->channel_find($channel); + + if (defined $channel && ref($channel) eq 'Irssi::Irc::Channel') { + Irssi::active_win()->print("You are already connected to " + . " $channel on " . $server->{tag}); + return; + } else { + _debug_print ("joining channel: $channel"); + $server->command("JOIN $channel"); + } + } else { + # not connected to server. + _debug_print ("connecting to server: $server_id"); + + Irssi::command("CONNECT $server_id"); + _debug_print ("awaiting connection for join"); + + $pending_joins->{$server_id} = $channel; + Irssi::signal_add_last("event 376", 'do_channel_join'); + } +} + +sub do_channel_join { + my ($serv) = @_; + #_debug_print("server is " . Dumper($serv)); + _debug_print(sprintf("server is %s (%s)", $serv->{address}, $serv->{tag})); + + my $channel = $pending_joins->{$serv->{address}}; + $channel = $pending_joins->{$serv->{tag}} unless $channel; + + _debug_print ("attempting to join $channel"); + + Irssi::server_find_tag($serv->{tag})->command("JOIN $channel"); + + delete $pending_joins->{$serv->{address}}; + delete $pending_joins->{$serv->{tag}}; + +} + +auto_server_init(); -- cgit v1.2.3 From 535b897f97ee6abee811bd33bab6828244ec241f Mon Sep 17 00:00:00 2001 From: Rich Healey Date: Thu, 6 Jan 2011 19:45:35 -0800 Subject: --- auto-server/auto_server.pl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'auto-server') diff --git a/auto-server/auto_server.pl b/auto-server/auto_server.pl index a9f6645..0f5a11e 100644 --- a/auto-server/auto_server.pl +++ b/auto-server/auto_server.pl @@ -198,6 +198,8 @@ sub join_plus { _debug_print ("awaiting connection for join"); $pending_joins->{$server_id} = $channel; + # This comes tumbling down if the server doesn't have a MOTD. + # is that RFC required? Irssi::signal_add_last("event 376", 'do_channel_join'); } } -- cgit v1.2.3 From eddd7d5487252dc40e1ec8de12a0042cd98e8c0c Mon Sep 17 00:00:00 2001 From: richo Date: Wed, 21 Sep 2011 21:34:01 +1000 Subject: Staging a few ideas on this slow shutdown issue --- auto-server/auto_server.pl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'auto-server') diff --git a/auto-server/auto_server.pl b/auto-server/auto_server.pl index 8f24e50..9f18be9 100644 --- a/auto-server/auto_server.pl +++ b/auto-server/auto_server.pl @@ -108,7 +108,7 @@ sub parse_channel_map { Irssi::active_win->print("Could not process channel => server mappings"); $channel_map = {}; } - _debug_print Dumper($channel_map); + #_debug_print Dumper($channel_map); bind_completion(); } @@ -200,6 +200,7 @@ sub join_plus { } sub do_channel_join { + Irssi::signal_remove("event 376", 'do_channel_join'); my ($serv) = @_; #_debug_print("server is " . Dumper($serv)); _debug_print(sprintf("server is %s (%s)", $serv->{address}, $serv->{tag})); -- cgit v1.2.3 From 92d8c0227f5da999a32431063cbc38e0950c9081 Mon Sep 17 00:00:00 2001 From: richo Date: Wed, 21 Sep 2011 21:34:15 +1000 Subject: TODO notes --- auto-server/auto_server.pl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'auto-server') diff --git a/auto-server/auto_server.pl b/auto-server/auto_server.pl index 9f18be9..77ba527 100644 --- a/auto-server/auto_server.pl +++ b/auto-server/auto_server.pl @@ -150,6 +150,8 @@ sub join_plus { return; } # TODO: search values() and give a 'did you mean' for closest channel + # TODO: Fuzzy match for ## channels (Would be nice to hax at teh tab + # completion too) # check if we're connected to that server my $server = Irssi::server_find_tag($server_id); @@ -177,6 +179,8 @@ sub join_plus { # check if we're already on the required channel my $on_channel = $server->channel_find($channel); + # FIXME + # Should this be $on_channel? Need docs.. if (defined $channel && ref($channel) eq 'Irssi::Irc::Channel') { Irssi::active_win()->print("You are already connected to " . " $channel on " . $server->{tag}); -- cgit v1.2.3