| 1 |
#!/usr/bin/perl |
|---|
| 2 |
use warnings; |
|---|
| 3 |
use strict; |
|---|
| 4 |
|
|---|
| 5 |
use FindBin; |
|---|
| 6 |
use lib "$FindBin::Bin/../lib"; |
|---|
| 7 |
|
|---|
| 8 |
use Getopt::Long; |
|---|
| 9 |
use List::Util qw(first); |
|---|
| 10 |
use YAML; |
|---|
| 11 |
|
|---|
| 12 |
use Plagger::ConfigLoader; |
|---|
| 13 |
|
|---|
| 14 |
use POE qw( |
|---|
| 15 |
Session |
|---|
| 16 |
Component::IRC |
|---|
| 17 |
Component::IKC::Server |
|---|
| 18 |
Component::IKC::Specifier |
|---|
| 19 |
); |
|---|
| 20 |
|
|---|
| 21 |
sub msg (@) { print "[msg] ", "@_\n" } |
|---|
| 22 |
sub err (@) { print "[err] ", "@_\n" } |
|---|
| 23 |
|
|---|
| 24 |
my $path = "$FindBin::Bin/../config.yaml"; |
|---|
| 25 |
GetOptions("--config=s", \$path); |
|---|
| 26 |
Getopt::Long::Configure("bundling"); # allows -c |
|---|
| 27 |
|
|---|
| 28 |
msg "loading configuration $path"; |
|---|
| 29 |
|
|---|
| 30 |
my $loader = Plagger::ConfigLoader->new; |
|---|
| 31 |
my $base_config = $loader->load($path); |
|---|
| 32 |
|
|---|
| 33 |
$loader->load_include($base_config); |
|---|
| 34 |
$loader->load_recipes($base_config); |
|---|
| 35 |
|
|---|
| 36 |
my $plugin = first { $_->{module} eq 'Notify::IRC' } @{ $base_config->{plugins} } |
|---|
| 37 |
or die "Can't find Notify::IRC config in $path"; |
|---|
| 38 |
|
|---|
| 39 |
my $config = $plugin->{config}; |
|---|
| 40 |
|
|---|
| 41 |
msg 'creating daemon component'; |
|---|
| 42 |
POE::Component::IKC::Server->spawn( |
|---|
| 43 |
port => $config->{daemon_port} || 9999, |
|---|
| 44 |
name => 'NotifyIRCBot', |
|---|
| 45 |
); |
|---|
| 46 |
|
|---|
| 47 |
msg 'creating irc component'; |
|---|
| 48 |
POE::Component::IRC->spawn( alias => 'bot' ) |
|---|
| 49 |
or die "Couldn't create IRC POE session: $!"; |
|---|
| 50 |
|
|---|
| 51 |
msg 'creating kernel session'; |
|---|
| 52 |
POE::Session->create( |
|---|
| 53 |
inline_states => { |
|---|
| 54 |
_start => \&bot_start, |
|---|
| 55 |
_stop => \&bot_stop, |
|---|
| 56 |
connect => \&bot_connect, |
|---|
| 57 |
irc_001 => \&bot_connected, |
|---|
| 58 |
irc_372 => \&bot_motd, |
|---|
| 59 |
irc_433 => \&bot_nick_taken, |
|---|
| 60 |
irc_disconnected => \&bot_reconnect, |
|---|
| 61 |
irc_error => \&bot_reconnect, |
|---|
| 62 |
irc_socketerr => \&bot_reconnect, |
|---|
| 63 |
autoping => \&bot_do_autoping, |
|---|
| 64 |
update => \&update, |
|---|
| 65 |
_default => $ENV{DEBUG} ? \&bot_default : sub { }, |
|---|
| 66 |
} |
|---|
| 67 |
); |
|---|
| 68 |
|
|---|
| 69 |
msg 'starting the kernel'; |
|---|
| 70 |
POE::Kernel->run(); |
|---|
| 71 |
msg 'exiting'; |
|---|
| 72 |
exit 0; |
|---|
| 73 |
|
|---|
| 74 |
sub bot_default |
|---|
| 75 |
{ |
|---|
| 76 |
my ( $event, $args ) = @_[ ARG0 .. $#_ ]; |
|---|
| 77 |
err "unhandled $event"; |
|---|
| 78 |
err " - $_" foreach @$args; |
|---|
| 79 |
return 0; |
|---|
| 80 |
} |
|---|
| 81 |
|
|---|
| 82 |
sub update |
|---|
| 83 |
{ |
|---|
| 84 |
my ( $kernel, $heap, $msg ) = @_[ KERNEL, HEAP, ARG0 ]; |
|---|
| 85 |
eval { |
|---|
| 86 |
for my $channel (@{ $config->{server_channels} }) { |
|---|
| 87 |
if ($config->{announce} =~ /action/i) { |
|---|
| 88 |
$kernel->post( bot => ctcp => $channel, "ACTION $msg"); |
|---|
| 89 |
} else { |
|---|
| 90 |
$kernel->post( bot => notice => $channel, $msg ) |
|---|
| 91 |
} |
|---|
| 92 |
} |
|---|
| 93 |
}; |
|---|
| 94 |
err "update error: $@" if $@; |
|---|
| 95 |
} |
|---|
| 96 |
|
|---|
| 97 |
sub bot_start |
|---|
| 98 |
{ |
|---|
| 99 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 100 |
msg "starting irc session"; |
|---|
| 101 |
$kernel->alias_set('notify_irc'); |
|---|
| 102 |
$kernel->call( IKC => publish => notify_irc => ['update'] ); |
|---|
| 103 |
$kernel->post( bot => register => 'all' ); |
|---|
| 104 |
$kernel->yield('connect'); |
|---|
| 105 |
} |
|---|
| 106 |
|
|---|
| 107 |
sub bot_connect |
|---|
| 108 |
{ |
|---|
| 109 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 110 |
msg "attempting to connect to server"; |
|---|
| 111 |
$kernel->post( |
|---|
| 112 |
bot => connect => { |
|---|
| 113 |
Nick => $config->{nickname}, |
|---|
| 114 |
Ircname => $config->{ircname} || $config->{nickname}, |
|---|
| 115 |
Username => $ENV{USER}, |
|---|
| 116 |
Server => $config->{server_host}, |
|---|
| 117 |
Port => $config->{server_port} || 6667, |
|---|
| 118 |
Password => $config->{server_password} || undef, |
|---|
| 119 |
} |
|---|
| 120 |
); |
|---|
| 121 |
} |
|---|
| 122 |
|
|---|
| 123 |
sub bot_stop |
|---|
| 124 |
{ |
|---|
| 125 |
msg "stopping bot"; |
|---|
| 126 |
} |
|---|
| 127 |
|
|---|
| 128 |
sub bot_connected |
|---|
| 129 |
{ |
|---|
| 130 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 131 |
foreach ( @{$config->{server_channels}} ) |
|---|
| 132 |
{ |
|---|
| 133 |
msg "joining channel $_"; |
|---|
| 134 |
$kernel->post( bot => join => $_ ); |
|---|
| 135 |
if ($config->{charset}) { |
|---|
| 136 |
$kernel->post( bot => charset => $config->{charset} ); |
|---|
| 137 |
} |
|---|
| 138 |
} |
|---|
| 139 |
} |
|---|
| 140 |
|
|---|
| 141 |
sub bot_motd |
|---|
| 142 |
{ |
|---|
| 143 |
msg '[motd] ' . $_[ARG1]; |
|---|
| 144 |
} |
|---|
| 145 |
|
|---|
| 146 |
sub bot_do_autoping |
|---|
| 147 |
{ |
|---|
| 148 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 149 |
$kernel->post( bot => userhost => $config->{nickname} ) |
|---|
| 150 |
unless $heap->{seen_traffic}; |
|---|
| 151 |
$heap->{seen_traffic} = 0; |
|---|
| 152 |
$kernel->delay( autoping => 300 ); |
|---|
| 153 |
} |
|---|
| 154 |
|
|---|
| 155 |
sub bot_reconnect |
|---|
| 156 |
{ |
|---|
| 157 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 158 |
err "reconnect: " . $_[ARG0]; |
|---|
| 159 |
$kernel->delay( autoping => undef ); |
|---|
| 160 |
$kernel->delay( connect => 60 ); |
|---|
| 161 |
} |
|---|
| 162 |
|
|---|
| 163 |
sub bot_nick_taken |
|---|
| 164 |
{ |
|---|
| 165 |
my ( $kernel, $heap ) = @_[ KERNEL, HEAP ]; |
|---|
| 166 |
if ($config->{nick} !~ /\d$/) { |
|---|
| 167 |
$config->{nick} .= 0; |
|---|
| 168 |
} else { |
|---|
| 169 |
substr( $config->{nick}, -1, 1 )++; |
|---|
| 170 |
} |
|---|
| 171 |
err 'nick taken, trying new nick ' . $config->{nick}; |
|---|
| 172 |
$kernel->post( bot => nick => $config->{nick} ); |
|---|
| 173 |
$heap->{seen_traffic} = 1; |
|---|
| 174 |
} |
|---|