112 lines
4.3 KiB
PHP
112 lines
4.3 KiB
PHP
<?php
|
|
class JoynBridge extends BridgeAbstract {
|
|
const NAME = 'Joyn.de Serien RSS';
|
|
const URI = 'https://www.joyn.de/';
|
|
const DESCRIPTION = 'RSS-Feed für Serien von Joyn.de';
|
|
const CACHE_TIMEOUT = 21600; // 6h
|
|
const MAINTAINER = 'Akamaru';
|
|
const ICON = 'https://www.joyn.de/favicon.ico';
|
|
const PARAMETERS = [
|
|
[
|
|
'series_id' => [
|
|
'name' => 'Serien-ID',
|
|
'type' => 'text',
|
|
'title' => 'ID der Serie (z.B. match-in-paradise)',
|
|
'required' => true
|
|
]
|
|
]
|
|
];
|
|
|
|
public function collectData() {
|
|
$series_id = $this->getInput('series_id');
|
|
if (empty($series_id)) {
|
|
return;
|
|
}
|
|
|
|
$url = 'https://www.joyn.de/serien/' . $series_id;
|
|
$html = getSimpleHTMLDOM($url);
|
|
|
|
if (!$html) {
|
|
returnServerError('Could not load page');
|
|
}
|
|
|
|
$scriptTag = $html->find('script[id="__NEXT_DATA__"]', 0);
|
|
if (!$scriptTag) {
|
|
returnServerError('Could not find NEXT_DATA script tag');
|
|
}
|
|
|
|
$jsonData = json_decode($scriptTag->innertext, true);
|
|
if (!$jsonData) {
|
|
returnServerError('Could not parse JSON data');
|
|
}
|
|
|
|
$series = $jsonData['props']['pageProps']['initialData']['page']['series'] ?? null;
|
|
if (!$series) {
|
|
returnServerError('Could not find series data');
|
|
}
|
|
|
|
$episodeMap = [];
|
|
if (isset($series['freeSeasons'])) {
|
|
foreach ($series['freeSeasons'] as $season) {
|
|
if (isset($season['episodes'])) {
|
|
foreach ($season['episodes'] as $episode) {
|
|
$episode['seasonNumber'] = $season['number'];
|
|
$episode['__plus__'] = false;
|
|
$episodeMap[$episode['id']] = $episode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Joyn Plus (svodSeasons) ergänzen
|
|
if (isset($series['svodSeasons'])) {
|
|
foreach ($series['svodSeasons'] as $season) {
|
|
if (isset($season['episodes'])) {
|
|
foreach ($season['episodes'] as $episode) {
|
|
$episode['seasonNumber'] = $season['number'];
|
|
$episode['__plus__'] = true;
|
|
// Überschreibe ggf. free-Episode mit PLUS-Version
|
|
$episodeMap[$episode['id']] = $episode;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$allEpisodes = array_values($episodeMap);
|
|
// Sortiere nach Episodennummer absteigend (neueste zuerst)
|
|
usort($allEpisodes, function($a, $b) {
|
|
$seasonCompare = ($b['seasonNumber'] ?? 0) <=> ($a['seasonNumber'] ?? 0);
|
|
if ($seasonCompare !== 0) {
|
|
return $seasonCompare;
|
|
}
|
|
return ($b['number'] ?? 0) <=> ($a['number'] ?? 0);
|
|
});
|
|
foreach ($allEpisodes as $episode) {
|
|
$seasonNumber = $episode['seasonNumber'] ?? 1;
|
|
$episodeNumber = $episode['number'] ?? 1;
|
|
$title = $episode['title'] ?? '';
|
|
$airdate = $episode['airdate'] ?? null;
|
|
$path = $episode['path'] ?? '';
|
|
$primaryImage = $episode['primaryImage']['url'] ?? '';
|
|
$isPlus = !empty($episode['__plus__']);
|
|
$item = [];
|
|
$item['title'] = sprintf('%sS%02dE%02d "%s"', $isPlus ? '[Joyn PLUS+] ' : '', $seasonNumber, $episodeNumber, $title);
|
|
$item['content'] = '<p>Neue Folge verfügbar';
|
|
if ($isPlus) {
|
|
$item['content'] .= ' <span style="color:red;font-weight:bold">Joyn PLUS+ (Abo benötigt)</span>';
|
|
}
|
|
$item['content'] .= '</p>';
|
|
if ($primaryImage) {
|
|
$item['content'] .= '<p><img src="' . htmlspecialchars($primaryImage) . '" alt="' . htmlspecialchars($title) . '"></p>';
|
|
$item['enclosures'] = [$primaryImage];
|
|
}
|
|
if ($airdate) {
|
|
$item['timestamp'] = $airdate;
|
|
}
|
|
if ($path) {
|
|
$item['uri'] = 'https://www.joyn.de' . $path;
|
|
} else {
|
|
$item['uri'] = $url;
|
|
}
|
|
$this->items[] = $item;
|
|
}
|
|
}
|
|
} |