uiharu/src/Lookup/TwitterLookup.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.');
}
}