@nekosuneprojects/gaming-infos 2.2.0 → 3.0.1

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.
Files changed (277) hide show
  1. package/CHANGELOG.md +77 -3
  2. package/README.md +62 -495
  3. package/index.js +3 -223
  4. package/package.json +53 -46
  5. package/src/providers/vrchat.js +11 -0
  6. package/src/providers/warframe.js +7 -0
  7. package/src/registry.js +23 -0
  8. package/.github/workflows/npm-publish-github-packages.yml +0 -56
  9. package/.github/workflows/npm-publish.yml +0 -71
  10. package/.github/workflows/sync-api-cache.yml +0 -72
  11. package/CACHE_SYNC.md +0 -172
  12. package/CONTRIBUTING.md +0 -217
  13. package/DATA.md +0 -292
  14. package/data/arknightsendfield/meta.json +0 -14
  15. package/data/fortnite/meta.json +0 -14
  16. package/data/game-codes/.gitkeep +0 -0
  17. package/data/genshinimpact/characters/albedo.json +0 -11
  18. package/data/genshinimpact/characters/alhaitham.json +0 -12
  19. package/data/genshinimpact/characters/aloy.json +0 -11
  20. package/data/genshinimpact/characters/amber.json +0 -12
  21. package/data/genshinimpact/characters/aratakiitto.json +0 -12
  22. package/data/genshinimpact/characters/arlecchino.json +0 -12
  23. package/data/genshinimpact/characters/baizhu.json +0 -12
  24. package/data/genshinimpact/characters/barbara.json +0 -11
  25. package/data/genshinimpact/characters/beidou.json +0 -12
  26. package/data/genshinimpact/characters/bennett.json +0 -11
  27. package/data/genshinimpact/characters/candace.json +0 -12
  28. package/data/genshinimpact/characters/charlotte.json +0 -11
  29. package/data/genshinimpact/characters/chasca.json +0 -11
  30. package/data/genshinimpact/characters/chevreuse.json +0 -11
  31. package/data/genshinimpact/characters/chiori.json +0 -11
  32. package/data/genshinimpact/characters/chongyun.json +0 -12
  33. package/data/genshinimpact/characters/citlali.json +0 -11
  34. package/data/genshinimpact/characters/clorinde.json +0 -11
  35. package/data/genshinimpact/characters/collei.json +0 -12
  36. package/data/genshinimpact/characters/cyno.json +0 -12
  37. package/data/genshinimpact/characters/dahlia.json +0 -10
  38. package/data/genshinimpact/characters/dehya.json +0 -11
  39. package/data/genshinimpact/characters/diluc.json +0 -11
  40. package/data/genshinimpact/characters/diona.json +0 -11
  41. package/data/genshinimpact/characters/dori.json +0 -11
  42. package/data/genshinimpact/characters/durin.json +0 -11
  43. package/data/genshinimpact/characters/emilie.json +0 -11
  44. package/data/genshinimpact/characters/escoffier.json +0 -12
  45. package/data/genshinimpact/characters/eula.json +0 -11
  46. package/data/genshinimpact/characters/faruzan.json +0 -12
  47. package/data/genshinimpact/characters/fischl.json +0 -12
  48. package/data/genshinimpact/characters/freminet.json +0 -11
  49. package/data/genshinimpact/characters/furina.json +0 -12
  50. package/data/genshinimpact/characters/gaming.json +0 -11
  51. package/data/genshinimpact/characters/ganyu.json +0 -11
  52. package/data/genshinimpact/characters/gorou.json +0 -12
  53. package/data/genshinimpact/characters/hutao.json +0 -12
  54. package/data/genshinimpact/characters/iansan.json +0 -11
  55. package/data/genshinimpact/characters/ineffa.json +0 -11
  56. package/data/genshinimpact/characters/jean.json +0 -11
  57. package/data/genshinimpact/characters/kachina.json +0 -11
  58. package/data/genshinimpact/characters/kaedeharakazuha.json +0 -12
  59. package/data/genshinimpact/characters/kaeya.json +0 -11
  60. package/data/genshinimpact/characters/kamisatoayaka.json +0 -11
  61. package/data/genshinimpact/characters/kamisatoayato.json +0 -11
  62. package/data/genshinimpact/characters/kaveh.json +0 -12
  63. package/data/genshinimpact/characters/keqing.json +0 -11
  64. package/data/genshinimpact/characters/kinich.json +0 -11
  65. package/data/genshinimpact/characters/kirara.json +0 -11
  66. package/data/genshinimpact/characters/klee.json +0 -11
  67. package/data/genshinimpact/characters/kujousara.json +0 -11
  68. package/data/genshinimpact/characters/kukishinobu.json +0 -12
  69. package/data/genshinimpact/characters/lanyan.json +0 -11
  70. package/data/genshinimpact/characters/layla.json +0 -11
  71. package/data/genshinimpact/characters/lisa.json +0 -12
  72. package/data/genshinimpact/characters/lohen.json +0 -11
  73. package/data/genshinimpact/characters/lynette.json +0 -11
  74. package/data/genshinimpact/characters/lyney.json +0 -11
  75. package/data/genshinimpact/characters/mavuika.json +0 -11
  76. package/data/genshinimpact/characters/mikaschmidt.json +0 -11
  77. package/data/genshinimpact/characters/mona.json +0 -12
  78. package/data/genshinimpact/characters/mualani.json +0 -11
  79. package/data/genshinimpact/characters/nahida.json +0 -12
  80. package/data/genshinimpact/characters/navia.json +0 -11
  81. package/data/genshinimpact/characters/neuvillette.json +0 -11
  82. package/data/genshinimpact/characters/nilou.json +0 -11
  83. package/data/genshinimpact/characters/ningguang.json +0 -11
  84. package/data/genshinimpact/characters/noelle.json +0 -12
  85. package/data/genshinimpact/characters/ororon.json +0 -11
  86. package/data/genshinimpact/characters/prune.json +0 -10
  87. package/data/genshinimpact/characters/qiqi.json +0 -12
  88. package/data/genshinimpact/characters/raidenshogun.json +0 -12
  89. package/data/genshinimpact/characters/razor.json +0 -11
  90. package/data/genshinimpact/characters/rosaria.json +0 -12
  91. package/data/genshinimpact/characters/sangonomiyakokomi.json +0 -12
  92. package/data/genshinimpact/characters/sayu.json +0 -11
  93. package/data/genshinimpact/characters/sethos.json +0 -11
  94. package/data/genshinimpact/characters/shenhe.json +0 -12
  95. package/data/genshinimpact/characters/shikanoinheizou.json +0 -12
  96. package/data/genshinimpact/characters/sigewinne.json +0 -11
  97. package/data/genshinimpact/characters/skirk.json +0 -11
  98. package/data/genshinimpact/characters/sucrose.json +0 -12
  99. package/data/genshinimpact/characters/thoma.json +0 -11
  100. package/data/genshinimpact/characters/tighnari.json +0 -12
  101. package/data/genshinimpact/characters/varesa.json +0 -11
  102. package/data/genshinimpact/characters/varka.json +0 -10
  103. package/data/genshinimpact/characters/venti.json +0 -12
  104. package/data/genshinimpact/characters/wanderer.json +0 -11
  105. package/data/genshinimpact/characters/wriothesley.json +0 -12
  106. package/data/genshinimpact/characters/xiangling.json +0 -12
  107. package/data/genshinimpact/characters/xianyun.json +0 -11
  108. package/data/genshinimpact/characters/xiao.json +0 -11
  109. package/data/genshinimpact/characters/xilonen.json +0 -11
  110. package/data/genshinimpact/characters/xingqiu.json +0 -12
  111. package/data/genshinimpact/characters/xinyan.json +0 -12
  112. package/data/genshinimpact/characters/yaemiko.json +0 -12
  113. package/data/genshinimpact/characters/yanfei.json +0 -12
  114. package/data/genshinimpact/characters/yaoyao.json +0 -12
  115. package/data/genshinimpact/characters/yelan.json +0 -11
  116. package/data/genshinimpact/characters/yoimiya.json +0 -12
  117. package/data/genshinimpact/characters/yumemizukimizuki.json +0 -11
  118. package/data/genshinimpact/characters/yunjin.json +0 -11
  119. package/data/genshinimpact/characters/zhongli.json +0 -11
  120. package/data/genshinimpact/characters/zibai.json +0 -11
  121. package/data/genshinimpact/meta.json +0 -14
  122. package/data/honkaistarrail/characters/acheron.json +0 -12
  123. package/data/honkaistarrail/characters/aglaea.json +0 -12
  124. package/data/honkaistarrail/characters/anaxa.json +0 -12
  125. package/data/honkaistarrail/characters/argenti.json +0 -12
  126. package/data/honkaistarrail/characters/arlan.json +0 -12
  127. package/data/honkaistarrail/characters/ashveil.json +0 -12
  128. package/data/honkaistarrail/characters/asta.json +0 -12
  129. package/data/honkaistarrail/characters/aventurine.json +0 -12
  130. package/data/honkaistarrail/characters/bailu.json +0 -12
  131. package/data/honkaistarrail/characters/blackswan.json +0 -12
  132. package/data/honkaistarrail/characters/blade.json +0 -12
  133. package/data/honkaistarrail/characters/boothill.json +0 -12
  134. package/data/honkaistarrail/characters/bronya.json +0 -12
  135. package/data/honkaistarrail/characters/castorice.json +0 -12
  136. package/data/honkaistarrail/characters/cerydra.json +0 -12
  137. package/data/honkaistarrail/characters/cipher.json +0 -12
  138. package/data/honkaistarrail/characters/clara.json +0 -12
  139. package/data/honkaistarrail/characters/constance.json +0 -12
  140. package/data/honkaistarrail/characters/cyrene.json +0 -12
  141. package/data/honkaistarrail/characters/danheng.json +0 -12
  142. package/data/honkaistarrail/characters/drratio.json +0 -12
  143. package/data/honkaistarrail/characters/feixiao.json +0 -12
  144. package/data/honkaistarrail/characters/firefly.json +0 -12
  145. package/data/honkaistarrail/characters/fuxuan.json +0 -12
  146. package/data/honkaistarrail/characters/gallagher.json +0 -12
  147. package/data/honkaistarrail/characters/gepard.json +0 -12
  148. package/data/honkaistarrail/characters/guinaifen.json +0 -12
  149. package/data/honkaistarrail/characters/hanya.json +0 -12
  150. package/data/honkaistarrail/characters/herta.json +0 -12
  151. package/data/honkaistarrail/characters/himeko.json +0 -13
  152. package/data/honkaistarrail/characters/hook.json +0 -12
  153. package/data/honkaistarrail/characters/huohuo.json +0 -12
  154. package/data/honkaistarrail/characters/hyacine.json +0 -12
  155. package/data/honkaistarrail/characters/hysilens.json +0 -12
  156. package/data/honkaistarrail/characters/jade.json +0 -12
  157. package/data/honkaistarrail/characters/jiaoqiu.json +0 -12
  158. package/data/honkaistarrail/characters/jingliu.json +0 -12
  159. package/data/honkaistarrail/characters/jingyuan.json +0 -12
  160. package/data/honkaistarrail/characters/kafka.json +0 -12
  161. package/data/honkaistarrail/characters/lingsha.json +0 -12
  162. package/data/honkaistarrail/characters/lisushang.json +0 -12
  163. package/data/honkaistarrail/characters/luka.json +0 -12
  164. package/data/honkaistarrail/characters/luocha.json +0 -12
  165. package/data/honkaistarrail/characters/lynx.json +0 -12
  166. package/data/honkaistarrail/characters/march7th.json +0 -12
  167. package/data/honkaistarrail/characters/misha.json +0 -12
  168. package/data/honkaistarrail/characters/moze.json +0 -12
  169. package/data/honkaistarrail/characters/mydei.json +0 -12
  170. package/data/honkaistarrail/characters/natasha.json +0 -12
  171. package/data/honkaistarrail/characters/pela.json +0 -12
  172. package/data/honkaistarrail/characters/phainon.json +0 -12
  173. package/data/honkaistarrail/characters/qingque.json +0 -12
  174. package/data/honkaistarrail/characters/rappa.json +0 -12
  175. package/data/honkaistarrail/characters/robin.json +0 -12
  176. package/data/honkaistarrail/characters/ruanmei.json +0 -12
  177. package/data/honkaistarrail/characters/sampo.json +0 -12
  178. package/data/honkaistarrail/characters/seele.json +0 -12
  179. package/data/honkaistarrail/characters/serval.json +0 -12
  180. package/data/honkaistarrail/characters/silverwolf.json +0 -12
  181. package/data/honkaistarrail/characters/sparkle.json +0 -12
  182. package/data/honkaistarrail/characters/tingyun.json +0 -12
  183. package/data/honkaistarrail/characters/topaz.json +0 -12
  184. package/data/honkaistarrail/characters/tribbie.json +0 -12
  185. package/data/honkaistarrail/characters/weltyang.json +0 -12
  186. package/data/honkaistarrail/characters/xueyi.json +0 -12
  187. package/data/honkaistarrail/characters/yanqing.json +0 -12
  188. package/data/honkaistarrail/characters/yaoguang.json +0 -12
  189. package/data/honkaistarrail/characters/yukong.json +0 -12
  190. package/data/honkaistarrail/characters/yunli.json +0 -12
  191. package/data/honkaistarrail/meta.json +0 -14
  192. package/data/nte/characters/adler.json +0 -14
  193. package/data/nte/characters/aurelia.json +0 -14
  194. package/data/nte/characters/baicang.json +0 -14
  195. package/data/nte/characters/chaos.json +0 -14
  196. package/data/nte/characters/chiz.json +0 -14
  197. package/data/nte/characters/daffodill.json +0 -14
  198. package/data/nte/characters/edgar.json +0 -14
  199. package/data/nte/characters/esperzero.json +0 -14
  200. package/data/nte/characters/fadia.json +0 -14
  201. package/data/nte/characters/haniel.json +0 -14
  202. package/data/nte/characters/hathor.json +0 -14
  203. package/data/nte/characters/hotori.json +0 -14
  204. package/data/nte/characters/iroi.json +0 -14
  205. package/data/nte/characters/jiuyuan.json +0 -14
  206. package/data/nte/characters/lacrimosa.json +0 -14
  207. package/data/nte/characters/mint.json +0 -14
  208. package/data/nte/characters/nanally.json +0 -14
  209. package/data/nte/characters/sakiri.json +0 -14
  210. package/data/nte/characters/shinku.json +0 -14
  211. package/data/nte/characters/skia.json +0 -14
  212. package/data/nte/meta.json +0 -14
  213. package/data/toweroffantasy/meta.json +0 -14
  214. package/data/vrchat/avatars/.gitkeep +0 -0
  215. package/data/vrchat/groups/clubzodiac.json +0 -7
  216. package/data/vrchat/groups/dirtydancers.json +0 -7
  217. package/data/vrchat/groups/drumsynews.json +0 -7
  218. package/data/vrchat/groups/ebola20.json +0 -7
  219. package/data/vrchat/groups/internationaldancersassociation.json +0 -7
  220. package/data/vrchat/groups/kannagang.json +0 -6
  221. package/data/vrchat/groups/lolisquad.json +0 -7
  222. package/data/vrchat/groups/nekonightsnightclub.json +0 -7
  223. package/data/vrchat/groups/nekostudios.json +0 -7
  224. package/data/vrchat/groups/nekosunecommunity.json +0 -7
  225. package/data/vrchat/groups/voidclub.json +0 -7
  226. package/data/vrchat/groups/voltdanceclub.json +0 -7
  227. package/data/vrchat/groups/vrceventsgroup.json +0 -7
  228. package/data/vrchat/groups/vrchatcommunitydiscord.json +0 -6
  229. package/data/vrchat/meta.json +0 -13
  230. package/data/vrchat/players/alto.json +0 -9
  231. package/data/vrchat/players/arcadum.json +0 -10
  232. package/data/vrchat/players/chairhandler.json +0 -9
  233. package/data/vrchat/players/chipz.json +0 -9
  234. package/data/vrchat/players/hikarivr.json +0 -10
  235. package/data/vrchat/players/kimple.json +0 -10
  236. package/data/vrchat/players/linkzr.json +0 -8
  237. package/data/vrchat/players/nagzz21.json +0 -9
  238. package/data/vrchat/players/nebride.json +0 -10
  239. package/data/vrchat/players/nekosunevr.json +0 -10
  240. package/data/vrchat/players/pokelawls.json +0 -9
  241. package/data/vrchat/players/qwonk.json +0 -8
  242. package/data/vrchat/players/roflgator.json +0 -10
  243. package/data/vrchat/players/scifri.json +0 -7
  244. package/data/vrchat/players/sodapoppin.json +0 -9
  245. package/data/vrchat/players/woops.json +0 -9
  246. package/data/vrchat/players/zentreya.json +0 -10
  247. package/data/vrchat/worlds/ascensionacademy.json +0 -7
  248. package/data/vrchat/worlds/clubvgl.json +0 -8
  249. package/data/vrchat/worlds/fightfinder.json +0 -8
  250. package/data/vrchat/worlds/hangouthouse.json +0 -7
  251. package/data/vrchat/worlds/nekostudioshalloween.json +0 -9
  252. package/data/vrchat/worlds/nekostudiosnewyear.json +0 -9
  253. package/data/vrchat/worlds/nekostudiosxmas.json +0 -9
  254. package/data/vrchat/worlds/nekosunevranimations2023.json +0 -9
  255. package/data/vrchat/worlds/nekosunevranimations2024.json +0 -9
  256. package/data/vrchat/worlds/nekosunevranimations2025.json +0 -9
  257. package/data/vrchat/worlds/rumhamsavatarworld.json +0 -7
  258. package/data/vrchat/worlds/smewsranch.json +0 -7
  259. package/data/vrchat/worlds/smewsroom.json +0 -7
  260. package/data/vrchat/worlds/sunsetbar.json +0 -7
  261. package/data/vrchat/worlds/theblackcat.json +0 -9
  262. package/data/vrchat/worlds/thegreatpug.json +0 -8
  263. package/data/vrchat/worlds/themidnightbar.json +0 -7
  264. package/data/vrchat/worlds/voidclub.json +0 -7
  265. package/data/vrchat/worlds/voltdanceclub.json +0 -7
  266. package/data/vrchat/worlds/vrchathome.json +0 -8
  267. package/data/vrchat/worlds/whatalegend.json +0 -6
  268. package/data/warframe/meta.json +0 -14
  269. package/data/wutheringwaves/meta.json +0 -14
  270. package/data/zenlesszonezero/meta.json +0 -14
  271. package/gamecodes.js +0 -178
  272. package/scripts/cache-sync-smoke.js +0 -92
  273. package/scripts/game-code-cache-smoke.js +0 -85
  274. package/scripts/sync-all-cache.js +0 -18
  275. package/scripts/sync-api-cache.js +0 -319
  276. package/scripts/sync-game-code-cache.js +0 -244
  277. package/scripts/sync-gaming-info-cache.js +0 -46
