File Coverage

blib/lib/Mojo/IRC/Server/User.pm
Criterion Covered Total %
statement 6 145 4.1
branch 0 56 0.0
condition 0 17 0.0
subroutine 2 20 10.0
pod 0 16 0.0
total 8 254 3.1


line stmt bran cond sub pod time code
1             package Mojo::IRC::Server::User;
2 1     1   5 use Mojo::IRC::Server::Base 'Mojo::IRC::Server::Object';
  1         1  
  1         6  
3 1     1   5 use List::Util qw(first);
  1         2  
  1         2648  
4             has [qw(id name io)];
5             has user => '*';
6             has pass => undef;
7             has nick => '*';
8             has mode => 'i';
9             has buffer => '';
10             has virtual => 0;
11             has host => sub{$_[0]->virtual?"virtualhost":"hidden"};
12             has port => sub{$_[0]->virtual?"virtualport":"hidden"};
13             has ctime => sub{time()};
14             has 'last_speak_time';
15             has 'last_active_time';
16             has ping_count => 0;
17             has close_reason => undef;
18             has channel => sub{[]};
19             has realname => 'unset';
20             has is_quit => 0;
21             has is_away => 0;
22             has is_registered => 0;
23             has away_info => undef;
24              
25             sub is_virtual {
26 0     0 0   $_[0]->virtual;
27             }
28             sub away {
29 0     0 0   my $s = shift;
30 0           my $away_info = shift;
31 0           $s->send($s->serverident,"306",$s->nick,"你已经被标记为离开");
32 0           $s->is_away(1);
33 0           $s->away_info($away_info);
34             }
35             sub back {
36 0     0 0   my $s = shift;
37 0           $s->send($s->serverident,"305",$s->nick,"你不再被标记为离开");
38 0           $s->is_away(0);
39 0           $s->away_info(undef);
40             }
41             sub quit{
42 0     0 0   my $s = shift;
43 0   0       my $quit_reason = shift || "";
44 0           $s->broadcast($s->ident,"QUIT",$quit_reason);
45 0           $s->info("[" . $s->name . "] 已退出($quit_reason)");
46 0 0         $s->io->close_gracefully() if not $s->is_virtual;
47 0           $s->{_server}->remove_user($s);
48             }
49             sub ident{
50 0     0 0   my $s = shift;
51 0           return $s->nick . '!' . $s->user . '@' . $s->host;
52             }
53             sub set_nick{
54 0     0 0   my $s = shift;
55 0           my $nick = shift;
56 0           my $user = $s->search_user(nick=>$nick);
57 0 0 0       if(defined $user and $user->id ne $s->id){
58 0 0         if($user->is_virtual){
59 0           $user->quit("虚拟帐号被移除");
60 0     0     $s->once(close=>sub{$s->{_server}->add_user($user)});
  0            
61 0           $s->broadcast($s->ident,NICK => $nick);
62 0           $s->info("[" . $s->nick . "] 修改昵称为 [$nick]");
63 0           $s->nick($nick);
64 0           $s->name($nick);
65 0 0 0       if(!$s->is_registered and $s->nick ne "*" and $s->user ne "*"){
      0        
66 0           $s->is_registered(1);
67 0           $s->send($s->serverident,"001",$s->nick,"欢迎来到 Mojo IRC Network " . $s->ident);
68 0           $s->send($s->serverident,"396",$s->nick,$s->host,"您的主机地址已被隐藏");
69             }
70             }
71             else{
72 0           $s->send($s->serverident,"433",$s->nick,$nick,'昵称已经被使用');
73 0           $s->info("昵称 [$nick] 已经被使用");
74             }
75             }
76             else{
77 0           $s->broadcast($s->ident,NICK => $nick);
78 0           $s->info("[" . $s->nick . "] 修改昵称为 [$nick]");
79 0           $s->nick($nick);
80 0           $s->name($nick);
81 0 0 0       if(!$s->is_registered and $s->nick ne "*" and $s->user ne "*"){
      0        
82 0           $s->is_registered(1);
83 0           $s->send($s->serverident,"001",$s->nick,"欢迎来到 Mojo IRC Network " . $s->ident);
84 0           $s->send($s->serverident,"396",$s->nick,$s->host,"您的主机地址已被隐藏");
85             }
86             }
87             }
88             sub set_mode{
89 0     0 0   my $s = shift;
90 0           my $mode = shift;
91 0           my %mode = map {$_=>1} split //,$s->mode;
  0            
92 0 0         if(substr($mode,0,1) eq "+"){
    0          
93 0           $mode{$_}=1 for split //,substr($mode,1,);
94             }
95             elsif(substr($mode,0,1) eq "-"){
96 0           delete $mode{$_} for split //,substr($mode,1,);
97             }
98             else{
99 0           %mode = ();
100 0           $mode{$_}=1 for split //,$mode;
101             }
102 0           $s->mode(join "",keys %mode);
103 0           $s->send($s->ident,"MODE",$s->nick,$mode);
104 0           $s->info("[" . $s->nick . "] 模式设置为: " . $s->mode);
105             }
106             sub join_channel{
107 0     0 0   my $s = shift;
108 0           my $channel;
109 0 0         $channel = ref($_[0]) eq "Mojo::IRC::Server::Channel"?$_[0]:$s->search_channel(id=>$_[0]);
110 0 0         return if not defined $channel;
111 0 0         if(not $s->is_join_channel($channel->id)){
112 0           push @{$s->channel},$channel->id;
  0            
113 0           $channel->add_user($s->id);
114 0           $channel->broadcast($s->ident,"JOIN",$channel->name);
115             }
116 0           else{$s->send($s->ident,"JOIN",$channel->name);}
117 0           $s->send($s->serverident,"332",$s->nick,$channel->name,$channel->topic);
118 0           $s->send($s->serverident,"353",$s->nick,'=',$channel->name,join " ",map {$_->nick} $channel->users);
  0            
119 0           $s->send($s->serverident,"366",$s->nick,$channel->name,"End of NAMES list");
120             #$s->send($s->serverident,"329",$s->nick,$channel->name,$channel->ctime);
121 0           $s->info("[" . $s->name . "] 加入频道 " . $channel->name);
122             }
123             sub part_channel{
124 0     0 0   my $s = shift;
125 0 0         my $channel = ref($_[0]) eq "Mojo::IRC::Server::Channel"?$_[0]:$s->search_channel(id=>$_[0]);
126 0           my $part_info = $_[1];
127 0 0         return if not defined $channel;
128 0           $channel->broadcast($s->ident,"PART",$channel->name,$part_info);
129 0           for(my $i=0;$i<@{$s->channel};$i++){
  0            
130 0 0         if($channel->id eq $s->channel->[$i]){
131 0           splice @{$s->channel},$i,1;
  0            
132 0           last;
133             }
134             }
135 0           $channel->remove_user($s->id);
136 0           $s->info("[" . $s->nick . "] 离开频道 " . $channel->name);
137            
138             }
139             sub is_join_channel{
140 0     0 0   my $s = shift;
141 0 0         my $cid = ref($_[0]) eq "Mojo::IRC::Server::Channel"?$_[0]->id:$_[0];
142 0 0         if(defined $cid){
143 0 0   0     return (first {$cid eq $_} @{$s->channel})?1:0;
  0            
  0            
144             }
145             else{
146 0           return 0+@{$s->channel};
  0            
147             }
148             }
149             sub forward{
150 0     0 0   my $s = shift;
151 0           my %unique;
152 0           for my $channel ($s->channels){
153 0           for my $user ($channel->users){
154 0 0         next if $user->id eq $s->id;
155 0 0         next if exists $unique{$user->id};
156 0           $user->send(@_);
157 0           $unique{$user->id} = 1;
158             }
159             }
160             }
161              
162             sub broadcast{
163 0     0 0   my $s = shift;
164 0           $s->send(@_);
165 0           my %unique;
166 0           for my $channel ($s->channels){
167 0           for my $user ($channel->users){
168 0 0         next if $user->id eq $s->id;
169 0 0         next if exists $unique{$user->id};
170 0           $user->send(@_);
171 0           $unique{$user->id} = 1;
172             }
173             }
174             }
175             sub channels{
176 0     0 0   my $s = shift;
177 0           my @channels = ();
178 0           for my $cid (@{$s->channel}){
  0            
179 0           my $channel = $s->search_channel(id=>$cid);
180 0 0         push @channels ,$channel if defined $channel;
181             }
182 0           return @channels;
183             }
184             sub each_channel{
185 0     0 0   my $s = shift;
186 0           my $callback = shift;
187 0 0         return if not $s->is_join_channel();
188 0           for my $cid (@{$s->channel}){
  0            
189 0           my $channel = $s->search_channel(id=>$cid);
190 0 0         $callback->($s,$channel,@_) if defined $channel;
191             }
192             }
193              
194             sub send{
195 0     0 0   my $s = shift;
196 0 0         return if $s->is_virtual ;
197 0           my($prefix,$command,@params)=@_;
198 0           my $msg = "";
199 0 0         $msg .= defined $prefix ? ":$prefix " : "";
200 0           $msg .= $command;
201 0           my $trail;
202 0           $trail = pop @params;
203 0           $msg .= " $_" for @params;
204 0 0         $msg .= defined $trail ? " :$trail" : "";
205 0           $msg .= "\r\n";
206 0           $s->io->write($msg);
207 0           $s->debug("S[".$s->name."] $msg");
208             }
209             sub is_localhost{
210 0     0 0   my $s = shift;
211 0 0         return 0 if $s->is_virtual;
212 0 0         return 1 if $s->io->handle->peerhost eq "127.0.0.1";
213             }
214             1;