File Coverage

blib/lib/Alice/IRC.pm
Criterion Covered Total %
statement 35 105 33.3
branch 2 22 9.0
condition 0 11 0.0
subroutine 12 30 40.0
pod 0 20 0.0
total 49 188 26.0


line stmt bran cond sub pod time code
1             package Alice::IRC;
2              
3 2     2   11 use AnyEvent;
  2         4  
  2         61  
4 2     2   2063 use AnyEvent::IRC::Client;
  2         54291  
  2         125  
5 2     2   28 use AnyEvent::IRC::Util qw/parse_irc_msg/;
  2         4  
  2         146  
6 2     2   12 use List::MoreUtils qw/any/;
  2         4  
  2         89  
7 2     2   11 use Digest::MD5 qw/md5_hex/;
  2         4  
  2         79  
8 2     2   12 use Any::Moose;
  2         4  
  2         28  
9 2     2   1412 use Encode;
  2         5  
  2         379  
10              
11             my $email_re = qr/([^<\s]+@[^\s>]+\.[^\s>]+)/;
12             my $image_re = qr/(https?:\/\/\S+(?:jpe?g|png|gif))/i;
13              
14             {
15 2     2   13 no warnings;
  2         4  
  2         3017  
16              
17             # YUCK!!!
18             *AnyEvent::IRC::Connection::_feed_irc_data = sub {
19 0     0   0 my ($self, $line) = @_;
20 0         0 my $m = parse_irc_msg (decode ("utf8", $line));
21 0         0 $self->event (read => $m);
22 0         0 $self->event ('irc_*' => $m);
23 0         0 $self->event ('irc_' . (lc $m->{command}), $m);
24             };
25              
26             *AnyEvent::IRC::Connection::mk_msg = \&mk_msg;
27             *AnyEvent::IRC::Client::mk_msg = \&mk_msg;
28             }
29              
30             has 'cl' => (is => 'rw');
31              
32             has 'name' => (
33             is => 'ro',
34             required => 1,
35             );
36              
37             has 'reconnect_timer' => (
38             is => 'rw'
39             );
40              
41             has [qw/is_connecting reconnect_count connect_time/] => (
42             is => 'rw',
43             default => 0,
44             );
45              
46 1     1 0 8 sub increase_reconnect_count {$_[0]->reconnect_count($_[0]->reconnect_count + 1)}
47 0     0 0 0 sub reset_reconnect_count {$_[0]->reconnect_count(0)}
48              
49             has [qw/disabled removed/] => (
50             is => 'rw',
51             default => 0,
52             );
53              
54             has whois => (
55             is => 'rw',
56             default => sub {{}},
57             );
58              
59             has avatars => (
60             is => 'rw',
61             default => sub {{}},
62             );
63              
64             sub add_whois {
65 0     0 0 0 my ($self, $nick, $cb) = @_;
66 0         0 $nick = lc $nick;
67 0         0 $self->whois->{$nick} = {info => "", cb => $cb};
68 0         0 $self->send_srv(WHOIS => $nick);
69             }
70              
71             sub new_client {
72 1     1 0 2 my ($self, $events, $config) = @_;
73              
74 1         13 my $client = AnyEvent::IRC::Client->new(send_initial_whois => 1);
75 1 50       7677 $client->enable_ssl if $config->{ssl};
76 1         14 $client->reg_cb(%$events);
77 1         2254 $client->ctcp_auto_reply ('VERSION', ['VERSION', "alice $Alice::VERSION"]);
78              
79 1         16 $self->cl($client);
80             }
81              
82             sub send_srv {
83 0     0 0 0 my $self = shift;
84 0 0       0 $self->cl->send_srv(@_) if $self->cl;
85             }
86              
87             sub send_long_line {
88 0     0 0 0 my ($self, $cmd, @params) = @_;
89 0         0 my $msg = pop @params;
90 0         0 my $ident = $self->cl->nick_ident($self->cl->nick);
91 0         0 my $init_len = length mk_msg($ident, $cmd, @params, " ");
92              
93 0         0 my $max_len = 500; # give 10 bytes extra margin
94 0         0 my $line_len = $max_len - $init_len;
95              
96             # split up the multiple lines in the message:
97 0         0 my @lines = split /\n/, $msg;
98 0         0 @lines = map split_unicode_string ("utf-8", $_, $line_len), @lines;
99              
100 0         0 $self->cl->send_srv($cmd => @params, $_) for @lines;
101             }
102              
103             sub send_raw {
104 0     0 0 0 my $self = shift;
105 0         0 $self->cl->send_raw(encode "utf8", $_[0]);
106             }
107              
108             sub is_connected {
109 1     1 0 3 my $self = shift;
110 1 50       16 $self->cl ? $self->cl->is_connected : 0;
111             }
112              
113             sub is_disconnected {
114 0     0 0 0 my $self = shift;
115 0   0     0 return !($self->is_connected or $self->is_connecting);
116             }
117              
118             sub nick {
119 0     0 0 0 my $self = shift;
120 0         0 my $nick = $self->cl->nick;
121             }
122              
123             sub nick_avatar {
124 0     0 0 0 my $self = shift;
125 0   0     0 return $self->avatars->{$_[0]} || "";
126             }
127              
128             sub channels {
129 0     0 0 0 my $self = shift;
130 0         0 return keys %{$self->cl->channel_list};
  0         0  
131             }
132              
133             sub channel_nicks {
134 0     0 0 0 my ($self, $channel, $mode) = @_;
135 0         0 my $nicks = $self->cl->channel_list($channel);
136 0 0       0 return map {
137 0         0 $mode ? $self->prefix_from_modes($_, $nicks->{$_}).$_ : $_;
138             } keys %$nicks;
139             }
140              
141             sub prefix_from_modes {
142 0     0 0 0 my ($self, $nick, $modes) = @_;
143 0         0 for my $mode (keys %$modes) {
144 0 0       0 if (my $prefix = $self->cl->map_mode_to_prefix($mode)) {
145 0         0 return $prefix;
146             }
147             }
148 0         0 return "";
149             }
150              
151             sub nick_channels {
152 0     0 0 0 my ($self, $nick) = @_;
153 0     0   0 grep {any {$nick eq $_} $self->channel_nicks($_)} $self->channels;
  0         0  
  0         0  
154             }
155              
156             sub realname_avatar {
157 0     0 0 0 my ($self, $realname) = @_;
158              
159 0 0       0 if ($realname =~ $email_re) {
    0          
160 0         0 my $email = $1;
161 0         0 return "http://www.gravatar.com/avatar/"
162             . md5_hex($email) . "?s=32&r=x";
163             }
164             elsif ($realname =~ $image_re) {
165 0         0 return $1;
166             }
167              
168 0         0 return ();
169             }
170              
171             sub update_realname {
172 0     0 0 0 my ($self, $realname) = @_;
173 0         0 $self->send_srv(REALNAME => $realname);
174 0         0 $self->avatars->{$self->nick} = $self->realname_avatar($realname);
175             }
176              
177             sub is_channel {
178 2     2 0 6 my ($self, $channel) = @_;
179 2         34 return $self->cl->is_channel_name($channel);
180             }
181              
182             sub split_unicode_string {
183 0     0 0   my ($enc, $str, $maxlen) = @_;
184              
185 0 0         return $str unless length (encode ($enc, $str)) > $maxlen;
186              
187 0           my $cur_out = '';
188 0           my $word = '';
189 0           my @lines;
190              
191 0           while (length ($str) > 0) {
192 0           $word .= substr $str, 0, 1, '';
193              
194 0 0 0       if ($word =~ /\w\W$/
      0        
195             || length ($str) == 0
196             || length ( encode ($enc, $word)) >= $maxlen) {
197              
198 0 0         if (length (encode ($enc, $cur_out.$word)) > $maxlen) {
199 0           push @lines, $cur_out;
200 0           $cur_out = '';
201             }
202              
203 0           $cur_out .= $word;
204 0           $word = '';
205             }
206             }
207              
208 0 0         push @lines, $cur_out if length ($cur_out);
209 0           return @lines;
210             }
211              
212             sub mk_msg {
213 0     0 0   encode "utf8", AnyEvent::IRC::Util::mk_msg(@_);
214             }
215              
216             __PACKAGE__->meta->make_immutable;
217             1;