diff --git a/.gitignore b/.gitignore index fa10f37..aa661c8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ build/ .DS_Store .env + +input.xml +output.json diff --git a/package-lock.json b/package-lock.json index 071a612..b4e91cc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "dedent-js": "^1.0.1", "dotenv": "^16.4.5", "fast-xml-parser": "^4.3.2", + "highwayhash": "^3.1.1", "koa": "^2.15.0", "koa-bodyparser": "^4.4.1", "lodash": "^4.17.21", @@ -2522,7 +2523,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -2555,6 +2555,11 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmmirror.com/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, "node_modules/arc4": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/arc4/-/arc4-2.1.4.tgz", @@ -2563,6 +2568,15 @@ "node": ">=0.10" } }, + "node_modules/are-we-there-yet": { + "version": "1.1.7", + "resolved": "https://registry.npmmirror.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz", + "integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmmirror.com/arg/-/arg-4.1.3.tgz", @@ -2729,6 +2743,34 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2812,6 +2854,15 @@ "node": ">=16.20.1" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2924,6 +2975,11 @@ "is-regex": "^1.0.3" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmmirror.com/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/ci-info": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", @@ -2979,6 +3035,14 @@ "type-is": "^1.6.16" } }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", @@ -3009,6 +3073,11 @@ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/constantinople": { "version": "4.0.1", "resolved": "https://registry.npmmirror.com/constantinople/-/constantinople-4.0.1.tgz", @@ -3069,6 +3138,11 @@ "cosmokit": "^1.5.2" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, "node_modules/cosmokit": { "version": "1.5.2", "resolved": "https://registry.npmmirror.com/cosmokit/-/cosmokit-1.5.2.tgz", @@ -3133,6 +3207,17 @@ } } }, + "node_modules/decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/dedent": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", @@ -3157,6 +3242,14 @@ "resolved": "https://registry.npmmirror.com/deep-equal/-/deep-equal-1.0.1.tgz", "integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==" }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -3207,6 +3300,17 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3305,8 +3409,7 @@ "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/encodeurl": { "version": "1.0.2", @@ -3316,6 +3419,14 @@ "node": ">= 0.8" } }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3754,6 +3865,14 @@ "node": ">= 0.8.0" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmmirror.com/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, "node_modules/expect": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", @@ -3956,6 +4075,11 @@ "node": ">= 0.6" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -3984,6 +4108,64 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmmirror.com/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha512-14x4kjc6lkD3ltw589k0NrPD6cCNTD6CWoVUNpB85+DrtONoZn+Rug6xZU5RvSC4+TZPxA5AnBibQYAvZn41Hg==", + "dependencies": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha512-1pqUqRjkhPJ9miNq9SwMfdvi6lBJcd6eFxvfaivQhaH3SgisfiuudvFntdKOmxuee/77l+FPjKrQjWvmPjWrRw==", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha512-0XsVpQLnVCXHJfyEs8tC0zpTVIr5PKKsQtkT29IwupnPTjtPmQ3xT/4yCREF9hYkV/3M3kzcUTSAZT6a6h81tw==", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -4047,6 +4229,11 @@ "resolve-pkg-maps": "^1.0.0" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmmirror.com/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -4177,6 +4364,11 @@ "node": ">= 0.4" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", @@ -4188,6 +4380,19 @@ "node": ">= 0.4" } }, + "node_modules/highwayhash": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/highwayhash/-/highwayhash-3.1.1.tgz", + "integrity": "sha512-FjsF/X47Q9+y7TJ+xjZxcNaOGhrGJTg5AFedEpNYate5GB5ezXeG3tqMjsuZ99R2If9xDdQQRCrka6hRC7J82g==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^3.1.0", + "prebuild-install": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -4249,6 +4454,11 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, "node_modules/ignore": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", @@ -4325,6 +4535,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4375,7 +4590,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -4459,6 +4673,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -5452,6 +5671,14 @@ "node": ">=6" } }, + "node_modules/mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "engines": { + "node": ">=8" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -5464,6 +5691,11 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" + }, "node_modules/minipass": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", @@ -5473,6 +5705,11 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmmirror.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, "node_modules/mongodb": { "version": "6.4.0", "resolved": "https://registry.npmmirror.com/mongodb/-/mongodb-6.4.0.tgz", @@ -5532,6 +5769,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/napi-build-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz", + "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5546,6 +5788,27 @@ "node": ">= 0.6" } }, + "node_modules/node-abi": { + "version": "2.30.1", + "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-2.30.1.tgz", + "integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==", + "dependencies": { + "semver": "^5.4.1" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-addon-api": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-3.2.1.tgz", + "integrity": "sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==" + }, "node_modules/node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -5579,6 +5842,25 @@ "node": ">=8" } }, + "node_modules/npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmmirror.com/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "dependencies": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmmirror.com/object-assign/-/object-assign-4.1.1.tgz", @@ -5607,7 +5889,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "dependencies": { "wrappy": "1" } @@ -5888,6 +6169,32 @@ "node": ">=8" } }, + "node_modules/prebuild-install": { + "version": "6.1.4", + "resolved": "https://registry.npmmirror.com/prebuild-install/-/prebuild-install-6.1.4.tgz", + "integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==", + "dependencies": { + "detect-libc": "^1.0.3", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^2.21.0", + "npmlog": "^4.0.1", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^3.0.3", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5938,6 +6245,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/promise": { "version": "7.3.1", "resolved": "https://registry.npmmirror.com/promise/-/promise-7.3.1.tgz", @@ -6071,6 +6383,15 @@ "resolved": "https://registry.npmmirror.com/pug-walk/-/pug-walk-2.0.0.tgz", "integrity": "sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==" }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6163,12 +6484,53 @@ "node": ">= 0.8" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/reflect-metadata": { "version": "0.2.1", "resolved": "https://registry.npmmirror.com/reflect-metadata/-/reflect-metadata-0.2.1.tgz", @@ -6405,6 +6767,11 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.2.2", "resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz", @@ -6464,8 +6831,22 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmmirror.com/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==" + }, + "node_modules/simple-get": { + "version": "3.1.1", + "resolved": "https://registry.npmmirror.com/simple-get/-/simple-get-3.1.1.tgz", + "integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==", + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } }, "node_modules/sisteransi": { "version": "1.0.5", @@ -6544,6 +6925,19 @@ "node": ">= 0.6" } }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -6561,7 +6955,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6590,7 +6983,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6669,6 +7061,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar-fs": { + "version": "2.1.1", + "resolved": "https://registry.npmmirror.com/tar-fs/-/tar-fs-2.1.1.tgz", + "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmmirror.com/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/test-exclude": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", @@ -6908,6 +7339,17 @@ "resolved": "https://registry.npmmirror.com/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmmirror.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7019,6 +7461,11 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -7101,6 +7548,14 @@ "node": ">= 8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmmirror.com/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/with": { "version": "7.0.2", "resolved": "https://registry.npmmirror.com/with/-/with-7.0.2.tgz", @@ -7153,8 +7608,7 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" }, "node_modules/write-file-atomic": { "version": "4.0.2", diff --git a/package.json b/package.json index f230b2e..023e99d 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,8 @@ "lint:fix": "eslint . --ext .ts --ext .mts --fix", "test": "jest --coverage", "prettier": "prettier --config .prettierrc --write .", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "xmltojson": "tsx src/tool/xml-to-json.ts" }, "author": "GEEKiDoS", "license": "MIT", @@ -53,6 +54,7 @@ "dedent-js": "^1.0.1", "dotenv": "^16.4.5", "fast-xml-parser": "^4.3.2", + "highwayhash": "^3.1.1", "koa": "^2.15.0", "koa-bodyparser": "^4.4.1", "lodash": "^4.17.21", diff --git a/src/apis/p2d/index.ts b/src/apis/p2d/index.ts index 594af28..12aaca4 100644 --- a/src/apis/p2d/index.ts +++ b/src/apis/p2d/index.ts @@ -2,8 +2,8 @@ import { Logger } from "@cordisjs/logger"; import Router from "@koa/router"; import { Context } from "../index.js"; import { UserService } from "../../services/p2d/user.js"; -import { PlayerCustomizeSetting, PlayerRivalData } from "../../types/index.js"; -import { RivalPatch, RivalPostOrDelete } from "../../types/api.js"; +import { PlayerCustomizeSetting, PlayerRivalData } from "../../types/p2d/index.js"; +import { RivalPatch, RivalPostOrDelete } from "../../types/p2d/api.js"; const logger = new Logger('p2d-api'); const router = new Router({ diff --git a/src/controllers/p2d/music.ts b/src/controllers/p2d/music.ts index b7376fc..74a0089 100644 --- a/src/controllers/p2d/music.ts +++ b/src/controllers/p2d/music.ts @@ -1,4 +1,4 @@ -import { PlayerPlayLog } from "../../types/index.js"; +import { PlayerPlayLog } from "../../types/p2d/index.js"; import { p2d } from "../../decorators/eacnet.js"; import { UserService } from "../../services/p2d/user.js"; import { Context } from "../../types.js"; @@ -62,7 +62,7 @@ export class Music { ghost_data: v.bin(Buffer.from(playlog.ghost.buffer)), dj_name: v.str(djname), best_option: { - valid: v.bool(1), + valid: v.bool(true), arrange_0: v.s32(playlog.arrange_0), arrange_1: v.s32(playlog.arrange_1), assist: v.s32(playlog.assist), diff --git a/src/controllers/p2d/user.ts b/src/controllers/p2d/user.ts index 7db4f75..07f9803 100644 --- a/src/controllers/p2d/user.ts +++ b/src/controllers/p2d/user.ts @@ -1,7 +1,7 @@ import { p2d } from "../../decorators/eacnet.js"; import { Context } from "../../types.js"; import { v } from "../../utils/kxml-value.js"; -import { fromToken } from "../../utils/laochan-id.js"; +import { tokenToInfinitasId } from "../../utils/laochan-id.js"; import { UserService } from "../../services/p2d/user.js"; import { sha256 } from "../../utils/sha256.js"; import { toKBinXml } from "../../utils/kbinxml.js"; @@ -212,7 +212,7 @@ export class User { const { check_sum } = ctx.body as { check_sum: string }; const checksum = await this.userService.getPDataChecksum(ctx.token); - const id = fromToken(ctx.token); + const id = tokenToInfinitasId(ctx.token); if (!checksum) { return { diff --git a/src/controllers/sdvx/ac-relay.ts b/src/controllers/sdvx/ac-relay.ts index 7bb5330..f918ed1 100644 --- a/src/controllers/sdvx/ac-relay.ts +++ b/src/controllers/sdvx/ac-relay.ts @@ -1,11 +1,11 @@ import { sdvx } from "../../decorators/eacnet.js"; import { Context } from "../../types.js"; -import { v } from "../../utils/kxml-value.js"; +import { Serializable, v } from "../../utils/kxml-value.js"; import * as data from '../../datas/sdvx.js'; export class AcRelay { @sdvx() - async sv6_music_url(ctx: Context) { + async sv6_music_url(ctx: Context): Promise { let { music_id } = ctx.body as { music_id: number | number[] }; if (typeof music_id === 'number') { music_id = [music_id]; diff --git a/src/controllers/sdvx/index.ts b/src/controllers/sdvx/index.ts index 2d4a44d..08465dd 100644 --- a/src/controllers/sdvx/index.ts +++ b/src/controllers/sdvx/index.ts @@ -1,61 +1,24 @@ import { sdvx } from "../../decorators/eacnet.js"; import { Combine } from "../../utils/combine.js"; import config from "../../utils/config.js"; -import { v } from "../../utils/kxml-value.js"; +import { Serializable, v } from "../../utils/kxml-value.js"; import { AcRelay } from "./ac-relay.js"; +import { UserService } from "../../services/sdvx/user.js"; +import { inject, singleton } from "tsyringe"; +import { User } from "./user.js"; -export default class extends Combine(AcRelay) { - @sdvx() - async getItemList() { - return { - status: v.s32(0), - error_code: v.s32(0), - response: { - item_num: v.s32(0), - } - }; +@singleton() +export default class extends Combine(AcRelay, User) { + constructor( + @inject(UserService) private readonly userService: UserService, + ) { + super(); + + this.userService; } @sdvx() - async getGoodsList() { - return { - status: v.s32(0), - error_code: v.s32(0), - response: { - goods_num: v.s32(0), - } - }; - } - - @sdvx() - async getUserIDs() { - return { - status: v.s32(0), - error_code: v.s32(0), - response: { - card_num: v.str('0123456789ABCDEF'), - ref_id: v.str('0123456789ABCDEF'), - data_id: v.str('0123456789ABCDEF'), - sns_id: v.str('012345678'), - } - }; - } - - @sdvx() - async getSubscriptionStatus() { - return { - status: v.s32(0), - error_code: v.s32(0), - response: { - subscription: { - name: v.str('test'), - }, - } - }; - } - - @sdvx() - async heartbeat() { + async heartbeat(): Promise { return { status: v.s32(0), error_code: v.s32(0), @@ -72,7 +35,7 @@ export default class extends Combine(AcRelay) { } @sdvx() - async checkVersion() { + async checkVersion(): Promise { return { status: v.s32(0), error_code: v.s32(0), @@ -83,7 +46,7 @@ export default class extends Combine(AcRelay) { } @sdvx() - async getServerClock() { + async getServerClock(): Promise { return { status: v.s32(0), error_code: v.s32(0), @@ -94,7 +57,7 @@ export default class extends Combine(AcRelay) { } @sdvx() - async getServerState() { + async getServerState(): Promise { return { status: v.s32(0), error_code: v.s32(0), @@ -107,7 +70,7 @@ export default class extends Combine(AcRelay) { } @sdvx('SHIFT_JIS') - async getServices() { + async getServices(): Promise { return { status: v.s32(0), error_code: v.s32(0), diff --git a/src/controllers/sdvx/user.ts b/src/controllers/sdvx/user.ts new file mode 100644 index 0000000..afbff1f --- /dev/null +++ b/src/controllers/sdvx/user.ts @@ -0,0 +1,218 @@ +import * as data from '../../datas/sdvx.js'; +import { tokenToCardNumber, tokenToHash, tokenToSnsId } from "../../utils/laochan-id.js"; +import { Context } from "../../types.js"; +import { sdvx } from '../../decorators/eacnet.js'; +import { KValueG, Serializable, ValueTypes, v } from '../../utils/kxml-value.js'; +import { UserService } from '../../services/sdvx/user.js'; + +function trySave(kvalue: KValueG, value: T) { + if (value === undefined || value === null) + return; + + kvalue.__value = value; +} + +function tryAdd(kvalue: KValueG, value: number) { + if (value === undefined || value === null) + return; + + if (kvalue.__value instanceof Array) + return; + + kvalue.__value += value; +} + +export class User { + userService: UserService; + + @sdvx() + async sv6_save(ctx: Context): Promise { + const playData = await this.userService.getPlayerData(ctx.token); + if (!playData) { + return { + status: v.s32(0), + error_code: v.s32(0), + xrpc_status_code: v.s32(1), + xrpc_fault_code: v.s32(404), + }; + } + + const newData = ctx.body; + + trySave(playData.skill_level, newData.skill_level); + trySave(playData.skill_base_id, newData.skill_base_id); + trySave(playData.skill_name_id, newData.skill_name_id); + + tryAdd(playData.blaster_energy, newData.earned_blaster_energy); + tryAdd(playData.gamecoin_packet, newData.earned_gamecoin_packet); + tryAdd(playData.gamecoin_block, newData.earned_gamecoin_block); + + trySave(playData.hispeed, newData.hispeed); + trySave(playData.lanespeed, newData.lanespeed); + trySave(playData.gauge_option, newData.gauge_option); + trySave(playData.ars_option, newData.ars_option); + trySave(playData.notes_option, newData.notes_option); + trySave(playData.early_late_disp, newData.early_late_disp); + trySave(playData.draw_adjust, newData.draw_adjust); + trySave(playData.eff_c_left, newData.eff_c_left); + trySave(playData.eff_c_right, newData.eff_c_right); + trySave(playData.last_music_id, newData.music_id); + trySave(playData.last_music_type, newData.music_type); + trySave(playData.sort_type, newData.sort_type); + trySave(playData.narrow_down, newData.narrow_down); + trySave(playData.headphone, newData.headphone); + + if (newData.item?.info instanceof Array) { + playData.item.info = [ + ...(playData.item.info ?? []), + ...newData.item.info.map((info: { id: number; type: number; param: number; }) => ({ + id: v.u8(info.id), + type: v.u32(info.type), + param: v.u32(info.param), + })) + ] + } + + if (newData.item_infinite?.info instanceof Array) { + playData.item_infinite.info = [ + ...(playData.item_infinite.info ?? []), + ...newData.item_infinite.info.map((info: { id: number; type: number; param: number; }) => ({ + id: v.u8(info.id), + type: v.u32(info.type), + param: v.u32(info.param), + })) + ] + } + + if (newData.param?.info instanceof Array) { + playData.param.info = [ + ...(playData.param.info ?? []), + ...newData.param.info.map((info: { id: number; type: number; param: number; }) => ({ + id: v.u8(info.id), + type: v.u32(info.type), + param: v.u32(info.param), + })) + ] + } + + await this.userService.savePlayerData(ctx.token, playData); + + return { + status: v.s32(0), + error_code: v.s32(0), + xrpc_status_code: v.s32(0), + xrpc_fault_code: v.s32(0), + response: { + game: { $status: 0 }, + } + }; + } + + @sdvx() + async sv6_new(ctx: Context): Promise { + await this.userService.createEmptyPlayerData(ctx.token, ctx.body.name); + + return { + status: v.s32(0), + error_code: v.s32(0), + xrpc_status_code: v.s32(0), + xrpc_fault_code: v.s32(0), + response: { + game: { + $status: 0, + } + } + }; + } + + @sdvx() + async sv6_load(ctx: Context): Promise { + const playData = await this.userService.getPlayerData(ctx.token); + + if (!playData) { + return { + status: v.s32(0), + error_code: v.s32(0), + xrpc_status_code: v.s32(0), + xrpc_fault_code: v.s32(0), + response: { + game: { + $status: 0, + result: v.u8(1), + } + } + } + } + + // update blaster pass date + playData.ea_shop.blaster_pass_limit_date = v.u64(new Date().valueOf() + (30 * 60 * 60 * 1000)); + + return { + status: v.s32(0), + error_code: v.s32(0), + xrpc_status_code: v.s32(0), + xrpc_fault_code: v.s32(0), + response: { + game: { + $status: 0, + ...playData, + } + } + }; + } + + @sdvx() + async getItemList(): Promise { + return { + status: v.s32(0), + error_code: v.s32(0), + response: { + item_num: v.s32(data.itemList.length), + item: data.itemList.map(id => ({ + item_id: v.str(id), + not_free_count: v.s32(1), + free_count: v.s32(0), + })), + } + }; + } + + @sdvx() + async getGoodsList(): Promise { + return { + status: v.s32(0), + error_code: v.s32(0), + response: { + goods_num: v.s32(0), + } + }; + } + + @sdvx() + async getUserIDs(ctx: Context): Promise { + return { + status: v.s32(0), + error_code: v.s32(0), + response: { + card_num: v.str(tokenToCardNumber(ctx.token)), + ref_id: v.str(tokenToHash(ctx.token)), + data_id: v.str(tokenToHash(ctx.token)), + sns_id: v.str(tokenToSnsId(ctx.token)), + } + }; + } + + @sdvx() + async getSubscriptionStatus(): Promise { + return { + status: v.s32(0), + error_code: v.s32(0), + response: { + subscription: { + name: v.str('eac_sdvx_basic'), + }, + } + }; + } + +} diff --git a/src/database.ts b/src/database.ts index 01c0d4e..9a40ff0 100644 --- a/src/database.ts +++ b/src/database.ts @@ -1,9 +1,9 @@ import { Logger } from "@cordisjs/logger"; import { MongoClient } from "mongodb"; import config from "./utils/config.js"; -import { PlayerPlayData } from "./types/index.js"; +import { PlayerPlayData } from "./types/p2d/index.js"; import { fromKBinXml } from "./utils/kbinxml.js"; -import { Pdata } from "./types/pdata.js"; +import { Pdata } from "./types/p2d/pdata.js"; interface DatabaseMeta { version: number; diff --git a/src/datas/sdvx.ts b/src/datas/sdvx.ts index 3abaef5..93026ec 100644 --- a/src/datas/sdvx.ts +++ b/src/datas/sdvx.ts @@ -1,3 +1,5 @@ +import { v } from "../utils/kxml-value.js"; + export const musicDownloadLinks: Record = { [1]: { url: "https://dks1q2aivwkd6.cloudfront.net/vi/downloads/m_data/5bd191e2-8331-42e9-afbc-ddeda989cae9.bin", @@ -8285,3 +8287,45 @@ export const musicDownloadLinks: Record ({ + type: v.u8(11), + id: v.u32(i), + param: v.u32(10), +})); + +console.log(charaItems) diff --git a/src/services/p2d/user.ts b/src/services/p2d/user.ts index 8a3bc65..369e0fc 100644 --- a/src/services/p2d/user.ts +++ b/src/services/p2d/user.ts @@ -1,14 +1,11 @@ import { Binary, Db } from "mongodb"; import { inject, injectable } from "tsyringe"; -import { PlayerPlayData, PlayerMusicData, PlayerPlayLog, PlayerCourseLog, PlayerCustomizeSetting, PlayerRivalData } from "../../types/index.js"; -import { Pdata } from "../../types/pdata.js"; +import { PlayerPlayData, PlayerMusicData, PlayerPlayLog, PlayerCourseLog, PlayerCustomizeSetting, PlayerRivalData } from "../../types/p2d/index.js"; +import { Pdata } from "../../types/p2d/pdata.js"; import { fromKBinXml } from "../../utils/kbinxml.js"; @injectable() export class UserService { - /** - * - */ constructor( @inject(Db) private readonly db: Db, diff --git a/src/services/sdvx/user.ts b/src/services/sdvx/user.ts new file mode 100644 index 0000000..c29d98f --- /dev/null +++ b/src/services/sdvx/user.ts @@ -0,0 +1,114 @@ +import { Binary, Db, FindOptions } from "mongodb"; +import { inject, injectable } from "tsyringe"; +import { PlayerPlayData } from "../../types/sdvx/index.js"; +import { tokenToCardNumber, tokenToSdvxId } from "../../utils/laochan-id.js"; +import { v } from "../../utils/kxml-value.js"; +import { dateToString } from "../../utils/time.js"; +import * as data from '../../datas/sdvx.js' +import { brotliCompress, brotliDecompress } from "zlib"; +import { promisify } from "util"; +import { SaveData } from "../../types/sdvx/savedata.js"; + +@injectable() +export class UserService { + constructor( + @inject(Db) + private readonly db: Db, + ) { } + + get playDataCol() { + return this.db.collection('sdvx_player_data'); + } + + async hasPlayerData(token: string) { + return !!await this.playDataCol.countDocuments({ _id: token }); + } + + async savePlayerData(token: string, data: SaveData, name?: string) { + const bin = await promisify(brotliCompress)(JSON.stringify(data)); + const $set = { + save_data: new Binary(bin), + }; + + if (name) { + $set['name'] = name; + } + + return this.playDataCol.updateOne({ _id: token }, { $set }, { upsert: true }) + } + + async getPlayerData(token: string, options?: FindOptions): Promise { + const result = await this.playDataCol.findOne({ _id: token }, options); + if (!result) + return undefined; + + const decompressed = await promisify(brotliDecompress)(result.save_data.buffer) + return JSON.parse(decompressed.toString('utf-8')); + } + + async createEmptyPlayerData(token: string, name: string) { + const save_data: SaveData = { + code: v.str(tokenToCardNumber(token)), + name: v.str(name), + sdvx_id: v.str(tokenToSdvxId(token)), + creator_id: v.u32(0), + gamecoin_block: v.u32(0), + gamecoin_packet: v.u32(0), + blaster_energy: v.u32(0), + blaster_count: v.u32(0), + appeal_id: v.u16(0), + skill_level: v.s16(0), + skill_base_id: v.s16(0), + skill_name_id: v.s16(0), + + hispeed: v.s32(0), + lanespeed: v.u32(0), + gauge_option: v.u8(0), + ars_option: v.u8(0), + notes_option: v.u8(0), + early_late_disp: v.u8(0), + draw_adjust: v.s32(0), + eff_c_left: v.u8(0), + eff_c_right: v.u8(0), + last_music_id: v.s32(0), + last_music_type: v.u8(0), + sort_type: v.u8(0), + narrow_down: v.u8(0), + headphone: v.u8(0), + + play_count: v.u32(0), + day_count: v.u32(0), + today_count: v.u32(0), + play_chain: v.u32(0), + max_play_chain: v.u32(0), + week_count: v.u32(0), + week_play_count: v.u32(0), + week_chain: v.u32(0), + max_week_chain: v.u32(0), + + last_date: v.str(dateToString(new Date())), + start_date: v.str(dateToString(new Date())), + + item: { + info: [ + ...data.charaItems, + ] + }, + item_cloud: {}, + item_infinite: {}, + skill: {}, + param: {}, + present: {}, + cloud: { + relation: v.s8(1), + }, + ea_shop: { + blaster_pass_enable: v.bool(true), + blaster_pass_limit_date: v.u64(0), + shop_item: {}, + }, + }; + + return this.savePlayerData(token, save_data, name); + } +} diff --git a/src/tool/xml-to-json.ts b/src/tool/xml-to-json.ts new file mode 100644 index 0000000..f2377d5 --- /dev/null +++ b/src/tool/xml-to-json.ts @@ -0,0 +1,9 @@ +import { readFileSync, writeFileSync } from "fs"; +import { toObject, parser } from "../utils/kbinxml.js"; + +const xml = readFileSync('input.xml', 'utf-8'); + +const parsedXml = parser.parse(xml); +const obj = toObject(parsedXml); + +writeFileSync('output.json', JSON.stringify(obj, undefined, 2)); diff --git a/src/types/api.ts b/src/types/p2d/api.ts similarity index 100% rename from src/types/api.ts rename to src/types/p2d/api.ts diff --git a/src/types/index.ts b/src/types/p2d/index.ts similarity index 100% rename from src/types/index.ts rename to src/types/p2d/index.ts diff --git a/src/types/pdata.ts b/src/types/p2d/pdata.ts similarity index 100% rename from src/types/pdata.ts rename to src/types/p2d/pdata.ts diff --git a/src/types/sdvx/index.ts b/src/types/sdvx/index.ts new file mode 100644 index 0000000..1bfd086 --- /dev/null +++ b/src/types/sdvx/index.ts @@ -0,0 +1,7 @@ +import { Binary } from "mongodb"; + +export interface PlayerPlayData { + _id: string; + name: string; + save_data: Binary; +} diff --git a/src/types/sdvx/savedata.ts b/src/types/sdvx/savedata.ts new file mode 100644 index 0000000..2177b70 --- /dev/null +++ b/src/types/sdvx/savedata.ts @@ -0,0 +1,86 @@ +import { KBoolean, KS16, KS32, KS8, KString, KU16, KU32, KU64, KU8 } from "../../utils/kxml-value.js"; + +export interface SaveData { + code: KString; + name: KString; + sdvx_id: KString; + + creator_id: KU32; + + gamecoin_packet: KU32; + gamecoin_block: KU32; + + blaster_energy: KU32; + blaster_count: KU32; + + appeal_id: KU16; + + skill_level: KS16; + skill_base_id: KS16; + skill_name_id: KS16; + + hispeed: KS32; + lanespeed: KU32; + gauge_option: KU8; + ars_option: KU8; + notes_option: KU8; + early_late_disp: KU8; + draw_adjust: KS32; + eff_c_left: KU8; + eff_c_right: KU8; + last_music_id: KS32; + last_music_type: KU8; + sort_type: KU8; + narrow_down: KU8; + headphone: KU8; + + play_count: KU32; + day_count: KU32; + today_count: KU32; + play_chain: KU32; + max_play_chain: KU32; + week_count: KU32; + week_play_count: KU32; + week_chain: KU32; + max_week_chain: KU32; + last_date: KString; + start_date: KString; + + item: { info?: Item[] }; + item_cloud: { info?: Item[] }; + item_infinite: { info?: Item[] }; + + skill: { course?: Course[] }; + + param: { info?: Item[] }; + + present: { info?: Item[] }; + cloud: { relation: KS8 }; + ea_shop: EaShop; +} + +export interface Course { + ssnid: KS16; + crsid: KS16; + st: KS16; + sc: KS32; + ex: KS32; + ct: KS16; + gr: KS16; + ar: KS16; + cnt: KS16; +} + +export interface EaShop { + blaster_pass_enable: KBoolean; + blaster_pass_limit_date: KU64; + shop_item: { + item?: Item[]; + } +} + +export interface Item { + type: KU8; + id: KU32; + param: KU32; +} diff --git a/src/utils/kbinxml.ts b/src/utils/kbinxml.ts index ae3a8f9..f3e1c55 100644 --- a/src/utils/kbinxml.ts +++ b/src/utils/kbinxml.ts @@ -1,8 +1,9 @@ import { to_bin, to_xml } from "@kamyu/kbinxml"; import { XMLParser } from "fast-xml-parser"; import _ from "lodash"; +import { Serializable } from "./kxml-value.js"; -const parser = new XMLParser({ +export const parser = new XMLParser({ ignoreAttributes: false, parseAttributeValue: false, attributeNamePrefix: '$', @@ -67,7 +68,7 @@ function parseValue(node: { $__type: string; $__count?: unknown }): any { }; } -function toObject(node: Record | unknown[] | string): any { +export function toObject(node: Record | unknown[] | string): any { if (node instanceof Array) { return node.map((v) => toObject(v as Record)); } @@ -152,7 +153,7 @@ function serializeValue(value: any, type: string): string { throw new Error(`unsupported type ${type}`); } -function serializeObject(obj: Object, name: string, linePrefix: string = '') { +function serializeObject(obj: Serializable, name: string, linePrefix: string = '') { let output = `${linePrefix}<${name}`; const entries = Object.entries(obj); @@ -175,12 +176,19 @@ function serializeObject(obj: Object, name: string, linePrefix: string = '') { attrs.sort((a, b) => a[0] < b[0] ? 1 : (a[0] > b[0] ? -1 : 0)); for (const attr of attrs) { + if (attr[1] === undefined) + continue; + output += ` ${attr[0]}="${_.escape(attr[1])}"`; } output += '>'; if (value) { + if (value[1] === undefined) { + return ''; + } + const type = attrs.find(v => v[0] == '__type'); if (!type) { @@ -217,7 +225,7 @@ function serializeObject(obj: Object, name: string, linePrefix: string = '') { return output + `\n`; } -export function toKBinXml(topName: string, obj: unknown, encoding: 'UTF-8' | 'SHIFT_JIS' = 'UTF-8') { +export function toKBinXml(topName: string, obj: Serializable, encoding: 'UTF-8' | 'SHIFT_JIS' = 'UTF-8') { const xml = `` + serializeObject(obj, topName); return to_bin(xml); } diff --git a/src/utils/kxml-value.ts b/src/utils/kxml-value.ts index 104ca85..90d09b0 100644 --- a/src/utils/kxml-value.ts +++ b/src/utils/kxml-value.ts @@ -14,8 +14,40 @@ export type ValueTypes = 's8' | 'str' | 'string' | 'time'; -function vg(type: ValueTypes) { - return (value: unknown, attrs?: object) => { +export type KValueG = { + $__type: T; + __value: VT | VT[]; +} & Record; + +export type KS8 = KValueG<'s8', number>; +export type KU8 = KValueG<'u8', number>; +export type KS16 = KValueG<'s16', number>; +export type KU16 = KValueG<'u16', number>; +export type KS32 = KValueG<'s32', number>; +export type KU32 = KValueG<'u32', number>; +export type KS64 = KValueG<'s64', number>; +export type KU64 = KValueG<'u64', number>; +export type KFloat = KValueG<'float', number>; +export type KDouble = KValueG<'double', number>; +export type KBoolean = KValueG<'bool', boolean> | KValueG<'b', boolean>; +export type KBinary = KValueG<'bin', Buffer> | KValueG<'binary', Buffer>; +export type KString = KValueG<'str', string> | KValueG<'string', string>; +export type KIPv4 = KValueG<'ip4', string>; +export type KTime = KValueG<'time', Date | number>; +export type KValue = KS8 | KU8 | KS16 | KU16 | KS32 | KS64 | KU64 | KFloat | KDouble | KBoolean | KBinary | KString | KIPv4 | KTime; + +type AttributeProperty = { + [K in keyof T as K extends string ? `$${K}` : never]: T[K] +} + +export type Serializable = { + [key: string]: KValue | Serializable +} | AttributeProperty<{ + [key: string]: string | number; +}>; + +function vg(type: T) { + return (value: VT | VT[], attrs?: object): KValueG => { const result = { $__type: type, __value: value, @@ -31,23 +63,23 @@ function vg(type: ValueTypes) { }; } -export const v: Record object> = { - s8: vg('s8'), - u8: vg('u8'), - s16: vg('s16'), - u16: vg('u16'), - s32: vg('s32'), - u32: vg('u32'), - s64: vg('s64'), - u64: vg('u64'), - float: vg('float'), - double: vg('double'), - b: vg('b'), - bool: vg('bool'), - bin: vg('bin'), - binary: vg('binary'), - ip4: vg('ip4'), - str: vg('str'), - string: vg('string'), - time: vg('time'), +export const v = { + s8: vg<'s8', number>('s8'), + u8: vg<'u8', number>('u8'), + s16: vg<'s16', number>('s16'), + u16: vg<'u16', number>('u16'), + s32: vg<'s32', number>('s32'), + u32: vg<'u32', number>('u32'), + s64: vg<'s64', number>('s64'), + u64: vg<'u64', number>('u64'), + float: vg<'float', number>('float'), + double: vg<'double', number>('double'), + b: vg<'b', boolean>('b'), + bool: vg<'bool', boolean>('bool'), + bin: vg<'bin', Buffer>('bin'), + binary: vg<'binary', Buffer>('binary'), + ip4: vg<'ip4', string>('ip4'), + str: vg<'str', string>('str'), + string: vg<'string', string>('string'), + time: vg<'time', Date | number>('time'), } diff --git a/src/utils/laochan-id.ts b/src/utils/laochan-id.ts index 9293736..35b443d 100644 --- a/src/utils/laochan-id.ts +++ b/src/utils/laochan-id.ts @@ -1,9 +1,32 @@ import { createHash } from 'crypto'; +import highwayHash from 'highwayhash'; -export function fromToken(token: string) { +export function tokenToInfinitasId(token: string) { const key = createHash('md5') .update(token, 'utf-8') .digest('hex'); return ('LCHAN' + key).slice(0, 13); } + +const HIGHWAY_KEY = Buffer.from('LAOCHANID_HIGHWAY_KEY_NOTSECURE!'); + +export function tokenToHash(token: string) { + const key = highwayHash.asHexString(HIGHWAY_KEY, Buffer.from(token)); + return key.toUpperCase(); +} + +export function tokenToCardNumber(token: string) { + const hash = tokenToHash(token); + return ('LCHAN' + hash.toUpperCase()).slice(0, 16); +} + +export function tokenToSnsId(token: string) { + const key = highwayHash.asUInt32Low(HIGHWAY_KEY, Buffer.from(token)); + return key.toString().padStart(8, '0'); +} + +export function tokenToSdvxId(token: string) { + const snsId = tokenToSnsId(token); + return 'SV-' + snsId.slice(0, 4) + '-' + snsId.slice(4, 8); +} diff --git a/src/utils/time.ts b/src/utils/time.ts new file mode 100644 index 0000000..8255985 --- /dev/null +++ b/src/utils/time.ts @@ -0,0 +1,7 @@ +export function dateToString(date: Date) { + const isoStr = date.toISOString(); + const d = isoStr.split('T')[0] + const t = isoStr.split('T')[1].split('.')[0]; + + return `${d} ${t}`; +}