feat(*.php, *.psql): deduplicate API code + performance improvements

This commit is contained in:
Cory Dransfeldt 2025-04-22 12:39:42 -07:00
parent cf3dac8a46
commit 4bad005e58
No known key found for this signature in database
31 changed files with 502 additions and 666 deletions

View file

@ -7,9 +7,6 @@ use GuzzleHttp\Client;
class WatchingImportHandler extends ApiHandler
{
protected string $postgrestUrl;
protected string $postgrestApiKey;
private string $tmdbApiKey;
private string $tmdbImportToken;
@ -17,17 +14,9 @@ class WatchingImportHandler extends ApiHandler
{
parent::__construct();
$this->ensureCliAccess();
$this->loadEnvironment();
}
private function loadEnvironment(): void
{
$this->postgrestUrl = $_ENV["POSTGREST_URL"] ?? getenv("POSTGREST_URL");
$this->postgrestApiKey =
$_ENV["POSTGREST_API_KEY"] ?? getenv("POSTGREST_API_KEY");
$this->tmdbApiKey = $_ENV["TMDB_API_KEY"] ?? getenv("TMDB_API_KEY");
$this->tmdbImportToken =
$_ENV["WATCHING_IMPORT_TOKEN"] ?? getenv("WATCHING_IMPORT_TOKEN");
$this->tmdbImportToken = $_ENV["WATCHING_IMPORT_TOKEN"] ?? getenv("WATCHING_IMPORT_TOKEN");
}
public function handleRequest(): void
@ -37,19 +26,22 @@ class WatchingImportHandler extends ApiHandler
if (!$input) $this->sendErrorResponse("Invalid or missing JSON body", 400);
$providedToken = $input["token"] ?? null;
if (!$providedToken || $providedToken !== $this->tmdbImportToken) $this->sendErrorResponse("Unauthorized access", 401);
$tmdbId = $input["tmdb_id"] ?? null;
$mediaType = $input["media_type"] ?? null;
if (!$tmdbId || !$mediaType) $this->sendErrorResponse("tmdb_id and media_type are required", 400);
if ($providedToken !== $this->tmdbImportToken) {
$this->sendErrorResponse("Unauthorized access", 401);
}
if (!$tmdbId || !$mediaType) {
$this->sendErrorResponse("tmdb_id and media_type are required", 400);
}
try {
$mediaData = $this->fetchTMDBData($tmdbId, $mediaType);
$this->processMedia($mediaData, $mediaType);
$this->sendResponse("Media imported successfully", 200);
} catch (Exception $e) {
$this->sendResponse(["message" => "Media imported successfully"], 200);
} catch (\Exception $e) {
$this->sendErrorResponse("Error: " . $e->getMessage(), 500);
}
}
@ -65,8 +57,7 @@ class WatchingImportHandler extends ApiHandler
]);
$data = json_decode($response->getBody(), true);
if (empty($data)) throw new Exception("No data found for TMDB ID: {$tmdbId}");
if (empty($data)) throw new \Exception("No data found for TMDB ID: {$tmdbId}");
return $data;
}
@ -75,18 +66,19 @@ class WatchingImportHandler extends ApiHandler
{
$id = $mediaData["id"];
$title = $mediaType === "movie" ? $mediaData["title"] : $mediaData["name"];
$year =
$mediaData["release_date"] ?? ($mediaData["first_air_date"] ?? null);
$year = $mediaData["release_date"] ?? $mediaData["first_air_date"] ?? null;
$year = $year ? substr($year, 0, 4) : null;
$description = $mediaData["overview"] ?? "";
$tags = array_map(
fn($genre) => strtolower(trim($genre["name"])),
$mediaData["genres"]
$mediaData["genres"] ?? []
);
$slug =
$mediaType === "movie"
? "/watching/movies/{$id}"
: "/watching/shows/{$id}";
$slug = $mediaType === "movie"
? "/watching/movies/{$id}"
: "/watching/shows/{$id}";
$payload = [
"title" => $title,
"year" => $year,
@ -94,80 +86,64 @@ class WatchingImportHandler extends ApiHandler
"tmdb_id" => $id,
"slug" => $slug,
];
$response = $this->fetchFromPostgREST(
$mediaType === "movie" ? "movies" : "shows",
"",
"POST",
$payload
);
if (empty($response["id"])) {
$queryResponse = $this->fetchFromPostgREST(
$mediaType === "movie" ? "movies" : "shows",
"tmdb_id=eq.{$id}",
"GET"
);
$response = $queryResponse[0] ?? [];
$table = $mediaType === "movie" ? "movies" : "shows";
try {
$response = $this->makeRequest("POST", $table, ["json" => $payload]);
} catch (\Exception $e) {
$response = $this->fetchFromApi($table, "tmdb_id=eq.{$id}")[0] ?? [];
}
if (!empty($response["id"])) {
$mediaId = $response["id"];
$existingTagMap = $this->getTagIds($tags);
$updatedTagMap = $this->insertMissingTags($tags, $existingTagMap);
$this->associateTagsWithMedia(
$mediaType,
$mediaId,
array_values($updatedTagMap)
);
$this->associateTagsWithMedia($mediaType, $mediaId, array_values($updatedTagMap));
}
}
private function getTagIds(array $tags): array
{
$existingTagMap = [];
$map = [];
foreach ($tags as $tag) {
$query = "name=ilike." . urlencode($tag);
$existingTags = $this->fetchFromPostgREST("tags", $query, "GET");
if (!empty($existingTags[0]["id"])) $existingTagMap[strtolower($tag)] = $existingTags[0]["id"];
}
return $existingTagMap;
}
private function insertMissingTags(array $tags, array $existingTagMap): array
{
$newTags = array_diff($tags, array_keys($existingTagMap));
foreach ($newTags as $newTag) {
try {
$response = $this->fetchFromPostgREST("tags", "", "POST", [
"name" => $newTag,
]);
if (!empty($response["id"])) $existingTagMap[$newTag] = $response["id"];
} catch (Exception $e) {
$queryResponse = $this->fetchFromPostgREST(
"tags",
"name=eq.{$newTag}",
"GET"
);
if (!empty($queryResponse[0]["id"])) $existingTagMap[$newTag] = $queryResponse[0]["id"];
$response = $this->fetchFromApi("tags", "name=ilike." . urlencode($tag));
if (!empty($response[0]["id"])) {
$map[strtolower($tag)] = $response[0]["id"];
}
}
return $existingTagMap;
return $map;
}
private function associateTagsWithMedia(
string $mediaType,
int $mediaId,
array $tagIds
): void {
$junctionTable = $mediaType === "movie" ? "movies_tags" : "shows_tags";
private function insertMissingTags(array $tags, array $existingMap): array
{
$newTags = array_diff($tags, array_keys($existingMap));
foreach ($newTags as $tag) {
try {
$created = $this->makeRequest("POST", "tags", ["json" => ["name" => $tag]]);
if (!empty($created["id"])) $existingMap[$tag] = $created["id"];
} catch (\Exception $e) {
$fallback = $this->fetchFromApi("tags", "name=eq." . urlencode($tag));
if (!empty($fallback[0]["id"])) $existingMap[$tag] = $fallback[0]["id"];
}
}
return $existingMap;
}
private function associateTagsWithMedia(string $mediaType, int $mediaId, array $tagIds): void
{
$junction = $mediaType === "movie" ? "movies_tags" : "shows_tags";
$mediaColumn = $mediaType === "movie" ? "movies_id" : "shows_id";
foreach ($tagIds as $tagId) {
$this->fetchFromPostgREST($junctionTable, "", "POST", [
$this->makeRequest("POST", $junction, ["json" => [
$mediaColumn => $mediaId,
"tags_id" => $tagId,
]);
"tags_id" => $tagId
]]);
}
}
}