[ 'name' => 'Maximale Anzahl', 'type' => 'number', 'required' => false, 'defaultValue' => 20, 'title' => 'Maximale Anzahl an Uploads (max. 50)' ] ] ]; public function collectData() { // HTML von der Startseite laden $html = getSimpleHTMLDOM(self::URI); if (!$html) { returnServerError('Konnte FilmFans.org nicht laden'); } // Upload-Einträge finden $entries = $html->find('div.sra'); if (empty($entries)) { returnServerError('Keine Uploads gefunden'); } // Jeden Eintrag parsen foreach ($entries as $entry) { // Upload-Zeit aus lsf-icon timed extrahieren $timeTag = $entry->find('span.lsf-icon.timed', 0); $uploadTime = $timeTag ? trim($timeTag->plaintext) : ''; // Timestamp berechnen (HH:MM Format zu Unix timestamp) $timestamp = $this->parseUploadTime($uploadTime); // h2 Tag finden $h2 = $entry->find('h2', 0); if (!$h2) { continue; } // Titel extrahieren (nur der Text vor dem Tag) $titleText = ''; foreach ($h2->nodes as $node) { if ($node->tag === 'text') { $titleText .= $node->outertext; } elseif ($node->tag === 'i') { break; // Stop bei Jahr } } $title = trim($titleText); // Jahr aus Tag extrahieren $yearTag = $h2->find('i', 0); $year = $yearTag ? trim($yearTag->plaintext, '()') : ''; // Movie URL extrahieren (erstes Tag im Entry) $linkTag = $entry->find('a', 0); $movieUrl = $linkTag ? $linkTag->href : ''; if ($movieUrl && strpos($movieUrl, '/') === 0) { $movieUrl = 'https://filmfans.org' . $movieUrl; } // Cover-Bild extrahieren (aus i.cover) $coverTag = $entry->find('i.cover img', 0); $coverUrl = ''; if ($coverTag && $coverTag->src) { $coverUrl = $coverTag->src; if (strpos($coverUrl, '/') === 0) { $coverUrl = 'https://filmfans.org' . $coverUrl; } } // Beschreibung extrahieren $descTag = $entry->find('p.description', 0); $description = $descTag ? trim($descTag->plaintext) : ''; // Release-Namen sammeln (alle Tags innerhalb h2 > span) $releases = []; $releaseSpan = $h2->find('span', 0); if ($releaseSpan) { foreach ($releaseSpan->find('a') as $releaseLink) { $releaseName = trim($releaseLink->plaintext); if ($releaseName) { $releases[] = $releaseName; } } } // Sprachen extrahieren $languages = []; foreach ($entry->find('span.audiotag img') as $langImg) { if ($langImg->src) { // /images/DE.svg → DE if (preg_match('#/images/([A-Z]{2})\.svg#', $langImg->src, $match)) { $languages[] = $match[1]; } } } // Genres extrahieren $genres = []; foreach ($entry->find('a.genre') as $genreLink) { $genre = trim($genreLink->plaintext); if ($genre) { $genres[] = $genre; } } // Item erstellen $item = [ 'title' => $title . ($year ? " ($year)" : ''), 'uri' => $movieUrl ?: self::URI, 'timestamp' => $timestamp, 'content' => $this->buildContent($coverUrl, $description, $releases, $languages, $genres), 'author' => 'FilmFans', 'categories' => $genres, 'enclosures' => $coverUrl ? [$coverUrl] : [], 'uid' => md5($movieUrl) ]; $this->items[] = $item; } // Nach Timestamp sortieren (neueste zuerst) usort($this->items, function ($a, $b) { return $b['timestamp'] <=> $a['timestamp']; }); // Limit anwenden $limit = min((int)$this->getInput('limit'), 50); $this->items = array_slice($this->items, 0, $limit); } private function parseUploadTime($timeString) { // Format: "HH:MM" z.B. "13:57" if (preg_match('/^(\d{1,2}):(\d{2})$/', $timeString, $match)) { $hours = (int)$match[1]; $minutes = (int)$match[2]; $today = date('Y-m-d'); $timestamp = strtotime("$today $hours:$minutes:00"); // Wenn Timestamp in der Zukunft liegt (mehr als 1 Stunde), ist es von gestern if ($timestamp > time() + 3600) { $timestamp = strtotime("yesterday $hours:$minutes:00"); } return $timestamp; } // Fallback: aktueller Zeitstempel return time(); } private function buildContent($coverUrl, $description, $releases, $languages, $genres) { $content = ''; // Cover-Bild if ($coverUrl) { $content .= 'Cover
'; } // Beschreibung if ($description) { $content .= '

Beschreibung: ' . htmlspecialchars($description) . '

'; } // Sprachen if (!empty($languages)) { $content .= '

Sprachen: ' . implode(', ', $languages) . '

'; } // Genres if (!empty($genres)) { $content .= '

Genres: ' . implode(', ', $genres) . '

'; } // Releases if (!empty($releases)) { $content .= '

Releases:

    '; foreach ($releases as $release) { $content .= '
  • ' . htmlspecialchars($release) . '
  • '; } $content .= '
'; } return $content; } public function getIcon() { return 'https://www.google.com/s2/favicons?domain=filmfans.org&sz=32'; } }