diff --git a/app/Controllers/AdultController.php b/app/Controllers/AdultController.php index a9ae961..cfbf93b 100644 --- a/app/Controllers/AdultController.php +++ b/app/Controllers/AdultController.php @@ -34,6 +34,30 @@ class AdultController extends Controller // Get adult videos with pagination and search $adultVideos = AdultVideo::getAllWithPagination($this->pdo, $page, $perPage, $search); + // Process metadata to extract local image paths for template compatibility + foreach ($adultVideos as &$video) { + if (!empty($video['metadata'])) { + $metadata = json_decode($video['metadata'], true); + + // Use local cover path if available, otherwise fall back to original URL + if (!empty($metadata['local_cover_path'])) { + $video['poster_url'] = '/public/images/'.$metadata['local_cover_path']; + } elseif (!empty($metadata['cover_url'])) { + $video['poster_url'] = $metadata['cover_url']; + } + + // Add other local paths if needed + if (!empty($metadata['local_screenshot_path'])) { + $video['screenshot_url'] = $metadata['local_screenshot_path']; + } + + // Add actors data if available + if (!empty($metadata['actors'])) { + $video['actors'] = $metadata['actors']; + } + } + } + // Get total count for pagination $totalCount = AdultVideo::getTotalCount($this->pdo, $search); @@ -82,6 +106,17 @@ class AdultController extends Controller // Decode metadata for display $metadata = json_decode($adultVideo['metadata'], true); + // Add local image paths to the video data for template compatibility + if (!empty($metadata['local_cover_path'])) { + $adultVideo['poster_url'] = '/public/images/'.$metadata['local_cover_path']; + } elseif (!empty($metadata['cover_url'])) { + $adultVideo['poster_url'] = $metadata['cover_url']; + } + + if (!empty($metadata['local_screenshot_path'])) { + $adultVideo['screenshot_url'] = '/public/images/'.$metadata['local_screenshot_path']; + } + return $this->view->render($response, 'adult/show.twig', [ 'title' => $adultVideo['title'], 'movie' => $adultVideo, // Keep same variable name for template compatibility diff --git a/app/Services/StashSyncService.php b/app/Services/StashSyncService.php index 3e65ee3..15917aa 100644 --- a/app/Services/StashSyncService.php +++ b/app/Services/StashSyncService.php @@ -21,16 +21,21 @@ class StashSyncService extends BaseSyncService public function __construct(PDO $pdo, array $source) { parent::__construct($pdo, $source); + + // Initialize properties first before using them + $this->apiKey = $source['api_key']; + $this->baseUrl = rtrim($source['api_url'], '/'); + $this->httpClient = new Client([ 'timeout' => 60, // Stash can be slow 'headers' => [ 'User-Agent' => 'MediaCollector/1.0', - 'Content-Type' => 'application/json' + 'Content-Type' => 'application/json', + 'ApiKey' => $this->apiKey // Now safe to access ] ]); - $this->apiKey = $source['api_key']; - $this->baseUrl = rtrim($source['api_url'], '/'); - $this->imageDownloader = new ImageDownloader(); + + $this->imageDownloader = new ImageDownloader('public/images', $this->apiKey); } protected function executeSync(string $syncType): void @@ -282,12 +287,24 @@ class StashSyncService extends BaseSyncService // Stash provides paths.screenshot for screenshot if (!empty($sceneData['paths']['screenshot'])) { - // Convert relative path to full URL - $screenshotUrl = "{$this->baseUrl}/" . ltrim($sceneData['paths']['screenshot'], '/'); + $screenshotPath = $sceneData['paths']['screenshot']; + + // Handle different path formats from Stash + if (strpos($screenshotPath, 'http') === 0) { + // Already a full URL + $screenshotUrl = $screenshotPath; + } elseif (strpos($screenshotPath, '/') === 0) { + // Absolute path from Stash root + $screenshotUrl = "{$this->baseUrl}" . $screenshotPath; + } else { + // Relative path - assume it's in a standard location + $screenshotUrl = "{$this->baseUrl}/scene/" . $sceneData['id'] . "/" . $screenshotPath; + } + + $this->logProgress("Screenshot URL: " . $screenshotUrl); } - // For cover, we might need to use a different approach or check if there's a primary image - // For now, we'll use the screenshot as cover if available + // For cover, we'll use the screenshot as cover if available if ($screenshotUrl) { $coverUrl = $screenshotUrl; } @@ -297,6 +314,9 @@ class StashSyncService extends BaseSyncService $localCoverPath = $this->imageDownloader->downloadImage($coverUrl, $coverFilename, 'adult_videos'); if ($localCoverPath) { $sceneData['local_cover_path'] = $this->imageDownloader->getPublicUrl($localCoverPath); + $this->logProgress("Downloaded cover: " . $localCoverPath); + } else { + $this->logProgress("Failed to download cover from: " . $coverUrl); } } @@ -305,6 +325,9 @@ class StashSyncService extends BaseSyncService $localScreenshotPath = $this->imageDownloader->downloadImage($screenshotUrl, $screenshotFilename, 'adult_videos'); if ($localScreenshotPath) { $sceneData['local_screenshot_path'] = $this->imageDownloader->getPublicUrl($localScreenshotPath); + $this->logProgress("Downloaded screenshot: " . $localScreenshotPath); + } else { + $this->logProgress("Failed to download screenshot from: " . $screenshotUrl); } } @@ -434,11 +457,26 @@ class StashSyncService extends BaseSyncService // Try to download performer image if available $thumbnailPath = null; if ($imagePath) { - $imageUrl = "{$this->baseUrl}/" . ltrim($imagePath, '/'); + // Handle different image path formats from Stash + if (strpos($imagePath, 'http') === 0) { + // Already a full URL + $imageUrl = $imagePath; + } elseif (strpos($imagePath, '/') === 0) { + // Absolute path from Stash root + $imageUrl = "{$this->baseUrl}" . $imagePath; + } else { + // Relative path - assume it's in performer images directory + $imageUrl = "{$this->baseUrl}/performer/" . $imagePath; + } + + $this->logProgress("Performer image URL for {$name}: " . $imageUrl); $thumbnailFilename = $this->imageDownloader->generateFilename($imageUrl, 'actor'); $localImagePath = $this->imageDownloader->downloadImage($imageUrl, $thumbnailFilename, 'actors'); if ($localImagePath) { $thumbnailPath = $this->imageDownloader->getPublicUrl($localImagePath); + $this->logProgress("Downloaded performer image: " . $localImagePath); + } else { + $this->logProgress("Failed to download performer image from: " . $imageUrl); } } diff --git a/app/Services/XbvrSyncService.php b/app/Services/XbvrSyncService.php index 22f5a7c..a88f8e9 100644 --- a/app/Services/XbvrSyncService.php +++ b/app/Services/XbvrSyncService.php @@ -20,6 +20,11 @@ class XbvrSyncService extends BaseSyncService public function __construct(\PDO $pdo, array $source) { parent::__construct($pdo, $source); + + // Initialize properties first before using them + $this->apiKey = $source['api_key']; + $this->baseUrl = rtrim($source['api_url'], '/'); + $this->httpClient = new Client([ 'timeout' => 30, 'headers' => [ @@ -27,9 +32,8 @@ class XbvrSyncService extends BaseSyncService 'X-API-Key' => $source['api_key'] ] ]); - $this->apiKey = $source['api_key']; - $this->baseUrl = rtrim($source['api_url'], '/'); - $this->imageDownloader = new ImageDownloader(); + + $this->imageDownloader = new ImageDownloader('public/images', $this->apiKey); } protected function executeSync(string $syncType): void @@ -78,27 +82,6 @@ class XbvrSyncService extends BaseSyncService } } - private function syncScene(array $sceneData): void - { - $adultVideoModel = new AdultVideo($this->pdo); - - // Check if scene already exists by xbvr_id in metadata - $stmt = $this->pdo->prepare(" - SELECT id, metadata FROM adult_videos - WHERE source_id = :source_id - "); - $stmt->execute(['source_id' => $this->source['id']]); - $existingScenes = $stmt->fetchAll(\PDO::FETCH_ASSOC); - - $existingScene = null; - foreach ($existingScenes as $scene) { - $metadata = json_decode($scene['metadata'], true); - if (isset($metadata['xbvr_id']) && $metadata['xbvr_id'] === $sceneData['id']) { - $existingScene = $scene; - break; - } - } - private function syncScene(array $sceneData): void { $adultVideoModel = new AdultVideo($this->pdo); @@ -124,19 +107,39 @@ class XbvrSyncService extends BaseSyncService $coverFilename = null; $screenshotFilename = null; + // Extract image URLs from XBVR API response + $coverUrl = null; + $screenshotUrl = null; + if (!empty($sceneData['cover_url'])) { - $coverFilename = $this->imageDownloader->generateFilename($sceneData['cover_url'], 'cover'); - $localCoverPath = $this->imageDownloader->downloadImage($sceneData['cover_url'], $coverFilename, 'adult_videos'); - if ($localCoverPath) { - $sceneData['local_cover_path'] = $this->imageDownloader->getPublicUrl($localCoverPath); - } + $coverUrl = $sceneData['cover_url']; + $this->logProgress("Cover URL: " . $coverUrl); } if (!empty($sceneData['screenshot_url'])) { - $screenshotFilename = $this->imageDownloader->generateFilename($sceneData['screenshot_url'], 'screenshot'); - $localScreenshotPath = $this->imageDownloader->downloadImage($sceneData['screenshot_url'], $screenshotFilename, 'adult_videos'); + $screenshotUrl = $sceneData['screenshot_url']; + $this->logProgress("Screenshot URL: " . $screenshotUrl); + } + + if (!empty($coverUrl)) { + $coverFilename = $this->imageDownloader->generateFilename($coverUrl, 'cover'); + $localCoverPath = $this->imageDownloader->downloadImage($coverUrl, $coverFilename, 'adult_videos'); + if ($localCoverPath) { + $sceneData['local_cover_path'] = $this->imageDownloader->getPublicUrl($localCoverPath); + $this->logProgress("Downloaded cover: " . $localCoverPath); + } else { + $this->logProgress("Failed to download cover from: " . $coverUrl); + } + } + + if (!empty($screenshotUrl)) { + $screenshotFilename = $this->imageDownloader->generateFilename($screenshotUrl, 'screenshot'); + $localScreenshotPath = $this->imageDownloader->downloadImage($screenshotUrl, $screenshotFilename, 'adult_videos'); if ($localScreenshotPath) { $sceneData['local_screenshot_path'] = $this->imageDownloader->getPublicUrl($localScreenshotPath); + $this->logProgress("Downloaded screenshot: " . $localScreenshotPath); + } else { + $this->logProgress("Failed to download screenshot from: " . $screenshotUrl); } } diff --git a/app/Utils/ImageDownloader.php b/app/Utils/ImageDownloader.php index 64ebafd..a6558a0 100644 --- a/app/Utils/ImageDownloader.php +++ b/app/Utils/ImageDownloader.php @@ -10,13 +10,19 @@ class ImageDownloader private Client $httpClient; private string $basePath; - public function __construct(string $basePath = 'public/images') + public function __construct(string $basePath = 'public/images', ?string $apiKey = null) { + $headers = [ + 'User-Agent' => 'MediaCollector/1.0' + ]; + + if ($apiKey) { + $headers['ApiKey'] = $apiKey; + } + $this->httpClient = new Client([ 'timeout' => 30, - 'headers' => [ - 'User-Agent' => 'MediaCollector/1.0' - ] + 'headers' => $headers ]); $this->basePath = rtrim($basePath, '/'); } @@ -27,6 +33,7 @@ class ImageDownloader public function downloadImage(string $url, string $filename, string $subfolder = ''): ?string { if (empty($url) || !filter_var($url, FILTER_VALIDATE_URL)) { + error_log("Invalid URL provided: {$url}"); return null; } @@ -48,10 +55,45 @@ class ImageDownloader return $filePath; } - $response = $this->httpClient->get($url, ['sink' => $filePath]); + error_log("Downloading image from: {$url} to: {$filePath}"); - if ($response->getStatusCode() === 200) { - return $filePath; + $response = $this->httpClient->get($url, [ + 'sink' => $filePath, + 'headers' => [ + 'User-Agent' => 'MediaCollector/1.0', + 'Accept' => 'image/*', + ] + ]); + + $statusCode = $response->getStatusCode(); + $contentType = $response->getHeaderLine('content-type'); + + error_log("Download response - Status: {$statusCode}, Content-Type: {$contentType}"); + + if ($statusCode === 200) { + $fileSize = filesize($filePath); + error_log("Successfully downloaded image. Size: {$fileSize} bytes"); + + // Check if file is actually an image and not empty + if ($fileSize > 0) { + $imageInfo = getimagesize($filePath); + if ($imageInfo !== false) { + error_log("Valid image downloaded: {$imageInfo[0]}x{$imageInfo[1]} {$imageInfo['mime']}"); + return $filePath; + } else { + error_log("Downloaded file is not a valid image"); + if (file_exists($filePath)) { + unlink($filePath); + } + } + } else { + error_log("Downloaded file is empty"); + if (file_exists($filePath)) { + unlink($filePath); + } + } + } else { + error_log("Failed to download image. HTTP Status: {$statusCode}"); } return null; diff --git a/resources/views/adult/index.twig b/resources/views/adult/index.twig index 502e829..24c5297 100644 --- a/resources/views/adult/index.twig +++ b/resources/views/adult/index.twig @@ -104,7 +104,7 @@