1
0
Files
Bridges/NIKKENewsBridge.php
2025-12-12 18:07:49 +01:00

233 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
class NIKKENewsBridge extends BridgeAbstract
{
const MAINTAINER = 'Akamaru';
const NAME = 'GODDESS OF VICTORY: NIKKE News';
const URI = 'https://nikke-en.com/news.html';
const CACHE_TIMEOUT = 3600; // 1h
const DESCRIPTION = 'Get the latest news from GODDESS OF VICTORY: NIKKE!';
public function getIcon()
{
return 'https://www.google.com/s2/favicons?domain=nikke-en.com&sz=32';
}
const PARAMETERS = array(
array(
'category' => array(
'name' => 'Category',
'type' => 'list',
'values' => array(
'All' => 'all',
'Important' => 'important',
'News' => 'news',
'Notice' => 'notice'
),
'required' => true,
'defaultValue' => 'all'
),
'lang' => array(
'name' => 'Language',
'type' => 'list',
'values' => array(
'English' => 'en',
'Deutsch' => 'de',
'Français' => 'fr',
'日本語' => 'ja',
'한국어' => 'ko',
'ไทย' => 'th'
),
'required' => true,
'defaultValue' => 'en'
),
'limit' => array(
'name' => 'Limit',
'type' => 'number',
'required' => false,
'defaultValue' => 10
)
)
);
private $apiUrl = 'https://na-community.playerinfinite.com/api/gpts.information_feeds_svr.InformationFeedsSvr/GetContentByLabel';
private $apiUrlDetail = 'https://na-community.playerinfinite.com/api/gpts.information_feeds_svr.InformationFeedsSvr/GetContentInfoById';
private $pageUrl = self::URI;
public function getURI()
{
return $this->pageUrl;
}
public function collectData()
{
$category = $this->getInput('category');
$lang = $this->getInput('lang');
$limit = $this->getInput('limit') ?? 10;
// Map category to label IDs
$labelConfig = $this->getLabelConfig($category);
$allItems = [];
// If "all" is selected, fetch from multiple labels
if ($category === 'all') {
$seenIds = [];
foreach ($labelConfig as $config) {
$items = $this->fetchNews($config['primary'], $config['secondary'], $lang, $limit);
foreach ($items as $item) {
// Use URI as unique identifier to prevent duplicates
if (!isset($seenIds[$item['uri']])) {
$seenIds[$item['uri']] = true;
$allItems[] = $item;
}
}
}
// Sort by timestamp and limit
usort($allItems, function ($a, $b) {
return $b['timestamp'] <=> $a['timestamp'];
});
$allItems = array_slice($allItems, 0, $limit);
} else {
$config = $labelConfig[0];
$allItems = $this->fetchNews($config['primary'], $config['secondary'], $lang, $limit);
}
$this->items = $allItems;
}
private function getLabelConfig($category)
{
switch ($category) {
case 'important':
return [['primary' => 308, 'secondary' => 494]];
case 'news':
return [['primary' => 309, 'secondary' => 496]];
case 'notice':
return [['primary' => 309, 'secondary' => 892]];
case 'all':
return [
['primary' => 308, 'secondary' => 494], // Important
['primary' => 309, 'secondary' => 496], // News
['primary' => 309, 'secondary' => 892] // Notice
];
default:
returnClientError('Invalid category: ' . $category);
}
}
private function fetchNews($primaryLabelId, $secondaryLabelId, $lang, $limit)
{
$requestBody = json_encode([
'language' => [$lang],
'gameid' => '16',
'offset' => 0,
'get_num' => $limit,
'ext_info_type_list' => [0, 1, 2],
'secondary_label_id' => $secondaryLabelId,
'primary_label_id' => $primaryLabelId
]);
$headers = [
'Content-Type: application/json;charset=utf-8',
'x-areaid: na',
'x-gameid: 16',
'x-language: ' . $lang,
'x-source: pc_web'
];
$opts = [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $requestBody,
CURLOPT_HTTPHEADER => $headers
];
$json = getContents($this->apiUrl, $headers, $opts)
or returnServerError('Could not fetch NIKKE news.');
$data = json_decode($json, true);
if (!isset($data['data']['info_content'])) {
returnServerError('Invalid response structure.');
}
$items = [];
foreach ($data['data']['info_content'] as $element) {
$contentId = $element['content_id'] ?? '';
$fatherContentId = $element['father_content_id'] ?? $contentId;
$title = $element['title'] ?? 'Untitled';
$timestamp = isset($element['pub_timestamp']) ? (int)$element['pub_timestamp'] : time();
$picUrls = $element['pic_urls'] ?? [];
// Fetch full content
$fullContent = $this->fetchFullContent($fatherContentId, $lang);
// Prepend image to content if available
if (!empty($picUrls)) {
$imageUrl = $picUrls[0];
$imageHtml = '<p><img src="' . htmlspecialchars($imageUrl) . '" alt="' . htmlspecialchars($title) . '" /></p>';
$fullContent = $imageHtml . $fullContent;
}
// Construct article URI
$uri = 'https://nikke-en.com/newsdetail.html?content_id=' . $contentId;
$item = [
'uri' => $uri,
'title' => $title,
'timestamp' => $timestamp,
'content' => $fullContent,
'author' => 'NIKKE Team'
];
// Add image as enclosure
if (!empty($picUrls)) {
$item['enclosures'] = [$picUrls[0]];
}
$items[] = $item;
}
return $items;
}
private function fetchFullContent($fatherContentId, $lang)
{
$requestBody = json_encode([
'father_content_id' => $fatherContentId
]);
$headers = [
'Content-Type: application/json;charset=utf-8',
'x-areaid: na',
'x-gameid: 16',
'x-language: ' . $lang,
'x-source: pc_web'
];
$opts = [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $requestBody,
CURLOPT_HTTPHEADER => $headers
];
$json = getContents($this->apiUrlDetail, $headers, $opts);
if (!$json) {
// Fallback to empty content if detail fetch fails
return '';
}
$data = json_decode($json, true);
if (!isset($data['data']['content'])) {
return '';
}
// Return the HTML content
return $data['data']['content'];
}
}