Merge remote-tracking branch 'upstream/main' into worldstate

This commit is contained in:
dutlist 2024-06-20 21:36:25 +02:00
commit 9cc17c2a66
42 changed files with 775 additions and 492 deletions

467
package-lock.json generated
View File

@ -22,8 +22,8 @@
"@tsconfig/node20": "^1.0.0", "@tsconfig/node20": "^1.0.0",
"@types/express": "^4.17.20", "@types/express": "^4.17.20",
"@types/morgan": "^1.9.7", "@types/morgan": "^1.9.7",
"@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^6.2.0", "@typescript-eslint/parser": "^7.13.1",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"morgan": "^1.10.0", "morgan": "^1.10.0",
@ -364,12 +364,6 @@
"@types/send": "*" "@types/send": "*"
} }
}, },
"node_modules/@types/json-schema": {
"version": "7.0.14",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz",
"integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==",
"dev": true
},
"node_modules/@types/mime": { "node_modules/@types/mime": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
@ -403,12 +397,6 @@
"integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
"dev": true "dev": true
}, },
"node_modules/@types/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==",
"dev": true
},
"node_modules/@types/send": { "node_modules/@types/send": {
"version": "0.17.1", "version": "0.17.1",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz",
@ -460,33 +448,31 @@
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.9.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz",
"integrity": "sha512-lgX7F0azQwRPB7t7WAyeHWVfW1YJ9NIgd9mvGhfQpRY56X6AVf8mwM8Wol+0z4liE7XX3QOt8MN1rUKCfSjRIA==", "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.5.1", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "6.9.0", "@typescript-eslint/scope-manager": "7.13.1",
"@typescript-eslint/type-utils": "6.9.0", "@typescript-eslint/type-utils": "7.13.1",
"@typescript-eslint/utils": "6.9.0", "@typescript-eslint/utils": "7.13.1",
"@typescript-eslint/visitor-keys": "6.9.0", "@typescript-eslint/visitor-keys": "7.13.1",
"debug": "^4.3.4",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^5.2.4", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"semver": "^7.5.4", "ts-api-utils": "^1.3.0"
"ts-api-utils": "^1.0.1"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", "@typescript-eslint/parser": "^7.0.0",
"eslint": "^7.0.0 || ^8.0.0" "eslint": "^8.56.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"typescript": { "typescript": {
@ -494,97 +480,27 @@
} }
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz",
"integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"@typescript-eslint/visitor-keys": "6.9.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz",
"integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz",
"integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "6.2.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.2.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz",
"integrity": "sha512-igVYOqtiK/UsvKAmmloQAruAdUHihsOCvplJpplPZ+3h4aDkC/UKZZNKgB6h93ayuYLuEymU3h8nF1xMRbh37g==", "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "6.2.0", "@typescript-eslint/scope-manager": "7.13.1",
"@typescript-eslint/types": "6.2.0", "@typescript-eslint/types": "7.13.1",
"@typescript-eslint/typescript-estree": "6.2.0", "@typescript-eslint/typescript-estree": "7.13.1",
"@typescript-eslint/visitor-keys": "6.2.0", "@typescript-eslint/visitor-keys": "7.13.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0" "eslint": "^8.56.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"typescript": { "typescript": {
@ -593,9 +509,9 @@
} }
}, },
"node_modules/@typescript-eslint/parser/node_modules/debug": { "node_modules/@typescript-eslint/parser/node_modules/debug": {
"version": "4.3.4", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
@ -616,16 +532,16 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "6.2.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.2.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz",
"integrity": "sha512-1ZMNVgm5nnHURU8ZSJ3snsHzpFeNK84rdZjluEVBGNu7jDymfqceB3kdIZ6A4xCfEFFhRIB6rF8q/JIqJd2R0Q==", "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.2.0", "@typescript-eslint/types": "7.13.1",
"@typescript-eslint/visitor-keys": "6.2.0" "@typescript-eslint/visitor-keys": "7.13.1"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -633,25 +549,25 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "6.9.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz",
"integrity": "sha512-XXeahmfbpuhVbhSOROIzJ+b13krFmgtc4GlEuu1WBT+RpyGPIA4Y/eGnXzjbDj5gZLzpAXO/sj+IF/x2GtTMjQ==", "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "6.9.0", "@typescript-eslint/typescript-estree": "7.13.1",
"@typescript-eslint/utils": "6.9.0", "@typescript-eslint/utils": "7.13.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^1.0.1" "ts-api-utils": "^1.3.0"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0" "eslint": "^8.56.0"
}, },
"peerDependenciesMeta": { "peerDependenciesMeta": {
"typescript": { "typescript": {
@ -659,67 +575,10 @@
} }
} }
}, },
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz",
"integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz",
"integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"@typescript-eslint/visitor-keys": "6.9.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz",
"integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/type-utils/node_modules/debug": { "node_modules/@typescript-eslint/type-utils/node_modules/debug": {
"version": "4.3.4", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
@ -740,12 +599,12 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "6.2.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.2.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz",
"integrity": "sha512-1nRRaDlp/XYJQLvkQJG5F3uBTno5SHPT7XVcJ5n1/k2WfNI28nJsvLakxwZRNY5spuatEKO7d5nZWsQpkqXwBA==", "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -753,21 +612,22 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "6.2.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.2.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz",
"integrity": "sha512-Mts6+3HQMSM+LZCglsc2yMIny37IhUgp1Qe8yJUYVyO6rHP7/vN0vajKu3JvHCBIy8TSiKddJ/Zwu80jhnGj1w==", "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.2.0", "@typescript-eslint/types": "7.13.1",
"@typescript-eslint/visitor-keys": "6.2.0", "@typescript-eslint/visitor-keys": "7.13.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"globby": "^11.1.0", "globby": "^11.1.0",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"semver": "^7.5.4", "minimatch": "^9.0.4",
"ts-api-utils": "^1.0.1" "semver": "^7.6.0",
"ts-api-utils": "^1.3.0"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -779,10 +639,19 @@
} }
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
"version": "4.3.4", "version": "4.3.5",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
@ -796,6 +665,21 @@
} }
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@ -803,138 +687,38 @@
"dev": true "dev": true
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "6.9.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.9.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz",
"integrity": "sha512-5Wf+Jsqya7WcCO8me504FBigeQKVLAMPmUzYgDbWchINNh1KJbxCgVya3EQ2MjvJMVeXl3pofRmprqX6mfQkjQ==", "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.4.0", "@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12", "@typescript-eslint/scope-manager": "7.13.1",
"@types/semver": "^7.5.0", "@typescript-eslint/types": "7.13.1",
"@typescript-eslint/scope-manager": "6.9.0", "@typescript-eslint/typescript-estree": "7.13.1"
"@typescript-eslint/types": "6.9.0",
"@typescript-eslint/typescript-estree": "6.9.0",
"semver": "^7.5.4"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
"url": "https://opencollective.com/typescript-eslint" "url": "https://opencollective.com/typescript-eslint"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": "^7.0.0 || ^8.0.0" "eslint": "^8.56.0"
} }
}, },
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.9.0.tgz",
"integrity": "sha512-1R8A9Mc39n4pCCz9o79qRO31HGNDvC7UhPhv26TovDsWPBDx+Sg3rOZdCELIA3ZmNoWAuxaMOT7aWtGRSYkQxw==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"@typescript-eslint/visitor-keys": "6.9.0"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.9.0.tgz",
"integrity": "sha512-+KB0lbkpxBkBSiVCuQvduqMJy+I1FyDbdwSpM3IoBS7APl4Bu15lStPjgBIdykdRqQNYqYNMa8Kuidax6phaEw==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.9.0.tgz",
"integrity": "sha512-NJM2BnJFZBEAbCfBP00zONKXvMqihZCrmwCaik0UhLr0vAgb6oguXxLX1k00oQyD+vZZ+CJn3kocvv2yxm4awQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"@typescript-eslint/visitor-keys": "6.9.0",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
"semver": "^7.5.4",
"ts-api-utils": "^1.0.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "6.9.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.9.0.tgz",
"integrity": "sha512-dGtAfqjV6RFOtIP8I0B4ZTBRrlTT8NHHlZZSchQx3qReaoDeXhYM++M4So2AgFK9ZB0emRPA6JI1HkafzA2Ibg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "6.9.0",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/utils/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/utils/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "6.2.0", "version": "7.13.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.2.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz",
"integrity": "sha512-QbaYUQVKKo9bgCzpjz45llCfwakyoxHetIy8CAvYCtd16Zu1KrpzNHofwF8kGkpPOxZB2o6kz+0nqH8ZkIzuoQ==", "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@typescript-eslint/types": "6.2.0", "@typescript-eslint/types": "7.13.1",
"eslint-visitor-keys": "^3.4.1" "eslint-visitor-keys": "^3.4.3"
}, },
"engines": { "engines": {
"node": "^16.0.0 || >=18.0.0" "node": "^18.18.0 || >=20.0.0"
}, },
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -1848,9 +1632,9 @@
"dev": true "dev": true
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.1", "version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
"integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -2245,9 +2029,9 @@
} }
}, },
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.2.4", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 4" "node": ">= 4"
@ -2496,18 +2280,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/make-error": { "node_modules/make-error": {
"version": "1.3.6", "version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
@ -2550,12 +2322,12 @@
} }
}, },
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.7",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"braces": "^3.0.2", "braces": "^3.0.3",
"picomatch": "^2.3.1" "picomatch": "^2.3.1"
}, },
"engines": { "engines": {
@ -3261,13 +3033,10 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "7.5.4", "version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"dev": true, "dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": { "bin": {
"semver": "bin/semver.js" "semver": "bin/semver.js"
}, },
@ -3658,12 +3427,12 @@
} }
}, },
"node_modules/ts-api-utils": { "node_modules/ts-api-utils": {
"version": "1.0.1", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.1.tgz", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz",
"integrity": "sha512-lC/RGlPmwdrIBFTX59wwNzqh7aR2otPNPR/5brHZm/XKFYKsfqxihXUe9pU3JI+3vGkl+vyCoNNnPhJn3aLK1A==", "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=16.13.0" "node": ">=16"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": ">=4.2.0" "typescript": ">=4.2.0"
@ -4061,12 +3830,6 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/yargs": { "node_modules/yargs": {
"version": "16.2.0", "version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",

View File

@ -26,8 +26,8 @@
"@tsconfig/node20": "^1.0.0", "@tsconfig/node20": "^1.0.0",
"@types/express": "^4.17.20", "@types/express": "^4.17.20",
"@types/morgan": "^1.9.7", "@types/morgan": "^1.9.7",
"@typescript-eslint/eslint-plugin": "^6.9.0", "@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^6.2.0", "@typescript-eslint/parser": "^7.13.1",
"eslint": "^8.56.0", "eslint": "^8.56.0",
"eslint-plugin-prettier": "^5.1.3", "eslint-plugin-prettier": "^5.1.3",
"morgan": "^1.10.0", "morgan": "^1.10.0",

View File

@ -4,6 +4,7 @@ import { IUpdateGlyphRequest } from "@/src/types/requestTypes";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService"; import { getInventory } from "@/src/services/inventoryService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const addFriendImageController: RequestHandler = async (req, res) => { const addFriendImageController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const json = getJSONfromString(req.body.toString()) as IUpdateGlyphRequest; const json = getJSONfromString(req.body.toString()) as IUpdateGlyphRequest;

View File

@ -5,6 +5,7 @@ import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
import { Guild } from "@/src/models/guildModel"; import { Guild } from "@/src/models/guildModel";
import { ICreateGuildRequest } from "@/src/types/guildTypes"; import { ICreateGuildRequest } from "@/src/types/guildTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const createGuildController: RequestHandler = async (req, res) => { const createGuildController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const payload: ICreateGuildRequest = getJSONfromString(req.body.toString()); const payload: ICreateGuildRequest = getJSONfromString(req.body.toString());

View File

@ -0,0 +1,42 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { WeaponTypeInternal } from "@/src/services/itemDataService";
import { EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const evolveWeaponController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId);
const payload = getJSONfromString(req.body.toString()) as IEvolveWeaponRequest;
console.assert(payload.Action == "EWA_INSTALL");
// TODO: We should remove the Genesis item & its resources, but currently we don't know these "recipes".
const item = inventory[payload.Category].find(item => item._id.toString() == (req.query.ItemId as string))!;
item.Features ??= 0;
item.Features |= EquipmentFeatures.INCARNON_GENESIS;
item.SkillTree = "0";
inventory.EvolutionProgress ??= [];
if (!inventory.EvolutionProgress.find(entry => entry.ItemType == payload.EvoType)) {
inventory.EvolutionProgress.push({
Progress: 0,
Rank: 1,
ItemType: payload.EvoType
});
}
await inventory.save();
res.end();
};
interface IEvolveWeaponRequest {
Action: "EWA_INSTALL";
Category: WeaponTypeInternal;
Recipe: string; // e.g. "/Lotus/Types/Items/MiscItems/IncarnonAdapters/UnlockerBlueprints/DespairIncarnonBlueprint"
UninstallRecipe: "";
EvoType: string; // e.g. "/Lotus/Weapons/Tenno/ThrowingWeapons/StalkerKunai"
}

View File

@ -5,6 +5,7 @@ import { IMiscItem, TFocusPolarity } from "@/src/types/inventoryTypes/inventoryT
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import baseFocusPointCosts from "@/static/json/baseFocusPointCosts.json"; import baseFocusPointCosts from "@/static/json/baseFocusPointCosts.json";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const focusController: RequestHandler = async (req, res) => { export const focusController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
switch (req.query.op) { switch (req.query.op) {

View File

@ -4,6 +4,7 @@ import { Guild } from "@/src/models/guildModel";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { toOid } from "@/src/helpers/inventoryHelpers"; import { toOid } from "@/src/helpers/inventoryHelpers";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const getGuildController: RequestHandler = async (req, res) => { const getGuildController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await Inventory.findOne({ accountOwnerId: accountId }); const inventory = await Inventory.findOne({ accountOwnerId: accountId });

View File

@ -4,6 +4,7 @@ import { Guild } from "@/src/models/guildModel";
import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes"; import { IDojoClient, IDojoComponentClient } from "@/src/types/guildTypes";
import { toOid, toMongoDate } from "@/src/helpers/inventoryHelpers"; import { toOid, toMongoDate } from "@/src/helpers/inventoryHelpers";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const getGuildDojoController: RequestHandler = async (req, res) => { export const getGuildDojoController: RequestHandler = async (req, res) => {
const guildId = req.query.guildId as string; const guildId = req.query.guildId as string;

View File

@ -0,0 +1,7 @@
import { RequestHandler } from "express";
import getVendorInfoResponse from "@/static/fixed_responses/getVendorInfo.json";
export const getVendorInfoController: RequestHandler = (req, res) => {
console.assert(req.query.vendor == "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest");
res.json(getVendorInfoResponse);
};

View File

@ -4,6 +4,7 @@ import { createNewSession } from "@/src/managers/sessionManager";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { ISession } from "@/src/types/session"; import { ISession } from "@/src/types/session";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const hostSessionController: RequestHandler = async (req, res) => { const hostSessionController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const hostSessionRequest = JSON.parse(req.body as string) as ISession; const hostSessionRequest = JSON.parse(req.body as string) as ISession;

View File

@ -4,6 +4,7 @@ import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { getInventory, addMiscItems } from "@/src/services/inventoryService"; import { getInventory, addMiscItems } from "@/src/services/inventoryService";
import { IOid } from "@/src/types/commonTypes"; import { IOid } from "@/src/types/commonTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const infestedFoundryController: RequestHandler = async (req, res) => { export const infestedFoundryController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const payload = getJSONfromString(req.body.toString()); const payload = getJSONfromString(req.body.toString());

View File

@ -1,15 +1,15 @@
/* eslint-disable @typescript-eslint/no-misused-promises */ import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { toInventoryResponse } from "@/src/helpers/inventoryHelpers"; import { toInventoryResponse } from "@/src/helpers/inventoryHelpers";
import { Inventory } from "@/src/models/inventoryModels/inventoryModel"; import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
import { Request, RequestHandler, Response } from "express";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import allMissions from "@/static/fixed_responses/allMissions.json"; import allMissions from "@/static/fixed_responses/allMissions.json";
import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes"; import { ILoadoutDatabase } from "@/src/types/saveLoadoutTypes";
import { IShipInventory } from "@/src/types/inventoryTypes/inventoryTypes"; import { IShipInventory } from "@/src/types/inventoryTypes/inventoryTypes";
import { ExportCustoms, ExportFlavour, ExportKeys, ExportResources } from "warframe-public-export-plus"; import { ExportCustoms, ExportFlavour, ExportKeys, ExportResources } from "warframe-public-export-plus";
const inventoryController: RequestHandler = async (request: Request, response: Response) => { // eslint-disable-next-line @typescript-eslint/no-misused-promises
const inventoryController: RequestHandler = async (request, response) => {
let accountId; let accountId;
try { try {
accountId = await getAccountIdForRequest(request); accountId = await getAccountIdForRequest(request);

View File

@ -2,6 +2,7 @@ import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { Account } from "@/src/models/loginModel"; import { Account } from "@/src/models/loginModel";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const logoutController: RequestHandler = async (req, res) => { const logoutController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const account = await Account.findOne({ _id: accountId }); const account = await Account.findOne({ _id: accountId });

View File

@ -18,6 +18,7 @@ interface IModularCraftRequest {
Parts: string[]; Parts: string[];
} }
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const modularWeaponCraftingController: RequestHandler = async (req, res) => { export const modularWeaponCraftingController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const data: IModularCraftRequest = getJSONfromString(req.body.toString()); const data: IModularCraftRequest = getJSONfromString(req.body.toString());

View File

@ -8,6 +8,7 @@ interface INameWeaponRequest {
ItemName: string; ItemName: string;
} }
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const nameWeaponController: RequestHandler = async (req, res) => { export const nameWeaponController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);

View File

@ -1,9 +1,10 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { toPurchaseRequest } from "@/src/helpers/purchaseHelpers"; import { toPurchaseRequest } from "@/src/helpers/purchaseHelpers";
import { handlePurchase } from "@/src/services/purchaseService"; import { handlePurchase } from "@/src/services/purchaseService";
import { Request, Response } from "express";
export const purchaseController = async (req: Request, res: Response) => { // eslint-disable-next-line @typescript-eslint/no-misused-promises
export const purchaseController: RequestHandler = async (req, res) => {
const purchaseRequest = toPurchaseRequest(JSON.parse(String(req.body))); const purchaseRequest = toPurchaseRequest(JSON.parse(String(req.body)));
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const response = await handlePurchase(purchaseRequest, accountId); const response = await handlePurchase(purchaseRequest, accountId);

View File

@ -3,6 +3,7 @@ import { ISellRequest } from "@/src/types/sellTypes";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory, addMods, addRecipes } from "@/src/services/inventoryService"; import { getInventory, addMods, addRecipes } from "@/src/services/inventoryService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const sellController: RequestHandler = async (req, res) => { export const sellController: RequestHandler = async (req, res) => {
const payload: ISellRequest = JSON.parse(req.body.toString()); const payload: ISellRequest = JSON.parse(req.body.toString());
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);

View File

@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { getPersonalRooms } from "@/src/services/personalRoomsService"; import { getPersonalRooms } from "@/src/services/personalRoomsService";
import { TBootLocation } from "@/src/types/shipTypes"; import { TBootLocation } from "@/src/types/shipTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const setBootLocationController: RequestHandler = async (req, res) => { export const setBootLocationController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const personalRooms = await getPersonalRooms(accountId); const personalRooms = await getPersonalRooms(accountId);

View File

@ -2,6 +2,7 @@ import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService"; import { getInventory } from "@/src/services/inventoryService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const setSupportedSyndicateController: RequestHandler = async (req, res) => { export const setSupportedSyndicateController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);

View File

@ -0,0 +1,24 @@
import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService";
import { getJSONfromString } from "@/src/helpers/stringHelpers";
import { WeaponTypeInternal } from "@/src/services/itemDataService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const setWeaponSkillTreeController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId);
const payload = getJSONfromString(req.body.toString()) as ISetWeaponSkillTreeRequest;
const item = inventory[req.query.Category as WeaponTypeInternal].find(
item => item._id.toString() == (req.query.ItemId as string)
)!;
item.SkillTree = payload.SkillTree;
await inventory.save();
res.end();
};
interface ISetWeaponSkillTreeRequest {
SkillTree: string;
}

View File

@ -8,6 +8,7 @@ interface IStartDojoRecipeRequest {
Revision: number; Revision: number;
} }
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const startDojoRecipeController: RequestHandler = async (req, res) => { export const startDojoRecipeController: RequestHandler = async (req, res) => {
const guild = await getGuildForRequest(req); const guild = await getGuildForRequest(req);
// At this point, we know that a member of the guild is making this request. Assuming they are allowed to start a build. // At this point, we know that a member of the guild is making this request. Assuming they are allowed to start a build.

View File

@ -3,6 +3,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { getInventory } from "@/src/services/inventoryService"; import { getInventory } from "@/src/services/inventoryService";
import { IStepSequencer } from "@/src/types/inventoryTypes/inventoryTypes"; import { IStepSequencer } from "@/src/types/inventoryTypes/inventoryTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const stepSequencersController: RequestHandler = async (req, res) => { export const stepSequencersController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);

View File

@ -3,6 +3,7 @@ import { syndicateSacrifice } from "@/src/services/inventoryService";
import { ISyndicateSacrifice } from "@/src/types/syndicateTypes"; import { ISyndicateSacrifice } from "@/src/types/syndicateTypes";
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises // eslint-disable-next-line @typescript-eslint/no-misused-promises
const syndicateSacrificeController: RequestHandler = async (request, response) => { const syndicateSacrificeController: RequestHandler = async (request, response) => {
const accountId = await getAccountIdForRequest(request); const accountId = await getAccountIdForRequest(request);

View File

@ -4,6 +4,7 @@ import { getAccountIdForRequest } from "@/src/services/loginService";
import { updateChallengeProgress } from "@/src/services/inventoryService"; import { updateChallengeProgress } from "@/src/services/inventoryService";
import { IUpdateChallengeProgressRequest } from "@/src/types/requestTypes"; import { IUpdateChallengeProgressRequest } from "@/src/types/requestTypes";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const updateChallengeProgressController: RequestHandler = async (req, res) => { const updateChallengeProgressController: RequestHandler = async (req, res) => {
const payload: IUpdateChallengeProgressRequest = getJSONfromString(req.body.toString()); const payload: IUpdateChallengeProgressRequest = getJSONfromString(req.body.toString());
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);

View File

@ -1,10 +1,11 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { IUpgradesRequest } from "@/src/types/requestTypes"; import { IUpgradesRequest } from "@/src/types/requestTypes";
import { FocusSchool, IEquipmentDatabase } from "@/src/types/inventoryTypes/commonInventoryTypes"; import { FocusSchool, IEquipmentDatabase, EquipmentFeatures } from "@/src/types/inventoryTypes/commonInventoryTypes";
import { IMiscItem, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes"; import { IMiscItem, TEquipmentKey } from "@/src/types/inventoryTypes/inventoryTypes";
import { getAccountIdForRequest } from "@/src/services/loginService"; import { getAccountIdForRequest } from "@/src/services/loginService";
import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService"; import { addMiscItems, getInventory, updateCurrency } from "@/src/services/inventoryService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
export const upgradesController: RequestHandler = async (req, res) => { export const upgradesController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const payload = JSON.parse(req.body.toString()) as IUpgradesRequest; const payload = JSON.parse(req.body.toString()) as IUpgradesRequest;
@ -31,7 +32,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) { if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0; item.Features ??= 0;
item.Features |= 1; item.Features |= EquipmentFeatures.DOUBLE_CAPACITY;
break; break;
} }
} }
@ -41,7 +42,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) { if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0; item.Features ??= 0;
item.Features |= 2; item.Features |= EquipmentFeatures.UTILITY_SLOT;
break; break;
} }
} }
@ -52,7 +53,7 @@ export const upgradesController: RequestHandler = async (req, res) => {
for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) { for (const item of inventory[payload.ItemCategory as TEquipmentKey] as IEquipmentDatabase[]) {
if (item._id.toString() == payload.ItemId.$oid) { if (item._id.toString() == payload.ItemId.$oid) {
item.Features ??= 0; item.Features ??= 0;
item.Features |= 32; item.Features |= EquipmentFeatures.ARCANE_SLOT;
break; break;
} }
} }

View File

@ -1,7 +1,13 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { MinItem, items, getEnglishString } from "@/src/services/itemDataService"; import { MinItem, items, getEnglishString } from "@/src/services/itemDataService";
import badItems from "@/static/json/exclude-mods.json"; import badItems from "@/static/json/exclude-mods.json";
import { ExportArcanes, ExportResources, ExportWarframes, ExportWeapons } from "warframe-public-export-plus"; import {
ExportArcanes,
ExportGear,
ExportResources,
ExportWarframes,
ExportWeapons
} from "warframe-public-export-plus";
interface ListedItem { interface ListedItem {
uniqueName: string; uniqueName: string;
@ -31,7 +37,7 @@ const getItemListsController: RequestHandler = (_req, res) => {
}); });
} else if (!item.excludeFromCodex) { } else if (!item.excludeFromCodex) {
miscitems.push({ miscitems.push({
uniqueName, uniqueName: "MiscItems:" + uniqueName,
name: getEnglishString(item.name) name: getEnglishString(item.name)
}); });
} }
@ -39,7 +45,13 @@ const getItemListsController: RequestHandler = (_req, res) => {
} }
for (const [uniqueName, item] of Object.entries(ExportResources)) { for (const [uniqueName, item] of Object.entries(ExportResources)) {
miscitems.push({ miscitems.push({
uniqueName, uniqueName: "MiscItems:" + uniqueName,
name: getEnglishString(item.name)
});
}
for (const [uniqueName, item] of Object.entries(ExportGear)) {
miscitems.push({
uniqueName: "Consumables:" + uniqueName,
name: getEnglishString(item.name) name: getEnglishString(item.name)
}); });
} }

View File

@ -1,6 +1,7 @@
import { RequestHandler } from "express"; import { RequestHandler } from "express";
import { updateConfig } from "@/src/services/configService"; import { updateConfig } from "@/src/services/configService";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const updateConfigDataController: RequestHandler = async (req, res) => { const updateConfigDataController: RequestHandler = async (req, res) => {
await updateConfig(req.body.toString()); await updateConfig(req.body.toString());
res.end(); res.end();

View File

@ -6,6 +6,7 @@ import { config } from "@/src/services/configService";
import view from "@/static/fixed_responses/view.json"; import view from "@/static/fixed_responses/view.json";
import allScans from "@/static/fixed_responses/allScans.json"; import allScans from "@/static/fixed_responses/allScans.json";
// eslint-disable-next-line @typescript-eslint/no-misused-promises
const viewController: RequestHandler = async (req, res) => { const viewController: RequestHandler = async (req, res) => {
const accountId = await getAccountIdForRequest(req); const accountId = await getAccountIdForRequest(req);
const inventory = await Inventory.findOne({ accountOwnerId: accountId }); const inventory = await Inventory.findOne({ accountOwnerId: accountId });

View File

@ -35,7 +35,8 @@ import {
ITauntHistory, ITauntHistory,
IPeriodicMissionCompletionDatabase, IPeriodicMissionCompletionDatabase,
IPeriodicMissionCompletionResponse, IPeriodicMissionCompletionResponse,
ILoreFragmentScan ILoreFragmentScan,
IEvolutionProgress
} from "../../types/inventoryTypes/inventoryTypes"; } from "../../types/inventoryTypes/inventoryTypes";
import { IOid } from "../../types/commonTypes"; import { IOid } from "../../types/commonTypes";
import { import {
@ -161,7 +162,8 @@ const ItemConfigSchema = new Schema<IItemConfig>(
facial: colorSchema, facial: colorSchema,
syancol: colorSchema, syancol: colorSchema,
Upgrades: [String], Upgrades: [String],
Songs: [ Songs: {
type: [
{ {
m: String, m: String,
b: String, b: String,
@ -169,6 +171,8 @@ const ItemConfigSchema = new Schema<IItemConfig>(
s: String s: String
} }
], ],
default: undefined
},
Name: String, Name: String,
AbilityOverride: abilityOverrideSchema, AbilityOverride: abilityOverrideSchema,
PvpUpgrades: [String], PvpUpgrades: [String],
@ -197,7 +201,8 @@ ArchonCrystalUpgradeSchema.set("toJSON", {
} }
}); });
const EquipmentSchema = new Schema<IEquipmentDatabase>({ const EquipmentSchema = new Schema<IEquipmentDatabase>(
{
ItemType: String, ItemType: String,
Configs: [ItemConfigSchema], Configs: [ItemConfigSchema],
UpgradeVer: Number, UpgradeVer: Number,
@ -214,12 +219,14 @@ const EquipmentSchema = new Schema<IEquipmentDatabase>({
InfestationDate: Date, InfestationDate: Date,
InfestationDays: Number, InfestationDays: Number,
InfestationType: String, InfestationType: String,
ModularParts: [String], ModularParts: { type: [String], default: undefined },
UnlockLevel: Number, UnlockLevel: Number,
Expiry: Date, Expiry: Date,
SkillTree: String, SkillTree: String,
ArchonCrystalUpgrades: { type: [ArchonCrystalUpgradeSchema], default: undefined } ArchonCrystalUpgrades: { type: [ArchonCrystalUpgradeSchema], default: undefined }
}); },
{ id: false }
);
EquipmentSchema.virtual("ItemId").get(function () { EquipmentSchema.virtual("ItemId").get(function () {
return { $oid: this._id.toString() } satisfies IOid; return { $oid: this._id.toString() } satisfies IOid;
@ -556,6 +563,15 @@ const loreFragmentScansSchema = new Schema<ILoreFragmentScan>(
{ _id: false } { _id: false }
); );
const evolutionProgressSchema = new Schema<IEvolutionProgress>(
{
Progress: Number,
Rank: Number,
ItemType: String
},
{ _id: false }
);
const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>( const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
{ {
accountOwnerId: Schema.Types.ObjectId, accountOwnerId: Schema.Types.ObjectId,
@ -875,7 +891,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
//Progress+Rank+ItemType(ZarimanPumpShotgun) //Progress+Rank+ItemType(ZarimanPumpShotgun)
//https://warframe.fandom.com/wiki/Incarnon //https://warframe.fandom.com/wiki/Incarnon
EvolutionProgress: [Schema.Types.Mixed], EvolutionProgress: { type: [evolutionProgressSchema], default: undefined },
//Unknown and system //Unknown and system
DuviriInfo: DuviriInfoSchema, DuviriInfo: DuviriInfoSchema,
@ -885,7 +901,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
ChallengesFixVersion: Number, ChallengesFixVersion: Number,
PlayedParkourTutorial: Boolean, PlayedParkourTutorial: Boolean,
SubscribedToEmailsPersonalized: Number, SubscribedToEmailsPersonalized: Number,
LastInventorySync: Schema.Types.Mixed, LastInventorySync: Schema.Types.Mixed, // this should be Schema.Types.ObjectId, but older inventories may break with that.
ActiveLandscapeTraps: [Schema.Types.Mixed], ActiveLandscapeTraps: [Schema.Types.Mixed],
RepVotes: [Schema.Types.Mixed], RepVotes: [Schema.Types.Mixed],
LeagueTickets: [Schema.Types.Mixed], LeagueTickets: [Schema.Types.Mixed],
@ -911,7 +927,7 @@ const inventorySchema = new Schema<IInventoryDatabase, InventoryDocumentProps>(
//Grustag three //Grustag three
DeathSquadable: Boolean DeathSquadable: Boolean
}, },
{ timestamps: { createdAt: "Created", updatedAt: "LastInventorySync" } } { timestamps: { createdAt: "Created" } }
); );
inventorySchema.set("toJSON", { inventorySchema.set("toJSON", {
@ -955,6 +971,10 @@ type InventoryDocumentProps = {
Sentinels: Types.DocumentArray<IEquipmentDatabase>; Sentinels: Types.DocumentArray<IEquipmentDatabase>;
Horses: Types.DocumentArray<IEquipmentDatabase>; Horses: Types.DocumentArray<IEquipmentDatabase>;
PendingRecipes: Types.DocumentArray<IPendingRecipeDatabase>; PendingRecipes: Types.DocumentArray<IPendingRecipeDatabase>;
SpaceSuits: Types.DocumentArray<IEquipmentDatabase>;
SpaceGuns: Types.DocumentArray<IEquipmentDatabase>;
SpaceMelee: Types.DocumentArray<IEquipmentDatabase>;
SentinelWeapons: Types.DocumentArray<IEquipmentDatabase>;
}; };
// eslint-disable-next-line @typescript-eslint/ban-types // eslint-disable-next-line @typescript-eslint/ban-types

View File

@ -7,6 +7,7 @@ import { createGuildController } from "@/src/controllers/api/createGuildControll
import { deleteSessionController } from "@/src/controllers/api/deleteSessionController"; import { deleteSessionController } from "@/src/controllers/api/deleteSessionController";
import { dojoController } from "@/src/controllers/api/dojoController"; import { dojoController } from "@/src/controllers/api/dojoController";
import { dronesController } from "@/src/controllers/api/dronesController"; import { dronesController } from "@/src/controllers/api/dronesController";
import { evolveWeaponController } from "@/src/controllers/api/evolveWeaponController";
import { findSessionsController } from "@/src/controllers/api/findSessionsController"; import { findSessionsController } from "@/src/controllers/api/findSessionsController";
import { focusController } from "@/src/controllers/api/focusController"; import { focusController } from "@/src/controllers/api/focusController";
import { genericUpdateController } from "@/src/controllers/api/genericUpdateController"; import { genericUpdateController } from "@/src/controllers/api/genericUpdateController";
@ -20,6 +21,7 @@ import { getGuildLogController } from "../controllers/api/getGuildLogController"
import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController"; import { getIgnoredUsersController } from "@/src/controllers/api/getIgnoredUsersController";
import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController"; import { getNewRewardSeedController } from "@/src/controllers/api/getNewRewardSeedController";
import { getShipController } from "@/src/controllers/api/getShipController"; import { getShipController } from "@/src/controllers/api/getShipController";
import { getVendorInfoController } from "@/src/controllers/api/getVendorInfoController";
import { guildTechController } from "../controllers/api/guildTechController"; import { guildTechController } from "../controllers/api/guildTechController";
import { hostSessionController } from "@/src/controllers/api/hostSessionController"; import { hostSessionController } from "@/src/controllers/api/hostSessionController";
import { hubController } from "@/src/controllers/api/hubController"; import { hubController } from "@/src/controllers/api/hubController";
@ -47,6 +49,7 @@ import { setActiveShipController } from "@/src/controllers/api/setActiveShipCont
import { setBootLocationController } from "@/src/controllers/api/setBootLocationController"; import { setBootLocationController } from "@/src/controllers/api/setBootLocationController";
import { setShipCustomizationsController } from "@/src/controllers/api/setShipCustomizationsController"; import { setShipCustomizationsController } from "@/src/controllers/api/setShipCustomizationsController";
import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController"; import { setSupportedSyndicateController } from "@/src/controllers/api/setSupportedSyndicateController";
import { setWeaponSkillTreeController } from "../controllers/api/setWeaponSkillTreeController";
import { shipDecorationsController } from "@/src/controllers/api/shipDecorationsController"; import { shipDecorationsController } from "@/src/controllers/api/shipDecorationsController";
import { startDojoRecipeController } from "@/src/controllers/api/startDojoRecipeController"; import { startDojoRecipeController } from "@/src/controllers/api/startDojoRecipeController";
import { startRecipeController } from "@/src/controllers/api/startRecipeController"; import { startRecipeController } from "@/src/controllers/api/startRecipeController";
@ -75,6 +78,7 @@ apiRouter.get("/getGuildLog.php", getGuildLogController);
apiRouter.get("/getIgnoredUsers.php", getIgnoredUsersController); apiRouter.get("/getIgnoredUsers.php", getIgnoredUsersController);
apiRouter.get("/getNewRewardSeed.php", getNewRewardSeedController); apiRouter.get("/getNewRewardSeed.php", getNewRewardSeedController);
apiRouter.get("/getShip.php", getShipController); apiRouter.get("/getShip.php", getShipController);
apiRouter.get("/getVendorInfo.php", getVendorInfoController);
apiRouter.get("/hub", hubController); apiRouter.get("/hub", hubController);
apiRouter.get("/hubInstances", hubInstancesController); apiRouter.get("/hubInstances", hubInstancesController);
apiRouter.get("/inbox.php", inboxController); apiRouter.get("/inbox.php", inboxController);
@ -97,6 +101,7 @@ apiRouter.post("/addFriendImage.php", addFriendImageController);
apiRouter.post("/artifacts.php", artifactsController); apiRouter.post("/artifacts.php", artifactsController);
apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController); apiRouter.post("/claimCompletedRecipe.php", claimCompletedRecipeController);
apiRouter.post("/createGuild.php", createGuildController); apiRouter.post("/createGuild.php", createGuildController);
apiRouter.post("/evolveWeapon.php", evolveWeaponController);
apiRouter.post("/findSessions.php", findSessionsController); apiRouter.post("/findSessions.php", findSessionsController);
apiRouter.post("/focus.php", focusController); apiRouter.post("/focus.php", focusController);
apiRouter.post("/genericUpdate.php", genericUpdateController); apiRouter.post("/genericUpdate.php", genericUpdateController);
@ -115,6 +120,7 @@ apiRouter.post("/rerollRandomMod.php", rerollRandomModController);
apiRouter.post("/saveLoadout.php", saveLoadoutController); apiRouter.post("/saveLoadout.php", saveLoadoutController);
apiRouter.post("/sell.php", sellController); apiRouter.post("/sell.php", sellController);
apiRouter.post("/setShipCustomizations.php", setShipCustomizationsController); apiRouter.post("/setShipCustomizations.php", setShipCustomizationsController);
apiRouter.post("/setWeaponSkillTree.php", setWeaponSkillTreeController);
apiRouter.post("/shipDecorations.php", shipDecorationsController); apiRouter.post("/shipDecorations.php", shipDecorationsController);
apiRouter.post("/startDojoRecipe.php", startDojoRecipeController); apiRouter.post("/startDojoRecipe.php", startDojoRecipeController);
apiRouter.post("/startRecipe.php", startRecipeController); apiRouter.post("/startRecipe.php", startRecipeController);

View File

@ -16,6 +16,7 @@ cacheRouter.get(/^\/origin\/[a-zA-Z0-9]+\/[0-9]+\/H\.Cache\.bin.*$/, (_req, res)
res.sendFile(`static/data/H.Cache_${buildConfig.version}.bin`, { root: "./" }); res.sendFile(`static/data/H.Cache_${buildConfig.version}.bin`, { root: "./" });
}); });
// eslint-disable-next-line @typescript-eslint/no-misused-promises
cacheRouter.get(/\.bk2!/, async (req, res) => { cacheRouter.get(/\.bk2!/, async (req, res) => {
try { try {
const dir = req.path.substr(0, req.path.lastIndexOf("/")); const dir = req.path.substr(0, req.path.lastIndexOf("/"));

View File

@ -2,7 +2,7 @@ import { Inventory } from "@/src/models/inventoryModels/inventoryModel";
import new_inventory from "@/static/fixed_responses/postTutorialInventory.json"; import new_inventory from "@/static/fixed_responses/postTutorialInventory.json";
import { config } from "@/src/services/configService"; import { config } from "@/src/services/configService";
import { Types } from "mongoose"; import { Types } from "mongoose";
import { SlotNames } from "@/src/types/purchaseTypes"; import { SlotNames, IInventoryChanges } from "@/src/types/purchaseTypes";
import { import {
IChallengeProgress, IChallengeProgress,
IConsumable, IConsumable,
@ -26,7 +26,7 @@ import { logger } from "@/src/utils/logger";
import { WeaponTypeInternal, getWeaponType, getExalted } from "@/src/services/itemDataService"; import { WeaponTypeInternal, getWeaponType, getExalted } from "@/src/services/itemDataService";
import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes"; import { ISyndicateSacrifice, ISyndicateSacrificeResponse } from "../types/syndicateTypes";
import { IEquipmentClient } from "../types/inventoryTypes/commonInventoryTypes"; import { IEquipmentClient } from "../types/inventoryTypes/commonInventoryTypes";
import { ExportRecipes } from "warframe-public-export-plus"; import { ExportRecipes, ExportResources } from "warframe-public-export-plus";
export const createInventory = async ( export const createInventory = async (
accountOwnerId: Types.ObjectId, accountOwnerId: Types.ObjectId,
@ -70,7 +70,7 @@ export const addItem = async (
accountId: string, accountId: string,
typeName: string, typeName: string,
quantity: number = 1 quantity: number = 1
): Promise<{ InventoryChanges: object }> => { ): Promise<{ InventoryChanges: IInventoryChanges }> => {
// Strict typing // Strict typing
if (typeName in ExportRecipes) { if (typeName in ExportRecipes) {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
@ -88,25 +88,28 @@ export const addItem = async (
} }
}; };
} }
if (typeName in ExportResources) {
const inventory = await getInventory(accountId);
const miscItemChanges = [
{
ItemType: typeName,
ItemCount: quantity
} satisfies IMiscItem
];
addMiscItems(inventory, miscItemChanges);
await inventory.save();
return {
InventoryChanges: {
MiscItems: miscItemChanges
}
};
}
// Path-based duck typing // Path-based duck typing
switch (typeName.substr(1).split("/")[1]) { switch (typeName.substr(1).split("/")[1]) {
case "Powersuits": case "Powersuits":
if (typeName.includes("EntratiMech")) { switch (typeName.substr(1).split("/")[2]) {
const mechSuit = await addMechSuit(typeName, accountId); default: {
await updateSlots(accountId, InventorySlot.MECHSUITS, 0, 1);
logger.debug("mech suit", mechSuit);
return {
InventoryChanges: {
MechBin: {
count: 1,
platinum: 0,
Slots: -1
},
MechSuits: [mechSuit]
}
};
}
const suit = await addPowerSuit(typeName, accountId); const suit = await addPowerSuit(typeName, accountId);
await updateSlots(accountId, InventorySlot.SUITS, 0, 1); await updateSlots(accountId, InventorySlot.SUITS, 0, 1);
return { return {
@ -119,6 +122,37 @@ export const addItem = async (
Suits: [suit] Suits: [suit]
} }
}; };
}
case "Archwing": {
const spaceSuit = await addSpaceSuit(typeName, accountId);
await updateSlots(accountId, InventorySlot.SPACESUITS, 0, 1);
return {
InventoryChanges: {
SpaceSuitBin: {
count: 1,
platinum: 0,
Slots: -1
},
SpaceSuits: [spaceSuit]
}
};
}
case "EntratiMech": {
const mechSuit = await addMechSuit(typeName, accountId);
await updateSlots(accountId, InventorySlot.MECHSUITS, 0, 1);
return {
InventoryChanges: {
MechBin: {
count: 1,
platinum: 0,
Slots: -1
},
MechSuits: [mechSuit]
}
};
}
}
break;
case "Weapons": case "Weapons":
const weaponType = getWeaponType(typeName); const weaponType = getWeaponType(typeName);
const weapon = await addWeapon(weaponType, typeName, accountId); const weapon = await addWeapon(weaponType, typeName, accountId);
@ -277,6 +311,13 @@ export const addSpecialItem = async (itemName: string, accountId: string) => {
return changedInventory.SpecialItems[specialItemIndex - 1].toJSON(); return changedInventory.SpecialItems[specialItemIndex - 1].toJSON();
}; };
export const addSpaceSuit = async (spacesuitName: string, accountId: string) => {
const inventory = await getInventory(accountId);
const suitIndex = inventory.SpaceSuits.push({ ItemType: spacesuitName, Configs: [], UpgradeVer: 101, XP: 0 });
const changedInventory = await inventory.save();
return changedInventory.SpaceSuits[suitIndex - 1].toJSON();
};
export const updateSlots = async (accountId: string, slotName: SlotNames, slotAmount: number, extraAmount: number) => { export const updateSlots = async (accountId: string, slotName: SlotNames, slotAmount: number, extraAmount: number) => {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
@ -391,22 +432,12 @@ export const addWeapon = async (
): Promise<IEquipmentClient> => { ): Promise<IEquipmentClient> => {
const inventory = await getInventory(accountId); const inventory = await getInventory(accountId);
let weaponIndex; const weaponIndex = inventory[weaponType].push({
switch (weaponType) {
case "LongGuns":
case "Pistols":
case "Melee":
case "OperatorAmps":
weaponIndex = inventory[weaponType].push({
ItemType: weaponName, ItemType: weaponName,
Configs: [], Configs: [],
XP: 0, XP: 0,
ModularParts: modularParts ModularParts: modularParts
}); });
break;
default:
throw new Error("unknown weapon type: " + weaponType);
}
const changedInventory = await inventory.save(); const changedInventory = await inventory.save();
return changedInventory[weaponType][weaponIndex - 1].toJSON(); return changedInventory[weaponType][weaponIndex - 1].toJSON();
@ -614,6 +645,22 @@ export const missionInventoryUpdate = async (data: IMissionInventoryUpdateReques
// Gear XP // Gear XP
gearKeys.forEach(key => addGearExpByCategory(inventory, data[key], key)); gearKeys.forEach(key => addGearExpByCategory(inventory, data[key], key));
// Incarnon Challenges
if (data.EvolutionProgress) {
for (const evoProgress of data.EvolutionProgress) {
const entry = inventory.EvolutionProgress
? inventory.EvolutionProgress.find(entry => entry.ItemType == evoProgress.ItemType)
: undefined;
if (entry) {
entry.Progress = evoProgress.Progress;
entry.Rank = evoProgress.Rank;
} else {
inventory.EvolutionProgress ??= [];
inventory.EvolutionProgress.push(evoProgress);
}
}
}
// other // other
addMods(inventory, RawUpgrades); addMods(inventory, RawUpgrades);
addMiscItems(inventory, MiscItems); addMiscItems(inventory, MiscItems);

View File

@ -174,7 +174,7 @@ const itemCheck = (
}; };
for (const key of Object.keys(rewardCheck) as IInventoryFieldType[]) { for (const key of Object.keys(rewardCheck) as IInventoryFieldType[]) {
if (rewardCheck[key]) { if (rewardCheck[key]) {
addRewardResponse(InventoryChanges, MissionRewards, name, rewardCheck[key]!, key); addRewardResponse(InventoryChanges, MissionRewards, name, rewardCheck[key], key);
return true; return true;
} }
} }

View File

@ -1,7 +1,7 @@
import { parseSlotPurchaseName } from "@/src/helpers/purchaseHelpers"; import { parseSlotPurchaseName } from "@/src/helpers/purchaseHelpers";
import { getSubstringFromKeyword } from "@/src/helpers/stringHelpers"; import { getSubstringFromKeyword } from "@/src/helpers/stringHelpers";
import { addItem, addBooster, updateCurrency, updateSlots } from "@/src/services/inventoryService"; import { addItem, addBooster, updateCurrency, updateSlots } from "@/src/services/inventoryService";
import { IPurchaseRequest, SlotPurchase } from "@/src/types/purchaseTypes"; import { IPurchaseRequest, SlotPurchase, IInventoryChanges, IBinChanges } from "@/src/types/purchaseTypes";
import { logger } from "@/src/utils/logger"; import { logger } from "@/src/utils/logger";
import { ExportBundles, TRarity } from "warframe-public-export-plus"; import { ExportBundles, TRarity } from "warframe-public-export-plus";
@ -46,12 +46,37 @@ export const handlePurchase = async (purchaseRequest: IPurchaseRequest, accountI
return purchaseResponse; return purchaseResponse;
}; };
const addInventoryChanges = (InventoryChanges: IInventoryChanges, delta: IInventoryChanges): void => {
for (const key in delta) {
if (!(key in InventoryChanges)) {
InventoryChanges[key] = delta[key];
} else if (Array.isArray(delta[key])) {
const left = InventoryChanges[key] as object[];
const right = delta[key] as object[];
for (const item of right) {
left.push(item);
}
} else {
console.assert(key.substring(-3) == "Bin");
const left = InventoryChanges[key] as IBinChanges;
const right = delta[key] as IBinChanges;
left.count += right.count;
left.platinum += right.platinum;
left.Slots += right.Slots;
if (right.Extra) {
left.Extra ??= 0;
left.Extra += right.Extra;
}
}
}
};
const handleStoreItemAcquisition = async ( const handleStoreItemAcquisition = async (
storeItemName: string, storeItemName: string,
accountId: string, accountId: string,
quantity: number, quantity: number,
durability: TRarity durability: TRarity
): Promise<{ InventoryChanges: object }> => { ): Promise<{ InventoryChanges: IInventoryChanges }> => {
let purchaseResponse = { let purchaseResponse = {
InventoryChanges: {} InventoryChanges: {}
}; };
@ -60,15 +85,17 @@ const handleStoreItemAcquisition = async (
const bundle = ExportBundles[storeItemName]; const bundle = ExportBundles[storeItemName];
logger.debug("acquiring bundle", bundle); logger.debug("acquiring bundle", bundle);
for (const component of bundle.components) { for (const component of bundle.components) {
purchaseResponse = { addInventoryChanges(
...purchaseResponse, purchaseResponse.InventoryChanges,
...(await handleStoreItemAcquisition( (
await handleStoreItemAcquisition(
component.typeName, component.typeName,
accountId, accountId,
component.purchaseQuantity, component.purchaseQuantity,
component.durability component.durability
)) )
}; ).InventoryChanges
);
} }
} else { } else {
const storeCategory = getStoreItemCategory(storeItemName); const storeCategory = getStoreItemCategory(storeItemName);
@ -106,7 +133,10 @@ export const slotPurchaseNameToSlotName: SlotPurchase = {
// // new slot above base = extra + 1 and slots +1 // // new slot above base = extra + 1 and slots +1
// // new frame = slots -1 // // new frame = slots -1
// // number of frames = extra - slots + 2 // // number of frames = extra - slots + 2
const handleSlotPurchase = async (slotPurchaseNameFull: string, accountId: string) => { const handleSlotPurchase = async (
slotPurchaseNameFull: string,
accountId: string
): Promise<{ InventoryChanges: IInventoryChanges }> => {
logger.debug(`slot name ${slotPurchaseNameFull}`); logger.debug(`slot name ${slotPurchaseNameFull}`);
const slotPurchaseName = parseSlotPurchaseName( const slotPurchaseName = parseSlotPurchaseName(
slotPurchaseNameFull.substring(slotPurchaseNameFull.lastIndexOf("/") + 1) slotPurchaseNameFull.substring(slotPurchaseNameFull.lastIndexOf("/") + 1)
@ -133,7 +163,11 @@ const handleSlotPurchase = async (slotPurchaseNameFull: string, accountId: strin
}; };
//TODO: change to getInventory, apply changes then save at the end //TODO: change to getInventory, apply changes then save at the end
const handleTypesPurchase = async (typesName: string, accountId: string, quantity: number) => { const handleTypesPurchase = async (
typesName: string,
accountId: string,
quantity: number
): Promise<{ InventoryChanges: IInventoryChanges }> => {
const typeCategory = getStoreItemTypesCategory(typesName); const typeCategory = getStoreItemTypesCategory(typesName);
logger.debug(`type category ${typeCategory}`); logger.debug(`type category ${typeCategory}`);
switch (typeCategory) { switch (typeCategory) {
@ -158,7 +192,11 @@ const boosterDuration: Record<TRarity, number> = {
LEGENDARY: 90 * 86400 LEGENDARY: 90 * 86400
}; };
const handleBoostersPurchase = async (boosterStoreName: string, accountId: string, durability: TRarity) => { const handleBoostersPurchase = async (
boosterStoreName: string,
accountId: string,
durability: TRarity
): Promise<{ InventoryChanges: IInventoryChanges }> => {
const ItemType = boosterStoreName.replace("StoreItem", ""); const ItemType = boosterStoreName.replace("StoreItem", "");
if (!boosterCollection.find(x => x == ItemType)) { if (!boosterCollection.find(x => x == ItemType)) {
logger.error(`unknown booster type: ${ItemType}`); logger.error(`unknown booster type: ${ItemType}`);

View File

@ -171,6 +171,10 @@ export const handleInventoryItemConfigChange = async (
inventory.EquippedGear = equipment as string[]; inventory.EquippedGear = equipment as string[];
break; break;
} }
case "UseAdultOperatorLoadout": {
inventory.UseAdultOperatorLoadout = equipment as boolean;
break;
}
default: { default: {
logger.error(`category not implemented: ${equipmentName}`, { config: equipment }); logger.error(`category not implemented: ${equipmentName}`, { config: equipment });
} }

View File

@ -82,6 +82,13 @@ export interface IEquipmentClient extends Omit<IEquipmentDatabase, "_id"> {
ItemId: IOid; ItemId: IOid;
} }
export enum EquipmentFeatures {
DOUBLE_CAPACITY = 1,
UTILITY_SLOT = 2,
ARCANE_SLOT = 32,
INCARNON_GENESIS = 512
}
export interface IEquipmentDatabase { export interface IEquipmentDatabase {
ItemType: string; ItemType: string;
ItemName?: string; ItemName?: string;

View File

@ -170,7 +170,7 @@ export interface IInventoryResponse {
SpectreLoadouts: ISpectreLoadout[]; SpectreLoadouts: ISpectreLoadout[];
SentinelWeapons: IEquipmentDatabase[]; SentinelWeapons: IEquipmentDatabase[];
Sentinels: IEquipmentDatabase[]; Sentinels: IEquipmentDatabase[];
EmailItems: ITypeXPItem[]; EmailItems: ITypeCount[];
CompletedSyndicates: string[]; CompletedSyndicates: string[];
FocusXP: IFocusXP; FocusXP: IFocusXP;
Wishlist: string[]; Wishlist: string[];
@ -239,14 +239,14 @@ export interface IInventoryResponse {
CrewMembers: ICrewMember[]; CrewMembers: ICrewMember[];
AdultOperatorLoadOuts: IOperatorConfigClient[]; AdultOperatorLoadOuts: IOperatorConfigClient[];
LotusCustomization: ILotusCustomization; LotusCustomization: ILotusCustomization;
UseAdultOperatorLoadout: boolean; UseAdultOperatorLoadout?: boolean;
DailyAffiliationZariman: number; DailyAffiliationZariman: number;
NemesisAbandonedRewards: string[]; NemesisAbandonedRewards: string[];
DailyAffiliationKahl: number; DailyAffiliationKahl: number;
LastInventorySync: IOid; LastInventorySync: IOid;
NextRefill: IMongoDate; NextRefill: IMongoDate;
ActiveLandscapeTraps: any[]; ActiveLandscapeTraps: any[];
EvolutionProgress: any[]; EvolutionProgress?: IEvolutionProgress[];
RepVotes: any[]; RepVotes: any[];
LeagueTickets: any[]; LeagueTickets: any[];
Quests: any[]; Quests: any[];
@ -358,6 +358,7 @@ export interface ICombat {
export enum InventorySlot { export enum InventorySlot {
SUITS = "SuitBin", SUITS = "SuitBin",
WEAPONS = "WeaponBin", WEAPONS = "WeaponBin",
SPACESUITS = "SpaceSuitBin",
MECHSUITS = "MechBin", MECHSUITS = "MechBin",
PVE_LOADOUTS = "PveBonusLoadoutBin", PVE_LOADOUTS = "PveBonusLoadoutBin",
SENTINELS = "SentinelBin" SENTINELS = "SentinelBin"
@ -866,3 +867,9 @@ export interface IWebFlags {
Anniversary2021: boolean; Anniversary2021: boolean;
HitDownloadBtn: IMongoDate; HitDownloadBtn: IMongoDate;
} }
export interface IEvolutionProgress {
Progress: number;
Rank: number;
ItemType: string;
}

View File

@ -1,6 +1,3 @@
import { IFlavourItem } from "@/src/types/inventoryTypes/inventoryTypes";
import { IEquipmentClient } from "./inventoryTypes/commonInventoryTypes";
export interface IPurchaseRequest { export interface IPurchaseRequest {
PurchaseParams: IPurchaseParams; PurchaseParams: IPurchaseParams;
buildLabel: string; buildLabel: string;
@ -17,22 +14,7 @@ export interface IPurchaseParams {
ExpectedPrice: number; ExpectedPrice: number;
} }
export interface IPurchaseResponse { export type IInventoryChanges = Record<string, IBinChanges | object[]>;
InventoryChanges: {
SuitBin?: IBinChanges;
WeaponBin?: IBinChanges;
MechBin?: IBinChanges;
MechSuits?: IEquipmentClient[];
Suits?: IEquipmentClient[];
LongGuns?: IEquipmentClient[];
Pistols?: IEquipmentClient[];
Melee?: IEquipmentClient[];
PremiumCredits?: number;
PremiumCreditsFree?: number;
RegularCredits?: number;
FlavourItems?: IFlavourItem[];
};
}
export type IBinChanges = { export type IBinChanges = {
count: number; count: number;

View File

@ -5,6 +5,7 @@ import {
IChallengeProgress, IChallengeProgress,
IConsumable, IConsumable,
ICrewShipSalvagedWeaponSkin, ICrewShipSalvagedWeaponSkin,
IEvolutionProgress,
IMiscItem, IMiscItem,
IMission, IMission,
IRawUpgrade, IRawUpgrade,
@ -53,6 +54,7 @@ export interface IMissionInventoryUpdateRequest {
RewardInfo?: IMissionInventoryUpdateRequestRewardInfo; RewardInfo?: IMissionInventoryUpdateRequestRewardInfo;
FusionPoints?: number; FusionPoints?: number;
Missions?: IMission; Missions?: IMission;
EvolutionProgress?: IEvolutionProgress[];
} }
export interface IMissionInventoryUpdateRequestRewardInfo { export interface IMissionInventoryUpdateRequestRewardInfo {

View File

@ -33,6 +33,7 @@ export interface ISaveLoadoutRequest {
CurrentLoadOutIds: IOid[]; CurrentLoadOutIds: IOid[];
ValidNewLoadoutId: string; ValidNewLoadoutId: string;
EquippedGear: string[]; EquippedGear: string[];
UseAdultOperatorLoadout: boolean;
} }
export interface ISaveLoadoutRequestNoUpgradeVer extends Omit<ISaveLoadoutRequest, "UpgradeVer"> {} export interface ISaveLoadoutRequestNoUpgradeVer extends Omit<ISaveLoadoutRequest, "UpgradeVer"> {}

View File

@ -0,0 +1,301 @@
{
"VendorInfo": {
"_id": {
"$oid": "598a090d9a4a313746fd1f24"
},
"TypeName": "/Lotus/Types/Game/VendorManifests/Ostron/MaskSalesmanManifest",
"ItemManifest": [
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/RevenantMask",
"ItemPrices": [
{
"ItemCount": 1,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797674"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumper",
"ItemPrices": [
{
"ItemCount": 2,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 32,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797675"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperMedium",
"ItemPrices": [
{
"ItemCount": 4,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemBCutAItem",
"ItemCount": 24,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
"ItemCount": 18,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 27,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797676"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Items/ShipDecos/Plushies/PlushyThumperLarge",
"ItemPrices": [
{
"ItemCount": 6,
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/CetusWispItem",
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonGemACutAItem",
"ItemCount": 35,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothCommonFishAPartItem",
"ItemCount": 95,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/NistlebrushItem",
"ItemCount": 60,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "63ed01ef4c37f93d0b797677"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareBlueBlueprint",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishBPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishCPartItem",
"ItemCount": 10,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a1"
}
},
{
"StoreItem": "/Lotus/StoreItems/Types/Recipes/SynthicatorRecipes/FlareRedBlueprint",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 37,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/BothUncommonFishAPartItem",
"ItemCount": 7,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a2"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/VoltMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreBAlloyBItem",
"ItemCount": 34,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
"ItemCount": 17,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a3"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/MagMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
"ItemCount": 16,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/ForestRodentPartItem",
"ItemCount": 5,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a4"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/ExcaliburMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/BirdOfPreyPartItem",
"ItemCount": 5,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Gameplay/Eidolon/Resources/GrokdrulItem",
"ItemCount": 20,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_0",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a5"
}
},
{
"StoreItem": "/Lotus/StoreItems/Upgrades/Skins/Ostron/GrineerMask",
"ItemPrices": [
{
"ItemType": "/Lotus/Types/Items/Fish/Eidolon/FishParts/DayCommonFishBPartItem",
"ItemCount": 20,
"ProductCategory": "MiscItems"
},
{
"ItemType": "/Lotus/Types/Items/Gems/Eidolon/CommonOreAAlloyAItem",
"ItemCount": 31,
"ProductCategory": "MiscItems"
}
],
"Bin": "BIN_1",
"QuantityMultiplier": 1,
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
},
"AllowMultipurchase": true,
"Id": {
"$oid": "6651291214e90115b91b50a6"
}
}
],
"PropertyTextHash": "6AACA376DA34B35B5C16F1B40DBC017D",
"Expiry": {
"$date": {
"$numberLong": "9999999000000"
}
}
}
}

View File

@ -109,10 +109,7 @@ window.itemListPromise = new Promise(resolve => {
items.forEach(item => { items.forEach(item => {
if (item.uniqueName in data.badItems) { if (item.uniqueName in data.badItems) {
item.name += " (Imposter)"; item.name += " (Imposter)";
} else if ( } else if (item.uniqueName.substr(0, 18) != "/Lotus/Types/Game/") {
item.uniqueName.substr(0, 18) != "/Lotus/Types/Game/" &&
item.uniqueName.substr(0, 18) != "/Lotus/StoreItems/"
) {
const option = document.createElement("option"); const option = document.createElement("option");
option.setAttribute("data-key", item.uniqueName); option.setAttribute("data-key", item.uniqueName);
option.value = item.name; option.value = item.name;
@ -515,17 +512,18 @@ function disposeOfItems(category, type, count) {
} }
function doAcquireMiscItems() { function doAcquireMiscItems() {
const uniqueName = getKey(document.getElementById("miscitem-type")); const data = getKey(document.getElementById("miscitem-type"));
if (!uniqueName) { if (!data) {
$("#miscitem-type").addClass("is-invalid").focus(); $("#miscitem-type").addClass("is-invalid").focus();
return; return;
} }
const [category, uniqueName] = data.split(":");
revalidateAuthz(() => { revalidateAuthz(() => {
$.post({ $.post({
url: "/api/missionInventoryUpdate.php?" + window.authz, url: "/api/missionInventoryUpdate.php?" + window.authz,
contentType: "text/plain", contentType: "text/plain",
data: JSON.stringify({ data: JSON.stringify({
MiscItems: [ [category]: [
{ {
ItemType: uniqueName, ItemType: uniqueName,
ItemCount: parseInt($("#miscitem-count").val()) ItemCount: parseInt($("#miscitem-count").val())
@ -538,8 +536,8 @@ function doAcquireMiscItems() {
}); });
} }
$("#miscitem-name").on("input", () => { $("#miscitem-type").on("input", () => {
$("#miscitem-name").removeClass("is-invalid"); $("#miscitem-type").removeClass("is-invalid");
}); });
function doAcquireRiven() { function doAcquireRiven() {