]>
jfr.im git - irc/SurrealServices/srsv.git/blob - branches/0.5.0/SrSv/Agent.pm
2856bdfcb1516e97dacc9276b347d223bc998e81
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
21 use Exporter
'import';
22 BEGIN { our @EXPORT = qw(
23 is_agent is_agent_in_chan
24 agent_connect agent_quit agent_quit_all
25 agent_join agent_part set_agent_umode
26 agent_sync is_invalid_agentname
29 use SrSv
::Process
::InParent
qw(
30 is_agent is_agent_in_chan
31 agent_connect agent_quit agent_quit_all
32 agent_join agent_part agent_sync
33 whois_callback kill_callback
36 use SrSv
::Conf2Consts
qw(main);
39 use SrSv
::Unreal
::Tokens
qw( :tokens );
40 use SrSv
::Unreal
::Base64
qw(itob64);
41 use SrSv
::IRCd
::State
qw(synced $ircd_ready %IRCd_capabilities);
42 use SrSv
::IRCd
::IO
qw(ircsend ircsendimm);
43 use SrSv
::IRCd
::Event
qw(addhandler);
44 use SrSv
::IRCd
::Validate
qw(valid_nick);
45 use SrSv
::RunLevel
'main_shutdown';
48 BEGIN { *SJB64
= \
&ircd
::SJB64
}
53 addhandler
('WHOIS', undef(), undef(), 'whois_callback', 1);
54 addhandler
('KILL', undef(), undef(), 'kill_callback', 1);
58 return (defined($agents{lc $nick}));
61 sub is_agent_in_chan
($$) {
62 my ($agent, $chan) = @_;
63 $agent = lc $agent; $chan = lc $chan;
65 if($agents{$agent} and $agents{$agent}{CHANS
} and $agents{$agent}{CHANS
}{$chan}) {
72 sub agent_connect
($$$$$) {
73 my ($nick, $ident, $host, $modes, $gecos) = @_;
77 if(defined($agents{lc $nick}) and ref($agents{lc $nick}{CHANS
})) {
78 @chans = keys(%{$agents{lc $nick}{CHANS
}});
81 $agents{lc $nick}{PARMS
} = [ @_ ];
83 $host = main_conf_local
unless $host;
84 ircsend
("@{[TOK_NICK]} $nick 1 $time $ident $host ".
85 (SJB64
? itob64
(main_conf_numeric
) : main_conf_local
).
86 " 1 $modes * :$gecos");
88 foreach my $chan (@chans) {
89 ircsend
(":$nick @{[TOK_JOIN]} $chan");
90 # If we tracked chanmodes for agents, that would go here as well.
95 my ($nick, $msg) = @_;
97 delete($agents{lc $nick}{CHANS
});
98 delete($agents{lc $nick});
100 ircsendimm
(":$nick @{[TOK_QUIT]} :$msg");
103 sub agent_quit_all
($) {
107 @agents = keys(%agents);
109 foreach my $a (@agents) {
110 agent_quit
($a, $msg);
114 sub is_invalid_agentname
($$$) {
115 my ($botnick, $botident, $bothost) = @_;
117 unless(valid_nick
($botnick)) {
118 return "Invalid nickname.";
120 unless($botident =~ /^[[:alnum:]_]+$/) {
121 return "Invalid ident.";
123 unless($bothost =~ /^[[:alnum:].-]+$/) {
124 return "Invalid vhost.";
126 unless($bothost =~ /\./) {
127 return "A vhost must contain at least one dot.";
133 my ($agent, $chan) = @_;
135 if($agents{lc $agent}) {
136 $agents{lc $agent}{CHANS
}{lc $chan} = 1;
137 ircsend
(":$agent @{[TOK_JOIN]} $chan");
140 print "Tried to make nonexistent agent ($agent) join channel ($chan)" if DEBUG
;
142 print "Deferred join: $agent $chan\n" if DEBUG
;
143 push @defer_join, "$agent $chan";
148 sub agent_part
($$$) {
149 my ($agent, $chan, $reason) = @_;
151 delete($agents{lc $agent}{CHANS
}{lc $chan});
152 ircsend
(":$agent @{[TOK_PART]} $chan :$reason");
155 sub set_agent_umode
($$) {
156 my ($src, $modes) = @_;
158 ircsend
(":$src @{[TOK_UMODE2]} $modes");
162 foreach my $j (@defer_join) {
163 print "Processing join: $j\n" if DEBUG
;
164 my ($agent, $chan) = split(/ /, $j);
165 agent_join
($agent, $chan);
171 #:wyvern.surrealchat.net 311 blah2 tabris northman SCnet-E5870F84.dsl.klmzmi.ameritech.net * :Sponsored by Skuld
172 #:wyvern.surrealchat.net 307 blah2 tabris :is a registered nick
173 #:wyvern.surrealchat.net 312 blah2 tabris wyvern.surrealchat.net :SurrealChat - aphrodite.wcshells.com - Chicago.IL
174 #:wyvern.surrealchat.net 671 blah2 tabris :is using a Secure Connection
175 #:wyvern.surrealchat.net 317 blah2 tabris 54 1118217330 :seconds idle, signon time
176 #:wyvern.surrealchat.net 401 blah2 nikanoru :No such nick/channel
177 #:wyvern.surrealchat.net 311 blah2 somebot bot SCnet-DA158DBF.hsd1.nh.comcast.net * :Some sort of bot
178 #:wyvern.surrealchat.net 312 blah2 somebot nascent.surrealchat.net :SurrealChat - Hub
179 #:wyvern.surrealchat.net 335 blah2 somebot :is a Bot on SurrealChat.net
180 #:wyvern.surrealchat.net 318 blah2 tabris,nikanoru,somebot :End of /WHOIS list.
182 # Also reference http://www.alien.net.au/irc/irc2numerics.html
184 my ($src, $nicklist) = @_;
186 my @nicks = split(/\,/, $nicklist);
188 foreach my $nick (@nicks) {
189 if (is_agent
($nick)) {
190 my ($nick, $ident, $host, $modes, $gecos) = @{$agents{lc $nick}{PARMS
}};
191 $host = main_conf_local
unless $host;
192 push @reply, ':'.main_conf_local
." 311 $src $nick $ident $host * :$gecos";
193 push @reply, ':'.main_conf_local
." 312 $src $nick ".main_conf_local
.' :'.main_conf_info
;
194 foreach my $mode (split(//, $modes)) {
196 push @reply, ':'.main_conf_local
." 671 $src $nick :is using a Secure Connection";
198 elsif($mode eq 'S') {
199 #313 tab ChanServ :is a Network Service
200 push @reply, ':'.main_conf_local
." 313 $src $nick :is a Network Service";
202 elsif($mode eq 'B') {
203 #335 blah2 TriviaBot :is a Bot on SurrealChat.net
204 push @reply, ':'.main_conf_local
.
205 " 335 $src $nick :is a \002Bot\002 on ".$IRCd_capabilities{NETWORK
};
210 push @reply, ':'.main_conf_local
." 401 $src $nick :No such service";
214 push @reply, ':'.main_conf_local
." 318 $src $nicklist :End of /WHOIS list.";
218 sub kill_callback
($$$$) {
219 my ($src, $dst, $path, $reason) = @_;
220 if (defined($agents{lc $dst})) {
221 if (defined ($agents{lc $dst}{KILLED
}) and ($agents{lc $dst}{KILLED
} == time())) {
222 if ($agents{lc $dst}{KILLCOUNT
} > 3) {
223 ircd
::debug
("Caught in a kill loop for $dst, dying now.");
226 $agents{lc $dst}{KILLCOUNT
}++;
229 $agents{lc $dst}{KILLED
} = time();
230 $agents{lc $dst}{KILLCOUNT
} = 1;
234 # let's NOT loopback this event
235 ircsendimm
(':'.main_conf_local
.' '."@{[TOK_KILL]} $dst :Nick Collision");
236 } elsif (defined($agents{lc $src})) {
239 ircd
::irckill
($main::rsnick
, $src, "Do not kill services agents.");
242 &agent_connect
(@{$agents{lc $dst}{PARMS
}}) if synced
();