@@ -1,9 +0,0 @@
1
- {
2
- "name": "Sodapoppin",
3
- "species": "Human",
4
- "gender": "Male",
5
- "aliases": "Soda, Chance",
6
- "image": "https://static.wikia.nocookie.net/vrchat-legends/images/6/6c/Rofl_April_24th_2020_60_Sodapoppin.png/revision/latest?cb=20200424234624",
7
- "description": "Sodapoppin is a major Twitch personality, historically known for streaming World of Warcraft, who has made recurring guest appearances in VRChat's roleplay scene. His in-VRChat persona is often referred to as Sodapoppin80085 or simply Soda, and he is best known in the community for visiting [Roflgator](https://vrchat-legends.fandom.com/wiki/Roflgator)'s bar communities alongside other prominent streamers such as xQc and Hasanabi.",
8
- "url": "https://vrchat-legends.fandom.com/wiki/Sodapoppin"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "Woops",
3
- "title": "The Purple-Haired Fox Girl",
4
- "species": "Kitsune (fox girl)",
5
- "gender": "Male",
6
- "image": "https://static.wikia.nocookie.net/vrchat-legends/images/3/3d/Woops.PNG/revision/latest?cb=20180603105244",
7
- "description": "Woops is a VRChat YouTuber and Twitch streamer, one of the five original leaders of [Team Five](https://vrchat-legends.fandom.com/wiki/Team_Five), first known for a custom fox-girl avatar in VRChat's public worlds. Described as happy-go-lucky and mischievous but loyal to friends, he records both roleplay and casual VRChat content for his channel and is affiliated with the [Midnite Central](https://vrchat-legends.fandom.com/wiki/Midnite_Central) community.",
8
- "url": "https://vrchat-legends.fandom.com/wiki/Woops"
9
- }
@@ -1,10 +0,0 @@
1
- {
2
- "name": "Zentreya",
3
- "title": "The Red Devil",
4
- "species": "Devil/Demon Dragon (formerly Devil/Demon Human)",
5
- "gender": "Female",
6
- "aliases": "Zen, Fearless Leader",
7
- "image": "https://static.wikia.nocookie.net/vrchat-legends/images/0/0e/Zentryey.png/revision/latest?cb=20180529152540",
8
- "description": "Zentreya is a roleplayer, streamer, and VTuber who was the leader and founder of the [Anti-Lewd Army](https://vrchat-legends.fandom.com/wiki/Anti-Lewd_Army), a prominent VRChat community faction, earning the nickname 'The Red Devil.' Portrayed as a demon who evolved from a demon-human hybrid into a demon-dragon persona, she is remembered in community lore as a strong-willed, strategic leader with a warmer side beneath a tough exterior. She has since become a well-known independent VTuber on platforms like Twitch and YouTube.",
9
- "url": "https://vrchat-legends.fandom.com/wiki/Zentreya"
10
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Ascension Academy",
3
- "creator": "Lnik Forstruth",
4
- "image": "",
5
- "description": "Ascension Academy is a large fantasy-themed roleplay map created by Lnik Forstruth, built as the setting for the Ascension Academy RP series organized by StealthRG (Chipz). Within the fiction of the roleplay, it depicts a military academy that trains cadets in magic, weaponry, and tactics; as a physical VRChat map it provides the classrooms, halls, and grounds used by that community's ongoing storylines. It stands out as one of the more elaborate purpose-built roleplay campuses documented on the wiki.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Ascension_Academy"
7
- }
@@ -1,8 +0,0 @@
1
- {
2
- "name": "Club VGL",
3
- "aliases": "Varneon's Gaming Lounge",
4
- "creator": "Varneon",
5
- "image": "",
6
- "description": "Club VGL is a realistic-looking nightclub world made by Varneon, made public in December 2018. Its name stands for Varneon's Gaming Lounge, and the map includes a dance floor with working lighting, a private catwalk area with a central dance pole, and lockable rooms with jacuzzis. It has been kept updated over the years and remains a recognizable nightclub-style hangout in VRChat.",
7
- "url": "https://vrchat-legends.fandom.com/wiki/Club_VGL"
8
- }
@@ -1,8 +0,0 @@
1
- {
2
- "name": "FIGHT FINDER",
3
- "aliases": "Sky Stadium, FIGHT FINDER HUB",
4
- "creator": "Gormundr",
5
- "image": "",
6
- "description": "FIGHT FINDER (originally released as Sky Stadium) is a PC and Quest compatible arena world co-created by Gormundr along with Mortugues, Wobblins, N1no001, and KazeTheAlien. It's built around stadium-style spaces where visitors perform choreographed roleplay fights and showcase avatar animations for recognition within affiliated combat and roleplay sub-groups. After growing quickly in mid-2024, the world and its Discord were rebranded as a permanent public hub supporting many independent fighting-roleplay communities.",
7
- "url": "https://vrchat-legends.fandom.com/wiki/FIGHT_FINDER"
8
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Hangout House",
3
- "creator": "Munificent",
4
- "image": "",
5
- "description": "Hangout House is an indoor social world created in mid-2018 by the user Munificent. It offers a cozy house-style layout with tabletop-style social games such as chess and four-in-a-row, plus a basement movie theater where visitors can queue up videos to watch together. It has remained a low-key, long-running spot for small-group hangouts rather than a large public party space.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Hangout_House"
7
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoStudios - Halloween Animations",
3
- "title": "Halloween Animations",
4
- "creator": "NekoStudios",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_fae4a508-97c4-4fea-82ff-e16eea083087/1/file",
7
- "description": "NekoStudios - Halloween Animations is a festive world featuring holiday-themed animations and decorations. Perfect for celebrating the season with your friends!",
8
- "url": "https://vrchat.com/home/world/wrld_bf840eeb-6a85-446b-9734-8f1d63c36ee9"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoStudios - New Year Animations",
3
- "title": "New Year Animations",
4
- "creator": "NekoStudios",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_ccf6fc05-b0a1-45b4-b4f3-e63460adf69d/1/file",
7
- "description": "NekoStudios - New Year Animations is a festive world featuring holiday-themed animations and decorations. Perfect for celebrating the season with your friends!",
8
- "url": "https://vrchat.com/home/world/wrld_7d7f9c06-1e16-4eb7-ac9c-cdcdd09e3ed1"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoStudios - XMAS Animations",
3
- "title": "XMAS Animations",
4
- "creator": "NekoStudios",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_6f8aecbb-1e7f-419a-b6fc-eb335866f031/1/file",
7
- "description": "NekoStudios - XMAS Animations is a festive world featuring holiday-themed animations and decorations. Perfect for celebrating the season with your friends!",
8
- "url": "https://vrchat.com/home/world/wrld_e753bcf7-8c65-4b8f-b5b6-fe0c1ccbd9d9"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoSuneVR Animations 2023",
3
- "title": "Animations 2023",
4
- "creator": "NekoSuneVR",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_ebcbd7e6-16a5-43a5-bde8-e842ede5f9dc/4/file",
7
- "description": "NekoSuneVR Animations World is where NekoSuneVR, formerly part of LatinGang (LTG) back in 2023, left at the end of the year to create their own, NekoStudios. This world features all animations from 2023 to 2024, with an exciting new world coming for 2025 animations—so stay tuned!",
8
- "url": "https://vrchat.com/home/world/wrld_f150bf66-e25b-42fb-9cf6-cd87794304c1"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoSuneVR Animations 2024",
3
- "title": "Animations 2024",
4
- "creator": "NekoSuneVR",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_ff27d04e-2469-4299-86e6-042892c6c2a8/2/file",
7
- "description": "NekoSuneVR Animations World is where NekoSuneVR, formerly part of LatinGang (LTG) back in 2023, left at the end of the year to create their own, NekoStudios. This world features all animations from 2023 to 2024, with an exciting new world coming for 2025 animations—so stay tuned!",
8
- "url": "https://vrchat.com/home/world/wrld_e5f19a02-2d19-4e37-bef2-e954566ce693"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "NekoSuneVR Animations 2025",
3
- "title": "Animations 2025",
4
- "creator": "NekoSuneVR",
5
- "aliases": "nekostudios animations",
6
- "image": "https://api.vrchat.cloud/api/1/file/file_35088ee5-4601-40b4-911a-8d7751110aad/2/file",
7
- "description": "NekoSuneVR Animations World is where NekoSuneVR, formerly part of LatinGang (LTG) back in 2023, left at the end of the year to create their own, NekoStudios. This world features all animations from 2023 to 2024, with an exciting new world coming for 2025 animations—so stay tuned!",
8
- "url": "https://vrchat.com/home/world/wrld_35c3d0ee-72c7-44b7-b518-1ea0ba7cdf66"
9
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Rum Ham's Avatar World",
3
- "creator": "Rum Ham",
4
- "image": "",
5
- "description": "Rum Ham's Avatar World is a meme-focused avatar showcase built by the creator Rum Ham, gathering a large collection of silly and intentionally over-the-top avatars, many accompanied by loud music or sound effects. Numerous avatars use clip-art-style cutouts and figures of internet personalities and celebrities, with Danny DeVito and Nicolas Cage recurring as particular running jokes throughout the world, including a small shrine-style area referencing DeVito. The world has been a favorite drop-in spot for comedic roleplay and random character events within the community.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Rum_Ham's_Avatar_World"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Smew's Ranch",
3
- "creator": "Smew",
4
- "image": "",
5
- "description": "Smew's Ranch is a follow-up world from creator Smew, built as a lighter, more playful companion to Smew's Room. It has an amusement-park feel, featuring a large Ferris wheel, a roller coaster, and assorted throwable gadgets and toys for visitors to mess around with. Since its release it has steadily grown in popularity as a fun, low-pressure hangout spot.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Smew's_Room"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Smew's Room",
3
- "creator": "Smew",
4
- "image": "",
5
- "description": "Smew's Room is a Quest-friendly hangout world built by the creator Smew as a comfortable space to relax with friends. Alongside various interactive gadgets, it doubles as a personal museum of sorts, displaying photos from Smew's travels through VRChat. It is also known as the birthplace of Simp Wars, a fan-made Star Wars parody that started here.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Smew's_Room"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Sunset Bar",
3
- "creator": "Lingie",
4
- "image": "",
5
- "description": "Sunset Bar is a PCVR and Oculus Quest compatible bar/club world published in August 2023, built to support up to around 60 players per instance. It centers on an elaborate drink-making system with customizable alcohol types, colors, and glassware, alongside a DJ and sound system, private rooms, and a video player. The world grew quickly into one of the more visited bar hangouts in VRChat's social scene.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Sunset_Bar"
7
- }
@@ -1,9 +0,0 @@
1
- {
2
- "name": "The Black Cat",
3
- "title": "Main Hall",
4
- "creator": "spookyghostboo",
5
- "aliases": "Black Cat",
6
- "image": "https://static.wikia.nocookie.net/vrchat-legends/images/2/25/The_Black_Cat_6.png",
7
- "description": "The Black Cat is an [Oculus Quest](https://en.wikipedia.org/wiki/Oculus_Quest) enabled world featuring a restaurant, two bars, two stages and many lounging areas. The map is fairly small but roomy enough that its possible to move to a private areas when needed. It has separate bathrooms for male and female visitors. The world has a mirror.",
8
- "url": "https://vrchat-legends.fandom.com/wiki/The_Black_Cat"
9
- }
@@ -1,8 +0,0 @@
1
- {
2
- "name": "The Great Pug",
3
- "title": "Night View Hall",
4
- "creator": "owlboy",
5
- "image": "",
6
- "description": "The Great Pug is a PC-only bar world launched in February 2017 by owlboy, modeled after a real pub called The Great Dane in Madison, Wisconsin. It spans three floors: a ground-floor bar with booths and tables, a second-floor bar and stage area known as Night View Hall with a billiards table, and a top-floor lounge called The Roost with a fireplace and loft seating. It became one of the most iconic early meeting places in VRChat's social and roleplay communities, later spawning a sister world, The Great Pug - West.",
7
- "url": "https://vrchat-legends.fandom.com/wiki/The_Great_Pug"
8
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "The Midnight Bar",
3
- "creator": "[Jmelt] Kurisu",
4
- "image": "",
5
- "description": "The Midnight Bar is an Oculus Quest and PCVR bar world commissioned by the group Midnights In Valhalla and built by [Jmelt] Kurisu. Its design draws inspiration from the visual novel [VA-11 Hall-A](https://en.wikipedia.org/wiki/VA-11_Hall-A), centering on an elaborate drink-mixing system where different concoctions produce different effects on the player. What began as a personal streaming space grew into one of VRChat's most-visited bar worlds, racking up several million visits and spawning a wider community of affiliated bar groups.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/The_Midnight_Bar"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "Void Club",
3
- "creator": "Lycon",
4
- "image": "",
5
- "description": "Void Club is one of VRChat's earliest well-known dance clubs, created in January 2018 and substantially redesigned in April of that year. It combines a bar, dance floor, and private rooms, and for years ran music around the clock as a public gathering spot. As a long-running, high-traffic public lobby it developed a mixed reputation depending on who visited, but remained an iconic fixture of VRChat's early nightlife scene.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/Void_Club"
7
- }
@@ -1,7 +0,0 @@
1
- {
2
- "name": "VOLT Dance Club",
3
- "creator": "DigitrevX",
4
- "image": "",
5
- "description": "VOLT Dance Club is a highly detailed mega-club world created by DigitrevX, featuring custom LED wall visuals, dynamic lighting, multiple bars, private rooms, a dart game, and jacuzzis. It's built to feel like a genuine high-end nightclub experience and even includes an optional RTX ray-tracing graphics mode for compatible Nvidia GPUs. The polish and scale of the build have made it a popular destination among VRChat's club and dance community.",
6
- "url": "https://vrchat-legends.fandom.com/wiki/VOLT_Dance_Club"
7
- }
@@ -1,8 +0,0 @@
1
- {
2
- "name": "VRChat Home",
3
- "aliases": "The Hub (former default world)",
4
- "creator": "VRChat",
5
- "image": "",
6
- "description": "VRChat Home is the official default landing world that new players arrive in after finishing the tutorial, replacing the older world known as The Hub and later refreshed by VRChat's own developers. It's set in a calm, space-themed environment with visible stars and galaxies, alien architecture, plants, and decorative motifs like mushrooms, flowers, and rainbows. Signage throughout explains core VRChat features, a mirror area lets new users try on different starter avatars, and portals lead out to a rotating selection of other worlds.",
7
- "url": "https://vrchat-legends.fandom.com/wiki/VRChat_Home"
8
- }
@@ -1,6 +0,0 @@
1
- {
2
- "name": "What a Legend!",
3
- "image": "",
4
- "description": "What a Legend! is a puzzle-dungeon world originally built as a birthday gift for a VRChat user known as Legend, later released publicly for others to play. Visitors explore a central corridor branching into six themed portal realms, each crafted by a different \"Cheese Guardian\" (including Lakuza, CyanLaser, Mimi, and Phasedragon) with its own puzzles to solve. Collecting all six cheese pieces from these realms unlocks the door to a final room, completing the game-like experience.",
5
- "url": "https://vrchat-legends.fandom.com/wiki/What_a_Legend!"
6
- }
@@ -1,14 +0,0 @@
1
- {
2
- "name": "Warframe",
3
- "title": "Cooperative science-fiction action game by Digital Extremes.",
4
- "engine": "Evolution",
5
- "Platform": "Windows, PlayStation, Xbox, Nintendo Switch, iOS, Android",
6
- "Release date": "March 25, 2013",
7
- "Genre": "Action RPG, Third-person shooter, Online co-op",
8
- "developers": "Digital Extremes",
9
- "publisher": "Digital Extremes",
10
- "aliases": "WF, Warframe",
11
- "image": "https://www.warframe.com/favicon.ico",
12
- "description": "Online action game built around collectible Warframes, weapons, companions and the Origin System.",
13
- "url": "https://www.warframe.com/"
14
- }
@@ -1,14 +0,0 @@
1
- {
2
- "name": "Wuthering Waves",
3
- "title": "Open-world action RPG by Kuro Games.",
4
- "engine": "Unreal Engine 4",
5
- "Platform": "Windows, PlayStation 5, iOS, Android, macOS",
6
- "Release date": "May 22, 2024",
7
- "Genre": "Action RPG, Open World, Gacha",
8
- "developers": "Kuro Games",
9
- "publisher": "Kuro Games",
10
- "aliases": "WuWa, Wuthering Waves",
11
- "image": "https://wutheringwaves.kurogames.com/favicon.ico",
12
- "description": "Open-world action RPG featuring playable Resonators with distinct attributes and weapons.",
13
- "url": "https://wutheringwaves.kurogames.com/"
14
- }
@@ -1,14 +0,0 @@
1
- {
2
- "name": "Zenless Zone Zero",
3
- "title": "Urban fantasy action RPG by HoYoverse.",
4
- "engine": "Unity",
5
- "Platform": "Windows, PlayStation 5, Xbox Series X/S, iOS, Android",
6
- "Release date": "July 4, 2024",
7
- "Genre": "Action RPG, Urban Fantasy, Gacha",
8
- "developers": "miHoYo",
9
- "publisher": "HoYoverse",
10
- "aliases": "ZZZ, Zenless Zone Zero",
11
- "image": "https://zenless.hoyoverse.com/favicon.ico",
12
- "description": "Action RPG featuring playable Agents organized by faction, attribute and specialty.",
13
- "url": "https://zenless.hoyoverse.com/"
14
- }
package/gamecodes.js DELETED
@@ -1,178 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
-
6
- const DATA_DIR = path.join(__dirname, 'data', 'game-codes');
7
- const DEFAULT_API_BASE = 'https://api.nekosunevr.co.uk';
8
- const DEFAULT_API_PATH = '/v5/games/api/codes';
9
- const DEFAULT_TIMEOUT_MS = 4000;
10
-
11
- function apiBase() {
12
- return String(process.env.GAMING_INFOS_API_BASE || DEFAULT_API_BASE).replace(/\/+$/, '');
13
- }
14
-
15
- function apiPath() {
16
- const raw = String(process.env.GAME_CODES_API_PATH || DEFAULT_API_PATH).trim();
17
- return `/${raw.replace(/^\/+|\/+$/g, '')}`;
18
- }
19
-
20
- function apiDisabled() {
21
- const raw = String(process.env.GAMING_INFOS_DISABLE_API || '').toLowerCase();
22
- return raw === '1' || raw === 'true';
23
- }
24
-
25
- function timeoutMs() {
26
- const raw = Number(process.env.GAMING_INFOS_TIMEOUT_MS);
27
- return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_TIMEOUT_MS;
28
- }
29
-
30
- async function apiGet(suffix = '', query = {}) {
31
- if (apiDisabled() || typeof fetch !== 'function') return null;
32
-
33
- const url = new URL(`${apiBase()}${apiPath()}${suffix}`);
34
- for (const [key, value] of Object.entries(query)) {
35
- if (value !== undefined && value !== null && value !== '') url.searchParams.set(key, String(value));
36
- }
37
-
38
- const controller = new AbortController();
39
- const timer = setTimeout(() => controller.abort(), timeoutMs());
40
- try {
41
- const response = await fetch(url, { signal: controller.signal, headers: { Accept: 'application/json' } });
42
- if (!response.ok) return null;
43
- const body = await response.json();
44
- if (!body || body.success === false) return null;
45
- return body;
46
- } catch (_) {
47
- return null;
48
- } finally {
49
- clearTimeout(timer);
50
- }
51
- }
52
-
53
- async function readJson(filePath) {
54
- return JSON.parse(await fs.promises.readFile(filePath, 'utf8'));
55
- }
56
-
57
- function safeFallbackPath(fileName) {
58
- const filePath = path.resolve(DATA_DIR, fileName);
59
- const root = `${path.resolve(DATA_DIR)}${path.sep}`;
60
- return filePath.startsWith(root) ? filePath : null;
61
- }
62
-
63
- async function readFallback(fileName) {
64
- const filePath = safeFallbackPath(fileName);
65
- if (!filePath || !fs.existsSync(filePath)) return null;
66
- try {
67
- return await readJson(filePath);
68
- } catch (_) {
69
- return null;
70
- }
71
- }
72
-
73
- function normalizeGame(game) {
74
- const slug = String(game || '').trim().toLowerCase();
75
- return /^[a-z0-9][a-z0-9-]*$/.test(slug) ? slug : null;
76
- }
77
-
78
- function normalizeCode(code) {
79
- return String(code || '').trim().toLowerCase();
80
- }
81
-
82
- async function resolveCachedGame(game) {
83
- const slug = normalizeGame(game);
84
- if (!slug) return null;
85
- if (await readFallback(path.join('games', `${slug}.json`))) return slug;
86
-
87
- const cachedDirectory = await readFallback('directory.json');
88
- const aliasTarget = cachedDirectory?.aliases?.[slug];
89
- const canonical = normalizeGame(aliasTarget);
90
- if (canonical && await readFallback(path.join('games', `${canonical}.json`))) return canonical;
91
- return slug;
92
- }
93
-
94
- function filterCachedList(data, options = {}) {
95
- if (!data || typeof data !== 'object') return data;
96
- const includeUnknown = Boolean(options.includeUnknown);
97
- const category = options.category ? String(options.category).toLowerCase() : null;
98
- const claimType = options.claimType ? String(options.claimType).toLowerCase() : null;
99
-
100
- const matches = (entry) => {
101
- if (!entry || typeof entry !== 'object') return false;
102
- if (category && String(entry.category || '').toLowerCase() !== category) return false;
103
- if (claimType && String(entry.claimType || '').toLowerCase() !== claimType) return false;
104
- return true;
105
- };
106
-
107
- const result = {
108
- Active: Array.isArray(data.Active) ? data.Active.filter(matches) : [],
109
- Expired: Array.isArray(data.Expired) ? data.Expired.filter(matches) : []
110
- };
111
- if (includeUnknown) result.Unknown = Array.isArray(data.Unknown) ? data.Unknown.filter(matches) : [];
112
- return result;
113
- }
114
-
115
- async function directory() {
116
- const live = await apiGet('');
117
- if (live) return live;
118
- const cached = await readFallback('directory.json');
119
- return cached || { success: false, error: 'Game code directory is unavailable and no fallback cache exists.' };
120
- }
121
-
122
- async function status() {
123
- const live = await apiGet('/status');
124
- if (live) return live.data !== undefined ? live.data : live;
125
- const cached = await readFallback('status.json');
126
- return cached || { error: 'Game code status is unavailable and no fallback cache exists.' };
127
- }
128
-
129
- async function gameCodes(game, options = {}) {
130
- if (!game) return { error: 'game is required' };
131
- const requested = normalizeGame(game);
132
- if (!requested) return { error: 'invalid game slug' };
133
- const query = {
134
- timezone: options.timezone,
135
- category: options.category,
136
- claimType: options.claimType,
137
- includeUnknown: options.includeUnknown ? 'true' : undefined
138
- };
139
- const live = await apiGet(`/${encodeURIComponent(requested)}`, query);
140
- if (live) return live;
141
-
142
- const cachedGame = await resolveCachedGame(requested);
143
- const cached = cachedGame ? await readFallback(path.join('games', `${cachedGame}.json`)) : null;
144
- if (!cached) return { error: `No cached game codes found for "${game}".` };
145
- return filterCachedList(cached, options);
146
- }
147
-
148
- async function gameCode(game, code, options = {}) {
149
- if (!game || !code) return { error: 'game and code are both required' };
150
- const requested = normalizeGame(game);
151
- if (!requested) return { error: 'invalid game slug' };
152
- const codeValue = String(code).trim();
153
- const live = await apiGet(`/${encodeURIComponent(requested)}/${encodeURIComponent(codeValue)}`, { timezone: options.timezone });
154
- if (live) return live.data !== undefined ? live.data : live;
155
-
156
- const cachedGame = await resolveCachedGame(requested);
157
- const cached = cachedGame ? await readFallback(path.join('games', `${cachedGame}.json`)) : null;
158
- if (!cached) return { error: `No cached game codes found for "${game}".` };
159
- const wanted = normalizeCode(codeValue);
160
- for (const bucket of ['Active', 'Expired', 'Unknown']) {
161
- for (const entry of Array.isArray(cached[bucket]) ? cached[bucket] : []) {
162
- if (normalizeCode(entry?.code) === wanted) return entry;
163
- }
164
- }
165
- return { error: `Code "${code}" not found for game "${game}".` };
166
- }
167
-
168
- async function cacheInfo() {
169
- return readFallback('.cache-manifest.json');
170
- }
171
-
172
- module.exports = {
173
- Codes: () => directory(),
174
- CodesStatus: () => status(),
175
- GameCodes: (game, options) => gameCodes(game, options),
176
- GameCode: (game, code, options) => gameCode(game, code, options),
177
- CodeCacheInfo: () => cacheInfo()
178
- };
@@ -1,92 +0,0 @@
1
- 'use strict';
2
-
3
- const assert = require('assert');
4
- const fs = require('fs');
5
- const http = require('http');
6
- const os = require('os');
7
- const path = require('path');
8
- const { syncApiCache } = require('./sync-api-cache');
9
-
10
- function json(res, status, body) {
11
- const payload = JSON.stringify(body);
12
- res.writeHead(status, { 'content-type': 'application/json', 'content-length': Buffer.byteLength(payload) });
13
- res.end(payload);
14
- }
15
-
16
- async function main() {
17
- const root = await fs.promises.mkdtemp(path.join(os.tmpdir(), 'gaming-infos-cache-test-'));
18
- const dataDir = path.join(root, 'data');
19
- let failCharacters = false;
20
- let characters = [
21
- { slug: 'alpha', name: 'Alpha', value: 1 },
22
- { slug: 'beta', name: 'Beta', value: 2 }
23
- ];
24
-
25
- const server = http.createServer((req, res) => {
26
- if (req.url === '/v5/games/api/gaming-infos') {
27
- return json(res, 200, { success: true, data: [{ name: 'Test Game' }] });
28
- }
29
- if (req.url === '/v5/games/api/gaming-infos/testgame/meta/testgame') {
30
- return json(res, 200, { success: true, data: { name: 'Test Game', description: 'fixture' } });
31
- }
32
- if (req.url === '/v5/games/api/gaming-infos/testgame/characters') {
33
- if (failCharacters) return json(res, 503, { success: false, error: 'fixture outage' });
34
- return json(res, 200, { success: true, data: characters });
35
- }
36
- return json(res, 404, { success: false, error: 'not found' });
37
- });
38
-
39
- await new Promise((resolve) => server.listen(0, '127.0.0.1', resolve));
40
- const address = server.address();
41
- const apiBase = `http://127.0.0.1:${address.port}`;
42
- const options = {
43
- apiBase,
44
- apiPath: '/v5/games/api/gaming-infos',
45
- dataDir,
46
- manifest: { testgame: ['characters'] },
47
- retries: 0,
48
- timeoutMs: 3000
49
- };
50
-
51
- try {
52
- const first = await syncApiCache(options);
53
- assert.strictEqual(first.changed, true);
54
- assert.ok(fs.existsSync(path.join(dataDir, 'testgame', 'characters', 'alpha.json')));
55
- assert.ok(fs.existsSync(path.join(dataDir, 'testgame', 'characters', 'beta.json')));
56
-
57
- characters = [
58
- { slug: 'alpha', name: 'Alpha', value: 99 },
59
- { slug: 'gamma', name: 'Gamma', value: 3 }
60
- ];
61
- const second = await syncApiCache(options);
62
- assert.strictEqual(second.changed, true);
63
- assert.strictEqual(second.stats.added, 1);
64
- assert.strictEqual(second.stats.removed, 1);
65
- assert.ok(second.stats.changed >= 1);
66
- assert.strictEqual(JSON.parse(await fs.promises.readFile(path.join(dataDir, 'testgame', 'characters', 'alpha.json'), 'utf8')).value, 99);
67
- assert.ok(fs.existsSync(path.join(dataDir, 'testgame', 'characters', 'gamma.json')));
68
- assert.ok(!fs.existsSync(path.join(dataDir, 'testgame', 'characters', 'beta.json')));
69
-
70
- const beforeOutage = await fs.promises.readFile(path.join(dataDir, 'testgame', 'characters', 'alpha.json'), 'utf8');
71
- failCharacters = true;
72
- let failed = false;
73
- try {
74
- await syncApiCache(options);
75
- } catch (_) {
76
- failed = true;
77
- }
78
- assert.strictEqual(failed, true, 'partial API outage must fail the sync');
79
- assert.strictEqual(await fs.promises.readFile(path.join(dataDir, 'testgame', 'characters', 'alpha.json'), 'utf8'), beforeOutage);
80
- assert.ok(fs.existsSync(path.join(dataDir, 'testgame', 'characters', 'gamma.json')), 'last good snapshot must survive an outage');
81
-
82
- console.log('gaming-infos cache sync smoke test passed');
83
- } finally {
84
- await new Promise((resolve) => server.close(resolve));
85
- await fs.promises.rm(root, { recursive: true, force: true });
86
- }
87
- }
88
-
89
- main().catch((error) => {
90
- console.error(error);
91
- process.exitCode = 1;
92
- });