@nekosuneprojects/gaming-infos 2.1.0 โ 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/sync-api-cache.yml +72 -0
- package/CACHE_SYNC.md +172 -0
- package/CHANGELOG.md +23 -2
- package/README.md +455 -126
- package/data/arknightsendfield/meta.json +14 -0
- package/data/fortnite/meta.json +14 -0
- package/data/game-codes/.gitkeep +0 -0
- package/data/toweroffantasy/meta.json +14 -0
- package/data/vrchat/avatars/.gitkeep +0 -0
- package/data/warframe/meta.json +14 -0
- package/data/wutheringwaves/meta.json +14 -0
- package/data/zenlesszonezero/meta.json +14 -0
- package/gamecodes.js +178 -0
- package/index.js +34 -17
- package/package.json +20 -2
- package/scripts/cache-sync-smoke.js +92 -0
- package/scripts/game-code-cache-smoke.js +85 -0
- package/scripts/sync-all-cache.js +18 -0
- package/scripts/sync-api-cache.js +319 -0
- package/scripts/sync-game-code-cache.js +244 -0
- package/scripts/sync-gaming-info-cache.js +46 -0
package/README.md
CHANGED
|
@@ -1,20 +1,50 @@
|
|
|
1
1
|
# ๐ @nekosuneprojects/gaming-infos
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
Started as VRChat-only (`vrchat-infos`), now built to grow across games. Currently covers **VRChat**,
|
|
5
|
-
**Genshin Impact**, **Neverness to Everness (NTE)**, and **Honkai: Star Rail** โ with more to come.
|
|
3
|
+
[](https://www.npmjs.com/package/@nekosuneprojects/gaming-infos)
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
A Node.js data package for **game information, VRChat community data, characters, redeem codes, and creator codes**.
|
|
6
|
+
|
|
7
|
+
The package is **API-first**: it reads from the NekoSuneVR V5 API whenever possible, then automatically falls back to bundled JSON when the API is unavailable. The fallback data in this repository is mirrored from APINODE once per day using an atomic add/change/remove synchronization system.
|
|
8
|
+
|
|
9
|
+
Current package version: **2.2.0**
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## โจ What it provides
|
|
14
|
+
|
|
15
|
+
- ๐ฎ Multi-game metadata and character data
|
|
16
|
+
- ๐ Live NekoSuneVR V5 API lookups
|
|
17
|
+
- ๐พ Automatic local JSON fallback when the API is unavailable
|
|
18
|
+
- ๐ Daily APINODE โ repository cache synchronization
|
|
19
|
+
- ๐งน Add/change/remove mirroring so deleted API entries disappear from the next successful fallback snapshot
|
|
20
|
+
- ๐ก๏ธ Last-good-cache protection if APINODE is down or a sync only partially succeeds
|
|
21
|
+
- ๐ค VRChat players
|
|
22
|
+
- ๐ฅ VRChat groups
|
|
23
|
+
- ๐ VRChat worlds
|
|
24
|
+
- ๐ง VRChat avatars
|
|
25
|
+
- ๐ง Character/roster datasets for supported games
|
|
26
|
+
- ๐ Redeem-code and creator-code helpers
|
|
27
|
+
- ๐ Game-code directory, counts, aliases, status, and source-cache information
|
|
28
|
+
- ๐งช Offline smoke tests for cache replacement and failure recovery
|
|
9
29
|
|
|
10
30
|
---
|
|
11
31
|
|
|
12
|
-
##
|
|
32
|
+
## ๐ฎ Gaming Infos coverage
|
|
13
33
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
34
|
+
| Game | Slug | Data |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| VRChat | `vrchat` | players, groups, worlds, avatars |
|
|
37
|
+
| Genshin Impact | `genshinimpact` | characters |
|
|
38
|
+
| Honkai: Star Rail | `honkaistarrail` | characters |
|
|
39
|
+
| Neverness to Everness | `nte` | characters |
|
|
40
|
+
| Wuthering Waves | `wutheringwaves` | Resonators under `characters` |
|
|
41
|
+
| Warframe | `warframe` | Warframes under `characters` |
|
|
42
|
+
| Fortnite | `fortnite` | current/released Battle Royale characters |
|
|
43
|
+
| Zenless Zone Zero | `zenlesszonezero` | Agents under `characters` |
|
|
44
|
+
| Tower of Fantasy | `toweroffantasy` | Simulacra under `characters` |
|
|
45
|
+
| Arknights: Endfield | `arknightsendfield` | Operators under `characters` |
|
|
46
|
+
|
|
47
|
+
The Game Codes system is separate and its supported game list is returned dynamically by the APINODE `/codes` directory endpoint.
|
|
18
48
|
|
|
19
49
|
---
|
|
20
50
|
|
|
@@ -24,181 +54,480 @@ without needing a new npm release. If the API can't be reached, it falls back to
|
|
|
24
54
|
npm install @nekosuneprojects/gaming-infos
|
|
25
55
|
```
|
|
26
56
|
|
|
27
|
-
|
|
57
|
+
Requires **Node.js 18 or newer**.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
# ๐ Quick start
|
|
28
62
|
|
|
29
63
|
```js
|
|
30
64
|
const gamingInfos = require('@nekosuneprojects/gaming-infos');
|
|
31
65
|
|
|
32
|
-
|
|
33
|
-
const games = await gamingInfos.Games();
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
66
|
+
async function main() {
|
|
67
|
+
const games = await gamingInfos.Games();
|
|
68
|
+
const vrchat = await gamingInfos.Game('vrchat');
|
|
69
|
+
|
|
70
|
+
const worlds = await gamingInfos.List('vrchat', 'worlds');
|
|
71
|
+
const avatars = await gamingInfos.List('vrchat', 'avatars');
|
|
72
|
+
const genshinCharacters = await gamingInfos.List('genshinimpact', 'characters');
|
|
73
|
+
const wuwaCharacters = await gamingInfos.List('wutheringwaves', 'characters');
|
|
74
|
+
|
|
75
|
+
console.log({
|
|
76
|
+
gameCount: games.length,
|
|
77
|
+
vrchat,
|
|
78
|
+
worlds: worlds.length,
|
|
79
|
+
avatars: avatars.length,
|
|
80
|
+
genshinCharacters: genshinCharacters.length,
|
|
81
|
+
wuwaCharacters: wuwaCharacters.length
|
|
82
|
+
});
|
|
83
|
+
}
|
|
39
84
|
|
|
40
|
-
|
|
41
|
-
})();
|
|
85
|
+
main();
|
|
42
86
|
```
|
|
43
87
|
|
|
44
|
-
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
# ๐ง Gaming Infos API
|
|
91
|
+
|
|
92
|
+
## `Games()`
|
|
93
|
+
|
|
94
|
+
Returns every game with bundled/API Gaming Infos metadata.
|
|
45
95
|
|
|
96
|
+
```js
|
|
97
|
+
const games = await gamingInfos.Games();
|
|
46
98
|
```
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
โโโ players/<name>.json
|
|
53
|
-
โโโ characters/<name>.json (for character-driven games, e.g. Genshin Impact)
|
|
99
|
+
|
|
100
|
+
Live endpoint:
|
|
101
|
+
|
|
102
|
+
```http
|
|
103
|
+
GET /v5/games/api/gaming-infos
|
|
54
104
|
```
|
|
55
105
|
|
|
56
|
-
|
|
106
|
+
## `Game(game)`
|
|
57
107
|
|
|
58
|
-
|
|
59
|
-
|---|---|
|
|
60
|
-
| `Games()` | Every supported game's meta info, in one array |
|
|
61
|
-
| `Game(game)` | Game-level info, e.g. `data/vrchat/meta.json` |
|
|
62
|
-
| `Worlds(game, name)` | A world entry |
|
|
63
|
-
| `Groups(game, name)` | A group entry |
|
|
64
|
-
| `Players(game, name)` | A player entry |
|
|
65
|
-
| `Characters(game, name)` | A character entry (games like Genshin Impact) |
|
|
66
|
-
| `Get(game, type, name)` | Generic escape hatch for any other entity type a future game needs |
|
|
67
|
-
| `List(game, type)` | Every entry of a type for a game, e.g. `List('genshinimpact', 'characters')` |
|
|
108
|
+
Returns game-level metadata.
|
|
68
109
|
|
|
69
|
-
|
|
110
|
+
```js
|
|
111
|
+
const game = await gamingInfos.Game('warframe');
|
|
112
|
+
```
|
|
70
113
|
|
|
71
|
-
|
|
114
|
+
## `List(game, type)`
|
|
72
115
|
|
|
73
|
-
|
|
74
|
-
|---|---|---|
|
|
75
|
-
| `GAMING_INFOS_API_BASE` | `https://api.nekosunevr.co.uk` | Base URL of the NekoSuneVR V5 API |
|
|
76
|
-
| `GAMING_INFOS_API_PATH` | `/v5/games/api/gaming-infos` | Path prefix for the gaming-infos endpoint |
|
|
77
|
-
| `GAMING_INFOS_DISABLE_API` | unset | Set to `1`/`true` to force local-only lookups (no network calls) |
|
|
78
|
-
| `GAMING_INFOS_TIMEOUT_MS` | `4000` | API request timeout before falling back to local JSON |
|
|
116
|
+
Returns every entity for a game/type.
|
|
79
117
|
|
|
80
|
-
|
|
118
|
+
```js
|
|
119
|
+
const resonators = await gamingInfos.List('wutheringwaves', 'characters');
|
|
120
|
+
const agents = await gamingInfos.List('zenlesszonezero', 'characters');
|
|
121
|
+
const operators = await gamingInfos.List('arknightsendfield', 'characters');
|
|
122
|
+
const vrchatGroups = await gamingInfos.List('vrchat', 'groups');
|
|
123
|
+
```
|
|
81
124
|
|
|
82
|
-
|
|
125
|
+
Live endpoint:
|
|
83
126
|
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
"name": "The Black Cat",
|
|
87
|
-
"title": "Main Hall",
|
|
88
|
-
"creator": "spookyghostboo",
|
|
89
|
-
"aliases": "Black Cat",
|
|
90
|
-
"image": "https://example.com/images/world.jpg",
|
|
91
|
-
"description": "A cozy hangout world for friends.",
|
|
92
|
-
"url": "VRCHAT WORLD URL"
|
|
93
|
-
}
|
|
127
|
+
```http
|
|
128
|
+
GET /v5/games/api/gaming-infos/:game/:type
|
|
94
129
|
```
|
|
95
130
|
|
|
96
|
-
##
|
|
131
|
+
## Single-entity helpers
|
|
132
|
+
|
|
133
|
+
```js
|
|
134
|
+
await gamingInfos.Worlds('vrchat', 'world-slug');
|
|
135
|
+
await gamingInfos.Groups('vrchat', 'group-slug');
|
|
136
|
+
await gamingInfos.Players('vrchat', 'player-slug');
|
|
137
|
+
await gamingInfos.Avatars('vrchat', 'avatar-slug');
|
|
138
|
+
await gamingInfos.Characters('warframe', 'warframe-slug');
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Generic lookup:
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
await gamingInfos.Get('vrchat', 'worlds', 'world-slug');
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Live endpoint:
|
|
148
|
+
|
|
149
|
+
```http
|
|
150
|
+
GET /v5/games/api/gaming-infos/:game/:type/:name
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
The V5 API returns stable `slug` values for list entries. Use those slugs for detail lookups instead of trying to generate filenames from display names yourself.
|
|
154
|
+
|
|
155
|
+
## `CacheInfo()`
|
|
156
|
+
|
|
157
|
+
Reads information about the last mirrored Gaming Infos fallback snapshot.
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
const cache = await gamingInfos.CacheInfo();
|
|
161
|
+
console.log(cache?.syncedAt, cache?.contentHash);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
# ๐ Game Codes API
|
|
167
|
+
|
|
168
|
+
Version 2.2.0 adds API-first redeem-code and creator-code support using the same fallback model.
|
|
169
|
+
|
|
170
|
+
APINODE endpoints:
|
|
171
|
+
|
|
172
|
+
```http
|
|
173
|
+
GET /v5/games/api/codes
|
|
174
|
+
GET /v5/games/api/codes/status
|
|
175
|
+
GET /v5/games/api/codes/:game
|
|
176
|
+
GET /v5/games/api/codes/:game/:code
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
`/codes/status` is cache/status data only and does **not** trigger website scraping or a source refresh.
|
|
180
|
+
|
|
181
|
+
## `Codes()`
|
|
182
|
+
|
|
183
|
+
Returns the Game Codes directory, including supported games, aliases, metadata, counters, source counts, and endpoint information.
|
|
184
|
+
|
|
185
|
+
```js
|
|
186
|
+
const directory = await gamingInfos.Codes();
|
|
187
|
+
|
|
188
|
+
console.log(directory.games);
|
|
189
|
+
console.log(directory.aliases);
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## `CodesStatus()`
|
|
193
|
+
|
|
194
|
+
Returns the cached source-refresh state.
|
|
195
|
+
|
|
196
|
+
```js
|
|
197
|
+
const status = await gamingInfos.CodesStatus();
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## `GameCodes(game, options)`
|
|
201
|
+
|
|
202
|
+
Returns code lists using the existing APINODE response shape:
|
|
203
|
+
|
|
204
|
+
```js
|
|
205
|
+
const fortniteCodes = await gamingInfos.GameCodes('fortnite');
|
|
206
|
+
|
|
207
|
+
console.log(fortniteCodes.Active);
|
|
208
|
+
console.log(fortniteCodes.Expired);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Default shape:
|
|
97
212
|
|
|
98
213
|
```json
|
|
99
214
|
{
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"image": "https://example.com/images/group.png",
|
|
103
|
-
"description": "A friendly VRChat group for chill vibes and fun events.",
|
|
104
|
-
"url": "VRCHAT GROUP URL"
|
|
215
|
+
"Active": [],
|
|
216
|
+
"Expired": []
|
|
105
217
|
}
|
|
106
218
|
```
|
|
107
219
|
|
|
108
|
-
|
|
220
|
+
Include queued/unknown records:
|
|
221
|
+
|
|
222
|
+
```js
|
|
223
|
+
const allFortniteCodes = await gamingInfos.GameCodes('fortnite', {
|
|
224
|
+
includeUnknown: true
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Which can return:
|
|
109
229
|
|
|
110
230
|
```json
|
|
111
231
|
{
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
"gender": "Male",
|
|
116
|
-
"aliases": "ChisdealHDYT, Chisdeal2013, Chisdeal2014, ChisdealHD, progamer-gr, DarkBlackWolfs",
|
|
117
|
-
"image": "https://media.discordapp.net/attachments/794229972490387496/794231249652678696/VRChat_1920x1080_2020-09-14_09-22-18.855.png",
|
|
118
|
-
"description": "A long time ago, Wild Player Chisdeal2013 (later known as ChisdealHDYT). He had been hanging out in a place called [The Black Cat](https://vrchat-legends.fandom.com/wiki/The_Black_Cat), [The Great Pug](https://vrchat-legends.fandom.com/wiki/The_Great_Pug) and [Japan Shrine (ITOAR)](https://vrchat-legends.fandom.com/wiki/Japan_Shrine_(ITOAR)). He had been talking about how he wanted to be Popular on [Twitch](https://twitch.tv/chisdealhdyt) and [TikTok](https://www.tiktok.com/@chisdealhd) / [YouTube](https://www.youtube.com/chisdealhd). Then he did started to streaming on Twitch and Upload Videos on TikTok / YouTube. He loves interest Cryptocurrency Money making and has lot support from [ZENZO Community](https://zenzo.io). He building Community with VRChat, Warframe and many more. He want become as VTuber as Twitch and doing a lot of VR Gaming. That dream is coming very soon in stage getting VR Headset and Brand new VR Ready PC.\n\nYou should Support this Cutie Streamer much on your Heart it can go.",
|
|
119
|
-
"url": "https://creator.nekosunevr.co.uk"
|
|
232
|
+
"Active": [],
|
|
233
|
+
"Expired": [],
|
|
234
|
+
"Unknown": []
|
|
120
235
|
}
|
|
121
236
|
```
|
|
122
237
|
|
|
123
|
-
|
|
238
|
+
Filtering is supported:
|
|
239
|
+
|
|
240
|
+
```js
|
|
241
|
+
const creatorCodes = await gamingInfos.GameCodes('fortnite', {
|
|
242
|
+
category: 'creator-code',
|
|
243
|
+
includeUnknown: true
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const freeCodes = await gamingInfos.GameCodes('genshin-impact', {
|
|
247
|
+
claimType: 'free'
|
|
248
|
+
});
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Timezone can also be passed through to the live API:
|
|
252
|
+
|
|
253
|
+
```js
|
|
254
|
+
const codes = await gamingInfos.GameCodes('fortnite', {
|
|
255
|
+
timezone: 'Europe/London',
|
|
256
|
+
includeUnknown: true
|
|
257
|
+
});
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Cached aliases from the `/codes` directory are resolved during API outages as well, so aliases such as `fn`, `genshin`, `hsr`, or `wuwa` can still map to their canonical cached game dataset.
|
|
261
|
+
|
|
262
|
+
## `GameCode(game, code, options)`
|
|
263
|
+
|
|
264
|
+
Looks up one specific code.
|
|
265
|
+
|
|
266
|
+
```js
|
|
267
|
+
const creator = await gamingInfos.GameCode('fortnite', 'NEKOSUNEVR');
|
|
268
|
+
console.log(creator);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Live endpoint:
|
|
272
|
+
|
|
273
|
+
```http
|
|
274
|
+
GET /v5/games/api/codes/:game/:code
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
When APINODE is unavailable, the package searches the locally mirrored Active, Expired, and Unknown code buckets.
|
|
278
|
+
|
|
279
|
+
## `CodeCacheInfo()`
|
|
280
|
+
|
|
281
|
+
Returns the local Game Codes cache manifest.
|
|
282
|
+
|
|
283
|
+
```js
|
|
284
|
+
const codeCache = await gamingInfos.CodeCacheInfo();
|
|
285
|
+
console.log(codeCache?.syncedAt, codeCache?.stats);
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
# ๐ Function reference
|
|
291
|
+
|
|
292
|
+
| Function | Purpose |
|
|
293
|
+
|---|---|
|
|
294
|
+
| `Games()` | List Gaming Infos games |
|
|
295
|
+
| `Game(game)` | Get game metadata |
|
|
296
|
+
| `List(game, type)` | List every entry for one game/type |
|
|
297
|
+
| `Worlds(game, name)` | Get one world |
|
|
298
|
+
| `Groups(game, name)` | Get one group |
|
|
299
|
+
| `Players(game, name)` | Get one player |
|
|
300
|
+
| `Avatars(game, name)` | Get one avatar |
|
|
301
|
+
| `Characters(game, name)` | Get one character/Warframe/Agent/etc. |
|
|
302
|
+
| `Get(game, type, name)` | Generic entity lookup |
|
|
303
|
+
| `CacheInfo()` | Gaming Infos fallback manifest |
|
|
304
|
+
| `Codes()` | Game Codes directory |
|
|
305
|
+
| `CodesStatus()` | Cached Game Codes source status |
|
|
306
|
+
| `GameCodes(game, options)` | Active/Expired/Unknown code lists |
|
|
307
|
+
| `GameCode(game, code, options)` | One specific redeem/creator code |
|
|
308
|
+
| `CodeCacheInfo()` | Game Codes fallback manifest |
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
# ๐พ API-first fallback behavior
|
|
313
|
+
|
|
314
|
+
Normal reads follow this path:
|
|
315
|
+
|
|
316
|
+
```text
|
|
317
|
+
Application
|
|
318
|
+
โ
|
|
319
|
+
โผ
|
|
320
|
+
NekoSuneVR V5 API
|
|
321
|
+
โ
|
|
322
|
+
โโโ available โโโบ return live data
|
|
323
|
+
โ
|
|
324
|
+
โโโ unavailable
|
|
325
|
+
โ
|
|
326
|
+
โผ
|
|
327
|
+
bundled data/
|
|
328
|
+
โ
|
|
329
|
+
โผ
|
|
330
|
+
return last-good fallback
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
The package does not need an API key for the public read endpoints documented above.
|
|
334
|
+
|
|
335
|
+
Set this to force local-only reads:
|
|
124
336
|
|
|
125
|
-
|
|
337
|
+
```bash
|
|
338
|
+
GAMING_INFOS_DISABLE_API=1
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
# ๐ Daily fallback synchronization
|
|
344
|
+
|
|
345
|
+
The repository automatically runs the cache mirror **once every day at 03:23 UTC** through GitHub Actions.
|
|
346
|
+
|
|
347
|
+
The combined command is:
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npm run sync:cache
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
That performs both:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
npm run sync:gaming-infos-cache
|
|
357
|
+
npm run sync:game-codes-cache
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The synchronization process is designed to be authoritative and failure-safe:
|
|
361
|
+
|
|
362
|
+
1. Download the complete configured API snapshot into a temporary directory.
|
|
363
|
+
2. Validate all required responses.
|
|
364
|
+
3. Calculate content hashes and add/change/remove statistics.
|
|
365
|
+
4. Replace the old fallback only after the new snapshot succeeds completely.
|
|
366
|
+
5. Keep the previous fallback untouched if the API fails, times out, returns an error, or produces an incomplete snapshot.
|
|
367
|
+
6. Commit actual fallback changes back to the repository.
|
|
368
|
+
|
|
369
|
+
Successful syncs mirror **additions, modifications, and removals**. If APINODE removes an entry, that entry is removed from the fallback during the next successful mirror.
|
|
370
|
+
|
|
371
|
+
Gaming Infos and Game Codes use independent atomic caches so a failure in one dataset cannot destroy the last-good snapshot of the other.
|
|
372
|
+
|
|
373
|
+
See [CACHE_SYNC.md](CACHE_SYNC.md) for the detailed cache architecture.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
# ๐งช Cache tests
|
|
378
|
+
|
|
379
|
+
Run all cache safety tests:
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
npm run test:all-cache
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Or individually:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
npm run test:cache-sync
|
|
389
|
+
npm run test:game-code-cache
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
The tests cover scenarios including:
|
|
393
|
+
|
|
394
|
+
- new entries appearing
|
|
395
|
+
- existing entries changing
|
|
396
|
+
- upstream entries being removed
|
|
397
|
+
- duplicate/invalid data protection
|
|
398
|
+
- partial API failures
|
|
399
|
+
- simulated HTTP 5xx outages
|
|
400
|
+
- preserving the last-good fallback after a failed sync
|
|
401
|
+
|
|
402
|
+
---
|
|
403
|
+
|
|
404
|
+
# ๐ Fallback data structure
|
|
405
|
+
|
|
406
|
+
```text
|
|
407
|
+
data/
|
|
408
|
+
โโโ genshinimpact/
|
|
409
|
+
โ โโโ meta.json
|
|
410
|
+
โ โโโ characters/
|
|
411
|
+
โโโ honkaistarrail/
|
|
412
|
+
โโโ nte/
|
|
413
|
+
โโโ wutheringwaves/
|
|
414
|
+
โโโ warframe/
|
|
415
|
+
โโโ fortnite/
|
|
416
|
+
โโโ zenlesszonezero/
|
|
417
|
+
โโโ toweroffantasy/
|
|
418
|
+
โโโ arknightsendfield/
|
|
419
|
+
โโโ vrchat/
|
|
420
|
+
โ โโโ meta.json
|
|
421
|
+
โ โโโ players/
|
|
422
|
+
โ โโโ groups/
|
|
423
|
+
โ โโโ worlds/
|
|
424
|
+
โ โโโ avatars/
|
|
425
|
+
โโโ .cache-manifest.json
|
|
426
|
+
โโโ game-codes/
|
|
427
|
+
โโโ directory.json
|
|
428
|
+
โโโ status.json
|
|
429
|
+
โโโ .cache-manifest.json
|
|
430
|
+
โโโ games/
|
|
431
|
+
โโโ <game>.json
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
An entity with no verified image can use:
|
|
126
435
|
|
|
127
436
|
```json
|
|
128
437
|
{
|
|
129
|
-
|
|
130
|
-
"quote": "Outrider Amber, at the ready!",
|
|
131
|
-
"cv": "Iwami Manaka",
|
|
132
|
-
"description": "A perky, straightforward girl, who is also the only Outrider of the Knights of Favonius.",
|
|
133
|
-
"image": "https://uploadstatic-sea.mihoyo.com/contentweb/20191009/2019100914372396510.png",
|
|
134
|
-
"city": "Mondstadt",
|
|
135
|
-
"url": "https://genshin.mihoyo.com/en/character/mondstadt?char=1",
|
|
136
|
-
"element": "Pyro",
|
|
137
|
-
"weapon": "Bow",
|
|
138
|
-
"rating": 4
|
|
438
|
+
"image": ""
|
|
139
439
|
}
|
|
140
440
|
```
|
|
141
441
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
442
|
+
Consumers should treat a blank image string as "no verified image available".
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
# โ๏ธ Environment variables
|
|
145
447
|
|
|
146
|
-
##
|
|
448
|
+
## Runtime API reads
|
|
147
449
|
|
|
148
|
-
|
|
450
|
+
| Variable | Default | Purpose |
|
|
451
|
+
|---|---|---|
|
|
452
|
+
| `GAMING_INFOS_API_BASE` | `https://api.nekosunevr.co.uk` | NekoSuneVR APINODE base URL |
|
|
453
|
+
| `GAMING_INFOS_API_PATH` | `/v5/games/api/gaming-infos` | Gaming Infos path |
|
|
454
|
+
| `GAME_CODES_API_PATH` | `/v5/games/api/codes` | Game Codes path |
|
|
455
|
+
| `GAMING_INFOS_DISABLE_API` | unset | `1`/`true` forces local-only operation |
|
|
456
|
+
| `GAMING_INFOS_TIMEOUT_MS` | `4000` | Runtime API timeout before fallback |
|
|
149
457
|
|
|
150
|
-
|
|
458
|
+
## Cache mirror
|
|
151
459
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
460
|
+
| Variable | Default | Purpose |
|
|
461
|
+
|---|---|---|
|
|
462
|
+
| `GAMING_INFOS_CACHE_TIMEOUT_MS` | `15000` | Gaming Infos sync request timeout |
|
|
463
|
+
| `GAMING_INFOS_CACHE_RETRIES` | `2` | Gaming Infos retry count |
|
|
464
|
+
| `GAMING_INFOS_CACHE_RETRY_DELAY_MS` | `750` | Gaming Infos retry delay |
|
|
465
|
+
| `GAME_CODES_CACHE_TIMEOUT_MS` | `15000` | Game Codes sync request timeout |
|
|
466
|
+
| `GAME_CODES_CACHE_RETRIES` | `2` | Game Codes retry count |
|
|
467
|
+
| `GAME_CODES_CACHE_RETRY_DELAY_MS` | `750` | Game Codes retry delay |
|
|
468
|
+
| `GAME_CODES_CACHE_GAME_DELAY_MS` | small delay | Delay between per-game code snapshots |
|
|
156
469
|
|
|
157
|
-
|
|
470
|
+
---
|
|
158
471
|
|
|
159
|
-
|
|
160
|
-
- Any PR containing harassment, defamation, or private information will be rejected and reported.
|
|
161
|
-
- Respect each game's Terms of Service and Community Guidelines.
|
|
162
|
-
- Do not include private details, logs, or non-public data.
|
|
472
|
+
# ๐ Example character entry
|
|
163
473
|
|
|
164
|
-
|
|
474
|
+
Different games expose different fields. Consumers should use the fields relevant to that game rather than assuming every title has the same schema.
|
|
165
475
|
|
|
166
|
-
Each entry must include a valid image URL in its JSON:
|
|
167
476
|
```json
|
|
168
|
-
|
|
477
|
+
{
|
|
478
|
+
"name": "Example Character",
|
|
479
|
+
"slug": "examplecharacter",
|
|
480
|
+
"rarity": "5-star",
|
|
481
|
+
"element": "Electro",
|
|
482
|
+
"weapon": "Sword",
|
|
483
|
+
"description": "Public character information.",
|
|
484
|
+
"image": "https://example.com/character.webp",
|
|
485
|
+
"url": "https://example.com/source",
|
|
486
|
+
"source": {
|
|
487
|
+
"provider": "Public source",
|
|
488
|
+
"publicDataOnly": true
|
|
489
|
+
}
|
|
490
|
+
}
|
|
169
491
|
```
|
|
170
492
|
|
|
171
|
-
|
|
493
|
+
---
|
|
172
494
|
|
|
173
|
-
|
|
495
|
+
# ๐ค Contributions
|
|
174
496
|
|
|
175
|
-
|
|
176
|
-
data/
|
|
177
|
-
โโโ <game>/
|
|
178
|
-
โโโ meta.json
|
|
179
|
-
โโโ worlds/
|
|
180
|
-
โโโ groups/
|
|
181
|
-
โโโ players/
|
|
182
|
-
โโโ characters/
|
|
183
|
-
```
|
|
497
|
+
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
184
498
|
|
|
185
|
-
|
|
499
|
+
Please follow these rules:
|
|
186
500
|
|
|
187
|
-
|
|
501
|
+
- Only include publicly available data or data you have permission to publish.
|
|
502
|
+
- Do not include private profiles, private Discord messages, DMs, private logs, authentication data, or personal information.
|
|
503
|
+
- Do not add leaks, datamined/unreleased content, hidden APIs, memory-inspection data, or client-extracted private data.
|
|
504
|
+
- Respect each game's Terms of Service and community rules.
|
|
505
|
+
- Keep sources clear and verifiable.
|
|
506
|
+
- Do not submit harassment, defamation, doxxing, or invasive profile information.
|
|
188
507
|
|
|
189
|
-
|
|
508
|
+
---
|
|
509
|
+
|
|
510
|
+
# โ ๏ธ Package fallback note
|
|
511
|
+
|
|
512
|
+
GitHub repository cache snapshots update automatically, but published npm packages are immutable.
|
|
513
|
+
|
|
514
|
+
An already-installed npm release keeps the fallback JSON bundled with that release until you update the package. While APINODE is online, live API reads still provide current data without requiring a package release.
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
# โ ๏ธ Disclaimer
|
|
519
|
+
|
|
520
|
+
This project is not affiliated with or endorsed by VRChat Inc., HoYoverse, Kuro Games, Digital Extremes, Epic Games, Hotta Studio, Hypergryph/GRYPHLINE, or any other game publisher represented by the data.
|
|
190
521
|
|
|
191
|
-
|
|
522
|
+
Game names, logos, characters, and related trademarks belong to their respective owners.
|
|
523
|
+
|
|
524
|
+
---
|
|
192
525
|
|
|
193
|
-
|
|
194
|
-
All names, logos, and related elements are property of their respective owners.
|
|
195
|
-
Always follow each game's official Terms of Service and Community Guidelines
|
|
196
|
-
(e.g. [VRChat](https://hello.vrchat.com/legal) / [VRChat Community Guidelines](https://hello.vrchat.com/community-guidelines)).
|
|
526
|
+
# ๐ง Credits
|
|
197
527
|
|
|
198
|
-
|
|
528
|
+
Maintained by **NekoSune Projects**.
|
|
199
529
|
|
|
200
|
-
|
|
201
|
-
๐พ Contributions welcome โ stay game-friendly!
|
|
530
|
+
Contributions are welcome โ keep the data public, accurate, and game-friendly.
|
|
202
531
|
|
|
203
532
|
<!-- GitAds-Verify: 2XHQSF1IKOWF4FH8P2TRI5GRWIJG2TJP -->
|
|
204
533
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Arknights: Endfield",
|
|
3
|
+
"title": "3D real-time strategy action RPG by Hypergryph.",
|
|
4
|
+
"engine": "Unity",
|
|
5
|
+
"Platform": "Windows, PlayStation 5, iOS, Android",
|
|
6
|
+
"Release date": "2026",
|
|
7
|
+
"Genre": "Action RPG, Strategy, Gacha",
|
|
8
|
+
"developers": "Hypergryph",
|
|
9
|
+
"publisher": "GRYPHLINE",
|
|
10
|
+
"aliases": "Endfield, Arknights Endfield",
|
|
11
|
+
"image": "https://endfield.gryphline.com/favicon.ico",
|
|
12
|
+
"description": "Arknights spin-off featuring playable Operators with classes, elements, weapons and factions.",
|
|
13
|
+
"url": "https://endfield.gryphline.com/"
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Fortnite",
|
|
3
|
+
"title": "Epic Games online ecosystem featuring Battle Royale and creator experiences.",
|
|
4
|
+
"engine": "Unreal Engine 5",
|
|
5
|
+
"Platform": "Windows, PlayStation, Xbox, Nintendo Switch, Android, Cloud",
|
|
6
|
+
"Release date": "July 25, 2017",
|
|
7
|
+
"Genre": "Battle Royale, Action, Sandbox",
|
|
8
|
+
"developers": "Epic Games",
|
|
9
|
+
"publisher": "Epic Games",
|
|
10
|
+
"aliases": "Fortnite, FN",
|
|
11
|
+
"image": "https://www.fortnite.com/favicon.ico",
|
|
12
|
+
"description": "Fortnite characters, current Battle Royale NPCs and related public game information.",
|
|
13
|
+
"url": "https://www.fortnite.com/"
|
|
14
|
+
}
|