mirror of
https://github.com/RSS-Bridge/rss-bridge.git
synced 2025-08-04 10:04:54 +02:00
fix: rewrite and improve caching (#3594)
This commit is contained in:
parent
a786bbd4e0
commit
4b9f6f7e53
45 changed files with 993 additions and 1169 deletions
|
@ -594,156 +594,4 @@ EOD;
|
|||
{
|
||||
return (intval($tweet1['id']) < intval($tweet2['id']) ? 1 : -1);
|
||||
}
|
||||
|
||||
//The aim of this function is to get an API key and a guest token
|
||||
//This function takes 2 requests, and therefore is cached
|
||||
private function getApiKey($forceNew = 0)
|
||||
{
|
||||
$r_cache = RssBridge::getCache();
|
||||
$scope = 'TwitterBridge';
|
||||
$r_cache->setScope($scope);
|
||||
$r_cache->setKey(['refresh']);
|
||||
$data = $r_cache->loadData();
|
||||
|
||||
$refresh = null;
|
||||
if ($data === null) {
|
||||
$refresh = time();
|
||||
$r_cache->saveData($refresh);
|
||||
} else {
|
||||
$refresh = $data;
|
||||
}
|
||||
|
||||
$cacheFactory = new CacheFactory();
|
||||
|
||||
$cache = RssBridge::getCache();
|
||||
$cache->setScope($scope);
|
||||
$cache->setKey(['api_key']);
|
||||
$data = $cache->loadData();
|
||||
|
||||
$apiKey = null;
|
||||
if ($forceNew || $data === null || (time() - $refresh) > self::GUEST_TOKEN_EXPIRY) {
|
||||
$twitterPage = getContents('https://twitter.com');
|
||||
|
||||
$jsLink = false;
|
||||
$jsMainRegexArray = [
|
||||
'/(https:\/\/abs\.twimg\.com\/responsive-web\/web\/main\.[^\.]+\.js)/m',
|
||||
'/(https:\/\/abs\.twimg\.com\/responsive-web\/web_legacy\/main\.[^\.]+\.js)/m',
|
||||
'/(https:\/\/abs\.twimg\.com\/responsive-web\/client-web\/main\.[^\.]+\.js)/m',
|
||||
'/(https:\/\/abs\.twimg\.com\/responsive-web\/client-web-legacy\/main\.[^\.]+\.js)/m',
|
||||
];
|
||||
foreach ($jsMainRegexArray as $jsMainRegex) {
|
||||
if (preg_match_all($jsMainRegex, $twitterPage, $jsMainMatches, PREG_SET_ORDER, 0)) {
|
||||
$jsLink = $jsMainMatches[0][0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$jsLink) {
|
||||
returnServerError('Could not locate main.js link');
|
||||
}
|
||||
|
||||
$jsContent = getContents($jsLink);
|
||||
$apiKeyRegex = '/([a-zA-Z0-9]{59}%[a-zA-Z0-9]{44})/m';
|
||||
preg_match_all($apiKeyRegex, $jsContent, $apiKeyMatches, PREG_SET_ORDER, 0);
|
||||
$apiKey = $apiKeyMatches[0][0];
|
||||
$cache->saveData($apiKey);
|
||||
} else {
|
||||
$apiKey = $data;
|
||||
}
|
||||
|
||||
$gt_cache = RssBridge::getCache();
|
||||
$gt_cache->setScope($scope);
|
||||
$gt_cache->setKey(['guest_token']);
|
||||
$guestTokenUses = $gt_cache->loadData();
|
||||
|
||||
$guestToken = null;
|
||||
if (
|
||||
$forceNew || $guestTokenUses === null || !is_array($guestTokenUses) || count($guestTokenUses) != 2
|
||||
|| $guestTokenUses[0] <= 0 || (time() - $refresh) > self::GUEST_TOKEN_EXPIRY
|
||||
) {
|
||||
$guestToken = $this->getGuestToken($apiKey);
|
||||
if ($guestToken === null) {
|
||||
if ($guestTokenUses === null) {
|
||||
returnServerError('Could not parse guest token');
|
||||
} else {
|
||||
$guestToken = $guestTokenUses[1];
|
||||
}
|
||||
} else {
|
||||
$gt_cache->saveData([self::GUEST_TOKEN_USES, $guestToken]);
|
||||
$r_cache->saveData(time());
|
||||
}
|
||||
} else {
|
||||
$guestTokenUses[0] -= 1;
|
||||
$gt_cache->saveData($guestTokenUses);
|
||||
$guestToken = $guestTokenUses[1];
|
||||
}
|
||||
|
||||
$this->apiKey = $apiKey;
|
||||
$this->guestToken = $guestToken;
|
||||
$this->authHeaders = [
|
||||
'authorization: Bearer ' . $apiKey,
|
||||
'x-guest-token: ' . $guestToken,
|
||||
];
|
||||
|
||||
return [$apiKey, $guestToken];
|
||||
}
|
||||
|
||||
// Get a guest token. This is different to an API key,
|
||||
// and it seems to change more regularly than the API key.
|
||||
private function getGuestToken($apiKey)
|
||||
{
|
||||
$headers = [
|
||||
'authorization: Bearer ' . $apiKey,
|
||||
];
|
||||
$opts = [
|
||||
CURLOPT_POST => 1,
|
||||
];
|
||||
|
||||
try {
|
||||
$pageContent = getContents('https://api.twitter.com/1.1/guest/activate.json', $headers, $opts, true);
|
||||
$guestToken = json_decode($pageContent['content'])->guest_token;
|
||||
} catch (Exception $e) {
|
||||
$guestToken = null;
|
||||
}
|
||||
return $guestToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to make an API call to twitter.
|
||||
* @param $api string API entry point
|
||||
* @param $params array additional URI parmaeters
|
||||
* @return object json data
|
||||
*/
|
||||
private function makeApiCall($api, $params)
|
||||
{
|
||||
$uri = self::API_URI . $api . '?' . http_build_query($params);
|
||||
|
||||
$retries = 1;
|
||||
$retry = 0;
|
||||
do {
|
||||
$retry = 0;
|
||||
|
||||
try {
|
||||
$result = getContents($uri, $this->authHeaders, [], true);
|
||||
} catch (HttpException $e) {
|
||||
switch ($e->getCode()) {
|
||||
case 401:
|
||||
// fall-through
|
||||
case 403:
|
||||
if ($retries) {
|
||||
$retries--;
|
||||
$retry = 1;
|
||||
$this->getApiKey(1);
|
||||
continue 2;
|
||||
}
|
||||
// fall-through
|
||||
default:
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
} while ($retry);
|
||||
|
||||
$data = json_decode($result['content']);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue