[ 'series_id' => [ 'name' => 'Serien-ID (z.B. "Y3JpZDovL2hyLW9ubGluZS8zODIyMDAzMw")', 'type' => 'text', 'required' => true, 'exampleValue' => 'Y3JpZDovL2hyLW9ubGluZS8zODIyMDAzMw' ], 'limit' => [ 'name' => 'Maximale Anzahl an Episoden', 'type' => 'number', 'required' => false, 'defaultValue' => 20 ] ] ]; public function getIcon() { return 'https://www.google.com/s2/favicons?domain=www.ardmediathek.de&sz=32'; } private $seriesTitle = ''; private $seriesDescription = ''; public function getName() { if (!empty($this->seriesTitle)) { return $this->seriesTitle . ' - ARD Mediathek'; } return parent::getName(); } public function collectData() { $seriesId = $this->getInput('series_id'); $limit = $this->getInput('limit') ?? 20; if (empty($seriesId)) { returnClientError('Ungültige Serien-ID.'); } $apiUrl = self::API_URI . urlencode($seriesId); $jsonData = getContents($apiUrl); $data = json_decode($jsonData, true); if (!$data) { returnServerError('Keine Daten von der ARD Mediathek API erhalten.'); } // Extrahiere Serien-Informationen $this->seriesTitle = $data['title'] ?? 'Unbekannte Serie'; $this->seriesDescription = $data['synopsis'] ?? ''; // Die Episoden befinden sich im ersten Widget unter 'teasers' if (!isset($data['widgets'][0]['teasers']) || !is_array($data['widgets'][0]['teasers'])) { returnServerError('Keine Episoden gefunden.'); } $teasers = $data['widgets'][0]['teasers']; // Sortiere nach Sendedatum (neueste zuerst) usort($teasers, function ($a, $b) { $timeA = strtotime($a['broadcastedOn'] ?? 0); $timeB = strtotime($b['broadcastedOn'] ?? 0); return $timeB - $timeA; }); // Limitiere die Anzahl der Episoden $teasers = array_slice($teasers, 0, $limit); foreach ($teasers as $teaser) { $item = []; // Titel der Episode $item['title'] = $teaser['longTitle'] ?? $teaser['mediumTitle'] ?? $teaser['shortTitle'] ?? 'Unbekannter Titel'; // URL zur Episode $episodeId = $teaser['id'] ?? ''; if (!empty($episodeId)) { $item['uri'] = self::URI . '/video/' . $episodeId; } else { $item['uri'] = self::URI; } // Zeitstempel if (isset($teaser['broadcastedOn'])) { $item['timestamp'] = strtotime($teaser['broadcastedOn']); } // Eindeutige ID $item['uid'] = $episodeId; // Sender/Autor if (isset($teaser['publicationService']['name'])) { $item['author'] = $teaser['publicationService']['name']; } // Content: Bild + Beschreibung $content = ''; // Vorschaubild if (isset($teaser['images']['aspect16x9']['src'])) { $imageUrl = $teaser['images']['aspect16x9']['src']; // Setze eine vernünftige Bildbreite $imageUrl = str_replace('{width}', '960', $imageUrl); $imageAlt = $teaser['images']['aspect16x9']['alt'] ?? ''; $content .= '' . htmlspecialchars($imageAlt) . '
'; } // Episoden-Beschreibung per Detail-API abrufen if (!empty($episodeId)) { $synopsis = $this->getEpisodeSynopsis($episodeId); if (!empty($synopsis)) { $content .= '

' . htmlspecialchars($synopsis) . '

'; } } $item['content'] = $content; // Enclosure für das Vorschaubild if (isset($teaser['images']['aspect16x9']['src'])) { $imageUrl = str_replace('{width}', '960', $teaser['images']['aspect16x9']['src']); $item['enclosures'] = [$imageUrl]; } $this->items[] = $item; } } public function getURI() { $seriesId = $this->getInput('series_id'); if (empty($seriesId)) { return self::URI; } return self::URI . '/serie/' . $seriesId; } public function detectParameters($url) { // Versuche die Serien-ID aus verschiedenen ARD Mediathek URL-Formaten zu extrahieren // Format 1: https://www.ardmediathek.de/serie/Y3JpZDovL2hyLW9ubGluZS8zODIyMDAzMw // Format 2: https://www.ardmediathek.de/serie/name/staffel-X/Y3JpZDovL2hyLW9ubGluZS8zODIyMDAzMw/X if (preg_match('#ardmediathek\.de/serie/(?:[^/]+/(?:staffel-\d+/)?)?([A-Za-z0-9_-]+)(?:/\d+)?#', $url, $matches)) { return [ 'series_id' => $matches[1] ]; } return null; } /** * Holt die Beschreibung einer Episode von der Detail-API */ private function getEpisodeSynopsis(string $episodeId): ?string { $apiUrl = 'https://api.ardmediathek.de/page-gateway/pages/ard/item/' . urlencode($episodeId); try { $jsonData = getContents($apiUrl); $data = json_decode($jsonData, true); if (!$data || !isset($data['widgets']) || !is_array($data['widgets'])) { return null; } // Synopsis ist im ersten Widget (player_ondemand) foreach ($data['widgets'] as $widget) { if (!empty($widget['synopsis'])) { return $widget['synopsis']; } } } catch (Exception $e) { // Bei Fehlern einfach keine Beschreibung zurückgeben } return null; } }