231 lines
9.0 KiB
PHP
231 lines
9.0 KiB
PHP
<?php
|
|
namespace Uiharu\APIs;
|
|
|
|
use stdClass;
|
|
use DOMDocument;
|
|
use Exception;
|
|
use InvalidArgumentException;
|
|
use Uiharu\Colour;
|
|
use Uiharu\Config;
|
|
use Uiharu\FFMPEG;
|
|
use Uiharu\IHasMediaInfo;
|
|
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 Index\MediaType;
|
|
use Index\Data\IDbConnection;
|
|
use Index\Http\HttpFx;
|
|
use Index\Performance\Stopwatch;
|
|
|
|
final class v1_0 implements \Uiharu\IApi {
|
|
private UihContext $ctx;
|
|
private IDbConnection $db;
|
|
|
|
public function __construct(UihContext $ctx) {
|
|
$this->ctx = $ctx;
|
|
$this->db = $ctx->getDatabase();
|
|
}
|
|
|
|
public function match(string $url): string {
|
|
return !str_starts_with($url, '/v');
|
|
}
|
|
|
|
public function register(HttpFx $router): void {
|
|
$router->get('/metadata', [$this, 'handleGET']);
|
|
$router->post('/metadata', [$this, 'handlePOST']);
|
|
}
|
|
|
|
public function handleGET($response, $request) {
|
|
if($request->getMethod() === 'HEAD') {
|
|
$response->setTypeJson();
|
|
return;
|
|
}
|
|
|
|
return $this->handler(
|
|
$response, $request,
|
|
(string)$request->getParam('url')
|
|
);
|
|
}
|
|
|
|
public function handlePOST($response, $request) {
|
|
if(!$request->isStreamContent())
|
|
return 400;
|
|
|
|
return $this->handler(
|
|
$response, $request,
|
|
$request->getContent()->getStream()->read(1000)
|
|
);
|
|
}
|
|
|
|
private function handler($response, $request, string $targetUrl) {
|
|
$sw = Stopwatch::startNew();
|
|
|
|
$resp = new stdClass;
|
|
$response->setTypeJson();
|
|
|
|
if(empty($targetUrl)) {
|
|
$response->setStatusCode(400);
|
|
return $resp;
|
|
}
|
|
|
|
try {
|
|
$parsedUrl = Url::parse($targetUrl);
|
|
} catch(InvalidArgumentException $ex) {
|
|
$response->setStatusCode(400);
|
|
$resp->error = 'metadata:uri';
|
|
return $resp;
|
|
}
|
|
|
|
// if no scheme is specified, try https
|
|
if(!$parsedUrl->hasScheme())
|
|
$parsedUrl->setScheme('https');
|
|
|
|
$resp->uri = $parsedUrl->toV1();
|
|
|
|
$urlHash = $parsedUrl->calculateHash(false);
|
|
|
|
$enableCache = !UIH_DEBUG || $request->hasParam('_cache');
|
|
$includeRawResult = UIH_DEBUG || $request->hasParam('include_raw');
|
|
|
|
if($enableCache) {
|
|
$cacheFetch = $this->db->prepare('SELECT `metadata_resp` FROM `uih_metadata_cache` WHERE `metadata_url` = UNHEX(?) AND `metadata_created` > NOW() - INTERVAL 10 MINUTE');
|
|
$cacheFetch->addParameter(1, $urlHash);
|
|
$cacheFetch->execute();
|
|
$cacheResult = $cacheFetch->getResult();
|
|
if($cacheResult->next()) {
|
|
$cacheResp = json_decode($cacheResult->getString(0));
|
|
if($cacheResp !== null)
|
|
$resp = $cacheResp;
|
|
}
|
|
}
|
|
|
|
if(empty($resp->type)) {
|
|
$lookup = $this->ctx->matchLookup($parsedUrl);
|
|
|
|
if($lookup !== null)
|
|
try {
|
|
$result = $lookup->lookup($parsedUrl);
|
|
|
|
$resp->uri = $result->getUrl()->toV1();
|
|
$resp->type = $result->getObjectType();
|
|
|
|
if($result->hasMediaType())
|
|
$resp->content_type = MediaTypeExts::toV1($result->getMediaType());
|
|
if($result->hasColour())
|
|
$resp->color = Colour::toHexString($result->getColour());
|
|
if($result->hasTitle())
|
|
$resp->title = $result->getTitle();
|
|
if($result->hasSiteName())
|
|
$resp->site_name = $result->getSiteName();
|
|
if($result->hasDescription())
|
|
$resp->description = $result->getDescription();
|
|
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();
|
|
|
|
if($result->hasYouTubeVideoStartTime())
|
|
$resp->youtube_start_time = $result->getYouTubeVideoStartTime();
|
|
if($result->hasYouTubePlayListId())
|
|
$resp->youtube_playlist = $result->getYouTubePlayListId();
|
|
if($result->hasYouTubePlayListIndex())
|
|
$resp->youtube_playlist_index = $result->getYouTubePlayListIndex();
|
|
|
|
if(UIH_DEBUG) {
|
|
$resp->dbg_youtube_info = $result->getYouTubeVideoInfo();
|
|
$resp->dbg_youtube_query = $result->getYouTubeUrlQuery();
|
|
}
|
|
}
|
|
|
|
if($result instanceof IHasMediaInfo) {
|
|
if($result->isMedia()) {
|
|
$resp->is_image = $result->isImage();
|
|
$resp->is_audio = $result->isAudio();
|
|
$resp->is_video = $result->isVideo();
|
|
|
|
if($result->hasDimensions()) {
|
|
$resp->width = $result->getWidth();
|
|
$resp->height = $result->getHeight();
|
|
}
|
|
|
|
$resp->media = new stdClass;
|
|
$resp->media->confidence = $result->getConfidence();
|
|
|
|
if($result->hasAspectRatio())
|
|
$resp->media->aspect_ratio = $result->getAspectRatio();
|
|
if($result->hasDuration())
|
|
$resp->media->duration = $result->getDuration();
|
|
if($result->hasSize())
|
|
$resp->media->size = $result->getSize();
|
|
if($result->hasBitRate())
|
|
$resp->media->bitrate = $result->getBitRate();
|
|
|
|
if($result->hasAudioTags()) {
|
|
$audioTags = $result->getAudioTags();
|
|
$resp->media->tags = new stdClass;
|
|
if($audioTags->hasTitle())
|
|
$resp->media->tags->title = $audioTags->getTitle();
|
|
if($audioTags->hasArtist())
|
|
$resp->media->tags->artist = $audioTags->getArtist();
|
|
if($audioTags->hasAlbum())
|
|
$resp->media->tags->album = $audioTags->getAlbum();
|
|
if($audioTags->hasDate())
|
|
$resp->media->tags->date = $audioTags->getDate();
|
|
if($audioTags->hasComment())
|
|
$resp->media->tags->comment = $audioTags->getComment();
|
|
if($audioTags->hasGenre())
|
|
$resp->media->tags->genre = $audioTags->getGenre();
|
|
}
|
|
}
|
|
|
|
if($result instanceof EEPROMLookupResult) {
|
|
$resp->eeprom_file_id = $result->getEEPROMId();
|
|
$resp->eeprom_file_info = $result->getEEPROMInfo();
|
|
}
|
|
|
|
if(UIH_DEBUG && $result->hasMediaInfo())
|
|
$resp->dbg_media_info = $result->getMediaInfo();
|
|
}
|
|
} catch(Exception $ex) {
|
|
$resp->error = 'metadata:lookup';
|
|
if(UIH_DEBUG) {
|
|
$resp->dbg_msg = $ex->getMessage();
|
|
$resp->dbg_ex = (string)$ex;
|
|
}
|
|
$response->setStatusCode(500);
|
|
return $resp;
|
|
}
|
|
|
|
$sw->stop();
|
|
$resp->took = $sw->getElapsedTime() / 1000;
|
|
$respJson = json_encode($resp);
|
|
$replaceCache = $this->db->prepare('REPLACE INTO `uih_metadata_cache` (`metadata_url`, `metadata_resp`) VALUES (UNHEX(?), ?)');
|
|
$replaceCache->addParameter(1, $urlHash);
|
|
$replaceCache->addParameter(2, $respJson);
|
|
$replaceCache->execute();
|
|
}
|
|
|
|
if(!empty($respJson))
|
|
$response->setContent($respJson);
|
|
else
|
|
return $resp;
|
|
}
|
|
}
|