File Coverage

blib/lib/Mojo/IRC/Server/Chinese.pm
Criterion Covered Total %
statement 39 439 8.8
branch 0 154 0.0
condition 0 20 0.0
subroutine 13 65 20.0
pod 1 21 4.7
total 53 699 7.5


line stmt bran cond sub pod time code
1             package Mojo::IRC::Server::Chinese;
2 1     1   14283 use strict;
  1         2  
  1         35  
3             $Mojo::IRC::Server::Chinese::VERSION = "1.8.1";
4 1     1   483 use Encode;
  1         7350  
  1         72  
5 1     1   384 use Encode::Locale;
  1         2404  
  1         44  
6 1     1   14 use Carp;
  1         2  
  1         69  
7 1     1   526 use Parse::IRC;
  1         1969  
  1         48  
8 1     1   455 use Mojo::IOLoop;
  1         151231  
  1         6  
9 1     1   39 use POSIX ();
  1         1  
  1         16  
10 1     1   3 use List::Util qw(first);
  1         1  
  1         46  
11 1     1   4 use Fcntl ':flock';
  1         0  
  1         92  
12 1     1   394 use Mojo::IRC::Server::Chinese::Base 'Mojo::EventEmitter';
  1         1  
  1         5  
13 1     1   376 use Mojo::IRC::Server::Chinese::User;
  1         2  
  1         9  
14 1     1   398 use Mojo::IRC::Server::Chinese::Channel;
  1         1  
  1         11  
