diff options
author | Zach Copley <zach@status.net> | 2010-11-09 00:56:53 +0000 |
---|---|---|
committer | Zach Copley <zach@status.net> | 2010-11-09 00:56:53 +0000 |
commit | cd236efe127c3f696b8a78c5ff66a08b24230a4e (patch) | |
tree | d2c95cc9771cfd33fd485c68d09faca7bf881163 /plugins/FacebookSSO/lib/facebookclient.php | |
parent | 035081a803b005b8a2410c6936eac4027fda493c (diff) |
- Still send notices to Facebook from existing Facebook app users
- Turns out we don't need the old REST lib to use the old REST API
(removed)
Diffstat (limited to 'plugins/FacebookSSO/lib/facebookclient.php')
-rw-r--r-- | plugins/FacebookSSO/lib/facebookclient.php | 287 |
1 files changed, 178 insertions, 109 deletions
diff --git a/plugins/FacebookSSO/lib/facebookclient.php b/plugins/FacebookSSO/lib/facebookclient.php index a0549a1d0..cf45c9ed9 100644 --- a/plugins/FacebookSSO/lib/facebookclient.php +++ b/plugins/FacebookSSO/lib/facebookclient.php @@ -47,9 +47,9 @@ class Facebookclient protected $flink = null; // Foreign_link StatusNet -> Facebook protected $notice = null; // The user's notice protected $user = null; // Sender of the notice - protected $oldRestClient = null; // Old REST API client + //protected $oldRestClient = null; // Old REST API client - function __constructor($notice) + function __construct($notice) { $this->facebook = self::getFacebook(); $this->notice = $notice; @@ -58,29 +58,8 @@ class Facebookclient $notice->profile_id, FACEBOOK_SERVICE ); - - $this->user = $this->flink->getUser(); - - $this->oldRestClient = self::getOldRestClient(); - } - - /* - * Get and instance of the old REST API client for sending notices from - * users with Facebook links that pre-exist the Graph API - */ - static function getOldRestClient() - { - $apikey = common_config('facebook', 'apikey'); - $secret = common_config('facebook', 'secret'); - // If there's no app key and secret set in the local config, look - // for a global one - if (empty($apikey) || empty($secret)) { - $apikey = common_config('facebook', 'global_apikey'); - $secret = common_config('facebook', 'global_secret'); - } - - return new FacebookRestClient($apikey, $secret, null); + $this->user = $this->flink->getUser(); } /* @@ -125,8 +104,9 @@ class Facebookclient */ static function facebookBroadcastNotice($notice) { + common_debug('Facebook broadcast'); $client = new Facebookclient($notice); - $client->sendNotice(); + return $client->sendNotice(); } /* @@ -191,12 +171,24 @@ class Facebookclient // If there's nothing in the credentials field try to send via // the Old Rest API - if (empty($this->flink->credentials)) { - $this->sendOldRest(); - } else { + if ($this->isFacebookBound()) { + common_debug("notice is facebook bound", __FILE__); + if (empty($this->flink->credentials)) { + $this->sendOldRest(); + } else { - // Otherwise we most likely have an access token - $this->sendGraph(); + // Otherwise we most likely have an access token + $this->sendGraph(); + } + + } else { + common_debug( + sprintf( + "Skipping notice %d - not bound for Facebook", + $this->notice->id, + __FILE__ + ) + ); } } @@ -205,7 +197,55 @@ class Facebookclient */ function sendGraph() { - common_debug("Send notice via Graph API", __FILE__); + try { + + $fbuid = $this->flink->foreign_id; + + common_debug( + sprintf( + "Attempting use Graph API to post notice %d as a stream item for %s (%d), fbuid %s", + $this->notice->id, + $this->user->nickname, + $this->user->id, + $fbuid + ), + __FILE__ + ); + + $params = array( + 'access_token' => $this->flink->credentials, + 'message' => $this->notice->content + ); + + $attachments = $this->notice->attachments(); + + if (!empty($attachments)) { + + // We can only send one attachment with the Graph API + + $first = array_shift($attachments); + + if (substr($first->mimetype, 0, 6) == 'image/' + || in_array( + $first->mimetype, + array('application/x-shockwave-flash', 'audio/mpeg' ))) { + + $params['picture'] = $first->url; + $params['caption'] = 'Click for full size'; + $params['source'] = $first->url; + } + + } + + $result = $this->facebook->api( + sprintf('/%s/feed', $fbuid), 'post', $params + ); + + } catch (FacebookApiException $e) { + return $this->handleFacebookError($e); + } + + return true; } /* @@ -216,40 +256,40 @@ class Facebookclient */ function sendOldRest() { - if (isFacebookBound()) { - - try { - - $canPublish = $this->checkPermission('publish_stream'); - $canUpdate = $this->checkPermission('status_update'); - - // Post to Facebook - if ($notice->hasAttachments() && $canPublish == 1) { - $this->restPublishStream(); - } elseif ($canUpdate == 1 || $canPublish == 1) { - $this->restStatusUpdate(); - } else { - - $msg = 'Not sending notice %d to Facebook because user %s ' - . '(%d), fbuid %s, does not have \'status_update\' ' - . 'or \'publish_stream\' permission.'; - - common_log( - LOG_WARNING, - sprintf( - $msg, - $this->notice->id, - $this->user->nickname, - $this->user->id, - $this->flink->foreign_id - ), - __FILE__ - ); - } + try { - } catch (FacebookRestClientException $e) { - return $this->handleFacebookError($e); + $canPublish = $this->checkPermission('publish_stream'); + $canUpdate = $this->checkPermission('status_update'); + + // We prefer to use stream.publish, because it can handle + // attachments and returns the ID of the published item + + if ($canPublish == 1) { + $this->restPublishStream(); + } else if ($canUpdate == 1) { + // as a last resort we can just update the user's "status" + $this->restStatusUpdate(); + } else { + + $msg = 'Not sending notice %d to Facebook because user %s ' + . '(%d), fbuid %s, does not have \'status_update\' ' + . 'or \'publish_stream\' permission.'; + + common_log( + LOG_WARNING, + sprintf( + $msg, + $this->notice->id, + $this->user->nickname, + $this->user->id, + $this->flink->foreign_id + ), + __FILE__ + ); } + + } catch (FacebookApiException $e) { + return $this->handleFacebookError($e); } return true; @@ -267,12 +307,11 @@ class Facebookclient */ function checkPermission($permission) { - if (!in_array($permission, array('publish_stream', 'status_update'))) { - throw new ServerExpception("No such permission!"); + throw new ServerException("No such permission!"); } - $fbuid = $this->flink->foreign_link; + $fbuid = $this->flink->foreign_id; common_debug( sprintf( @@ -285,24 +324,14 @@ class Facebookclient __FILE__ ); - // NOTE: $this->oldRestClient->users_hasAppPermission() has been - // returning bogus results, so we're using FQL to check for - // permissions - - $fql = sprintf( - "SELECT %s FROM permissions WHERE uid = %s", - $permission, - $fbuid + $hasPermission = $this->facebook->api( + array( + 'method' => 'users.hasAppPermission', + 'ext_perm' => $permission, + 'uid' => $fbuid + ) ); - $result = $this->oldRestClient->fql_query($fql); - - $hasPermission = 0; - - if (isset($result[0][$permission])) { - $canPublish = $result[0][$permission]; - } - if ($hasPermission == 1) { common_debug( @@ -338,14 +367,27 @@ class Facebookclient return false; } - } + /* + * Handle a Facebook API Exception + * + * @param FacebookApiException $e the exception + * + */ function handleFacebookError($e) { $fbuid = $this->flink->foreign_id; - $code = $e->getCode(); $errmsg = $e->getMessage(); + $code = $e->getCode(); + + // The Facebook PHP SDK seems to always set the code attribute + // of the Exception to 0; they put the real error code it in + // the message. Gar! + if ($code == 0) { + preg_match('/^\(#(?<code>\d+)\)/', $errmsg, $matches); + $code = $matches['code']; + } // XXX: Check for any others? switch($code) { @@ -414,6 +456,14 @@ class Facebookclient } } + /* + * Publish a notice to Facebook as a status update + * + * This is the least preferable way to send a notice to Facebook because + * it doesn't support attachments and the API method doesn't return + * the ID of the post on Facebook. + * + */ function restStatusUpdate() { $fbuid = $this->flink->foreign_id; @@ -429,11 +479,13 @@ class Facebookclient __FILE__ ); - $result = $this->oldRestClient->users_setStatus( - $this->notice->content, - $fbuid, - false, - true + $result = $this->facebook->api( + array( + 'method' => 'users.setStatus', + 'status' => $this->notice->content, + 'status_includes_verb' => true, + 'uid' => $fbuid + ) ); common_log( @@ -447,16 +499,19 @@ class Facebookclient ), __FILE__ ); + } + /* + * Publish a notice to a Facebook user's stream using the old REST API + */ function restPublishStream() { $fbuid = $this->flink->foreign_id; common_debug( sprintf( - 'Attempting to post notice %d as stream item with attachment for ' - . '%s (%d) fbuid %s', + 'Attempting to post notice %d as stream item for %s (%d) fbuid %s', $this->notice->id, $this->user->nickname, $this->user->id, @@ -465,42 +520,52 @@ class Facebookclient __FILE__ ); - $fbattachment = format_attachments($notice->attachments()); + $fbattachment = $this->formatAttachments(); - $this->oldRestClient->stream_publish( - $this->notice->content, - $fbattachment, - null, - null, - $fbuid + $result = $this->facebook->api( + array( + 'method' => 'stream.publish', + 'message' => $this->notice->content, + 'attachment' => $fbattachment, + 'uid' => $fbuid + ) ); common_log( LOG_INFO, sprintf( - 'Posted notice %d as a stream item with attachment for %s ' - . '(%d), fbuid %s', + 'Posted notice %d as a %s for %s (%d), fbuid %s', $this->notice->id, + empty($fbattachment) ? 'stream item' : 'stream item with attachment', $this->user->nickname, $this->user->id, $fbuid ), __FILE__ ); - + } - function format_attachments($attachments) + /* + * Format attachments for the old REST API stream.publish method + * + * Note: Old REST API supports multiple attachments per post + * + */ + function formatAttachments() { + + $attachments = $this->notice->attachments(); + $fbattachment = array(); $fbattachment['media'] = array(); foreach($attachments as $attachment) { if($enclosure = $attachment->getEnclosure()){ - $fbmedia = get_fbmedia_for_attachment($enclosure); + $fbmedia = $this->getFacebookMedia($enclosure); }else{ - $fbmedia = get_fbmedia_for_attachment($attachment); + $fbmedia = $this->getFacebookMedia($attachment); } if($fbmedia){ $fbattachment['media'][]=$fbmedia; @@ -518,9 +583,9 @@ class Facebookclient } /** - * given an File objects, returns an associative array suitable for Facebook media + * given a File objects, returns an associative array suitable for Facebook media */ - function get_fbmedia_for_attachment($attachment) + function getFacebookMedia($attachment) { $fbmedia = array(); @@ -545,9 +610,13 @@ class Facebookclient return $fbmedia; } + /* + * Disconnect a user from Facebook by deleting his Foreign_link. + * Notifies the user his account has been disconnected by email. + */ function disconnect() { - $fbuid = $this->flink->foreign_link; + $fbuid = $this->flink->foreign_id; common_log( LOG_INFO, @@ -560,7 +629,7 @@ class Facebookclient __FILE__ ); - $result = $flink->delete(); + $result = $this->flink->delete(); if (empty($result)) { common_log( @@ -631,7 +700,7 @@ BODY; $this->user->nickname, $siteName ); - + common_switch_locale(); return mail_to_user($this->user, $subject, $body); |