| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # ABSTRACT: Run Bot::BasicBot::Pluggable::Module_s in Irssi | 
| 2 |  |  |  |  |  |  | use strict; | 
| 3 | 1 |  |  | 1 |  | 85765 | use warnings; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 26 |  | 
| 4 | 1 |  |  | 1 |  | 5 | use experimental 'signatures'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 25 |  | 
| 5 | 1 |  |  | 1 |  | 457 |  | 
|  | 1 |  |  |  |  | 2975 |  | 
|  | 1 |  |  |  |  | 5 |  | 
| 6 |  |  |  |  |  |  | use Irssi::Log::Log4perl; | 
| 7 | 1 |  |  | 1 |  | 494 | use Module::Pluggable | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 28 |  | 
| 8 |  |  |  |  |  |  | sub_name    => '_available', | 
| 9 | 1 |  |  |  |  | 5 | search_path => 'Bot::BasicBot::Pluggable::Module', | 
| 10 |  |  |  |  |  |  | except      => 'Bot::BasicBot::Pluggable::Module::Base'; | 
| 11 | 1 |  |  | 1 |  | 406 |  | 
|  | 1 |  |  |  |  | 8968 |  | 
| 12 |  |  |  |  |  |  | use Bot::BasicBot::Pluggable::Module; | 
| 13 | 1 |  |  | 1 |  | 513 | use Bot::BasicBot::Pluggable::Store; | 
|  | 1 |  |  |  |  | 843 |  | 
|  | 1 |  |  |  |  | 37 |  | 
| 14 | 1 |  |  | 1 |  | 382 | use Try::Tiny; | 
|  | 1 |  |  |  |  | 13928 |  | 
|  | 1 |  |  |  |  | 27 |  | 
| 15 | 1 |  |  | 1 |  | 7 | use Capture::Tiny 'capture'; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 47 |  | 
| 16 | 1 |  |  | 1 |  | 444 | use Text::Wrap (); | 
|  | 1 |  |  |  |  | 21800 |  | 
|  | 1 |  |  |  |  | 56 |  | 
| 17 | 1 |  |  | 1 |  | 430 |  | 
|  | 1 |  |  |  |  | 2187 |  | 
|  | 1 |  |  |  |  | 2363 |  | 
| 18 |  |  |  |  |  |  | #use Carp::Always; | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | # POE::Session constants | 
| 21 |  |  |  |  |  |  |  | 
| 22 | 0 |  |  | 0 | 0 |  | my $self = bless +{ @config } => $cls; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 23 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 24 | 0 |  |  | 0 | 0 |  | print "These modules are available for loading: " | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 25 | 0 |  |  | 0 | 0 |  | . join( ", ", $self->available_modules ); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  |  | 
| 27 | 0 |  |  | 0 | 0 |  | $self->init or die "init did not return a true value - dying"; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 28 | 0 |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | return $self; | 
| 30 | 0 |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 | 0 | 0 |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | $self->init_logging(); | 
| 35 | 0 |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 37 |  |  |  |  |  |  | $logger->info( 'Starting initialization of ' . ref $self ); | 
| 38 | 0 |  |  | 0 | 0 |  |  | 
| 39 |  |  |  |  |  |  | return 1; | 
| 40 | 0 |  |  | 0 | 0 |  | } | 
| 41 |  |  |  |  |  |  |  | 
| 42 | 0 |  |  | 0 | 0 |  | my $self   = shift; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 43 | 0 |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 44 |  |  |  |  |  |  | for my $log_entry (@_) { | 
| 45 | 0 |  |  |  |  |  | chomp $log_entry; | 
| 46 | 0 |  |  |  |  |  | $logger->warn($log_entry); | 
| 47 |  |  |  |  |  |  | } | 
| 48 | 0 |  |  |  |  |  | return; | 
| 49 |  |  |  |  |  |  | } | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | my @modules = sort | 
| 52 | 0 |  |  | 0 | 1 |  | map { | 
| 53 | 0 |  |  |  |  |  | my $mod = $_; | 
| 54 | 0 |  |  |  |  |  | $mod =~ s/^Bot::BasicBot::Pluggable::Module:://; | 
| 55 | 0 |  |  |  |  |  | $mod; | 
| 56 | 0 |  |  |  |  |  | } $self->_available(); | 
| 57 |  |  |  |  |  |  | return @modules; | 
| 58 | 0 |  |  |  |  |  | } | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 61 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | $logger->info("Dispatching $method") | 
| 63 |  |  |  |  |  |  | unless $method eq 'tick'; | 
| 64 | 0 |  |  |  |  |  | for my $who ( $self->modules ) { | 
|  | 0 |  |  |  |  |  |  | 
| 65 | 0 |  |  |  |  |  | ## Otherwise we would see tick every five seconds | 
| 66 | 0 |  |  |  |  |  | if ( $method eq 'tick' ) { | 
| 67 |  |  |  |  |  |  | $logger->trace("Trying to dispatch $method to $who"); | 
| 68 | 0 |  |  |  |  |  | } | 
| 69 |  |  |  |  |  |  | else { | 
| 70 |  |  |  |  |  |  | $logger->debug("Trying to dispatch $method to $who"); | 
| 71 | 0 |  |  | 0 | 0 |  | } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 72 | 0 |  |  |  |  |  | $logger->trace( "... with " . Dumper(@args) ) | 
| 73 |  |  |  |  |  |  | if $logger->is_trace && @args; | 
| 74 | 0 | 0 |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | next unless $self->module($who)->can($method); | 
| 76 | 0 |  |  |  |  |  | try { | 
| 77 |  |  |  |  |  |  | $logger->trace( | 
| 78 | 0 | 0 |  |  |  |  | "Dispatching $method to $who with " . Dumper(@args) ) | 
| 79 | 0 |  |  |  |  |  | if $logger->is_trace; | 
| 80 |  |  |  |  |  |  | $self->module($who)->$method(@args); | 
| 81 |  |  |  |  |  |  | } | 
| 82 | 0 |  |  |  |  |  | catch { | 
| 83 |  |  |  |  |  |  | $logger->warn($_); | 
| 84 | 0 | 0 | 0 |  |  |  | } | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  | return; | 
| 87 | 0 | 0 |  |  |  |  | } | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 0 | 0 |  | 0 |  |  | $self->dispatch('tick'); | 
| 90 |  |  |  |  |  |  | return 5; | 
| 91 |  |  |  |  |  |  | } | 
| 92 | 0 |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  | my $response; | 
| 94 |  |  |  |  |  |  | my $who; | 
| 95 | 0 |  |  | 0 |  |  |  | 
| 96 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 97 | 0 |  |  |  |  |  | $logger->info("Dispatching $event event"); | 
| 98 | 0 |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | for my $priority ( 0 .. 3 ) { | 
| 100 |  |  |  |  |  |  | for my $module ( $self->modules ) { | 
| 101 | 0 |  |  | 0 | 0 |  | my $response; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 102 | 0 |  |  |  |  |  | $logger->debug( | 
| 103 | 0 |  |  |  |  |  | "Trying to dispatch $event to $module on priority $priority"); | 
| 104 |  |  |  |  |  |  | $logger->trace( '... with arguments ' . Dumper($mess) ) | 
| 105 |  |  |  |  |  |  | if $logger->is_trace and $mess; | 
| 106 | 0 |  |  | 0 | 0 |  | try { | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 107 | 0 |  |  |  |  |  | $response = | 
| 108 |  |  |  |  |  |  | $self->module($module)->$event( $mess, $priority ); | 
| 109 |  |  |  |  |  |  | } | 
| 110 | 0 |  |  |  |  |  | catch { | 
| 111 | 0 |  |  |  |  |  | $logger->warn($_); | 
| 112 |  |  |  |  |  |  | }; | 
| 113 | 0 |  |  |  |  |  | if ( $priority and $response ) { | 
| 114 | 0 |  |  |  |  |  | $logger->debug("Response by $module on $priority"); | 
| 115 | 0 |  |  |  |  |  | $logger->trace( 'Response is ' . Dumper($response) ) | 
| 116 | 0 |  |  |  |  |  | if $logger->is_trace; | 
| 117 |  |  |  |  |  |  | return if $response eq '1'; | 
| 118 | 0 | 0 | 0 |  |  |  | $self->reply( $mess, $response ); | 
| 119 |  |  |  |  |  |  | return; | 
| 120 |  |  |  |  |  |  | } | 
| 121 | 0 |  |  | 0 |  |  | } | 
| 122 |  |  |  |  |  |  | } | 
| 123 |  |  |  |  |  |  | return; | 
| 124 |  |  |  |  |  |  | } | 
| 125 | 0 |  |  | 0 |  |  |  | 
| 126 | 0 |  |  |  |  |  | $self->dispatch( 'replied', {%$mess}, @other ); | 
| 127 | 0 | 0 | 0 |  |  |  | if ( $mess->{reply_hook} ) { | 
| 128 | 0 |  |  |  |  |  | return $mess->{reply_hook}->( $mess, @other ); | 
| 129 | 0 | 0 |  |  |  |  | } | 
| 130 |  |  |  |  |  |  | else { | 
| 131 | 0 | 0 |  |  |  |  | my ($body) = @other; | 
| 132 | 0 |  |  |  |  |  | my %hash = %$mess; | 
| 133 | 0 |  |  |  |  |  | $hash{body} = $body; | 
| 134 |  |  |  |  |  |  | return $self->say(%hash); | 
| 135 |  |  |  |  |  |  | } | 
| 136 |  |  |  |  |  |  | } | 
| 137 | 0 |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | # If we're called without an object ref, then we're handling saying | 
| 139 |  |  |  |  |  |  | # stuff from inside a forked subroutine, so we'll freeze it, and toss | 
| 140 | 0 |  |  | 0 | 0 |  | # it out on STDOUT so that POE::Wheel::Run's handler can pick it up. | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 141 | 0 |  |  |  |  |  | if (!ref $_[0]) { | 
| 142 | 0 | 0 |  |  |  |  | print $_[0], "\n"; | 
| 143 | 0 |  |  |  |  |  | return 1; | 
| 144 |  |  |  |  |  |  | } | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 0 |  |  |  |  |  | # Otherwise, this is a standard object method | 
| 147 | 0 |  |  |  |  |  |  | 
| 148 | 0 |  |  |  |  |  | my $self = shift; | 
| 149 | 0 |  |  |  |  |  | my $args; | 
| 150 |  |  |  |  |  |  | if (ref $_[0]) { | 
| 151 |  |  |  |  |  |  | $args = shift; | 
| 152 |  |  |  |  |  |  | } | 
| 153 |  |  |  |  |  |  | else { | 
| 154 |  |  |  |  |  |  | my %args = @_; | 
| 155 |  |  |  |  |  |  | $args = \%args; | 
| 156 |  |  |  |  |  |  | } | 
| 157 | 0 | 0 |  | 0 | 0 |  |  | 
| 158 | 0 |  |  |  |  |  | my $body = $args->{body}; | 
| 159 | 0 |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | # add the "Foo: bar" at the start | 
| 161 |  |  |  |  |  |  | if ($args->{channel} ne "msg" && defined $args->{address}) { | 
| 162 |  |  |  |  |  |  | $body = "$args->{who}: $body"; | 
| 163 |  |  |  |  |  |  | } | 
| 164 | 0 |  |  |  |  |  |  | 
| 165 | 0 |  |  |  |  |  | # work out who we're going to send the message to | 
| 166 | 0 | 0 |  |  |  |  | my $who = $args->{channel} eq "msg" ? $args->{who} : $args->{channel}; | 
| 167 | 0 |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | if (!defined $who || !defined $body) { | 
| 169 |  |  |  |  |  |  | $self->log("Can't send a message without target and body\n" | 
| 170 | 0 |  |  |  |  |  | . " called from " | 
| 171 | 0 |  |  |  |  |  | . ( [caller]->[0] ) | 
| 172 |  |  |  |  |  |  | . " line " | 
| 173 |  |  |  |  |  |  | . ( [caller]->[2] ) . "\n" | 
| 174 | 0 |  |  |  |  |  | . " who = '$who'\n body = '$body'\n"); | 
| 175 |  |  |  |  |  |  | return; | 
| 176 |  |  |  |  |  |  | } | 
| 177 | 0 | 0 | 0 |  |  |  |  | 
| 178 | 0 |  |  |  |  |  | # if we have a long body, split it up.. | 
| 179 |  |  |  |  |  |  | #local $Text::Wrap::columns = 300; | 
| 180 |  |  |  |  |  |  | local $Text::Wrap::columns = 294; | 
| 181 |  |  |  |  |  |  | local $Text::Wrap::unexpand = 0; # no tabs | 
| 182 | 0 | 0 |  |  |  |  | my $wrapped = Text::Wrap::wrap('', '..', $body); #  =~ m!(.{1,300})!g; | 
| 183 |  |  |  |  |  |  | # I think the Text::Wrap docs lie - it doesn't do anything special | 
| 184 | 0 | 0 | 0 |  |  |  | # in list context | 
| 185 | 0 |  |  |  |  |  | my @bodies = split /\n+/, $wrapped; | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | # Allows to override the default "PRIVMSG". Used by notice() | 
| 188 |  |  |  |  |  |  | my $irc_command = defined $args->{irc_command} | 
| 189 |  |  |  |  |  |  | && $args->{irc_command} eq 'notice' | 
| 190 |  |  |  |  |  |  | ? 'notice' | 
| 191 | 0 |  |  |  |  |  | : 'privmsg'; | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | # possibility to set the network | 
| 194 |  |  |  |  |  |  | local $self->{conn_tag} = $args->{network} | 
| 195 |  |  |  |  |  |  | if $args->{network}; | 
| 196 | 0 |  |  |  |  |  |  | 
| 197 | 0 |  |  |  |  |  | # post an event that will send the message | 
| 198 | 0 |  |  |  |  |  | my $last_color; | 
| 199 |  |  |  |  |  |  | for my $body (@bodies) { | 
| 200 |  |  |  |  |  |  | if (defined $last_color) { | 
| 201 | 0 |  |  |  |  |  | $body = "..\cC$last_color".substr $body, 2; | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  | if ((my $bcol = rindex $body, "\cC") > -1) { | 
| 204 |  |  |  |  |  |  | $last_color = (substr $body, $bcol + 1) =~ /^(\d{1,2}(?:,\d{1,2})?)/ ? $1 : undef; | 
| 205 | 0 | 0 | 0 |  |  |  | } | 
| 206 |  |  |  |  |  |  | if ($who eq '@@@ local user @@@') { | 
| 207 |  |  |  |  |  |  | $self->localresponse({ body => $body }); | 
| 208 |  |  |  |  |  |  | } else { | 
| 209 |  |  |  |  |  |  | $self->{irssi}->$irc_command($self, $who, $body); | 
| 210 |  |  |  |  |  |  | } | 
| 211 | 0 | 0 |  |  |  |  | } | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | return; | 
| 214 | 0 |  |  |  |  |  | } | 
| 215 | 0 |  |  |  |  |  |  | 
| 216 | 0 | 0 |  |  |  |  | my $return; | 
| 217 | 0 |  |  |  |  |  | my $mess = {}; | 
| 218 |  |  |  |  |  |  | return unless $nick && $address; | 
| 219 | 0 | 0 |  |  |  |  | $mess->{who} = $nick; | 
| 220 | 0 | 0 |  |  |  |  | $mess->{raw_nick} = "$nick!$address"; | 
| 221 |  |  |  |  |  |  |  | 
| 222 | 0 | 0 |  |  |  |  | $mess->{channel} = $channel; | 
| 223 | 0 |  |  |  |  |  | $mess->{body} = $received; #chanjoin or chanpart | 
| 224 |  |  |  |  |  |  | $mess->{address} = "chan"; | 
| 225 | 0 |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | # okay, call the chanjoin/chanpart method | 
| 227 |  |  |  |  |  |  | $return = $self->$received($mess); | 
| 228 |  |  |  |  |  |  |  | 
| 229 | 0 |  |  |  |  |  | ### what did we get back? | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | # nothing? Say nothing then | 
| 232 | 0 |  |  | 0 | 0 |  | return if !defined $return; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 233 | 0 |  |  |  |  |  |  | 
| 234 | 0 |  |  |  |  |  | # a string?  Say it how we were addressed then | 
| 235 | 0 | 0 | 0 |  |  |  | if (!ref $return) { | 
| 236 | 0 |  |  |  |  |  | $mess->{body} = $return; | 
| 237 | 0 |  |  |  |  |  | $self->say($mess); | 
| 238 |  |  |  |  |  |  | return; | 
| 239 | 0 |  |  |  |  |  | } | 
| 240 | 0 |  |  |  |  |  | } | 
| 241 | 0 |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | my $return; | 
| 243 |  |  |  |  |  |  | my $mess = {}; | 
| 244 | 0 |  |  |  |  |  |  | 
| 245 |  |  |  |  |  |  | # pass the raw body through | 
| 246 |  |  |  |  |  |  | $mess->{raw_body} = $body; | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | # work out who it was from | 
| 249 | 0 | 0 |  |  |  |  | return unless $nick && $address; | 
| 250 |  |  |  |  |  |  | $mess->{who} = $nick; | 
| 251 |  |  |  |  |  |  | $mess->{raw_nick} = "$nick!$address"; | 
| 252 | 0 | 0 |  |  |  |  |  | 
| 253 | 0 |  |  |  |  |  | # right, get the list of places this message was | 
| 254 | 0 |  |  |  |  |  | # sent to and work out the first one that we're | 
| 255 | 0 |  |  |  |  |  | # either a memeber of is is our nick. | 
| 256 |  |  |  |  |  |  | # The IRC protocol allows messages to be sent to multiple | 
| 257 |  |  |  |  |  |  | # targets, which is pretty clever. However, noone actually | 
| 258 |  |  |  |  |  |  | # /does/ this, so we can get away with this: | 
| 259 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 260 | 0 |  |  |  |  |  | my $channel = $target; | 
| 261 | 0 |  |  |  |  |  | if (lc($channel) eq lc($self->nick)) { | 
| 262 |  |  |  |  |  |  | $mess->{channel} = "msg"; | 
| 263 |  |  |  |  |  |  | $mess->{address} = "msg"; | 
| 264 | 0 |  |  |  |  |  | } | 
| 265 |  |  |  |  |  |  | else { | 
| 266 |  |  |  |  |  |  | $mess->{channel} = $channel; | 
| 267 | 0 | 0 | 0 |  |  |  | } | 
| 268 | 0 |  |  |  |  |  |  | 
| 269 | 0 |  |  |  |  |  | # okay, work out if we're addressed or not | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | $mess->{body} = $body; | 
| 272 |  |  |  |  |  |  | if ($mess->{channel} ne "msg") { | 
| 273 |  |  |  |  |  |  | my $own_nick = $self->nick; | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | if ($mess->{body} =~ s/^(\Q$own_nick\E)\s*[:,-]?\s*//i) { | 
| 276 |  |  |  |  |  |  | $mess->{address} = $1; | 
| 277 |  |  |  |  |  |  | } | 
| 278 | 0 |  |  |  |  |  |  | 
| 279 | 0 | 0 |  |  |  |  | for my $alt_nick ($self->alt_nicks) { | 
| 280 | 0 |  |  |  |  |  | last if $mess->{address}; | 
| 281 | 0 |  |  |  |  |  | if ($mess->{body} =~ s/^(\Q$alt_nick\E)\s*[:,-]?\s*//i) { | 
| 282 |  |  |  |  |  |  | $mess->{address} = $1; | 
| 283 |  |  |  |  |  |  | } | 
| 284 | 0 |  |  |  |  |  | } | 
| 285 |  |  |  |  |  |  | } | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | # strip off whitespace before and after the message | 
| 288 |  |  |  |  |  |  | $mess->{body} =~ s/^\s+//; | 
| 289 | 0 |  |  |  |  |  | $mess->{body} =~ s/\s+$//; | 
| 290 | 0 | 0 |  |  |  |  |  | 
| 291 | 0 |  |  |  |  |  | # check if someone was asking for help | 
| 292 |  |  |  |  |  |  | if ($mess->{address} && $mess->{body} =~ /^help/i) { | 
| 293 | 0 | 0 |  |  |  |  | $mess->{body} = $self->help($mess) or return; | 
| 294 | 0 |  |  |  |  |  | $self->say($mess); | 
| 295 |  |  |  |  |  |  | return; | 
| 296 |  |  |  |  |  |  | } | 
| 297 | 0 |  |  |  |  |  |  | 
| 298 | 0 | 0 |  |  |  |  | # okay, call the said/emoted method | 
| 299 | 0 | 0 |  |  |  |  | $return = $self->$received($mess); | 
| 300 | 0 |  |  |  |  |  |  | 
| 301 |  |  |  |  |  |  | ### what did we get back? | 
| 302 |  |  |  |  |  |  |  | 
| 303 |  |  |  |  |  |  | # nothing? Say nothing then | 
| 304 |  |  |  |  |  |  | return if !defined $return; | 
| 305 |  |  |  |  |  |  |  | 
| 306 | 0 |  |  |  |  |  | # a string?  Say it how we were addressed then | 
| 307 | 0 |  |  |  |  |  | if (!ref $return && length $return) { | 
| 308 |  |  |  |  |  |  | $mess->{body} = $return; | 
| 309 |  |  |  |  |  |  | $self->$respond($mess); | 
| 310 | 0 | 0 | 0 |  |  |  | return; | 
| 311 | 0 | 0 |  |  |  |  | } | 
| 312 | 0 |  |  |  |  |  | } | 
| 313 | 0 |  |  |  |  |  |  | 
| 314 |  |  |  |  |  |  | print "[ => ] " . ($self->{server} ? "[$self->{server}{tag}] " : "") . $mess->{body}; | 
| 315 |  |  |  |  |  |  | } | 
| 316 |  |  |  |  |  |  |  | 
| 317 | 0 |  |  |  |  |  | local $self->{conn_tag} = $network | 
| 318 |  |  |  |  |  |  | if $network; | 
| 319 |  |  |  |  |  |  | $self->{irssi}->own_nick($self) | 
| 320 |  |  |  |  |  |  | } | 
| 321 |  |  |  |  |  |  |  | 
| 322 | 0 | 0 |  |  |  |  | local $self->{conn_tag} = $network | 
| 323 |  |  |  |  |  |  | if $network; | 
| 324 |  |  |  |  |  |  | $self->{irssi}->find_alternate_nicks($self) | 
| 325 | 0 | 0 | 0 |  |  |  | } | 
| 326 | 0 |  |  |  |  |  |  | 
| 327 | 0 |  |  |  |  |  | my $self = shift; | 
| 328 | 0 |  |  |  |  |  | my $args; | 
| 329 |  |  |  |  |  |  |  | 
| 330 |  |  |  |  |  |  | if (ref($_[0])) { | 
| 331 |  |  |  |  |  |  | $args = shift; | 
| 332 | 0 |  |  | 0 | 0 |  | } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 333 | 0 | 0 |  |  |  |  | else { | 
| 334 |  |  |  |  |  |  | my %args = @_; | 
| 335 |  |  |  |  |  |  | $args = \%args; | 
| 336 | 0 |  |  | 0 | 0 |  | } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 337 | 0 | 0 |  |  |  |  |  | 
| 338 |  |  |  |  |  |  | return if !$args->{run}; | 
| 339 | 0 |  |  |  |  |  |  | 
| 340 |  |  |  |  |  |  | $args->{handler}   = $args->{handler}   || "_fork_said"; | 
| 341 |  |  |  |  |  |  | $args->{arguments} = $args->{arguments} || []; | 
| 342 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 343 | 0 | 0 |  |  |  |  | #$poe_kernel->state( $args->{handler}, $args->{callback} || $self  ); | 
| 344 |  |  |  |  |  |  |  | 
| 345 | 0 |  |  |  |  |  | my $run; | 
| 346 |  |  |  |  |  |  | $run = sub { | 
| 347 |  |  |  |  |  |  | my ($stdout, $stderr, $result) = capture { | 
| 348 |  |  |  |  |  |  | return scalar $args->{run}->($args->{body}, @{ $args->{arguments} }); | 
| 349 | 0 |  |  | 0 | 0 |  | }; | 
| 350 | 0 |  |  |  |  |  | return $stdout || $result; | 
| 351 |  |  |  |  |  |  | }; | 
| 352 | 0 | 0 |  |  |  |  |  | 
| 353 | 0 |  |  |  |  |  | my $pt = $self->{irssi}->bg_do($run, $args->{handler}); | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | # store the wheel object in our bot, so we can retrieve/delete easily | 
| 356 | 0 |  |  |  |  |  |  | 
| 357 | 0 |  |  |  |  |  | $self->{forks}{ $pt } = { | 
| 358 |  |  |  |  |  |  | args  => { | 
| 359 |  |  |  |  |  |  | conn_tag => $self->{conn_tag}, | 
| 360 | 0 | 0 |  |  |  |  | channel => $args->{channel}, | 
| 361 |  |  |  |  |  |  | who     => $args->{who}, | 
| 362 | 0 |  | 0 |  |  |  | address => $args->{address} | 
| 363 | 0 |  | 0 |  |  |  | } | 
| 364 |  |  |  |  |  |  | }; | 
| 365 |  |  |  |  |  |  | return; | 
| 366 |  |  |  |  |  |  | } | 
| 367 | 0 |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | my $func = $rhandler =~ /::/ ? $rhandler : "Bot::BasicBot::Pluggable::$rhandler"; | 
| 369 |  |  |  |  |  |  | my $args = $self->{forks}{$pipetag}; | 
| 370 | 0 |  |  |  |  |  | $args = $args->{args} if $args; | 
|  | 0 |  |  |  |  |  |  | 
| 371 | 0 |  |  | 0 |  |  | local $self->{conn_tag} = $args->{conn_tag}; | 
| 372 | 0 |  | 0 |  |  |  | local $self->{server} = Irssi::server_find_tag($args->{conn_tag}) | 
| 373 | 0 |  |  |  |  |  | if $args->{conn_tag}; | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 0 |  |  |  |  |  | my @args; | 
| 376 |  |  |  |  |  |  | $args[OBJECT] = $self; | 
| 377 |  |  |  |  |  |  | $args[ARG0] = $data; | 
| 378 |  |  |  |  |  |  | $args[ARG1] = $pipetag; | 
| 379 |  |  |  |  |  |  | { | 
| 380 |  |  |  |  |  |  | no strict 'refs'; | 
| 381 |  |  |  |  |  |  | &$func(@args); | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | delete $self->{forks}{$pipetag}; | 
| 385 |  |  |  |  |  |  | } | 
| 386 | 0 |  |  |  |  |  |  | 
| 387 | 0 |  |  |  |  |  | my ($bot, $body, $wheel_id) = @_[OBJECT, ARG0, ARG1]; | 
| 388 |  |  |  |  |  |  | chomp $body;    # remove newline necessary to move data; | 
| 389 |  |  |  |  |  |  |  | 
| 390 | 0 |  |  | 0 | 0 |  | # pick up the default arguments we squirreled away earlier | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 391 | 0 | 0 |  |  |  |  | my $args = $bot->{forks}{$wheel_id}{args}; | 
| 392 | 0 |  |  |  |  |  | $args->{body} = $body; | 
| 393 | 0 | 0 |  |  |  |  |  | 
| 394 | 0 |  |  |  |  |  | $bot->say($args); | 
| 395 |  |  |  |  |  |  | return; | 
| 396 | 0 | 0 |  |  |  |  | } | 
| 397 |  |  |  |  |  |  |  | 
| 398 | 0 |  |  |  |  |  | BEGIN { | 
| 399 | 0 |  |  |  |  |  | my @dispatchable_events = ( | 
| 400 | 0 |  |  |  |  |  | qw/ | 
| 401 | 0 |  |  |  |  |  | connected chanjoin chanpart userquit nick_change | 
| 402 |  |  |  |  |  |  | topic kicked raw_in raw_out | 
| 403 | 1 |  |  | 1 |  | 7 | / | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 180 |  | 
|  | 0 |  |  |  |  |  |  | 
| 404 | 0 |  |  |  |  |  | ); | 
| 405 |  |  |  |  |  |  | my @priority_events = (qw/ said emoted /); | 
| 406 |  |  |  |  |  |  | { | 
| 407 | 0 |  |  |  |  |  | ## no critic qw(ProhibitNoStrict) | 
| 408 |  |  |  |  |  |  | no strict 'refs'; | 
| 409 |  |  |  |  |  |  | for my $event (@dispatchable_events) { | 
| 410 |  |  |  |  |  |  | *$event = sub { | 
| 411 | 0 |  |  | 0 |  |  | shift->dispatch( $event, @_ ); | 
| 412 | 0 |  |  |  |  |  | }; | 
| 413 |  |  |  |  |  |  | } | 
| 414 |  |  |  |  |  |  | for my $event (@priority_events) { | 
| 415 | 0 |  |  |  |  |  | *$event = sub { | 
| 416 | 0 |  |  |  |  |  | shift->dispatch_priorities( $event, @_ ); | 
| 417 |  |  |  |  |  |  | }; | 
| 418 | 0 |  |  |  |  |  | } | 
| 419 | 0 |  |  |  |  |  | } | 
| 420 |  |  |  |  |  |  | } | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | $mess->{body} =~ s/^help\s*//i; | 
| 423 | 1 |  |  | 1 |  | 6 | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  | unless ( $mess->{body} ) { | 
| 426 |  |  |  |  |  |  | return | 
| 427 |  |  |  |  |  |  | "Ask me for help about: " | 
| 428 |  |  |  |  |  |  | . join( ", ", $self->modules() ) | 
| 429 | 1 |  |  |  |  | 3 | . " (say 'help <modulename>')."; | 
| 430 |  |  |  |  |  |  | } | 
| 431 |  |  |  |  |  |  | else { | 
| 432 | 1 |  |  | 1 |  | 8 | if ( my $module = $self->module( $mess->{body} ) ) { | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 115 |  | 
|  | 1 |  |  |  |  | 2 |  | 
| 433 | 1 |  |  |  |  | 3 | try { | 
| 434 |  |  |  |  |  |  | return $module->help($mess); | 
| 435 | 0 |  |  | 0 |  | 0 | } | 
| 436 | 9 |  |  |  |  | 41 | catch { | 
| 437 |  |  |  |  |  |  | $logger->warn( | 
| 438 | 1 |  |  |  |  | 2 | "Error calling help for module $mess->{body}: $_"); | 
| 439 |  |  |  |  |  |  | } | 
| 440 | 0 |  |  | 0 |  | 0 | } | 
| 441 | 2 |  |  |  |  | 355 | else { | 
| 442 |  |  |  |  |  |  | return "I don't know anything about '$mess->{body}'."; | 
| 443 |  |  |  |  |  |  | } | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  | } | 
| 446 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 447 | 0 |  |  |  |  |  | return bless +{ bot => $self, irssi => $self->{irssi}, conn_tag => ($network // $self->{conn_tag}) } | 
| 448 | 0 |  |  |  |  |  | => 'Irssi::Bot::BasicBot::Pluggable::PoCoIrc'; | 
| 449 |  |  |  |  |  |  | } | 
| 450 | 0 | 0 |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 452 | 0 |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | # it's safe to die here, mostly this call is eval'd. | 
| 454 |  |  |  |  |  |  | $logger->logdie("Cannot load module without a name") unless $module; | 
| 455 |  |  |  |  |  |  | $logger->logdie("Module $module already loaded") if $self->module($module); | 
| 456 |  |  |  |  |  |  |  | 
| 457 | 0 | 0 |  |  |  |  | # This is possible a leeeetle bit evil. | 
| 458 |  |  |  |  |  |  | $logger->info("Loading module $module"); | 
| 459 | 0 |  |  | 0 |  |  | my $filename = $module; | 
| 460 |  |  |  |  |  |  | $filename =~ s{::}{/}g; | 
| 461 |  |  |  |  |  |  | my $file = "Bot/BasicBot/Pluggable/Module/$filename.pm"; | 
| 462 | 0 |  |  | 0 |  |  | $file = "Irssi/Bot/BasicBot/Pluggable/Module/Auth.pm" | 
| 463 |  |  |  |  |  |  | if lc $module eq 'auth'; | 
| 464 |  |  |  |  |  |  | $logger->debug("Loading module $module from file $file"); | 
| 465 | 0 |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | # force a reload of the file (in the event that we've already loaded it). | 
| 467 | 0 |  |  |  |  |  | no warnings 'redefine'; | 
| 468 |  |  |  |  |  |  | delete $INC{$file}; | 
| 469 |  |  |  |  |  |  |  | 
| 470 |  |  |  |  |  |  | try { require $file } catch { die "Can't load $module: $_"; }; | 
| 471 |  |  |  |  |  |  |  | 
| 472 | 0 |  |  | 0 | 0 |  | # Ok, it's very evil. Don't bother me, I'm working. | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 473 | 0 |  | 0 |  |  |  |  | 
| 474 |  |  |  |  |  |  | my $m = "Bot::BasicBot::Pluggable::Module::$module"->new( | 
| 475 |  |  |  |  |  |  | Bot   => $self, | 
| 476 |  |  |  |  |  |  | ); | 
| 477 | 0 |  |  | 0 | 0 |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 478 | 0 |  |  |  |  |  | $logger->logdie("->new didn't return an object") unless ( $m and ref($m) ); | 
| 479 |  |  |  |  |  |  | $logger->logdie( ref($m) . " isn't a $module" ) | 
| 480 |  |  |  |  |  |  | unless ref($m) =~ /\Q$module/; | 
| 481 | 0 | 0 |  |  |  |  |  | 
| 482 | 0 | 0 |  |  |  |  | $self->add_module( $m, $module ); | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | return $m; | 
| 485 | 0 |  |  |  |  |  | } | 
| 486 | 0 |  |  |  |  |  |  | 
| 487 | 0 |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 488 | 0 |  |  |  |  |  | $logger->logdie("Cannot reload module without a name") unless $module; | 
| 489 | 0 | 0 |  |  |  |  | $self->remove_module($module) if $self->module($module); | 
| 490 |  |  |  |  |  |  | return $self->load($module); | 
| 491 | 0 |  |  |  |  |  | } | 
| 492 |  |  |  |  |  |  |  | 
| 493 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 494 | 1 |  |  | 1 |  | 7 | $logger->logdie("Need name")  unless $module; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 725 |  | 
| 495 | 0 |  |  |  |  |  | $logger->logdie("Not loaded") unless $self->module($module); | 
| 496 |  |  |  |  |  |  | $logger->info("Unloading module $module"); | 
| 497 | 0 |  |  | 0 |  |  | $self->remove_module($module); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 498 |  |  |  |  |  |  | } | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | return $self->{store}; | 
| 501 | 0 |  |  |  |  |  | } | 
| 502 |  |  |  |  |  |  |  | 
| 503 |  |  |  |  |  |  | return $self->{modules}{ lc($name) }; | 
| 504 |  |  |  |  |  |  | } | 
| 505 | 0 | 0 | 0 |  |  |  |  | 
| 506 | 0 | 0 |  |  |  |  | my @keys = sort { | 
| 507 |  |  |  |  |  |  | my $xa = $self->module($a); | 
| 508 |  |  |  |  |  |  | my $xb = $self->module($b); | 
| 509 | 0 |  |  |  |  |  | ( | 
| 510 |  |  |  |  |  |  | ($xb->get('user_priority') || $xb->get('priority') || 0) | 
| 511 | 0 |  |  |  |  |  | <=> | 
| 512 |  |  |  |  |  |  | ($xa->get('user_priority') || $xa->get('priority') || 0) | 
| 513 |  |  |  |  |  |  | ) || ($a cmp $b) | 
| 514 | 0 |  |  | 0 | 0 |  | } keys( %{ $self->{modules} } ); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 515 | 0 |  |  |  |  |  | return @keys if wantarray; | 
| 516 | 0 | 0 |  |  |  |  | return \@keys; | 
| 517 | 0 | 0 |  |  |  |  | } | 
| 518 | 0 |  |  |  |  |  |  | 
| 519 |  |  |  |  |  |  | # deprecated | 
| 520 |  |  |  |  |  |  |  | 
| 521 | 0 |  |  | 0 | 0 |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 522 | 0 |  |  |  |  |  | $logger->logdie("Need a name for adding a module") unless $name; | 
| 523 | 0 | 0 |  |  |  |  | $logger->logdie("Can't load a module with a duplicate name $name") | 
| 524 | 0 | 0 |  |  |  |  | if $self->{modules}{ lc($name) }; | 
| 525 | 0 |  |  |  |  |  | $self->{modules}{ lc($name) } = $module; | 
| 526 | 0 |  |  |  |  |  | } | 
| 527 |  |  |  |  |  |  |  | 
| 528 |  |  |  |  |  |  | my $logger = Irssi::Log::Log4perl->get_logger( ref $self ); | 
| 529 | 0 |  |  | 0 | 0 |  | $logger->logdie("Need a name for removing a module") unless $name; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 530 | 0 |  |  |  |  |  | $logger->logdie("Module $name not defined") | 
| 531 |  |  |  |  |  |  | unless $self->{modules}{ lc($name) }; | 
| 532 |  |  |  |  |  |  | $self->{modules}{ lc($name) }->stop(); | 
| 533 | 0 |  |  | 0 | 1 |  | delete $self->{modules}{ lc($name) }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 534 | 0 |  |  |  |  |  | } | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | for my $module (reverse $self->modules) { | 
| 537 | 0 |  |  | 0 | 1 |  | $self->remove_module($module); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 538 |  |  |  |  |  |  | } | 
| 539 | 0 |  |  |  |  |  | return; | 
| 540 | 0 |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 | 0 | 0 | 0 |  |  |  |  | 
|  |  |  | 0 |  |  |  |  | 
| 543 |  |  |  |  |  |  | 1; | 
| 544 |  |  |  |  |  |  |  | 
| 545 |  |  |  |  |  |  | use strict; | 
| 546 | 0 |  |  |  |  |  | use warnings; | 
|  | 0 |  |  |  |  |  |  | 
| 547 | 0 | 0 |  |  |  |  | use experimental 'signatures'; | 
| 548 | 0 |  |  |  |  |  |  | 
| 549 |  |  |  |  |  |  | return 0 unless $self->{conn_tag}; | 
| 550 |  |  |  |  |  |  | my $server = Irssi::server_find_tag($self->{conn_tag}) | 
| 551 |  |  |  |  |  |  | or return 0; | 
| 552 | 0 |  |  | 0 | 0 |  | my $ch = $server->channel_find($channel) | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 553 |  |  |  |  |  |  | or return 0; | 
| 554 | 0 |  |  | 0 | 0 |  | my $n = $ch->nick_find($nick) | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 555 | 0 |  |  |  |  |  | or return 0; | 
| 556 | 0 | 0 |  |  |  |  | return 1; | 
| 557 |  |  |  |  |  |  | } | 
| 558 | 0 | 0 |  |  |  |  |  | 
| 559 | 0 |  |  |  |  |  | warn "connection lost: $channel", | 
| 560 |  |  |  |  |  |  | return () unless $self->{conn_tag}; | 
| 561 |  |  |  |  |  |  | my $server = Irssi::server_find_tag($self->{conn_tag}) | 
| 562 | 0 |  |  | 0 | 0 |  | or warn "connection lost: $self->{conn_tag}", return (); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 563 | 0 |  |  |  |  |  | my $ch = $server->channel_find($channel) | 
| 564 | 0 | 0 |  |  |  |  | or return (); | 
| 565 |  |  |  |  |  |  | return map { $_->{nick} } $ch->nicks; | 
| 566 | 0 | 0 |  |  |  |  | } | 
| 567 | 0 |  |  |  |  |  |  | 
| 568 | 0 |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  | 1; |