root/lang/perl/POE-Component-Client-Nowa/trunk/bin/nowa2ircd.pl @ 6568

Revision 6568, 8.5 kB (checked in by woremacx, 5 years ago)

lang/perl/POE-Component-Client-Nowa: fix bug joining channel

Line 
1#!/usr/bin/perl
2
3# most of codes were copyed from twitter2ircd.pl
4
5use strict;
6use warnings;
7use FindBin;
8use lib ("$FindBin::Bin/../extlib", "$FindBin::Bin/../lib");
9
10use Data::Dumper;
11use Getopt::Long;
12use POE qw(Component::Client::Nowa Component::Server::IRC Component::TSTP);
13use YAML;
14
15my $conf = "config.yaml";
16GetOptions('-c=s' => \ $conf, '--quiet' => \my $quiet);
17$conf or die "Usage: nowa2ircd.pl -c=config.yaml\n";
18
19my $config = YAML::LoadFile($conf) or die $!;
20
21if ($quiet) {
22    close STDIN;
23    close STDOUT;
24    close STDERR;
25    exit if fork;
26} else {
27    # for Ctrl-Z
28    POE::Component::TSTP->create();
29}
30
31sub msg (@) { print "[msg] ", "@_\n" }
32sub err (@) { print "[err] ", "@_\n" }
33
34my $ircd = POE::Component::Server::IRC->spawn(
35    alias  => 'ircd',
36    config => {
37        servername => $config->{irc}->{servername},
38        nicklen    => 15,
39        network    => 'NowaNET'
40    },
41);
42
43my $nowa = POE::Component::Client::Nowa->spawn(%{ $config->{nowa} });
44
45POE::Session->create(
46    inline_states => {
47        _start   => \&_start,
48        ircd_daemon_nick => \&ircd_nick,
49        ircd_daemon_join => \&ircd_join,
50        ircd_daemon_part => \&ircd_part,
51        ircd_daemon_quit => \&ircd_quit,
52        ircd_daemon_public  => \&ircd_public,
53
54        'nowa.recent' => \&nowa_recent,
55        'nowa.recent_success' => \&nowa_recent_success,
56        'nowa.channel_recent' => \&nowa_channel_recent,
57        'nowa.channel_recent_success' => \&nowa_channel_recent_success,
58        'nowa.channels_success' => \&nowa_channels_success,
59
60        bot_join => \&bot_join,
61        delay_nowa_recent => \&delay_nowa_recent,
62        delay_nowa_channel_recent => \&delay_nowa_channel_recent,
63
64        _default => \&ircd_default,
65    },
66    options => { trace => 0 },
67    heap => { ircd => $ircd, nowa => $nowa, config => $config, previous_recent => [] },
68);
69
70$poe_kernel->run();
71exit 0;
72
73sub _start {
74    my ($kernel,$heap) = @_[KERNEL,HEAP];
75    my $conf = $heap->{config}->{irc};
76
77    msg '_start';
78
79    # register ircd to receive events
80    $heap->{ircd}->yield('register');
81    $heap->{nowa}->yield('register');
82    $heap->{ircd}->add_auth(
83        mask => $conf->{mask},
84        password => $conf->{password}
85    );
86    $heap->{ircd}->add_listener( port => $conf->{serverport} || 6667 );
87
88    # add super user
89    $heap->{ircd}->yield(add_spoofed_nick => { nick => $conf->{botname} });
90    $heap->{ircd}->yield(daemon_cmd_join => $conf->{botname}, $conf->{channel});
91    $heap->{nowa}->yield('channels');
92
93    $heap->{nicknames} = {};
94    $heap->{channel_nicknames} = {};
95    $heap->{joined}    = 0;
96    $heap->{stack}     = [];
97
98    undef;
99}
100
101sub delay_nowa_recent {
102    my($kernel, $heap) = @_[KERNEL, HEAP];
103
104    msg 'delay_nowa_recent';
105    $heap->{nowa}->yield('recent');
106}
107
108sub delay_nowa_channel_recent {
109    my($kernel, $heap) = @_[KERNEL, HEAP];
110
111    msg 'delay_nowa_channel_recent';
112    $heap->{nowa}->yield('channel_recent');
113}
114
115sub nowa_privmsg {
116    my($kernel, $heap, $ret) = @_[KERNEL, HEAP, ARG0];
117    my $conf = $heap->{config}->{irc};
118
119    msg 'nowa_privmsg';
120    $heap->{ircd}->yield(daemon_cmd_notice => $conf->{botname}, $conf->{channel}, $ret->{text});
121}
122
123sub bot_join {
124    my($kernel, $heap, $nick, $ch) = @_[KERNEL, HEAP, ARG0, ARG1];
125
126    msg 'bot_join';
127    return if $heap->{nicknames}->{$nick};
128    $heap->{ircd}->yield(add_spoofed_nick => { nick => $nick });
129    $heap->{ircd}->yield(daemon_cmd_join => $nick, $ch);
130    $heap->{nicknames}->{$nick} = 1;
131}
132
133sub ircd_nick {
134    my($kernel, $heap, $nick, $host) = @_[KERNEL, HEAP, ARG0, ARG5];
135    my $conf = $heap->{config}->{irc};
136
137    return if $nick eq $conf->{botname};
138    return if $heap->{nick_change} || '';
139    if (($host || '') eq $conf->{servername}) {
140        $heap->{ircd}->_daemon_cmd_join($nick, $conf->{channel});
141        $heap->{nick_change} = 1;
142        $heap->{ircd}->_daemon_cmd_nick($nick, $conf->{nickname});
143        delete $heap->{nick_change};
144    }
145
146    $heap->{nick} = $nick;
147}
148
149sub nowa_channels_success {
150    my($kernel, $heap, $res) = @_[KERNEL, HEAP, ARG0];
151    my $conf = $heap->{config}->{irc};
152
153    msg 'nowa_channels_success';
154    while (my ($channel, $topic) = each(%$res)) {
155        unless ($heap->{joined_channel}->{$channel}) {
156            $heap->{joined_channel}->{$channel} = 1;
157            $heap->{ircd}->yield(daemon_cmd_join => $conf->{botname}, $channel);
158            $heap->{ircd}->yield(daemon_cmd_topic => $conf->{botname}, $channel, $topic);
159        }
160    }
161}
162
163sub ircd_join {
164    my($kernel, $heap, $user, $ch) = @_[KERNEL,HEAP,ARG0,ARG1];
165    my $conf = $heap->{config}->{irc};
166
167    return unless my($nick) = $user =~ /^([^!]+)!/;
168    return if $heap->{nicknames}->{$nick};
169    return if $nick eq $conf->{botname};
170    if ($ch eq $conf->{channel}) {
171        $heap->{joined} = 1;
172        $heap->{nowa}->yield(update => 'hello, world') if $heap->{config}->{greeting};
173
174        for my $data (@{ $heap->{stack} }) {
175            $heap->{ircd}->yield(daemon_cmd_privmsg => $data->{name}, $conf->{channel}, $data->{text});
176        }
177        $heap->{stack} = [];
178        $kernel->delay('delay_nowa_recent', 5);
179    } else {
180        $kernel->delay('delay_nowa_channel_recent', 15) unless $heap->{initial_channel_recent}++;
181    }
182}
183
184sub ircd_part {
185    my($kernel, $heap, $user, $ch) = @_[KERNEL,HEAP,ARG0,ARG1];
186    my $conf = $heap->{config}->{irc};
187
188    return unless my($nick) = $user =~ /^([^!]+)!/;
189    return if $heap->{nicknames}->{$nick};
190    return if $nick eq $conf->{botname};
191
192    if ($ch eq $conf->{channel}) {
193        $heap->{joined} = 0;
194        $heap->{nowa}->yield(update => 'good nite!') if $heap->{config}->{greeting};
195    }
196}
197
198sub ircd_quit {
199    my($kernel, $heap, $user) = @_[KERNEL,HEAP,ARG0];
200    my $conf = $heap->{config}->{irc};
201
202    return unless my($nick) = $user =~ /^([^!]+)!/;
203    return if $heap->{nicknames}->{$nick};
204    return if $nick eq $conf->{botname};
205    $heap->{joined} = 0;
206    $heap->{nowa}->yield(update => 'good nite, yeah!') if $heap->{config}->{greeting};
207}
208
209sub ircd_public {
210    my($kernel, $heap, $user, $channel, $text) = @_[KERNEL, HEAP, ARG0, ARG1, ARG2];
211    my $conf = $heap->{config}->{irc};
212
213    my $nick = ( $user =~ m/^(.*)!/)[0];
214    unless ($channel eq $conf->{channel}) {
215        $text = "$channel $text";
216    }
217    $heap->{nowa}->yield(update => $text);
218}
219
220sub nowa_recent_success {
221    my($kernel, $heap, $ret) = @_[KERNEL, HEAP, ARG0];
222    my $conf = $heap->{config}->{irc};
223
224    msg "nowa_recent_success";
225
226    if ($heap->{joined}) {
227        my %prev = map { $_->{permalink} => 1 } @{ $heap->{previous_recent} };
228
229        for my $line (reverse @{ $ret }) {
230            next if $prev{ $line->{permalink} };
231
232            my $name = $line->{user};
233            my $text = $line->{body};
234
235            unless ($heap->{nicknames}->{$name}) {
236                $heap->{ircd}->yield(add_spoofed_nick => { nick => $name });
237                $heap->{ircd}->yield(daemon_cmd_join => $name, $conf->{channel});
238                $heap->{nicknames}->{$name} = 1;
239            }
240
241#            next if $heap->{config}->{nowa}->{nowa_id} eq $name;
242            if ($heap->{joined}) {
243                $heap->{ircd}->yield(daemon_cmd_privmsg => $name, $conf->{channel}, $text);
244            } else {
245                push @{ $heap->{stack} }, { name => $name, text => $text }
246            }
247        }
248
249        $heap->{previous_recent} = $ret;
250    }
251
252    $kernel->delay('delay_nowa_recent', $heap->{config}->{nowa}->{retry});
253}
254
255sub nowa_channel_recent_success {
256    my($kernel, $heap, $ret) = @_[KERNEL, HEAP, ARG0];
257    my $conf = $heap->{config}->{irc};
258
259    msg "nowa_channel_recent_success";
260
261    if (scalar(@$ret)) {
262        my %prev = map { $_->{permalink} => 1 } @{ $heap->{previous_channel_recent} };
263
264        for my $line (reverse @{ $ret }) {
265            next if $prev{ $line->{permalink} };
266
267            my $name = $line->{user};
268            my $text = $line->{body};
269            my $channel = $line->{channel};
270
271            next unless $heap->{joined_channel}->{$channel};
272
273            unless ($heap->{channel_nicknames}->{$channel}->{$name}) {
274                $heap->{ircd}->yield(daemon_cmd_join => $name, $channel);
275                $heap->{channel_nicknames}->{$channel}->{$name} = 1;
276            }
277
278#            next if $heap->{config}->{nowa}->{nowa_id} eq $name;
279            $heap->{ircd}->yield(daemon_cmd_privmsg => $name, $channel, $text);
280        }
281
282        $heap->{previous_channel_recent} = $ret;
283    }
284
285    $kernel->delay('delay_nowa_channel_recent', $heap->{config}->{nowa}->{retry});
286}
287
288sub ircd_default {
289    my ($event, $args) = @_[ARG0 .. ARG1];
290
291    use YAML;
292    warn Dump [$event, $args];
293}
Note: See TracBrowser for help on using the browser.