Compare commits

..

No commits in common. "main" and "1.1.1" have entirely different histories.
main ... 1.1.1

23 changed files with 1882 additions and 2628 deletions

View File

@ -62,10 +62,6 @@ jobs:
with:
projectPath: ./gui
- name: Prepare to release the app
if: ${{ startsWith(github.ref, 'refs/tags/gui-v') }}
run: deno run -A ./gui/scripts/enable-updater.ts
- name: Release the app
uses: tauri-apps/tauri-action@v0
if: ${{ startsWith(github.ref, 'refs/tags/gui-v') }}

View File

@ -1,31 +1,3 @@
## 0.4.1
feat: add support for Challenges
([#72](https://github.com/spacemeowx2/s3si.ts/issues/72))
## 0.4.0
feat: update `callImink`
feat: update VersionData
## 0.3.6
feat: update `WEB_VIEW_VERSION` and query hashes for 4.0.0
## 0.3.5
fix: wrong ability keys in some languages
## 0.3.4
fix(gui): GUI ja translation about VS and Salmon Run
([#68](https://github.com/spacemeowx2/s3si.ts/issues/68))
## 0.3.3
feat: add eggstra work mode
## 0.3.2
feat: update `WEB_VIEW_VERSION` and query hashes

View File

@ -71,7 +71,7 @@
},
"npm": {
"specifiers": {
"mongodb": "mongodb@5.5.0",
"mongodb": "mongodb@5.1.0",
"splatnet3-types": "splatnet3-types@0.2.20230227204004"
},
"packages": {
@ -94,10 +94,6 @@
"integrity": "sha512-y09gBGusgHtinMon/GVbv1J6FrXhnr/+6hqLlSmEFzkz6PodqF6TxjyvfvY3AfO+oG1mgUtbC86xSbOlwvM62Q==",
"dependencies": {}
},
"bson@5.3.0": {
"integrity": "sha512-ukmCZMneMlaC5ebPHXIkP8YJzNl5DC41N5MAIvKDqLggdao342t4McltoJBQfQya/nHBWAcSsYRqlXPoQkTJag==",
"dependencies": {}
},
"ip@2.0.0": {
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
"dependencies": {}
@ -122,15 +118,6 @@
"socks": "socks@2.7.1"
}
},
"mongodb@5.5.0": {
"integrity": "sha512-XgrkUgAAdfnZKQfk5AsYL8j7O99WHd4YXPxYxnh8dZxD+ekYWFRA3JktUsBnfg+455Smf75/+asoU/YLwNGoQQ==",
"dependencies": {
"bson": "bson@5.3.0",
"mongodb-connection-string-url": "mongodb-connection-string-url@2.6.0",
"saslprep": "saslprep@1.0.3",
"socks": "socks@2.7.1"
}
},
"punycode@2.3.0": {
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"dependencies": {}

View File

@ -11,34 +11,34 @@
"lint": "eslint --max-warnings=0 src"
},
"dependencies": {
"@tauri-apps/api": "^1.3.0",
"@tauri-apps/api": "^1.2.0",
"classnames": "^2.3.2",
"daisyui": "^2.52.0",
"i18next": "^22.5.0",
"i18next-browser-languagedetector": "^7.0.2",
"daisyui": "^2.51.3",
"i18next": "^22.4.10",
"i18next-browser-languagedetector": "^7.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.3.1",
"react-icons": "^4.9.0",
"react-router-dom": "^6.11.2",
"react-i18next": "^12.2.0",
"react-icons": "^4.8.0",
"react-router-dom": "^6.8.2",
"react-use": "^17.4.0"
},
"devDependencies": {
"@tauri-apps/cli": "^1.3.1",
"@types/node": "^20.2.5",
"@tauri-apps/cli": "^1.2.3",
"@types/node": "^18.14.5",
"@types/react": "^18.0.15",
"@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^4.0.0",
"autoprefixer": "^10.4.14",
"eslint": "^8.41.0",
"@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.13",
"eslint": "^8.35.0",
"eslint-config-react-app": "^7.0.1",
"i18next-http-backend": "^2.2.1",
"postcss": "^8.4.24",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.4",
"vite": "^4.3.9",
"i18next-http-backend": "^2.1.1",
"postcss": "^8.4.21",
"tailwindcss": "^3.2.7",
"typescript": "^4.9.5",
"vite": "^4.1.4",
"vite-plugin-eslint": "^1.8.1",
"vite-tsconfig-paths": "^4.2.0"
"vite-tsconfig-paths": "^4.0.5"
},
"eslintConfig": {
"extends": "react-app"

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +0,0 @@
import * as path from "https://deno.land/std@0.178.0/path/mod.ts";
if (import.meta.main) {
const __dirname = path.dirname(path.fromFileUrl(import.meta.url));
const tauriConf = path.join(__dirname, '../src-tauri/tauri.conf.json');
const tauriConfContent = await Deno.readTextFile(tauriConf);
const tauriConfJson = JSON.parse(tauriConfContent);
tauriConfJson.tauri.updater.active = true;
await Deno.writeTextFile(tauriConf, JSON.stringify(tauriConfJson, null, 2));
}

321
gui/src-tauri/Cargo.lock generated
View File

@ -62,6 +62,22 @@ dependencies = [
"system-deps 6.0.3",
]
[[package]]
name = "attohttpc"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fcf00bc6d5abb29b5f97e3c61a90b6d3caa12f3faf897d4a3e3607c050a35a7"
dependencies = [
"flate2",
"http",
"log",
"native-tls",
"serde",
"serde_json",
"serde_urlencoded",
"url",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -132,6 +148,12 @@ dependencies = [
"serde",
]
[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "bytemuck"
version = "1.13.1"
@ -1197,6 +1219,15 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "json-patch"
version = "0.2.7"
@ -1340,6 +1371,12 @@ dependencies = [
"autocfg",
]
[[package]]
name = "minisign-verify"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "933dca44d65cdd53b355d0b73d380a2ff5da71f87f036053188bf1eab6a19881"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
@ -1349,6 +1386,24 @@ dependencies = [
"adler",
]
[[package]]
name = "native-tls"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]]
name = "ndk"
version = "0.6.0"
@ -1470,6 +1525,17 @@ dependencies = [
"objc_exception",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
dependencies = [
"block",
"objc",
"objc_id",
]
[[package]]
name = "objc_exception"
version = "0.1.2"
@ -1504,6 +1570,51 @@ dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "openssl"
version = "0.10.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b102428fd03bc5edf97f62620f7298614c45cedf287c271e7ed450bbaf83f2e1"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23bbbf7854cd45b83958ebe919f0e8e516793727652e27fda10a8384cfc790b7"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "os_pipe"
version = "1.1.3"
@ -1953,6 +2064,30 @@ version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rfd"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0149778bd99b6959285b0933288206090c50e2327f47a9c463bfdbf45c8823ea"
dependencies = [
"block",
"dispatch",
"glib-sys",
"gobject-sys",
"gtk-sys",
"js-sys",
"lazy_static",
"log",
"objc",
"objc-foundation",
"objc_id",
"raw-window-handle",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows 0.37.0",
]
[[package]]
name = "rustc_version"
version = "0.3.3"
@ -2024,6 +2159,15 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "schannel"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3"
dependencies = [
"windows-sys 0.42.0",
]
[[package]]
name = "scoped-tls"
version = "1.0.1"
@ -2036,6 +2180,29 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "selectors"
version = "0.22.0"
@ -2125,6 +2292,18 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa 1.0.5",
"ryu",
"serde",
]
[[package]]
name = "serde_with"
version = "1.14.0"
@ -2406,6 +2585,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe7e0f1d535e7cbbbab43c82be4fc992b84f9156c16c160955617e0260ebc449"
dependencies = [
"anyhow",
"attohttpc",
"base64 0.13.1",
"cocoa",
"dirs-next",
"embed_plist",
@ -2418,6 +2599,7 @@ dependencies = [
"heck 0.4.1",
"http",
"ignore",
"minisign-verify",
"objc",
"once_cell",
"open",
@ -2426,6 +2608,7 @@ dependencies = [
"rand 0.8.5",
"raw-window-handle",
"regex",
"rfd",
"semver 1.0.16",
"serde",
"serde_json",
@ -2440,12 +2623,14 @@ dependencies = [
"tauri-utils",
"tempfile",
"thiserror",
"time",
"tokio",
"url",
"uuid 1.3.0",
"webkit2gtk",
"webview2-com",
"windows 0.39.0",
"zip",
]
[[package]]
@ -2869,6 +3054,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version-compare"
version = "0.0.11"
@ -2910,6 +3101,82 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
dependencies = [
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "web-sys"
version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "webkit2gtk"
version = "0.18.2"
@ -3026,6 +3293,19 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57b543186b344cc61c85b5aab0d2e3adf4e0f99bc076eff9aa5927bcc0b8a647"
dependencies = [
"windows_aarch64_msvc 0.37.0",
"windows_i686_gnu 0.37.0",
"windows_i686_msvc 0.37.0",
"windows_x86_64_gnu 0.37.0",
"windows_x86_64_msvc 0.37.0",
]
[[package]]
name = "windows"
version = "0.39.0"
@ -3126,6 +3406,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a"
[[package]]
name = "windows_aarch64_msvc"
version = "0.39.0"
@ -3138,6 +3424,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1"
[[package]]
name = "windows_i686_gnu"
version = "0.39.0"
@ -3150,6 +3442,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c"
[[package]]
name = "windows_i686_msvc"
version = "0.39.0"
@ -3162,6 +3460,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.39.0"
@ -3180,6 +3484,12 @@ version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.37.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.39.0"
@ -3277,3 +3587,14 @@ checksum = "6d1526bbe5aaeb5eb06885f4d987bcdfa5e23187055de9b83fe00156a821fabc"
dependencies = [
"libc",
]
[[package]]
name = "zip"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
dependencies = [
"byteorder",
"crc32fast",
"crossbeam-utils",
]

View File

@ -13,7 +13,7 @@ edition = "2021"
tauri-build = { version = "1.2", features = [] }
[dependencies]
tauri = { version = "1.2", features = ["fs-all", "path-all", "process-relaunch", "shell-execute", "shell-open", "shell-sidecar", "window-all"] }
tauri = { version = "1.2", features = ["fs-all", "path-all", "process-relaunch", "shell-execute", "shell-open", "shell-sidecar", "updater", "window-all"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tokio = { version = "1.0", features = ["time"] }

View File

@ -8,7 +8,7 @@
},
"package": {
"productName": "s3si-ts",
"version": "0.4.1"
"version": "0.2.0"
},
"tauri": {
"allowlist": {
@ -72,9 +72,8 @@
"csp": null
},
"updater": {
"active": false,
"active": true,
"endpoints": [
"https://s3si-update.imspace.cn/v1/{{target}}/{{arch}}/{{current_version}}",
"https://gist.githubusercontent.com/spacemeowx2/a67078487d3450b75927953f6edc14e2/raw/update-request.json"
],
"dialog": true,

View File

@ -4,8 +4,8 @@
"打开 stat.ink": "stat.inkを開く",
"打开鱿鱼圈3": "イカリング3を開く",
"导出": "エクスポートする",
"导出打工数据": "サーモンランデータをエクスポートする",
"导出对战数据": "バトルデータをエクスポートする",
"导出打工数据": "勤務データをエクスポートする",
"导出对战数据": "対戦データをエクスポートする",
"欢迎! 请点击\"导出\"按钮开始使用.": "ようこそ!「エクスポート」ボタンをクリックして使い始めてください。",
"界面语言": "インターフェース言語",
"没有更改": "変更はありません",

View File

@ -9,19 +9,22 @@ if (import.meta.main) {
"x86_64-apple-darwin",
"aarch64-apple-darwin",
];
const rustInfo = await (new Deno.Command("rustc", {
args: ["-Vv"],
})).output();
const target =
/host: (\S+)/g.exec(new TextDecoder().decode(rustInfo.stdout))?.[1] ?? "?";
const rustInfo = new TextDecoder().decode(
await Deno.run({
cmd: ["rustc", "-Vv"],
stdout: "piped",
}).output(),
);
const target = /host: (\S+)/g.exec(rustInfo)?.[1] ?? "?";
if (!TARGETS.includes(target)) {
console.error(`Unsupported target: ${target}`);
Deno.exit(1);
}
const p = new Deno.Command("deno", {
args: [
const p = Deno.run({
cmd: [
"deno",
"compile",
"--target",
target,
@ -32,7 +35,7 @@ if (import.meta.main) {
],
cwd: __dirname,
});
const status = await p.output();
const status = await p.status();
if (!status.success) {
console.error(
"Failed to run deno compile for target",
@ -47,21 +50,18 @@ if (import.meta.main) {
Deno.build.os === "windows" ? ".exe" : ""
}`;
console.log("Test the binary");
const s3si = new Deno.Command(binPath, {
const s3si = Deno.run({
cmd: [binPath],
stdin: "piped",
stdout: "piped",
}).spawn();
const s3siWriter = s3si.stdin.getWriter();
await s3siWriter.write(
});
await s3si.stdin?.write(
new TextEncoder().encode(
'{"jsonrpc":"2.0","method":"hello","params":[],"id":1}\n',
),
);
const output = new TextDecoder().decode(
(await s3si.stdout.getReader().read()).value,
);
await s3siWriter.close();
s3si.stdin?.close();
const output = new TextDecoder().decode(await s3si.output());
assertEquals(
output,

View File

@ -84,104 +84,5 @@
"https://deno.land/x/ts_essentials@v9.1.2/lib/mod.ts": "d7e44a25aa621425ffd118a0210a492c5c354411018e2db648a68614d5901f5b",
"https://deno.land/x/ts_essentials@v9.1.2/lib/types.ts": "7ee99797a880948c07020e90d569ca3c5d465c378949262110283aa7856f5603",
"https://deno.land/x/ts_essentials@v9.1.2/mod.ts": "ffae461c16d4a1bf24c2179582ab8d5c81ad0df61e4ae2fba51ef5e5bdf90345"
},
"npm": {
"specifiers": {
"mongodb": "mongodb@5.1.0",
"splatnet3-types": "splatnet3-types@0.2.20230227204004"
},
"packages": {
"@types/node@18.14.2": {
"integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==",
"dependencies": {}
},
"@types/webidl-conversions@7.0.0": {
"integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==",
"dependencies": {}
},
"@types/whatwg-url@8.2.2": {
"integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==",
"dependencies": {
"@types/node": "@types/node@18.14.2",
"@types/webidl-conversions": "@types/webidl-conversions@7.0.0"
}
},
"bson@5.0.1": {
"integrity": "sha512-y09gBGusgHtinMon/GVbv1J6FrXhnr/+6hqLlSmEFzkz6PodqF6TxjyvfvY3AfO+oG1mgUtbC86xSbOlwvM62Q==",
"dependencies": {}
},
"ip@2.0.0": {
"integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==",
"dependencies": {}
},
"memory-pager@1.5.0": {
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"dependencies": {}
},
"mongodb-connection-string-url@2.6.0": {
"integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==",
"dependencies": {
"@types/whatwg-url": "@types/whatwg-url@8.2.2",
"whatwg-url": "whatwg-url@11.0.0"
}
},
"mongodb@5.1.0": {
"integrity": "sha512-qgKb7y+EI90y4weY3z5+lIgm8wmexbonz0GalHkSElQXVKtRuwqXuhXKccyvIjXCJVy9qPV82zsinY0W1FBnJw==",
"dependencies": {
"bson": "bson@5.0.1",
"mongodb-connection-string-url": "mongodb-connection-string-url@2.6.0",
"saslprep": "saslprep@1.0.3",
"socks": "socks@2.7.1"
}
},
"punycode@2.3.0": {
"integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==",
"dependencies": {}
},
"saslprep@1.0.3": {
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"dependencies": {
"sparse-bitfield": "sparse-bitfield@3.0.3"
}
},
"smart-buffer@4.2.0": {
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"dependencies": {}
},
"socks@2.7.1": {
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==",
"dependencies": {
"ip": "ip@2.0.0",
"smart-buffer": "smart-buffer@4.2.0"
}
},
"sparse-bitfield@3.0.3": {
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"dependencies": {
"memory-pager": "memory-pager@1.5.0"
}
},
"splatnet3-types@0.2.20230227204004": {
"integrity": "sha512-FAY6pbUcrp5O8c49BNXSKxoyM3UlCrRx2AtA9Y3qlvqOLdHqwxtzcdzbk1b1hRam8ZcrxRzE/ii6ESRiPIAnZw==",
"dependencies": {}
},
"tr46@3.0.0": {
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"dependencies": {
"punycode": "punycode@2.3.0"
}
},
"webidl-conversions@7.0.0": {
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"dependencies": {}
},
"whatwg-url@11.0.0": {
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"dependencies": {
"tr46": "tr46@3.0.0",
"webidl-conversions": "webidl-conversions@7.0.0"
}
}
}
}
}

View File

@ -1,77 +0,0 @@
import { MongoDB } from "../deps.ts";
import { DEFAULT_ENV } from "../src/env.ts";
import { MongoDBExporter } from "../src/exporters/mongodb.ts";
import { FileStateBackend, Profile } from "../src/state.ts";
const env = DEFAULT_ENV;
const stateBackend = new FileStateBackend("./profile.json");
const profile = new Profile({ stateBackend, env });
await profile.readState();
if (!profile.state.mongoDbUri) {
console.error("MongoDB URI not set");
Deno.exit(1);
}
const mongoDbClient = new MongoDB.MongoClient(profile.state.mongoDbUri);
const battlesCollection = mongoDbClient.db("splashcat").collection("battles");
const cursor = battlesCollection.find();
const oldDocuments = await battlesCollection.countDocuments();
console.log(`Found ${oldDocuments} old battles to upload...`);
let count = 0;
const erroredBattles = [];
for await (const doc of cursor) {
const { splatNetData, _id } = doc;
// start time for performance tracking, needs to be very accurate
const startTime = new Date();
splatNetData.playedTime = splatNetData.playedTime.toISOString();
const response = await fetch("http://127.0.0.1:8000/battles/api/upload/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${profile.state.splashcatApiKey}`,
},
body: JSON.stringify({
"data_type": "splatnet3",
"battle": splatNetData,
})
})
if (!response.ok) {
console.error(`Failed to upload ${splatNetData.id}`);
erroredBattles.push({
id: doc.gameId,
error: await response.text(),
});
}
// end time for performance tracking, needs to be very accurate
const endTime = new Date();
const timeTaken = endTime.getTime() - startTime.getTime();
console.log(`Uploaded ${splatNetData.id} (${timeTaken}ms)`);
count++;
console.log(`Uploaded ${count}/${oldDocuments} battles`)
if (count % 100 === 0) {
console.log("Updating error logs...");
if (erroredBattles.length > 0) {
await Deno.writeFile("./errored-battles.json", new TextEncoder().encode(JSON.stringify(erroredBattles, null, "\t")));
}
}
}
console.log("Done!");
if (erroredBattles.length > 0) {
await Deno.writeFile("./errored-battles.json", new TextEncoder().encode(JSON.stringify(erroredBattles, null, 2)));
}

View File

@ -30,62 +30,6 @@ function getConst(content: string, name: string): string {
return JSON.parse(match[1]);
}
function replaceEnum(
content: string,
name: string,
pairs: Record<string, string>,
): string {
const regex = new RegExp(`export enum ${name} {([\\s\\S^}]+?)}`);
const body = Object.entries(pairs).map(([key, value]) =>
` ${key} = "${value}"`
).join(",\n");
return content.replace(regex, `export enum ${name} {\n${body}\n}`);
}
function getEnumKeys(content: string, name: string): string[] {
const regex = new RegExp(`export enum ${name} {([\\s\\S^}]+?)}`);
const match = regex.exec(content);
if (!match) {
throw new Error(`Cannot find ${name}`);
}
const body = match[1];
// extract keys from `key = "value"`
const keys: string[] = [];
const keyRE = /\s*(\w+)\s*=/g;
while (true) {
const match = keyRE.exec(body);
if (!match) {
break;
}
keys.push(match[1]);
}
return keys;
}
function getQueryHash(js: string, query: string): string {
const regex = new RegExp(
`params:\\{id:"([^"]*?)",metadata:{},name:"${query}"`,
);
const match = regex.exec(js);
if (!match) {
throw new Error(`Cannot find ${query}`);
}
if (match[0].length > 500) {
throw new Error(`Match too large ${match[0].length}`);
}
return match[1];
}
async function printError<T>(p: Promise<T>): Promise<T | undefined> {
try {
return await p;
@ -95,7 +39,7 @@ async function printError<T>(p: Promise<T>): Promise<T | undefined> {
}
}
async function getMainJSBody(): Promise<string> {
async function getWebViewVer(): Promise<string> {
const splatnet3Home = await (await fetch(SPLATNET3_URL)).text();
const mainJS = /src="(\/.*?\.js)"/.exec(splatnet3Home)?.[1];
@ -106,16 +50,9 @@ async function getMainJSBody(): Promise<string> {
const mainJSBody = await (await fetch(SPLATNET3_URL + mainJS)).text();
return mainJSBody;
}
const mainJSBody = await getMainJSBody();
// deno-lint-ignore require-await
async function getWebViewVer(js: string): Promise<string> {
const revision = /"([0-9a-f]{40})"/.exec(js)?.[1];
const revision = /"([0-9a-f]{40})"/.exec(mainJSBody)?.[1];
const version = /revision_info_not_set.*?=("|`)(\d+\.\d+\.\d+)-/.exec(
js,
mainJSBody,
)
?.[2];
@ -146,7 +83,7 @@ const oldValues = {
};
const newValues: Record<string, string | undefined> = {};
newValues.WEB_VIEW_VERSION = await printError(getWebViewVer(mainJSBody));
newValues.WEB_VIEW_VERSION = await printError(getWebViewVer());
newValues.NSOAPP_VERSION = await printError(getNSOVer());
for (const [key, value] of Object.entries(newValues)) {
@ -154,27 +91,8 @@ for (const [key, value] of Object.entries(newValues)) {
content = replaceConst(content, key, value);
}
}
console.log("const updated");
console.log("Old:", oldValues);
console.log("New:", newValues);
const keys = getEnumKeys(content, "Queries");
const pairs = Object.fromEntries(
keys.map((key) => [key, getQueryHash(mainJSBody, key)]),
);
content = replaceEnum(content, "Queries", pairs);
console.log("query updated");
await Deno.writeTextFile(CONSTANT_PATH, content);
const command = new Deno.Command(Deno.execPath(), {
args: ["fmt", "./src/constant.ts"],
cwd: ROOT_DIR,
stdin: "inherit",
stdout: "inherit",
});
const { code } = command.outputSync();
if (code !== 0) {
Deno.exit(code);
}
console.log("Done");
console.log("Old:", oldValues);
console.log("New:", newValues);

View File

@ -26,10 +26,6 @@ Deno.test("getSeason", () => {
assertEquals(season3?.id, "season202303");
const season4 = getSeason(new Date("2023-06-01T00:00:00+00:00"));
assertEquals(season4?.id, "season202306");
const nonExist = getSeason(new Date("2022-06-09T00:00:00+00:00"));
assertEquals(nonExist, undefined);

View File

@ -24,12 +24,6 @@ export const SEASONS: Season[] = [
start: new Date("2023-03-01T00:00:00+00:00"),
end: new Date("2023-06-01T00:00:00+00:00"),
},
{
id: "season202306",
name: "Sizzle Season 2023",
start: new Date("2023-06-01T00:00:00+00:00"),
end: new Date("2023-09-01T00:00:00+00:00"),
},
];
export const getSeason = (date: Date): Season | undefined => {

View File

@ -1,522 +0,0 @@
[
{
"key": "ink_saver_main",
"name": {
"de-DE": "Hauptverbrauch",
"en-GB": "Ink Saver (Main)",
"en-US": "Ink Saver (Main)",
"es-ES": "Tintahorro (ppal.)",
"es-MX": "Ahorro tinta (ppal.)",
"fr-CA": "Encrémenteur (pr.)",
"fr-FR": "Encrémenteur (pr.)",
"it-IT": "Eco-colore princ.",
"ja-JP": "インク効率アップ(メイン)",
"ko-KR": "잉크 효율 업(메인)",
"nl-NL": "Hoofdspaarder",
"ru-RU": "Основной баллон X",
"zh-CN": "提升墨汁效率(主要武器)",
"zh-TW": "提升墨汁效率(主要武器)"
},
"primary_only": false
},
{
"key": "ink_saver_sub",
"name": {
"de-DE": "Sekundärverbrauch",
"en-GB": "Ink Saver (Sub)",
"en-US": "Ink Saver (Sub)",
"es-ES": "Tintahorro (sec.)",
"es-MX": "Ahorro tinta (sec.)",
"fr-CA": "Encrémenteur (sec.)",
"fr-FR": "Encrémenteur (sec.)",
"it-IT": "Eco-colore second.",
"ja-JP": "インク効率アップ(サブ)",
"ko-KR": "잉크 효율 업(서브)",
"nl-NL": "Subspaarder",
"ru-RU": "Запасной баллон X",
"zh-CN": "提升墨汁效率(次要武器)",
"zh-TW": "提升墨汁效率(次要武器)"
},
"primary_only": false
},
{
"key": "ink_recovery_up",
"name": {
"de-DE": "Regeneration +",
"en-GB": "Ink Recovery Up",
"en-US": "Ink Recovery Up",
"es-ES": "Recarga rápida",
"es-MX": "Mejor recarga tinta",
"fr-CA": "Levée d'encre",
"fr-FR": "Levée d'encre",
"it-IT": "Recupero colore +",
"ja-JP": "インク回復力アップ",
"ko-KR": "잉크 회복력 업",
"nl-NL": "Inktvulling",
"ru-RU": "Быстрый баллон",
"zh-CN": "提升墨汁回复力",
"zh-TW": "提升墨汁回復力"
},
"primary_only": false
},
{
"key": "run_speed_up",
"name": {
"de-DE": "Lauftempo +",
"en-GB": "Run Speed Up",
"en-US": "Run Speed Up",
"es-ES": "Supercarrera",
"es-MX": "Carrera acelerada",
"fr-CA": "Course à pied",
"fr-FR": "Course à pied",
"it-IT": "Velocità +",
"ja-JP": "ヒト移動速度アップ",
"ko-KR": "인간 이동 속도 업",
"nl-NL": "Hardloper",
"ru-RU": "Спринтер",
"zh-CN": "提升人类移动速度",
"zh-TW": "提升人類移動速度"
},
"primary_only": false
},
{
"key": "swim_speed_up",
"name": {
"de-DE": "Schwimmtempo +",
"en-GB": "Swim Speed Up",
"en-US": "Swim Speed Up",
"es-ES": "Superbuceo",
"es-MX": "Nado acelerado",
"fr-CA": "Turbo-calmar",
"fr-FR": "Turbo-calamar",
"it-IT": "Velocità nuoto +",
"ja-JP": "イカダッシュ速度アップ",
"ko-KR": "징어대시 속도 업",
"nl-NL": "Zwemdiploma",
"ru-RU": "Плавунец",
"zh-CN": "提升鱿鱼冲刺速度",
"zh-TW": "提升魷魚衝刺速度"
},
"primary_only": false
},
{
"key": "special_charge_up",
"name": {
"de-DE": "Spezialladezeit +",
"en-GB": "Special Charge Up",
"en-US": "Special Charge Up",
"es-ES": "Recarga especial",
"es-MX": "Recarga especial",
"fr-CA": "Jauge spéciale +",
"fr-FR": "Jauge spéciale +",
"it-IT": "Ricarica speciale +",
"ja-JP": "スペシャル増加量アップ",
"ko-KR": "스페셜 증가량 업",
"nl-NL": "Speciaallader",
"ru-RU": "Особый насос",
"zh-CN": "提升特殊武器增加量",
"zh-TW": "提升特殊武器增加量"
},
"primary_only": false
},
{
"key": "special_saver",
"name": {
"de-DE": "Spezialabzug -",
"en-GB": "Special Saver",
"en-US": "Special Saver",
"es-ES": "Reducción especial",
"es-MX": "Ahorro especial",
"fr-CA": "Baisse spéciale -",
"fr-FR": "Baisse spéciale -",
"it-IT": "Riduzione speciale -",
"ja-JP": "スペシャル減少量ダウン",
"ko-KR": "스페셜 감소량 다운",
"nl-NL": "Speciaalspaarder",
"ru-RU": "Особый резерв",
"zh-CN": "降低特殊武器减少量",
"zh-TW": "降低特殊武器減少量"
},
"primary_only": false
},
{
"key": "special_power_up",
"name": {
"de-DE": "Spezialstärke +",
"en-GB": "Special Power Up",
"en-US": "Special Power Up",
"es-ES": "Superarma especial",
"es-MX": "Mejora especial",
"fr-CA": "Arme spéciale +",
"fr-FR": "Arme spéciale +",
"it-IT": "Arma speciale +",
"ja-JP": "スペシャル性能アップ",
"ko-KR": "스페셜 성능 업",
"nl-NL": "Specialist",
"ru-RU": "Особый подход",
"zh-CN": "提升特殊武器性能",
"zh-TW": "提升特殊武器性能"
},
"primary_only": false
},
{
"key": "quick_respawn",
"name": {
"de-DE": "Schnelle Rückkehr",
"en-GB": "Quick Respawn",
"en-US": "Quick Respawn",
"es-ES": "Retorno exprés",
"es-MX": "Regeneración rápida",
"fr-CA": "Sans temps mort",
"fr-FR": "Sans temps morts",
"it-IT": "Il tempo è colore",
"ja-JP": "復活時間短縮",
"ko-KR": "부활 시간 단축",
"nl-NL": "Comeback",
"ru-RU": "Феникс",
"zh-CN": "缩短复活时间",
"zh-TW": "縮短復活時間"
},
"primary_only": false
},
{
"key": "quick_super_jump",
"name": {
"de-DE": "Supersprung +",
"en-GB": "Quick Super Jump",
"en-US": "Quick Super Jump",
"es-ES": "Supersalto rápido",
"es-MX": "Supersalto rápido",
"fr-CA": "Aérodynamisme",
"fr-FR": "Aérodynamisme",
"it-IT": "Salti super e veloci",
"ja-JP": "スーパージャンプ時間短縮",
"ko-KR": "슈퍼 점프 시간 단축",
"nl-NL": "Turbosprong",
"ru-RU": "Суперпрыгун",
"zh-CN": "缩短超级跳跃时间",
"zh-TW": "縮短超級跳躍時間"
},
"primary_only": false
},
{
"key": "sub_power_up",
"name": {
"de-DE": "Sekundärstärke +",
"en-GB": "Sub Power Up",
"en-US": "Sub Power Up",
"es-ES": "Superarma secundaria",
"es-MX": "Mejora secundaria",
"fr-CA": "Arme secondaire +",
"fr-FR": "Arme secondaire +",
"it-IT": "Arma secondaria +",
"ja-JP": "サブ性能アップ",
"ko-KR": "서브 성능 업",
"nl-NL": "Subtopper",
"ru-RU": "Про-Запас",
"zh-CN": "提升次要武器性能",
"zh-TW": "提升次要武器性能"
},
"primary_only": false
},
{
"key": "ink_resistance_up",
"name": {
"de-DE": "Tintentoleranz +",
"en-GB": "Ink Resistance Up",
"en-US": "Ink Resistance Up",
"es-ES": "Impermeabilidad",
"es-MX": "Impermeabilidad",
"fr-CA": "Imperméabilité",
"fr-FR": "Pieds au sec",
"it-IT": "Scarpe impermeabili",
"ja-JP": "相手インク影響軽減",
"ko-KR": "상대 잉크 영향 감소",
"nl-NL": "Inkttolerantie",
"ru-RU": "Краскостойкость",
"zh-CN": "减轻对手墨汁影响",
"zh-TW": "減輕對手墨汁影響"
},
"primary_only": false
},
{
"key": "sub_resistance_up",
"name": {
"de-DE": "Sekundärschutz +",
"en-GB": "Sub Resistance Up",
"en-US": "Sub Resistance Up",
"es-ES": "Resistencia secundaria",
"es-MX": "Resistencia secundaria",
"fr-CA": "Filtre à secondaires",
"fr-FR": "Filtre à secondaires",
"it-IT": "Arma sec. impermeabile",
"ja-JP": "サブ影響軽減",
"ko-KR": "서브 영향 감소",
"nl-NL": "Subdemper",
"ru-RU": "Стойкость запаса",
"zh-CN": "减轻次要武器影响",
"zh-TW": "減輕次要武器影響"
},
"primary_only": false
},
{
"key": "intensify_action",
"name": {
"de-DE": "Action +",
"en-GB": "Intensify Action",
"en-US": "Intensify Action",
"es-ES": "Agilidad extra",
"es-MX": "Agilidad extra",
"fr-CA": "Feu de l'action",
"fr-FR": "Feu de l'action",
"it-IT": "Intensificazione",
"ja-JP": "アクション強化",
"ko-KR": "액션 강화",
"nl-NL": "Actie-assistentie",
"ru-RU": "Ультраудар",
"zh-CN": "行动强化",
"zh-TW": "行動強化"
},
"primary_only": false
},
{
"key": "opening_gambit",
"name": {
"de-DE": "Startvorteil",
"en-GB": "Opening Gambit",
"en-US": "Opening Gambit",
"es-ES": "Acelerón de salida",
"es-MX": "Acelerón de salida",
"fr-CA": "Départ toute allure",
"fr-FR": "Chapeaux de roue",
"it-IT": "Partenza a razzo",
"ja-JP": "スタートダッシュ",
"ko-KR": "스타트 대시",
"nl-NL": "Vliegende start",
"ru-RU": "Стартовый спурт",
"zh-CN": "最初冲刺",
"zh-TW": "最初衝刺"
},
"primary_only": true
},
{
"key": "last_ditch_effort",
"name": {
"de-DE": "Endspurt",
"en-GB": "Last-Ditch Effort",
"en-US": "Last-Ditch Effort",
"es-ES": "Sprint final",
"es-MX": "Último recurso",
"fr-CA": "Ultime sursaut",
"fr-FR": "Ultime sursaut",
"it-IT": "Splash finale",
"ja-JP": "ラストスパート",
"ko-KR": "라스트 스퍼트",
"nl-NL": "Eindsprint",
"ru-RU": "Финишный спурт",
"zh-CN": "最后冲刺",
"zh-TW": "最後衝刺"
},
"primary_only": true
},
{
"key": "tenacity",
"name": {
"de-DE": "Zähigkeit",
"en-GB": "Tenacity",
"en-US": "Tenacity",
"es-ES": "Ventaja",
"es-MX": "Tenacidad",
"fr-CA": "Ténacité",
"fr-FR": "Justice",
"it-IT": "Tenacia",
"ja-JP": "逆境強化",
"ko-KR": "역경 강화",
"nl-NL": "Volharding",
"ru-RU": "Компенсатор",
"zh-CN": "逆境强化",
"zh-TW": "逆境強化"
},
"primary_only": true
},
{
"key": "comeback",
"name": {
"de-DE": "Rückkehr",
"en-GB": "Comeback",
"en-US": "Comeback",
"es-ES": "Remontada",
"es-MX": "Remonte",
"fr-CA": "Retour",
"fr-FR": "Come-back",
"it-IT": "Gran ritorno",
"ja-JP": "カムバック",
"ko-KR": "컴백",
"nl-NL": "Opfrisser",
"ru-RU": "Ответный удар",
"zh-CN": "回归",
"zh-TW": "回歸"
},
"primary_only": true
},
{
"key": "ninja_squid",
"name": {
"de-DE": "Tintenfisch-Ninja",
"en-GB": "Ninja Squid",
"en-US": "Ninja Squid",
"es-ES": "Ninjalamar",
"es-MX": "Ninjalamar",
"fr-CA": "Ninjalmar",
"fr-FR": "Ninjalamar",
"it-IT": "Calamaro ninja",
"ja-JP": "イカニンジャ",
"ko-KR": "징어닌자",
"nl-NL": "Ninja-inktvis",
"ru-RU": "Мимикрия",
"zh-CN": "鱿鱼忍者",
"zh-TW": "魷魚忍者"
},
"primary_only": true
},
{
"key": "haunt",
"name": {
"de-DE": "Vergeltung",
"en-GB": "Haunt",
"en-US": "Haunt",
"es-ES": "Represalia",
"es-MX": "Resentimiento",
"fr-CA": "Vengeance",
"fr-FR": "Revanche",
"it-IT": "Rappresaglia",
"ja-JP": "リベンジ",
"ko-KR": "리벤지",
"nl-NL": "Revanche",
"ru-RU": "Вендетта",
"zh-CN": "复仇",
"zh-TW": "復仇"
},
"primary_only": true
},
{
"key": "thermal_ink",
"name": {
"de-DE": "Markierfarbe",
"en-GB": "Thermal Ink",
"en-US": "Thermal Ink",
"es-ES": "Señuelo",
"es-MX": "Tinta rastreadora",
"fr-CA": "Encre thermique",
"fr-FR": "Encre thermique",
"it-IT": "Inchiostro termico",
"ja-JP": "サーマルインク",
"ko-KR": "서멀 잉크",
"nl-NL": "Markeerstift",
"ru-RU": "Клеймо",
"zh-CN": "热力墨汁",
"zh-TW": "熱力墨汁"
},
"primary_only": true
},
{
"key": "respawn_punisher",
"name": {
"de-DE": "Heimsuchung",
"en-GB": "Respawn Punisher",
"en-US": "Respawn Punisher",
"es-ES": "Castigo póstumo",
"es-MX": "Castigo póstumo",
"fr-CA": "Retour perdant",
"fr-FR": "Retour perdant",
"it-IT": "Castigo",
"ja-JP": "復活ペナルティアップ",
"ko-KR": "부활 페널티 업",
"nl-NL": "Repercussie",
"ru-RU": "Кара",
"zh-CN": "提升复活惩罚",
"zh-TW": "提升復活懲罰"
},
"primary_only": true
},
{
"key": "ability_doubler",
"name": {
"de-DE": "Effektdoppelung",
"en-GB": "Ability Doubler",
"en-US": "Ability Doubler",
"es-ES": "Duplicador",
"es-MX": "Duplicador",
"fr-CA": "Bonus ×2",
"fr-FR": "Bonus ×2",
"it-IT": "Raddoppiatore",
"ja-JP": "追加ギアパワー倍化",
"ko-KR": "추가 기어 파워 2배",
"nl-NL": "Verdubbelaar",
"ru-RU": "Дупликатор",
"zh-CN": "追加装备能力增倍",
"zh-TW": "追加裝備能力增倍"
},
"primary_only": true
},
{
"key": "stealth_jump",
"name": {
"de-DE": "Sprunginfiltration",
"en-GB": "Stealth Jump",
"en-US": "Stealth Jump",
"es-ES": "Supersalto invisible",
"es-MX": "Supersalto invisible",
"fr-CA": "Super saut invisible",
"fr-FR": "Réception réussie",
"it-IT": "Salto al buio",
"ja-JP": "ステルスジャンプ",
"ko-KR": "스텔스 점프",
"nl-NL": "Sluipsprong",
"ru-RU": "Десант",
"zh-CN": "隐身跳跃",
"zh-TW": "隱身跳躍"
},
"primary_only": true
},
{
"key": "object_shredder",
"name": {
"de-DE": "Zerstörer",
"en-GB": "Object Shredder",
"en-US": "Object Shredder",
"es-ES": "Demolición",
"es-MX": "Demolición",
"fr-CA": "Démolition",
"fr-FR": "Démolition",
"it-IT": "Demolitore",
"ja-JP": "対物攻撃力アップ",
"ko-KR": "오브젝트 공격력 업",
"nl-NL": "Sloper",
"ru-RU": "Демонтажник",
"zh-CN": "提升对物体攻击力",
"zh-TW": "提升對物體攻擊力"
},
"primary_only": true
},
{
"key": "drop_roller",
"name": {
"de-DE": "Tricklandung",
"en-GB": "Drop Roller",
"en-US": "Drop Roller",
"es-ES": "Amortiguador",
"es-MX": "Aterrizaje rodante",
"fr-CA": "Super roulade",
"fr-FR": "Super roulade",
"it-IT": "Atterraggio stiloso",
"ja-JP": "受け身術",
"ko-KR": "낙법",
"nl-NL": "Rolmodel",
"ru-RU": "Акробат",
"zh-CN": "受身术",
"zh-TW": "受身術"
},
"primary_only": true
}
]

View File

@ -2,27 +2,10 @@ import type { StatInkPostBody, VsHistoryDetail } from "./types.ts";
export const AGENT_NAME = "splashcat / s3si.ts";
export const AGENT_VERSION = "1.1.1";
export const S3SI_VERSION = "0.4.1";
export const S3SI_VERSION = "0.3.2";
export const COMBINED_VERSION = `${AGENT_VERSION}/${S3SI_VERSION}`;
export const NSOAPP_VERSION = "2.5.1";
export const WEB_VIEW_VERSION = "4.0.0-d5178440";
export enum Queries {
HomeQuery = "7dcc64ea27a08e70919893a0d3f70871",
LatestBattleHistoriesQuery = "0d90c7576f1916469b2ae69f64292c02",
RegularBattleHistoriesQuery = "3baef04b095ad8975ea679d722bc17de",
BankaraBattleHistoriesQuery = "0438ea6978ae8bd77c5d1250f4f84803",
XBattleHistoriesQuery = "6796e3cd5dc3ebd51864dc709d899fc5",
PrivateBattleHistoriesQuery = "8e5ae78b194264a6c230e262d069bd28",
VsHistoryDetailQuery = "9ee0099fbe3d8db2a838a75cf42856dd",
CoopHistoryQuery = "91b917becd2fa415890f5b47e15ffb15",
CoopHistoryDetailQuery = "379f0d9b78b531be53044bcac031b34b",
myOutfitCommonDataFilteringConditionQuery =
"d02ab22c9dccc440076055c8baa0fa7a",
myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8",
HistoryRecordQuery = "d9246baf077b2a29b5f7aac321810a77",
ConfigureAnalyticsQuery = "f8ae00773cc412a50dd41a6d9a159ddd",
StageRecordQuery = "f08a932d533845dde86e674e03bbb7d3",
}
export const NSOAPP_VERSION = "2.5.0";
export const WEB_VIEW_VERSION = "3.0.0-0742bda0";
export const S3SI_LINK = "https://forgejo.catgirlin.space/catgirl/s3si.ts";
export const USERAGENT = `${AGENT_NAME}/(${COMBINED_VERSION}) (${S3SI_LINK})`;

View File

@ -113,9 +113,8 @@ export class MongoDBExporter implements GameExporter {
};
}
async exportStages(
stages: RespMap[Queries.StageRecordQuery]["stageRecords"]["nodes"],
): Promise<ExportResult> {
async exportStages(stages: RespMap[Queries.StageRecordQuery]["stageRecords"]["nodes"]): Promise<ExportResult> {
for (const stage of stages) {
await this.mongoDb.collection("stages").updateOne({
"stage.id": stage.id,
@ -128,6 +127,6 @@ export class MongoDBExporter implements GameExporter {
return {
status: "success",
};
}
}
}

View File

@ -15,6 +15,7 @@ import {
GameExporter,
Image,
PlayerGear,
StatInkAbility,
StatInkCoopPlayer,
StatInkCoopPostBody,
StatInkCoopWave,
@ -41,7 +42,6 @@ import {
urlSimplify,
} from "../utils.ts";
import { Env } from "../env.ts";
import GEAR_MAP from "../assets/gear-map.json" assert { type: "json" };
const COOP_POINT_MAP: Record<number, number | undefined> = {
0: -20,
@ -229,7 +229,8 @@ class StatInkAPI {
);
getWeapon = () =>
this._getCached<StatInkWeapon>(`${this.statInk}/api/v3/weapon?full=1`);
getAbility = () => GEAR_MAP;
getAbility = () =>
this._getCached<StatInkAbility>(`${this.statInk}/api/v3/ability?full=1`);
getStage = () =>
this._getCached<StatInkStage>(`${this.statInk}/api/v3/stage`);
}
@ -330,8 +331,6 @@ export class StatInkExporter implements GameExporter {
}
} else if (vsMode === "X_MATCH") {
return "xmatch";
} else if (vsMode === "LEAGUE") {
return "event";
}
throw new TypeError(`Unknown vsMode ${vsMode}`);
@ -423,7 +422,6 @@ export class StatInkExporter implements GameExporter {
myTeam,
otherTeams,
bankaraMatch,
leagueMatch,
festMatch,
playedTime,
} = vsDetail;
@ -566,10 +564,6 @@ export class StatInkExporter implements GameExporter {
result.rank_after_s_plus = result.rank_before_s_plus;
}
}
if (leagueMatch) {
result.event = leagueMatch.leagueMatchEvent?.id;
result.event_power = leagueMatch.myLeaguePower;
}
if (challengeProgress) {
result.challenge_win = challengeProgress.winCount;
@ -730,8 +724,6 @@ export class StatInkExporter implements GameExporter {
golden_appearances: wave.goldenPopCount,
golden_delivered: wave.teamDeliverCount,
special_uses,
// fill it later
danger_rate: null,
};
}
async mapCoop(
@ -775,13 +767,10 @@ export class StatInkExporter implements GameExporter {
: undefined;
const title_exp_after = detail.afterGradePoint;
const maxWaves = detail.rule === "TEAM_CONTEST" ? 5 : 3;
let clear_waves: number;
if (waveResults.length > 0) {
// when cleared, resultWave === 0, so we need to add 1.
clear_waves = waveResults.filter((i) =>
i.waveNumber < maxWaves + 1
).length -
clear_waves = waveResults.filter((i) => i.waveNumber < 4).length -
1 + (resultWave === 0 ? 1 : 0);
} else {
clear_waves = 0;
@ -822,7 +811,7 @@ export class StatInkExporter implements GameExporter {
let fail_reason: StatInkCoopPostBody["fail_reason"] = null;
// failed
if (clear_waves !== maxWaves && waveResults.length > 0) {
if (clear_waves !== 3 && waveResults.length > 0) {
const lastWave = waveResults[waveResults.length - 1];
if (lastWave.teamDeliverCount >= lastWave.deliverNorm) {
fail_reason = "wipe_out";
@ -833,9 +822,8 @@ export class StatInkExporter implements GameExporter {
uuid: await gameId(detail.id),
private: groupInfo?.mode === "PRIVATE_CUSTOM" ? "yes" : "no",
big_run: detail.rule === "BIG_RUN" ? "yes" : "no",
eggstra_work: detail.rule === "TEAM_CONTEST" ? "yes" : "no",
stage: b64Number(detail.coopStage.id).toString(),
danger_rate: detail.rule === "TEAM_CONTEST" ? null : dangerRate * 100,
danger_rate: dangerRate * 100,
clear_waves,
fail_reason,
king_smell: smellMeter,
@ -868,57 +856,6 @@ export class StatInkExporter implements GameExporter {
automated: "yes",
start_at: startedAt,
};
// caculate wave danger_rate.
// translated from here: https://github.com/frozenpandaman/s3s/commit/d46ece00e5a7706688eaf025f18c5a8ea1c54c0f#diff-819571ec7b067d2398cd1f9dbc737160312efc4128ba4a2f0e165c70225dea0eR1050
if (detail.rule === "TEAM_CONTEST") {
let lastWave: StatInkCoopWave | undefined;
for (
const [wave] of result.waves
.map((p, i) => [p, i] as const)
) {
let haz_level: number;
if (!lastWave) {
haz_level = 60;
} else {
const num_players = result.players.length;
const quota = lastWave.golden_quota; // last wave, most recent one added to the list
const delivered = lastWave.golden_delivered;
let added_percent = 0; // default, no increase if less than 1.5x quota delivered
if (num_players == 4) {
if (delivered >= quota * 2) {
added_percent = 60;
} else if (delivered >= quota * 1.5) {
added_percent = 30;
}
} else if (num_players == 3) {
if (delivered >= quota * 2) {
added_percent = 40;
} else if (delivered >= quota * 1.5) {
added_percent = 20;
}
} else if (num_players == 2) {
if (delivered >= quota * 2) {
added_percent = 20;
} else if (delivered >= quota * 1.5) {
added_percent = 10;
added_percent = 5;
}
} else if (num_players == 1) {
if (delivered >= quota * 2) {
added_percent = 10;
} else if (delivered >= quota * 1.5) {
added_percent = 5;
}
}
const prev_percent = lastWave.danger_rate!;
haz_level = prev_percent + added_percent;
}
wave.danger_rate = haz_level;
lastWave = wave;
}
}
return result;
}
}

View File

@ -175,14 +175,13 @@ export async function getGToken(
},
);
const uiRespJson = await uiResp.json();
const { nickname, birthday, language, country, id: userId } = uiRespJson;
const { nickname, birthday, language, country } = uiRespJson;
const getIdToken2 = async (idToken: string) => {
const { f, request_id: requestId, timestamp } = await callImink({
fApi,
step: 1,
idToken,
userId,
env,
});
const resp = await fetch.post(
@ -211,28 +210,23 @@ export async function getGToken(
);
const respJson = await resp.json();
const idToken2: string = respJson?.result?.webApiServerCredential
?.accessToken;
const coralUserId: number = respJson?.result?.user?.id;
const idToken2 = respJson?.result?.webApiServerCredential?.accessToken;
if (!idToken2 || !coralUserId) {
if (!idToken2) {
throw new APIError({
response: resp,
json: respJson,
message:
`No idToken2 or coralUserId found. Please try again later. ('${idToken2}', '${coralUserId}')`,
message: "No idToken2 found",
});
}
return [idToken2, coralUserId] as const;
return idToken2 as string;
};
const getGToken = async (idToken: string, coralUserId: number) => {
const getGToken = async (idToken: string) => {
const { f, request_id: requestId, timestamp } = await callImink({
step: 2,
idToken,
fApi,
userId,
coralUserId,
env,
});
const resp = await fetch.post(
@ -272,8 +266,8 @@ export async function getGToken(
return webServiceToken as string;
};
const [idToken2, coralUserId] = await retry(() => getIdToken2(idToken));
const webServiceToken = await retry(() => getGToken(idToken2, coralUserId));
const idToken2 = await retry(() => getIdToken2(idToken));
const webServiceToken = await retry(() => getGToken(idToken2));
return {
webServiceToken,
@ -409,16 +403,13 @@ type IminkResponse = {
timestamp: number;
};
async function callImink(
params: {
{ fApi, step, idToken, env }: {
fApi: string;
step: number;
idToken: string;
userId: string;
coralUserId?: number;
env: Env;
},
): Promise<IminkResponse> {
const { fApi, step, idToken, userId, coralUserId, env } = params;
const { post } = env.newFetcher();
const resp = await post({
url: fApi,
@ -429,8 +420,6 @@ async function callImink(
body: JSON.stringify({
"token": idToken,
"hash_method": step,
"na_id": userId,
"coral_user_id": coralUserId,
}),
});

View File

@ -31,7 +31,6 @@ export type State = {
fileExportPath: string;
monitorInterval: number;
mongoDbUri?: string;
splashcatApiKey?: string;
};
export const DEFAULT_STATE: State = {

View File

@ -1,8 +1,23 @@
import { splatNet3Types } from "../deps.ts";
import { RankState } from "./state.ts";
import { Queries } from "./constant.ts";
export { Queries };
export enum Queries {
HomeQuery = "22e2fa8294168003c21b00c333c35384",
LatestBattleHistoriesQuery = "0176a47218d830ee447e10af4a287b3f",
RegularBattleHistoriesQuery = "3baef04b095ad8975ea679d722bc17de",
BankaraBattleHistoriesQuery = "0438ea6978ae8bd77c5d1250f4f84803",
XBattleHistoriesQuery = "6796e3cd5dc3ebd51864dc709d899fc5",
PrivateBattleHistoriesQuery = "8e5ae78b194264a6c230e262d069bd28",
VsHistoryDetailQuery = "291295ad311b99a6288fc95a5c4cb2d2",
CoopHistoryQuery = "91b917becd2fa415890f5b47e15ffb15",
CoopHistoryDetailQuery = "379f0d9b78b531be53044bcac031b34b",
myOutfitCommonDataFilteringConditionQuery =
"d02ab22c9dccc440076055c8baa0fa7a",
myOutfitCommonDataEquipmentsQuery = "d29cd0c2b5e6bac90dd5b817914832f8",
HistoryRecordQuery = "f09da9d24d888797fdfb2f060dbdf4ed",
ConfigureAnalyticsQuery = "f8ae00773cc412a50dd41a6d9a159ddd",
StageRecordQuery = "f08a932d533845dde86e674e03bbb7d3",
}
export type VarsMap = {
[Queries.HomeQuery]: [];
[Queries.LatestBattleHistoriesQuery]: [];
@ -206,13 +221,7 @@ export type CoopInfo = {
};
};
export type Game = VsInfo | CoopInfo;
export type VsMode =
| "REGULAR"
| "BANKARA"
| "PRIVATE"
| "FEST"
| "X_MATCH"
| "LEAGUE";
export type VsMode = "REGULAR" | "BANKARA" | "PRIVATE" | "FEST" | "X_MATCH";
export type VsHistoryDetail = {
id: string;
vsRule: {
@ -243,13 +252,6 @@ export type VsHistoryDetail = {
contribution: number;
myFestPower: number | null;
} | null;
leagueMatch: {
leagueMatchEvent: {
"name": string;
"id": string;
} | null;
myLeaguePower: number | null;
} | null;
myTeam: VsTeam;
otherTeams: VsTeam[];
@ -288,7 +290,7 @@ export type CoopHistoryDetail = {
name: string;
id: string;
};
rule: "REGULAR" | "BIG_RUN" | "TEAM_CONTEST";
rule: "REGULAR" | "BIG_RUN";
myResult: CoopHistoryPlayerResult;
memberResults: CoopHistoryPlayerResult[];
bossResult: null | {
@ -679,8 +681,6 @@ export type StatInkCoopWave = {
golden_delivered: number;
golden_appearances: number;
special_uses?: Record<string, number>;
// [0, 333]
danger_rate: number | null;
};
export type StatInkCoopPlayer = {
@ -719,10 +719,9 @@ export type StatInkCoopPostBody = {
uuid: string;
private: "yes" | "no";
big_run: "yes" | "no";
eggstra_work: "yes" | "no";
stage: string;
// [0, 333]
danger_rate: number | null;
danger_rate: number;
// [0, 3]
clear_waves: number;
fail_reason?: null | "wipe_out" | "time_limit";
@ -768,13 +767,12 @@ export type StatInkPostBody = {
| "xmatch"
| "splatfest_challenge"
| "splatfest_open"
| "private"
| "event";
| "private";
rule: "nawabari" | "area" | "hoko" | "yagura" | "asari" | "tricolor";
stage: string;
weapon: string;
result: "win" | "lose" | "draw" | "exempted_lose";
knockout?: "yes" | "no" | null; // for TW, set null or not sending
knockout?: "yes" | "no"; // for TW, set null or not sending
rank_in_team: number; // position in scoreboard
kill?: number;
assist?: number;
@ -826,8 +824,6 @@ export type StatInkPostBody = {
clout_before?: number; // Splatfest Clout, before the battle
clout_after?: number; // Splatfest Clout, after the battle
clout_change?: number; // Splatfest Clout, equals to clout_after - clout_before if you know them
event?: string;
event_power?: number | null;
cash_before?: number;
cash_after?: number;
our_team_players: StatInkPlayer[];