15              
16             has host => "0.0.0.0";
17             has port => 6667;
18             has listen => undef;
19             has network => "Chinese IRC NetWork";
20             has ioloop => sub { Mojo::IOLoop->singleton };
21             has parser => sub { Parse::IRC->new };
22             has servername => "chinese-irc-server";
23             has clienthost => undef,
24             has create_time => sub{POSIX::strftime( '%Y/%m/%d %H:%M:%S', localtime() )};
25             has log_level => "info";
26             has log_path => undef;
27             has auth=>undef;
28              
29             has version => sub{$Mojo::IRC::Server::Chinese::VERSION};
30             has start_time => sub{time};
31              
32             has user => sub {[]};
33             has channel => sub {[]};
34              
35             has log => sub{
36             require Mojo::Log;
37 1     1   224 no warnings 'redefine';
  1         1  
  1         4300  
38             *Mojo::Log::append = sub{
39             my ($self, $msg) = @_;
40             return unless my $handle = $self->handle;
41             flock $handle, LOCK_EX;
42             $handle->print(encode("console_out", decode("utf8",$msg))) or $_[0]->die("Can't write to log: $!");
43             flock $handle, LOCK_UN;
44             };
45             Mojo::Log->new(path=>$_[0]->log_path,level=>$_[0]->log_level,format=>sub{
46             my ($time, $level, @lines) = @_;
47             my $title="";
48             if(ref $lines[0] eq "HASH"){
49             my $opt = shift @lines;
50             $time = $opt->{"time"} if defined $opt->{"time"};
51             $title = (defined $opt->{"title"})?$opt->{title} . " ":"";
52             $level = $opt->{level} if defined $opt->{"level"};
53             }
54             @lines = split /\n/,join "",@lines;
55             my $return = "";
56             $time = POSIX::strftime('[%y/%m/%d %H:%M:%S]',localtime($time));
57             for(@lines){
58             $return .=
59             $time
60             . " "
61             . "[$level]"
62             . " "
63             . $title
64             . $_
65             . "\n";
66             }
67             return $return;
68             });
69             };
70              
71             sub new_user{
72 0     0 0   my $s = shift;
73 0           my $user = $s->add_user(Mojo::IRC::Server::Chinese::User->new(@_,_server=>$s));
74 0 0         return $user if $user->is_virtual;
75             $user->io->on(read=>sub{
76 0     0     my($stream,$bytes) = @_;
77 0           $bytes = $user->buffer . $bytes;
78 0           my $pos = rindex($bytes,"\r\n");
79 0 0         if($pos != -1){#\r\n
80 0           my $lines = substr($bytes,0,$pos);
81 0           my $remains = substr($bytes,$pos+2);
82 0           $user->buffer($remains);
83 0           $stream->emit(line=>$_) for split /\r?\n/,$lines;
84             }
85             else{
86 0           $pos = rindex($bytes,"\n");
87 0 0         if($pos != -1){
88 0           my $lines = substr($bytes,0,$pos);
89 0           my $remains = substr($bytes,$pos+1);
90 0           $user->buffer($remains);
91 0           $stream->emit(line=>$_) for split /\r?\n/,$lines;
92             }
93             else{
94 0           $user->buffer($bytes);
95             }
96             }
97 0           });
98             $user->io->on(line=>sub{
99 0     0     my($stream,$line) = @_;
100 0           my $msg = $s->parser->parse($line);
101 0           $user->last_active_time(time());
102 0           $s->emit(user_msg=>$user,$msg);
103 0 0         if($msg->{command} eq "CAP"){$user->emit(cap=>$msg);$s->emit(cap=>$user,$msg);}
  0 0          
  0 0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
104 0           elsif($msg->{command} eq "PASS"){$user->emit(pass=>$msg);$s->emit(pass=>$user,$msg);}
  0            
105 0           elsif($msg->{command} eq "NICK"){$user->emit(nick=>$msg);$s->emit(nick=>$user,$msg);}
  0            
106 0           elsif($msg->{command} eq "USER"){$user->emit(user=>$msg);$s->emit(user=>$user,$msg);}
  0            
107 0           elsif($msg->{command} eq "JOIN"){$user->emit(join=>$msg);$s->emit(join=>$user,$msg);}
  0            
108 0           elsif($msg->{command} eq "PART"){$user->emit(part=>$msg);$s->emit(part=>$user,$msg);}
  0            
109 0           elsif($msg->{command} eq "PING"){$user->emit(ping=>$msg);$s->emit(ping=>$user,$msg);}
  0            
110 0           elsif($msg->{command} eq "PONG"){$user->emit(pong=>$msg);$s->emit(pong=>$user,$msg);}
  0            
111 0           elsif($msg->{command} eq "MODE"){$user->emit(mode=>$msg);$s->emit(mode=>$user,$msg);}
  0            
112 0           elsif($msg->{command} eq "PRIVMSG"){$user->emit(privmsg=>$msg);$s->emit(privmsg=>$user,$msg);}
  0            
113 0           elsif($msg->{command} eq "QUIT"){$user->is_quit(1);$user->emit(quit=>$msg);$s->emit(quit=>$user,$msg);}
  0            
  0            
114 0           elsif($msg->{command} eq "WHO"){$user->emit(who=>$msg);$s->emit(who=>$user,$msg);}
  0            
115 0           elsif($msg->{command} eq "WHOIS"){$user->emit(whois=>$msg);$s->emit(whois=>$user,$msg);}
  0            
116 0           elsif($msg->{command} eq "LIST"){$user->emit(list=>$msg);$s->emit(list=>$user,$msg);}
  0            
117 0           elsif($msg->{command} eq "TOPIC"){$user->emit(topic=>$msg);$s->emit(topic=>$user,$msg);}
  0            
118 0           elsif($msg->{command} eq "AWAY"){$user->emit(away=>$msg);$s->emit(away=>$user,$msg);}
  0            
119 0           else{$user->send($user->serverident,"421",$user->nick,$msg->{command},"Unknown command");}
120 0           });
121              
122             $user->io->on(error=>sub{
123 0     0     my ($stream, $err) = @_;
124 0           $user->emit("close",$err);
125 0           $s->emit(close_user=>$user,$err);
126 0           $s->debug("C[" .$user->name."] 连接错误: $err");
127 0           });
128             $user->io->on(close=>sub{
129 0     0     my ($stream, $err) = @_;
130 0           $user->emit("close",$err);
131 0           $s->emit(close_user=>$user,$err);
132 0           });
133             $user->on(close=>sub{
134 0     0     my ($user,$err) = @_;
135 0 0         return if $user->is_quit;
136 0 0         my $quit_reason = defined $user->close_reason? $user->close_reason:
    0          
137             defined $err ? $err :
138             "remote host closed connection";
139 0           $user->forward($user->ident,"QUIT",$quit_reason);
140 0           $user->is_quit(1);
141 0           $user->info("[" . $user->name . "] 已退出($quit_reason)");
142 0           $user->{_server}->remove_user($user);
143 0           });
144 0     0     $user->on(pass=>sub{my($user,$msg) = @_;my $pass = $msg->{params}[0]; $user->pass($pass);});
  0            
  0            
  0            
145 0     0     $user->on(nick=>sub{my($user,$msg) = @_;my $nick = $msg->{params}[0];$user->set_nick($nick)});
  0            
  0            
  0            
146 0     0     $user->on(user=>sub{my($user,$msg) = @_;
147 0 0         if(defined $user->search_user(user=>$msg->{params}[0])){
148 0           $user->send($user->serverident,"446",$user->nick,"该帐号已被使用");
149 0           $user->io->close_gracefully();
150 0           $user->{_server}->remove_user($user);
151 0           return;
152             }
153 0           $user->user($msg->{params}[0]);
154             #$user->mode($msg->{params}[1]);
155 0           $user->realname($msg->{params}[3]);
156 0 0 0       if(!$user->is_registered and $user->nick ne "*" and $user->user ne "*"){
      0        
157 0           $user->is_registered(1);
158             }
159 0           });
160 0     0     $user->on(join=>sub{my($user,$msg) = @_;
161 0           my $channels = $msg->{params}[0];
162 0           for my $channel_name (split /,/,$channels){
163 0           my $channel = $user->search_channel(name=>$channel_name);
164 0 0         if(defined $channel){
165 0           $user->join_channel($channel);
166             }
167             else{
168 0           $channel = $user->new_channel(name=>$channel_name,id=>lc($channel_name));
169 0           $user->join_channel($channel);
170             }
171             }
172 0           });
173 0     0     $user->on(part=>sub{my($user,$msg) = @_;
174 0           my $channel_name = $msg->{params}[0];
175 0           my $part_info = $msg->{params}[1];
176 0           my $channel = $user->search_channel(name=>$channel_name);
177 0 0         return if not defined $channel;
178 0           $user->part_channel($channel,$part_info);
179 0           });
180 0     0     $user->on(ping=>sub{my($user,$msg) = @_;
181 0           my $servername = $msg->{params}[0];
182 0           $user->send($user->serverident,"PONG",$user->servername,$servername);
183 0           });
184             $user->on(pong=>sub{
185 0     0     my($user,$msg) = @_;
186 0           my $current_ping_count = $user->ping_count;
187 0           $user->ping_count(--$current_ping_count);
188 0           });
189 0     0     $user->on(quit=>sub{my($user,$msg) = @_;
190 0           my $quit_reason = $msg->{params}[0];
191 0           $user->quit($quit_reason);
192 0           });
193 0     0     $user->on(privmsg=>sub{my($user,$msg) = @_;
194 0           $user->last_speak_time(time());
195 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
196 0           my $channel_name = $msg->{params}[0];
197 0           my $content = $msg->{params}[1];
198 0           my $channel = $user->search_channel(name=>$channel_name);
199 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
200 0           $channel->forward($user,$user->ident,"PRIVMSG",$channel_name,$content);
201 0           $s->info({level=>"IRC频道消息",title=>$user->nick ."|" .$channel->name.":"},$content);
202             }
203             else{
204 0           my $nick = $msg->{params}[0];
205 0           my $content = $msg->{params}[1];
206 0           my $u = $user->search_user(nick=>$nick);
207 0 0         if(defined $u){
208 0           $u->send($user->ident,"PRIVMSG",$nick,$content);
209 0 0         $user->send($user->serverident,"301",$user->nick,$u->nick,$u->away_info) if $u->is_away;
210 0           $s->info({level=>"IRC私信消息",title=>"[".$user->nick."]->[$nick] :"},$content);
211             }
212             else{
213 0           $user->send($user->serverident,"401",$user->nick,$nick,"No such nick");
214             }
215             }
216 0           });
217 0     0     $user->on(mode=>sub{my($user,$msg) = @_;
218 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
219 0           my $channel_name = $msg->{params}[0];
220 0           my $channel_mode = $msg->{params}[1];
221 0           my $channel = $user->search_channel(name=>$channel_name);
222 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
223 0 0 0       if(defined $channel_mode and $channel_mode eq "b"){
    0 0        
224 0           $user->send($user->serverident,"368",$user->nick,$channel_name,"End of channel ban list");
225             }
226             elsif(defined $channel_mode and $channel_mode ne "b") {
227 0           $channel->set_mode($user,$channel_mode);
228             }
229             else{
230 0           $user->send($user->serverident,"324",$user->nick,$channel_name,'+'.$channel->mode);
231 0           $user->send($user->serverident,"329",$user->nick,$channel_name,$channel->ctime);
232             }
233             }
234             else{
235 0           my $nick = $msg->{params}[0];
236 0           my $mode = $msg->{params}[1];
237 0 0         if(defined $mode){$user->set_mode($mode)}
  0            
238 0           else{$user->send($user->serverident,"221",$user->nick,'+'.$user->mode)}
239             }
240 0           });
241 0     0     $user->on(who=>sub{my($user,$msg) = @_;
242 0 0         if(substr($msg->{params}[0],0,1) eq "#" ){
243 0           my $channel_name = $msg->{params}[0];
244 0           my $channel = $user->search_channel(name=>$channel_name);
245 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
246 0           for($channel->users){
247 0           $user->send($user->serverident,"352",$user->nick,$channel_name,$_->user,$_->host,$_->servername,$_->nick,"H","0 " . $_->realname);
248             }
249 0           $user->send($user->serverident,"315",$user->nick,$channel_name,"End of WHO list");
250             }
251             else{
252 0           my $nick = $msg->{params}[0];
253 0           my $u = $user->search_user(nick=>$nick);
254 0 0         if(defined $u){
255 0           my $channel_name = "*";
256 0 0         if($u->is_join_channel()){
257 0           my $last_channel = (grep {$_->mode !~ /s/} $u->channels)[-1];
  0            
258 0 0         $channel_name = $last_channel->name if defined $last_channel;
259             }
260 0           $user->send($user->serverident,"352",$user->nick,$channel_name,$u->user,$u->host,$u->servername,$u->nick,"H","0 " . $u->realname);
261 0           $user->send($user->serverident,"315",$user->nick,$nick,"End of WHO list");
262             }
263             else{
264 0           $user->send($user->serverident,"401",$user->nick,$nick,"No such nick");
265             }
266            
267             }
268 0           });
269 0     0     $user->on(whois=>sub{my($user,$msg) = @_;});
  0            
