File Coverage

blib/lib/WebService/Lingr.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package WebService::Lingr;
2              
3 1     1   4 use strict;
  1         2  
  1         39  
4             our $VERSION = '0.02';
5              
6 1     1   5 use Carp;
  1         1  
  1         82  
7 1     1   466 use Data::Visitor::Callback;
  0            
  0            
8             use HTTP::Request::Common;
9             use LWP::UserAgent;
10             use JSON::Syck;
11             use URI;
12              
13             our $APIBase = "http://www.lingr.com/api";
14              
15             # scraped from Lingr wiki page
16             our $Methods = {
17             'session.create' => 'POST',
18             'session.destroy' => 'POST',
19             'auth.login' => 'POST',
20             'auth.logout' => 'POST',
21             'explore.getHotRooms' => 'GET',
22             'explore.getNewRooms' => 'GET',
23             'explore.getHotTags' => 'GET',
24             'explore.getAllTags' => 'GET',
25             'explore.search' => 'GET',
26             'explore.searchTags' => 'GET',
27             'user.getInfo' => 'GET',
28             'user.startObserving' => 'POST',
29             'user.observe' => 'GET',
30             'user.stopObserving' => 'POST',
31             'room.getInfo' => 'GET',
32             'room.enter' => 'POST',
33             'room.getMessages' => 'GET',
34             'room.observe' => 'GET',
35             'room.setNickname' => 'POST',
36             'room.say' => 'POST',
37             'room.exit' => 'POST',
38             };
39              
40             sub new {
41             my($class, %args) = @_;
42              
43             my %self;
44             $self{api_key} = $args{api_key} or croak "api_key is required.";
45             $self{ua} = $args{ua} || LWP::UserAgent->new(agent => __PACKAGE__ . "/$VERSION");
46              
47             my $self = bless \%self, $class;
48              
49             unless($args{no_create_session}) {
50             my $res = $self->create_session;
51             $self->{session} = $res->{session};
52             }
53              
54             $self;
55             }
56              
57             sub create_session {
58             my $self = shift;
59             $self->_call('session.create', { api_key => $self->{api_key} });
60             }
61              
62             sub call {
63             my($self, $method, $args) = @_;
64             $args->{session} = $self->{session} if $self->{session};
65             $self->_call($method, $args);
66             }
67              
68             sub _call {
69             my($self, $method, $args) = @_;
70              
71             my @method = map { s/([A-Z])/"_".lc($1)/eg; $_ } split /\./, $method;
72             my $uri = URI->new($APIBase . "/" . join("/", @method));
73              
74             # downgrade all parameters to utf-8, if they're Unicode
75             my $v = Data::Visitor::Callback->new(
76             plain_value => sub {
77             if (utf8::is_utf8($_)) {
78             utf8::encode($_);
79             }
80             },
81             ignore_return_values => 1,
82             );
83              
84             $v->visit($args);
85              
86             my $req_method = $Methods->{$method} || do {
87             Carp::carp "Don't know method '$method'. Defaults to GET";
88             "GET";
89             };
90              
91             $args->{format} = 'json';
92              
93             my $req;
94             if ($req_method eq 'GET') {
95             $uri->query_form(%$args);
96             $req = HTTP::Request->new(GET => $uri);
97             } else {
98             $req = HTTP::Request::Common::POST( $uri, [ %$args ] );
99             }
100              
101             my $res = $self->{ua}->request($req);
102             $self->_parse_response($res);
103             }
104              
105             sub _parse_response {
106             my($self, $res) = @_;
107              
108             $res->is_success or croak "Request failed: " . $res->status_line;
109              
110             local $JSON::Syck::ImplicitUnicode = 1;
111             my $data = JSON::Syck::Load($res->content);
112             $data->{status} eq 'ok' or croak "Response error: $data->{error}->{message} ($data->{error}->{code})";
113              
114             return $self->{res} = $data;
115             }
116              
117             sub response { $_[0]->{res} }
118              
119             sub DESTROY {
120             my $self = shift;
121             $self->call('session.destroy');
122             }
123              
124             1;
125             __END__
126              
127             =for stopwords JSON API Lingr
128              
129             =head1 NAME
130              
131             WebService::Lingr - Low-level Lingr Chat API
132              
133             =head1 SYNOPSIS
134              
135             use WebService::Lingr;
136              
137             # create a session using your API key
138             my $lingr = WebService::Lingr->new(api_key => "YOUR_API_KEY");
139              
140             # enter the room 'MyFavoriteRoom' with nick 'api-dude'
141             my $res = $lingr->call('room.enter', { id => 'MyFavoriteRoom', nickname => 'api-dude' });
142             my $ticket = $res->{ticket};
143             my $counter = $res->{counter};
144              
145             # say "Hello world!"
146             my $res = $lingr->call('room.say', { message => 'hello world', ticket => $ticket });
147              
148             # room.observe blocks
149             while (1) {
150             my $res = $lingr->call('room.observe', { ticket => $ticket, counter => $counter });
151             for my $message (@{$res->{messages}}) {
152             print "$message->{nick} says: $message->{content}\n";
153             }
154             }
155              
156             # room.getMessages doesn't, but you can call this method at most once per minute
157             while (1) {
158             my $res = $lingr->call('room.getMessages', { ticket => $ticket, counter => $counter });
159             # do something ...
160             sleep 60;
161             }
162              
163             =head1 DESCRIPTION
164              
165             WebService::Lingr is a low-level Lingr API implementation in Perl. By
166             "low-level" it means that this module just gives you a straight
167             mapping of Perl object methods to Lingr REST API, session management
168             and data mapping via JSON.
169              
170             For higher level event driven programming, you might want to use
171             POE::Component::Client::Lingr (unfinished).
172              
173             =head1 AUTHOR
174              
175             Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
176              
177             =head1 LICENSE
178              
179             This library is free software; you can redistribute it and/or modify
180             it under the same terms as Perl itself.
181              
182             =head1 SEE ALSO
183              
184             L<http://wiki.lingr.com/dev/show/HomePage>
185              
186             =cut