Commit 500f0c70 authored by Zach Copley's avatar Zach Copley Committed by Evan Prodromou

Make the TwitterQueuehandler post to Twitter using OAuth

parent e9edaab3
......@@ -67,39 +67,57 @@ class TwitterauthorizationAction extends Action
if (empty($this->oauth_token)) {
// Get a new request token and authorize it
try {
$client = new TwitterOAuthClient();
$req_tok = $client->getRequestToken();
// Get a new request token and authorize it
// Sock the request token away in the session temporarily
$client = new TwitterOAuthClient();
$req_tok = $client->getRequestToken();
$_SESSION['twitter_request_token'] = $req_tok->key;
$_SESSION['twitter_request_token_secret'] = $req_tok->key;
// Sock the request token away in the session temporarily
$_SESSION['twitter_request_token'] = $req_tok->key;
$_SESSION['twitter_request_token_secret'] = $req_tok->key;
$auth_link = $client->getAuthorizeLink($req_tok);
} catch (TwitterOAuthClientException $e) {
$msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s',
$e->getCode(), $e->getMessage());
$this->serverError(_('Couldn\'t link your Twitter account.'));
}
$auth_link = $client->getAuthorizeLink($req_tok);
common_redirect($auth_link);
} else {
// Check to make sure Twitter sent us the same request token we sent
// Check to make sure Twitter returned the same request
// token we sent them
if ($_SESSION['twitter_request_token'] != $this->oauth_token) {
$this->serverError(_('Couldn\'t link your Twitter account.'));
}
$client = new TwitterOAuthClient($_SESSION['twitter_request_token'],
$_SESSION['twitter_request_token_secret']);
try {
// Exchange the request token for an access token
$client = new TwitterOAuthClient($_SESSION['twitter_request_token'],
$_SESSION['twitter_request_token_secret']);
$atok = $client->getAccessToken();
// Exchange the request token for an access token
// Save the access token and Twitter user info
$atok = $client->getAccessToken();
$client = new TwitterOAuthClient($atok->key, $atok->secret);
// Save the access token and Twitter user info
$twitter_user = $client->verify_credentials();
$client = new TwitterOAuthClient($atok->key, $atok->secret);
$twitter_user = $client->verify_credentials();
} catch (OAuthClientException $e) {
$msg = sprintf('OAuth client cURL error - code: %1s, msg: %2s',
$e->getCode(), $e->getMessage());
$this->serverError(_('Couldn\'t link your Twitter account.'));
}
$user = common_current_user();
......
......@@ -645,13 +645,14 @@ function mail_twitter_bridge_removed($user)
$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" .
$site_name = common_config('site', 'name');
$body = sprintf(_('Hi, %1$s. We\'re sorry to inform you that your ' .
'link to Twitter has been disabled. We no longer seem to have ' .
'permission to update your Twitter status. (Did you revoke ' .
'%3$s\'s access?)' . "\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'),
......@@ -679,11 +680,11 @@ function mail_facebook_app_removed($user)
$site_name = common_config('site', 'name');
$subject = sprintf(
_('Your %1\$s Facebook application access has been disabled.',
_('Your %1$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 %2\$s, and have disabled ' .
'unable to update your Facebook status from %2$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 ' .
......
......@@ -360,104 +360,72 @@ function is_twitter_bound($notice, $flink) {
function broadcast_twitter($notice)
{
$flink = Foreign_link::getByUserID($notice->profile_id,
TWITTER_SERVICE);
if (is_twitter_bound($notice, $flink)) {
$fuser = $flink->getForeignUser();
$twitter_user = $fuser->nickname;
$twitter_password = $flink->credentials;
$uri = 'http://www.twitter.com/statuses/update.json';
$user = $flink->getUser();
// XXX: Hack to get around PHP cURL's use of @ being a a meta character
$statustxt = preg_replace('/^@/', ' @', $notice->content);
$options = array(
CURLOPT_USERPWD => "$twitter_user:$twitter_password",
CURLOPT_POST => true,
CURLOPT_POSTFIELDS =>
array(
'status' => $statustxt,
'source' => common_config('integration', 'source')
),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FAILONERROR => true,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => "Laconica",
CURLOPT_CONNECTTIMEOUT => 120, // XXX: How long should this be?
CURLOPT_TIMEOUT => 120,
# Twitter is strict about accepting invalid "Expect" headers
CURLOPT_HTTPHEADER => array('Expect:')
);
$ch = curl_init($uri);
curl_setopt_array($ch, $options);
$data = curl_exec($ch);
$errmsg = curl_error($ch);
$errno = curl_errno($ch);
$client = new TwitterOAuthClient($flink->token, $flink->credentials);
if (!empty($errmsg)) {
common_debug("cURL error ($errno): $errmsg - " .
"trying to send notice for $twitter_user.",
__FILE__);
$status = null;
$user = $flink->getUser();
try {
$status = $client->statuses_update($statustxt);
} catch (OAuthClientCurlException $e) {
if ($errmsg == 'The requested URL returned error: 401') {
common_debug(sprintf('User %s (user id: %s) ' .
'has bad Twitter credentials!',
$user->nickname, $user->id));
if ($e->getMessage() == 'The requested URL returned error: 401') {
// Bad credentials we need to delete the foreign_link
// to Twitter and inform the user.
$errmsg = sprintf('User %1$s (user id: %2$s) has an invalid ' .
'Twitter OAuth access token.',
$user->nickname, $user->id);
common_log(LOG_WARNING, $errmsg);
remove_twitter_link($flink);
// Bad auth token! We need to delete the foreign_link
// to Twitter and inform the user.
return true;
remove_twitter_link($flink);
return true;
} else {
} else {
// Some other error happened, so we should try to
// send again later
// Some other error happened, so we should probably
// try to send again later.
return false;
}
$errmsg = sprintf('cURL error trying to send notice to Twitter ' .
'for user %1$s (user id: %2$s) - ' .
'code: %3$s message: $4$s.',
$user->nickname, $user->id,
$e->getCode(), $e->getMessage());
common_log(LOG_WARNING, $errmsg);
return false;
}
}
curl_close($ch);
if (empty($data)) {
common_debug("No data returned by Twitter's " .
"API trying to send update for $twitter_user",
__FILE__);
if (empty($status)) {
// XXX: Not sure this represents a failure to send, but it
// probably does
// This could represent a failure posting,
// or the Twitter API might just be behaving flakey.
return false;
$errmsg = sprint('No data returned by Twitter API when ' .
'trying to send update for %1$s (user id %2$s).',
$user->nickname, $user->id);
common_log(LOG_WARNING, $errmsg);
} else {
// Twitter should return a status
$status = json_decode($data);
return false;
}
if (empty($status)) {
common_debug("Unexpected data returned by Twitter " .
" API trying to send update for $twitter_user",
__FILE__);
// Notice crossed the great divide
// 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.
$msg = sprintf('Twitter bridge posted notice %s to Twitter.',
$notice->id);
common_log(LOG_INFO, $msg);
return false;
}
}
}
return true;
......@@ -480,17 +448,20 @@ function remove_twitter_link($flink)
// Notify the user that her Twitter bridge is down
if (isset($user->email)) {
$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 ' .
"$user->nickname (user id: $user->id) " .
'that their Twitter bridge link was ' .
'removed!';
common_log(LOG_WARNING, $msg);
}
}
}
......@@ -2,6 +2,8 @@
require_once('OAuth.php');
class OAuthClientCurlException extends Exception { }
class TwitterOAuthClient
{
public static $requestTokenURL = 'https://twitter.com/oauth/request_token';
......@@ -54,6 +56,16 @@ class TwitterOAuthClient
return $twitter_user;
}
function statuses_update($status, $in_reply_to_status_id = null)
{
$url = 'https://twitter.com/statuses/update.json';
$params = array('status' => $status,
'in_reply_to_status_id' => $in_reply_to_status_id);
$response = $this->oAuthPost($url, $params);
$status = json_decode($response);
return $status;
}
function oAuthGet($url)
{
$request = OAuthRequest::from_consumer_and_token($this->consumer,
......@@ -91,19 +103,26 @@ class TwitterOAuthClient
// Twitter is strict about accepting invalid "Expect" headers
CURLOPT_HTTPHEADER => array('Expect:')
);
);
if (isset($params)) {
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $params;
}
if (isset($params)) {
$options[CURLOPT_POST] = true;
$options[CURLOPT_POSTFIELDS] = $params;
}
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
if ($response === false) {
$msg = curl_error($ch);
$code = curl_errno($ch);
throw new OAuthClientCurlException($msg, $code);
}
$ch = curl_init($url);
curl_setopt_array($ch, $options);
$response = curl_exec($ch);
curl_close($ch);
curl_close($ch);
return $response;
return $response;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment