From 616d68cf9481f08eae75095e2188fb7fea6d822c Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 9 Jul 2009 00:40:12 +0000 Subject: Better error handling for TwitterQueueHandler --- lib/mail.php | 36 +++++++++++++++++++++ lib/twitter.php | 97 +++++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 116 insertions(+), 17 deletions(-) diff --git a/lib/mail.php b/lib/mail.php index 4e1f1dbb1..c948f83ca 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -625,3 +625,39 @@ function mail_notify_attn($user, $notice) common_init_locale(); mail_to_user($user, $subject, $body); } + +/** + * Send a mail message to notify a user that her Twitter bridge link + * has stopped working, and therefore has been removed. This can + * happen when the user changes her Twitter password, or otherwise + * revokes access. + * + * @param User $user user whose Twitter bridge link has been removed + * + * @return boolean success flag + */ + +function mail_twitter_bridge_removed($user) +{ + common_init_locale($user->language); + + $profile = $user->getProfile(); + + $subject = sprintf(_('Your Twitter bridge has been disabled.')); + + $body = sprintf(_("Hi, %1\$s. We're sorry to inform you that your " . + 'link to Twitter has been disabled. Your Twitter credentials ' . + 'have either changed (did you recently change your Twitter ' . + 'password?) or you have otherwise revoked our access to your ' . + "Twitter account.\n\n" . + 'You can re-enable your Twitter bridge by visiting your ' . + "Twitter settings page:\n\n\t%2\$s\n\n" . + "Regards,\n%3\$s\n"), + $profile->getBestName(), + common_local_url('twittersettings'), + common_config('site', 'name')); + + common_init_locale(); + return mail_to_user($user, $subject, $body); +} + diff --git a/lib/twitter.php b/lib/twitter.php index d5eba084b..47af32e61 100644 --- a/lib/twitter.php +++ b/lib/twitter.php @@ -360,13 +360,10 @@ function is_twitter_bound($notice, $flink) { function broadcast_twitter($notice) { - $success = true; $flink = Foreign_link::getByUserID($notice->profile_id, TWITTER_SERVICE); - // XXX: Not sure WHERE to check whether a notice should go to - // Twitter. Should we even put in the queue if it shouldn't? --Zach if (is_twitter_bound($notice, $flink)) { $fuser = $flink->getForeignUser(); @@ -401,33 +398,99 @@ function broadcast_twitter($notice) curl_setopt_array($ch, $options); $data = curl_exec($ch); $errmsg = curl_error($ch); + $errno = curl_errno($ch); - if ($errmsg) { - common_debug("cURL error: $errmsg - " . + if (!empty($errmsg)) { + common_debug("cURL error ($errno): $errmsg - " . "trying to send notice for $twitter_user.", __FILE__); - $success = false; + + $user = $flink->getUser(); + + if ($errmsg == 'The requested URL returned error: 401') { + common_debug(sprintf('User %s (user id: %s) ' . + 'has bad Twitter credentials!', + $user->nickname, $user->id)); + + // Bad credentials we need to delete the foreign_link + // to Twitter and inform the user. + + remove_twitter_link($flink); + + return true; + + } else { + + // Some other error happened, so we should try to + // send again later + + return false; + } + } curl_close($ch); - if (!$data) { + if (empty($data)) { common_debug("No data returned by Twitter's " . "API trying to send update for $twitter_user", __FILE__); - $success = false; - } - // Twitter should return a status - $status = json_decode($data); + // XXX: Not sure this represents a failure to send, but it + // probably does - if (!$status->id) { - common_debug("Unexpected data returned by Twitter " . - " API trying to send update for $twitter_user", - __FILE__); - $success = false; + return false; + + } else { + + // Twitter should return a status + $status = json_decode($data); + + if (empty($status)) { + common_debug("Unexpected data returned by Twitter " . + " API trying to send update for $twitter_user", + __FILE__); + + // XXX: Again, this could represent a failure posting + // or the Twitter API might just be behaving flakey. + // We're treating it as a failure to post. + + return false; + } } } - return $success; + return true; +} + +function remove_twitter_link($flink) +{ + $user = $flink->getUser(); + + common_log(LOG_INFO, 'Removing Twitter bridge Foreign link for ' . + "user $user->nickname (user id: $user->id)."); + + $result = $flink->delete(); + + if (empty($result)) { + common_log(LOG_ERR, 'Could not remove Twitter bridge ' . + "Foreign_link for $user->nickname (user id: $user->id)!"); + common_log_db_error($flink, 'DELETE', __FILE__); + } + + // Notify the user that her Twitter bridge is down + + $result = mail_twitter_bridge_removed($user); + + if (!$result) { + + $msg = 'Unable to send email to notify ' . + "$user->nickname (user id: $user->id) " . + 'that their Twitter bridge link was ' . + 'removed!'; + + common_log(LOG_WARNING, $msg); + } + } + -- cgit v1.2.3-54-g00ecf From bbb25e2153c3c58053155c7258644738fc9e6ab6 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 9 Jul 2009 02:04:38 +0000 Subject: Better error handling for FacebookQueueHandler --- lib/facebookutil.php | 75 ++++++++++++++++++++++++++++++++++++++++++++++------ lib/mail.php | 36 +++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/lib/facebookutil.php b/lib/facebookutil.php index 762d17bff..632ec4bad 100644 --- a/lib/facebookutil.php +++ b/lib/facebookutil.php @@ -90,10 +90,10 @@ function isFacebookBound($notice, $flink) { if ($result != 1) { $user = $flink->getUser(); - $msg = "Can't send notice $notice->id to Facebook " . + $msg = "Not sending notice $notice->id to Facebook " . "because user $user->nickname hasn't given the " . 'Facebook app \'status_update\' permission.'; - common_log(LOG_INFO, $msg); + common_debug($msg); $success = false; } @@ -118,7 +118,10 @@ function facebookBroadcastNotice($notice) $status = null; $fbuid = $flink->foreign_id; + $user = $flink->getUser(); + // Get the status 'verb' (prefix) the user has set + try { $prefix = $facebook->api_client-> data_getUserPreference(FACEBOOK_NOTICE_PREFIX, $fbuid); @@ -126,23 +129,79 @@ function facebookBroadcastNotice($notice) $status = "$prefix $notice->content"; } catch(FacebookRestClientException $e) { - common_log(LOG_ERR, $e->getMessage()); - return false; + common_log(LOG_WARNING, $e->getMessage()); + common_log(LOG_WARNING, + 'Unable to get the status verb setting from Facebook ' . + "for $user->nickname (user id: $user->id)."); } - // Okay, we're good to go! + // Okay, we're good to go, update the FB status try { $facebook->api_client->users_setStatus($status, $fbuid, false, true); - updateProfileBox($facebook, $flink, $notice); } catch(FacebookRestClientException $e) { common_log(LOG_ERR, $e->getMessage()); - return false; + common_log(LOG_ERR, + 'Unable to update Facebook status for ' . + "$user->nickname (user id: $user->id)!"); - // Should we remove flink if this fails? + $code = $e->getCode(); + + if ($code >= 200) { + + // 200 The application does not have permission to operate on the passed in uid parameter. + // 250 Updating status requires the extended permission status_update. + // see: http://wiki.developers.facebook.com/index.php/Users.setStatus#Example_Return_XML + + remove_facebook_app($flink); + } + + } + + // Now try to update the profile box + + try { + updateProfileBox($facebook, $flink, $notice); + } catch(FacebookRestClientException $e) { + common_log(LOG_WARNING, $e->getMessage()); + common_log(LOG_WARNING, + 'Unable to update Facebook profile box for ' . + "$user->nickname (user id: $user->id)."); } } return true; } + +function remove_facebook_app($flink) +{ + + $user = $flink->getUser(); + + common_log(LOG_INFO, 'Removing Facebook App Foreign link for ' . + "user $user->nickname (user id: $user->id)."); + + $result = $flink->delete(); + + if (empty($result)) { + common_log(LOG_ERR, 'Could not remove Facebook App ' . + "Foreign_link for $user->nickname (user id: $user->id)!"); + common_log_db_error($flink, 'DELETE', __FILE__); + } + + // Notify the user that we are removing their FB app access + + $result = mail_facebook_app_removed($user); + + if (!$result) { + + $msg = 'Unable to send email to notify ' . + "$user->nickname (user id: $user->id) " . + 'that their Facebook app link was ' . + 'removed!'; + + common_log(LOG_WARNING, $msg); + } + +} diff --git a/lib/mail.php b/lib/mail.php index c948f83ca..90ee3c992 100644 --- a/lib/mail.php +++ b/lib/mail.php @@ -661,3 +661,39 @@ function mail_twitter_bridge_removed($user) return mail_to_user($user, $subject, $body); } +/** + * Send a mail message to notify a user that her Facebook Application + * access has been removed. + * + * @param User $user user whose Facebook app link has been removed + * + * @return boolean success flag + */ + +function mail_facebook_app_removed($user) +{ + common_init_locale($user->language); + + $profile = $user->getProfile(); + + $site_name = common_config('site', 'name'); + + $subject = sprintf( + _('Your %s Facebook application access has been disabled.', + $site_name)); + + $body = sprintf(_("Hi, %1\$s. We're sorry to inform you that we are " . + 'unable to update your Facebook status from %s, and have disabled ' . + 'the Facebook application for your account. This may be because ' . + 'you have removed the Facebook application\'s authorization, or ' . + 'have deleted your Facebook account. You can re-enable the ' . + 'Facebook application and automatic status updating by ' . + "re-installing the %1\$s Facebook application.\n\nRegards,\n\n%1\$s"), + $site_name); + + common_init_locale(); + return mail_to_user($user, $subject, $body); + +} + + -- cgit v1.2.3-54-g00ecf