1+ import fs from 'fs' ;
2+ import path from 'path' ;
3+ import { fileURLToPath } from 'url' ;
4+
5+ const __filename = fileURLToPath ( import . meta. url ) ;
6+ const __dirname = path . dirname ( __filename ) ;
7+
8+ const apiPath = 'https://nomanssky.fandom.com/api.php' ;
9+ const MIN_REQUEST_INTERVAL = 35000 ; // 35 seconds between fetchs
10+
11+ const sleep = ( ms ) => new Promise ( resolve => setTimeout ( resolve , ms ) ) ;
12+
13+ const filterValidData = ( data ) => {
14+ return data . filter ( item =>
15+ item . title . civilizeD &&
16+ item . title . civilizeD !== 'Uncharted' &&
17+ item . title . coordinateS &&
18+ item . title . galaxY &&
19+ item . title . pageName
20+ ) ;
21+ } ;
22+
23+ const fetchCivilizationsPage = async ( offset = 0 ) => {
24+ const params = new URLSearchParams ( ) ;
25+ params . append ( 'action' , 'cargoquery' ) ;
26+ params . append ( 'tables' , 'Regions' ) ;
27+ params . append ( 'fields' , 'Regions.Civilized=civilizeD,Regions.Galaxy=galaxY,Regions.Coordinates=coordinateS,_pageName=pageName' ) ;
28+ params . append ( 'group_by' , '_pageName' ) ;
29+ params . append ( 'order_by' , '_pageName' ) ;
30+ params . append ( 'limit' , '500' ) ;
31+ params . append ( 'offset' , offset . toString ( ) ) ;
32+ params . append ( 'format' , 'json' ) ;
33+ params . append ( 'origin' , '*' ) ;
34+
35+ const url = `${ apiPath } ?${ params . toString ( ) } ` ;
36+ console . log ( `Fetching page with offset: ${ offset } ` ) ;
37+
38+ const response = await fetch ( url ) ;
39+ if ( ! response . ok ) {
40+ throw new Error ( `HTTP error! status: ${ response . status } ` ) ;
41+ }
42+
43+ const data = await response . json ( ) ;
44+ return data . cargoquery || [ ] ;
45+ } ;
46+
47+ const fetchAllCivilizationsAndRegions = async ( ) => {
48+ console . log ( 'Starting data fetch...' ) ;
49+ let allData = [ ] ;
50+ let offset = 0 ;
51+ let hasMore = true ;
52+ let requestCount = 0 ;
53+
54+ while ( hasMore ) {
55+ try {
56+ const pageData = await fetchCivilizationsPage ( offset ) ;
57+ const validPageData = filterValidData ( pageData ) ;
58+
59+ console . log ( `Page ${ requestCount + 1 } : ${ pageData . length } raw items, ${ validPageData . length } valid items` ) ;
60+
61+ if ( pageData . length === 0 ) {
62+ hasMore = false ;
63+ console . log ( 'No more data available' ) ;
64+ } else {
65+ allData = allData . concat ( validPageData ) ;
66+ requestCount ++ ;
67+
68+ console . log ( `Total valid items so far: ${ allData . length } ` ) ;
69+
70+ if ( pageData . length < 50 ) {
71+ hasMore = false ;
72+ console . log ( 'Last page reached' ) ;
73+ } else {
74+ offset += 500 ;
75+
76+ if ( hasMore ) {
77+ console . log ( `Waiting ${ MIN_REQUEST_INTERVAL } ms before next request...` ) ;
78+ await sleep ( MIN_REQUEST_INTERVAL ) ;
79+ }
80+ }
81+ }
82+ } catch ( error ) {
83+ console . error ( 'Error fetching page:' , error ) ;
84+ throw error ;
85+ }
86+ }
87+
88+ console . log ( `Total valid items fetched: ${ allData . length } ` ) ;
89+
90+ if ( allData . length > 0 ) {
91+ const galaxies = [ ...new Set (
92+ allData . map ( item => item . title . galaxY )
93+ ) ] . filter ( Boolean ) . sort ( ) ;
94+
95+ const data = { } ;
96+
97+ galaxies . forEach ( galaxy => {
98+ data [ galaxy ] = {
99+ civilizations : [ ] ,
100+ regions : { }
101+ } ;
102+
103+ const galaxyData = allData . filter ( item => item . title . galaxY === galaxy ) ;
104+ const civilizations = [ ...new Set (
105+ galaxyData . map ( item => item . title . civilizeD )
106+ ) ] . sort ( ) ;
107+
108+ data [ galaxy ] . civilizations = civilizations ;
109+
110+ civilizations . forEach ( civ => {
111+ data [ galaxy ] . regions [ civ ] = galaxyData
112+ . filter ( item => item . title . civilizeD === civ )
113+ . map ( item => ( {
114+ name : item . title . pageName ,
115+ coordinates : item . title . coordinateS ,
116+ } ) )
117+ . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ;
118+ } ) ;
119+ } ) ;
120+
121+ return { galaxies, data } ;
122+ } else {
123+ throw new Error ( 'No valid data could be fetched' ) ;
124+ }
125+ } ;
126+
127+ const main = async ( ) => {
128+ try {
129+ console . log ( '=== Starting defaultData.json update ===' ) ;
130+
131+ const result = await fetchAllCivilizationsAndRegions ( ) ;
132+
133+ const outputPath = path . join ( __dirname , '../../public/assets/defaultData/defaultData.json' ) ;
134+ const outputDir = path . dirname ( outputPath ) ;
135+
136+ if ( ! fs . existsSync ( outputDir ) ) {
137+ fs . mkdirSync ( outputDir , { recursive : true } ) ;
138+ }
139+
140+ fs . writeFileSync ( outputPath , JSON . stringify ( result , null , 2 ) ) ;
141+
142+ console . log ( `=== Data successfully saved to ${ outputPath } ===` ) ;
143+ console . log ( `Total galaxies: ${ result . galaxies . length } ` ) ;
144+ console . log ( `Total civilizations: ${ Object . values ( result . data ) . reduce ( ( sum , g ) => sum + g . civilizations . length , 0 ) } ` ) ;
145+
146+ } catch ( error ) {
147+ console . error ( '=== Error updating data ===' ) ;
148+ console . error ( error ) ;
149+ process . exit ( 1 ) ;
150+ }
151+ } ;
152+
153+ main ( ) ;
0 commit comments