From d9094f0d05fdc22a1adfced9b5a9e3fefb696ffb Mon Sep 17 00:00:00 2001 From: flashwave Date: Thu, 6 Jul 2023 22:53:02 +0000 Subject: [PATCH] Removed Twitter and Nitter support. It's over folks. --- lib/index | 2 +- public/index.php | 1 - src/Apis/v1_0.php | 14 -- src/Colour.php | 296 ++++++++++++------------ src/Lookup/TwitterLookup.php | 135 ----------- src/Lookup/TwitterLookupResult.php | 51 ---- src/Lookup/TwitterLookupTweetResult.php | 46 ---- src/Lookup/TwitterLookupUserResult.php | 46 ---- src/Lookup/WebLookup.php | 8 +- 9 files changed, 154 insertions(+), 445 deletions(-) delete mode 100644 src/Lookup/TwitterLookup.php delete mode 100644 src/Lookup/TwitterLookupResult.php delete mode 100644 src/Lookup/TwitterLookupTweetResult.php delete mode 100644 src/Lookup/TwitterLookupUserResult.php diff --git a/lib/index b/lib/index index bce5ba7..1cd1695 160000 --- a/lib/index +++ b/lib/index @@ -1 +1 @@ -Subproject commit bce5ba77a268ecd6338d0e3520e41ff4c40cbeda +Subproject commit 1cd1695429b5a313ac357f3f3faba365e425f504 diff --git a/public/index.php b/public/index.php index 31a4476..92353dd 100644 --- a/public/index.php +++ b/public/index.php @@ -10,7 +10,6 @@ $ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('eeprom', 'eeprom.flashii.n if(UIH_DEBUG) $ctx->registerLookup(new \Uiharu\Lookup\EEPROMLookup('devrom', 'eeprom.edgii.net', ['i.edgii.net'])); -$ctx->registerLookup(new \Uiharu\Lookup\TwitterLookup); $ctx->registerLookup(new \Uiharu\Lookup\YouTubeLookup); $ctx->registerLookup(new \Uiharu\Lookup\NicoNicoLookup); diff --git a/src/Apis/v1_0.php b/src/Apis/v1_0.php index e95cbca..b8edf93 100644 --- a/src/Apis/v1_0.php +++ b/src/Apis/v1_0.php @@ -13,9 +13,6 @@ use Uiharu\MediaTypeExts; use Uiharu\UihContext; use Uiharu\Url; use Uiharu\Lookup\EEPROMLookupResult; -use Uiharu\Lookup\TwitterLookupResult; -use Uiharu\Lookup\TwitterLookupTweetResult; -use Uiharu\Lookup\TwitterLookupUserResult; use Uiharu\Lookup\YouTubeLookupResult; use Uiharu\Lookup\NicoNicoLookupResult; use Index\MediaType; @@ -188,17 +185,6 @@ final class v1_0 implements \Uiharu\IApi { if($result->hasPreviewImage()) $resp->image = $result->getPreviewImage(); - if($result instanceof TwitterLookupResult) { - if($result instanceof TwitterLookupTweetResult) - $resp->tweet_id = $result->getTwitterTweetId(); - - if($result instanceof TwitterLookupUserResult) - $resp->twitter_user_name = $result->getTwitterUserName(); - - if(UIH_DEBUG) - $resp->dbg_twitter_info = $result->getTwitterResult(); - } - if($result instanceof YouTubeLookupResult) { $resp->youtube_video_id = $result->getYouTubeVideoId(); diff --git a/src/Colour.php b/src/Colour.php index b053ea8..0876b39 100644 --- a/src/Colour.php +++ b/src/Colour.php @@ -13,298 +13,298 @@ final class Colour { switch($input) { // CSS Level 1 - case @"black": + case "black": return self::BLACK; - case @"silver": + case "silver": return self::SILVER; - case @"gray": - case @"grey": // CSS Level 3 + case "gray": + case "grey": // CSS Level 3 return self::GREY; - case @"white": + case "white": return self::WHITE; - case @"maroon": + case "maroon": return self::MAROON; - case @"red": + case "red": return self::RED; - case @"purple": + case "purple": return self::PURPLE; - case @"fuchsia": - case @"magenta": // CSS Level 3 + case "fuchsia": + case "magenta": // CSS Level 3 return self::MAGENTA; - case @"green": + case "green": return self::GREEN; - case @"lime": + case "lime": return self::LIME; - case @"olive": + case "olive": return self::OLIVE; - case @"yellow": + case "yellow": return self::YELLOW; - case @"navy": + case "navy": return self::NAVY; - case @"blue": + case "blue": return self::BLUE; - case @"teal": + case "teal": return self::TEAL; - case @"aqua": - case @"cyan": // CSS Level 3 + case "aqua": + case "cyan": // CSS Level 3 return self::CYAN; // CSS Level 2 - case @"orange": + case "orange": return self::ORANGE; // CSS Level 3 - case @"aliceblue": + case "aliceblue": return self::ALICEBLUE; - case @"antiquewhite": + case "antiquewhite": return self::ANTIQUEWHITE; - case @"aquamarine": + case "aquamarine": return self::AQUAMARINE; - case @"azure": + case "azure": return self::AZURE; - case @"beige": + case "beige": return self::BEIGE; - case @"bisque": + case "bisque": return self::BISQUE; - case @"blanchedalmond": + case "blanchedalmond": return self::BLANCHEDALMOND; - case @"blueviolet": + case "blueviolet": return self::BLUEVIOLET; - case @"brown": + case "brown": return self::BROWN; - case @"burlywood": + case "burlywood": return self::BURLYWOOD; - case @"cadetblue": + case "cadetblue": return self::CADETBLUE; - case @"chartreuse": + case "chartreuse": return self::CHARTREUSE; - case @"chocolate": + case "chocolate": return self::CHOCOLATE; - case @"coral": + case "coral": return self::CORAL; - case @"cornflowerblue": + case "cornflowerblue": return self::CORNFLOWERBLUE; - case @"cornsilk": + case "cornsilk": return self::CORNSILK; - case @"crimson": + case "crimson": return self::CRIMSON; - case @"darkblue": + case "darkblue": return self::DARKBLUE; - case @"darkcyan": + case "darkcyan": return self::DARKCYAN; - case @"darkgoldenrod": + case "darkgoldenrod": return self::DARKGOLDENROD; - case @"darkgrey": - case @"darkgray": + case "darkgrey": + case "darkgray": return self::DARKGREY; - case @"darkgreen": + case "darkgreen": return self::DARKGREEN; - case @"darkkhaki": + case "darkkhaki": return self::DARKKHAKI; - case @"darkmagenta": + case "darkmagenta": return self::DARKMAGENTA; - case @"darkolivegreen": + case "darkolivegreen": return self::DARKOLIVEGREEN; - case @"darkorange": + case "darkorange": return self::DARKORANGE; - case @"darkorchid": + case "darkorchid": return self::DARKORCHID; - case @"darkred": + case "darkred": return self::DARKRED; - case @"darksalmon": + case "darksalmon": return self::DARKSALMON; - case @"darkseagreen": + case "darkseagreen": return self::DARKSEAGREEN; - case @"darkslateblue": + case "darkslateblue": return self::DARKSLATEBLUE; - case @"darkslategrey": - case @"darkslategray": + case "darkslategrey": + case "darkslategray": return self::DARKSLATEGREY; - case @"darkturquoise": + case "darkturquoise": return self::DARKTURQUOISE; - case @"darkviolet": + case "darkviolet": return self::DARKVIOLET; - case @"deeppink": + case "deeppink": return self::DEEPPINK; - case @"deepskyblue": + case "deepskyblue": return self::DEEPSKYBLUE; - case @"dimgray": - case @"dimgrey": + case "dimgray": + case "dimgrey": return self::DIMGREY; - case @"dodgerblue": + case "dodgerblue": return DodgerBluself::DODGERBLUE; - case @"firebrick": + case "firebrick": return self::FIREBRICK; - case @"floralwhite": + case "floralwhite": return self::FLORALWHITE; - case @"forestgreen": + case "forestgreen": return self::FORESTGREEN; - case @"gainsboro": + case "gainsboro": return self::GAINSBORO; - case @"ghostwhite": + case "ghostwhite": return self::GHOSTWHITE; - case @"gold": + case "gold": return self::GOLD; - case @"goldenrod": + case "goldenrod": return self::GOLDENROD; - case @"greenyellow": + case "greenyellow": return self::GREENYELLOW; - case @"honeydew": + case "honeydew": return self::HONEYDEW; - case @"hotpink": + case "hotpink": return self::HOTPINK; - case @"indianred": + case "indianred": return self::INDIANRED; - case @"indigo": + case "indigo": return self::INDIGO; - case @"ivory": + case "ivory": return self::IVORY; - case @"khaki": + case "khaki": return self::KHAKI; - case @"lavender": + case "lavender": return self::LAVENDER; - case @"lavenderblush": + case "lavenderblush": return self::LAVENDERBLUSH; - case @"lawngreen": + case "lawngreen": return self::LAWNGREEN; - case @"lemonchiffon": + case "lemonchiffon": return self::LEMONCHIFFON; - case @"lightblue": + case "lightblue": return self::LIGHTBLUE; - case @"lightcoral": + case "lightcoral": return self::LIGHTCORAL; - case @"lightcyan": + case "lightcyan": return self::LIGHTCYAN; - case @"lightgoldenrodyellow": + case "lightgoldenrodyellow": return self::LIGHTGOLDENRODYELLOW; - case @"lightgray": - case @"lightgrey": + case "lightgray": + case "lightgrey": return self::LIGHTGREY; - case @"lightgreen": + case "lightgreen": return self::LIGHTGREEN; - case @"lightpink": + case "lightpink": return self::LIGHTPINK; - case @"lightsalmon": + case "lightsalmon": return self::LIGHTSALMON; - case @"lightseagreen": + case "lightseagreen": return self::LIGHTSEAGREEN; - case @"lightskyblue": + case "lightskyblue": return self::LIGHTSEAGREEN; - case @"lightslategray": - case @"lightslategrey": + case "lightslategray": + case "lightslategrey": return self::LIGHTSLATEGREY; - case @"lightsteelblue": + case "lightsteelblue": return self::LIGHTSTEELBLUE; - case @"lightyellow": + case "lightyellow": return self::LIGHTYELLOW; - case @"limegreen": + case "limegreen": return self::LIMEGREEN; - case @"linen": + case "linen": return self::LINEN; - case @"mediumaquamarine": + case "mediumaquamarine": return self::MEDIUMAQUAMARINE; - case @"mediumblue": + case "mediumblue": return self::MEDIUMBLUE; - case @"mediumorchid": + case "mediumorchid": return self::MEDIUMORCHID; - case @"mediumpurple": + case "mediumpurple": return self::MEDIUMPURPLE; - case @"mediumseagreen": + case "mediumseagreen": return self::MEDIUMSEAGREEN; - case @"mediumslateblue": + case "mediumslateblue": return self::MEDIUMSLATEBLUE; - case @"mediumspringgreen": + case "mediumspringgreen": return self::MEDIUMSPRINGGREEN; - case @"mediumturquoise": + case "mediumturquoise": return self::MEDIUMTURQUOISE; - case @"mediumvioletred": + case "mediumvioletred": return self::MEDIUMVIOLETRED; - case @"midnightblue": + case "midnightblue": return self::MIDNIGHTBLUE; - case @"mintcream": + case "mintcream": return self::MINTCREAM; - case @"mistyrose": + case "mistyrose": return self::MISTYROSE; - case @"moccasin": + case "moccasin": return self::MOCCASIN; - case @"navajowhite": + case "navajowhite": return self::NAVAJOWHITE; - case @"oldlace": + case "oldlace": return self::OLDLACE; - case @"olivedrab": + case "olivedrab": return self::OLIVEDRAB; - case @"orangered": + case "orangered": return self::ORANGERED; - case @"orchid": + case "orchid": return self::ORCHID; - case @"palegoldenrod": + case "palegoldenrod": return self::PALEGOLDENROD; - case @"palegreen": + case "palegreen": return self::PALEGREEN; - case @"paleturquoise": + case "paleturquoise": return self::PALETURQUOISE; - case @"palevioletred": + case "palevioletred": return self::PALEVIOLETRED; - case @"papayawhip": + case "papayawhip": return self::PAPAYAWHIP; - case @"peachpuff": + case "peachpuff": return self::PEACHPUFF; - case @"peru": + case "peru": return self::PERU; - case @"pink": + case "pink": return self::PINK; - case @"plum": + case "plum": return self::PLUM; - case @"powderblue": + case "powderblue": return self::POWDERBLUE; - case @"rosybrown": + case "rosybrown": return self::ROSYBROWN; - case @"royalblue": + case "royalblue": return self::ROYALBLUE; - case @"saddlebrown": + case "saddlebrown": return self::SADDLEBROWN; - case @"salmon": + case "salmon": return self::SALMON; - case @"sandybrown": + case "sandybrown": return self::SANDYBROWN; - case @"seagreen": + case "seagreen": return self::SEAGREEN; - case @"seashell": + case "seashell": return self::SEASHELL; - case @"sienna": + case "sienna": return self::SIENNA; - case @"skyblue": + case "skyblue": return self::SKYBLUE; - case @"slateblue": + case "slateblue": return self::SLATEBLUE; - case @"slategray": - case @"slategrey": + case "slategray": + case "slategrey": return self::SLATEGREY; - case @"snow": + case "snow": return self::SNOW; - case @"springgreen": + case "springgreen": return self::SPRINGGREEN; - case @"steelblue": + case "steelblue": return self::STEELBLUE; - case @"tan": + case "tan": return self::TAN; - case @"thistle": + case "thistle": return self::THISTLE; - case @"tomato": + case "tomato": return self::TOMATO; - case @"turquoise": + case "turquoise": return self::TURQUOISE; - case @"violet": + case "violet": return self::VIOLET; - case @"wheat": + case "wheat": return self::WHEAT; - case @"whitesmoke": + case "whitesmoke": return self::WHITESMOKE; - case @"yellowgreen": + case "yellowgreen": return self::YELLOWGREEN; // CSS Level 4 - case @"rebeccapurple": + case "rebeccapurple": return self::REBECCAPURPLE; } diff --git a/src/Lookup/TwitterLookup.php b/src/Lookup/TwitterLookup.php deleted file mode 100644 index 373c48f..0000000 --- a/src/Lookup/TwitterLookup.php +++ /dev/null @@ -1,135 +0,0 @@ -isWeb() || !in_array(strtolower($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 getString(string $path): string { - $curl = curl_init(Config::get('Nitter', 'endpoint') . $path); - 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, - ]); - $resp = curl_exec($curl); - curl_close($curl); - return $resp; - } - - private function getDocument(string $path): DOMDocument { - $string = $this->getString($path); - if(empty($string)) - throw new RuntimeException('Failed to download Nitter page.'); - - return (new HTML5)->loadHTML($string); - } - - private static function convertNitterMediaURL(string $path): string { - if($path === '') - return $path; - - [,,$url] = explode('/', $path); - $url = rawurldecode($url); - - if(!str_starts_with($url, 'pbs.twimg.com')) - $url = 'pbs.twimg.com/' . str_replace('_bigger', '', $url); - - return 'https://' . $url; - } - - private function lookupUser(string $userName): ?object { - $document = $this->getDocument("/{$userName}"); - $xpath = new DOMXpath($document); - - $out = new stdClass; - - $userNameElems = $xpath->query('//*[@class="profile-card-username"]'); - $out->userName = $userNameElems->length < 1 ? '' : trim($userNameElems[0]->textContent); - - $profileNameElems = $xpath->query('//*[@class="profile-card-fullname"]'); - $out->profileName = $profileNameElems->length < 1 ? '' : trim($profileNameElems[0]->textContent); - - $profileBioElems = $xpath->query('//*[@class="profile-bio"]/*'); - $out->profileBio = $profileBioElems->length < 1 ? '' : trim($profileBioElems[0]->textContent); - - $profilePictureElems = $xpath->query('//*[@class="profile-card-avatar"]'); - $out->profilePicture = $profilePictureElems->length < 1 ? '' : $profilePictureElems[0]->getAttribute('href'); - $out->profilePicture = self::convertNitterMediaURL($out->profilePicture); - - return $out; - } - - private function lookupTweet(string $tweetId): ?object { - $document = $this->getDocument("/i/status/{$tweetId}"); - $xpath = new DOMXpath($document); - - $out = new stdClass; - - $tweetDateElems = $xpath->query('//*[@class="tweet-date"]/*'); - $out->tweetId = $tweetDateElems->length < 1 ? '' : trim($tweetDateElems[0]->getAttribute('href')); - if($out->tweetId !== '') { - [,,,$out->tweetId] = explode('/', $out->tweetId); - [$out->tweetId] = explode('#', $out->tweetId); - } - - $tweetTextElems = $xpath->query('//*[@class="tweet-content media-body"]'); - $out->tweetText = $tweetTextElems->length < 1 ? '' : trim($tweetTextElems[0]->textContent); - - $profileNameElems = $xpath->query('//*[@class="fullname"]'); - $out->profileName = $profileNameElems->length < 1 ? '' : trim($profileNameElems[0]->textContent); - - $profilePictureElems = $xpath->query('//*[@class="tweet-avatar"]/*'); - $out->profilePicture = $profilePictureElems->length < 1 ? '' : $profilePictureElems[0]->getAttribute('src'); - $out->profilePicture = self::convertNitterMediaURL($out->profilePicture); - - return $out; - } - - 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.'); - } -} diff --git a/src/Lookup/TwitterLookupResult.php b/src/Lookup/TwitterLookupResult.php deleted file mode 100644 index 3b1db64..0000000 --- a/src/Lookup/TwitterLookupResult.php +++ /dev/null @@ -1,51 +0,0 @@ -url = $url; - } - - public function getUrl(): Url { - return $this->url; - } - public abstract function getObjectType(): string; - - public function hasMediaType(): bool { - return false; - } - public function getMediaType(): MediaType { - throw new RuntimeException('Unsupported'); - } - - public function hasColour(): bool { - return true; - } - public function getColour(): int { - return 0x1DA1F2; - } - - public abstract function hasTitle(): bool; - public abstract function getTitle(): string; - - public function hasSiteName(): bool { - return true; - } - public function getSiteName(): string { - return 'Twitter'; - } - - public abstract function hasDescription(): bool; - public abstract function getDescription(): string; - - public abstract function hasPreviewImage(): bool; - public abstract function getPreviewImage(): string; - - public abstract function getTwitterResult(): object; -} diff --git a/src/Lookup/TwitterLookupTweetResult.php b/src/Lookup/TwitterLookupTweetResult.php deleted file mode 100644 index 9837f4f..0000000 --- a/src/Lookup/TwitterLookupTweetResult.php +++ /dev/null @@ -1,46 +0,0 @@ -tweetInfo = $tweetInfo; - } - - public function getObjectType(): string { - return 'twitter:tweet'; - } - - public function getTwitterTweetId(): string { - return $this->tweetInfo->tweetId; - } - - public function hasTitle(): bool { - return $this->tweetInfo->profileName !== ''; - } - public function getTitle(): string { - return $this->tweetInfo->profileName; - } - - public function hasDescription(): bool { - return $this->tweetInfo->tweetText !== ''; - } - public function getDescription(): string { - return $this->tweetInfo->tweetText; - } - - public function hasPreviewImage(): bool { - return $this->tweetInfo->profilePicture !== ''; - } - public function getPreviewImage(): string { - return $this->tweetInfo->profilePicture; - } - - public function getTwitterResult(): object { - return $this->tweetInfo; - } -} diff --git a/src/Lookup/TwitterLookupUserResult.php b/src/Lookup/TwitterLookupUserResult.php deleted file mode 100644 index 92aac15..0000000 --- a/src/Lookup/TwitterLookupUserResult.php +++ /dev/null @@ -1,46 +0,0 @@ -userInfo = $userInfo; - } - - public function getObjectType(): string { - return 'twitter:user'; - } - - public function getTwitterUserName(): string { - return $this->userInfo->userName; - } - - public function hasTitle(): bool { - return $this->userInfo->profileName !== ''; - } - public function getTitle(): string { - return $this->userInfo->profileName; - } - - public function hasDescription(): bool { - return $this->userInfo->profileBio !== ''; - } - public function getDescription(): string { - return $this->userInfo->profileBio; - } - - public function hasPreviewImage(): bool { - return $this->userInfo->profilePicture !== ''; - } - public function getPreviewImage(): string { - return $this->userInfo->profilePicture; - } - - public function getTwitterResult(): object { - return $this->userInfo; - } -} diff --git a/src/Lookup/WebLookup.php b/src/Lookup/WebLookup.php index dd3a999..731f4b7 100644 --- a/src/Lookup/WebLookup.php +++ b/src/Lookup/WebLookup.php @@ -32,7 +32,7 @@ final class WebLookup implements \Uiharu\ILookup { CURLOPT_REDIR_PROTOCOLS => CURLPROTO_HTTP | CURLPROTO_HTTPS, CURLOPT_TIMEOUT => 5, CURLOPT_DEFAULT_PROTOCOL => 'https', - CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible) Uiharu/' . UIH_VERSION, + CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; FlashiiBot/2.5; Uiharu/' . UIH_VERSION . '; +http://fii.moe/uiharu)', CURLOPT_HTTPHEADER => [ 'Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8', ], @@ -200,11 +200,13 @@ final class WebLookup implements \Uiharu\ILookup { break; case 'theme-color': - $siteInfo->colour = $valueAttr; + if(empty($siteInfo->colour)) + $siteInfo->colour = $valueAttr; break; case 'og:type': - $siteInfo->type = 'website:' . $valueAttr; + if(empty($siteInfo->type)) + $siteInfo->type = 'website:' . $valueAttr; break; } }