File Coverage

blib/lib/POE/Component/YahooMessenger.pm
Criterion Covered Total %
statement 15 109 13.7
branch 0 12 0.0
condition 0 13 0.0
subroutine 5 29 17.2
pod 0 17 0.0
total 20 180 11.1


line stmt bran cond sub pod time code
1             package POE::Component::YahooMessenger;
2              
3 1     1   42590 use strict;
  1         2  
  1         38  
4 1     1   5 use vars qw($VERSION);
  1         1  
  1         58  
5             $VERSION = 0.05;
6              
7 1         6 use POE qw(Wheel::SocketFactory Wheel::ReadWrite Driver::SysRW
8 1     1   1587 Filter::YahooMessengerPacket Component::YahooMessenger::Constants);
  1         80630  
9 1     1   286 use Socket;
  1         1  
  1         815  
10 1     1   954 use Net::YahooMessenger::CRAM;
  1         1724  
  1         2382  
11              
12             sub spawn {
13 0     0 0   my($class, %args) = @_;
14 0   0       $args{Alias} ||= 'ym';
15 0           POE::Session->create(
16             inline_states => {
17             _start => \&_start,
18             _stop => \&_stop,
19             _sock_up => \&_sock_up,
20             _sock_failed => \&_sock_failed,
21             _sock_down => \&_sock_down,
22              
23             # API
24             register => \®ister,
25             unregister => \&unregister,
26             connect => \&connect,
27             send_message => \&send_message,
28             change_my_status => \&change_my_status,
29             buddies => \&buddies,
30             add_buddy => \&add_buddy,
31             delete_buddy => \&delete_buddy,
32              
33             # internals
34             login => \&login,
35             notify => \¬ify,
36             _unregister => \&_unregister,
37             handle_event => \&handle_event,
38              
39             # own callbacks
40             goes_online => \&goes_online,
41             goes_offline => \&goes_offline,
42             change_status => \&_handle_common,
43             change_normal_status => \&_handle_common,
44             receive_message => \&receive_message,
45             new_buddy_alert => \&_handle_common,
46             toggle_typing => \&_handle_common,
47             server_is_alive => \&_handle_common,
48             cram_auth_fail => \&_handle_common,
49             receive_buddy_list => \&receive_buddy_list,
50             challenge_start => \&challenge_start,
51             receive_file => \&_handle_common,
52             },
53             args => [ \%args ],
54             );
55             }
56              
57             sub _start {
58 0     0     my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
59 0           $kernel->alias_set($args->{Alias});
60             }
61              
62 0     0     sub _stop { }
63              
64             sub register {
65 0     0 0   my($kernel, $heap, $sender) = @_[KERNEL, HEAP, SENDER];
66 0           $kernel->refcount_increment($sender->ID, __PACKAGE__);
67 0           $heap->{listeners}->{$sender->ID} = 1;
68             }
69              
70             sub unregister {
71 0     0 0   my($kernel, $heap, $sender) = @_[KERNEL, HEAP, SENDER];
72 0           $kernel->yield(_unregister => $sender->ID);
73             }
74              
75             sub _unregister {
76 0     0     my($kernel, $heap, $session) = @_[KERNEL, HEAP, ARG0];
77 0           $kernel->refcount_decrement($session, __PACKAGE__);
78 0           delete $heap->{listeners}->{$session};
79             }
80              
81             sub notify {
82 0     0 0   my($kernel, $heap, $name, $event) = @_[KERNEL, HEAP, ARG0, ARG1];
83 0   0       $event ||= POE::Component::YahooMessenger::Event::Null->new;
84 0           $kernel->post($_ => "ym_$name" => $event) for keys %{$heap->{listeners}};
  0            
85             }
86              
87             sub connect {
88 0     0 0   my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
89              
90             # set up parameters
91             $heap->{$_} = $args->{$_}
92 0           for qw(id password);
93             $heap->{$_} = $args->{$_} || $Default->{$_}
94 0   0       for qw(hostname port);
95              
96 0 0         return if $heap->{sock};
97 0           $heap->{sock} = POE::Wheel::SocketFactory->new(
98             SocketDomain => AF_INET,
99             SocketType => SOCK_STREAM,
100             SocketProtocol => 'tcp',
101             RemoteAddress => $heap->{hostname},
102             RemotePort => $heap->{port},
103             SuccessEvent => '_sock_up',
104             FailureEvent => '_sock_failed',
105             );
106             }
107              
108             sub _sock_up {
109 0     0     my($kernel, $heap, $socket) = @_[KERNEL, HEAP, ARG0];
110              
111             # new ReadWrite wheel for the socket
112 0           $heap->{sock} = POE::Wheel::ReadWrite->new(
113             Handle => $socket,
114             Driver => POE::Driver::SysRW->new,
115             Filter => POE::Filter::YahooMessengerPacket->new,
116             ErrorEvent => '_sock_down',
117             );
118 0           $heap->{sock}->event(InputEvent => 'handle_event');
119 0           $heap->{connected} = 1;
120 0           $kernel->yield(notify => connected => ());
121 0           $kernel->yield(login => ());
122             }
123              
124             sub _sock_failed {
125 0     0     my($kernel, $heap) = @_[KERNEL, HEAP];
126 0           $kernel->yield(notify => socket_error => ());
127 0           for my $session (keys %{$heap->{listeners}}) {
  0            
128 0           $kernel->yield(_unregister => $session);
129             }
130              
131             }
132              
133             sub _sock_down {
134 0     0     my($kernel, $heap) = @_[KERNEL, HEAP];
135 0           delete $heap->{sock};
136 0           $heap->{connected} = 0;
137 0           $kernel->yield(notify => disconnected => ());
138 0           for my $session (keys %{$heap->{listeners}}) {
  0            
139 0           $kernel->yield(_unregister => $session);
140             }
141             }
142              
143             sub handle_event {
144 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
145             # check if event is implemented
146 0 0         if ($event->name) {
147 0           $kernel->yield($event->name, $event);
148             }
149             }
150              
151             sub login {
152 0     0 0   my($kernel, $heap) = @_[KERNEL, HEAP];
153 0           $heap->{sock}->put(
154             POE::Component::YahooMessenger::Event->new(
155             'challenge_start', 0, {
156             my_id => $heap->{id},
157             },
158             ),
159             );
160             }
161              
162             sub _handle_common {
163 0     0     $_[KERNEL]->yield(notify => $_[ARG0]->name, $_[ARG0]);
164             }
165              
166             sub challenge_start {
167 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
168              
169             # calculate CRAM
170 0           my $cram = Net::YahooMessenger::CRAM->new;
171 0           $cram->set_id($heap->{id});
172 0           $cram->set_password($heap->{password});
173 0           $cram->set_challenge_string($event->challenge_string);
174 0           my($response_password, $response_crypt) = $cram->get_response_strings;
175              
176 0           $heap->{sock}->event(InputEvent => 'handle_event');
177 0           $heap->{sock}->put(
178             POE::Component::YahooMessenger::Event->new(
179             'challenge_response', 0, {
180             my_id => $heap->{id},
181             crypt_salt => $response_password,
182             crypted_response => $response_crypt,
183             login_nickname => 1,
184             id => $heap->{id},
185             },
186             ),
187             );
188 0           $kernel->yield(notify => $event->name, $event);
189             }
190              
191             sub receive_buddy_list {
192 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
193 0           my $buddy_list = $event->buddy_list;
194 0           while ($buddy_list =~ /([^:]+):([^\x0a]+)\x0a/g) {
195 0           my $group = $1;
196 0           my @buddies = split /,/, $2;
197 0           $heap->{buddies}->{$_} = $group for @buddies;
198             }
199 0           $kernel->yield(notify => $event->name, $event);
200             }
201              
202             sub goes_online {
203 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
204 0           my $number = $event->number_of_online_buddies;
205 0 0         $number = 1 unless defined $number;
206              
207             # XXX status message is optional
208 0           my $status_num;
209 0           for my $num (0..$number-1) {
210 0           $heap->{online}->{$event->buddy_id($num)} = 1;
211 0           my $status_code = $event->status_code($num);
212 0           my $status_message;
213 0 0         if ($status_code == 99) {
214 0           $status_message = $event->status_message($status_num);
215 0           $status_num++;
216             }
217 0           my $goes_online = POE::Component::YahooMessenger::Event->new(
218             'goes_online', 0, {
219             buddy_id => $event->buddy_id($num),
220             status_code => $status_code,
221             status_message => $status_message,
222             busy_code => $event->busy_code($num),
223             },
224             );
225 0           $kernel->yield(notify => $goes_online->name, $goes_online);
226             }
227             }
228              
229             sub goes_offline {
230 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
231 0           delete $heap->{online}->{$event->buddy_id};
232 0           $kernel->yield(notify => $event->name, $event);
233             }
234              
235             sub receive_message {
236 0     0 0   my($kernel, $heap, $event) = @_[KERNEL, HEAP, ARG0];
237 0           my $code = $event->status_code;
238 0 0 0       unless (defined $code && $code == 99) {
239 0           $kernel->yield(notify => $event->name, $event);
240             }
241             }
242              
243             sub send_message {
244 0     0 0   my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
245 0 0         my $option = $heap->{buddies}->{$args->{to}}
246             ? $Options->{to_buddies} : $Options->{to_non_buddies};
247 0           $heap->{sock}->put(
248             POE::Component::YahooMessenger::Event->new(
249             'send_message', $option, {
250             from => $heap->{id},
251             to => $args->{to},
252             message => $args->{message},
253             },
254             ),
255             );
256             }
257              
258             sub change_my_status {
259 0     0 0   my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
260 0   0       $heap->{sock}->put(
261             POE::Component::YahooMessenger::Event->new(
262             'change_status', 0, {
263             status_code => 99, # XXX custom status
264             busy_code => $args->{busy} || 0,
265             status_message => $args->{message},
266             },
267             ),
268             );
269             }
270              
271             sub buddies {
272 0     0 0   my($kernel, $heap, $sender, $reply) = @_[KERNEL, HEAP, SENDER, ARG0];
273 0           $kernel->post($sender => $reply => $heap->{buddies});
274             }
275              
276             sub add_buddy {
277 0     0 0   my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
278 0           $heap->{sock}->put(
279             POE::Component::YahooMessenger::Event->new(
280             'add_buddy', 0, {
281             id => $heap->{id},
282             buddy_id => $args->{buddy_id},
283             group => $args->{group},
284             message => $args->{message},
285             },
286             ),
287             );
288             }
289              
290             sub delete_buddy {
291 0     0 0   my($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0];
292 0           $heap->{sock}->put(
293             POE::Component::YahooMessenger::Event->new(
294             'delete_buddy', 0, {
295             id => $heap->{id},
296             buddy_id => $args->{buddy_id},
297             group => $args->{group},
298             },
299             ),
300             );
301             }
302              
303             1;
304             __END__