root/lang/perl/irssi/scripts/mobirc.pl

Revision 1090, 8.8 kB (checked in by typester, 20 months ago)

irssi-mobirc: follow up recent Mobirc changes

Line 
1use strict;
2use warnings;
3use utf8;
4
5use Irssi;
6
7use Glib;
8use POE::Sugar::Args;
9use POE qw/Session::Irssi Loop::Glib/;
10
11use Encode;
12use Mobirc;
13use Mobirc::Util;
14use Mobirc::HTTPD;
15use Module::Reload;
16use YAML::Syck;
17
18our %IRSSI = ( name => 'mobirc' );
19
20Irssi::settings_add_str('mobirc', 'mobirc_config_path', '');
21Irssi::settings_add_bool('mobirc', 'mobirc_auto_start', 0);
22
23POE::Session::Irssi->create(
24    inline_states => {
25        map { ( $_ => __PACKAGE__->can("poe_$_") ) }
26            qw/_start load initialize_mobirc unload/
27    },
28
29    irssi_commands => {
30        mobirc => sub {
31            my $poe = sweet_args;
32            my ($data, $server, $witem) = @{ $poe->args->[1] };
33
34            if (($data || '') =~ /start/) {
35                if ($poe->kernel->alias_resolve('mobirc_httpd')) {
36                    Irssi::print('mobirc is already started!');
37                    return;
38                }
39                $poe->kernel->yield('load');
40            }
41            elsif (($data || '') =~ /stop/) {
42                $poe->kernel->yield('unload');
43            }
44        },
45    },
46
47    irssi_signals => {
48        map( { ( "message $_" => bind_signal("irssi_$_") ) }
49            qw/public private own_public own_private join part quit kick nick own_nick invite topic/
50        ),
51        map( { ( "message irc $_" => bind_signal("irssi_irc_$_") ) }
52            qw/op_public own_wall own_action action own_notice notice own_ctcp ctcp/
53        ),
54        'server event' => bind_signal('irssi_irc_snotice'),
55        'print text' => bind_signal('irssi_print_text'),
56        'command script unload' => \&script_unload,
57    },
58);
59
60sub nick_name {
61    my $server = Irssi::active_server() or return '';
62    $server->{nick};
63}
64
65sub bind_signal {
66    my $sub = __PACKAGE__->can(shift) or return;
67
68    return sub {
69        return unless $_[KERNEL]->alias_resolve('mobirc_httpd');
70        $sub->(@_);
71    };
72}
73
74sub poe__start {
75    my $poe = sweet_args;
76
77    if (Irssi::settings_get_bool('mobirc_auto_start')) {
78        $poe->kernel->yield('load');
79    }
80}
81
82sub poe_load {
83    my $poe = sweet_args;
84    Module::Reload->check;
85
86    my $mobirc = $poe->kernel->call( $poe->session, 'initialize_mobirc')
87        or return;
88
89    # dummy irc session to handle post message from httpd
90    POE::Session->create(
91        inline_states => {
92            _start => sub {
93                $_[KERNEL]->alias_set('irc_session');
94            },
95        },
96        heap => {
97            irc => __PACKAGE__,
98            config => { incode => 'utf-8' },
99        },
100    );
101
102    POE::Session->create(
103        inline_states => {
104            _start => sub {
105                $_[KERNEL]->alias_set('mobirc_irc');
106            },
107
108            privmsg => sub {
109                my ($channel, $message) = @_[ARG0, ARG1];
110
111                ($channel) = grep { $_->{name} eq $channel } Irssi::channels();
112                if ($channel) {
113                    $channel->{server}->command("MSG $channel->{name} $message");
114                }
115            },
116        },
117    );
118
119    Mobirc::HTTPD->init($mobirc->config);
120    Irssi::print('started mobirc') if $poe->kernel->alias_resolve('mobirc_httpd');
121}
122
123sub irssi_print_text {
124    my $poe = sweet_args;
125    my ($dest, $text, $stripped) = @{ $poe->args->[1] };
126
127    if ($dest->{level} & MSGLEVEL_HILIGHT) {
128        Mobirc::Channel->update_keyword_buffer($poe->heap->{mobirc}, $poe->heap->{__last_row});
129    }
130}
131
132sub irssi_public {
133    my $poe = sweet_args;
134    my ($server, $msg, $nick, $address, $target) = @{ $poe->args->[1] };
135
136    add_message( $poe, $target, $nick, $msg, 'public' );
137}
138
139sub irssi_private {}
140
141sub irssi_own_public {
142    my $poe = sweet_args;
143    my ($server, $msg, $target) = @{ $poe->args->[1] };
144
145    add_message( $poe, $target, $server->{nick}, $msg, 'public' );
146}
147sub irssi_own_private {}
148
149sub irssi_join {
150    my $poe = sweet_args;
151    my ($server, $channel, $nick, $address) = @{ $poe->args->[1] };
152
153    my $mobirc = $poe->heap->{mobirc};
154
155    $channel = decode('utf-8', $channel);
156    $channel = $mobirc->get_channel($channel)
157            || $mobirc->add_channel( Mobirc::Channel->new($poe->heap->{mobirc}, normalize_channel_name($channel) ) );
158
159    unless ($server->{nick} eq $nick) {
160        add_message( $poe, $channel, undef, "$nick joined", 'join');
161    }
162}
163
164sub irssi_part {
165    my $poe = sweet_args;
166    my ($server, $channel, $nick, $address, $reason) = @{ $poe->args->[1] };
167
168    my $mobirc = $poe->heap->{mobirc};
169
170    $channel = normalize_channel_name( decode('utf-8', $channel) );
171    if ($server->{nick} eq $nick) {
172        delete $mobirc->{channels}->{$channel};
173    }
174    else {
175        add_message($poe, $channel, undef, "$nick leaves", 'leave');
176    }
177}
178
179sub irssi_quit {}
180sub irssi_kick {}
181sub irssi_nick {}
182sub irssi_own_nick {}
183sub irssi_invite {}
184
185sub irssi_topic {
186    my $poe = sweet_args;
187    my ($server, $channel, $topic, $nick, $address) = @{ $poe->args->[1] };
188
189    my $mobirc = $poe->heap->{mobirc};
190
191    $channel = $mobirc->get_channel( normalize_channel_name(decode('utf-8', $channel)) );
192    $channel->topic( decode('utf-8', $topic) );
193
194    add_message($poe, $channel, undef, "$nick set topic: $topic", 'topic');
195}
196
197sub irssi_irc_op_public {}
198sub irssi_irc_own_wall {}
199
200sub irssi_irc_own_action {
201    my $poe = sweet_args;
202    my ($server, $msg, $target) = @{ $poe->args->[1] };
203
204    $msg = sprintf('* %s %s', $server->{nick}, decode('utf-8', $msg));
205    add_message( $poe, $target, '', $msg, 'ctcp_action');
206}
207
208sub irssi_irc_action {
209    my $poe = sweet_args;
210    my ($server, $msg, $nick, $address, $target) = @{ $poe->args->[1] };
211
212    $msg = sprintf('* %s %s', $nick, decode('utf-8', $msg));
213    add_message( $poe, $target, '', $msg, 'ctcp_action');
214}
215
216sub irssi_irc_own_notice {
217    my $poe = sweet_args;
218    my ($server, $msg, $target) = @{ $poe->args->[1] };
219
220    add_message($poe, $target, $server->{nick}, $msg, 'notice');
221}
222
223sub irssi_irc_notice {
224    my $poe = sweet_args;
225    my ($server, $msg, $nick, $address, $target) = @{ $poe->args->[1] };
226
227    add_message($poe, $target, $nick, $msg, 'notice');
228}
229
230sub irssi_irc_snotice {
231    my $poe = sweet_args;
232    my ($server, $msg, $nick, $address, $target) = @{ $poe->args->[1] };
233    return unless $msg =~ /^\d/; # messages only
234
235    add_message($poe, '*server*', undef, $msg, 'snotice');
236}
237sub irssi_irc_own_ctcp {}
238sub irssi_irc_ctcp {}
239
240sub poe_initialize_mobirc {
241    my $poe = sweet_args;
242
243    delete $poe->heap->{mobirc} if $poe->heap->{mobirc};
244
245    my $conffname = Irssi::settings_get_str('mobirc_config_path');
246    unless ($conffname) {
247        Irssi::print('mobirc_config_path is not defined, please do "/set mobirc_config_path your_yaml_path" first');
248        return;
249    }
250    unless (-f $conffname && -r _) {
251        Irssi::print("file does not exist: $conffname");
252        return;
253    }
254
255    my $mobirc;
256    eval { $mobirc = Mobirc->new($conffname) };
257    if ($@) {
258        Irssi::print("can't initialize mobirc: $@");
259        return;
260    }
261
262    # httpd echo mode is disable
263    $mobirc->config->{httpd}->{echo} = false;
264    $poe->heap->{mobirc} = $mobirc;
265    $poe->heap->{config} = $mobirc->config;
266
267    $mobirc->add_channel( Mobirc::Channel->new($mobirc, '*server*') );
268    for my $channel (Irssi::channels()) {
269        my $channel_name = normalize_channel_name(decode('utf-8', $channel));
270        $mobirc->add_channel( Mobirc::Channel->new($mobirc, $channel_name) );
271    }
272
273    $mobirc;
274}
275
276sub poe_unload {
277    my $kernel = $_[KERNEL];
278
279    if (my $httpd_session = $kernel->alias_resolve('mobirc_httpd')) {
280        $kernel->call( $httpd_session => 'shutdown' );
281        delete $_[HEAP]->{mobirc};
282        Irssi::print('stopped mobirc');
283    }
284}
285
286sub script_unload {
287    my ($kernel, $session, $args) = @_[KERNEL, SESSION, ARG1];
288    my ($script) = @$args;
289
290    if ($script =~ /mobirc/) {
291        $kernel->call($session, 'unload');
292    }
293}
294
295# XXX: to avoid weird warnings
296{ package Irssi::Nick }
297
298{
299    no warnings 'redefine';
300    sub add_message {
301        my ($poe, @args) = @_;
302        for my $arg (@args) {
303            $arg = decode('utf-8', $arg) unless utf8::is_utf8($arg);
304        }
305        my ($channel, $who, $body, $class) = @args;
306
307        $channel = $poe->heap->{mobirc}->get_channel(normalize_channel_name($channel))
308            or return;
309
310        my $message = Mobirc::Message->new(
311            who   => $who,
312            body  => $body,
313            class => $class,
314        );
315        $channel->add_message($poe->heap->{__last_row} = $message);
316    }
317}
318
319=pod
320
321=head1 NAME
322
323mobirc.pl - irssi plugin for Mobirc
324
325=head1 SYNOPSIS
326
327    1.. copy (or link) this script into irssi script directory
328   
329    2. run irssi with Mobirc
330   
331       PERL5LIB=/path/to/mobirc/lib irssi
332   
333    3. start script in irssi
334   
335       /run mobirc
336   
337    4. set config.yaml path
338   
339       /set mobirc_config_path /path/to/your/config.yaml
340   
341    5. start mobirc
342   
343       /mobirc start
344
345=head1 AUTHOR
346
347Daisuke Murase <typester@cpan.org>
348
349Kazuhiro Osawa
350
351=cut
352
353
Note: See TracBrowser for help on using the browser.