270 0     0     $user->on(list=>sub{my($user,$msg) = @_;
271 0           for my $channel ($user->{_server}->channels){
272 0 0         next if $channel->mode =~ /s/;
273 0           $user->send($user->serverident,"322",$user->nick,$channel->name,$channel->count(),$channel->topic);
274             }
275 0           $user->send($user->serverident,"323",$user->nick,"End of LIST");
276 0           });
277 0     0     $user->on(topic=>sub{my($user,$msg) = @_;
278 0           my $channel_name = $msg->{params}[0];
279 0           my $channel = $user->search_channel(name=>$channel_name);
280 0 0         if(not defined $channel){$user->send($user->serverident,"403",$user->nick,$channel_name,"No such channel");return}
  0            
  0            
281 0 0         if(defined $msg->{params}[1]){
282 0           my $topic = $msg->{params}[1];
283 0           $channel->set_topic($user,$topic);
284             }
285             else{
286 0           $user->send($user->serverident,"332",$user->nick,$channel_name,$channel->topic);
287             }
288 0           });
289 0     0     $user->on(away=>sub{my($user,$msg) = @_;
290 0 0         if($msg->{params}[0]){
291 0           my $away_info = $msg->{params}[0];
292 0           $user->away($away_info);
293             }
294             else{
295 0           $user->back();
296             }
297 0           });
298              
299 0           $user;
300             }
301             sub new_channel{
302 0     0 0   my $s = shift;
303 0           my $channel = $s->add_channel(Mojo::IRC::Server::Chinese::Channel->new(@_,_server=>$s));
304 0           $s->emit(new_channel=>$channel);
305 0           return $channel;
306             }
307             sub add_channel{
308 0     0 0   my $s = shift;
309 0           my $channel = shift;
310 0           my $is_cover = shift;
311 0           my $channel_name = $channel->name;
312 0 0         $channel_name = "#" . $channel_name if substr($channel_name,0,1) ne "#";
313 0           $channel_name=~s/\s|,|&//g;
314 0           $channel->name($channel_name);
315 0           my $c = $s->search_channel(name=>$channel->name);
316 0 0         return $c if defined $c;
317 0           $c = $s->search_channel(id=>$channel->id);
318 0 0         if(defined $c){if($is_cover){$s->info("频道 " . $c->name. " 已更新");$c=$channel;};return $c;}
  0 0          
  0            
  0            
  0            
319 0           else{push @{$s->channel},$channel;$s->info("频道 ".$channel->name. " 已创建");return $channel;}
  0            
  0            
  0            
320              
321             }
322             sub add_user{
323 0     0 0   my $s = shift;
324 0           my $user = shift;
325 0           my $is_cover = shift;
326 0 0         if($user->is_virtual){
327 0           my $nick = $user->nick;
328 0 0         $nick =~s/\s|\@|!//g;$nick = '未知昵称' if not $nick;
  0            
329 0           $user->nick($nick);
330 0           my $u = $s->search_user(nick=>$user->nick,virtual=>1,id=>$user->id);
331 0 0         return $u if defined $u;
332 0           while(1){
333 0           my $u = $s->search_user(nick=>$user->nick);
334 0 0         if(defined $u){
335 0 0         if($u->nick =~/\((\d+)\)$/){
336 0           my $num = $1;$num++;$user->nick($nick . "($num)");
  0            
  0            
337             }
338 0           else{$user->nick($nick . "(1)")}
339             }
340 0           else{last};
341             }
342             }
343 0           my $u = $s->search_user(id=>$user->id);
344 0 0         if(defined $u){if($is_cover){$s->info("C[".$u->name. "]已更新");$u=$user;};return $u;}
  0 0          
  0            
  0            
  0            
345             else{
346 0           push @{$s->user},$user;$s->info("C[".$user->name. "]已加入");return $user;
  0            
  0            
  0            
347             }
348             }
349             sub remove_user{
350 0     0 0   my $s = shift;
351 0           my $user = shift;
352 0           for(my $i=0;$i<@{$s->user};$i++){
  0            
353 0 0         if($user->id eq $s->user->[$i]->id){
354 0           $_->remove_user($s->user->[$i]->id) for $s->user->[$i]->channels;
355 0           $user->channel([]);
356 0           splice @{$s->user},$i,1;
  0            
357 0 0         if($user->is_virtual){
358 0           $s->info("c[".$user->name."] 已被移除");
359             }
360             else{
361 0           $s->info("C[".$user->name."] 已离开");
362             }
363 0           last;
364             }
365             }
366             }
367              
368             sub remove_channel{
369 0     0 0   my $s = shift;
370 0           my $channel = shift;
371 0           for(my $i=0;$i<@{$s->channel};$i++){
  0            
372 0 0         if($channel->id eq $s->channel->[$i]->id){
373 0           splice @{$s->channel},$i,1;
  0            
374 0           $s->info("频道 ".$channel->name." 已删除");
375 0           last;
376             }
377             }
378             }
379             sub users {
380 0     0 0   my $s = shift;
381 0           return @{$s->user};
  0            
382             }
383             sub channels{
384 0     0 0   my $s = shift;
385 0           return @{$s->channel};
  0            
386             }
387              
388             sub search_user{
389 0     0 0   my $s = shift;
390 0           my %p = @_;
391 0 0         return if 0 == grep {defined $p{$_}} keys %p;
  0            
392 0 0         if(wantarray){
393 0 0   0     return grep {my $c = $_;(first {$p{$_} ne $c->$_} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->user};
  0            
  0            
  0            
  0            
  0            
394             }
395             else{
396 0 0   0     return first {my $c = $_;(first {$p{$_} ne $c->$_} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->user};
  0            
  0            
  0            
  0            
  0            
397             }
398              
399             }
400             sub search_channel{
401 0     0 0   my $s = shift;
402 0           my %p = @_;
403 0 0         return if 0 == grep {defined $p{$_}} keys %p;
  0            
404 0 0         if(wantarray){
405 0 0   0     return grep {my $c = $_;(first {$_ eq "name"?(lc($p{$_}) ne lc($c->$_)):($p{$_} ne $c->$_)} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->channel};
  0 0          
  0            
  0            
  0            
  0            
406             }
407             else{
408 0 0   0     return first {my $c = $_;(first {$_ eq "name"?(lc($p{$_}) ne lc($c->$_)):($p{$_} ne $c->$_)} grep {defined $p{$_}} keys %p) ? 0 : 1;} @{$s->channel};
  0 0          
  0            
  0            
  0            
  0            
409             }
410              
411             }
412             sub timer{
413 0     0 0   my $s = shift;
414 0           $s->ioloop->timer(@_);
415             }
416             sub interval{
417 0     0 0   my $s = shift;
418 0           $s->ioloop->recurring(@_);
419             }
420             sub ident {
421 0     0 0   return $_[0]->servername;
422             }
423             sub ready {
424 0     0 0   my $s = shift;
425 0           my @listen = ();
426 0 0 0       if(defined $s->listen and ref $s->listen eq "ARRAY"){
427 0           for (@{$s->listen}){
  0            
428 0   0       $_->{address} = (delete $_->{host}) // "0.0.0.0";
429 0 0         $_->{port} = ($_->{tls} ? 6697: 6667) if not defined $_->{port};
    0          
430 0           push @listen,$_;
431             }
432             }
433             else{
434 0           @listen = ({host=>$s->host,port=>$s->port});
435             }
436 0           for my $listen (@listen){
437             $s->ioloop->server($listen=>sub{
438 0     0     my ($loop, $stream) = @_;
439 0           $stream->timeout(0);
440 0           my $id = join ":",(
441             $stream->handle->sockhost,
442             $stream->handle->sockport,
443             $stream->handle->peerhost,
444             $stream->handle->peerport
445             );
446 0           my $user = $s->new_user(
447             id => $id,
448             name => join(":",($stream->handle->peerhost,$stream->handle->peerport)),
449             io => $stream,
450             );
451 0 0         $user->host($s->clienthost) if defined $s->clienthost;
452 0           $s->emit(new_user=>$user);
453 0           });
454             }
455            
456             $s->on(new_user=>sub{
457 0     0     my ($s,$user)=@_;
458 0           $s->debug("C[".$user->name. "]已连接");
459 0           });
460              
461             $s->on(user_registered=>sub{
462 0     0     my($s,$user) = @_;
463 0 0 0       if(defined $s->auth and ref $s->auth eq "CODE"){
464 0 0         if(! $s->auth->($user->nick,$user->user,$user->pass)){
465 0           $user->send($user->serverident,"464",$user->nick,"认证失败");
466 0           $user->io->close_gracefully();
467 0           $user->{_server}->remove_user($user);
468 0           return;
469             }
470             }
471 0           $user->send($user->serverident,"001",$user->nick,"Welcome to " . $s->network . " " . $user->ident);
472 0           $user->send($user->serverident,"002",$user->nick,"Your host is " . $s->servername. ", running version " . $s->version);
473 0           $user->send($user->serverident,"003",$user->nick,"This server was created " . POSIX::strftime('%a %b %d %y at %H:%M:%S %Z',localtime($s->start_time)));
474 0           $user->send($user->serverident,"004",$user->nick,$s->servername." " .$s->version . " DOQRSZaghilopswz Pbis");
475             #$user->send($user->serverident,"001",$user->nick,"欢迎来到 Chinese IRC Network " . $user->ident);
476 0           $user->send($user->serverident,"396",$user->nick,$user->host,"您的主机地址已被隐藏");
477 0           });
478             $s->on(user_msg=>sub{
479 0     0     my ($s,$user,$msg)=@_;
480 0           $s->debug("C[".$user->name."] $msg->{raw_line}");
481 0           });
482              
483             $s->on(close_user=>sub{
484 0     0     my ($s,$user,$msg)=@_;
485 0           });
486              
487             $s->interval(60,sub{
488 0 0   0     for(grep {defined $_->last_active_time and time() - $_->last_active_time > 60 } grep {!$_->is_virtual} $s->users){
  0            
  0            
489 0 0         if($_->ping_count >=3 ){
490 0           $_->close_reason("PING timeout 180 seconds");
491 0           $_->io->close_gracefully();
492             }
493             else{
494 0           $_->send(undef,"PING",$_->servername);
495 0           my $current_ping_count = $_->ping_count;
496 0           $_->ping_count(++$current_ping_count);
497             }
498             }
499 0           });
500             }
501              
502             sub run{
503 0     0 0   my $s = shift;
504 0           $s->ready();
505 0 0         $s->ioloop->start unless $s->ioloop->is_running;
506             }
507             sub die{
508 0     0 0   my $s = shift;
509 0     0     local $SIG{__DIE__} = sub{$s->log->fatal(@_);exit -1};
  0            
  0            
510 0           Carp::confess(@_);
511             }
512             sub info{
513 0     0 0   my $s = shift;
514 0           $s->log->info(@_);
515 0           $s;
516             }
517             sub warn{
518 0     0 0   my $s = shift;
519 0           $s->log->warn(@_);
520 0           $s;
521             }
522             sub error{
523 0     0 1   my $s = shift;
524 0           $s->log->error(@_);
525 0           $s;
526             }
527             sub fatal{
528 0     0 0   my $s = shift;
529 0           $s->log->fatal(@_);
530 0           $s;
531             }
532             sub debug{
533 0     0 0   my $s = shift;
534 0           $s->log->debug(@_);
535 0           $s;
536             }
537              
538              
539             1;