beatsaber-bot-core 0.2.0-rc.11 → 0.2.0-rc.13

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 (193) hide show
  1. package/dist/cjs/cmd/deprecated/tmp.js +2 -2
  2. package/dist/cjs/cmd/deprecated/tmp.js.map +1 -1
  3. package/dist/cjs/cmd/score.js.map +1 -1
  4. package/dist/cjs/config.js.map +1 -1
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/infra/i18n/default.js +10 -0
  7. package/dist/cjs/infra/i18n/default.js.map +1 -0
  8. package/dist/cjs/infra/i18n/index.js +29 -104
  9. package/dist/cjs/infra/i18n/index.js.map +1 -1
  10. package/dist/cjs/infra/i18n/util.js +76 -0
  11. package/dist/cjs/infra/i18n/util.js.map +1 -0
  12. package/dist/cjs/infra/i18n/zh-cn.json +1 -1
  13. package/dist/cjs/infra/index.js +8 -3
  14. package/dist/cjs/infra/index.js.map +1 -1
  15. package/dist/cjs/infra/support/render/index.js +9 -3
  16. package/dist/cjs/infra/support/render/index.js.map +1 -1
  17. package/dist/cjs/interface/bot.js.map +1 -1
  18. package/dist/cjs/interface/cmd/type.js.map +1 -1
  19. package/dist/cjs/interface/db/index.js +0 -6
  20. package/dist/cjs/interface/db/index.js.map +1 -1
  21. package/dist/cjs/interface/index.js.map +1 -1
  22. package/dist/cjs/schedules/index.js +2 -2
  23. package/dist/cjs/schedules/index.js.map +1 -1
  24. package/dist/cjs/schedules/interface.js.map +1 -1
  25. package/dist/cjs/schedules/temp.js.map +1 -1
  26. package/dist/cjs/service/api/index.js +1 -1
  27. package/dist/cjs/service/api/index.js.map +1 -1
  28. package/dist/cjs/service/index.js +15 -0
  29. package/dist/cjs/service/index.js.map +1 -1
  30. package/dist/cjs/service/preference.js.map +1 -1
  31. package/dist/cjs/service/render/index.js +12 -2
  32. package/dist/cjs/service/render/index.js.map +1 -1
  33. package/dist/cjs/ws/beatleader.js.map +1 -1
  34. package/dist/cjs/ws/beatsaver.js.map +1 -1
  35. package/dist/cjs/ws/index.js +0 -2
  36. package/dist/cjs/ws/index.js.map +1 -1
  37. package/dist/esm/cmd/deprecated/tmp.js +2 -2
  38. package/dist/esm/cmd/deprecated/tmp.js.map +1 -1
  39. package/dist/esm/cmd/score.js.map +1 -1
  40. package/dist/esm/index.js.map +1 -1
  41. package/dist/esm/infra/i18n/default.js +10 -0
  42. package/dist/esm/infra/i18n/default.js.map +1 -0
  43. package/dist/esm/infra/i18n/index.js +29 -92
  44. package/dist/esm/infra/i18n/index.js.map +1 -1
  45. package/dist/esm/infra/i18n/util.js +51 -0
  46. package/dist/esm/infra/i18n/util.js.map +1 -0
  47. package/dist/esm/infra/index.js +5 -2
  48. package/dist/esm/infra/index.js.map +1 -1
  49. package/dist/esm/infra/support/render/index.js +9 -3
  50. package/dist/esm/infra/support/render/index.js.map +1 -1
  51. package/dist/esm/interface/db/index.js +0 -1
  52. package/dist/esm/interface/db/index.js.map +1 -1
  53. package/dist/esm/interface/index.js.map +1 -1
  54. package/dist/esm/schedules/index.js +2 -2
  55. package/dist/esm/schedules/index.js.map +1 -1
  56. package/dist/esm/schedules/temp.js.map +1 -1
  57. package/dist/esm/service/api/index.js +1 -1
  58. package/dist/esm/service/api/index.js.map +1 -1
  59. package/dist/esm/service/index.js +6 -0
  60. package/dist/esm/service/index.js.map +1 -1
  61. package/dist/esm/service/preference.js.map +1 -1
  62. package/dist/esm/service/render/index.js +12 -2
  63. package/dist/esm/service/render/index.js.map +1 -1
  64. package/dist/esm/ws/beatleader.js.map +1 -1
  65. package/dist/esm/ws/beatsaver.js.map +1 -1
  66. package/dist/esm/ws/index.js +0 -1
  67. package/dist/esm/ws/index.js.map +1 -1
  68. package/dist/types/index.d.ts +1030 -44
  69. package/package.json +7 -7
  70. package/dist/cjs/ws/scoresaber.js +0 -75
  71. package/dist/cjs/ws/scoresaber.js.map +0 -1
  72. package/dist/esm/ws/scoresaber.js +0 -53
  73. package/dist/esm/ws/scoresaber.js.map +0 -1
  74. package/dist/types/cmd/bind/bind-beatleader.d.ts +0 -34
  75. package/dist/types/cmd/bind/bind-beatsaver.d.ts +0 -34
  76. package/dist/types/cmd/bind/bind-id-beatleader.d.ts +0 -34
  77. package/dist/types/cmd/bind/bind-id-beatsaver.d.ts +0 -34
  78. package/dist/types/cmd/bind/bind-scoresaber.d.ts +0 -34
  79. package/dist/types/cmd/bind/index.d.ts +0 -41
  80. package/dist/types/cmd/bsmap/id-search.d.ts +0 -41
  81. package/dist/types/cmd/bsmap/key-search.d.ts +0 -41
  82. package/dist/types/cmd/bsmap/latest.d.ts +0 -41
  83. package/dist/types/cmd/config/index.d.ts +0 -2
  84. package/dist/types/cmd/deprecated/tmp.d.ts +0 -41
  85. package/dist/types/cmd/index.d.ts +0 -34
  86. package/dist/types/cmd/rank.d.ts +0 -41
  87. package/dist/types/cmd/score.d.ts +0 -41
  88. package/dist/types/cmd/subscribe/beatleader.d.ts +0 -34
  89. package/dist/types/cmd/subscribe/beatsaver.d.ts +0 -34
  90. package/dist/types/cmd/subscribe/id-beatleader-score.d.ts +0 -34
  91. package/dist/types/cmd/subscribe/id-beatsaver-mapper.d.ts +0 -34
  92. package/dist/types/cmd/subscribe/index.d.ts +0 -41
  93. package/dist/types/cmd/subscribe/subjoin.d.ts +0 -41
  94. package/dist/types/cmd/subscribe/subleave.d.ts +0 -41
  95. package/dist/types/cmd/subscribe/unsubscribe.d.ts +0 -41
  96. package/dist/types/components/components/RankDifficulty.d.ts +0 -10
  97. package/dist/types/components/components/base/avatar.d.ts +0 -10
  98. package/dist/types/components/components/bl-rank-score-item.d.ts +0 -21
  99. package/dist/types/components/components/bl-score-item.d.ts +0 -10
  100. package/dist/types/components/components/characteristic.d.ts +0 -9
  101. package/dist/types/components/components/flag.d.ts +0 -9
  102. package/dist/types/components/components/icons/BeatLeader.d.ts +0 -6
  103. package/dist/types/components/components/icons/RankIcon.d.ts +0 -8
  104. package/dist/types/components/components/icons/ScoreSaberIcon.d.ts +0 -6
  105. package/dist/types/components/components/progressbar.d.ts +0 -8
  106. package/dist/types/components/components/scoreItem.d.ts +0 -8
  107. package/dist/types/components/components/scoregraph.d.ts +0 -15
  108. package/dist/types/components/components/skill-graph.d.ts +0 -9
  109. package/dist/types/components/components/socre-badge.d.ts +0 -9
  110. package/dist/types/components/components/ss-rank-score-item.d.ts +0 -21
  111. package/dist/types/components/components/ss-score-item.d.ts +0 -8
  112. package/dist/types/components/index.d.ts +0 -5
  113. package/dist/types/components/pages/bl-player.d.ts +0 -11
  114. package/dist/types/components/pages/bl-score-with-rank.d.ts +0 -18
  115. package/dist/types/components/pages/bl-score.d.ts +0 -15
  116. package/dist/types/components/pages/bs-map.d.ts +0 -11
  117. package/dist/types/components/pages/index.d.ts +0 -14
  118. package/dist/types/components/pages/ss-player.d.ts +0 -13
  119. package/dist/types/components/utils/bl/beatleader.d.ts +0 -15
  120. package/dist/types/components/utils/bl/blheadset.d.ts +0 -275
  121. package/dist/types/components/utils/bl/bsorDecoder.d.ts +0 -189
  122. package/dist/types/components/utils/bl/bsorReplayAcc.d.ts +0 -38
  123. package/dist/types/components/utils/bl/getPart.d.ts +0 -9
  124. package/dist/types/components/utils/bl/stastic.d.ts +0 -3
  125. package/dist/types/components/utils/canvas.d.ts +0 -2
  126. package/dist/types/components/utils/format.d.ts +0 -8
  127. package/dist/types/components/utils/getMods.d.ts +0 -5
  128. package/dist/types/components/utils/index.d.ts +0 -6
  129. package/dist/types/components/utils/qrcode.d.ts +0 -3
  130. package/dist/types/components/utils/sleep.d.ts +0 -3
  131. package/dist/types/components/utils/tag-format.d.ts +0 -3
  132. package/dist/types/components/utils/tw-join.d.ts +0 -5
  133. package/dist/types/config.d.ts +0 -30
  134. package/dist/types/index-Dagy_c8G.d.ts +0 -74
  135. package/dist/types/infra/errors/index.d.ts +0 -69
  136. package/dist/types/infra/i18n/index.d.ts +0 -4
  137. package/dist/types/infra/i18n/parser.d.ts +0 -16
  138. package/dist/types/infra/index.d.ts +0 -6
  139. package/dist/types/infra/s3/index.d.ts +0 -20
  140. package/dist/types/infra/support/cache.d.ts +0 -6
  141. package/dist/types/infra/support/fetch/error.d.ts +0 -11
  142. package/dist/types/infra/support/fetch/index.d.ts +0 -7
  143. package/dist/types/infra/support/fetch/ofetch.d.ts +0 -24
  144. package/dist/types/infra/support/render/index.d.ts +0 -38
  145. package/dist/types/infra/support/render/puppeteer.d.ts +0 -43
  146. package/dist/types/interface/bot.d.ts +0 -22
  147. package/dist/types/interface/cmd/builder.d.ts +0 -53
  148. package/dist/types/interface/cmd/type.d.ts +0 -30
  149. package/dist/types/interface/db/index.d.ts +0 -45
  150. package/dist/types/interface/db/models.d.ts +0 -41
  151. package/dist/types/interface/index.d.ts +0 -30
  152. package/dist/types/interface/logger.d.ts +0 -8
  153. package/dist/types/schedules/index.d.ts +0 -40
  154. package/dist/types/schedules/interface.d.ts +0 -45
  155. package/dist/types/schedules/temp.d.ts +0 -35
  156. package/dist/types/service/api/base/aioclient.d.ts +0 -13
  157. package/dist/types/service/api/base/blclient.d.ts +0 -28
  158. package/dist/types/service/api/base/bsclient.d.ts +0 -29
  159. package/dist/types/service/api/base/index.d.ts +0 -19
  160. package/dist/types/service/api/base/ssclient.d.ts +0 -17
  161. package/dist/types/service/api/index.d.ts +0 -59
  162. package/dist/types/service/api/interfaces/aiosaber/index.d.ts +0 -9
  163. package/dist/types/service/api/interfaces/beatleader/bsor.d.ts +0 -113
  164. package/dist/types/service/api/interfaces/beatleader/index.d.ts +0 -5
  165. package/dist/types/service/api/interfaces/beatleader/req.d.ts +0 -22
  166. package/dist/types/service/api/interfaces/beatleader/score.d.ts +0 -164
  167. package/dist/types/service/api/interfaces/beatleader/user.d.ts +0 -173
  168. package/dist/types/service/api/interfaces/beatleader/ws.d.ts +0 -90
  169. package/dist/types/service/api/interfaces/beatsaver/alert.d.ts +0 -20
  170. package/dist/types/service/api/interfaces/beatsaver/bsmap.d.ts +0 -70
  171. package/dist/types/service/api/interfaces/beatsaver/index.d.ts +0 -13
  172. package/dist/types/service/api/interfaces/beatsaver/resp.d.ts +0 -11
  173. package/dist/types/service/api/interfaces/beatsaver/user.d.ts +0 -10
  174. package/dist/types/service/api/interfaces/beatsaver/ws.d.ts +0 -13
  175. package/dist/types/service/api/interfaces/index.d.ts +0 -14
  176. package/dist/types/service/api/interfaces/scoresaber/index.d.ts +0 -3
  177. package/dist/types/service/api/interfaces/scoresaber/item.d.ts +0 -67
  178. package/dist/types/service/api/interfaces/scoresaber/leaderboard.d.ts +0 -13
  179. package/dist/types/service/api/interfaces/scoresaber/resp.d.ts +0 -12
  180. package/dist/types/service/api/interfaces/scoresaber/user.d.ts +0 -35
  181. package/dist/types/service/api/interfaces/scoresaber/ws.d.ts +0 -80
  182. package/dist/types/service/api/sortScore.d.ts +0 -5
  183. package/dist/types/service/index.d.ts +0 -30
  184. package/dist/types/service/preference.d.ts +0 -38
  185. package/dist/types/service/render/index.d.ts +0 -43
  186. package/dist/types/service/render/interfaces.d.ts +0 -30
  187. package/dist/types/utils/index.d.ts +0 -5
  188. package/dist/types/ws/beatleader.d.ts +0 -47
  189. package/dist/types/ws/beatsaver.d.ts +0 -52
  190. package/dist/types/ws/bl-filter.d.ts +0 -2
  191. package/dist/types/ws/handler.d.ts +0 -8
  192. package/dist/types/ws/index.d.ts +0 -36
  193. package/dist/types/ws/scoresaber.d.ts +0 -47
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/infra/support/render/index.ts"],"sourcesContent":["import {html2imgBuffer, RenderOptions, url2imgBuffer} from \"./puppeteer\";\nimport {Browser, Puppeteer} from \"puppeteer-core\";\nimport {Fetch} from \"@/infra/support/fetch\";\nexport {RenderOptions as PuppeteerOptions}\nexport interface ImageRender {\n html2img: (html: string, opt: RenderOptions) => Promise<Buffer>\n url2img: (url: string, opt: RenderOptions) => Promise<Buffer>\n}\n\nexport type RenderConfig = {\n mode: 'cf' | 'puppeteer'\n puppeteerURL?: string\n defaultWaitTimeout?: number\n waitTimeout?: number\n cfAccountId?: string,\n cfAPIKey?: string,\n}\n\nexport class CFBrowserRendering implements ImageRender {\n f: Fetch\n constructor(private accountId: string, private cfAPIKey: string) {\n this.f = new Fetch()\n .baseUrl(`https://api.cloudflare.com/client/v4/accounts/${accountId}`)\n .extend({\n headers: {\n Authorization: `Bearer ${cfAPIKey}`\n },\n })\n }\n private post(body) {\n return this.f.post('/browser-rendering/screenshot', {\n responseType: 'arrayBuffer',\n body: {\n ...body,\n \"viewport\": {\n \"width\": 3840,\n \"height\": 2160,\n \"deviceScaleFactor\": 2,\n },\n \"gotoOptions\": {\n \"waitUntil\": \"networkidle0\",\n \"timeout\": 30000\n },\n }\n })\n }\n\n\n\n async html2img (html: string, opt: RenderOptions) {\n const buf = await this.post({html: html, ...opt})\n return Buffer.from(buf)\n }\n async url2img (url: string, opt: RenderOptions) {\n const buf = await this.post({url: url, ...opt})\n return Buffer.from(buf)\n }\n}\n\nexport class PuppeteerRendering implements ImageRender {\n constructor(private browserGetter: () => Promise<Browser>) {\n }\n async html2img (html: string, opt: RenderOptions) {\n return html2imgBuffer(this.browserGetter, html, opt)\n }\n async url2img (html: string, opt: RenderOptions) {\n return url2imgBuffer(this.browserGetter, html, opt)\n }\n}\n\n\nexport const RemoteBrowserGetter = (addr: string) => {\n const p = new Puppeteer()\n let opt = {}\n if(addr.startsWith('ws')) {\n opt = { browserWSEndpoint: addr }\n }else if(addr.startsWith('http')) {\n opt = { browserURL: addr }\n }\n return () => p.connect(opt)\n}\n\n\nexport const getImageRender = (cfg: RenderConfig & {browserGetter?: () => Promise<Browser>}) => {\n if(cfg.mode === 'cf') {\n return new CFBrowserRendering(cfg.cfAccountId, cfg.cfAPIKey)\n }\n if(cfg.puppeteerURL) {\n return new PuppeteerRendering(RemoteBrowserGetter(cfg.puppeteerURL))\n }\n if(cfg.browserGetter) {\n return new PuppeteerRendering(cfg.browserGetter)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAQ,gBAAgB,eAAe,qBAAoB;AAC3D,SAAiB,iBAAgB;AACjC,SAAQ,aAAY;AAgBb,MAAM,mBAA0C;AAAA,EAErD,YAAoB,WAA2B,UAAkB;AAA7C;AAA2B;AAD/C;AAEE,SAAK,IAAI,IAAI,MAAM,EAChB,QAAQ,iDAAiD,SAAS,EAAE,EACpE,OAAO;AAAA,MACN,SAAS;AAAA,QACP,eAAe,UAAU,QAAQ;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EACQ,KAAK,MAAM;AACjB,WAAO,KAAK,EAAE,KAAK,iCAAiC;AAAA,MAClD,cAAc;AAAA,MACd,MAAM,iCACD,OADC;AAAA,QAEJ,YAAY;AAAA,UACV,SAAS;AAAA,UACT,UAAU;AAAA,UACV,qBAAqB;AAAA,QACvB;AAAA,QACA,eAAe;AAAA,UACb,aAAa;AAAA,UACb,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAIM,SAAU,MAAc,KAAoB;AAAA;AAChD,YAAM,MAAM,MAAM,KAAK,KAAK,iBAAC,QAAe,IAAI;AAChD,aAAO,OAAO,KAAK,GAAG;AAAA,IACxB;AAAA;AAAA,EACM,QAAS,KAAa,KAAoB;AAAA;AAC9C,YAAM,MAAM,MAAM,KAAK,KAAK,iBAAC,OAAa,IAAI;AAC9C,aAAO,OAAO,KAAK,GAAG;AAAA,IACxB;AAAA;AACF;AAEO,MAAM,mBAA0C;AAAA,EACrD,YAAoB,eAAuC;AAAvC;AAAA,EACpB;AAAA,EACM,SAAU,MAAc,KAAoB;AAAA;AAChD,aAAO,eAAe,KAAK,eAAe,MAAM,GAAG;AAAA,IACrD;AAAA;AAAA,EACM,QAAS,MAAc,KAAoB;AAAA;AAC/C,aAAO,cAAc,KAAK,eAAe,MAAM,GAAG;AAAA,IACpD;AAAA;AACF;AAGO,MAAM,sBAAsB,CAAC,SAAiB;AACnD,QAAM,IAAI,IAAI,UAAU;AACxB,MAAI,MAAM,CAAC;AACX,MAAG,KAAK,WAAW,IAAI,GAAG;AACxB,UAAM,EAAE,mBAAmB,KAAK;AAAA,EAClC,WAAS,KAAK,WAAW,MAAM,GAAG;AAChC,UAAM,EAAE,YAAY,KAAK;AAAA,EAC3B;AACA,SAAO,MAAM,EAAE,QAAQ,GAAG;AAC5B;AAGO,MAAM,iBAAiB,CAAC,QAAiE;AAC9F,MAAG,IAAI,SAAS,MAAM;AACpB,WAAO,IAAI,mBAAmB,IAAI,aAAa,IAAI,QAAQ;AAAA,EAC7D;AACA,MAAG,IAAI,cAAc;AACnB,WAAO,IAAI,mBAAmB,oBAAoB,IAAI,YAAY,CAAC;AAAA,EACrE;AACA,MAAG,IAAI,eAAe;AACpB,WAAO,IAAI,mBAAmB,IAAI,aAAa;AAAA,EACjD;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/infra/support/render/index.ts"],"sourcesContent":["import {html2imgBuffer, RenderOptions, url2imgBuffer} from \"./puppeteer\";\nimport {Browser, Puppeteer} from \"puppeteer-core\";\nimport {Fetch} from \"@/infra/support/fetch\";\nexport {RenderOptions as PuppeteerOptions}\nexport interface ImageRender {\n html2img: (html: string, opt: RenderOptions) => Promise<Buffer>\n url2img: (url: string, opt: RenderOptions) => Promise<Buffer>\n}\n\nexport type RenderConfig = {\n mode: 'cf' | 'puppeteer' | 'custom'\n puppeteerURL?: string\n defaultWaitTimeout?: number\n waitTimeout?: number\n cfAccountId?: string,\n cfAPIKey?: string,\n}\n\nexport class CFBrowserRendering implements ImageRender {\n f: Fetch\n constructor(accountId: string, cfAPIKey: string) {\n this.f = new Fetch()\n .baseUrl(`https://api.cloudflare.com/client/v4/accounts/${accountId}`)\n .extend({\n headers: {\n Authorization: `Bearer ${cfAPIKey}`\n },\n })\n }\n private post(body) {\n return this.f.post('/browser-rendering/screenshot', {\n responseType: 'arrayBuffer',\n body: {\n \"screenshotOptions\": {\n quality: 90\n },\n ...body,\n \"viewport\": {\n \"width\": 3840,\n \"height\": 2160,\n \"deviceScaleFactor\": 2,\n },\n \"gotoOptions\": {\n \"waitUntil\": \"networkidle0\",\n \"timeout\": 30000\n },\n }\n })\n }\n\n\n\n async html2img (html: string, opt: RenderOptions) {\n const buf = await this.post({html: html, ...opt})\n return Buffer.from(buf)\n }\n async url2img (url: string, opt: RenderOptions) {\n const buf = await this.post({url: url, ...opt})\n return Buffer.from(buf)\n }\n}\n\nexport class PuppeteerRendering implements ImageRender {\n constructor(private browserGetter: () => Promise<Browser>) {\n }\n async html2img (html: string, opt: RenderOptions) {\n return html2imgBuffer(this.browserGetter, html, opt)\n }\n async url2img (html: string, opt: RenderOptions) {\n return url2imgBuffer(this.browserGetter, html, opt)\n }\n}\n\n\nexport const RemoteBrowserGetter = (addr: string) => {\n const p = new Puppeteer()\n let opt = {}\n if(addr.startsWith('ws')) {\n opt = { browserWSEndpoint: addr }\n }else if(addr.startsWith('http')) {\n opt = { browserURL: addr }\n }\n return () => p.connect(opt)\n}\n\n\n\nexport const getImageRender = (cfg: RenderConfig & {render?: ImageRender,browserGetter?: () => Promise<Browser>}) => {\n if(cfg.mode === 'cf') {\n return new CFBrowserRendering(cfg.cfAccountId, cfg.cfAPIKey)\n }\n if(cfg.mode === 'custom') {\n if(!cfg.render) throw new Error(\"please provide custom img render\")\n return cfg.render\n }\n if(cfg.puppeteerURL) {\n return new PuppeteerRendering(RemoteBrowserGetter(cfg.puppeteerURL))\n }\n if(cfg.browserGetter) {\n return new PuppeteerRendering(cfg.browserGetter)\n }\n}\n\nexport type CreateImageRenderOption = Parameters<typeof getImageRender>[0]\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAQ,gBAAgB,eAAe,qBAAoB;AAC3D,SAAiB,iBAAgB;AACjC,SAAQ,aAAY;AAgBb,MAAM,mBAA0C;AAAA,EAErD,YAAY,WAAmB,UAAkB;AADjD;AAEE,SAAK,IAAI,IAAI,MAAM,EAChB,QAAQ,iDAAiD,SAAS,EAAE,EACpE,OAAO;AAAA,MACN,SAAS;AAAA,QACP,eAAe,UAAU,QAAQ;AAAA,MACnC;AAAA,IACF,CAAC;AAAA,EACL;AAAA,EACQ,KAAK,MAAM;AACjB,WAAO,KAAK,EAAE,KAAK,iCAAiC;AAAA,MAClD,cAAc;AAAA,MACd,MAAM;AAAA,QACJ,qBAAqB;AAAA,UACnB,SAAS;AAAA,QACX;AAAA,SACG,OAJC;AAAA,QAKJ,YAAY;AAAA,UACV,SAAS;AAAA,UACT,UAAU;AAAA,UACV,qBAAqB;AAAA,QACvB;AAAA,QACA,eAAe;AAAA,UACb,aAAa;AAAA,UACb,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAIM,SAAU,MAAc,KAAoB;AAAA;AAChD,YAAM,MAAM,MAAM,KAAK,KAAK,iBAAC,QAAe,IAAI;AAChD,aAAO,OAAO,KAAK,GAAG;AAAA,IACxB;AAAA;AAAA,EACM,QAAS,KAAa,KAAoB;AAAA;AAC9C,YAAM,MAAM,MAAM,KAAK,KAAK,iBAAC,OAAa,IAAI;AAC9C,aAAO,OAAO,KAAK,GAAG;AAAA,IACxB;AAAA;AACF;AAEO,MAAM,mBAA0C;AAAA,EACrD,YAAoB,eAAuC;AAAvC;AAAA,EACpB;AAAA,EACM,SAAU,MAAc,KAAoB;AAAA;AAChD,aAAO,eAAe,KAAK,eAAe,MAAM,GAAG;AAAA,IACrD;AAAA;AAAA,EACM,QAAS,MAAc,KAAoB;AAAA;AAC/C,aAAO,cAAc,KAAK,eAAe,MAAM,GAAG;AAAA,IACpD;AAAA;AACF;AAGO,MAAM,sBAAsB,CAAC,SAAiB;AACnD,QAAM,IAAI,IAAI,UAAU;AACxB,MAAI,MAAM,CAAC;AACX,MAAG,KAAK,WAAW,IAAI,GAAG;AACxB,UAAM,EAAE,mBAAmB,KAAK;AAAA,EAClC,WAAS,KAAK,WAAW,MAAM,GAAG;AAChC,UAAM,EAAE,YAAY,KAAK;AAAA,EAC3B;AACA,SAAO,MAAM,EAAE,QAAQ,GAAG;AAC5B;AAIO,MAAM,iBAAiB,CAAC,QAAsF;AACnH,MAAG,IAAI,SAAS,MAAM;AACpB,WAAO,IAAI,mBAAmB,IAAI,aAAa,IAAI,QAAQ;AAAA,EAC7D;AACA,MAAG,IAAI,SAAS,UAAU;AACxB,QAAG,CAAC,IAAI,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AAClE,WAAQ,IAAI;AAAA,EACd;AACA,MAAG,IAAI,cAAc;AACnB,WAAO,IAAI,mBAAmB,oBAAoB,IAAI,YAAY,CAAC;AAAA,EACrE;AACA,MAAG,IAAI,eAAe;AACpB,WAAO,IAAI,mBAAmB,IAAI,aAAa;AAAA,EACjD;AACF;","names":[]}
@@ -1,2 +1 @@
1
- export * from "./models";
2
1
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/interface/db/index.ts"],"sourcesContent":["import {\n RelateAccount,\n RelateChannelInfo,\n Subscribe,\n SubscribeMember,\n} from './models'\n\nexport * from './models'\n\nexport interface SubInfoRes {\n subscribe: Subscribe\n memberCount: number\n me: any\n}\n\nexport interface SubInfoRes {\n subscribe: Subscribe\n memberCount: number\n me: any\n}\n\nexport interface SubDetailWithGroupRes<T> {\n account: RelateAccount\n accountChannel: RelateChannelInfo<T>\n subscribeMember: SubscribeMember\n subscribe: Subscribe\n groupChannel: RelateChannelInfo<T>\n}\n\nexport interface SubWithGroupRes<T> {\n subscribe: Subscribe\n groupChannel: RelateChannelInfo<T>\n}\n\nexport interface DB<T> {\n storeUserPreference<V = any>(\n uid: number,\n // channelId: string | undefined,\n value: V\n ): Promise<boolean>\n getUserPreference<V = any>(\n uid: number\n // channelId: string | undefined,\n // value: V\n ): Promise<V>\n getUserAccountsByUid(id: number): Promise<Record<string, RelateAccount>>\n\n batchGetOrCreateUBySessionInfo(s: T[]): Promise<RelateChannelInfo<T>[]>\n getUAndGBySessionInfo(\n s: T\n ): Promise<[RelateChannelInfo<T>, RelateChannelInfo<T>]>\n\n // binding\n addUserBindingInfo(account: Partial<RelateAccount>): Promise<void>\n\n // subscription\n upsertSubscription(data: Partial<Subscribe>): Promise<void>\n\n getSubscriptionInfoByUGID(gid: number, uid: number): Promise<SubInfoRes[]>\n getSubscriptionsByGID(gid: number): Promise<Record<string, Subscribe>>\n // group subscription\n getIDSubscriptionByGID(gid: number): Promise<Subscribe[]>\n getIDSubscriptionByType(type: string): Promise<SubWithGroupRes<T>[]>\n removeIDSubscriptionByID(id: number): Promise<void>\n getIDSubscriptionByGIDAndType(gid: number, type: string): Promise<Subscribe[]>\n getAllSubscriptionByUIDAndPlatform(\n id: string | number,\n type: string\n ): Promise<SubDetailWithGroupRes<T>[]>\n\n getSubscriptionsByType(type: string): Promise<SubDetailWithGroupRes<T>[]>\n addSubscribeMember(data: Partial<SubscribeMember>): Promise<void>\n removeFromSubGroupBySubAndUid(subId: number, id: number): Promise<void>\n}\n"],"mappings":"AAOA,cAAc;","names":[]}
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/interface/index.ts"],"sourcesContent":["export * from './db'\nexport * from './logger'\nexport * from './bot'\nexport enum Platform {\n SS = 'scoresaber',\n BS = 'beatsaver',\n BL = 'beatleader',\n}\n\nexport const parsePlatform = (p: string) => {\n return p == 'ss' ? Platform.SS : Platform.BL\n}\n\nexport * from './cmd/type'\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACP,IAAK,WAAL,kBAAKA,cAAL;AACL,EAAAA,UAAA,QAAK;AACL,EAAAA,UAAA,QAAK;AACL,EAAAA,UAAA,QAAK;AAHK,SAAAA;AAAA,GAAA;AAML,MAAM,gBAAgB,CAAC,MAAc;AAC1C,SAAO,KAAK,OAAO,wBAAc;AACnC;AAEA,cAAc;","names":["Platform"]}
1
+ {"version":3,"sources":["../../../src/interface/index.ts"],"sourcesContent":["import type {APIService, RenderService} from \"@/service\";\n\nimport type { DB } from \"@/interface\";\nexport * from './db'\nexport * from './logger'\nexport * from './bot'\nexport enum Platform {\n SS = 'scoresaber',\n BS = 'beatsaver',\n BL = 'beatleader',\n}\n\nexport const parsePlatform = (p: string) => {\n return p == 'ss' ? Platform.SS : Platform.BL\n}\nexport type Services<T> = {\n render: RenderService,\n api: APIService,\n db: DB<T>\n}\nexport * from './cmd/type'\n"],"mappings":"AAGA,cAAc;AACd,cAAc;AACd,cAAc;AACP,IAAK,WAAL,kBAAKA,cAAL;AACL,EAAAA,UAAA,QAAK;AACL,EAAAA,UAAA,QAAK;AACL,EAAAA,UAAA,QAAK;AAHK,SAAAA;AAAA,GAAA;AAML,MAAM,gBAAgB,CAAC,MAAc;AAC1C,SAAO,KAAK,OAAO,wBAAc;AACnC;AAMA,cAAc;","names":["Platform"]}
@@ -1,11 +1,11 @@
1
- import { LBScoreMonitor } from "../schedules/temp";
1
+ import { LBScoreMonitor } from "./temp";
2
2
  const getScheduleTasks = (config) => {
3
3
  return [
4
4
  {
5
5
  name: "lb-rank-notifier",
6
6
  handler: LBScoreMonitor,
7
7
  cron: config.tempCron.cron,
8
- enable: config.tempCron.enable
8
+ enabled: config.tempCron.enabled
9
9
  }
10
10
  ];
11
11
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/schedules/index.ts"],"sourcesContent":["import { Config } from '@/config'\nimport { LBScoreMonitor } from '@/schedules/temp'\n\n\nexport const getScheduleTasks = (config: Config) => {\n return [\n {\n name: 'lb-rank-notifier',\n handler: LBScoreMonitor,\n cron: config.tempCron.cron,\n enable: config.tempCron.enable,\n },\n ]\n}\n"],"mappings":"AACA,SAAS,sBAAsB;AAGxB,MAAM,mBAAmB,CAAC,WAAmB;AAClD,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,OAAO,SAAS;AAAA,MACtB,QAAQ,OAAO,SAAS;AAAA,IAC1B;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/schedules/index.ts"],"sourcesContent":["import { Config } from '@/config'\nimport { LBScoreMonitor } from './temp'\n\n\nexport const getScheduleTasks = (config: Config) => {\n return [\n {\n name: 'lb-rank-notifier',\n handler: LBScoreMonitor,\n cron: config.tempCron.cron,\n enabled: config.tempCron.enabled,\n },\n ]\n}\n"],"mappings":"AACA,SAAS,sBAAsB;AAGxB,MAAM,mBAAmB,CAAC,WAAmB;AAClD,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,SAAS;AAAA,MACT,MAAM,OAAO,SAAS;AAAA,MACtB,SAAS,OAAO,SAAS;AAAA,IAC3B;AAAA,EACF;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/schedules/temp.ts"],"sourcesContent":["import { ScheduleTaskCtx } from '@/schedules/interface'\n\nexport const LBScoreMonitor = async <T>(c: ScheduleTaskCtx<T>) => {\n const channels = await c.services.db.getSubscriptionsByType('lb-rank')\n if (channels.length <= 0) {\n return\n }\n const [hitbuf, scorebuf] = await Promise.all([\n c.services.render.renderUrl('https://aiobs.ktlab.io/tmp/lb/hitcnt'),\n c.services.render.renderUrl('https://aiobs.ktlab.io/tmp/lb/score'),\n ])\n for (const group of channels) {\n const session = c.botService.getSessionByChannelInfo(group.groupChannel)\n if (!session) {\n continue\n }\n await session.sendImgBuffer(hitbuf, 'image/png')\n await session.sendImgBuffer(scorebuf, 'image/png')\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAEO,MAAM,iBAAiB,CAAU,MAA0B;AAChE,QAAM,WAAW,MAAM,EAAE,SAAS,GAAG,uBAAuB,SAAS;AACrE,MAAI,SAAS,UAAU,GAAG;AACxB;AAAA,EACF;AACA,QAAM,CAAC,QAAQ,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,EAAE,SAAS,OAAO,UAAU,sCAAsC;AAAA,IAClE,EAAE,SAAS,OAAO,UAAU,qCAAqC;AAAA,EACnE,CAAC;AACD,aAAW,SAAS,UAAU;AAC5B,UAAM,UAAU,EAAE,WAAW,wBAAwB,MAAM,YAAY;AACvE,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,QAAQ,WAAW;AAC/C,UAAM,QAAQ,cAAc,UAAU,WAAW;AAAA,EACnD;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/schedules/temp.ts"],"sourcesContent":["import { ScheduleTaskCtx } from './interface'\n\nexport const LBScoreMonitor = async <T>(c: ScheduleTaskCtx<T>) => {\n const channels = await c.services.db.getSubscriptionsByType('lb-rank')\n if (channels.length <= 0) {\n return\n }\n const [hitbuf, scorebuf] = await Promise.all([\n c.services.render.renderUrl('https://aiobs.ktlab.io/tmp/lb/hitcnt'),\n c.services.render.renderUrl('https://aiobs.ktlab.io/tmp/lb/score'),\n ])\n for (const group of channels) {\n const session = c.botService.getSessionByChannelInfo(group.groupChannel)\n if (!session) {\n continue\n }\n await session.sendImgBuffer(hitbuf, 'image/png')\n await session.sendImgBuffer(scorebuf, 'image/png')\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAEO,MAAM,iBAAiB,CAAU,MAA0B;AAChE,QAAM,WAAW,MAAM,EAAE,SAAS,GAAG,uBAAuB,SAAS;AACrE,MAAI,SAAS,UAAU,GAAG;AACxB;AAAA,EACF;AACA,QAAM,CAAC,QAAQ,QAAQ,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC3C,EAAE,SAAS,OAAO,UAAU,sCAAsC;AAAA,IAClE,EAAE,SAAS,OAAO,UAAU,qCAAqC;AAAA,EACnE,CAAC;AACD,aAAW,SAAS,UAAU;AAC5B,UAAM,UAAU,EAAE,WAAW,wBAAwB,MAAM,YAAY;AACvE,QAAI,CAAC,SAAS;AACZ;AAAA,IACF;AACA,UAAM,QAAQ,cAAc,QAAQ,WAAW;AAC/C,UAAM,QAAQ,cAAc,UAAU,WAAW;AAAA,EACnD;AACF;","names":[]}
@@ -38,7 +38,7 @@ var __async = (__this, __arguments, generator) => {
38
38
  import { AIOSaberClient, BeatLeaderClient, BeatSaverClient, ScoreSaberClient } from "./base";
39
39
  import { BLIDNotFoundError, MapIdNotFoundError, SSIDNotFoundError } from "../../infra/errors";
40
40
  import { NotFoundError } from "../../infra/support/fetch/error";
41
- import { sortScore } from "../../service/api/sortScore";
41
+ import { sortScore } from "./sortScore";
42
42
  import { decode } from "../../components/utils/bl/bsorDecoder";
43
43
  class APIService {
44
44
  constructor(cfg, logger) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/service/api/index.ts"],"sourcesContent":["import {AIOSaberClient, BeatLeaderClient, BeatSaverClient, ScoreSaberClient} from \"./base\";\nimport {Config} from \"@/config\";\nimport {Logger} from \"@/interface\";\nimport {BLIDNotFoundError, MapIdNotFoundError, SSIDNotFoundError} from \"@/infra/errors\";\nimport {BSMap, HashResponse} from \"@/service/api/interfaces/beatsaver\";\nimport {ScoreSaberItem} from \"@/service/api/interfaces/scoresaber\";\nimport {Leaderboard} from \"@/service/api/interfaces/beatleader\";\nimport {NotFoundError} from \"@/infra/support/fetch/error\";\nimport {sortScore} from \"@/service/api/sortScore\";\nimport {decode} from \"@/components/utils/bl/bsorDecoder\";\n\ntype MapDiffOption = {\n difficulty?: string\n mode?: string\n}\n\n\nexport class APIService {\n BeatLeader: BeatLeaderClient\n ScoreSaber: ScoreSaberClient\n BeatSaver: BeatSaverClient\n AIOSaber: AIOSaberClient\n constructor(cfg: Config, logger: Logger) {\n this.BeatSaver = new BeatSaverClient({logger})\n this.BeatLeader = new BeatLeaderClient({logger})\n this.ScoreSaber = new ScoreSaberClient(logger)\n this.AIOSaber = new AIOSaberClient(logger)\n }\n async getBLPlayerScoresWithUserInfo(accountId: string) {\n const [userInfo, playerScores, pinnedScores] = await Promise.all([\n this.BeatLeader.getPlayerInfo(accountId),\n this.BeatLeader.getPlayerScores(accountId),\n this.BeatLeader.getPlayerPinnedScores(accountId),\n ])\n if (!(userInfo && playerScores)) {\n throw new BLIDNotFoundError({ accountId })\n }\n const filteredScores = playerScores.data.filter(\n (item) => !pinnedScores.some((pinned) => pinned.id === item.id)\n )\n const scores = pinnedScores.concat(filteredScores).slice(0, 24)\n return {\n scores: scores,\n userInfo: userInfo,\n }\n }\n async getSSPlayerScoresWithUserInfo(accountId: string) {\n\n }\n async getScoreByPlayerIdAndMapId(\n playerId: string,\n mapId: string,\n option?: MapDiffOption\n ): Promise<Leaderboard> {\n const map = await this.BeatSaver.searchMapById(mapId)\n if (!map) {\n throw new MapIdNotFoundError()\n }\n const hash = map.versions[0].hash\n let reqs = map.versions[0].diffs.map((it) => ({\n diff: it.difficulty,\n mode: it.characteristic,\n hash: hash,\n playerID: playerId,\n leaderboardContext: 'general',\n }))\n if (option && option.difficulty) {\n reqs = reqs.filter((item) => item.diff == option.difficulty)\n }\n if (option && option.mode) {\n reqs = reqs.filter((item) => item.mode == option.mode)\n }\n const res = await Promise.allSettled(reqs.map(\n (it) => this.BeatLeader.getPlayerScore(it)))\n const scores = res\n .filter((item) => item.status === 'fulfilled')\n .map(<T>(it: PromiseFulfilledResult<T>) => it.value)\n if (scores.length < 1) {\n throw new NotFoundError()\n }\n scores.sort(sortScore)\n return scores[0]\n }\n\n async getAroundScoreAndRegionScoreByRankAndPage(\n leaderboardId: string,\n rank: number,\n regionCode: string\n ) {\n const page = Math.ceil(rank / 10)\n const rest = rank % 10\n let startIndex = 0\n if (rest > 7) {\n startIndex = 2\n }\n const [regionScore, aroundScore] = await Promise.all([\n this.BeatLeader.getLeaderboard(leaderboardId, {\n leaderboardContext: 'general',\n page: 1,\n sortBy: 'rank',\n order: 'desc',\n countries: regionCode,\n }),\n this.BeatLeader.getLeaderboard(leaderboardId, {\n leaderboardContext: 'general',\n page: page,\n sortBy: 'rank',\n order: 'desc',\n }),\n ])\n const difficulties = regionScore.song.difficulties\n return {\n difficulties: difficulties,\n aroundScores: aroundScore.scores.slice(startIndex, startIndex + 7),\n regionTopScores: regionScore.scores,\n }\n }\n async getScoreAndBSMapByScoreId(scoreId: string) {\n const res = await this.BeatLeader.getBeatScore(scoreId)\n const bsorLink = res.replay\n const bsorContent = await fetch(bsorLink)\n const bsor = await new Promise((resolve, reject) => {\n bsorContent.arrayBuffer().then((res) => decode(res, resolve))\n setTimeout(() => reject('timeout exceed'), 5000)\n })\n const statistic = await fetch(\n `https://cdn.scorestats.beatleader.xyz/${scoreId}.json`\n ).then((res) => res.json())\n const id = res.song.id.split('x')?.[0]\n const bsMap = await this.BeatSaver.searchMapById(id)\n return {\n score: res,\n bsMap: bsMap,\n statistic: statistic,\n bsor: bsor,\n }\n }\n async getSSPlayerRecentScoreWithUserInfo(uid: string) {\n const [userInfo, scores] = await Promise.all([\n this.ScoreSaber.getScoreUserById(uid),\n this.ScoreSaber.getScoreItemsById(uid, 1, 24)\n .then((res) => res?.playerScores),\n ])\n if (!scores || !userInfo) {\n throw new SSIDNotFoundError({ accountId: uid })\n }\n const hashes = scores.map((it) => it.leaderboard.songHash)\n\n let hashInfo = await this.BeatSaver.getMapsByHashes(hashes)\n if (hashInfo.id) {\n const map = hashInfo as BSMap\n hashInfo = {} as HashResponse\n hashInfo[map.versions[0].hash] = map\n }\n const res = scores.map(\n (it) =>\n ({\n mapId: (hashInfo as HashResponse)[\n it.leaderboard.songHash.toLowerCase()\n ]?.id,\n ...it,\n }) as ScoreSaberItem\n )\n return {\n scores: res,\n userInfo: userInfo,\n }\n }\n}\n"],"mappings":"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","names":["res"]}
1
+ {"version":3,"sources":["../../../../src/service/api/index.ts"],"sourcesContent":["import {AIOSaberClient, BeatLeaderClient, BeatSaverClient, ScoreSaberClient} from \"./base\";\nimport {Config} from \"@/config\";\nimport {Logger} from \"@/interface\";\nimport {BLIDNotFoundError, MapIdNotFoundError, SSIDNotFoundError} from \"@/infra/errors\";\nimport {BSMap, HashResponse} from \"./interfaces/beatsaver\";\nimport {ScoreSaberItem} from \"./interfaces/scoresaber\";\nimport {Leaderboard} from \"./interfaces/beatleader\";\nimport {NotFoundError} from \"@/infra/support/fetch/error\";\nimport {sortScore} from \"./sortScore\";\nimport {decode} from \"@/components/utils/bl/bsorDecoder\";\n\ntype MapDiffOption = {\n difficulty?: string\n mode?: string\n}\n\n\nexport class APIService {\n BeatLeader: BeatLeaderClient\n ScoreSaber: ScoreSaberClient\n BeatSaver: BeatSaverClient\n AIOSaber: AIOSaberClient\n constructor(cfg: Config, logger: Logger) {\n this.BeatSaver = new BeatSaverClient({logger})\n this.BeatLeader = new BeatLeaderClient({logger})\n this.ScoreSaber = new ScoreSaberClient(logger)\n this.AIOSaber = new AIOSaberClient(logger)\n }\n async getBLPlayerScoresWithUserInfo(accountId: string) {\n const [userInfo, playerScores, pinnedScores] = await Promise.all([\n this.BeatLeader.getPlayerInfo(accountId),\n this.BeatLeader.getPlayerScores(accountId),\n this.BeatLeader.getPlayerPinnedScores(accountId),\n ])\n if (!(userInfo && playerScores)) {\n throw new BLIDNotFoundError({ accountId })\n }\n const filteredScores = playerScores.data.filter(\n (item) => !pinnedScores.some((pinned) => pinned.id === item.id)\n )\n const scores = pinnedScores.concat(filteredScores).slice(0, 24)\n return {\n scores: scores,\n userInfo: userInfo,\n }\n }\n async getSSPlayerScoresWithUserInfo(accountId: string) {\n\n }\n async getScoreByPlayerIdAndMapId(\n playerId: string,\n mapId: string,\n option?: MapDiffOption\n ): Promise<Leaderboard> {\n const map = await this.BeatSaver.searchMapById(mapId)\n if (!map) {\n throw new MapIdNotFoundError()\n }\n const hash = map.versions[0].hash\n let reqs = map.versions[0].diffs.map((it) => ({\n diff: it.difficulty,\n mode: it.characteristic,\n hash: hash,\n playerID: playerId,\n leaderboardContext: 'general',\n }))\n if (option && option.difficulty) {\n reqs = reqs.filter((item) => item.diff == option.difficulty)\n }\n if (option && option.mode) {\n reqs = reqs.filter((item) => item.mode == option.mode)\n }\n const res = await Promise.allSettled(reqs.map(\n (it) => this.BeatLeader.getPlayerScore(it)))\n const scores = res\n .filter((item) => item.status === 'fulfilled')\n .map(<T>(it: PromiseFulfilledResult<T>) => it.value)\n if (scores.length < 1) {\n throw new NotFoundError()\n }\n scores.sort(sortScore)\n return scores[0]\n }\n\n async getAroundScoreAndRegionScoreByRankAndPage(\n leaderboardId: string,\n rank: number,\n regionCode: string\n ) {\n const page = Math.ceil(rank / 10)\n const rest = rank % 10\n let startIndex = 0\n if (rest > 7) {\n startIndex = 2\n }\n const [regionScore, aroundScore] = await Promise.all([\n this.BeatLeader.getLeaderboard(leaderboardId, {\n leaderboardContext: 'general',\n page: 1,\n sortBy: 'rank',\n order: 'desc',\n countries: regionCode,\n }),\n this.BeatLeader.getLeaderboard(leaderboardId, {\n leaderboardContext: 'general',\n page: page,\n sortBy: 'rank',\n order: 'desc',\n }),\n ])\n const difficulties = regionScore.song.difficulties\n return {\n difficulties: difficulties,\n aroundScores: aroundScore.scores.slice(startIndex, startIndex + 7),\n regionTopScores: regionScore.scores,\n }\n }\n async getScoreAndBSMapByScoreId(scoreId: string) {\n const res = await this.BeatLeader.getBeatScore(scoreId)\n const bsorLink = res.replay\n const bsorContent = await fetch(bsorLink)\n const bsor = await new Promise((resolve, reject) => {\n bsorContent.arrayBuffer().then((res) => decode(res, resolve))\n setTimeout(() => reject('timeout exceed'), 5000)\n })\n const statistic = await fetch(\n `https://cdn.scorestats.beatleader.xyz/${scoreId}.json`\n ).then((res) => res.json())\n const id = res.song.id.split('x')?.[0]\n const bsMap = await this.BeatSaver.searchMapById(id)\n return {\n score: res,\n bsMap: bsMap,\n statistic: statistic,\n bsor: bsor,\n }\n }\n async getSSPlayerRecentScoreWithUserInfo(uid: string) {\n const [userInfo, scores] = await Promise.all([\n this.ScoreSaber.getScoreUserById(uid),\n this.ScoreSaber.getScoreItemsById(uid, 1, 24)\n .then((res) => res?.playerScores),\n ])\n if (!scores || !userInfo) {\n throw new SSIDNotFoundError({ accountId: uid })\n }\n const hashes = scores.map((it) => it.leaderboard.songHash)\n\n let hashInfo = await this.BeatSaver.getMapsByHashes(hashes)\n if (hashInfo.id) {\n const map = hashInfo as BSMap\n hashInfo = {} as HashResponse\n hashInfo[map.versions[0].hash] = map\n }\n const res = scores.map(\n (it) =>\n ({\n mapId: (hashInfo as HashResponse)[\n it.leaderboard.songHash.toLowerCase()\n ]?.id,\n ...it,\n }) as ScoreSaberItem\n )\n return {\n scores: res,\n userInfo: userInfo,\n }\n }\n}\n"],"mappings":"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","names":["res"]}
@@ -1 +1,7 @@
1
+ import { APIService } from "./api";
2
+ import { RenderService } from "./render";
3
+ export {
4
+ APIService,
5
+ RenderService
6
+ };
1
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../../src/service/index.ts"],"sourcesContent":["export { APIService } from './api'\nexport { RenderService } from './render'\n"],"mappings":"AAAA,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/service/preference.ts"],"sourcesContent":["import { DB } from '@/interface'\nimport { LRUCache } from 'lru-cache'\n\n// uid is key currently\n\nconst cache = new LRUCache({\n max: 500,\n maxSize: 500,\n sizeCalculation: () => 1,\n ttl: 1000 * 60 * 60 * 24 * 7,\n allowStale: false,\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n})\n\nexport class UserPreferenceStore {\n v: any = undefined\n constructor(\n private db: DB<any>,\n private uid: number\n ) {}\n async getUserPreference(uid: number) {\n return new UserPreferenceStore(this.db, uid)\n }\n async set<T extends string | number | boolean>(\n key: string,\n value: T\n ): Promise<boolean> {\n if (!this.v) {\n this.v = (await this.db.getUserPreference(this.uid)) ?? {}\n }\n const cacheKey = `${this.uid}`\n const v = {\n ...this.v,\n [key]: value,\n }\n await this.db.storeUserPreference(this.uid, v)\n cache.set(cacheKey, v)\n this.v = v\n return true\n }\n async get<T extends string | number | boolean>(\n key: string\n ): Promise<T | undefined> {\n const cacheKey = `${this.uid}`\n const has = cache.has(cacheKey)\n if (has) {\n const v = cache.get(cacheKey) as T\n return v?.[key] ?? preferenceSchema[key]?.default\n }\n const value = (await this.db.getUserPreference(this.uid)) ?? {}\n cache.set(cacheKey, value)\n return (value?.[key] as T) ?? preferenceSchema[key]?.default\n }\n async configEntries(): Promise<Record<string, any>> {\n await this.get('')\n return cache.get(this.uid) as Record<string, any>\n }\n}\n\ntype PreferenceItem = {\n key: string\n i18nName: string\n valueType: 'img-url' | 'string' | 'number' | 'boolean'\n default: any\n}\nexport const preferenceKey = {\n blProfileRenderImg: {\n key: 'bl::profile::render::img',\n i18nName: 'BLProfile背景图片',\n },\n ssProfileRenderImg: {\n key: 'ss::profile::render::img',\n i18nName: 'SSProfile背景图片',\n },\n blScoreImg: {\n key: 'bl::score::render::img',\n i18nName: 'BLScore背景图片',\n },\n}\n\nexport const preferenceSchema: Record<string, PreferenceItem> = {\n 'bl::profile::render::img': {\n key: 'bl::profile::render::img',\n i18nName: 'BLProfile背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n 'ss::profile::render::img': {\n key: 'ss::profile::render::img',\n i18nName: 'SSProfile背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n 'bl::score::render::img': {\n key: 'bl::score::render::img',\n i18nName: 'BLScore背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n}\n\nconst preferenceMap = new Map<string, PreferenceItem>()\n\nObject.entries(preferenceSchema).forEach(([key, value]) => {\n preferenceMap.set(value.i18nName, value)\n})\n\nexport const hasPreferenceSchemaByKeyOrName = (key: string) => {\n if (key in preferenceSchema) {\n return true\n }\n return preferenceMap.has(key)\n}\nexport const getPreferenceSchemaByKeyOrName = (key: string) => {\n if (key in preferenceSchema) {\n return preferenceSchema[key]\n }\n return preferenceMap.get(key)\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/service/preference.ts"],"sourcesContent":["import { DB } from '@/interface'\nimport { LRUCache } from 'lru-cache'\n\nconst cache = new LRUCache({\n max: 500,\n maxSize: 500,\n sizeCalculation: () => 1,\n ttl: 1000 * 60 * 60 * 24 * 7,\n allowStale: false,\n updateAgeOnGet: true,\n updateAgeOnHas: true,\n})\n\nexport class UserPreferenceStore {\n v: any = undefined\n constructor(\n private db: DB<any>,\n private uid: number\n ) {}\n async getUserPreference(uid: number) {\n return new UserPreferenceStore(this.db, uid)\n }\n async set<T extends string | number | boolean>(\n key: string,\n value: T\n ): Promise<boolean> {\n if (!this.v) {\n this.v = (await this.db.getUserPreference(this.uid)) ?? {}\n }\n const cacheKey = `${this.uid}`\n const v = {\n ...this.v,\n [key]: value,\n }\n await this.db.storeUserPreference(this.uid, v)\n cache.set(cacheKey, v)\n this.v = v\n return true\n }\n async get<T extends string | number | boolean>(\n key: string\n ): Promise<T | undefined> {\n const cacheKey = `${this.uid}`\n const has = cache.has(cacheKey)\n if (has) {\n const v = cache.get(cacheKey) as T\n return v?.[key] ?? preferenceSchema[key]?.default\n }\n const value = (await this.db.getUserPreference(this.uid)) ?? {}\n cache.set(cacheKey, value)\n return (value?.[key] as T) ?? preferenceSchema[key]?.default\n }\n async configEntries(): Promise<Record<string, any>> {\n await this.get('')\n return cache.get(this.uid) as Record<string, any>\n }\n}\n\ntype PreferenceItem = {\n key: string\n i18nName: string\n valueType: 'img-url' | 'string' | 'number' | 'boolean'\n default: any\n}\nexport const preferenceKey = {\n blProfileRenderImg: {\n key: 'bl::profile::render::img',\n i18nName: 'BLProfile背景图片',\n },\n ssProfileRenderImg: {\n key: 'ss::profile::render::img',\n i18nName: 'SSProfile背景图片',\n },\n blScoreImg: {\n key: 'bl::score::render::img',\n i18nName: 'BLScore背景图片',\n },\n}\n\nexport const preferenceSchema: Record<string, PreferenceItem> = {\n 'bl::profile::render::img': {\n key: 'bl::profile::render::img',\n i18nName: 'BLProfile背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n 'ss::profile::render::img': {\n key: 'ss::profile::render::img',\n i18nName: 'SSProfile背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n 'bl::score::render::img': {\n key: 'bl::score::render::img',\n i18nName: 'BLScore背景图片',\n valueType: 'img-url',\n default: 'https://www.loliapi.com/acg/pc/',\n },\n}\n\nconst preferenceMap = new Map<string, PreferenceItem>()\n\nObject.entries(preferenceSchema).forEach(([key, value]) => {\n preferenceMap.set(value.i18nName, value)\n})\n\nexport const hasPreferenceSchemaByKeyOrName = (key: string) => {\n if (key in preferenceSchema) {\n return true\n }\n return preferenceMap.has(key)\n}\nexport const getPreferenceSchemaByKeyOrName = (key: string) => {\n if (key in preferenceSchema) {\n return preferenceSchema[key]\n }\n return preferenceMap.get(key)\n}\n"],"mappings":"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","names":[]}
@@ -38,9 +38,10 @@ import { getHtml } from "../../components";
38
38
  import { PuppeteerError, TimeoutError } from "puppeteer-core";
39
39
  import { Platform } from "../../interface";
40
40
  import { getBLPlayerComp, getBLRankScoreComp, getBSMapComp, getSSPlayerComp } from "../../components/pages";
41
- import { preferenceKey } from "../../service/preference";
41
+ import { preferenceKey } from "../preference";
42
42
  import { ImageRenderError, RequestError } from "../../infra/errors";
43
43
  import createQrcode from "../../components/utils/qrcode";
44
+ import { getImageRender } from "../../infra/support/render";
44
45
  const getPreferenceKey = (platform) => {
45
46
  return platform == Platform.SS ? preferenceKey.ssProfileRenderImg.key : preferenceKey.blProfileRenderImg.key;
46
47
  };
@@ -49,6 +50,9 @@ class RenderService {
49
50
  this.api = api;
50
51
  this.imageRender = imageRender;
51
52
  }
53
+ static create(imgRenderConfig, api) {
54
+ return new RenderService(api, getImageRender(imgRenderConfig));
55
+ }
52
56
  renderRank(accountId, platform, renderOpts) {
53
57
  return __async(this, null, function* () {
54
58
  var _a;
@@ -113,7 +117,13 @@ class RenderService {
113
117
  }
114
118
  renderUrl(url, renderOption) {
115
119
  return __async(this, null, function* () {
116
- return this.imageRender.url2img(url, renderOption);
120
+ var _a, _b;
121
+ (_a = renderOption.onRenderStart) == null ? void 0 : _a.call(renderOption);
122
+ try {
123
+ return this.imageRender.url2img(url, renderOption);
124
+ } catch (e) {
125
+ (_b = renderOption == null ? void 0 : renderOption.onRenderError) == null ? void 0 : _b.call(renderOption, e);
126
+ }
117
127
  });
118
128
  }
119
129
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/service/render/index.ts"],"sourcesContent":["import {IRenderService, RenderOption} from './interfaces'\nimport { getHtml } from '@/components'\nimport { PuppeteerError, TimeoutError } from 'puppeteer-core'\nimport { Platform } from '@/interface'\nimport {getBLPlayerComp, getBLRankScoreComp, getBSMapComp, getSSPlayerComp} from '@/components/pages'\nimport {preferenceKey} from \"@/service/preference\";\nimport {ImageRenderError, RequestError} from \"@/infra/errors\";\nimport createQrcode from \"@/components/utils/qrcode\";\nimport {APIService} from \"@/service/api\";\nimport {BSMap} from \"@/service/api/interfaces/beatsaver\";\nimport {ImageRender} from \"@/infra/support/render\";\n\n\nconst getPreferenceKey = (platform: string) => {\n return platform == Platform.SS\n ? preferenceKey.ssProfileRenderImg.key\n : preferenceKey.blProfileRenderImg.key\n}\n\nexport class RenderService implements IRenderService {\n constructor(\n private api: APIService,\n private imageRender: ImageRender\n ) {}\n async renderRank(\n accountId: string,\n platform: Platform,\n renderOpts?: RenderOption\n ) {\n try {\n let bg = (await renderOpts?.userPreference?.get<string>(getPreferenceKey(platform)))\n bg = bg || 'https://www.loliapi.com/acg/pc/'\n let html: string\n if (platform == Platform.BL) {\n const { scores, userInfo } = await this.api.getBLPlayerScoresWithUserInfo(accountId)\n html = getHtml(getBLPlayerComp(scores, userInfo, bg))\n } else {\n const { scores, userInfo } = await this.api.getSSPlayerRecentScoreWithUserInfo(accountId)\n html = getHtml(getSSPlayerComp(scores, userInfo, bg))\n }\n return this.imageRender.html2img(html, {selector: '#render-result', ...renderOpts})\n }catch (e) {\n if (e instanceof TimeoutError || e instanceof PuppeteerError) {\n throw new ImageRenderError()\n }\n throw e\n }\n }\n\n async renderScore(\n scoreId: string,\n renderOpts?: RenderOption\n ) {\n const bg = (await renderOpts?.userPreference?.get<string>(preferenceKey.blScoreImg.key))\n ?? 'https://www.loliapi.com/acg/pc/'\n try {\n const { score, statistic, bsor, bsMap } =\n await this.api.getScoreAndBSMapByScoreId(scoreId)\n\n const { aroundScores, regionTopScores, difficulties } =\n await this.api.getAroundScoreAndRegionScoreByRankAndPage(\n score.leaderboardId,\n score.rank,\n score.player.country\n )\n return this.imageRender.html2img(\n getHtml(getBLRankScoreComp(score, aroundScores, regionTopScores, difficulties, bsMap, statistic, bsor, bg)),\n {selector: '#render-result', ...renderOpts}\n )\n }catch (e) {\n if (e instanceof RequestError) {\n throw e\n }\n throw new ImageRenderError()\n }\n }\n\n async renderMapById(\n mapId: string,\n renderOption: RenderOption\n ) {\n const map = await this.api.BeatSaver.searchMapById(mapId)\n return this.renderMap(map, renderOption)\n }\n\n async renderMap(\n bsMap: BSMap,\n renderOption?: RenderOption\n ) {\n const previewQrUrl = await createQrcode(`https://allpoland.github.io/ArcViewer/?id=${bsMap.id}`)\n const bsMapQrUrl = await createQrcode(`https://beatsaver.com/maps/${bsMap.id}`)\n return this.imageRender.html2img(\n getHtml(getBSMapComp(bsMap, bsMapQrUrl, previewQrUrl)), {selector: '#render-result', ...renderOption}\n )\n }\n\n async renderUrl(url: string, renderOption?: RenderOption) {\n return this.imageRender.url2img(url, renderOption)\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,SAAS,eAAe;AACxB,SAAS,gBAAgB,oBAAoB;AAC7C,SAAS,gBAAgB;AACzB,SAAQ,iBAAiB,oBAAoB,cAAc,uBAAsB;AACjF,SAAQ,qBAAoB;AAC5B,SAAQ,kBAAkB,oBAAmB;AAC7C,OAAO,kBAAkB;AAMzB,MAAM,mBAAmB,CAAC,aAAqB;AAC7C,SAAO,YAAY,SAAS,KACxB,cAAc,mBAAmB,MACjC,cAAc,mBAAmB;AACvC;AAEO,MAAM,cAAwC;AAAA,EACnD,YACU,KACA,aACR;AAFQ;AACA;AAAA,EACP;AAAA,EACG,WACJ,WACA,UACA,YACA;AAAA;AA5BJ;AA6BI,UAAI;AACF,YAAI,KAAM,OAAM,8CAAY,mBAAZ,mBAA4B,IAAY,iBAAiB,QAAQ;AACjF,aAAK,MAAM;AACX,YAAI;AACJ,YAAI,YAAY,SAAS,IAAI;AAC3B,gBAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,KAAK,IAAI,8BAA8B,SAAS;AACnF,iBAAO,QAAQ,gBAAgB,QAAQ,UAAU,EAAE,CAAC;AAAA,QACtD,OAAO;AACL,gBAAM,EAAE,QAAQ,SAAS,IAAI,MAAM,KAAK,IAAI,mCAAmC,SAAS;AACxF,iBAAO,QAAQ,gBAAgB,QAAQ,UAAU,EAAE,CAAC;AAAA,QACtD;AACA,eAAO,KAAK,YAAY,SAAS,MAAM,iBAAC,UAAU,oBAAqB,WAAW;AAAA,MACpF,SAAQ,GAAG;AACT,YAAI,aAAa,gBAAgB,aAAa,gBAAgB;AAC5D,gBAAM,IAAI,iBAAiB;AAAA,QAC7B;AACA,cAAM;AAAA,MACR;AAAA,IACF;AAAA;AAAA,EAEM,YACJ,SACA,YACA;AAAA;AApDJ;AAqDI,YAAM,MAAM,YAAM,8CAAY,mBAAZ,mBAA4B,IAAY,cAAc,WAAW,SAAvE,YACP;AACL,UAAI;AACF,cAAM,EAAE,OAAO,WAAW,MAAM,MAAM,IACpC,MAAM,KAAK,IAAI,0BAA0B,OAAO;AAElD,cAAM,EAAE,cAAc,iBAAiB,aAAa,IAClD,MAAM,KAAK,IAAI;AAAA,UACb,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM,OAAO;AAAA,QACf;AACF,eAAO,KAAK,YAAY;AAAA,UACtB,QAAQ,mBAAmB,OAAO,cAAc,iBAAiB,cAAc,OAAO,WAAW,MAAM,EAAE,CAAC;AAAA,UAC1G,iBAAC,UAAU,oBAAqB;AAAA,QAClC;AAAA,MACF,SAAQ,GAAG;AACT,YAAI,aAAa,cAAc;AAC7B,gBAAM;AAAA,QACR;AACA,cAAM,IAAI,iBAAiB;AAAA,MAC7B;AAAA,IACF;AAAA;AAAA,EAEM,cACJ,OACA,cACA;AAAA;AACA,YAAM,MAAM,MAAM,KAAK,IAAI,UAAU,cAAc,KAAK;AACxD,aAAO,KAAK,UAAU,KAAK,YAAY;AAAA,IACzC;AAAA;AAAA,EAEM,UACJ,OACA,cACA;AAAA;AACA,YAAM,eAAe,MAAM,aAAa,6CAA6C,MAAM,EAAE,EAAE;AAC/F,YAAM,aAAa,MAAM,aAAa,8BAA8B,MAAM,EAAE,EAAE;AAC9E,aAAO,KAAK,YAAY;AAAA,QACtB,QAAQ,aAAa,OAAO,YAAY,YAAY,CAAC;AAAA,QAAG,iBAAC,UAAU,oBAAqB;AAAA,MAC1F;AAAA,IACF;AAAA;AAAA,EAEM,UAAU,KAAa,cAA6B;AAAA;AACxD,aAAO,KAAK,YAAY,QAAQ,KAAK,YAAY;AAAA,IACnD;AAAA;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/service/render/index.ts"],"sourcesContent":["import {IRenderService, RenderOption} from './interfaces'\nimport { getHtml } from '@/components'\nimport { PuppeteerError, TimeoutError } from 'puppeteer-core'\nimport { Platform } from '@/interface'\nimport {getBLPlayerComp, getBLRankScoreComp, getBSMapComp, getSSPlayerComp} from '@/components/pages'\nimport {preferenceKey} from \"../preference\";\nimport {ImageRenderError, RequestError} from \"@/infra/errors\";\nimport createQrcode from \"@/components/utils/qrcode\";\nimport {APIService} from \"../api\";\nimport {BSMap} from \"../api/interfaces/beatsaver\";\nimport {CreateImageRenderOption, getImageRender, ImageRender} from \"@/infra/support/render\";\n\n\nconst getPreferenceKey = (platform: string) => {\n return platform == Platform.SS\n ? preferenceKey.ssProfileRenderImg.key\n : preferenceKey.blProfileRenderImg.key\n}\n\nexport class RenderService implements IRenderService {\n constructor(\n private api: APIService,\n private imageRender: ImageRender\n ) {}\n\n static create(imgRenderConfig: CreateImageRenderOption, api: APIService) {\n return new RenderService(api, getImageRender(imgRenderConfig))\n }\n\n async renderRank(\n accountId: string,\n platform: Platform,\n renderOpts?: RenderOption\n ) {\n try {\n let bg = (await renderOpts?.userPreference?.get<string>(getPreferenceKey(platform)))\n bg = bg || 'https://www.loliapi.com/acg/pc/'\n let html: string\n if (platform == Platform.BL) {\n const { scores, userInfo } = await this.api.getBLPlayerScoresWithUserInfo(accountId)\n html = getHtml(getBLPlayerComp(scores, userInfo, bg))\n } else {\n const { scores, userInfo } = await this.api.getSSPlayerRecentScoreWithUserInfo(accountId)\n html = getHtml(getSSPlayerComp(scores, userInfo, bg))\n }\n return this.imageRender.html2img(html, {selector: '#render-result', ...renderOpts})\n }catch (e) {\n if (e instanceof TimeoutError || e instanceof PuppeteerError) {\n throw new ImageRenderError()\n }\n throw e\n }\n }\n\n async renderScore(\n scoreId: string,\n renderOpts?: RenderOption\n ) {\n const bg = (await renderOpts?.userPreference?.get<string>(preferenceKey.blScoreImg.key))\n ?? 'https://www.loliapi.com/acg/pc/'\n try {\n const { score, statistic, bsor, bsMap } =\n await this.api.getScoreAndBSMapByScoreId(scoreId)\n\n const { aroundScores, regionTopScores, difficulties } =\n await this.api.getAroundScoreAndRegionScoreByRankAndPage(\n score.leaderboardId,\n score.rank,\n score.player.country\n )\n return this.imageRender.html2img(\n getHtml(getBLRankScoreComp(score, aroundScores, regionTopScores, difficulties, bsMap, statistic, bsor, bg)),\n {selector: '#render-result', ...renderOpts}\n )\n }catch (e) {\n if (e instanceof RequestError) {\n throw e\n }\n throw new ImageRenderError()\n }\n }\n\n async renderMapById(\n mapId: string,\n renderOption: RenderOption\n ) {\n const map = await this.api.BeatSaver.searchMapById(mapId)\n return this.renderMap(map, renderOption)\n }\n\n async renderMap(\n bsMap: BSMap,\n renderOption?: RenderOption\n ) {\n const previewQrUrl = await createQrcode(`https://allpoland.github.io/ArcViewer/?id=${bsMap.id}`)\n const bsMapQrUrl = await createQrcode(`https://beatsaver.com/maps/${bsMap.id}`)\n return this.imageRender.html2img(\n getHtml(getBSMapComp(bsMap, bsMapQrUrl, previewQrUrl)), {selector: '#render-result', ...renderOption}\n )\n }\n\n async renderUrl(url: string, renderOption?: RenderOption) {\n renderOption.onRenderStart?.()\n try {\n return this.imageRender.url2img(url, renderOption)\n }catch (e) {\n renderOption?.onRenderError?.(e)\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ws/beatleader.ts"],"sourcesContent":["import { WSHandler } from '@/ws/handler'\nimport { Logger } from '@/interface/logger'\nimport { Config } from '@/config'\nimport { DB } from '@/interface/db'\nimport { BotService, Session } from '@/interface'\nimport {RenderService} from \"@/service/render\";\nimport {BeatLeaderWSEvent} from \"@/service/api/interfaces/beatleader\";\n\nexport class BeatleaderWSHandler<T> implements WSHandler {\n private readonly logger: Logger\n private render: RenderService\n private botService: BotService<T, Session<T>>\n wsUrl: string = 'wss://sockets.api.beatleader.xyz/scores'\n private db: DB<T>\n config: Config\n constructor(\n db: DB<T>,\n render: RenderService,\n logger: Logger,\n config: Config,\n botService: BotService<T, Session<T>>\n ) {\n this.logger = logger\n this.render = render\n this.botService = botService\n this.config = config\n this.db = db\n }\n\n onOpen() {\n this.logger.info('BeatleaderWS opened')\n }\n\n onClose() {\n this.logger.info('BeatleaderWS closed')\n }\n\n async onEvent(event: any) {\n const data = JSON.parse(event.toString()) as BeatLeaderWSEvent\n const playerId = data.player.id\n // const ok = BeatLeaderFilter(data, ...this.config.BLScoreFilters)\n // if (!ok) {\n // return\n // }\n // logger.info('Received beatleader message',data.id, data.player.id);\n // cache all playerId\n const subscriptions = await this.db.getAllSubscriptionByUIDAndPlatform(playerId, 'beatleader')\n // .filter(item=> {\n // const channelFilters = item.sub.data as BLScoreFilter[]\n // const memberFilters = item.member.subscribeData\n // return BeatLeaderFilter(data, ...channelFilters, ...memberFilters)\n // })\n const restSub = subscriptions.filter((it) =>\n it.subscribe.type == 'beatleader-score' && it.subscribe.enable == true\n )\n // cacheService\n if (restSub.length === 0) return\n const img = await this.render.renderScore(data.id.toString())\n for (const item of restSub) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `恭喜 <at id=\"${item.account.uid}\"/> 刚刚在谱面「${data.leaderboard.song.name}」中打出了 ${(data.accuracy * 100).toFixed(2)}% 的好成绩`\n )\n await session.sendImgBuffer(img)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,oBAA4C;AAAA,EAOvD,YACE,IACA,QACA,QACA,QACA,YACA;AAZF,wBAAiB;AACjB,wBAAQ;AACR,wBAAQ;AACR,iCAAgB;AAChB,wBAAQ;AACR;AAQE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS;AACP,SAAK,OAAO,KAAK,qBAAqB;AAAA,EACxC;AAAA,EAEA,UAAU;AACR,SAAK,OAAO,KAAK,qBAAqB;AAAA,EACxC;AAAA,EAEM,QAAQ,OAAY;AAAA;AACxB,YAAM,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AACxC,YAAM,WAAW,KAAK,OAAO;AAO7B,YAAM,gBAAgB,MAAM,KAAK,GAAG,mCAAmC,UAAU,YAAY;AAM7F,YAAM,UAAU,cAAc;AAAA,QAAO,CAAC,OACpC,GAAG,UAAU,QAAQ,sBAAsB,GAAG,UAAU,UAAU;AAAA,MACpE;AAEA,UAAI,QAAQ,WAAW,EAAG;AAC1B,YAAM,MAAM,MAAM,KAAK,OAAO,YAAY,KAAK,GAAG,SAAS,CAAC;AAC5D,iBAAW,QAAQ,SAAS;AAC1B,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,wBAAc,KAAK,QAAQ,GAAG,2CAAa,KAAK,YAAY,KAAK,IAAI,mCAAU,KAAK,WAAW,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChH;AACA,cAAM,QAAQ,cAAc,GAAG;AAAA,MACjC;AAAA,IACF;AAAA;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/ws/beatleader.ts"],"sourcesContent":["import { WSHandler } from '@/ws/handler'\nimport { Logger } from '@/interface/logger'\nimport { Config } from '@/config'\nimport { DB } from '@/interface/db'\nimport { BotService, Session } from '@/interface'\nimport {RenderService} from \"@/service\";\nimport {BeatLeaderWSEvent} from \"@/service/api/interfaces/beatleader\";\n\nexport class BeatleaderWSHandler<T> implements WSHandler {\n private readonly logger: Logger\n private render: RenderService\n private botService: BotService<T, Session<T>>\n wsUrl: string = 'wss://sockets.api.beatleader.xyz/scores'\n private db: DB<T>\n config: Config\n constructor(\n db: DB<T>,\n render: RenderService,\n logger: Logger,\n config: Config,\n botService: BotService<T, Session<T>>\n ) {\n this.logger = logger\n this.render = render\n this.botService = botService\n this.config = config\n this.db = db\n }\n\n onOpen() {\n this.logger.info('BeatleaderWS opened')\n }\n\n onClose() {\n this.logger.info('BeatleaderWS closed')\n }\n\n async onEvent(event: any) {\n const data = JSON.parse(event.toString()) as BeatLeaderWSEvent\n const playerId = data.player.id\n // const ok = BeatLeaderFilter(data, ...this.config.BLScoreFilters)\n // if (!ok) {\n // return\n // }\n // logger.info('Received beatleader message',data.id, data.player.id);\n // cache all playerId\n const subscriptions = await this.db.getAllSubscriptionByUIDAndPlatform(playerId, 'beatleader')\n // .filter(item=> {\n // const channelFilters = item.sub.data as BLScoreFilter[]\n // const memberFilters = item.member.subscribeData\n // return BeatLeaderFilter(data, ...channelFilters, ...memberFilters)\n // })\n const restSub = subscriptions.filter((it) =>\n it.subscribe.type == 'beatleader-score' && it.subscribe.enable == true\n )\n // cacheService\n if (restSub.length === 0) return\n const img = await this.render.renderScore(data.id.toString())\n for (const item of restSub) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `恭喜 <at id=\"${item.account.uid}\"/> 刚刚在谱面「${data.leaderboard.song.name}」中打出了 ${(data.accuracy * 100).toFixed(2)}% 的好成绩`\n )\n await session.sendImgBuffer(img)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAQO,MAAM,oBAA4C;AAAA,EAOvD,YACE,IACA,QACA,QACA,QACA,YACA;AAZF,wBAAiB;AACjB,wBAAQ;AACR,wBAAQ;AACR,iCAAgB;AAChB,wBAAQ;AACR;AAQE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS;AACP,SAAK,OAAO,KAAK,qBAAqB;AAAA,EACxC;AAAA,EAEA,UAAU;AACR,SAAK,OAAO,KAAK,qBAAqB;AAAA,EACxC;AAAA,EAEM,QAAQ,OAAY;AAAA;AACxB,YAAM,OAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AACxC,YAAM,WAAW,KAAK,OAAO;AAO7B,YAAM,gBAAgB,MAAM,KAAK,GAAG,mCAAmC,UAAU,YAAY;AAM7F,YAAM,UAAU,cAAc;AAAA,QAAO,CAAC,OACpC,GAAG,UAAU,QAAQ,sBAAsB,GAAG,UAAU,UAAU;AAAA,MACpE;AAEA,UAAI,QAAQ,WAAW,EAAG;AAC1B,YAAM,MAAM,MAAM,KAAK,OAAO,YAAY,KAAK,GAAG,SAAS,CAAC;AAC5D,iBAAW,QAAQ,SAAS;AAC1B,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,wBAAc,KAAK,QAAQ,GAAG,2CAAa,KAAK,YAAY,KAAK,IAAI,mCAAU,KAAK,WAAW,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChH;AACA,cAAM,QAAQ,cAAc,GAAG;AAAA,MACjC;AAAA,IACF;AAAA;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ws/beatsaver.ts"],"sourcesContent":["import { WSHandler } from '@/ws/handler'\nimport { Logger } from '@/interface/logger'\nimport { Config } from '@/config'\nimport { DB } from '@/interface/db'\nimport { BotService, Session } from '@/interface'\nimport { handleWSEventWithCache } from '@/utils'\nimport {BeatSaverWSEvent, BSMap} from \"@/service/api/interfaces/beatsaver\";\nimport {RenderService} from \"@/service/render\";\n\nexport class BeatSaverWSHandler<T> implements WSHandler {\n private readonly logger: Logger\n private render: RenderService\n private botService: BotService<T, Session<T>>\n wsUrl: string = 'wss://ws.beatsaver.com/maps'\n private db: DB<T>\n config: Config\n constructor(\n db: DB<T>,\n render: RenderService,\n logger: Logger,\n config: Config,\n botService: BotService<T, Session<T>>\n ) {\n this.logger = logger\n this.render = render\n this.botService = botService\n this.config = config\n this.db = db\n }\n\n onOpen() {\n this.logger.info('BeatsaverWS opened')\n }\n\n onClose() {\n this.logger.info('BeatsaverWS closed')\n }\n\n eventParser(event) {\n return JSON.parse(event.toString()) as BeatSaverWSEvent\n }\n\n eventFilter = (data: BeatSaverWSEvent) => {\n return (\n data.type === 'MAP_UPDATE' &&\n data.msg.versions.some((it) => it.state == 'Published') &&\n data.msg.declaredAi === 'None'\n )\n }\n eventIdSelector = (data: BeatSaverWSEvent) =>\n `ws.bs.${data.type === 'MAP_DELETE' ? data.msg : data.msg.id}.${data.type}`\n\n async BSWSHandler(data: BeatSaverWSEvent) {\n // this.logger.info('Beatsaver message received', data.type, data?.msg?.id)\n\n const bsmap = data.msg as BSMap\n const userId = bsmap.uploader.id\n const subscriptions = await this.db.getAllSubscriptionByUIDAndPlatform(\n userId,\n 'beatsaver'\n )\n\n const restSub = subscriptions.filter(\n (it) =>\n it.subscribe.type == 'beatsaver-map' && it.subscribe.enable == true\n )\n const gids = restSub.map((it) => it.groupChannel.id)\n const groupSubs = await this.db.getIDSubscriptionByType('id-beatsaver-map')\n const restGroupSubs = groupSubs.filter(\n (it) =>\n !gids.includes(it.groupChannel.id) &&\n it.subscribe.data?.mapperId?.toString() === userId.toString()\n )\n\n // cacheService\n if (restSub.length === 0 && restGroupSubs) return\n const image = this.render.renderMap(bsmap)\n for (const item of restSub) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `本群谱师 「<at id=\"${item.account.uid}\"/> (${bsmap.uploader.name})」刚刚发布了新谱面,「${bsmap.name}」`\n )\n // text + mention element\n await session.sendImgBuffer(await image)\n await session.sendAudioByUrl(bsmap.versions[0].previewURL)\n }\n for (const item of restGroupSubs) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `谱师「${bsmap.uploader.name}」刚刚发布了新谱面,「${bsmap.name}」`\n )\n // text + mention element\n await session.sendImgBuffer(await image)\n await session.sendAudioByUrl(bsmap.versions[0].previewURL)\n }\n }\n\n onEvent = handleWSEventWithCache(\n this,\n this.BSWSHandler,\n 1000 * 60 * 15,\n this.eventParser,\n this.eventFilter,\n this.eventIdSelector\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,8BAA8B;AAIhC,MAAM,mBAA2C;AAAA,EAOtD,YACE,IACA,QACA,QACA,QACA,YACA;AAZF,wBAAiB;AACjB,wBAAQ;AACR,wBAAQ;AACR,iCAAgB;AAChB,wBAAQ;AACR;AA2BA,uCAAc,CAAC,SAA2B;AACxC,aACE,KAAK,SAAS,gBACd,KAAK,IAAI,SAAS,KAAK,CAAC,OAAO,GAAG,SAAS,WAAW,KACtD,KAAK,IAAI,eAAe;AAAA,IAE5B;AACA,2CAAkB,CAAC,SACjB,SAAS,KAAK,SAAS,eAAe,KAAK,MAAM,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI;AAqD3E,mCAAU;AAAA,MACR;AAAA,MACA,KAAK;AAAA,MACL,MAAO,KAAK;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAvFE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS;AACP,SAAK,OAAO,KAAK,oBAAoB;AAAA,EACvC;AAAA,EAEA,UAAU;AACR,SAAK,OAAO,KAAK,oBAAoB;AAAA,EACvC;AAAA,EAEA,YAAY,OAAO;AACjB,WAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AAAA,EACpC;AAAA,EAYM,YAAY,MAAwB;AAAA;AAGxC,YAAM,QAAQ,KAAK;AACnB,YAAM,SAAS,MAAM,SAAS;AAC9B,YAAM,gBAAgB,MAAM,KAAK,GAAG;AAAA,QAClC;AAAA,QACA;AAAA,MACF;AAEA,YAAM,UAAU,cAAc;AAAA,QAC5B,CAAC,OACC,GAAG,UAAU,QAAQ,mBAAmB,GAAG,UAAU,UAAU;AAAA,MACnE;AACA,YAAM,OAAO,QAAQ,IAAI,CAAC,OAAO,GAAG,aAAa,EAAE;AACnD,YAAM,YAAY,MAAM,KAAK,GAAG,wBAAwB,kBAAkB;AAC1E,YAAM,gBAAgB,UAAU;AAAA,QAC9B,CAAC,OAAI;AArEX;AAsEQ,kBAAC,KAAK,SAAS,GAAG,aAAa,EAAE,OACjC,cAAG,UAAU,SAAb,mBAAmB,aAAnB,mBAA6B,gBAAe,OAAO,SAAS;AAAA;AAAA,MAChE;AAGA,UAAI,QAAQ,WAAW,KAAK,cAAe;AAC3C,YAAM,QAAQ,KAAK,OAAO,UAAU,KAAK;AACzC,iBAAW,QAAQ,SAAS;AAC1B,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,0CAAiB,KAAK,QAAQ,GAAG,QAAQ,MAAM,SAAS,IAAI,sEAAe,MAAM,IAAI;AAAA,QACvF;AAEA,cAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,cAAM,QAAQ,eAAe,MAAM,SAAS,CAAC,EAAE,UAAU;AAAA,MAC3D;AACA,iBAAW,QAAQ,eAAe;AAChC,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,qBAAM,MAAM,SAAS,IAAI,qEAAc,MAAM,IAAI;AAAA,QACnD;AAEA,cAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,cAAM,QAAQ,eAAe,MAAM,SAAS,CAAC,EAAE,UAAU;AAAA,MAC3D;AAAA,IACF;AAAA;AAUF;","names":[]}
1
+ {"version":3,"sources":["../../../src/ws/beatsaver.ts"],"sourcesContent":["import { WSHandler } from '@/ws/handler'\nimport { Logger } from '@/interface/logger'\nimport { Config } from '@/config'\nimport { DB } from '@/interface/db'\nimport { BotService, Session } from '@/interface'\nimport { handleWSEventWithCache } from '@/utils'\nimport {BeatSaverWSEvent, BSMap} from \"@/service/api/interfaces/beatsaver\";\nimport {RenderService} from \"@/service\";\n\nexport class BeatSaverWSHandler<T> implements WSHandler {\n private readonly logger: Logger\n private render: RenderService\n private botService: BotService<T, Session<T>>\n wsUrl: string = 'wss://ws.beatsaver.com/maps'\n private db: DB<T>\n config: Config\n constructor(\n db: DB<T>,\n render: RenderService,\n logger: Logger,\n config: Config,\n botService: BotService<T, Session<T>>\n ) {\n this.logger = logger\n this.render = render\n this.botService = botService\n this.config = config\n this.db = db\n }\n\n onOpen() {\n this.logger.info('BeatsaverWS opened')\n }\n\n onClose() {\n this.logger.info('BeatsaverWS closed')\n }\n\n eventParser(event) {\n return JSON.parse(event.toString()) as BeatSaverWSEvent\n }\n\n eventFilter = (data: BeatSaverWSEvent) => {\n return (\n data.type === 'MAP_UPDATE' &&\n data.msg.versions.some((it) => it.state == 'Published') &&\n data.msg.declaredAi === 'None'\n )\n }\n eventIdSelector = (data: BeatSaverWSEvent) =>\n `ws.bs.${data.type === 'MAP_DELETE' ? data.msg : data.msg.id}.${data.type}`\n\n async BSWSHandler(data: BeatSaverWSEvent) {\n // this.logger.info('Beatsaver message received', data.type, data?.msg?.id)\n\n const bsmap = data.msg as BSMap\n const userId = bsmap.uploader.id\n const subscriptions = await this.db.getAllSubscriptionByUIDAndPlatform(\n userId,\n 'beatsaver'\n )\n\n const restSub = subscriptions.filter(\n (it) =>\n it.subscribe.type == 'beatsaver-map' && it.subscribe.enable == true\n )\n const gids = restSub.map((it) => it.groupChannel.id)\n const groupSubs = await this.db.getIDSubscriptionByType('id-beatsaver-map')\n const restGroupSubs = groupSubs.filter(\n (it) =>\n !gids.includes(it.groupChannel.id) &&\n it.subscribe.data?.mapperId?.toString() === userId.toString()\n )\n\n // cacheService\n if (restSub.length === 0 && restGroupSubs) return\n const image = this.render.renderMap(bsmap)\n for (const item of restSub) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `本群谱师 「<at id=\"${item.account.uid}\"/> (${bsmap.uploader.name})」刚刚发布了新谱面,「${bsmap.name}」`\n )\n // text + mention element\n await session.sendImgBuffer(await image)\n await session.sendAudioByUrl(bsmap.versions[0].previewURL)\n }\n for (const item of restGroupSubs) {\n const session = this.botService.getSessionByChannelInfo(item.groupChannel)\n if (!session) {\n continue\n }\n await session.send(\n `谱师「${bsmap.uploader.name}」刚刚发布了新谱面,「${bsmap.name}」`\n )\n // text + mention element\n await session.sendImgBuffer(await image)\n await session.sendAudioByUrl(bsmap.versions[0].previewURL)\n }\n }\n\n onEvent = handleWSEventWithCache(\n this,\n this.BSWSHandler,\n 1000 * 60 * 15,\n this.eventParser,\n this.eventFilter,\n this.eventIdSelector\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAKA,SAAS,8BAA8B;AAIhC,MAAM,mBAA2C;AAAA,EAOtD,YACE,IACA,QACA,QACA,QACA,YACA;AAZF,wBAAiB;AACjB,wBAAQ;AACR,wBAAQ;AACR,iCAAgB;AAChB,wBAAQ;AACR;AA2BA,uCAAc,CAAC,SAA2B;AACxC,aACE,KAAK,SAAS,gBACd,KAAK,IAAI,SAAS,KAAK,CAAC,OAAO,GAAG,SAAS,WAAW,KACtD,KAAK,IAAI,eAAe;AAAA,IAE5B;AACA,2CAAkB,CAAC,SACjB,SAAS,KAAK,SAAS,eAAe,KAAK,MAAM,KAAK,IAAI,EAAE,IAAI,KAAK,IAAI;AAqD3E,mCAAU;AAAA,MACR;AAAA,MACA,KAAK;AAAA,MACL,MAAO,KAAK;AAAA,MACZ,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AAvFE,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,aAAa;AAClB,SAAK,SAAS;AACd,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS;AACP,SAAK,OAAO,KAAK,oBAAoB;AAAA,EACvC;AAAA,EAEA,UAAU;AACR,SAAK,OAAO,KAAK,oBAAoB;AAAA,EACvC;AAAA,EAEA,YAAY,OAAO;AACjB,WAAO,KAAK,MAAM,MAAM,SAAS,CAAC;AAAA,EACpC;AAAA,EAYM,YAAY,MAAwB;AAAA;AAGxC,YAAM,QAAQ,KAAK;AACnB,YAAM,SAAS,MAAM,SAAS;AAC9B,YAAM,gBAAgB,MAAM,KAAK,GAAG;AAAA,QAClC;AAAA,QACA;AAAA,MACF;AAEA,YAAM,UAAU,cAAc;AAAA,QAC5B,CAAC,OACC,GAAG,UAAU,QAAQ,mBAAmB,GAAG,UAAU,UAAU;AAAA,MACnE;AACA,YAAM,OAAO,QAAQ,IAAI,CAAC,OAAO,GAAG,aAAa,EAAE;AACnD,YAAM,YAAY,MAAM,KAAK,GAAG,wBAAwB,kBAAkB;AAC1E,YAAM,gBAAgB,UAAU;AAAA,QAC9B,CAAC,OAAI;AArEX;AAsEQ,kBAAC,KAAK,SAAS,GAAG,aAAa,EAAE,OACjC,cAAG,UAAU,SAAb,mBAAmB,aAAnB,mBAA6B,gBAAe,OAAO,SAAS;AAAA;AAAA,MAChE;AAGA,UAAI,QAAQ,WAAW,KAAK,cAAe;AAC3C,YAAM,QAAQ,KAAK,OAAO,UAAU,KAAK;AACzC,iBAAW,QAAQ,SAAS;AAC1B,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,0CAAiB,KAAK,QAAQ,GAAG,QAAQ,MAAM,SAAS,IAAI,sEAAe,MAAM,IAAI;AAAA,QACvF;AAEA,cAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,cAAM,QAAQ,eAAe,MAAM,SAAS,CAAC,EAAE,UAAU;AAAA,MAC3D;AACA,iBAAW,QAAQ,eAAe;AAChC,cAAM,UAAU,KAAK,WAAW,wBAAwB,KAAK,YAAY;AACzE,YAAI,CAAC,SAAS;AACZ;AAAA,QACF;AACA,cAAM,QAAQ;AAAA,UACZ,qBAAM,MAAM,SAAS,IAAI,qEAAc,MAAM,IAAI;AAAA,QACnD;AAEA,cAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,cAAM,QAAQ,eAAe,MAAM,SAAS,CAAC,EAAE,UAAU;AAAA,MAC3D;AAAA,IACF;AAAA;AAUF;","names":[]}
@@ -1,5 +1,4 @@
1
1
  export * from "./beatleader";
2
- export * from "./scoresaber";
3
2
  export * from "./beatsaver";
4
3
  export * from "./handler";
5
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ws/index.ts"],"sourcesContent":["export * from './beatleader'\nexport * from './scoresaber'\nexport * from './beatsaver'\nexport * from './handler'\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
1
+ {"version":3,"sources":["../../../src/ws/index.ts"],"sourcesContent":["export * from './beatleader'\nexport * from './beatsaver'\nexport * from './handler'\n"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}