Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 225 lines (181 sloc) 6.526 kB
0ffb46a Merged changes from master
Rich Healey authored
1 # This script was initially written by shabble, this fork (and molestation) is
2 # built upon his original work.
3 #
4 # USAGE:
5 #
6 # the primary command used is /join+ #channelname
7 #
8 # Mappings for channels to servers is accomplished with the
9 # joinplus_server_maps setting.
10 #
11 # Within this setting, space separated pairs denote channel, server pairs.
12 # Spaces also separate individual pairs, for example:
13 #
14 # /set joinplus_server_maps #foo Freenode #bar irc.somewhere.tld #meep DALNet
15 #
16 # Then use /join+ #foo, and if you are not already connected to freenode, it
17 # will connect you, and then join that channel.
18
19 # TODO:
20 # Autocompletion for channel names
21 # address conflict resolution
22 # fix that disgusting race condition
23
24 use strict;
25 use warnings;
26
27
28 use Irssi;
29 use Irssi::Irc;
30 use Irssi::TextUI;
31
32 use Data::Dumper;
33
34
35 my $DEBUG_ENABLED = 0;
36 sub DEBUG () { $DEBUG_ENABLED }
37
38 sub _debug_print {
39 return unless DEBUG;
40 return unless scalar (grep { defined && length } @_) == @_;
41 my $win = Irssi::active_win;
42 my $str = join('', @_);
43 $win->print($str, Irssi::MSGLEVEL_CLIENTCRAP);
44 }
45
46 our $VERSION = '0.0.' . (split(/ /, '$Rev: 362 $'))[1];
47
48 our %IRSSI = (
49 authors => 'shabble, richo',
50 contact => 'richo@psych0tik.net',
51 name => 'auto-join-ng',
52 description => 'connects to a specified server in order to connect' .
53 ' to a channel there, without having first to' .
54 ' connect to the server',
55 license => 'Public Domain',
56 );
57
58 my $channel_map = {};
59 my @hack_channels;
60 my $pending_joins;
61
62 sub auto_server_init {
63 Irssi::command_bind('join+', \&join_plus);
64 Irssi::settings_add_str('join_plus', 'joinplus_server_maps', '');
65 Irssi::signal_add_last('setup changed', \&setup_changed);
66 Irssi::settings_add_bool('join_plus', 'join_plus_debug', 0);
67
68 setup_changed();
69 $pending_joins = {};
70
71 }
72
73 sub setup_changed {
74 $DEBUG_ENABLED = Irssi::settings_get_bool('join_plus_debug');
75 parse_channel_map();
76 }
77
78 # This is a tremendous kludge.
79 # If anyone knows a better way to get this listing, I'd like to hear it.
80 # This has so many race condition bugs I just don't even know where to start.
81 sub retrieve_channels {
82 @hack_channels = ();
83 Irssi::signal_add_first('print text', 'haxy_print_hook');
84 Irssi::command("CHANNEL LIST");
85 Irssi::signal_remove('print text', 'haxy_print_hook');
86 return join(" ", @hack_channels);
87 }
88
89
90 # The idea for how to do this courtesy of http://wouter.coekaerts.be/site/irssi/aliases
91 sub haxy_print_hook {
92 Irssi::signal_remove('print text', 'haxy_print_hook');
93 Irssi::signal_stop();
94 my $data = $_[1];
95 # Hose control characters
96 $data =~ s/\x04.//g;
97 if ($data =~ m/^#/) {
98 my @items = split /\s+/, $data;
99 push(@hack_channels, $items[0]);
100 push(@hack_channels, $items[1]);
101 }
102 Irssi::signal_add_first('print text', 'haxy_print_hook');
103 }
104
105 sub parse_channel_map {
106 #my $data = Irssi::settings_get_str('joinplus_server_maps');
107 my $data = retrieve_channels();
108 unbind_completion();
109 my @items = split /\s+/, $data;
110 if (@items % 2 == 0) {
111 $channel_map = { @items }; # risky?
112 } else {
113 Irssi::active_win->print("Could not process channel => server mappings");
114 $channel_map = {};
115 }
116 _debug_print Dumper($channel_map);
117 bind_completion();
118 }
119
120 # Bind a stack of commands so that irssi knows to complete them.
121 sub bind_completion {
122 foreach(%$channel_map) {
123 Irssi::command_bind("join+ $_", \&join_plus);
124 }
125 }
126
127 sub unbind_completion {
128 foreach(%$channel_map) {
129 Irssi::command_unbind("join+ $_", \&join_plus);
130 }
131 }
132
133
134 sub join_plus {
135 my ($args, $cmd_server, $witem) = @_;
136 #print Dumper($cmd, "moo", $win);
137
138 # parse out channel name from args:
139 my $channel;
140 if ($args =~ m/^(#?[#a-zA-Z0-9]+)/) {
141 $channel = $1;
142 _debug_print ("Channel is: $channel");
143 }
144
145 unless ($channel) {
146 Irssi::active_win()->print("Channel $args not recognised");
147 return;
148 }
149
150 # lookup server
151 my $server_id = $channel_map->{$channel};
152 _debug_print($server_id);
153
154 unless ($server_id) {
155 Irssi::active_win()->print("Channel $channel does not have an"
156 . " appropriate server mapping");
157 return;
158 }
159 # TODO: search values() and give a 'did you mean' for closest channel
160
161 # check if we're connected to that server
162 my $server = Irssi::server_find_tag($server_id);
163
164 if (not defined $server) {
165 $server = Irssi::server_find_chatnet($server_id);
166 }
167
168 if (not defined $server) {
169 # still no server, walk the server list looking for address matches.
170 my @servers = Irssi::servers();
171 foreach my $srv (@servers) {
172 if (($srv->{address} eq $server_id) or
173 ($srv->{real_address} eq $server_id)) {
174 $server = $srv;
175 last;
176 }
177 }
178 }
179
180 if (defined $server) {
181
182 _debug_print ("Already connected to server: " . $server->{tag} );
183
184 # check if we're already on the required channel
185 my $on_channel = $server->channel_find($channel);
186
187 if (defined $channel && ref($channel) eq 'Irssi::Irc::Channel') {
188 Irssi::active_win()->print("You are already connected to "
189 . " $channel on " . $server->{tag});
190 return;
191 } else {
192 _debug_print ("joining channel: $channel");
193 $server->command("JOIN $channel");
194 }
195 } else {
196 # not connected to server.
197 _debug_print ("connecting to server: $server_id");
198
199 Irssi::command("CONNECT $server_id");
200 _debug_print ("awaiting connection for join");
201
202 $pending_joins->{$server_id} = $channel;
203 Irssi::signal_add_last("event 376", 'do_channel_join');
204 }
205 }
206
207 sub do_channel_join {
208 my ($serv) = @_;
209 #_debug_print("server is " . Dumper($serv));
210 _debug_print(sprintf("server is %s (%s)", $serv->{address}, $serv->{tag}));
211
212 my $channel = $pending_joins->{$serv->{address}};
213 $channel = $pending_joins->{$serv->{tag}} unless $channel;
214
215 _debug_print ("attempting to join $channel");
216
217 Irssi::server_find_tag($serv->{tag})->command("JOIN $channel");
218
219 delete $pending_joins->{$serv->{address}};
220 delete $pending_joins->{$serv->{tag}};
221
222 }
223
224 auto_server_init();
Something went wrong with that request. Please try again.