diff --git a/HytaleNewsBridge.php b/HytaleNewsBridge.php new file mode 100644 index 0000000..d02cf43 --- /dev/null +++ b/HytaleNewsBridge.php @@ -0,0 +1,136 @@ + [ + '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 .= '
' . htmlspecialchars($post['bodyExcerpt'] ?? '') . '
'; + $item['content'] = $content; + + // Enclosure for image + if ($imageUrl) { + $item['enclosures'] = [$imageUrl]; + } + + $this->items[] = $item; + } + } +}