233 lines
7.4 KiB
PHP
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'];
|
|
}
|
|
}
|