File Coverage

blib/lib/WWW/Omegle.pm
Criterion Covered Total %
statement 27 109 24.7
branch 0 42 0.0
condition 0 9 0.0
subroutine 9 21 42.8
pod 7 12 58.3
total 43 193 22.2


line stmt bran cond sub pod time code
1             package WWW::Omegle;
2              
3 1     1   101184 use 5.006000;
  1         4  
  1         39  
4 1     1   5 use strict;
  1         2  
  1         34  
5 1     1   6 use warnings;
  1         7  
  1         44  
6              
7 1     1   5 use Carp qw/croak/;
  1         2  
  1         51  
8 1     1   1186 use JSON;
  1         21698  
  1         4  
9              
10 1     1   134 use base qw/WWW::Mechanize/;
  1         3  
  1         1173  
11 1     1   1333292 use HTTP::Async;
  1         109456  
  1         59  
12 1     1   16 use HTTP::Request;
  1         2  
  1         29  
13 1     1   3220 use HTTP::Request::Common;
  1         2485  
  1         1287  
14              
15             our $VERSION = '0.02';
16              
17             sub new {
18 0     0 1   my ($class, %opts) = @_;
19              
20 0           my $chat_cb = delete $opts{on_chat};
21 0           my $disconnect_cb = delete $opts{on_disconnect};
22 0           my $connect_cb = delete $opts{on_connect};
23              
24 0           my $self = $class->SUPER::new(%opts);
25              
26 0           $self->{om_callbacks} = {
27             chat => $chat_cb,
28             connect => $connect_cb,
29             disconnect => $disconnect_cb,
30             };
31              
32 0           my $async = new HTTP::Async();
33 0           $self->{async} = $async;
34              
35 0           bless $self, $class;
36              
37 0           return $self;
38             }
39              
40             sub start {
41 0     0 1   my ($self) = @_;
42              
43 0           my $res = $self->post("http://omegle.com/start");
44 0 0         return undef unless $res->is_success;
45              
46 0   0       my $res_body = $res->content || '';
47 0           my ($id) = $res_body =~ /"(\w+)"/;
48 0 0         return undef unless $id;
49              
50 0           $self->{om_id} = $id;
51              
52 0           $self->handle_event($res);
53 0           $self->request_next_event;
54              
55 0           return $id;
56             }
57              
58             sub callback {
59 0     0 0   my ($self, $action, @args) = @_;
60            
61 0 0         my $callback = $self->{om_callbacks}->{$action}
62             or return;
63              
64 0   0       my $extra = $self->{om_callback_userdata}->{$action} || [];
65 0           $callback->($self, @args, @$extra);
66             }
67              
68             sub set_callback {
69 0     0 1   my ($self, $action, $cb, @extra) = @_;
70              
71 0           $self->{om_callback_userdata}->{$action} = \@extra;
72 0           $self->{om_callbacks}->{$action} = $cb;
73             }
74              
75             # process a HTTP::Response from /events. parse JSON and dispatch to callbacks
76             sub handle_event {
77 0     0 0   my ($self, $res) = @_;
78              
79 0 0         unless ($res->is_success) {
80 0           $self->callback('error', $res->status_line);
81 0           warn "HTTP error: " . $res->status_line;
82 0           return;
83             }
84              
85 0 0         return undef unless $res->content;
86              
87 0 0         unless ($res->content =~ /^\[/) {
88 0 0         if ($res->content eq 'win') {
    0          
89             # yay, message delivered OK
90 0           return;
91             } elsif ($res->content =~ /^"/) { # " ){ # emacs :(
92             # got id
93 0           return;
94             } else {
95             # not JSON array of events
96 0           $self->callback(error => "Got invalid JSON: " . $res->content);
97 0           return;
98             }
99             }
100            
101 0           my $json = new JSON;
102 0 0         my $events = $json->decode($res->content)
103             or return undef;
104              
105 0 0 0       return undef unless ref $events && ref $events eq 'ARRAY';
106              
107 0           foreach my $evt (@$events) {
108 0 0         my $evt_name = $evt->[0]
109             or next;
110 0 0         if ($evt_name eq 'connected') {
    0          
    0          
    0          
111 0           $self->callback('connect');
112             } elsif ($evt_name eq 'gotMessage') {
113 0           $self->callback('chat', $evt->[1]);
114             } elsif ($evt_name eq 'strangerDisconnected') {
115 0           $self->callback('disconnect');
116 0           delete $self->{om_id};
117             } elsif ($evt_name eq 'waiting') {
118            
119             } else {
120 0           warn "Got unknown omegle event: $evt_name";
121             }
122             }
123              
124 0           $self->callback('event_handled', 1);
125              
126 0           return 1;
127             }
128              
129             # event loop, currently runs forever.
130             sub run_event_loop {
131 0     0 1   my ($self) = @_;
132              
133 0           my $done;
134 0           while (! $done) {
135 0           my $res = $self->wait_next_event;
136 0 0         next unless $res;
137              
138 0           $self->handle_event($res);
139 0           $self->request_next_event;
140             }
141             }
142              
143             # block and wait for next omegle event
144             sub wait_next_event {
145 0     0 0   my ($self, $wait_for) = @_;
146 0   0       $wait_for ||= 0.5;
147 0           return $self->{async}->wait_for_next_response($wait_for);
148             }
149              
150             # let async http worker do some work, and flush event queue
151             sub poke {
152 0     0 1   my $self = shift;
153              
154 0           $self->{async}->poke;
155 0           $self->flush_events;
156             }
157              
158             # process all http responses in the queue
159             sub flush_events {
160 0     0 0   my $self = shift;
161              
162 0           my $got_events = 0;
163              
164 0           while ($self->{async}->not_empty) {
165 0 0         if (my $response = $self->{async}->next_response) {
166 0           $self->handle_event($response);
167 0           $got_events = 1;
168             } else {
169 0           last;
170             }
171             }
172              
173             # got some events, should ask for more
174 0 0         $self->request_next_event if $got_events;
175             }
176              
177             # post an asynchronous http request asking omegle for the next event.
178             # this may take a long time to complete
179             sub request_next_event {
180 0     0 0   my ($self) = @_;
181              
182 0 0         return undef unless $self->{om_id};
183 0           $self->{async}->add(POST "http://omegle.com/events", [ id => $self->{om_id} ]);
184             }
185              
186             sub say {
187 0     0 1   my ($self, $what) = @_;
188              
189 0 0         return undef unless $self->{om_id};
190 0           $self->{async}->add(POST "http://omegle.com/send", [ id => $self->{om_id}, msg => $what ]);
191             }
192              
193             sub disconnect {
194 0     0 1   my ($self) = @_;
195              
196 0 0         return undef unless $self->{om_id};
197 0           $self->{async}->add(POST "http://omegle.com/disconnect", [ id => $self->{om_id} ]);
198             }
199              
200             1;
201              
202              
203             __END__