]>
jfr.im git - irc/SurrealServices/srsv.git/blob - branches/erry-devel/modules/serviceslibs/botserv.pm
1 # This file is part of SurrealServices.
3 # SurrealServices is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 # SurrealServices is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with SurrealServices; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 use SrSv
::Process
::Worker
'ima_worker'; #FIXME
26 use SrSv
::Text
::Format
qw(columnar);
30 use SrSv
::Conf2Consts
qw( main services );
32 use SrSv
::User
qw(get_user_nick get_user_id :flood);
33 use SrSv
::User
::Notice
;
34 use SrSv
::Help
qw( sendhelp );
36 use SrSv
::ChanReg
::Flags
;
37 use SrSv
::NickReg
::Flags
qw(NRF_NOHIGHLIGHT nr_chk_flag_user);
39 use SrSv
::MySQL
'$dbh';
46 our $bsnick_default = 'BotServ';
47 our $bsnick = $bsnick_default;
49 our $bsuser = { NICK
=> $bsnick, ID
=> "123AAAAAF" };
50 if(!ircd
::PREFIXAQ_DISABLE
()) {
56 *agent
= \
&chanserv
::agent
;
58 our $calc_safe = new Safe
;
61 $get_all_bots, $get_botchans, $get_botstay_chans, $get_chan_bot, $get_bots_chans, $get_bot_info,
63 $create_bot, $delete_bot, $delete_bot_allchans, $assign_bot, $unassign_bot,
64 $change_bot, $update_chanreg_bot,
68 $set_flag, $unset_flag, $get_flags
72 $get_all_bots = $dbh->prepare("SELECT nick, ident, vhost, gecos, flags FROM bot");
73 $get_botchans = $dbh->prepare("SELECT chan, COALESCE(bot, '$chanserv::csnick') FROM chanreg WHERE bot != '' OR (flags & ". CRF_BOTSTAY
() . ")");
74 $get_botstay_chans = $dbh->prepare("SELECT chan, COALESCE(bot, '$chanserv::csnick') FROM chanreg WHERE (flags & ".
76 $get_chan_bot = $dbh->prepare("SELECT bot FROM chanreg WHERE chan=?");
77 $get_bots_chans = $dbh->prepare("SELECT chan FROM chanreg WHERE bot=?");
78 $get_bot_info = $dbh->prepare("SELECT nick, ident, vhost, gecos, flags FROM bot WHERE nick=?");
80 $create_bot = $dbh->prepare("INSERT INTO bot SET nick=?, ident=?, vhost=?, gecos=?");
81 $delete_bot = $dbh->prepare("DELETE FROM bot WHERE nick=?");
82 $delete_bot_allchans = $dbh->prepare("UPDATE chanreg SET bot='' WHERE bot=?");
83 $change_bot = $dbh->prepare("UPDATE bot SET nick=?, ident=?, vhost=?, gecos=? WHERE nick=?");
84 $update_chanreg_bot = $dbh->prepare("UPDATE chanreg SET bot=? WHERE bot=?");
86 $assign_bot = $dbh->prepare("UPDATE chanreg, bot SET chanreg.bot=bot.nick WHERE bot.nick=? AND chan=?");
87 $unassign_bot = $dbh->prepare("UPDATE chanreg SET chanreg.bot='' WHERE chan=?");
89 $is_bot = $dbh->prepare("SELECT 1 FROM bot WHERE nick=?");
90 $has_bot = $dbh->prepare("SELECT 1 FROM chanreg WHERE chan=? AND bot != ''");
92 $set_flag = $dbh->prepare("UPDATE bot SET flags=(flags | (?)) WHERE nick=?");
93 $unset_flag = $dbh->prepare("UPDATE bot SET flags=(flags & ~(?)) WHERE nick=?");
94 $get_flags = $dbh->prepare("SELECT flags FROM bot WHERE bot.nick=?");
96 register
() unless ima_worker
; #FIXME
100 my ($user, $dstUser, $msg) = @_;
101 $user -> {AGENT
} = $dstUser;
102 my $src = $user->{NICK
};
103 my $dst = $dstUser->{NICK
};
104 if(lc $dstUser->{NICK
} eq lc $bsnick or lc $dstUser->{NICK
} eq lc $bsnick_default ) {
105 bs_dispatch
($user, $dstUser, $msg);
107 elsif($dst =~ /^#/) {
109 $has_bot->execute($dst);
110 return unless($has_bot->fetchrow_array);
111 chan_dispatch
($src, $dst, $msg);
113 chan_msg
($src, $dst, $msg);
117 $is_bot->execute($dst);
118 if($is_bot->fetchrow_array) {
119 bot_dispatch
($src, $dst, $msg);
124 ### BOTSERV COMMANDS ###
126 sub bs_dispatch
($$$) {
127 my ($user, $dst, $msg) = @_;
129 my @args = split(/\s+/, $msg);
130 my $cmd = shift @args;
131 $user -> {AGENT
} = $dst;
132 my $src = $user->{NICK
};
133 return if flood_check
($user);
135 if($cmd =~ /^assign$/i) {
137 bs_assign
($user, {CHAN
=> $args[0]}, $args[1]);
139 notice
($user, 'Syntax: ASSIGN <#channel> <bot>');
142 elsif ($cmd =~ /^unassign$/i) {
144 bs_assign
($user, {CHAN
=> $args[0]}, '');
146 notice
($user, 'Syntax: UNASSIGN <#channel>');
149 elsif ($cmd =~ /^list$/i) {
153 notice
($user, 'Syntax: LIST');
156 elsif ($cmd =~ /^add$/i) {
158 @args = split(/\s+/, $msg, 5);
159 bs_add
($user, $args[1], $args[2], $args[3], $args[4]);
161 notice
($user, 'Syntax: ADD <nick> <ident> <vhost> <realname>');
164 elsif ($cmd =~ /^change$/i) {
166 @args = split(/\s+/, $msg, 6);
167 bs_change
($user, $args[1], $args[2], $args[3], $args[4], $args[5]);
169 notice
($user, 'Syntax: ADD <oldnick> <nick> <ident> <vhost> <realname>');
172 elsif ($cmd =~ /^del(ete)?$/i) {
174 bs_del
($user, $args[0]);
176 notice
($user, 'Syntax: DEL <botnick>');
179 elsif($cmd =~ /^set$/i) {
181 bs_set
($user, $args[0], $args[1], $args[2]);
183 notice
($user, 'Syntax: SET <botnick> <option> <value>');
186 elsif($cmd =~ /^seen$/i) {
188 nickserv
::ns_seen
($user, @args);
190 notice
($user, 'Syntax: SEEN <nick> [nick ...]');
194 elsif($cmd =~ /^(say|act)$/i) {
196 my @args = split(/\s+/, $msg, 3);
197 my $botmsg = $args[2];
198 $botmsg = "\001ACTION $botmsg\001" if(lc $cmd eq 'act');
199 bot_say
($user, {CHAN
=> $args[1]}, $botmsg);
201 notice
($user, 'Syntax: '.uc($cmd).' <#chan> <message>');
204 elsif($cmd =~ /^info$/i) {
206 bs_info
($user, $args[0]);
208 notice
($user, 'Syntax: INFO <botnick>');
211 elsif($cmd =~ /^help$/i) {
212 sendhelp
($user, 'botserv', @args);
214 elsif($cmd =~ /^d(ice)?$/i) {
215 notice
($user, get_dice
($args[0]));
218 notice
($user, "Unrecognized command. For help, type: \002/bs help\002");
222 # For unassign, set $bot to ''
225 my ($user, $chan, $bot) = @_;
227 chanserv
::chk_registered
($user, $chan) or return;
229 unless (chanserv
::can_do
($chan, 'BotAssign', $user)) {
230 notice
($user, $err_deny);
235 $is_bot->execute($bot);
236 unless($is_bot->fetchrow_array) {
237 notice
($user, "\002$bot\002 is not a bot.");
242 $get_flags->execute($bot);
243 my ($botflags) = $get_flags->fetchrow_array;
244 if (($botflags & F_PRIVATE
) && !adminserv
::can_do
($user, 'BOT')) {
245 notice
($user, $err_deny);
250 my $cn = $chan->{CHAN
};
251 my $src = get_user_nick
($user);
253 if ($oldbot = get_chan_bot
($chan)) {
254 agent_part
($oldbot, $cn, "Unassigned by \002$src\002.");
258 $assign_bot->execute($bot, $cn);
259 my $botUser = { NICK
=>$bot, ID
=>ircd
::getUuid
($bot) };
260 bot_join
($chan, $botUser);
261 notice
($user, "\002$bot\002 now assigned to \002$cn\002.");
263 $unassign_bot->execute($cn);
264 notice
($user, "\002$oldbot\002 removed from \002$cn\002.");
271 my $is_oper = adminserv
::is_svsop
($user, adminserv
::S_HELP
());
273 $get_all_bots->execute();
274 while (my ($botnick, $botident, $bothost, $botgecos, $flags) = $get_all_bots->fetchrow_array) {
276 push @data, [$botnick, "($botident\@$bothost)", $botgecos,
277 (($flags & F_PRIVATE
) ? "Private":"Public")];
279 next if($flags & F_PRIVATE
);
280 push @data, [$botnick, "($botident\@$bothost)", $botgecos];
284 notice
($user, columnar
({TITLE
=> "The following bots are available:",
285 NOHIGHLIGHT
=> nr_chk_flag_user
($user, NRF_NOHIGHLIGHT
)}, @data));
289 my ($user, $botnick, $botident, $bothost, $botgecos) = @_;
291 unless (adminserv
::can_do
($user, 'BOT')) {
292 notice
($user, $err_deny);
296 if (my $ret = is_invalid_agentname
($botnick, $botident, $bothost)) {
301 if(nickserv
::is_registered
($botnick)) {
302 notice
($user, "The nick \002$botnick\002 is already registered.");
306 if(nickserv
::is_online
($botnick)) {
307 notice
($user, "The nick \002$botnick\002 is currently in use.");
311 $is_bot->execute($botnick);
312 if($is_bot->fetchrow_array) {
313 notice
($user, "\002$botnick\002 already exists.");
317 $create_bot->execute($botnick, $botident, $bothost, $botgecos);
318 ircd
::sqline
($botnick, $services::qlreason
);
319 agent_connect
($botnick, $botident, $bothost, '+pqBSrz', $botgecos);
320 agent_join
($botnick, main_conf_diag
);
321 my $bot = { NICK
=> $botnick};
323 my $rsuser = { NICK
=> $main::rsnick
};
324 get_user_id
($rsuser);
325 $rsuser->{ID
} = encodeUUID
($rsuser->{ID
});
326 ircd
::setmode
($rsuser, main_conf_diag
, '+h', $bot);
327 notice
($user, "Bot $botnick connected.");
331 my ($user, $botnick) = @_;
333 unless (adminserv
::can_do
($user, 'BOT')) {
334 notice
($user, $err_deny);
337 $is_bot->execute($botnick);
338 if (!$is_bot->fetchrow_array) {
339 notice
($user, "\002$botnick\002 is not a bot.");
343 my $src = get_user_nick
($user);
344 $delete_bot->execute($botnick);
345 agent_quit
($botnick, "Deleted by \002$src\002.");
346 ircd
::unsqline
($botnick);
348 $delete_bot_allchans->execute($botnick);
349 notice
($user, "Bot \002$botnick\002 disconnected.");
353 my ($user, $botnick, $set, $parm) = @_;
355 unless (adminserv
::can_do
($user, 'BOT')) {
356 notice
($user, $err_deny);
359 if($set =~ /^private$/i) {
360 if ($parm =~ /^(on|true)$/i) {
361 set_flag
($botnick, F_PRIVATE
());
362 notice
($user, "\002$botnick\002 is now private.");
364 elsif ($parm =~ /^(off|false)$/i) {
365 unset_flag
($botnick, F_PRIVATE
());
366 notice
($user, "\002$botnick\002 is now public.");
369 notice
($user, 'Syntax: SET <botnick> PRIVATE <ON|OFF>');
372 if($set =~ /^deaf$/i) {
373 if ($parm =~ /^(on|true)$/i) {
374 set_flag
($botnick, F_DEAF
());
375 setagent_umode
($botnick, '+d');
376 notice
($user, "\002$botnick\002 is now deaf.");
378 elsif ($parm =~ /^(off|false)$/i) {
379 unset_flag
($botnick, F_DEAF
());
380 setagent_umode
($botnick, '-d');
381 notice
($user, "\002$botnick\002 is now undeaf.");
384 notice
($user, 'Syntax: SET <botnick> DEAF <ON|OFF>');
390 my ($user, $botnick) = @_;
392 unless (adminserv
::can_do
($user, 'HELP')) {
393 notice
($user, $err_deny);
396 $is_bot->execute($botnick);
397 unless($is_bot->fetchrow_array) {
398 notice
($user, "\002$botnick\002 is not a bot.");
402 $get_bot_info->execute($botnick);
403 my ($nick, $ident, $vhost, $gecos, $flags) = $get_bot_info->fetchrow_array;
404 $get_bot_info->finish();
405 $get_bots_chans->execute($botnick);
407 while (my $chan = $get_bots_chans->fetchrow_array) {
410 $get_bots_chans->finish();
412 notice
($user, columnar
({TITLE
=> "Information for bot \002$nick\002:",
413 NOHIGHLIGHT
=> nr_chk_flag_user
($user, NRF_NOHIGHLIGHT
)},
414 ['Mask:', "$ident\@$vhost"], ['Realname:', $gecos],
415 ['Flags:', (($flags & F_PRIVATE
())?'Private ':'').(($flags & F_DEAF
())?'Deaf ':'')],
417 'Assigned to '. @chans.' channel(s):',
418 ' ' . join(' ', @chans)
423 sub bs_change
($$$$$$) {
424 my ($user, $oldnick, $botnick, $botident, $bothost, $botgecos) = @_;
426 if (lc $oldnick eq lc $botnick) {
427 notice
($user, "Error: $oldnick is the same (case-insensitive) as $botnick",
428 "At this time, you cannot change only the ident, host, gecos, or nick-case of a bot.");
432 unless (adminserv
::can_do
($user, 'BOT')) {
433 notice
($user, $err_deny);
437 if (my $ret = is_invalid_agentname
($botnick, $botident, $bothost)) {
442 if(nickserv
::is_registered
($botnick)) {
443 notice
($user, "The nick \002$botnick\002 is already registered.");
447 if(nickserv
::is_online
($botnick)) {
448 notice
($user, "The nick \002$botnick\002 is currently in use.");
452 $is_bot->execute($botnick);
453 if($is_bot->fetchrow_array) {
454 notice
($user, "\002$botnick\002 already exists.");
458 #Create bot first, join it to its chans
459 # then finally delete the old bot
460 # This is to prevent races.
461 $create_bot->execute($botnick, $botident, $bothost, $botgecos);
462 ircd
::sqline
($botnick, $services::qlreason
);
463 agent_connect
($botnick, $botident, $bothost, '+pqBSrz', $botgecos);
464 agent_join
($botnick, main_conf_diag
);
465 my $rsnick = $main::rsnick
;
466 my $rsuser = { NICK
=> $main::rsnick
};
467 get_user_id
($rsuser);
468 $rsuser->{ID
} = encodeUUID
($rsuser->{ID
});
469 my $bot = { NICK
=> $botnick };
471 ircd
::setmode
($rsuser, main_conf_diag
, '+h', $bot);
473 notice
($user, "Bot $botnick connected.");
475 $get_bots_chans->execute($oldnick);
476 while(my ($cn) = $get_bots_chans->fetchrow_array()) {
477 my $chan = { CHAN
=> $cn };
478 my $botUser = { NICK
=>$botnick, ID
=>ircd
::getUuid
($botnick) };
479 bot_join
($chan, $botUser)
480 if chanserv
::get_user_count
($chan) or cr_chk_flag
($chan, CRF_BOTSTAY
(), 1);
482 $get_bots_chans->finish();
484 $update_chanreg_bot->execute($botnick, $oldnick); $update_chanreg_bot->finish();
486 my $src = get_user_nick
($user);
487 $delete_bot->execute($oldnick);
488 agent_quit
($oldnick, "Deleted by \002$src\002.");
489 ircd
::unsqline
($oldnick);
490 notice
($user, "Bot \002$oldnick\002 disconnected.");
493 ### CHANNEL COMMANDS ###
495 sub chan_dispatch
($$$) {
496 my ($user, $cn, $msg) = @_;
497 my $src = $user->{NICK
};
498 my @args = split(/\s+/, $msg);
499 my $cmd = lc(shift @args);
502 my $chan = { CHAN
=> $cn };
505 'voice' => \
&give_ops
,
506 'devoice' => \
&give_ops
,
508 'halfop' => \
&give_ops
,
509 'dehop' => \
&give_ops
,
510 'dehalfop' => \
&give_ops
,
512 'deop' => \
&give_ops
,
513 'protect' => \
&give_ops
,
514 'admin' => \
&give_ops
,
515 'deprotect' => \
&give_ops
,
516 'deadmin' => \
&give_ops
,
523 'invite' => \
&invite
,
529 'kickb' => \
&kickban
,
531 'kickban' => \
&kickban
,
533 'bkick' => \
&kickban
,
535 'bankick' => \
&kickban
,
537 'kickmask' => \
&kickmask
,
539 'kmask' => \
&kickmask
,
541 'kickbanmask' => \
&kickbanmask
,
542 'kickbmask' => \
&kickbanmask
,
543 'kickbm' => \
&kickbanmask
,
544 'kbm' => \
&kickbanmask
,
545 'kbanm' => \
&kickbanmask
,
546 'kbanmask' => \
&kickbanmask
,
547 'kbmask' => \
&kickbanmask
,
553 #We really need something that is mostly obvious
554 # and won't be used by any other bots.
555 #TriviaBot I added !trivhelp
556 # I guess anope uses !commands
558 'commands' => \
&help
,
566 'banlist' => \
&banlist
,
567 'blist' => \
&banlist
,
580 'resync' => \
&resync
,
584 my ($user, $cmd, $chan, @args) = @_;
586 chanserv
::cs_setmodes
($user, $cmd, $chan, @args);
589 my ($user, $cmd, $chan, @args) = @_;
590 chanserv
::cs_updown
($user, $cmd, $chan->{CHAN
}, @args);
593 my ($user, $cmd, $chan, @args) = @_;
594 if(lc $cmd eq 'molest') {
595 chanserv
::unset_modes
($user, $chan);
597 chanserv
::cs_updown
($user, $cmd, $chan->{CHAN
}, @args);
602 my ($user, $cmd, $chan, @args) = @_;
603 chanserv
::cs_invite
($user, $chan, @args) unless @args == 0;
607 my ($user, $cmd, $chan, @args) = @_;
608 my $target = shift @args;
609 chanserv
::cs_kick
($user, $chan, $target, 0, join(' ', @args));
612 my ($user, $cmd, $chan, @args) = @_;
613 my $target = shift @args;
614 chanserv
::cs_kick
($user, $chan, $target, 1, join(' ', @args));
618 my ($user, $cmd, $chan, @args) = @_;
619 my $target = shift @args;
620 chanserv
::cs_kickmask
($user, $chan, $target, 0, join(' ', @args));
623 my ($user, $cmd, $chan, @args) = @_;
624 my $target = shift @args;
625 chanserv
::cs_kickmask
($user, $chan, $target, 1, join(' ', @args));
629 my ($user, $cmd, $chan, @args) = @_;
630 my $msg = join(' ', @args);
633 s/[^*.+0-9&|)(x\/^-]//g
;
634 s/([*+\\.\/x-])\1*/$1/g;
639 my $answer = $calc_safe->reval("($msg) || 0");
640 $answer = 'ERROR' unless defined $answer;
642 notice
($user, ($@ ? "$msg = ERROR (${\ (split / at/, $@, 2)[0]})" : "$msg = $answer"));
646 my ($user, $cmd, $chan, @args) = @_;
649 nickserv
::ns_seen
($user, @args);
651 notice
($user, 'Syntax: SEEN <nick> [nick ...]');
656 my ($user, $cmd, $chan, @args) = @_;
657 sendhelp
($user, 'chanbot');
661 my ($user, $cmd, $chan, @args) = @_;
662 chanserv
::cs_alist
($user, $chan);
666 my ($user, $cmd, $chan, @args) = @_;
668 chanserv
::cs_unban
($user, $chan, get_user_nick
($user));
671 chanserv
::cs_unban
($user, $chan, @args);
676 my ($user, $cmd, $chan, @args) = @_;
677 $cmd =~ /^(q|n)?ban$/; my $type = $1;
679 chanserv
::cs_ban
($user, $chan, $type, @args);
684 my ($user, $cmd, $chan, @args) = @_;
685 chanserv
::cs_banlist
($user, $chan);
689 # FIXME: If dice is disabled, don't count towards flooding.
690 my ($user, $cmd, $chan, @args) = @_;
692 if(chanserv
::can_do
($chan, 'DICE', $user)) {
693 ircd
::privmsg
(agent
($chan), $chan->{CHAN
},
699 my ($user, $cmd, $chan, @args) = @_;
701 chanserv
::cs_mode
($user, $chan, shift @args, @args);
706 my ($user, $cmd, $chan) = @_;
707 chanserv
::cs_resync
($user, $chan->{CHAN
});
710 if(defined($cmdhash{$cmd})) {
711 return if flood_check
($user);
713 &{$cmdhash{$cmd}}($user, $cmd, $chan, @args);
718 my ($user, $chan, $botmsg) = @_;
719 my $cn = $chan->{CHAN
};
721 if(chanserv
::can_do
($chan, 'BotSay', $user)) {
722 ircd
::notice
(agent
($chan), '%'.$cn, get_user_nick
($user).' used BotSay')
723 if cr_chk_flag
($chan, CRF_VERBOSE
());
724 ircd
::privmsg
(agent
($chan), $cn, $botmsg);
726 notice
($user, $err_deny);
732 sub bot_dispatch
($$$) {
733 my ($user, $bot, $msg) = @_;
734 my ($cmd, $cn, $botmsg) = split(/ /, $msg, 3);
735 my $src = $user->{NICK
};
736 my $chan = { CHAN
=> $cn };
737 return if flood_check
($user);
738 if ($cmd =~ /^join$/i) {
739 if (adminserv
::can_do
($user, 'BOT')) {
740 agent_join
($bot, $cn);
742 notice
($user, $err_deny);
745 elsif ($cmd =~ /^part$/i) {
746 if (adminserv
::can_do
($user, 'BOT')) {
747 agent_part
($bot, $cn, "$src requested part");
749 notice
($user, $err_deny);
752 elsif ($cmd =~ /^say$/i) {
753 bot_say
($user, $chan, $botmsg);
755 elsif ($cmd =~ /^act$/i) {
756 bot_say
($user, $chan, "\001ACTION $botmsg\001");
758 elsif ($cmd =~ /^help$/i) {
759 #my @help; @help = ($cn) if $cn; push @help, split(/\s+/, $botmsg);
760 sendhelp
($user, 'botpriv');
765 my ($count, $sides) = map int($_), ($_[0] ? split('d', $_[0]) : (1, 6));
767 if ($sides < 1 or $sides > 1000 or $count < 0 or $count > 100) {
768 return "Sorry, you can't have more than 100 dice, or 1000 sides, or less than 1 of either.";
770 $count = 1 if $count == 0;
774 if($count == 1 or $count > 25) {
775 for(my $i = 1; $i <= $count; $i++) {
776 $sum += int(rand($sides)+1);
779 return "${count}d$sides: $sum";
784 for(my $i = 1; $i <= $count; $i++) {
785 my $n = int(rand($sides)+1);
790 return "${count}d$sides: $sum [" . join(' ', sort {$a <=> $b} @dice) . "]";
797 #We don't do chanmsg processing yet, like badwords.
801 $get_all_bots->execute();
802 while(my ($nick, $ident, $vhost, $gecos, $flags) = $get_all_bots->fetchrow_array) {
803 agent_connect
($nick, $ident, $vhost, '+pqBSrz'.(($flags & F_DEAF
())?'d':''), $gecos);
804 ircd
::sqline
($nick, $services::qlreason
);
805 my $bot = { NICK
=> $nick };
807 agent_join
($nick, main_conf_diag
);
808 my $rsuser = { NICK
=> $main::rsnick
};
809 get_user_id
($rsuser);
810 $rsuser->{ID
} = encodeUUID
($rsuser->{ID
});
811 ircd
::setmode
($rsuser, main_conf_diag
, '+h', $bot);
816 $get_botchans->execute();
817 while(my ($cn, $nick) = $get_botchans->fetchrow_array) {
818 my $chan = { CHAN
=> $cn };
819 if(chanserv
::get_user_count
($chan)) {
820 my $botUser = { NICK
=>$nick, ID
=>ircd
::getUuid
($nick) };
821 bot_join
($chan, $botUser);
823 elsif(cr_chk_flag
($chan, CRF_BOTSTAY
(), 1)) {
824 my $botUser = { NICK
=>$nick, ID
=>ircd
::getUuid
($nick) };
825 bot_join
($chan, $nick);
826 my $modelock = chanserv
::get_modelock
($chan);
827 ircd
::setmode
(main_conf_local
, $cn, $modelock) if $modelock;
832 ### Database Functions ###
835 my ($bot, $flag) = @_;
837 $set_flag->execute($flag, $bot);
841 my ($bot, $flag) = @_;
843 $unset_flag->execute($flag, $bot);
847 my ($chan, $bot) = @_;
848 my $cn = $chan->{CHAN
};
849 $bot = agent
($chan) unless $bot;
850 my $nick = $bot->{NICK
};
851 unless(is_agent_in_chan
($nick, $cn)) {
852 agent_join
($bot, $cn);
854 my $bot2 = { NICK
=> $nick, ID
=> encodeUUID
($bot->{ID
}) };
855 print "!!!!!!!! BOT $nick " . $bot->{ID
} . "\n";
856 ircd
::setmode
($bot2, $cn, $botchmode, $bot );
860 sub bot_part_if_needed
($$$;$) {
861 my ($nick, $chan, $reason, $empty) = @_;
862 my $cn = $chan->{CHAN
};
863 my $bot = get_chan_bot
($chan);
864 $nick = agent
($chan) unless $nick;
865 return if (lc $chanserv::enforcers
{lc $cn} eq lc $nick);
867 if(is_agent_in_chan
($nick, $cn)) {
868 if(lc $bot eq lc $nick) {
869 if(cr_chk_flag
($chan, CRF_BOTSTAY
(), 1) or ($empty != 1 or chanserv
::get_user_count
($chan))) {
874 agent_part
($nick, $cn, $reason);
878 sub get_chan_bot
($) {
880 my $cn = $chan->{CHAN
};
881 $botserv::get_chan_bot-
>execute($cn);
883 my ($bot) = $botserv::get_chan_bot-
>fetchrow_array();
884 $botserv::get_chan_bot-
>finish();