90 lines
3.7 KiB
PHP
90 lines
3.7 KiB
PHP
<?php
|
|
namespace Uiharu\Lookup;
|
|
|
|
use RuntimeException;
|
|
use Uiharu\Config;
|
|
use Uiharu\Url;
|
|
use Index\MediaType;
|
|
|
|
final class TwitterLookup implements \Uiharu\ILookup {
|
|
private const TWITTER_DOMAINS = [
|
|
'twitter.com', 'www.twitter.com',
|
|
'm.twitter.com', 'mobile.twitter.com',
|
|
'nitter.net', 'www.nitter.net',
|
|
];
|
|
|
|
public function match(Url $url): bool {
|
|
if(!in_array($url->getHost(), self::TWITTER_DOMAINS))
|
|
return false;
|
|
|
|
return preg_match('#^/@?(?:[A-Za-z0-9_]{1,20})/status(?:es)?/([0-9]+)/?$#', $url->getPath())
|
|
|| preg_match('#^/@?([A-Za-z0-9_]{1,20})/?$#', $url->getPath());
|
|
}
|
|
|
|
private function lookupUser(string $userName): ?object {
|
|
$curl = curl_init("https://api.twitter.com/2/users/by?usernames={$userName}&user.fields=description,entities,id,name,profile_image_url,protected,url,username,verified");
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_AUTOREFERER => false,
|
|
CURLOPT_CERTINFO => false,
|
|
CURLOPT_FAILONERROR => false,
|
|
CURLOPT_FOLLOWLOCATION => false,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TCP_FASTOPEN => true,
|
|
CURLOPT_CONNECTTIMEOUT => 2,
|
|
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_USERAGENT => 'Uiharu/' . UIH_VERSION,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Authorization: Bearer ' . Config::get('Twitter', 'apiToken'),
|
|
'Accept: application/json',
|
|
],
|
|
]);
|
|
$resp = curl_exec($curl);
|
|
curl_close($curl);
|
|
return json_decode($resp);
|
|
}
|
|
|
|
private function lookupTweet(string $tweetId): ?object {
|
|
$curl = curl_init("https://api.twitter.com/2/tweets?ids={$tweetId}&expansions=attachments.media_keys,author_id,entities.mentions.username,referenced_tweets.id,referenced_tweets.id.author_id&media.fields=height,width,media_key,preview_image_url,url,type&tweet.fields=attachments,conversation_id,text,source,possibly_sensitive,created_at&user.fields=id,name,profile_image_url,protected,username,verified");
|
|
curl_setopt_array($curl, [
|
|
CURLOPT_AUTOREFERER => false,
|
|
CURLOPT_CERTINFO => false,
|
|
CURLOPT_FAILONERROR => false,
|
|
CURLOPT_FOLLOWLOCATION => false,
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TCP_FASTOPEN => true,
|
|
CURLOPT_CONNECTTIMEOUT => 2,
|
|
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
|
|
CURLOPT_TIMEOUT => 5,
|
|
CURLOPT_USERAGENT => 'Uiharu/' . UIH_VERSION,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Authorization: Bearer ' . Config::get('Twitter', 'apiToken'),
|
|
'Accept: application/json',
|
|
],
|
|
]);
|
|
$resp = curl_exec($curl);
|
|
curl_close($curl);
|
|
return json_decode($resp);
|
|
}
|
|
|
|
public function lookup(Url $url): TwitterLookupResult {
|
|
if(preg_match('#^/@?(?:[A-Za-z0-9_]{1,20})/status(?:es)?/([0-9]+)/?$#', $url->getPath(), $matches)) {
|
|
$tweetId = strval($matches[1] ?? '0');
|
|
$tweetInfo = $this->lookupTweet($tweetId);
|
|
if($tweetInfo === null)
|
|
throw new RuntimeException('Tweet lookup failed.');
|
|
return new TwitterLookupTweetResult($url, $tweetInfo);
|
|
}
|
|
|
|
if(preg_match('#^/@?([A-Za-z0-9_]{1,20})/?$#', $url->getPath(), $matches)) {
|
|
$userName = strval($matches[1] ?? '');
|
|
$userInfo = $this->lookupUser($userName);
|
|
if($userInfo === null)
|
|
throw new RuntimeException('Twitter user lookup failed.');
|
|
return new TwitterLookupUserResult($url, $userInfo);
|
|
}
|
|
|
|
throw new RuntimeException('Unknown Twitter URL format.');
|
|
}
|
|
}
|