1
0

Übernehme Bridges von Brawl

- GenshinImpactNewsBridge
- HolonometriaMangaBridge
- PokemonGOBridge
This commit is contained in:
Akamaru
2025-07-03 21:32:20 +02:00
parent 7ff988e06d
commit efbc4f60da
3 changed files with 270 additions and 0 deletions

101
GenshinImpactNewsBridge.php Normal file
View File

@ -0,0 +1,101 @@
<?php
class GenshinImpactNewsBridge extends BridgeAbstract
{
const MAINTAINER = 'Brawl, Akamaru';
const NAME = 'Genshin Impact News';
const URI = 'https://sg-public-api-static.hoyoverse.com/content_v2_user/app/a1b1f9d3315447cc/getContentList';
const CACHE_TIMEOUT = 3600; // 3600 = 1h
const DESCRIPTION = 'Get the latest news from Genshin Impact!';
const PARAMETERS = array(
array(
'lang' => array(
'name' => 'Language',
'type' => 'list',
'values' => array(
'English' => 'en-us',
'繁體中文' => 'zh-tw',
'한국어' => 'ko-kr',
'日本語' => 'ja-jp',
'Français' => 'fr-fr',
'Deutsch' => 'de-de',
'Português' => 'pt-pt',
'Español' => 'es-es',
'Русский' => 'ru-ru',
'Bahasa Indonesia' => 'id-id',
'Tiếng Việt' => 'vi-vn',
'ไทย' => 'th-th',
),
'required' => true
),
'limit' => array(
'name' => 'Limit',
'type' => 'number',
'required' => false,
'defaultValue' => 10
)
)
);
private $pageUrl = self::URI;
public function getURI()
{
return $this->pageUrl;
}
public function collectData()
{
// Eingaben prüfen
$lang = $this->getInput('lang');
if (empty($lang)) {
returnClientError('Ungültige Sprache: ' . $lang);
}
$limit = $this->getInput('limit');
if (empty($limit)) {
$limit = 10;
}
// Neue API-URL zusammenbauen
$query = http_build_query([
'iAppId' => 32,
'iChanId' => 395, // Standard-News-Kanal, ggf. anpassbar
'iPageSize' => $limit,
'iPage' => 1,
'sLangKey' => $lang
]);
$jsonUrl = self::URI . '?' . $query;
$json = getContents($jsonUrl)
or returnServerError('Konnte die Genshin-News nicht abrufen.');
$data = json_decode($json);
if (!isset($data->data->list)) {
returnServerError('Ungültige Antwortstruktur.');
}
$this->pageUrl = 'https://genshin.hoyoverse.com/' . $lang . '/news';
foreach ($data->data->list as $element) {
$article_title = $element->sTitle;
$article_uid = $element->iInfoId;
$article_uri = $this->pageUrl . '/detail/' . $article_uid;
$article_timestamp = strtotime($element->dtStartTime);
$article_content = $element->sIntro;
$item = array();
$item['uri'] = $article_uri;
$item['title'] = $article_title;
$item['timestamp'] = $article_timestamp;
$item['content'] = $article_content;
// Thumbnail aus sExt->banner
if (!empty($element->sExt)) {
$ext = json_decode($element->sExt);
if (isset($ext->banner) && is_array($ext->banner) && isset($ext->banner[0]->url)) {
$item['enclosures'] = array($ext->banner[0]->url);
}
}
$this->items[] = $item;
}
}
}

View File

