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 = '