+++ /dev/null
-<?php
-
-/*
- * Abraham Williams (abraham@abrah.am) http://abrah.am
- *
- * The first PHP Library to support OAuth for Tumblr's REST API. (Originally for Twitter, modified for Tumblr by Lucas)
- */
-
-use Friendica\Core\Logger;
-use Friendica\DI;
-use Friendica\Security\OAuth1\OAuthConsumer;
-use Friendica\Security\OAuth1\OAuthRequest;
-use Friendica\Security\OAuth1\Signature\OAuthSignatureMethod_HMAC_SHA1;
-use Friendica\Security\OAuth1\OAuthToken;
-use Friendica\Security\OAuth1\OAuthUtil;
-use GuzzleHttp\Client;
-use GuzzleHttp\Exception\RequestException;
-use GuzzleHttp\HandlerStack;
-use GuzzleHttp\Subscriber\Oauth\Oauth1;
-use Psr\Http\Message\ResponseInterface;
-
-/**
- * Tumblr OAuth class
- */
-class TumblrOAuth
-{
- private $consumer_key;
- private $consumer_secret;
- private $oauth_token;
- private $oauth_token_secret;
-
- /** @var GuzzleHttp\Client */
- private $client;
-
- // API URLs
- const accessTokenURL = 'https://www.tumblr.com/oauth/access_token';
- const authorizeURL = 'https://www.tumblr.com/oauth/authorize';
- const requestTokenURL = 'https://www.tumblr.com/oauth/request_token';
-
- function __construct(string $consumer_key, string $consumer_secret, string $oauth_token = '', string $oauth_token_secret = '')
- {
- $this->consumer_key = $consumer_key;
- $this->consumer_secret = $consumer_secret;
- $this->oauth_token = $oauth_token;
- $this->oauth_token_secret = $oauth_token_secret;
-
- if (empty($this->oauth_token) || empty($this->oauth_token_secret)) {
- return;
- }
-
- $stack = HandlerStack::create();
-
- $middleware = new Oauth1([
- 'consumer_key' => $this->consumer_key,
- 'consumer_secret' => $this->consumer_secret,
- 'token' => $this->oauth_token,
- 'token_secret' => $this->oauth_token_secret
- ]);
- $stack->push($middleware);
-
- $this->client = new Client([
- 'base_uri' => 'https://api.tumblr.com/v2/',
- 'handler' => $stack
- ]);
- }
-
- /**
- * Get a request_token from Tumblr
- *
- * @param string $oauth_callback
- * @return array
- */
- function getRequestToken(string $oauth_callback): array
- {
- $request = $this->oAuthRequest(self::requestTokenURL, ['oauth_callback' => $oauth_callback]);
- if (empty($request)) {
- return [];
- }
- return OAuthUtil::parse_parameters($request);
- }
-
- /**
- * Get the authorize URL
- *
- * @param string $oauth_token
- * @return string
- */
- function getAuthorizeURL(string $oauth_token): string
- {
- return self::authorizeURL . "?oauth_token={$oauth_token}";
- }
-
- /**
- * Exchange request token and secret for an access token and
- * secret, to sign API calls.
- *
- * @param string $oauth_verifier
- * @param string $request_token
- * @param string $request_token_secret
- * @return array ("oauth_token" => "the-access-token",
- * "oauth_token_secret" => "the-access-secret",
- * "user_id" => "9436992",
- * "screen_name" => "abraham")
- */
- function getAccessToken(string $oauth_verifier, string $request_token, string $request_token_secret): array
- {
- $token = new OAuthToken($request_token, $request_token_secret);
-
- $parameters = [];
- if (!empty($oauth_verifier)) {
- $parameters['oauth_verifier'] = $oauth_verifier;
- }
-
- $request = $this->oAuthRequest(self::accessTokenURL, $parameters, $token);
- if (empty($request)) {
- return [];
- }
- return OAuthUtil::parse_parameters($request);
- }
-
- /**
- * Format and sign an OAuth / API request
- *
- * @param string $url
- * @param array $parameters
- * @param OAuthToken $token $name
- * @return string
- */
- private function oAuthRequest(string $url, array $parameters, OAuthToken $token = null): string
- {
- $consumer = new OAuthConsumer($this->consumer_key, $this->consumer_secret);
- $sha1_method = new OAuthSignatureMethod_HMAC_SHA1();
-
- $request = OAuthRequest::from_consumer_and_token($consumer, 'GET', $url, $parameters, $token);
- $request->sign_request($sha1_method, $consumer, $token);
-
- $curlResult = DI::httpClient()->get($request->to_url());
- if ($curlResult->isSuccess()) {
- return $curlResult->getBody();
- }
- return '';
- }
-
- /**
- * OAuth get from a given url with given parameters
- *
- * @param string $url
- * @param array $parameters
- * @return stdClass
- */
- public function get(string $url, array $parameters = []): stdClass
- {
- if (!empty($parameters)) {
- $url .= '?' . http_build_query($parameters);
- }
-
- try {
- $response = $this->client->get($url, ['auth' => 'oauth']);
- } catch (RequestException $exception) {
- $response = $exception->getResponse();
- Logger::notice('Get failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]);
- }
-
- return $this->formatResponse($response);
- }
-
- /**
- * OAuth Post to a given url with given parameters
- *
- * @param string $url
- * @param array $parameter
- * @return stdClass
- */
- public function post(string $url, array $parameter): stdClass
- {
- try {
- $response = $this->client->post($url, ['auth' => 'oauth', 'json' => $parameter]);
- } catch (RequestException $exception) {
- $response = $exception->getResponse();
- Logger::notice('Post failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]);
- }
-
- return $this->formatResponse($response);
- }
-
- /**
- * Convert the body in the given response to a class
- *
- * @param ResponseInterface|null $response
- * @return stdClass
- */
- private function formatResponse(ResponseInterface $response = null): stdClass
- {
- if (!is_null($response)) {
- $content = $response->getBody()->getContents();
- if (!empty($content)) {
- $result = json_decode($content);
- }
- }
-
- if (empty($result) || empty($result->meta)) {
- $result = new stdClass;
- $result->meta = new stdClass;
- $result->meta->status = 500;
- $result->meta->msg = '';
- $result->response = [];
- $result->errors = [];
- }
- return $result;
- }
-}
\ No newline at end of file
* Author: Michael Vogel <https://pirati.ca/profile/heluecht>
*/
-require_once __DIR__ . DIRECTORY_SEPARATOR . 'library' . DIRECTORY_SEPARATOR . 'tumblroauth.php';
-
use Friendica\Content\PageInfo;
use Friendica\Content\Text\BBCode;
use Friendica\Content\Text\HTML;
use Friendica\Model\Photo;
use Friendica\Model\Post;
use Friendica\Model\Tag;
+use Friendica\Network\HTTPClient\Capability\ICanHandleHttpResponses;
+use Friendica\Network\HTTPClient\Client\HttpClientAccept;
+use Friendica\Network\HTTPClient\Client\HttpClientOptions;
use Friendica\Protocol\Activity;
use Friendica\Util\DateTimeFormat;
use Friendica\Util\Network;
use Friendica\Util\Strings;
+use GuzzleHttp\Client;
+use GuzzleHttp\Exception\RequestException;
+use GuzzleHttp\HandlerStack;
+use GuzzleHttp\Subscriber\Oauth\Oauth1;
define('TUMBLR_DEFAULT_POLL_INTERVAL', 10); // given in minutes
Hook::register('jot_networks', __FILE__, 'tumblr_jot_nets');
Hook::register('connector_settings', __FILE__, 'tumblr_settings');
Hook::register('connector_settings_post', __FILE__, 'tumblr_settings_post');
- Hook::register('cron' , __FILE__, 'tumblr_cron');
+ Hook::register('cron', __FILE__, 'tumblr_cron');
}
/**
{
if (!DI::userSession()->getLocalUserId()) {
DI::sysmsg()->addNotice(DI::l10n()->t('Permission denied.'));
- return '';
- }
-
- if (!isset(DI::args()->getArgv()[1])) {
- DI::baseUrl()->redirect('settings/connectors/tumblr');
+ return;
}
- switch (DI::args()->getArgv()[1]) {
+ switch (DI::args()->getArgv()[1] ?? '') {
case 'connect':
- $o = tumblr_connect();
+ tumblr_connect();
break;
- case 'callback':
- $o = tumblr_callback();
- break;
-
- default:
- DI::baseUrl()->redirect('settings/connectors/tumblr');
+ case 'redirect':
+ tumblr_redirect();
break;
}
-
- return $o;
+ DI::baseUrl()->redirect('settings/connectors/tumblr');
}
-function tumblr_connect()
+function tumblr_redirect()
{
- // Define the needed keys
- $consumer_key = DI::config()->get('tumblr', 'consumer_key');
- $consumer_secret = DI::config()->get('tumblr', 'consumer_secret');
-
- if (empty($consumer_key) || empty($consumer_secret)) {
- DI::baseUrl()->redirect('settings/connectors/tumblr');
- }
-
- // The callback URL is the script that gets called after the user authenticates with tumblr
- // In this example, it would be the included callback.php
- $callback_url = DI::baseUrl() . '/tumblr/callback';
-
- // Let's begin. First we need a Request Token. The request token is required to send the user
- // to Tumblr's login page.
-
- // Create a new instance of the TumblrOAuth library. For this step, all we need to give the library is our
- // Consumer Key and Consumer Secret
- $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret);
-
- // Ask Tumblr for a Request Token. Specify the Callback URL here too (although this should be optional)
- $request_token = $tum_oauth->getRequestToken($callback_url);
-
- if (empty($request_token)) {
- // Give an error message
- return DI::l10n()->t('Could not connect to Tumblr. Refresh the page or try again later.');
+ if (($_REQUEST['state'] ?? '') != DI::session()->get('oauth_state')) {
+ return;
}
- // Store the request token and Request Token Secret as out callback.php script will need this
- DI::session()->set('request_token', $request_token['oauth_token']);
- DI::session()->set('request_token_secret', $request_token['oauth_token_secret']);
-
- // Ask Tumblr to give us a special address to their login page
- $url = $tum_oauth->getAuthorizeURL($request_token['oauth_token']);
-
- // Redirect the user to the login URL given to us by Tumblr
- System::externalRedirect($url);
-
- /*
- * That's it for our side. The user is sent to a Tumblr Login page and
- * asked to authroize our app. After that, Tumblr sends the user back to
- * our Callback URL (callback.php) along with some information we need to get
- * an access token.
- */
+ tumblr_get_token(DI::userSession()->getLocalUserId(), $_REQUEST['code'] ?? '');
}
-function tumblr_callback()
+function tumblr_connect()
{
// Define the needed keys
$consumer_key = DI::config()->get('tumblr', 'consumer_key');
$consumer_secret = DI::config()->get('tumblr', 'consumer_secret');
- if (empty($_REQUEST['oauth_verifier']) || empty($consumer_key) || empty($consumer_secret)) {
- DI::baseUrl()->redirect('settings/connectors/tumblr');
+ if (empty($consumer_key) || empty($consumer_secret)) {
+ return;
}
- // Once the user approves your app at Tumblr, they are sent back to this script.
- // This script is passed two parameters in the URL, oauth_token (our Request Token)
- // and oauth_verifier (Key that we need to get Access Token).
- // We'll also need out Request Token Secret, which we stored in a session.
-
- // Create instance of TumblrOAuth.
- // It'll need our Consumer Key and Secret as well as our Request Token and Secret
- $tum_oauth = new TumblrOAuth($consumer_key, $consumer_secret);
-
- // Ok, let's get an Access Token. We'll need to pass along our oauth_verifier which was given to us in the URL.
- $access_token = $tum_oauth->getAccessToken($_REQUEST['oauth_verifier'], DI::session()->get('request_token'), DI::session()->get('request_token_secret'));
-
- // We're done with the Request Token and Secret so let's remove those.
- DI::session()->remove('request_token');
- DI::session()->remove('request_token_secret');
+ $state = base64_encode(random_bytes(20));
+ DI::session()->set('oauth_state', $state);
- if (empty($access_token)) {
- return DI::l10n()->t('Unable to authenticate');
- }
-
- // What's next? Now that we have an Access Token and Secret, we can make an API call.
- DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token', $access_token['oauth_token']);
- DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'tumblr', 'oauth_token_secret', $access_token['oauth_token_secret']);
+ $parameters = [
+ 'client_id' => $consumer_key,
+ 'response_type' => 'code',
+ 'scope' => 'basic write offline_access',
+ 'state' => $state
+ ];
- DI::baseUrl()->redirect('settings/connectors/tumblr');
+ System::externalRedirect('https://www.tumblr.com/oauth2/authorize?' . http_build_query($parameters));
}
function tumblr_addon_admin(string &$o)
$o = Renderer::replaceMacros($t, [
'$submit' => DI::l10n()->t('Save Settings'),
- // name, label, value, help, [extra values]
'$consumer_key' => ['consumer_key', DI::l10n()->t('Consumer Key'), DI::config()->get('tumblr', 'consumer_key'), ''],
'$consumer_secret' => ['consumer_secret', DI::l10n()->t('Consumer Secret'), DI::config()->get('tumblr', 'consumer_secret'), ''],
]);
if (!empty($blogs)) {
DI::cache()->set($cachekey, $blogs, Duration::HALF_HOUR);
}
- } elseif (empty(tumblr_connection(DI::userSession()->getLocalUserId()))) {
- $blogs = null;
- DI::cache()->delete($cachekey);
}
if (!empty($blogs)) {
return;
}
} elseif (!strstr($post['postopts'] ?? '', 'tumblr') || ($post['parent'] != $post['id']) || $post['private']) {
- DI::logger()->info('Activities are never exported when we don\'t import the tumblr timeline');
+ DI::logger()->info('Activities are never exported when we don\'t import the tumblr timeline', ['uid' => $post['uid']]);
$b['execute'] = false;
return;
}
Logger::debug('Parent found', ['parent' => $parent]);
- $connection = tumblr_connection($b['uid']);
- if (empty($connection)) {
- return;
- }
-
$page = tumblr_get_page($b['uid']);
if ($b['gravity'] == Item::GRAVITY_COMMENT) {
} else {
if (($b['verb'] == Activity::LIKE) && !$b['deleted']) {
$params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']];
- $result = $connection->post('user/like', $params);
+ $result = tumblr_post($b['uid'], 'user/like', $params);
} elseif (($b['verb'] == Activity::LIKE) && $b['deleted']) {
$params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']];
- $result = $connection->post('user/unlike', $params);
+ $result = tumblr_post($b['uid'], 'user/unlike', $params);
} elseif (($b['verb'] == Activity::ANNOUNCE) && !$b['deleted']) {
$params = ['id' => $parent['id'], 'reblog_key' => $parent['reblog_key']];
- $result = $connection->post('blog/' . $page . '/post/reblog', $params);
+ $result = tumblr_post($b['uid'], 'blog/' . $page . '/post/reblog', $params);
} elseif (($b['verb'] == Activity::ANNOUNCE) && $b['deleted']) {
$announce = tumblr_get_post_from_uri($b['extid']);
if (empty($announce)) {
return;
}
$params = ['id' => $announce['id']];
- $result = $connection->post('blog/' . $page . '/post/delete', $params);
+ $result = tumblr_post($b['uid'], 'blog/' . $page . '/post/delete', $params);
} else {
// Unsupported activity
return;
function tumblr_send_legacy(array $b)
{
- $connection = tumblr_connection($b['uid']);
- if (empty($connection)) {
- return;
- }
-
$b['body'] = BBCode::removeAttachment($b['body']);
$title = trim($b['title']);
$page = tumblr_get_page($b['uid']);
- $result = $connection->post('blog/' . $page . '/post', $params);
+ $result = tumblr_post($b['uid'], 'blog/' . $page . '/post', $params);
if ($result->meta->status < 400) {
Logger::info('Success (legacy)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]);
{
$page = tumblr_get_page($post['uid']);
- $connection = tumblr_connection($post['uid']);
if (empty($page)) {
Logger::notice('Missing page, post will not be send to Tumblr.', ['uid' => $post['uid'], 'page' => $page, 'id' => $post['id']]);
// "true" is returned, since the legacy function will fail as well.
'interactability_reblog' => 'everyone'
];
- $result = $connection->post('blog/' . $page . '/posts', $params);
+ $result = tumblr_post($post['uid'], 'blog/' . $page . '/posts', $params);
if ($result->meta->status < 400) {
Logger::info('Success (NPF)', ['blog' => $page, 'meta' => $result->meta, 'response' => $result->response]);
if (($parts[0] != 'tumblr') || empty($parts[2])) {
return [];
}
-
- $post ['id'] = $parts[2];
+
+ $post['id'] = $parts[2];
$post['reblog_key'] = $parts[3] ?? '';
$post['reblog_key'] = str_replace('@t', '', $post['reblog_key']); // Temp
$parameters['since_id'] = $last;
}
- $connection = tumblr_connection($uid);
- $dashboard = $connection->get('user/dashboard', $parameters);
+ $dashboard = tumblr_get($uid, 'user/dashboard', $parameters);
if ($dashboard->meta->status > 399) {
Logger::notice('Error fetching dashboard', ['meta' => $dashboard->meta, 'response' => $dashboard->response, 'errors' => $dashboard->errors]);
return [];
$item['body'] = HTML::toBBCode($post->caption);
if (!empty($post->video_url)) {
$item['body'] .= "\n[video]" . $post->video_url . "[/video]\n";
- } elseif(!empty($post->thumbnail_url)) {
- $item['body'] .= "\n[url=" . $post->permalink_url ."][img]" . $post->thumbnail_url . "[/img][/url]\n";
- } elseif(!empty($post->permalink_url)) {
- $item['body'] .= "\n[url]" . $post->permalink_url ."[/url]\n";
- } elseif(!empty($post->source_url) && !empty($post->source_title)) {
- $item['body'] .= "\n[url=" . $post->source_url ."]" . $post->source_title . "[/url]\n";
- } elseif(!empty($post->source_url)) {
- $item['body'] .= "\n[url]" . $post->source_url ."[/url]\n";
+ } elseif (!empty($post->thumbnail_url)) {
+ $item['body'] .= "\n[url=" . $post->permalink_url . "][img]" . $post->thumbnail_url . "[/img][/url]\n";
+ } elseif (!empty($post->permalink_url)) {
+ $item['body'] .= "\n[url]" . $post->permalink_url . "[/url]\n";
+ } elseif (!empty($post->source_url) && !empty($post->source_title)) {
+ $item['body'] .= "\n[url=" . $post->source_url . "]" . $post->source_title . "[/url]\n";
+ } elseif (!empty($post->source_url)) {
+ $item['body'] .= "\n[url]" . $post->source_url . "[/url]\n";
}
break;
case 'audio':
$item['body'] = HTML::toBBCode($post->caption);
- if(!empty($post->source_url) && !empty($post->source_title)) {
- $item['body'] .= "\n[url=" . $post->source_url ."]" . $post->source_title . "[/url]\n";
- } elseif(!empty($post->source_url)) {
- $item['body'] .= "\n[url]" . $post->source_url ."[/url]\n";
+ if (!empty($post->source_url) && !empty($post->source_title)) {
+ $item['body'] .= "\n[url=" . $post->source_url . "]" . $post->source_title . "[/url]\n";
+ } elseif (!empty($post->source_url)) {
+ $item['body'] .= "\n[url]" . $post->source_url . "[/url]\n";
}
break;
{
switch ($data['type']) {
case 'poll':
- $body = '[p][url=' . $plink. ']'. $data['question'] . '[/url][/p][ul]';
+ $body = '[p][url=' . $plink . ']' . $data['question'] . '[/url][/p][ul]';
foreach ($data['answers'] as $answer) {
$body .= '[li]' . $answer['answer_text'] . '[/li]';
}
$body = '[video]' . $data['url'] . '[/video]';
break;
}
-
+
default:
Logger::notice('Unknown type', ['type' => $data['type'], 'data' => $data, 'plink' => $plink]);
$body = '';
*/
function tumblr_update_contact(stdClass $blog, int $uid, int $cid, int $pcid)
{
- $connection = tumblr_connection($uid);
- $info = $connection->get('blog/' . $blog->uuid . '/info');
+ $info = tumblr_get($uid, 'blog/' . $blog->uuid . '/info');
if ($info->meta->status > 399) {
Logger::notice('Error fetching dashboard', ['meta' => $info->meta, 'response' => $info->response, 'errors' => $info->errors]);
return;
*/
function tumblr_get_blogs(int $uid): array
{
- $connection = tumblr_connection($uid);
- if (empty($connection)) {
- return [];
- }
-
- $userinfo = $connection->get('user/info');
+ $userinfo = tumblr_get($uid, 'user/info');
if ($userinfo->meta->status > 299) {
Logger::notice('Error fetching blogs', ['meta' => $userinfo->meta, 'response' => $userinfo->response, 'errors' => $userinfo->errors]);
return [];
}
/**
- * Creates a OAuth connection for the given user
+ * Perform an OAuth2 GET request
+ *
+ * @param integer $uid
+ * @param string $url
+ * @param array $parameters
+ * @return stdClass
+ */
+function tumblr_get(int $uid, string $url, array $parameters = []): stdClass
+{
+ $url = 'https://api.tumblr.com/v2/' . $url;
+
+ if (!empty($parameters)) {
+ $url .= '?' . http_build_query($parameters);
+ }
+
+ $curlResult = DI::httpClient()->get($url, HttpClientAccept::JSON, [HttpClientOptions::HEADERS => ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]]);
+ return tumblr_format_result($curlResult);
+}
+
+/**
+ * Perform an OAuth2 POST request
*
* @param integer $uid
- * @return TumblrOAuth|null
+ * @param string $url
+ * @param array $parameters
+ * @return stdClass
+ */
+function tumblr_post(int $uid, string $url, array $parameters): stdClass
+{
+ $url = 'https://api.tumblr.com/v2/' . $url;
+
+ $curlResult = DI::httpClient()->post($url, $parameters, ['Authorization' => ['Bearer ' . tumblr_get_token($uid)]]);
+ return tumblr_format_result($curlResult);
+}
+
+/**
+ * Format the get/post result value
+ *
+ * @param ICanHandleHttpResponses $curlResult
+ * @return stdClass
*/
-function tumblr_connection(int $uid): ?TumblrOAuth
+function tumblr_format_result(ICanHandleHttpResponses $curlResult): stdClass
+{
+ $result = json_decode($curlResult->getBody());
+ if (empty($result) || empty($result->meta)) {
+ $result = new stdClass;
+ $result->meta = new stdClass;
+ $result->meta->status = 500;
+ $result->meta->msg = '';
+ $result->response = [];
+ $result->errors = [];
+ }
+ return $result;
+}
+
+/**
+ * Fetch the OAuth token, update it if needed
+ *
+ * @param integer $uid
+ * @param string $code
+ * @return string
+ */
+function tumblr_get_token(int $uid, string $code = ''): string
+{
+ $access_token = DI::pConfig()->get($uid, 'tumblr', 'access_token');
+ $expires_at = DI::pConfig()->get($uid, 'tumblr', 'expires_at');
+ $refresh_token = DI::pConfig()->get($uid, 'tumblr', 'refresh_token');
+
+ if (empty($code) && !empty($access_token) && ($expires_at > (time()))) {
+ Logger::debug('Got token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]);
+ return $access_token;
+ }
+
+ $consumer_key = DI::config()->get('tumblr', 'consumer_key');
+ $consumer_secret = DI::config()->get('tumblr', 'consumer_secret');
+
+ $parameters = ['client_id' => $consumer_key, 'client_secret' => $consumer_secret];
+
+ if (empty($refresh_token) && empty($code)) {
+ $result = tumblr_exchange_token($uid);
+ if (empty($result)) {
+ Logger::info('Invalid result while exchanging token', ['uid' => $uid]);
+ return '';
+ }
+ $expires_at = time() + $result->expires_in;
+ Logger::debug('Updated token from OAuth1 to OAuth2', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]);
+ } else {
+ if (!empty($code)) {
+ $parameters['code'] = $code;
+ $parameters['grant_type'] = 'authorization_code';
+ } else {
+ $parameters['refresh_token'] = $refresh_token;
+ $parameters['grant_type'] = 'refresh_token';
+ }
+
+ $curlResult = DI::httpClient()->post('https://api.tumblr.com/v2/oauth2/token', $parameters);
+ if (!$curlResult->isSuccess()) {
+ Logger::info('Error fetching token', ['uid' => $uid, 'code' => $code, 'result' => $curlResult->getBody(), 'parameters' => $parameters]);
+ return '';
+ }
+
+ $result = json_decode($curlResult->getBody());
+ if (empty($result)) {
+ Logger::info('Invalid result when updating token', ['uid' => $uid]);
+ return '';
+ }
+
+ $expires_at = time() + $result->expires_in;
+ Logger::debug('Renewed token', ['uid' => $uid, 'expires_at' => date('c', $expires_at)]);
+ }
+
+ DI::pConfig()->set($uid, 'tumblr', 'access_token', $result->access_token);
+ DI::pConfig()->set($uid, 'tumblr', 'expires_at', $expires_at);
+ DI::pConfig()->set($uid, 'tumblr', 'refresh_token', $result->refresh_token);
+
+ return $result->access_token;
+}
+
+/**
+ * Create an OAuth2 token out of an OAuth1 token
+ *
+ * @param int $uid
+ * @return stdClass
+ */
+function tumblr_exchange_token(int $uid): stdClass
{
$oauth_token = DI::pConfig()->get($uid, 'tumblr', 'oauth_token');
$oauth_token_secret = DI::pConfig()->get($uid, 'tumblr', 'oauth_token_secret');
$consumer_key = DI::config()->get('tumblr', 'consumer_key');
$consumer_secret = DI::config()->get('tumblr', 'consumer_secret');
- if (!$consumer_key || !$consumer_secret || !$oauth_token || !$oauth_token_secret) {
- Logger::notice('Missing data, connection is not established', ['uid' => $uid]);
- return null;
- }
+ $stack = HandlerStack::create();
- return new TumblrOAuth($consumer_key, $consumer_secret, $oauth_token, $oauth_token_secret);
-}
\ No newline at end of file
+ $middleware = new Oauth1([
+ 'consumer_key' => $consumer_key,
+ 'consumer_secret' => $consumer_secret,
+ 'token' => $oauth_token,
+ 'token_secret' => $oauth_token_secret
+ ]);
+
+ $stack->push($middleware);
+
+ try {
+ $client = new Client([
+ 'base_uri' => 'https://api.tumblr.com/v2/',
+ 'handler' => $stack
+ ]);
+
+ $response = $client->post('oauth2/exchange', ['auth' => 'oauth']);
+ return json_decode($response->getBody()->getContents());
+ } catch (RequestException $exception) {
+ Logger::notice('Exchange failed', ['code' => $exception->getCode(), 'message' => $exception->getMessage()]);
+ return new stdClass;
+ }
+}