@ -0,0 +1,75 @@
<?php
class HolonometriaMangaBridge extends BridgeAbstract
{
const MAINTAINER = 'Brawl, Akamaru';
const NAME = 'Holonometria Manga Series';
const URI = 'https://holoearth.com/en/alt/holonometria/manga/';
const CACHE_TIMEOUT = 21600; // 6h
const DESCRIPTION = 'Get the latest chapters of the Holonometria Manga series.';
const PARAMETERS = [
[
'manga' => [
'name' => 'Manga',
'type' => 'list',
'values' => [
'Vesta de Cooking' => 'vestadecooking',
'Underworld Academy Overload!!' => 'soreyukemakaigakko',
'Yamato Phantasia' => 'yamatokasoukaiitan',
]
],
],
];
public function getIcon()
{
return 'https://holoearth.com/assets/img/favicon_holonometria.ico';
}
public function collectData()
{
$manga = $this->getInput('manga');
$pageUrl = self::URI . $manga . '/';
$html = getSimpleHTMLDOM($pageUrl)
or returnServerError('Konnte die Webseite nicht laden: ' . $pageUrl);
$items = [];
foreach ($html->find('ul.manga-detail__list li.manga-detail__list-item') as $element) {
$a = $element->find('a.manga-detail__list-link', 0);
if (!$a) continue;
$item = [];
$item['uri'] = $a->href;
$title = $a->find('p.manga-detail__list-title', 0);
$date = $a->find('p.manga-detail__list-date', 0);
$timestamp = null;
$date_str = '';
if ($date) {
$date_raw = trim(strip_tags($date->innertext));
if (preg_match('/^(\d{4})\.(\d{2})\.(\d{2})$/', $date_raw, $m)) {
$timestamp = mktime(0, 0, 0, $m[2], $m[3], $m[1]);
} else {
$timestamp = strtotime($date_raw);
}
if ($timestamp && $timestamp > 0) {
$date_str = ' (' . date('d.m.Y', $timestamp) . ')';
$item['timestamp'] = $timestamp;
}
}
$item['title'] = ($title ? trim(strip_tags($title->innertext)) : 'Kapitel') . $date_str;
$thumb = $a->find('p.manga-detail__list-thumb img', 0);
if ($thumb) {
$item['enclosures'] = [$thumb->src];
$item['content'] = '<img src="' . $thumb->src . '" />';
}
$item['uid'] = $item['uri'];
$items[] = $item;
}
// Nach Datum absteigend sortieren (neustes zuerst, ohne 0-Timestamps)
usort($items, function($a, $b) {
$at = isset($a['timestamp']) ? $a['timestamp'] : 0;
$bt = isset($b['timestamp']) ? $b['timestamp'] : 0;
return $bt <=> $at;
});
$this->items = array_slice($items, 0, 15);
}
}

94
PokemonGOBridge.php Normal file
View File

@ -0,0 +1,94 @@
<?php
class PokemonGOBridge extends BridgeAbstract {
const MAINTAINER = 'Brawl, Akamaru';
const NAME = 'Pokémon GO News';
const URI = 'https://pokemongo.com/';
const CACHE_TIMEOUT = 21600; // 21600 = 6h
const DESCRIPTION = 'Get the latest official "Pokémon GO" news.';
const PARAMETERS = array(
array(
'lang' => array(
'name' => 'Language',
'type' => 'list',
'values' => array(
'English' => 'en',
'繁體中文' => 'zh_hant',
'Français' => 'fr',
'Deutsch' => 'de',
'Italiano' => 'it',
'日本語' => 'ja',
'한국어' => 'ko',
'Português' => 'pt_br',
'Español' => 'es',
'Español (México)' => 'es_mx',
'Polski' => 'pl',
'Русский' => 'ru',
'हिन्दी' => 'hi',
'Bahasa Indonesia' => 'id',
'ไทย' => 'th',
'Türkçe' => 'tr',
),
'defaultValue' => 'en'
)
)
);
public function getIcon(){
return 'https://pokemongo.com/img/icons/favicon.ico';
}
public function collectData() {
$lang = $this->getInput('lang');
$pageUrl = self::URI . $lang . '/news';
$html = getSimpleHTMLDOM($pageUrl)
or returnServerError('Konnte die Webseite nicht laden: ' . $pageUrl);
// Finde alle News-Karten
foreach($html->find('a._newsCard_119ao_16') as $element) {
if(count($this->items) >= 10) break;
// Titel
$contentDiv = $element->find('div._newsCardContent_119ao_59', 0);
$title = '';
if ($contentDiv) {
$titleDiv = $contentDiv->find('div', 1); // Das zweite <div> ist der Titel
if ($titleDiv) {
$title = trim($titleDiv->plaintext);
}
}
// Link
$href = $element->href;
if(strpos($href, 'http') !== 0) {
$uri = rtrim(self::URI, '/') . $href;
} else {
$uri = $href;
}
// Datum
$dateElement = $element->find('pg-date-format', 0);
$timestamp = null;
if ($dateElement && isset($dateElement->timestamp)) {
$timestamp = intval($dateElement->timestamp / 1000); // JS ms -> s
}
// Bild
$imgElement = $element->find('img', 0);
$imgHtml = '';
if ($imgElement && isset($imgElement->src)) {
$imgHtml = '<img src="' . htmlspecialchars($imgElement->src) . '" alt="" style="max-width:100%;height:auto;" />';
}
// Content (nur Bild, da kein Teasertext im Listing)
$content = $imgHtml;
$item = array();
$item['uri'] = $uri;
$item['title'] = $title;
if ($timestamp) $item['timestamp'] = $timestamp;
$item['content'] = $content;
$this->items[] = $item;
}
}
}