Neu: Hytale News Bridge
This commit is contained in:
136
HytaleNewsBridge.php
Normal file
136
HytaleNewsBridge.php
Normal file
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
class HytaleNewsBridge extends BridgeAbstract
|
||||
{
|
||||
const MAINTAINER = 'Akamaru';
|
||||
const NAME = 'Hytale News';
|
||||
const URI = 'https://hytale.com/news';
|
||||
const CACHE_TIMEOUT = 3600;
|
||||
const DESCRIPTION = 'Get the latest news from Hytale!';
|
||||
const PARAMETERS = [
|
||||
[
|
||||
'limit' => [
|
||||
'name' => 'Max. Articles',
|
||||
'type' => 'number',
|
||||
'required' => false,
|
||||
'defaultValue' => 20
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
public function getIcon()
|
||||
{
|
||||
return 'https://hytale.com/favicon.ico';
|
||||
}
|
||||
|
||||
public function collectData()
|
||||
{
|
||||
$html = getContents(self::URI);
|
||||
if (!$html) {
|
||||
returnServerError('Could not load Hytale news page.');
|
||||
}
|
||||
|
||||
// Find the JSON data in __INITIAL_COMPONENTS_STATE__
|
||||
$marker = 'window.__INITIAL_COMPONENTS_STATE__ = ';
|
||||
$startPos = strpos($html, $marker);
|
||||
if ($startPos === false) {
|
||||
returnServerError('Could not find initial state marker.');
|
||||
}
|
||||
|
||||
$jsonStart = $startPos + strlen($marker);
|
||||
|
||||
// Find the matching closing bracket by counting brackets
|
||||
$bracketCount = 0;
|
||||
$jsonEnd = $jsonStart;
|
||||
$len = strlen($html);
|
||||
$inString = false;
|
||||
$escapeNext = false;
|
||||
|
||||
for ($i = $jsonStart; $i < $len; $i++) {
|
||||
$char = $html[$i];
|
||||
|
||||
if ($escapeNext) {
|
||||
$escapeNext = false;
|
||||
continue;
|
||||
}
|
||||
if ($char === '\\') {
|
||||
$escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
if ($char === '"' && !$escapeNext) {
|
||||
$inString = !$inString;
|
||||
continue;
|
||||
}
|
||||
if ($inString) {
|
||||
continue;
|
||||
}
|
||||
if ($char === '[') {
|
||||
$bracketCount++;
|
||||
} elseif ($char === ']') {
|
||||
$bracketCount--;
|
||||
if ($bracketCount === 0) {
|
||||
$jsonEnd = $i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$jsonStr = substr($html, $jsonStart, $jsonEnd - $jsonStart);
|
||||
$jsonData = json_decode($jsonStr, true);
|
||||
|
||||
if (!$jsonData || !isset($jsonData[0]['posts'])) {
|
||||
returnServerError('Could not extract posts data from page.');
|
||||
}
|
||||
|
||||
$posts = $jsonData[0]['posts'];
|
||||
|
||||
$limit = $this->getInput('limit') ?? 20;
|
||||
$count = 0;
|
||||
|
||||
foreach ($posts as $post) {
|
||||
if ($count >= $limit) {
|
||||
break;
|
||||
}
|
||||
$count++;
|
||||
$item = [];
|
||||
|
||||
$item['title'] = $post['title'] ?? 'Untitled';
|
||||
$item['author'] = $post['author'] ?? 'Hytale Team';
|
||||
$item['uid'] = $post['_id'] ?? '';
|
||||
|
||||
// Build URI from publishedAt date and slug
|
||||
$publishedAt = $post['publishedAt'] ?? null;
|
||||
$slug = $post['slug'] ?? '';
|
||||
if ($publishedAt && $slug) {
|
||||
$date = new DateTime($publishedAt);
|
||||
$year = $date->format('Y');
|
||||
$month = $date->format('n'); // Month without leading zero
|
||||
$item['uri'] = 'https://hytale.com/news/' . $year . '/' . $month . '/' . $slug;
|
||||
$item['timestamp'] = $date->getTimestamp();
|
||||
} else {
|
||||
$item['uri'] = self::URI;
|
||||
}
|
||||
|
||||
// Content with image
|
||||
$content = '';
|
||||
$imageUrl = null;
|
||||
if (isset($post['coverImage']['s3Key'])) {
|
||||
$s3Key = $post['coverImage']['s3Key'];
|
||||
$imageUrl = 'https://cdn.hytale.com/variants/blog_cover_' . $s3Key;
|
||||
$content .= '<p><img src="' . $imageUrl . '" alt="' . htmlspecialchars($item['title']) . '"></p>';
|
||||
}
|
||||
|
||||
$content .= '<p>' . htmlspecialchars($post['bodyExcerpt'] ?? '') . '</p>';
|
||||
$item['content'] = $content;
|
||||
|
||||
// Enclosure for image
|
||||
if ($imageUrl) {
|
||||
$item['enclosures'] = [$imageUrl];
|
||||
}
|
||||
|
||||
$this->items[] = $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user