1use strict;
2use warnings FATAL => 'all';
3use lib 't/inc';
4use POE;
5use POE::Component::IRC::State;
6use POE::Component::IRC::Plugin::AutoJoin;
7use POE::Component::Server::IRC;
8use Test::More tests => 9;
9
10my $bot1 = POE::Component::IRC::State->spawn(
11    Flood        => 1,
12    plugin_debug => 1,
13);
14my $bot2 = POE::Component::IRC::State->spawn(
15    Flood        => 1,
16    plugin_debug => 1,
17);
18my $ircd = POE::Component::Server::IRC->spawn(
19    Auth      => 0,
20    AntiFlood => 0,
21);
22
23$bot2->plugin_add(AutoJoin => POE::Component::IRC::Plugin::AutoJoin->new(
24    Retry_when_banned => 1,
25));
26
27POE::Session->create(
28    package_states => [
29        main => [qw(
30            _start
31            ircd_listener_add
32            ircd_listener_failure
33            _shutdown
34            irc_001
35            irc_join
36            irc_disconnected
37            irc_chan_mode
38            irc_474
39        )],
40    ],
41);
42
43$poe_kernel->run();
44
45sub _start {
46    my ($kernel) = $_[KERNEL];
47
48    $ircd->yield('register', 'all');
49    $ircd->yield('add_listener');
50    $kernel->delay(_shutdown => 60, 'Timed out');
51}
52
53sub ircd_listener_failure {
54    my ($kernel, $op, $reason) = @_[KERNEL, ARG1, ARG3];
55    $kernel->yield('_shutdown', "$op: $reason");
56}
57
58sub ircd_listener_add {
59    my ($kernel, $port) = @_[KERNEL, ARG0];
60
61    $bot1->yield(register => 'all');
62    $bot1->yield(connect => {
63        nick    => 'TestBot1',
64        server  => '127.0.0.1',
65        port    => $port,
66    });
67
68    $bot2->yield(register => 'all');
69    $bot2->yield(connect => {
70        nick    => 'TestBot2',
71        server  => '127.0.0.1',
72        port    => $port,
73    });
74}
75
76sub irc_001 {
77    my $irc = $_[SENDER]->get_heap();
78    pass($irc->nick_name.' logged in');
79
80    if ($irc == $bot1) {
81        $irc->yield(join => '#testchannel');
82    }
83}
84
85sub irc_join {
86    my ($sender, $who, $where) = @_[SENDER, ARG0, ARG1];
87    my $nick = ( split /!/, $who )[0];
88    my $irc = $sender->get_heap();
89
90    return if $nick ne $irc->nick_name();
91    is($where, '#testchannel', $irc->nick_name. ' joined channel');
92
93    if ($nick eq 'TestBot1') {
94        $irc->yield(mode => $where, '+b TestBot2!*@*');
95    }
96    else {
97        $bot1->yield('quit');
98        $bot2->yield('quit');
99    }
100}
101
102sub irc_chan_mode {
103    my ($chan, $mode) = @_[ARG1, ARG2];
104
105    if ($mode eq '+b') {
106        pass('Ban set');
107        $bot2->yield(join => $chan);
108    }
109    elsif ($mode eq '-b') {
110        pass('Ban removed');
111    }
112}
113
114sub irc_474 {
115    my ($chan) = $_[ARG2]->[0];
116
117    if (!$_[HEAP]->{denied}) {
118        pass("Can't join due to ban");
119        $bot1->yield(mode => $chan, '-b TestBot2!*@*');
120        $_[HEAP]->{denied} = 1;
121    }
122}
123
124sub irc_disconnected {
125    my ($kernel, $heap) = @_[KERNEL, HEAP];
126    pass('irc_disconnected');
127    $heap->{count}++;
128    $kernel->yield('_shutdown') if $heap->{count} == 2;
129}
130
131sub _shutdown {
132    my ($kernel, $error) = @_[KERNEL, ARG0];
133    fail($error) if defined $error;
134
135    $kernel->alarm_remove_all();
136    $bot1->yield('shutdown');
137    $bot2->yield('shutdown');
138    $ircd->yield('shutdown');
139}
140