From 6d3cfa675ca5243a01cddcc9fa3f16bef184f78d Mon Sep 17 00:00:00 2001 From: JT Smith Date: Thu, 15 Nov 2012 15:24:06 -0600 Subject: [PATCH] started working on asyncing Facebook::Graph --- Changes | 4 +- dist.ini | 6 +- lib/Facebook/Graph.pm | 49 +++++-------- lib/Facebook/Graph/AccessToken.pm | 11 ++- lib/Facebook/Graph/BatchRequests.pm | 10 +-- lib/Facebook/Graph/Cookbook.pod | 2 +- lib/Facebook/Graph/Publish.pm | 16 ++--- lib/Facebook/Graph/Query.pm | 17 +---- lib/Facebook/Graph/Request.pm | 108 ++++++++++++++++++++++++++++ lib/Facebook/Graph/Response.pm | 6 +- lib/Facebook/Graph/Session.pm | 10 +-- 11 files changed, 151 insertions(+), 88 deletions(-) create mode 100644 lib/Facebook/Graph/Request.pm diff --git a/Changes b/Changes index f329d50..d73c3bb 100644 --- a/Changes +++ b/Changes @@ -2,7 +2,9 @@ - Added batch requests. Thanks to fayland. - Fix: Facebook no longer allows public queries. Thanks to spazm. - Added authentication test. - - Fixed some other tests. + - Fixed some other failing tests due to Facebook changes. + - Started making Facebook::Graph async. Still working deciding on callback API, so left out true async in this release. + - WARNING: "ua" method no longer available from Facebook::Graph. 1.0401 2012-05-07 - Added impersonation recipe. diff --git a/dist.ini b/dist.ini index a27ab5b..f77e8e7 100644 --- a/dist.ini +++ b/dist.ini @@ -3,7 +3,7 @@ author = JT Smith license = Perl_5 copyright_holder = Plain Black Corporation copyright_year = 2012 -version = 1.0401 +version = 1.0500 [@Classic] @@ -18,9 +18,7 @@ Any::Moose = 0.13 JSON = 2.16 Test::More = 0 URI = 1.54 -LWP = 6.02 -LWP::Protocol::https = 6.02 -Mozilla::CA = 20110409 +AnyEvent::HTTP::LWP::UserAgent = 0.8 DateTime = 0.61 DateTime::Format::Strptime = 1.4000 MIME::Base64::URLSafe = 0.01 diff --git a/lib/Facebook/Graph.pm b/lib/Facebook/Graph.pm index e2020ce..753146e 100644 --- a/lib/Facebook/Graph.pm +++ b/lib/Facebook/Graph.pm @@ -20,7 +20,6 @@ use Facebook::Graph::Publish::RSVPAttending; use Facebook::Graph::Publish::RSVPDeclined; use Facebook::Graph::BatchRequests; use Ouch; -use LWP::UserAgent; has app_id => ( is => 'ro', @@ -40,14 +39,6 @@ has access_token => ( predicate => 'has_access_token', ); -has ua => ( - is => 'rw', - lazy => 1, - default => sub { - LWP::UserAgent->new; - }, -); - sub parse_signed_request { my ($self, $signed_request) = @_; require Digest::SHA; @@ -74,7 +65,6 @@ sub request_access_token { postback => $self->postback, secret => $self->secret, app_id => $self->app_id, - ua => $self->ua, )->request; $self->access_token($token->token); return $token; @@ -86,7 +76,6 @@ sub convert_sessions { secret => $self->secret, app_id => $self->app_id, sessions => $sessions, - ua => $self->ua, ) ->request ->as_hashref; @@ -112,7 +101,7 @@ sub fql { sub query { my ($self) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($self->has_access_token) { $params{access_token} = $self->access_token; } @@ -124,7 +113,7 @@ sub query { sub batch_requests { my ($self) = @_; - my %params = ( ua => $self->ua, access_token => $self->access_token ); + my %params = ( access_token => $self->access_token ); return Facebook::Graph::BatchRequests->new(%params); } @@ -135,7 +124,7 @@ sub picture { sub add_post { my ($self, $object_name) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($object_name) { $params{object_name} = $object_name; } @@ -150,7 +139,7 @@ sub add_post { sub add_photo { my ($self, $object_name) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($object_name) { $params{object_name} = $object_name; } @@ -165,7 +154,7 @@ sub add_photo { sub add_checkin { my ($self, $object_name) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($object_name) { $params{object_name} = $object_name; } @@ -182,7 +171,6 @@ sub add_like { my ($self, $object_name) = @_; my %params = ( object_name => $object_name, - ua => $self->ua, ); if ($self->has_access_token) { $params{access_token} = $self->access_token; @@ -209,7 +197,7 @@ sub add_comment { sub add_note { my ($self) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($self->has_access_token) { $params{access_token} = $self->access_token; } @@ -221,7 +209,7 @@ sub add_note { sub add_link { my ($self) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($self->has_access_token) { $params{access_token} = $self->access_token; } @@ -233,7 +221,7 @@ sub add_link { sub add_event { my ($self, $object_name) = @_; - my %params = ( ua => $self->ua ); + my %params = ( ); if ($object_name) { $params{object_name} = $object_name; } @@ -250,7 +238,6 @@ sub rsvp_maybe { my ($self, $object_name) = @_; my %params = ( object_name => $object_name, - ua => $self->ua, ); if ($self->has_access_token) { $params{access_token} = $self->access_token; @@ -265,7 +252,6 @@ sub rsvp_attending { my ($self, $object_name) = @_; my %params = ( object_name => $object_name, - ua => $self->ua, ); if ($self->has_access_token) { $params{access_token} = $self->access_token; @@ -280,7 +266,6 @@ sub rsvp_declined { my ($self, $object_name) = @_; my %params = ( object_name => $object_name, - ua => $self->ua, ); if ($self->has_access_token) { $params{access_token} = $self->access_token; @@ -317,11 +302,19 @@ Or better yet: my $sarahs_picture_uri = $fb->picture('sarahbownds')->get_large->uri_as_string; +You can also do asynchronous calls like this: + + my $sarah = $fb->query->find('sarahbownds'); # making request in background here + # ... do stuff here ... + my $hashref = $sarah->as_hashref; # handling the response here + + Or fetching a response from a URI you already have: - my $response = $fb->query + my $hashref = $fb->query ->request('https://graph.facebook.com/btaylor') ->as_hashref; + =head2 Building A Privileged App @@ -395,10 +388,6 @@ The URI that Facebook should post your authorization code back to. Required if y B It must be a sub URI of the URI that you put in the Application Settings > Connect > Connect URL field of your application's profile on Facebook. -=item ua - -This allows you to pass in your own L object. By default Facebook::Graph will just create one on the fly. - =back @@ -578,9 +567,7 @@ I still need to add publishing albums/photos, deleting of content, impersonation L L -L -L -L +L L L L diff --git a/lib/Facebook/Graph/AccessToken.pm b/lib/Facebook/Graph/AccessToken.pm index 44915b9..66efa0e 100644 --- a/lib/Facebook/Graph/AccessToken.pm +++ b/lib/Facebook/Graph/AccessToken.pm @@ -2,8 +2,8 @@ package Facebook::Graph::AccessToken; use Any::Moose; use Facebook::Graph::AccessToken::Response; +use Facebook::Graph::Request; with 'Facebook::Graph::Role::Uri'; -use LWP::UserAgent; has app_id => ( is => 'ro', @@ -25,10 +25,6 @@ has code => ( required=> 1, ); -has ua => ( - is => 'rw', -); - sub uri_as_string { my ($self) = @_; my $uri = $self->uri; @@ -44,8 +40,9 @@ sub uri_as_string { sub request { my ($self) = @_; - my $response = ($self->ua || LWP::UserAgent->new)->get($self->uri_as_string); - return Facebook::Graph::AccessToken::Response->new(response => $response); + return Facebook::Graph::AccessToken::Response->new( + response => Facebook::Graph::Request->new->get($self->uri_as_string)->recv->response + ); } no Any::Moose; diff --git a/lib/Facebook/Graph/BatchRequests.pm b/lib/Facebook/Graph/BatchRequests.pm index fb5c381..8afc3a9 100644 --- a/lib/Facebook/Graph/BatchRequests.pm +++ b/lib/Facebook/Graph/BatchRequests.pm @@ -1,9 +1,8 @@ package Facebook::Graph::BatchRequests; use Any::Moose; -use LWP::UserAgent; -use JSON; use Ouch; +use Facebook::Graph::Request; has access_token => ( is => 'ro', @@ -16,10 +15,6 @@ has requests => ( default => sub { [] }, ); -has ua => ( - is => 'rw', -); - sub add_request { my ($self, $ele) = @_; @@ -45,7 +40,8 @@ sub request { $self->requests([]); # reset my $uri = "https://graph.facebook.com"; - my $resp = ($self->ua || LWP::UserAgent->new)->post($uri, $post); + my $resp = Facebook::Graph::Request->new->post($uri, $post)->recv->response; + unless ($resp->is_success) { my $message = $resp->message; my $error = eval { $json->decode($resp->content) }; diff --git a/lib/Facebook/Graph/Cookbook.pod b/lib/Facebook/Graph/Cookbook.pod index 6543366..81c695e 100644 --- a/lib/Facebook/Graph/Cookbook.pod +++ b/lib/Facebook/Graph/Cookbook.pod @@ -20,7 +20,7 @@ A fully functional Facebook::Graph app that publishes data to Facebook and reads =item L - Impersonation -Shows you how to post as all the different pages under your control. +Shows you how to post as all the different pages under your control. =back diff --git a/lib/Facebook/Graph/Publish.pm b/lib/Facebook/Graph/Publish.pm index c57ba08..e712cba 100644 --- a/lib/Facebook/Graph/Publish.pm +++ b/lib/Facebook/Graph/Publish.pm @@ -1,9 +1,9 @@ package Facebook::Graph::Publish; use Any::Moose; -use Facebook::Graph::Response; +use Facebook::Graph::Request; with 'Facebook::Graph::Role::Uri'; -use LWP::UserAgent; +use AnyEvent::HTTP::LWP::UserAgent; use URI::Escape; has secret => ( @@ -22,10 +22,6 @@ has object_name => ( default => 'me', ); -has ua => ( - is => 'rw', -); - sub to { my ($self, $object_name) = @_; $self->object_name($object_name); @@ -45,14 +41,10 @@ sub publish { my ($self) = @_; my $uri = $self->uri; $uri->path($self->object_name.$self->object_path); - my $response = ($self->ua || LWP::UserAgent->new)->post($uri, $self->get_post_params); - my %params = (response => $response); - if ($self->has_secret) { - $params{secret} = $self->secret; - } - return Facebook::Graph::Response->new(%params); + return Facebook::Graph::Request->new->post($uri, $self->get_post_params)->recv; } + no Any::Moose; __PACKAGE__->meta->make_immutable; diff --git a/lib/Facebook/Graph/Query.pm b/lib/Facebook/Graph/Query.pm index 3973b44..e74299e 100644 --- a/lib/Facebook/Graph/Query.pm +++ b/lib/Facebook/Graph/Query.pm @@ -1,9 +1,8 @@ package Facebook::Graph::Query; use Any::Moose; -use Facebook::Graph::Response; +use Facebook::Graph::Request; with 'Facebook::Graph::Role::Uri'; -use LWP::UserAgent; use URI::Escape; has secret => ( @@ -77,10 +76,6 @@ has since => ( predicate => 'has_since', ); -has ua => ( - is => 'rw', -); - sub limit_results { my ($self, $limit) = @_; $self->limit($limit); @@ -197,14 +192,8 @@ sub uri_as_string { } sub request { - my ($self, $uri) = @_; - $uri ||= $self->uri_as_string; - my $response = ($self->ua || LWP::UserAgent->new)->get($uri); - my %params = (response => $response); - if ($self->has_secret) { - $params{secret} = $self->secret; - } - return Facebook::Graph::Response->new(%params); + my ($self) = @_; + return Facebook::Graph::Request->new->get($self->uri_as_string)->recv; } no Any::Moose; diff --git a/lib/Facebook/Graph/Request.pm b/lib/Facebook/Graph/Request.pm new file mode 100644 index 0000000..3868099 --- /dev/null +++ b/lib/Facebook/Graph/Request.pm @@ -0,0 +1,108 @@ +package Facebook::Graph::Request; + +use Any::Moose; +use JSON; +use Ouch; +use AnyEvent::HTTP::LWP::UserAgent; +use AnyEvent; +use Facebook::Graph::Response; + +has ua => ( + is => 'rw', + isa => 'AnyEvent::HTTP::LWP::UserAgent', + lazy => 1, + default => sub { + my $ua = AnyEvent::HTTP::LWP::UserAgent->new; + $ua->timeout(30); + return $ua; + }, +); + +sub post { + my ($self, $uri, $params) = @_; + my $cv = AnyEvent->condvar; + $self->ua->post_async($uri, $params)->cb(sub { + $cv->send(Facebook::Graph::Response->new(response => shift->recv)); + }); + return $cv; +} + +sub get { + my ($self, $uri) = @_; + my $ua = $self->ua; + my $cv = AnyEvent->condvar; + $ua->get_async($uri)->cb(sub { + $cv->send(Facebook::Graph::Response->new(response => shift->recv)); + }); + return $cv; +} + +no Any::Moose; +__PACKAGE__->meta->make_immutable; + +=head1 NAME + +Facebook::Graph::Request - Handling posts to Facebook Graph. + +=head1 DESCRIPTION + +This is the standard interface to the Facebook Graph API that all other modules use. + +=head1 METHODS + +=head2 new(params) + +=over + +=item params + +A hash or hashref of parameters to pass to the constructor. + +=over + +=item ua + +An L object. It will be created for you if you don't pass one in. + +=back + +=back + +=head2 post ( uri, params ) + +A POST request will be made. + +=over + +=item uri + +A URI string to Facebook. + +=item headers + +A hash of headers to pass to L when making the request. + +=back + + +=head2 get ( uri, params ) + +A GET request will be made. + +=over + +=item uri + +A URI to fetch. + +=back + + + +=head1 LEGAL + +Facebook::Graph is Copyright 2010 - 2012 Plain Black Corporation (L) and is licensed under the same terms as Perl itself. + +=cut + + diff --git a/lib/Facebook/Graph/Response.pm b/lib/Facebook/Graph/Response.pm index 3c8989f..9e9cf43 100644 --- a/lib/Facebook/Graph/Response.pm +++ b/lib/Facebook/Graph/Response.pm @@ -5,7 +5,8 @@ use JSON; use Ouch; has response => ( - is => 'ro', + is => 'rw', + isa => 'HTTP::Response', required=> 1, ); @@ -56,8 +57,7 @@ Facebook::Graph::Response - Handling of a Facebook::Graph response documents. =head1 DESCRIPTION -You'll be given one of these as a result of calling the C method on a C or others. - +You'll be given one of these as a result of calling the C method on a L or others, or C on any of the L modules. =head1 METHODS diff --git a/lib/Facebook/Graph/Session.pm b/lib/Facebook/Graph/Session.pm index 8bc5357..2e4a3e9 100644 --- a/lib/Facebook/Graph/Session.pm +++ b/lib/Facebook/Graph/Session.pm @@ -1,9 +1,8 @@ package Facebook::Graph::Session; use Any::Moose; -use Facebook::Graph::Response; +use Facebook::Graph::Request; with 'Facebook::Graph::Role::Uri'; -use LWP::UserAgent; has app_id => ( is => 'ro', @@ -20,10 +19,6 @@ has sessions => ( required=> 1, ); -has ua => ( - is => 'rw', -); - sub uri_as_string { my ($self) = @_; my $uri = $self->uri; @@ -39,8 +34,7 @@ sub uri_as_string { sub request { my ($self) = @_; - my $response = ($self->ua || LWP::UserAgent->new)->get($self->uri_as_string); - return Facebook::Graph::Response->new(response => $response); + return Facebook::Graph::Request->new->get($self->uri_as_string)->recv; } no Any::Moose;