diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 495f4cf5..00000000 --- a/.eslintignore +++ /dev/null @@ -1,3 +0,0 @@ -docs/ -tests/ -testing/ \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json deleted file mode 100644 index 0042607c..00000000 --- a/.eslintrc.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": ["google", "plugin:@typescript-eslint/recommended", "eslint-config-prettier"], - "env": { "commonjs": true, "es2021": true, "node": true }, - "parserOptions": { "ecmaVersion": 2021 }, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint"], - "rules": { - "valid-jsdoc": [ - "error", - { "requireParamDescription": false, "requireReturnDescription": false, "requireReturn": true } - ], - "max-len": ["error", { "code": 120, "ignoreUrls": true, "ignoreComments": true }], - "@typescript-eslint/no-var-requires": "off", - "@typescript-eslint/no-unused-vars": "off", - "quote-props": ["error", "as-needed"], - "space-before-function-paren": "off", - "comma-dangle": ["error", "never"], - "object-curly-spacing": "off", - "linebreak-style": "off", - "no-extra-semi": "error", - "no-console": "error", - "curly": "error", - "semi": "error" - } -} diff --git a/.github/workflows/ci-cd-16x.yml b/.github/workflows/ci-cd-20x.yml similarity index 97% rename from .github/workflows/ci-cd-16x.yml rename to .github/workflows/ci-cd-20x.yml index e1266b07..be45e140 100644 --- a/.github/workflows/ci-cd-16x.yml +++ b/.github/workflows/ci-cd-20x.yml @@ -1,5 +1,5 @@ # This CI Workflow was deployed and configured by WarpWing and Nate. -name: CI/CD (16.x) +name: CI/CD (20.x) on: push: @@ -7,7 +7,7 @@ on: workflow_dispatch: env: - NODE_VERSION: '16.x' + NODE_VERSION: '20.x' jobs: es-lint: diff --git a/.npmignore b/.npmignore index 42838a9c..4f71b935 100644 --- a/.npmignore +++ b/.npmignore @@ -12,7 +12,7 @@ config.gypi CVS npm-debug.log .eslintignore -.eslintrc.json +.eslintrc. testing/ .github .travis.yml @@ -23,4 +23,5 @@ tests/ typings/*.json master.json .env -dtslint.json \ No newline at end of file +dtslint.json +.eslintcache \ No newline at end of file diff --git a/README.md b/README.md index babc7041..976e86e0 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ #### Requirements -**For Node.js users >= v14.x.x**
**For TypeScript users >= v3.5** +**For Node.js users >= v18.18.0**
**For TypeScript users >= v3.5** ### Installation & Usage diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 00000000..01c98f0d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,71 @@ +import jsdoc from 'eslint-plugin-jsdoc'; +import globals from 'globals'; +import js from '@eslint/js'; + +export default [ + js.configs.recommended, + { + ignores: ['docs/**', 'tests/**', 'node_modules/*'], + plugins: { jsdoc: jsdoc }, + languageOptions: { + ecmaVersion: 2021, + sourceType: 'commonjs', + globals: { + ...globals.commonjs, + ...globals.es2021, + ...globals.node + } + }, + rules: { + 'max-len': ['error', { code: 120, ignoreUrls: true, ignoreComments: true }], + 'no-constant-condition': ['error', { checkLoops: false }], + 'prefer-const': ['warn', { destructuring: 'all' }], + 'no-unused-vars': ['error', { args: 'none' }], + curly: ['warn', 'multi-line', 'consistent'], + 'logical-assignment-operators': 'warn', + 'no-template-curly-in-string': 'error', + 'quote-props': ['error', 'as-needed'], + 'jsdoc/no-undefined-types': 'warn', + 'comma-dangle': ['error', 'never'], + 'no-useless-constructor': 'error', + 'no-useless-assignment': 'error', + 'no-inner-declarations': 'error', + 'no-implicit-coercion': 'error', + 'jsdoc/require-jsdoc': 'error', + 'no-use-before-define': 'warn', + 'no-underscore-dangle': 'warn', + 'no-unneeded-ternary': 'error', + 'jsdoc/check-values': 'error', + 'default-param-last': 'error', + 'one-var': ['warn', 'never'], + 'no-inline-comments': 'warn', + 'jsdoc/valid-types': 'error', + 'no-empty-function': 'error', + 'no-useless-return': 'error', + 'no-useless-rename': 'warn', + 'no-useless-concat': 'warn', + 'no-throw-literal': 'error', + 'no-extend-native': 'error', + 'default-case-last': 'warn', + 'no-self-compare': 'error', + 'no-new-wrappers': 'error', + 'no-lone-blocks': 'error', + 'no-undef-init': 'error', + 'no-else-return': 'warn', + 'no-extra-semi': 'error', + 'require-await': 'warn', + yoda: ['error', 'always'], + 'default-case': 'error', + 'dot-notation': 'error', + 'no-sequences': 'warn', + 'no-multi-str': 'warn', + 'no-lonely-if': 'warn', + 'no-new-func': 'error', + 'no-console': 'error', + camelcase: 'warn', + 'no-var': 'warn', + eqeqeq: 'warn', + semi: 'error' + } + } +]; diff --git a/package-lock.json b/package-lock.json index 362e17bb..c9cd693f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,12 +18,10 @@ "devDependencies": { "@discordjs/docgen": "github:discordjs/docgen", "@types/node": "^20.11.19", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", "chai": "^4.3.4", - "eslint": "^8.56.0", - "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.1.0", + "eslint": "^9.3.0", + "eslint-plugin-jsdoc": "^48.2.7", + "globals": "^15.3.0", "mocha": "^10.4.0", "node-env-run": "^4.0.2", "path": "^0.12.7", @@ -31,16 +29,7 @@ "typescript": "^5.3.3" }, "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node": ">=18.18.0" } }, "node_modules/@babel/code-frame": { @@ -659,18 +648,6 @@ "node": ">=6" } }, - "node_modules/@discordjs/docgen/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@discordjs/docgen/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -774,11 +751,30 @@ "decamelize": "^1.2.0" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz", + "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "^8.56.5", + "@types/estree": "^1.0.5", + "@typescript-eslint/types": "^7.2.0", + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -789,25 +785,40 @@ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/@eslint-community/regexpp": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -815,7 +826,7 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -825,13 +836,28 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/@eslint/eslintrc/node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -839,34 +865,24 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.3.0.tgz", + "integrity": "sha512-niBqk8iwv96+yuTwjM6bWg8ovzAPF9qkICsGtcoa5/dmqcEMfdwNAX7+/OHcJHc7wj7XqPxH98oAHytFYlw6Sw==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", + "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" }, @@ -879,6 +895,7 @@ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -888,16 +905,32 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.0.tgz", + "integrity": "sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -911,6 +944,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -920,6 +954,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -943,6 +978,31 @@ "@types/ms": "*" } }, + "node_modules/@types/eslint": { + "version": "8.56.10", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz", + "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/linkify-it": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.5.tgz", @@ -995,207 +1055,12 @@ "integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==", "dev": true }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz", - "integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/type-utils": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz", - "integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz", - "integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz", - "integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "7.9.0", - "@typescript-eslint/utils": "7.9.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@typescript-eslint/types": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz", - "integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==", - "dev": true, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz", - "integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.11.0.tgz", + "integrity": "sha512-MPEsDRZTyCiXkD4vd3zywDCifi7tatc4K37KqTprCvaXptP7Xlpdw0NR2hRJTetG5TxbWDB79Ys4kLmHliEo/w==", "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/visitor-keys": "7.9.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "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/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/utils": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz", - "integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.9.0", - "@typescript-eslint/types": "7.9.0", - "@typescript-eslint/typescript-estree": "7.9.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.56.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz", - "integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "7.9.0", - "eslint-visitor-keys": "^3.4.3" - }, + "license": "MIT", "engines": { "node": "^18.18.0 || >=20.0.0" }, @@ -1204,12 +1069,6 @@ "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "node_modules/acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", @@ -1331,6 +1190,16 @@ "node": ">= 8" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -1349,15 +1218,6 @@ "node": ">=8" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -1765,6 +1625,16 @@ "node": ">=4" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/common-sequence": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", @@ -1899,18 +1769,6 @@ "node": ">=0.3.1" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dmd": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/dmd/-/dmd-4.0.6.tgz", @@ -1991,41 +1849,38 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.3.0.tgz", + "integrity": "sha512-5Iv4CsZW030lpUqHBapdPo3MJetAPtejVW8B84GIcIIv8+ohFaddXsrn1Gn8uD9ijDb+kcYKFUVmC8qG8B2ORQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.3.0", + "@humanwhocodes/config-array": "^0.13.0", "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.0", "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", + "eslint-scope": "^8.0.1", + "eslint-visitor-keys": "^4.0.0", + "espree": "^10.0.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", "lodash.merge": "^4.6.2", @@ -2039,34 +1894,33 @@ "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint-config-google": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/eslint-config-google/-/eslint-config-google-0.14.0.tgz", - "integrity": "sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==", + "node_modules/eslint-plugin-jsdoc": { + "version": "48.2.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.7.tgz", + "integrity": "sha512-fYj3roTnkFL9OFFTB129rico8lerC5G8Vp2ZW9SjO9RNWG0exVvI+i/Y8Bpm1ufjR0uvT38xtoab/U0Hp8Ybog==", "dev": true, - "engines": { - "node": ">=0.10.0" + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.43.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "semver": "^7.6.2", + "spdx-expression-parse": "^4.0.0" }, - "peerDependencies": { - "eslint": ">=5.16.0" - } - }, - "node_modules/eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "bin": { - "eslint-config-prettier": "bin/cli.js" + "engines": { + "node": ">=18" }, "peerDependencies": { - "eslint": ">=7.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-scope": { @@ -2083,34 +1937,30 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz", + "integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==", "dev": true, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.0.1.tgz", + "integrity": "sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2121,6 +1971,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -2130,6 +1981,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -2137,30 +1989,19 @@ "node": ">=10.13.0" } }, - "node_modules/eslint/node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz", + "integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.11.3", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2171,6 +2012,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -2282,22 +2124,6 @@ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2314,6 +2140,7 @@ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -2365,15 +2192,16 @@ } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/file-set": { @@ -2448,24 +2276,25 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.2.7", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": ">=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.9", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", - "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.6", @@ -2584,35 +2413,13 @@ } }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.3.0.tgz", + "integrity": "sha512-cCdyVjIUVTtX8ZsPkq1oCsOsLmGIswqnjZYMJJTGaNApj1yHtLSymKhwH51ttirREn75z3p4k051clwg7rvNKA==", "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2624,12 +2431,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -2686,6 +2487,7 @@ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -2824,6 +2626,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3001,6 +2804,16 @@ "node": ">=8.0.0" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsdoc/node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -3034,23 +2847,12 @@ "node": ">=10" } }, - "node_modules/jsdoc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/json-buffer": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3064,10 +2866,11 @@ "dev": true }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -3086,6 +2889,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -3139,7 +2943,8 @@ "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.omit": { "version": "4.5.0", @@ -3180,18 +2985,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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/markdown-it": { "version": "12.3.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.3.2.tgz", @@ -3251,28 +3044,6 @@ "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==", "dev": true }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", @@ -3482,18 +3253,6 @@ "node": ">=8" } }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3704,17 +3463,18 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -3817,15 +3577,6 @@ "node": ">=8" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pathval": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", @@ -3861,6 +3612,7 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } @@ -3962,7 +3714,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", @@ -4141,26 +3894,12 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/rss-parser": { "version": "3.13.0", "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.13.0.tgz", @@ -4198,6 +3937,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -4245,13 +3985,11 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4314,15 +4052,6 @@ "url": "https://patreon.com/skyhelper" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/sort-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-2.0.0.tgz", @@ -4358,6 +4087,31 @@ "node": ">=0.10.0" } }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.18", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", + "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "dev": true, + "license": "CC0-1.0" + }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -4417,6 +4171,19 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4518,18 +4285,6 @@ "node": ">=8.0" } }, - "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", - "dev": true, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, "node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -4551,6 +4306,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -4567,18 +4323,6 @@ "node": ">=4" } }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", @@ -4841,12 +4585,6 @@ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", "dev": true }, - "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": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", diff --git a/package.json b/package.json index 75204ddf..43a1852a 100644 --- a/package.json +++ b/package.json @@ -16,15 +16,15 @@ "url": "https://github.com/Hypixel-API-Reborn/hypixel-api-reborn/issues" }, "scripts": { - "lint": "npx eslint --cache src/ typings/", - "lint:fix": "npx eslint --cache src/ typings/ --fix", + "lint": "npx eslint --cache src/", + "lint:fix": "npx eslint --cache src/ --fix", "tests": "npx mocha tests --exit --recursive", "docgen": " npx docgen -s src/ --custom docs/index.yml -o ./master.json", "prettier": "npx prettier --cache --write src/ typings/", "prettier:check": "npx prettier --cache --check src/ typings/" }, "engines": { - "node": ">=14.0.0" + "node": ">=18.18.0" }, "author": "StavZ", "dependencies": { @@ -43,12 +43,10 @@ "devDependencies": { "@discordjs/docgen": "github:discordjs/docgen", "@types/node": "^20.11.19", - "@typescript-eslint/eslint-plugin": "^7.0.2", - "@typescript-eslint/parser": "^7.0.2", "chai": "^4.3.4", - "eslint": "^8.56.0", - "eslint-config-google": "^0.14.0", - "eslint-config-prettier": "^9.1.0", + "eslint": "^9.3.0", + "eslint-plugin-jsdoc": "^48.2.7", + "globals": "^15.3.0", "mocha": "^10.4.0", "node-env-run": "^4.0.2", "path": "^0.12.7", diff --git a/src/API/getAchievements.js b/src/API/getAchievements.js index 60c05fff..392aac51 100644 --- a/src/API/getAchievements.js +++ b/src/API/getAchievements.js @@ -1,5 +1,6 @@ module.exports = async function () { const Achievements = require('../structures/Static/Achievements'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/achievements'); if (res.raw) return res; return new Achievements(res); diff --git a/src/API/getBoosters.js b/src/API/getBoosters.js index 6d806acb..0660ca84 100644 --- a/src/API/getBoosters.js +++ b/src/API/getBoosters.js @@ -1,5 +1,6 @@ module.exports = async function () { const Booster = require('../structures/Boosters/Booster'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/boosters'); if (res.raw) return res; return res.boosters.length ? res.boosters.map((b) => new Booster(b)).reverse() : []; diff --git a/src/API/getChallenges.js b/src/API/getChallenges.js index 75f0eb3f..dc0d7948 100644 --- a/src/API/getChallenges.js +++ b/src/API/getChallenges.js @@ -1,5 +1,6 @@ module.exports = async function () { const Challenges = require('../structures/Static/Challenges'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/challenges'); if (res.raw) return res; return new Challenges(res); diff --git a/src/API/getGameCounts.js b/src/API/getGameCounts.js index 13e939ac..3378f40d 100644 --- a/src/API/getGameCounts.js +++ b/src/API/getGameCounts.js @@ -1,5 +1,6 @@ const GameCounts = require('../structures/GameCounts'); module.exports = async function () { + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/counts'); if (res.raw) return res; return new GameCounts(res); diff --git a/src/API/getGuild.js b/src/API/getGuild.js index aadd9516..fa28b070 100644 --- a/src/API/getGuild.js +++ b/src/API/getGuild.js @@ -4,13 +4,14 @@ const isGuildID = require('../utils/isGuildID'); module.exports = async function (searchParameter, query) { if (!query) throw new Error(Errors.NO_GUILD_QUERY); const Guild = require('../structures/Guild/Guild'); - if (searchParameter === 'id' && !isGuildID(query)) throw new Error(Errors.INVALID_GUILD_ID); - const isPlayerQuery = searchParameter === 'player'; + if ('id' === searchParameter && !isGuildID(query)) throw new Error(Errors.INVALID_GUILD_ID); + const isPlayerQuery = 'player' === searchParameter; if (isPlayerQuery) query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); if (!['id', 'name', 'player'].includes(searchParameter)) throw new Error(Errors.INVALID_GUILD_SEARCH_PARAMETER); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/guild?${searchParameter}=${encodeURI(query)}`); if (res.raw) return res; - if (!res.guild && searchParameter !== 'player') { + if (!res.guild && 'player' !== searchParameter) { throw new Error(Errors.GUILD_DOES_NOT_EXIST); } diff --git a/src/API/getGuildAchievements.js b/src/API/getGuildAchievements.js index 7dbf479d..982ebc7a 100644 --- a/src/API/getGuildAchievements.js +++ b/src/API/getGuildAchievements.js @@ -1,5 +1,6 @@ module.exports = async function () { const GuildAchievements = require('../structures/Static/GuildAchievements'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/guilds/achievements'); if (res.raw) return res; return new GuildAchievements(res); diff --git a/src/API/getLeaderboards.js b/src/API/getLeaderboards.js index 2b6c077b..d7e17a86 100644 --- a/src/API/getLeaderboards.js +++ b/src/API/getLeaderboards.js @@ -1,11 +1,11 @@ const Errors = require('../Errors'); module.exports = async function () { const Leaderboard = require('../structures/Leaderboard'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/leaderboards'); if (res.raw) return res; if (!res.leaderboards) throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, 'Try again.')); const lbnames = Object.create(require('../utils/Constants').leaderboardNames); - // eslint-disable-next-line guard-for-in for (const name in lbnames) { lbnames[name] = res.leaderboards[lbnames[name]].length ? res.leaderboards[lbnames[name]].map((lb) => new Leaderboard(lb)) diff --git a/src/API/getPlayer.js b/src/API/getPlayer.js index 5ca56381..c305cb03 100644 --- a/src/API/getPlayer.js +++ b/src/API/getPlayer.js @@ -6,6 +6,7 @@ module.exports = async function (query, options = { guild: false, recentGames: f if (!query) throw new Error(Errors.NO_NICKNAME_UUID); const Player = require('../structures/Player'); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/player?uuid=${query}`); if (res.raw) return res; if (query && !res.player) throw new Error(Errors.PLAYER_HAS_NEVER_LOGGED); diff --git a/src/API/getQuests.js b/src/API/getQuests.js index 0aac9662..1c6e4d63 100644 --- a/src/API/getQuests.js +++ b/src/API/getQuests.js @@ -1,5 +1,6 @@ module.exports = async function () { const Quests = require('../structures/Static/Quests'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/quests'); if (res.raw) return res; return new Quests(res); diff --git a/src/API/getRecentGames.js b/src/API/getRecentGames.js index a0879ac8..0628291b 100644 --- a/src/API/getRecentGames.js +++ b/src/API/getRecentGames.js @@ -4,12 +4,11 @@ const day3 = 1000 * 60 * 60 * 24 * 3; module.exports = async function (query, playerData) { if (!query) throw new Error(Errors.NO_NICKNAME_UUID); const RecentGame = require('../structures/RecentGame'); - query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); - + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/recentgames?uuid=${query}`); if (res.raw) return res; - if (res.games.length === 0) { + if (0 === res.games.length) { if (!playerData) throw new Error(Errors.PLAYER_IS_INACTIVE); if (Date.now() - playerData.lastLogoutTimestamp < day3) throw new Error(Errors.PLAYER_DISABLED_ENDPOINT); throw new Error(Errors.PLAYER_IS_INACTIVE); diff --git a/src/API/getServerInfo.js b/src/API/getServerInfo.js index f0b8d870..505a16b0 100644 --- a/src/API/getServerInfo.js +++ b/src/API/getServerInfo.js @@ -1,13 +1,43 @@ -const net = require('net'); -const Errors = require('../Errors'); +/* eslint-disable jsdoc/require-jsdoc */ const ServerInfo = require('../structures/ServerInfo'); const varInt = require('../utils/varInt'); +const Errors = require('../Errors'); +const net = require('net'); const packetsToSend = ['1500E0050E6D632E6879706978656C2E6E657463DD01', '0100', '09010000000000000000'].map((x) => + // To avoid dependency hell, these are precompiled as hex. Buffer.from(x, 'hex') -); // To avoid dependency hell, these are precompiled as hex. +); + +async function ping(cli) { + await cli.write(packetsToSend[2]); + const time = Date.now(); + return new Promise((resolve) => { + cli.once('data', () => { + resolve(Date.now() - time); + }); + }); +} + +async function getPing(amount, cli) { + let pingSum = 0; + for (let i = 0; i < amount; i++) { + pingSum += await ping(cli); + } + cli.destroy(); + return Math.round(pingSum / amount); +} + +function parseData(stringJson, ping) { + try { + return new ServerInfo(JSON.parse(stringJson), ping); + } catch { + return undefined; + } +} + module.exports = async function (repeats) { - if (repeats < 0 || typeof repeats !== 'number') repeats = 3; - if (repeats > 10) repeats = 10; + if (0 > repeats || 'number' !== typeof repeats) repeats = 3; + if (10 < repeats) repeats = 10; let aggregatedData = ''; let dataLength = 0; return await new Promise((resolve, reject) => { @@ -20,7 +50,7 @@ module.exports = async function (repeats) { }); cli.on('data', async (data) => { if (!aggregatedData) { - const varIntBorder = data.findIndex((x) => x === 0x00) + 1; + const varIntBorder = data.findIndex((x) => 0x00 === x) + 1; dataLength = varInt( data .toString('hex', 0, varIntBorder) @@ -29,40 +59,13 @@ module.exports = async function (repeats) { ); dataLength -= varIntBorder * 8; aggregatedData += data.toString('utf-8', 5); - } else aggregatedData += data.toString('utf-8'); + } else { + aggregatedData += data.toString('utf-8'); + } if (dataLength >= aggregatedData.length) return; - cli.removeAllListeners('data'); // Remove this listener + cli.removeAllListeners('data'); resolve(parseData(aggregatedData, await getPing(repeats, cli))); }); }); }; -// eslint-disable-next-line require-jsdoc -async function getPing(amount, cli) { - let pingSum = 0; - for (let i = 0; i < amount; i++) { - pingSum += await ping(cli); - } - cli.destroy(); - return Math.round(pingSum / amount); -} - -// eslint-disable-next-line require-jsdoc -async function ping(cli) { - await cli.write(packetsToSend[2]); - const time = Date.now(); - return new Promise((resolve) => { - cli.once('data', () => { - resolve(Date.now() - time); - }); - }); -} - -// eslint-disable-next-line require-jsdoc -function parseData(stringJson, ping) { - try { - return new ServerInfo(JSON.parse(stringJson), ping); - } catch (e) { - return undefined; - } -} diff --git a/src/API/getStatus.js b/src/API/getStatus.js index 8c223ade..e66ec8eb 100644 --- a/src/API/getStatus.js +++ b/src/API/getStatus.js @@ -2,6 +2,7 @@ const toUuid = require('../utils/toUuid'); module.exports = async function (query) { const Status = require('../structures/Status'); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/status?uuid=${query}`); if (res.raw) return res; return new Status(res.session); diff --git a/src/API/getWatchdogStats.js b/src/API/getWatchdogStats.js index f0a87da2..693d73e1 100644 --- a/src/API/getWatchdogStats.js +++ b/src/API/getWatchdogStats.js @@ -1,5 +1,6 @@ module.exports = async function () { const WatchdogStats = require('../structures/Watchdog/Stats'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/punishmentstats'); if (res.raw) return res; return new WatchdogStats(res); diff --git a/src/API/skyblock/getAuction.js b/src/API/skyblock/getAuction.js index 44fa3a01..390417e8 100644 --- a/src/API/skyblock/getAuction.js +++ b/src/API/skyblock/getAuction.js @@ -3,17 +3,19 @@ const toUuid = require('../../utils/toUuid'); module.exports = async function (type, query, includeItemBytes = false) { if (!query) throw new Error(Errors.NO_NICKNAME_UUID); const Auction = require('../../structures/SkyBlock/Auctions/Auction'); - let filter = ''; - if (type === 'PROFILE') { + let filter; + if ('PROFILE' === type) { filter = 'profile'; - } else if (type === 'PLAYER') { + } else if ('PLAYER' === type) { query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); filter = 'player'; - } else if (type === 'AUCTION') { + } else if ('AUCTION' === type) { filter = 'uuid'; - } else throw new Error(Errors.BAD_AUCTION_FILTER); + } else { + throw new Error(Errors.BAD_AUCTION_FILTER); + } + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/auction?${filter}=${query}`); if (res.raw) return res; - return res.auctions.length ? res.auctions.map((a) => new Auction(a, includeItemBytes)) : []; }; diff --git a/src/API/skyblock/getAuctions.js b/src/API/skyblock/getAuctions.js index dffac16c..7a4d341b 100644 --- a/src/API/skyblock/getAuctions.js +++ b/src/API/skyblock/getAuctions.js @@ -1,10 +1,10 @@ -/* eslint-disable require-jsdoc */ +/* eslint-disable jsdoc/require-jsdoc */ const Auction = require('../../structures/SkyBlock/Auctions/Auction'); const AuctionInfo = require('../../structures/SkyBlock/Auctions/AuctionInfo'); const Errors = require('../../Errors'); -let _makeRequest; async function getPage(page = 0, options = {}) { - const content = await _makeRequest(`/skyblock/auctions?page=${page}`, false); + // eslint-disable-next-line no-underscore-dangle + const content = await this._makeRequest(`/skyblock/auctions?page=${page}`, false); const result = {}; if (!options.noInfo) result.info = new AuctionInfo(content); if (options.raw) result.auctions = content.auctions; @@ -16,24 +16,24 @@ async function noReject(promise, args = [], retries = 3, cooldown = 100) { try { const result = await promise.call(null, ...args); return result; - } catch (e) { + } catch { if (retries) { await new Promise((resolve) => setTimeout(resolve, cooldown)); return await noReject(promise, args, retries - 1, cooldown); - } else return null; + } + return null; } } module.exports = async function (range, options = {}) { - _makeRequest = this._makeRequest; - options.retries = options.retries || 3; - options.cooldown = options.cooldown || 100; - if (range == null || range === '*') range = [0, (await getPage(0, { noAuctions: true })).info.totalPages]; + options.retries ||= 3; + options.cooldown ||= 100; + if (null === range || '*' === range) range = [0, (await getPage(0, { noAuctions: true })).info.totalPages]; if (!Array.isArray(range)) range = [parseInt(range), parseInt(range)]; if (isNaN(range[0])) throw new Error(Errors.PAGE_INDEX_ERROR); - if (parseInt(options.retries) !== options.retries || options.retries > 10 || options.retries < 0) { + if (parseInt(options.retries) !== options.retries || 10 < options.retries || 0 > options.retries) { throw new Error(Errors.INVALID_OPTION_VALUE); } - if (parseInt(options.cooldown) !== options.cooldown || options.cooldown > 3000 || options.cooldown < 0) { + if (parseInt(options.cooldown) !== options.cooldown || 3000 < options.cooldown || 0 > options.cooldown) { throw new Error(Errors.INVALID_OPTION_VALUE); } range = range.sort(); @@ -49,7 +49,9 @@ module.exports = async function (range, options = {}) { if (resp) { result.auctions = result.auctions.concat(resp.auctions); if (resp.info) result.info = resp.info; - } else failedPages.push(i); + } else { + failedPages.push(i); + } } } if (fetches.length) { @@ -63,6 +65,7 @@ module.exports = async function (range, options = {}) { return pV; }, []); } + // eslint-disable-next-line no-underscore-dangle result.info = result.info ? result.info._extend('failedPages', failedPages) : { failedPages }; return result; }; diff --git a/src/API/skyblock/getAuctionsByPlayer.js b/src/API/skyblock/getAuctionsByPlayer.js index 2ef53e9e..4e24f381 100644 --- a/src/API/skyblock/getAuctionsByPlayer.js +++ b/src/API/skyblock/getAuctionsByPlayer.js @@ -4,8 +4,8 @@ module.exports = async function (query, includeItemBytes = false) { if (!query) throw new Error(Errors.NO_NICKNAME_UUID); const Auction = require('../../structures/SkyBlock/Auctions/Auction'); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/auction?player=${query}`); if (res.raw) return res; - return res.auctions.length ? res.auctions.map((a) => new Auction(a, includeItemBytes)) : []; }; diff --git a/src/API/skyblock/getBazaar.js b/src/API/skyblock/getBazaar.js index 88e1197d..1576917e 100644 --- a/src/API/skyblock/getBazaar.js +++ b/src/API/skyblock/getBazaar.js @@ -1,10 +1,8 @@ module.exports = async function () { const Product = require('../../structures/SkyBlock/Bazzar/Product'); - + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/skyblock/bazaar'); if (res.raw) return res; - const productsKeys = Object.keys(res.products); - return productsKeys.map((x) => new Product(res.products[x])); }; diff --git a/src/API/skyblock/getBingo.js b/src/API/skyblock/getBingo.js index 4c2baa1c..978c9e0f 100644 --- a/src/API/skyblock/getBingo.js +++ b/src/API/skyblock/getBingo.js @@ -1,8 +1,7 @@ module.exports = async function () { const BingoData = require('../../structures/SkyBlock/Static/BingoData'); - + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/skyblock/bingo'); if (res.raw) return res; - return new BingoData(res); }; diff --git a/src/API/skyblock/getBingoByPlayer.js b/src/API/skyblock/getBingoByPlayer.js index fe350862..634f8e4c 100644 --- a/src/API/skyblock/getBingoByPlayer.js +++ b/src/API/skyblock/getBingoByPlayer.js @@ -1,14 +1,14 @@ -const getBingo = require('./getBingo'); const toUuid = require('../../utils/toUuid'); +const getBingo = require('./getBingo'); const Errors = require('../../Errors'); module.exports = async function (query, { fetchBingoData = false }) { if (!query) throw new Error(Errors.NO_NICKNAME_UUID); const PlayerBingo = require('../../structures/SkyBlock/PlayerBingo'); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/uuid?player=${query}`); if (res.raw) return res; let bingoData = null; if (fetchBingoData) bingoData = await getBingo.call(this); - - return new PlayerBingo(data, bingoData); + return new PlayerBingo(res, bingoData); }; diff --git a/src/API/skyblock/getEndedAuctions.js b/src/API/skyblock/getEndedAuctions.js index 5652b7e4..b6b993ed 100644 --- a/src/API/skyblock/getEndedAuctions.js +++ b/src/API/skyblock/getEndedAuctions.js @@ -1,6 +1,7 @@ const PartialAuction = require('../../structures/SkyBlock/Auctions/PartialAuction'); const AuctionInfo = require('../../structures/SkyBlock/Auctions/AuctionInfo'); module.exports = async function (includeItemBytes = false) { + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/skyblock/auctions_ended', false); if (res.raw) return res; return { diff --git a/src/API/skyblock/getFireSales.js b/src/API/skyblock/getFireSales.js index cd9f8e49..32a79b1b 100644 --- a/src/API/skyblock/getFireSales.js +++ b/src/API/skyblock/getFireSales.js @@ -1,7 +1,7 @@ module.exports = async function () { const FireSale = require('../../structures/SkyBlock/Static/FireSale'); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/skyblock/firesales'); if (res.raw) return res; - return res.sales.length ? res.sales.map((a) => new FireSale(a)) : []; }; diff --git a/src/API/skyblock/getGovernment.js b/src/API/skyblock/getGovernment.js index 7f60aed5..1e465750 100644 --- a/src/API/skyblock/getGovernment.js +++ b/src/API/skyblock/getGovernment.js @@ -1,8 +1,7 @@ module.exports = async function () { const GovernmentData = require('../../structures/SkyBlock/Static/Government.js'); - + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/resources/skyblock/election'); if (res.raw) return res; - return new GovernmentData(res); }; diff --git a/src/API/skyblock/getMember.js b/src/API/skyblock/getMember.js index aeafc4ad..0ffd45ca 100644 --- a/src/API/skyblock/getMember.js +++ b/src/API/skyblock/getMember.js @@ -6,6 +6,7 @@ module.exports = async function (query, options = { fetchPlayer: false, getMuseu const getSkyblockMuseum = require('../skyblock/getMuseum'); if (!query) throw new Error(Errors.NO_NICKNAME_UUID); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`); if (res.raw) return res; if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); diff --git a/src/API/skyblock/getMuseum.js b/src/API/skyblock/getMuseum.js index 20d459a0..370c8879 100644 --- a/src/API/skyblock/getMuseum.js +++ b/src/API/skyblock/getMuseum.js @@ -4,6 +4,7 @@ module.exports = async function (query, profileId) { const SkyblockMuseum = require('../../structures/SkyBlock/SkyblockMuseum'); if (!query) throw new Error(Errors.NO_NICKNAME_UUID); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/museum?uuid=${query}&profile=${profileId}`); if (res.raw) return res; return new SkyblockMuseum({ diff --git a/src/API/skyblock/getNews.js b/src/API/skyblock/getNews.js index 4037e253..a4cee626 100644 --- a/src/API/skyblock/getNews.js +++ b/src/API/skyblock/getNews.js @@ -1,5 +1,6 @@ const SkyblockNews = require('../../structures/SkyBlock/News/SkyblockNews'); module.exports = async function () { + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest('/skyblock/news'); if (res.raw) return res; return res.items.map((i) => new SkyblockNews(i)); diff --git a/src/API/skyblock/getProfiles.js b/src/API/skyblock/getProfiles.js index 5473084c..490429df 100644 --- a/src/API/skyblock/getProfiles.js +++ b/src/API/skyblock/getProfiles.js @@ -6,6 +6,7 @@ module.exports = async function (query, options = { fetchPlayer: false, getMuseu const getSkyblockMuseum = require('../skyblock/getMuseum'); if (!query) throw new Error(Errors.NO_NICKNAME_UUID); query = await toUuid(query, this.options.mojangCacheTime, this.options.useThirdPartyAPI); + // eslint-disable-next-line no-underscore-dangle const res = await this._makeRequest(`/skyblock/profiles?uuid=${query}`); if (res.raw) return res; if (!res.profiles || !res.profiles.length) throw new Error(Errors.NO_SKYBLOCK_PROFILES); diff --git a/src/Client.js b/src/Client.js index 49511f4f..77fdf68f 100644 --- a/src/Client.js +++ b/src/Client.js @@ -1,13 +1,37 @@ -/* eslint-disable require-jsdoc */ -/* eslint-disable max-len */ -const validate = new (require('./Private/validate'))(); const rateLimit = new (require('./Private/rateLimit'))(); -const Requests = require('./Private/requests'); +const validate = new (require('./Private/validate'))(); const updater = new (require('./Private/updater'))(); +const Requests = require('./Private/requests'); +const EventEmitter = require('events'); const Errors = require('./Errors'); const API = require('./API/index'); -const EventEmitter = require('events'); const clients = []; + +/* eslint-disable */ +const Player = require('./structures/Player'); +const Guild = require('./structures/Guild/Guild'); +const WatchdogStats = require('./structures/Watchdog/Stats'); +const Booster = require('./structures/Boosters/Booster'); +const SkyblockProfile = require('./structures/SkyBlock/SkyblockProfile'); +const SkyblockMember = require('./structures/SkyBlock/SkyblockMember'); +const SkyblockMuseum = require('./structures/SkyBlock/SkyblockMuseum'); +const APIStatus = require('./structures/APIStatus'); +const Leaderboard = require('./structures/Leaderboard'); +const ServerInfo = require('./structures/ServerInfo'); +const RecentGame = require('./structures/RecentGame'); +const Status = require('./structures/Status'); +const Auction = require('./structures/SkyBlock/Auctions/Auction'); +const AuctionInfo = require('./structures/SkyBlock/Auctions/AuctionInfo'); +const PartialAuction = require('./structures/SkyBlock/Auctions/PartialAuction'); +const Product = require('./structures/SkyBlock/Bazzar/Product'); +const BingoData = require('./structures/SkyBlock/Static/BingoData'); +const PlayerBingo = require('./structures/SkyBlock/PlayerBingo'); +const GovernmentData = require('./structures/SkyBlock/Static/Government'); +const FireSale = require('./structures/SkyBlock/Static/FireSale'); +const SkyblockNews = require('./structures/SkyBlock/News/SkyblockNews'); +const GameCounts = require('./structures/GameCounts'); +/* eslint-enable */ + /** * Client class */ @@ -15,6 +39,7 @@ class Client extends EventEmitter { /** * @param {string} key API key * @param {ClientOptions} [options={}] Client options + * @example */ constructor(key, options = {}) { super(); @@ -30,12 +55,13 @@ class Client extends EventEmitter { this.key = validate.validateKey(key); this.options = validate.parseOptions(options); validate.validateOptions(this.options); - // eslint-disable-next-line guard-for-in + for (const func in API) { Client.prototype[func] = (...args) => { const lastArg = args[args.length - 1]; return API[func].apply( { + // eslint-disable-next-line no-underscore-dangle _makeRequest: this._makeRequest.bind(this, validate.cacheSuboptions(lastArg) ? lastArg : {}), ...this }, @@ -65,11 +91,12 @@ class Client extends EventEmitter { * @param {boolean} [useRateLimitManager=true] Use rate limit * @returns {Promise} Response * @private + * @example */ async _makeRequest(options, url, useRateLimitManager = true) { if (!url) return; - if (url !== '/key' && !options.noCacheCheck && (await this.requests.cache.has(url))) { - return Object.assign(await this.requests.cache.get(url), { raw: !!options.raw }); + if ('/key' !== url && !options.noCacheCheck && (await this.requests.cache.has(url))) { + return Object.assign(await this.requests.cache.get(url), { raw: Boolean(options.raw) }); } if (useRateLimitManager) await rateLimit.rateLimitManager(); this.emit('outgoingRequest', url, { ...options, headers: { ...options.headers, ...this.options.headers } }); @@ -77,12 +104,13 @@ class Client extends EventEmitter { ...options, headers: { ...options.headers, ...this.options.headers } }); + // eslint-disable-next-line no-underscore-dangle if (this.options.syncWithHeaders) rateLimit.sync(result._headers); return result; } /** * Emitted when rate limiter is ready. ( You don't have to wait for this event to emit UNLESS you are planning to do data scraping which means spamming requests ) - * @event + * @event ready * @name Client#ready * @example * // This example gets player's uuid. @@ -94,14 +122,14 @@ class Client extends EventEmitter { */ /** * Emitted when a request is going to be sent - * @event + * @event outgoingRequest * @name Client#outgoingRequest * @param {string} url URL * @param {object} [options] Options, if any */ /** * Emitted when there is a warning. - * @event + * @event warn * @name Client#warn * @param {string} error Warning Message */ @@ -140,7 +168,7 @@ class Client extends EventEmitter { * Allows you to get statistics of hypixel guild * @method * @name Client#getGuild - * @param {id|name|player} searchParameter Search for guild by id, name or player (if player is in guild) + * @param {'id'|'name'|'player'} searchParameter Search for guild by id, name or player (if player is in guild) * @param {string} query Guild ID, Guild name or player uuid/nickname * @param {MethodOptions} [options={}] Method options * @return {Promise} @@ -347,7 +375,8 @@ class Client extends EventEmitter { * console.log(products[0].productId); // INK_SACK:3 * }) * .catch(console.log); - */ /** + */ + /** * Allows you to get bingo data * @method * @name Client#getSkyblockBingo @@ -404,6 +433,7 @@ class Client extends EventEmitter { * Delete x (by default all) cache entries * @param {?number} amount Amount of cache to delete * @return {Promise} + * @example */ sweepCache(amount) { return this.requests.sweepCache(amount); @@ -415,7 +445,7 @@ class Client extends EventEmitter { * @prop {number} [hypixelCacheTime=60] Amount of time in seconds to cache the hypixel api requests. * @prop {number} [mojangCacheTime=600] Amount of time in seconds to cache the mojang api requests. * @prop {CacheHandler} [cacheHandler] Custom Cache Handler - * @prop {AUTO|HARD|NONE} [rateLimit='AUTO'] Rate limit mode. + * @prop {'AUTO'|'HARD'|'NONE'} [rateLimit='AUTO'] Rate limit mode. * @prop {boolean} [syncWithHeaders=false] Sync with headers rate limit information. Usually not necessary nor recommended ( because of latency ) * @prop {number} [keyLimit=60] Key limit of your key. * @prop {number} [cacheSize=-1] The amount how many results will be cached. (`-1` for infinity) @@ -424,6 +454,7 @@ class Client extends EventEmitter { * @prop {boolean} [checkForUpdates=true] Enable/Disable check for new version of hypixel-api-reborn. * @prop {boolean|string} [useThirdPartyAPI=false] Enable/Disable Mojang Third Party API */ +// eslint-disable-next-line no-unused-vars const defaultCache = require('./Private/defaultCache.js'); /** * @typedef {defaultCache} Cache diff --git a/src/Private/defaultCache.js b/src/Private/defaultCache.js index 6fc8606b..e11aeba5 100644 --- a/src/Private/defaultCache.js +++ b/src/Private/defaultCache.js @@ -13,6 +13,7 @@ class Cache { /** * Constructor + * @example */ constructor() { this.storage = new Map(); @@ -22,6 +23,7 @@ class Cache { * @param {string} key String key * @param {*} value Any value * @return {boolean} + * @example */ set(key, value) { return this.storage.set(key, value); @@ -31,6 +33,7 @@ class Cache { * This doesn't have to return boolean, just a truthy/falsy value * @param {string} key String key * @return {boolean} Whether this key exists + * @example */ has(key) { return this.storage.has(key); @@ -39,6 +42,7 @@ class Cache { * Gets an entry, return a nullish value if not found * @param {string} key String key * @return {*} + * @example */ get(key) { return this.storage.get(key); @@ -47,6 +51,7 @@ class Cache { * Deletes an entry * @param {string} key String key * @return {boolean} Preferably, returns a boolean to check if the deletion is actually successful + * @example */ delete(key) { return this.storage.delete(key); @@ -54,6 +59,7 @@ class Cache { /** * Returns Array of string (not an iterator preferably, it can break) * @return {string[]} + * @example */ keys() { return Array.from(this.storage.keys()); @@ -61,6 +67,7 @@ class Cache { /** * Returns size of cache * @return {number} + * @example */ size() { return this.storage.size; @@ -68,6 +75,7 @@ class Cache { /** * Clears cache * @return {void} + * @example */ clear() { this.storage.clear(); diff --git a/src/Private/rateLimit.js b/src/Private/rateLimit.js index 90e07da5..3f32fb87 100644 --- a/src/Private/rateLimit.js +++ b/src/Private/rateLimit.js @@ -1,8 +1,5 @@ -/* eslint-disable @typescript-eslint/no-empty-function */ -/* eslint-disable camelcase */ const Errors = require('../Errors'); -/* eslint-disable require-jsdoc */ class RateLimit { constructor() { this.initialized = 0; @@ -12,12 +9,11 @@ class RateLimit { if (!this.initialized) return; this.requests++; this.requestQueue.unshift(Date.now()); - if (this.options.rateLimit === 'NONE' || !this.requestQueue.length) return; - if (this.options.rateLimit === 'AUTO' && this.requests <= this.options.keyLimit / 2) return; + if ('NONE' === this.options.rateLimit || !this.requestQueue.length) return; + if ('AUTO' === this.options.rateLimit && this.requests <= this.options.keyLimit / 2) return; const cooldown = this.computeCooldownTime(); this.requestQueue[0] = Date.now() + cooldown; - await new Promise((r) => setTimeout(r, cooldown), true); - return; + return await new Promise((r) => setTimeout(r, cooldown), true); } sync(data) { @@ -45,7 +41,7 @@ class RateLimit { reset() { this.requests = this.requests - this.options.keyLimit; - if (this.requests < 0) this.requests = 0; + if (0 > this.requests) this.requests = 0; this.lastResetHappenedAt = Date.now(); this.resetTimer = setTimeout(this.reset.bind(this), 300000); this.requestQueue = this.requestQueue.filter((x) => x >= Date.now()); @@ -58,13 +54,13 @@ class RateLimit { init(keyInfo, options, client) { this.options = options; this.requests = 0; - this.cooldownTime = 300000 / this.options.keyLimit; // Initial value + this.cooldownTime = 300000 / this.options.keyLimit; this.requestQueue = []; this.client = client; return keyInfo .then((info) => { this.requests = info.requestsInPastMin; - this.lastResetHappenedAt = Date.now() - (300 - info.resetsAfter) * 1000; // Computed reset time + this.lastResetHappenedAt = Date.now() - (300 - info.resetsAfter) * 1000; this.resetTimer = setTimeout(this.rateLimitMonitor.bind(this), 1000 * info.resetsAfter); this.initialized = 1; }) @@ -82,6 +78,6 @@ module.exports = RateLimit; /** * @typedef {Object} RLOptions * @property {number} keyLimit Max request of key per min - * @property {NONE|AUTO|HARD} rateLimit rate limit mode + * @property {'NONE'|'AUTO'|'HARD'} rateLimit rate limit mode * @property {boolean} syncWithHeaders Sync rate limits with headers */ diff --git a/src/Private/requests.js b/src/Private/requests.js index 54dc5a44..76ad9007 100644 --- a/src/Private/requests.js +++ b/src/Private/requests.js @@ -1,11 +1,9 @@ -/* eslint-disable require-jsdoc */ const requireFetch = !globalThis.fetch; const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const fetch = requireFetch ? externalFetch : globalThis.fetch; const BASE_URL = 'https://api.hypixel.net/v2'; -const Errors = require('../Errors'); const Cache = require('./defaultCache'); -const Client = require('../Client.js'); +const Errors = require('../Errors'); class Requests { constructor(client, cache) { @@ -19,7 +17,7 @@ class Requests { * @type {externalFetch.Response|Response} */ const res = await fetch(BASE_URL + endpoint, options); - if (res.status >= 500 && res.status < 528) { + if (500 <= res.status && 528 > res.status) { throw new Error( Errors.ERROR_STATUSTEXT.replace(/{statustext}/, `Server Error : ${res.status} ${res.statusText}`) ); @@ -27,20 +25,21 @@ class Requests { const parsedRes = await res.json().catch(() => { throw new Error(Errors.INVALID_RESPONSE_BODY); }); - if (res.status === 400) { + if (400 === res.status) { throw new Error( Errors.ERROR_CODE_CAUSE.replace(/{code}/, '400 Bad Request').replace(/{cause}/, parsedRes.cause || '') ); } - if (res.status === 403) throw new Error(Errors.INVALID_API_KEY); - if (res.status === 422) throw new Error(Errors.UNEXPECTED_ERROR); - if (res.status === 429) throw new Error(Errors.RATE_LIMIT_EXCEEDED); - if (res.status !== 200) throw new Error(Errors.ERROR_STATUSTEXT.replace(/{statustext}/, res.statusText)); + if (403 === res.status) throw new Error(Errors.INVALID_API_KEY); + if (422 === res.status) throw new Error(Errors.UNEXPECTED_ERROR); + if (429 === res.status) throw new Error(Errors.RATE_LIMIT_EXCEEDED); + if (200 !== res.status) throw new Error(Errors.ERROR_STATUSTEXT.replace(/{statustext}/, res.statusText)); if (!parsedRes.success) { throw new Error(Errors.SOMETHING_WENT_WRONG.replace(/{cause}/, res.cause)); } + // eslint-disable-next-line no-underscore-dangle parsedRes._headers = res.headers; - parsedRes.raw = !!options.raw; + parsedRes.raw = Boolean(options.raw); if (options.noCaching) return parsedRes; // split by question mark : first part is /path, remove / if (this.client.options.cache && this.client.options.cacheFilter(endpoint.split('?')[0].slice(1))) { @@ -49,7 +48,7 @@ class Requests { } await this.cached.delete(endpoint); await this.cached.set(endpoint, parsedRes); - if (this.client.options.hypixelCacheTime >= 0) { + if (0 <= this.client.options.hypixelCacheTime) { setTimeout(() => this.cached.delete(endpoint), 1000 * this.client.options.hypixelCacheTime); } } @@ -70,7 +69,7 @@ class Requests { } validateCustomCache(cache) { - return !!(cache.set && cache.get && cache.delete && cache.keys); + return Boolean(cache.set && cache.get && cache.delete && cache.keys); } } diff --git a/src/Private/updater.js b/src/Private/updater.js index e886f9e3..ff5768bd 100644 --- a/src/Private/updater.js +++ b/src/Private/updater.js @@ -1,4 +1,3 @@ -/* eslint-disable require-jsdoc */ /* eslint-disable no-console */ const requireFetch = !globalThis.fetch; const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); @@ -12,7 +11,7 @@ class Updater { const metadata = await request.json(); const latest = metadata['dist-tags'].latest; const compare = this.compare(version, latest); - if (compare === -1) { + if (-1 === compare) { console.log( `New version of hypixel-api-reborn is available! Current version: ${version}, Latest version: ${latest}` ); @@ -21,7 +20,7 @@ class Updater { compare(a, b) { const pa = a.split('.'); const pb = b.split('.'); - for (let i = 0; i < 3; i++) { + for (let i = 0; 3 > i; i++) { const na = Number(pa[i]); const nb = Number(pb[i]); if (na > nb) return 1; diff --git a/src/Private/uuidCache.js b/src/Private/uuidCache.js index 5bd56cf7..2a59bae9 100644 --- a/src/Private/uuidCache.js +++ b/src/Private/uuidCache.js @@ -1,4 +1,3 @@ -/* eslint-disable require-jsdoc */ const requireFetch = !globalThis.fetch; const externalFetch = (...args) => import('node-fetch').then(({ default: fetch }) => fetch(...args)); const fetch = requireFetch ? externalFetch : globalThis.fetch; @@ -12,7 +11,7 @@ module.exports = async (url, query, cacheTime) => { const res = await fetch(url); const data = await res.json(); // Don't cache 4xx - if (res.status >= 400) { + if (400 <= res.status) { return { status: res.status, id: null, diff --git a/src/Private/validate.js b/src/Private/validate.js index bcbf424d..08f58b03 100644 --- a/src/Private/validate.js +++ b/src/Private/validate.js @@ -1,4 +1,3 @@ -/* eslint-disable require-jsdoc */ const Errors = require('../Errors'); const { isStrArray, strToArray } = require('../utils/arrayTools'); /** @@ -10,19 +9,20 @@ class Validation { * @param {Object} options Global Cache Options to be validated * @returns {void} Void * @private + * @example */ validateOptions(options) { - if (typeof options.hypixelCacheTime !== 'number') throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); - if (typeof options.mojangCacheTime !== 'number') throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); - if (typeof options.cacheSize !== 'number') throw new Error(Errors.CACHE_LIMIT_MUST_BE_A_NUMBER); - if (typeof options.rateLimit !== 'string' || !['AUTO', 'HARD', 'NONE'].includes(options.rateLimit)) { + if ('number' !== typeof options.hypixelCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); + if ('number' !== typeof options.mojangCacheTime) throw new Error(Errors.CACHE_TIME_MUST_BE_A_NUMBER); + if ('number' !== typeof options.cacheSize) throw new Error(Errors.CACHE_LIMIT_MUST_BE_A_NUMBER); + if ('string' !== typeof options.rateLimit || !['AUTO', 'HARD', 'NONE'].includes(options.rateLimit)) { throw new Error(Errors.INVALID_RATE_LIMIT_OPTION); } - if (typeof options.keyLimit !== 'number') throw new Error(Errors.INVALID_KEY_LIMIT_OPTION); - if (typeof options.syncWithHeaders !== 'boolean') throw new Error(Errors.INVALID_HEADER_SYNC_OPTION); - if (typeof options.headers !== 'object') throw new Error(Errors.INVALID_HEADERS); - if (typeof options.silent !== 'boolean') throw new Error(Errors.INVALID_SILENT_OPTION); - if (typeof options.checkForUpdates !== 'boolean') throw new Error(Errors.INVALID_UPDATE_OPTION); + if ('number' !== typeof options.keyLimit) throw new Error(Errors.INVALID_KEY_LIMIT_OPTION); + if ('boolean' !== typeof options.syncWithHeaders) throw new Error(Errors.INVALID_HEADER_SYNC_OPTION); + if ('object' !== typeof options.headers) throw new Error(Errors.INVALID_HEADERS); + if ('boolean' !== typeof options.silent) throw new Error(Errors.INVALID_SILENT_OPTION); + if ('boolean' !== typeof options.checkForUpdates) throw new Error(Errors.INVALID_UPDATE_OPTION); if (!['boolean', 'string'].includes(typeof options.useThirdPartyAPI)) { throw new Error(Errors.INVALID_THIRD_PARTY_API_OPTION); } @@ -33,21 +33,23 @@ class Validation { * @param {Object} options Options to be parsed * @returns {Object} Parsed cache options * @private + * @example */ parseOptions(options) { - if (typeof options !== 'object' || options === null) throw new Error(Errors.OPTIONS_MUST_BE_AN_OBJECT); + if ('object' !== typeof options || null === options) throw new Error(Errors.OPTIONS_MUST_BE_AN_OBJECT); return { cache: options.cache ?? true, hypixelCacheTime: options.hypixelCacheTime ?? 60, mojangCacheTime: options.mojangCacheTime ?? 600, - cacheSize: (options.cacheSize === -1 ? Infinity : options.cacheSize) || Infinity, + cacheSize: (-1 === options.cacheSize ? Infinity : options.cacheSize) || Infinity, cacheFilter: - typeof options.cacheFilter === 'function' ? options.cacheFilter : this._handleFilter(options.cacheFilter), + // eslint-disable-next-line no-underscore-dangle + 'function' === typeof options.cacheFilter ? options.cacheFilter : this._handleFilter(options.cacheFilter), rateLimit: options.rateLimit ?? 'AUTO', keyLimit: options.keyLimit ?? 60, - syncWithHeaders: !!options.syncWithHeaders, + syncWithHeaders: Boolean(options.syncWithHeaders), headers: options.headers ?? {}, - silent: !!options.silent, + silent: Boolean(options.silent), checkForUpdates: options.checkForUpdates ?? true, useThirdPartyAPI: options.useThirdPartyAPI ?? false }; @@ -58,10 +60,11 @@ class Validation { * @param {string} key API Key * @returns {string} Key * @private + * @example */ validateKey(key) { if (!key) throw new Error(Errors.NO_API_KEY); - if (typeof key !== 'string') throw new Error(Errors.KEY_MUST_BE_A_STRING); + if ('string' !== typeof key) throw new Error(Errors.KEY_MUST_BE_A_STRING); return key; } @@ -70,9 +73,10 @@ class Validation { * @param {Object} input Cache options * @returns {boolean} Whether options are valid * @private + * @example */ cacheSuboptions(input) { - if (typeof input !== 'object' || input === null) return false; + if ('object' !== typeof input || null === input) return false; if (!input.noCacheCheck && !input.noCaching && !input.raw) return false; return true; } @@ -82,10 +86,11 @@ class Validation { * @param {*} filter FilterResolvable to be parsed * @returns {Function} Filter function * @private + * @example */ _handleFilter(filter) { if (!filter) return () => true; - if (typeof filter === 'object' && !Array.isArray(filter)) { + if ('object' === typeof filter && !Array.isArray(filter)) { if (filter.whitelist && isStrArray(filter.whitelist)) return (x) => strToArray(filter.whitelist).includes(x); if (filter.blacklist && isStrArray(filter.blacklist)) return (x) => !strToArray(filter.blacklist).includes(x); throw new Error(Errors.CACHE_FILTER_INVALID); @@ -99,10 +104,11 @@ class Validation { * -12 will return an error; -14 will result in a warning * @returns {void} * @private + * @example */ validateNodeVersion() { const nodeVersion = parseInt(process.version.match(/v(\d{2})\.\d{1,}\.\d+/)[1], 10); - if (nodeVersion < 12) throw new Error(Errors.NODE_VERSION_ERR); + if (12 > nodeVersion) throw new Error(Errors.NODE_VERSION_ERR); } } module.exports = Validation; diff --git a/src/structures/APIIncident.js b/src/structures/APIIncident.js index c8289576..249827e3 100644 --- a/src/structures/APIIncident.js +++ b/src/structures/APIIncident.js @@ -5,6 +5,7 @@ const regex = /https:\/\/status.hypixel.net\/incidents\/([a-z0-9]+)/; class APIIncident { /** * @param {object} data API incident data + * @example */ constructor(data) { /** @@ -16,7 +17,7 @@ class APIIncident { * Timestamp when investigation was started as Date object * @type {object|null} */ - this.start = new Date(data.pubDate) || null; + this.start = data.pubDate ? new Date(data.pubDate) : null; /** * Formatted timestamp when investigation was started * @type {string|null} @@ -56,13 +57,13 @@ class APIIncident { * Whether the incident is resolved/completed or not * @author linearaccelerator * @type {boolean} - * @version >6.0.1 */ this.isResolved = this.HTMLContent.includes('Resolved -') || this.HTMLContent.includes('Completed -'); } /** * HTML Content * @return {string} + * @example */ toString() { return this.HTMLContent; diff --git a/src/structures/APIStatus.js b/src/structures/APIStatus.js index 153ce889..05f9dfde 100644 --- a/src/structures/APIStatus.js +++ b/src/structures/APIStatus.js @@ -5,6 +5,7 @@ const APIIncident = require('./APIIncident'); class APIStatus { /** * @param {object} data API status data + * @example */ constructor(data) { /** @@ -31,13 +32,13 @@ class APIStatus { * All incidents that aren't completed/resolved * @author linearaccelerator * @type {APIIncident[]} - * @version >6.0.1 */ this.currentIncidents = this.incidents.filter((i) => !i.isResolved); } /** * Status Title * @return {string} + * @example */ toString() { return this.title; diff --git a/src/structures/Boosters/Booster.js b/src/structures/Boosters/Booster.js index f26e2e58..44113616 100644 --- a/src/structures/Boosters/Booster.js +++ b/src/structures/Boosters/Booster.js @@ -1,10 +1,19 @@ const Game = require('../Game'); + +// eslint-disable-next-line jsdoc/require-jsdoc +function parseType(data) { + if (true === data.stacked) return 'STACKED'; + if (!data.stacked) return 'QUEUED'; + return 'ACTIVE'; +} + /** * Booster class */ class Booster { /** * @param {object} data + * @example */ constructor(data) { /** @@ -63,21 +72,15 @@ class Booster { * Works by checking if date.length is negative * @type {boolean} */ - this.expired = data.length < 0; + this.expired = 0 > data.length; } /** * Beautiful format * @return {string} + * @example */ toString() { return `${this.purchaser}'s booster in ${this.game}`; } } - -// eslint-disable-next-line require-jsdoc -function parseType(data) { - if (data.stacked === true) return 'STACKED'; - if (!data.stacked) return 'QUEUED'; - return 'ACTIVE'; -} module.exports = Booster; diff --git a/src/structures/Color.js b/src/structures/Color.js index 9c50d6a7..8be407f0 100644 --- a/src/structures/Color.js +++ b/src/structures/Color.js @@ -4,6 +4,7 @@ class Color { /** * @param {ColorCode} color Color code + * @example */ constructor(color) { this.color = color; @@ -12,6 +13,7 @@ class Color { /** * Returns regular color name * @return {ColorString} + * @example */ toString() { const ColorStrings = { @@ -38,6 +40,7 @@ class Color { /** * Returns color HEX code * @return {ColorHex} + * @example */ toHex() { const ColorHex = { @@ -64,6 +67,7 @@ class Color { /** * Returns color code * @return {ColorCode} + * @example */ toCode() { return this.color; @@ -72,6 +76,7 @@ class Color { /** * Returns color code * @return {InGameCode} + * @example */ toInGameCode() { const InGameCodes = { diff --git a/src/structures/Game.js b/src/structures/Game.js index d014d78d..ef43d007 100644 --- a/src/structures/Game.js +++ b/src/structures/Game.js @@ -5,6 +5,7 @@ const { games } = require('../utils/Constants'); class Game { /** * @param {GameId|GameCode} game Game ID or Game Code + * @example */ constructor(game) { /** @@ -34,12 +35,13 @@ class Game { * Whether the game is found * @type {boolean} */ - this.found = !!result; + this.found = Boolean(result); } /** * Returns regular game name * @return {GameString} + * @example */ toString() { return this.name; diff --git a/src/structures/GameCounts.js b/src/structures/GameCounts.js index 6e4077f5..9b5d4786 100644 --- a/src/structures/GameCounts.js +++ b/src/structures/GameCounts.js @@ -6,6 +6,7 @@ const { removeSnakeCaseString, recursive } = require('../utils/removeSnakeCase') class GameCounts { /** * @param {object} data + * @example */ constructor(data) { /** diff --git a/src/structures/Guild/Guild.js b/src/structures/Guild/Guild.js index 7b03fe6e..c642332a 100644 --- a/src/structures/Guild/Guild.js +++ b/src/structures/Guild/Guild.js @@ -1,8 +1,8 @@ +const { getGuildLevel, ranks, members, totalWeeklyGexp, calculateExpHistory } = require('../../utils/Guild'); const GuildMember = require('./GuildMember'); const GuildRank = require('./GuildRank'); const Color = require('../Color'); const Game = require('../Game'); -const { getGuildLevel, parseHistory } = require('../../utils/guildExp'); /** * Guild class */ @@ -10,12 +10,15 @@ class Guild { /** * @param {data} data Guild data * @param {string} [me] Player uuid u#sed to search for this guild + * @example */ constructor(data, me = '') { /** * Guild ID * @type {string} */ + + // eslint-disable-next-line no-underscore-dangle this.id = data._id; /** * Guild name @@ -62,6 +65,7 @@ class Guild { * An array containing all guild ranks sorted by newest * @author linearaccelerator * @return {Array} + * @example */ this.getRanksByNewest = function () { return this.ranks.length @@ -72,6 +76,7 @@ class Guild { * A map containing all guild members, keyed by their uuids * @author linearaccelerator * @return {Map} + * @example */ this.getMemberUUIDMap = function () { return this.members.length ? new Map(this.members.map((m) => [m.uuid, m])) : null; @@ -81,6 +86,7 @@ class Guild { * @author linearaccelerator * @param {number} priority - The priority of the guild rank * @return {GuildRank} + * @example */ this.getRankByPriority = function (priority) { if (!this.ranks.length || !this.ranks.some((r) => r.priority === priority)) return null; @@ -105,7 +111,7 @@ class Guild { * Whether this guild is listed in the Guild Finder * @type {boolean} */ - this.publiclyListed = !!data.publiclyListed; + this.publiclyListed = Boolean(data.publiclyListed); /** * Timestamp guild chat will be unmuted at. * @type {number|null} @@ -115,7 +121,7 @@ class Guild { * Timestamp guild chat will be unmuted at as Date. * @type {Date|null} */ - this.chatMuteUntil = new Date(data.chatMute) ?? null; + this.chatMuteUntil = data.chatMute ? new Date(data.chatMute) : null; /** * Timestamp guild chat will be unmuted at. * @type {Array<{ Pattern: string, Color: string }>} @@ -160,6 +166,7 @@ class Guild { /** * Guild name * @return {string} + * @example */ toString() { return this.name; @@ -169,40 +176,8 @@ class Guild { * @type {GuildMember} */ get guildMaster() { - return this.members.find((member) => member.rank === 'Guild Master' || member.rank === 'GUILDMASTER'); + return this.members.find((member) => 'Guild Master' === member.rank || 'GUILDMASTER' === member.rank); } } -// eslint-disable-next-line require-jsdoc -function members(data) { - return data.members.length ? data.members.map((m) => new GuildMember(m)) : []; -} -// eslint-disable-next-line require-jsdoc -function ranks(data) { - return data.ranks && data.ranks.length - ? data.ranks.map((r) => new GuildRank(r)).sort((a, b) => a.priority - b.priority) - : []; -} -// eslint-disable-next-line require-jsdoc -function totalWeeklyGexp(data) { - return members(data) - .map((m) => m.weeklyExperience) - .reduce((acc, cur) => acc + cur); -} -// eslint-disable-next-line require-jsdoc -function calculateExpHistory(data) { - const finalObj = {}; - for (const day of Object.keys(data.members[0].expHistory)) { - let gexp = 0; - for (const member of data.members) { - gexp += member.expHistory[day] || 0; - } - finalObj[day] = expLimit(gexp); - } - return parseHistory(finalObj); -} -// eslint-disable-next-line require-jsdoc -function expLimit(exp) { - return exp > 2e5 ? (exp > 7e5 ? 2.5e5 + Math.round(exp * 0.03) : 2e5 + Math.round((exp - 2e5) / 10)) : exp; -} module.exports = Guild; diff --git a/src/structures/Guild/GuildMember.js b/src/structures/Guild/GuildMember.js index 6cab3b7e..cfb9f29a 100644 --- a/src/structures/Guild/GuildMember.js +++ b/src/structures/Guild/GuildMember.js @@ -1,10 +1,11 @@ -const { parseHistory } = require('../../utils/guildExp'); +const { parseHistory } = require('../../utils/Guild'); /** * GuildMember class */ class GuildMember { /** * @param {data} data Guild member data + * @example */ constructor(data) { /** @@ -42,7 +43,7 @@ class GuildMember { * @type {Date|null} */ this.mutedUntil = data.mutedTill ? new Date(data.mutedTill) : null; - const xpCheck = data.expHistory && typeof Object.values(data.expHistory)[0] === 'number'; + const xpCheck = data.expHistory && 'number' === typeof Object.values(data.expHistory)[0]; /** * Experience history per day, resets at 5 am UTC * @type {Array} @@ -57,6 +58,7 @@ class GuildMember { /** * UUID * @return {string} + * @example */ toString() { return this.uuid; diff --git a/src/structures/Guild/GuildRank.js b/src/structures/Guild/GuildRank.js index 4da8be8b..6e96a660 100644 --- a/src/structures/Guild/GuildRank.js +++ b/src/structures/Guild/GuildRank.js @@ -4,6 +4,7 @@ class GuildRank { /** * @param {data} data Guild rank data + * @example */ constructor(data) { /** @@ -40,6 +41,7 @@ class GuildRank { /** * Rank Name * @return {string} + * @example */ toString() { return this.name; diff --git a/src/structures/ItemBytes.js b/src/structures/ItemBytes.js index 628d1b58..2a240583 100644 --- a/src/structures/ItemBytes.js +++ b/src/structures/ItemBytes.js @@ -5,6 +5,7 @@ const { decode } = require('../utils/SkyblockUtils'); class ItemBytes { /** * @param {string} data base64 encoded bytes + * @example */ constructor(data) { /** @@ -17,6 +18,7 @@ class ItemBytes { /** * Returns Item Bytes in base64 encoded * @return {String} + * @example */ base64() { return this.bytesBuffer.toString('base64'); @@ -25,6 +27,7 @@ class ItemBytes { /** * Returns NBT of Item Bytes * @return {any[]} + * @example */ async readNBT() { return await decode(this.bytesBuffer, true); diff --git a/src/structures/Leaderboard.js b/src/structures/Leaderboard.js index 2e3d897c..f4ed056f 100644 --- a/src/structures/Leaderboard.js +++ b/src/structures/Leaderboard.js @@ -4,6 +4,7 @@ class Leaderboard { /** * @param {object} data Leaderboard data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Arcade.js b/src/structures/MiniGames/Arcade.js index 5fabee18..1002cbbc 100644 --- a/src/structures/MiniGames/Arcade.js +++ b/src/structures/MiniGames/Arcade.js @@ -1,178 +1,16 @@ // IMPORTANT : a lot of the properties from the API seem to be nonsense -const divide = require('../../utils/divide'); -const { weekAB, monthAB } = require('../../utils/oscillation'); const { removeSnakeCaseString } = require('../../utils/removeSnakeCase'); +const { weekAB, monthAB } = require('../../utils/oscillation'); +const divide = require('../../utils/divide'); -/** - * Arcade class - */ -class Arcade { - /** - * Constructor - * @param {Object} data Data from the API - */ - constructor(data = {}) { - /** - * Amount of coins - * @type {number} - */ - this.coins = data.coins || 0; - /** - * Weekly coins - * @type {number} - */ - this.weeklyCoins = parseInt(data[`weekly_coins_${weekAB()}`] || 0, 10); - /** - * Monthly coins - * @type {number} - */ - this.monthlyCoins = parseInt(data[`monthly_coins_${monthAB()}`] || 0, 10); - /** - * Hints Disabled - * @type {boolean} - */ - this.hintsDisabled = !data.hints; - /** - * Flash Disabled - * @type {boolean} - */ - this.flashDisabled = !data.flash; - /** - * Draw their thing stats - * @type {BaseGame} - */ - this.drawTheirThing = new BaseGame(data, 'draw_their_thing'); - /** - * Dragon wars "2" stats - * @type {BaseGame} - */ - this.dragonWars = new BaseGame(data, 'dragonwars2'); - /** - * Easter Simulator stats - * @type {EasterSimulator} - */ - this.easterSimulator = new BaseGame(data, 'easter_simulator').extend( - 'eggsFound', - data.eggs_found_easter_simulator || 0 - ); - /** - * Grinch Simulator stats - * @type {GrinchSimulator} - */ - this.grinchSimulator = new BaseGame(data, 'grinch_simulator_v2').extend( - 'giftsFound', - data.gifts_grinch_simulator_v2 || 0 - ); - /** - * Scuba Simulator stats - * @type {ScubaSimulator} - */ - this.scubaSimulator = new BaseGame(data, 'scuba_simulator').extend( - 'itemsFound', - data.items_found_scuba_simulator || 0 - ); - /** - * Santa Simulator stats - * @type {SantaSimulator} - */ - this.santaSimulator = new BaseGame(data, 'santa_simulator').extend( - 'giftsDelivered', - data.delivered_santa_simulator || 0 - ); - /** - * Santa Says stats - * @type {BaseGame} - */ - this.santaSays = new BaseGame(data, 'santa_says'); - /** - * Simon Says stats - * @type {BaseGame} - */ - this.simonSays = new BaseGame(data, 'simon_says'); - /** - * Farm Hunt stats - * @type {BaseGame} - */ - this.farmHunt = new BaseGame(data, 'farm_hunt'); - /** - * Hole in the Wall stats - * @type {HITW} - */ - this.holeInTheWall = new HITW(data, 'hole_in_the_wall'); - /** - * Mini Walls stats - * @type {MiniWalls} - */ - this.miniWalls = new MiniWalls(data); // needs extension - /** - * Party games (1) stats - * @type {BaseGame} - */ - this.partyGames = new BaseGame(data, 'party'); - /** - * Party Games 2 stats ( legacy ) - * @type {BaseGame} - * @deprecated - */ - this.partyGames2 = new BaseGame(data, 'party_2'); - /** - * Party Games 3 stats ( legacy ) - * @type {BaseGame} - * @deprecated - */ - this.partyGames3 = new BaseGame(data, 'party_3'); - /** - * Throw out stats - * @type {BaseGame} - */ - this.throwOut = new BaseGame(data, 'throw_out'); - /** - * Soccer stats - * @type {Soccer} - */ - this.soccer = new Soccer(data); - /** - * Hypixel Sports stats - * @type {BaseGame} - * @deprecated - */ - this.hypixelSports = new BaseGame(data, 'hypixel_sports'); - /** - * Ender Spleef stats - * @type {BaseGame} - */ - this.enderSpleef = new BaseGame(data, 'ender'); - /** - * Blocking dead ( previously known as DayOne ) stats - * @type {BlockingDead} - */ - this.blockingDead = new BaseGame(data, 'dayone').extend('headshots', data.headshots_dayone || 0); - /** - * Galaxy Wars stats - * @type {GalaxyWars} - */ - this.galaxyWars = new GalaxyWars(data); - // Lenient parsing - /** - * OITQ / One In The Quiver stats - * @type {OITQ} - */ - this.oitq = this.oneInTheQuiver = new BaseGame(data, 'oneinthequiver').extend( - 'bountyKills', - data.bounty_kills_oneinthequiver || 0 - ); - /** - * Zombies - * @type {Zombies} - */ - this.zombies = new Zombies(data); - /** - * Capture The Wool - * @type {{kills: number, captures: number}} - */ - this.captureTheWool = { kills: data.arcade_ctw_slayer || 0, captures: data.arcade_ctw_oh_sheep || 0 }; - } +// eslint-disable-next-line jsdoc/require-jsdoc +function parseZombiesKills(data) { + const matches = Array.from(Object.keys(data)) + .map((x) => x.match(/^([A-Za-z]+)_zombie_kills_zombies$/)) + .filter((x) => x); + // From entries might be broken + return Object.fromEntries(matches.map((x) => [removeSnakeCaseString(x[1]), data[x[0]] || 0])); } /** * Most basic game class, used by all arcade games @@ -181,6 +19,7 @@ class BaseGame { /** * @param {Object} data data * @param {string} gameName Game Name ( snake ) + * @example */ constructor(data, gameName) { /** @@ -210,6 +49,7 @@ class BaseGame { * @param {*} value Corresponding value * @private * @returns {BaseGame} + * @example */ extend(name, value) { this[name] = value; @@ -223,6 +63,7 @@ class BaseGame { class GalaxyWars { /** * @param {Object} data Data from API + * @example */ constructor(data) { /** @@ -273,6 +114,7 @@ class GalaxyWars { class Soccer { /** * @param {Object} data Data from API + * @example */ constructor(data) { /** @@ -303,6 +145,7 @@ class Soccer { class HITW extends BaseGame { /** * @param {Object} data Data From API + * @example */ constructor(data) { super(data, 'hole_in_the_wall'); @@ -330,6 +173,7 @@ class MiniWalls extends BaseGame { /** * Constructor * @param {Object} data data from API + * @example */ constructor(data) { super(data, 'mini_walls'); @@ -366,64 +210,77 @@ class MiniWalls extends BaseGame { } } /** - * Zombies - Overall stats + * Zombies - Stats by Map + Difficulty */ -class Zombies { +class ZombiesStats { /** * Constructor * @param {Object} data Data from API + * @param {string} type Map name + difficulty ( default overall ) + * @example */ - constructor(data) { + constructor(data, type = '') { + if (type) type = `_${type}`; /** - * Overall Stats - * @type {ZombiesStats} + * Best Round + * @type {number} */ - this.overall = new ZombiesStats(data); + this.bestRound = data[`best_round_zombies${type}`] || 0; /** - * Stats for Dead End - * @type {ZombieMap} + * Deaths ( NOT losses ) + * @type {number} */ - this.deadEnd = new ZombieMap(data, 'deadend'); + this.deaths = data[`deaths_zombies${type}`] || 0; /** - * Stats for Bad Blood - * @type {ZombieMap} + * Doors opened + * @type {number} */ - this.badBlood = new ZombieMap(data, 'badblood'); + this.doorsOpened = data[`doors_opened_zombies${type}`] || 0; /** - * Stats for Alien Arcadium - * @type {ZombieMap} + * Fastest time to reach round 10 in seconds + * @type {number} */ - this.alienArcadium = new ZombieMap(data, 'alienarcadium'); + this.fastestRound10 = data[`fastest_time_10_zombies${type}`] || 0; /** - * Kills By Zombie - * @type {Record} + * Fastest time to reach round 20 in seconds + * @type {number} */ - this.killsByZombie = parseZombiesKills(data); + this.fastestRound20 = data[`fastest_time_20_zombies${type}`] || 0; /** - * Bullets Hit + * Fastest time to reach round 30 in seconds * @type {number} */ - this.bulletsHit = data.bullets_hit_zombies || 0; + this.fastestRound30 = data[`fastest_time_30_zombies${type}`] || 0; /** - * Bullets Shot + * Players revived * @type {number} */ - this.bulletsShot = data.bullets_shot_zombies || 0; + this.playersRevived = data[`players_revived_zombies${type}`] || 0; /** - * Gun Accuracy + * Number of times player is knocked down * @type {number} */ - this.gunAccuracy = divide(this.bulletsHit, this.bulletsShot); + this.timesKnockedDown = data[`times_knocked_down_zombies${type}`] || 0; /** - * Headshots + * Total amount of rounds the player survived * @type {number} */ - this.headshots = data.headshots_zombies || 0; + this.roundsSurvived = data[`total_rounds_survived_zombies${type}`] || 0; /** - * Headshot Accuracy + * Total amount of windows fully repaired by player * @type {number} */ - this.headshotAccuracy = divide(this.headshots, this.bulletsShot); + this.windowsRepaired = data[`windows_repaired_zombies${type}`] || 0; + /** + * Wins + * @type {number} + */ + this.wins = data[`wins_zombies${type}`] || 0; + /** + * Total Zombie Kills + * @type {number} + */ + this.zombieKills = data[`zombie_kills_zombies${type}`] || 0; } } /** @@ -434,6 +291,7 @@ class ZombieMap { * Constructor * @param {Object} data Data from API * @param {string} mapName String map name + * @example */ constructor(data, mapName) { /** @@ -459,86 +317,240 @@ class ZombieMap { } } /** - * Zombies - Stats by Map + Difficulty + * Zombies - Overall stats */ -class ZombiesStats { +class Zombies { /** * Constructor * @param {Object} data Data from API - * @param {string} type Map name + difficulty ( default overall ) + * @example */ - constructor(data, type = '') { - if (type) type = `_${type}`; + constructor(data) { /** - * Best Round - * @type {number} + * Overall Stats + * @type {ZombiesStats} */ - this.bestRound = data[`best_round_zombies${type}`] || 0; + this.overall = new ZombiesStats(data); /** - * Deaths ( NOT losses ) - * @type {number} + * Stats for Dead End + * @type {ZombieMap} */ - this.deaths = data[`deaths_zombies${type}`] || 0; + this.deadEnd = new ZombieMap(data, 'deadend'); /** - * Doors opened - * @type {number} + * Stats for Bad Blood + * @type {ZombieMap} */ - this.doorsOpened = data[`doors_opened_zombies${type}`] || 0; + this.badBlood = new ZombieMap(data, 'badblood'); /** - * Fastest time to reach round 10 in seconds - * @type {number} + * Stats for Alien Arcadium + * @type {ZombieMap} */ - this.fastestRound10 = data[`fastest_time_10_zombies${type}`] || 0; + this.alienArcadium = new ZombieMap(data, 'alienarcadium'); /** - * Fastest time to reach round 20 in seconds + * Kills By Zombie + * @type {Record} + */ + this.killsByZombie = parseZombiesKills(data); + /** + * Bullets Hit * @type {number} */ - this.fastestRound20 = data[`fastest_time_20_zombies${type}`] || 0; + this.bulletsHit = data.bullets_hit_zombies || 0; /** - * Fastest time to reach round 30 in seconds + * Bullets Shot * @type {number} */ - this.fastestRound30 = data[`fastest_time_30_zombies${type}`] || 0; + this.bulletsShot = data.bullets_shot_zombies || 0; /** - * Players revived + * Gun Accuracy * @type {number} */ - this.playersRevived = data[`players_revived_zombies${type}`] || 0; + this.gunAccuracy = divide(this.bulletsHit, this.bulletsShot); /** - * Number of times player is knocked down + * Headshots * @type {number} */ - this.timesKnockedDown = data[`times_knocked_down_zombies${type}`] || 0; + this.headshots = data.headshots_zombies || 0; /** - * Total amount of rounds the player survived + * Headshot Accuracy * @type {number} */ - this.roundsSurvived = data[`total_rounds_survived_zombies${type}`] || 0; + this.headshotAccuracy = divide(this.headshots, this.bulletsShot); + } +} + +/** + * Arcade class + */ +class Arcade { + /** + * Constructor + * @param {Object} data Data from the API + * @example + */ + constructor(data = {}) { /** - * Total amount of windows fully repaired by player + * Amount of coins * @type {number} */ - this.windowsRepaired = data[`windows_repaired_zombies${type}`] || 0; + this.coins = data.coins || 0; /** - * Wins + * Weekly coins * @type {number} */ - this.wins = data[`wins_zombies${type}`] || 0; + this.weeklyCoins = parseInt(data[`weekly_coins_${weekAB()}`] || 0, 10); /** - * Total Zombie Kills + * Monthly coins * @type {number} */ - this.zombieKills = data[`zombie_kills_zombies${type}`] || 0; + this.monthlyCoins = parseInt(data[`monthly_coins_${monthAB()}`] || 0, 10); + /** + * Hints Disabled + * @type {boolean} + */ + this.hintsDisabled = !data.hints; + /** + * Flash Disabled + * @type {boolean} + */ + this.flashDisabled = !data.flash; + /** + * Draw their thing stats + * @type {BaseGame} + */ + this.drawTheirThing = new BaseGame(data, 'draw_their_thing'); + /** + * Dragon wars "2" stats + * @type {BaseGame} + */ + this.dragonWars = new BaseGame(data, 'dragonwars2'); + /** + * Easter Simulator stats + * @type {EasterSimulator} + */ + this.easterSimulator = new BaseGame(data, 'easter_simulator').extend( + 'eggsFound', + data.eggs_found_easter_simulator || 0 + ); + /** + * Grinch Simulator stats + * @type {GrinchSimulator} + */ + this.grinchSimulator = new BaseGame(data, 'grinch_simulator_v2').extend( + 'giftsFound', + data.gifts_grinch_simulator_v2 || 0 + ); + /** + * Scuba Simulator stats + * @type {ScubaSimulator} + */ + this.scubaSimulator = new BaseGame(data, 'scuba_simulator').extend( + 'itemsFound', + data.items_found_scuba_simulator || 0 + ); + /** + * Santa Simulator stats + * @type {SantaSimulator} + */ + this.santaSimulator = new BaseGame(data, 'santa_simulator').extend( + 'giftsDelivered', + data.delivered_santa_simulator || 0 + ); + /** + * Santa Says stats + * @type {BaseGame} + */ + this.santaSays = new BaseGame(data, 'santa_says'); + /** + * Simon Says stats + * @type {BaseGame} + */ + this.simonSays = new BaseGame(data, 'simon_says'); + /** + * Farm Hunt stats + * @type {BaseGame} + */ + this.farmHunt = new BaseGame(data, 'farm_hunt'); + /** + * Hole in the Wall stats + * @type {HITW} + */ + this.holeInTheWall = new HITW(data, 'hole_in_the_wall'); + /** + * Mini Walls stats + * @type {MiniWalls} + */ + // TODO needs extension + this.miniWalls = new MiniWalls(data); + /** + * Party games (1) stats + * @type {BaseGame} + */ + this.partyGames = new BaseGame(data, 'party'); + /** + * Party Games 2 stats ( legacy ) + * @type {BaseGame} + * @deprecated + */ + this.partyGames2 = new BaseGame(data, 'party_2'); + /** + * Party Games 3 stats ( legacy ) + * @type {BaseGame} + * @deprecated + */ + this.partyGames3 = new BaseGame(data, 'party_3'); + /** + * Throw out stats + * @type {BaseGame} + */ + this.throwOut = new BaseGame(data, 'throw_out'); + /** + * Soccer stats + * @type {Soccer} + */ + this.soccer = new Soccer(data); + /** + * Hypixel Sports stats + * @type {BaseGame} + * @deprecated + */ + this.hypixelSports = new BaseGame(data, 'hypixel_sports'); + /** + * Ender Spleef stats + * @type {BaseGame} + */ + this.enderSpleef = new BaseGame(data, 'ender'); + /** + * Blocking dead ( previously known as DayOne ) stats + * @type {BlockingDead} + */ + this.blockingDead = new BaseGame(data, 'dayone').extend('headshots', data.headshots_dayone || 0); + /** + * Galaxy Wars stats + * @type {GalaxyWars} + */ + this.galaxyWars = new GalaxyWars(data); + // Lenient parsing + /** + * OITQ / One In The Quiver stats + * @type {OITQ} + */ + this.oitq = this.oneInTheQuiver = new BaseGame(data, 'oneinthequiver').extend( + 'bountyKills', + data.bounty_kills_oneinthequiver || 0 + ); + /** + * Zombies + * @type {Zombies} + */ + this.zombies = new Zombies(data); + /** + * Capture The Wool + * @type {{kills: number, captures: number}} + */ + this.captureTheWool = { kills: data.arcade_ctw_slayer || 0, captures: data.arcade_ctw_oh_sheep || 0 }; } } -// eslint-disable-next-line require-jsdoc -function parseZombiesKills(data) { - const matches = Array.from(Object.keys(data)) - .map((x) => x.match(/^([A-z]+)_zombie_kills_zombies$/)) - .filter((x) => x); - // From entries might be broken - return Object.fromEntries(matches.map((x) => [removeSnakeCaseString(x[1]), data[x[0]] || 0])); -} /** * @typedef {Object} EasterSimulator * @extends BaseGame diff --git a/src/structures/MiniGames/ArenaBrawl.js b/src/structures/MiniGames/ArenaBrawl.js index fab75a39..03ed4003 100644 --- a/src/structures/MiniGames/ArenaBrawl.js +++ b/src/structures/MiniGames/ArenaBrawl.js @@ -1,10 +1,22 @@ const divide = require('../../utils/divide'); +// eslint-disable-next-line jsdoc/require-jsdoc +function generateModeStats(data, mode) { + return { + kills: data[`kills_${mode}`] || 0, + deaths: data[`deaths_${mode}`] || 0, + KDRatio: divide(data[`kills_${mode}`], data[`deaths_${mode}`]), + wins: data[`wins_${mode}`] || 0, + losses: data[`losses_${mode}`] || 0, + WLRatio: divide(data[`wins_${mode}`], data[`losses_${mode}`]) + }; +} /** * ArenaBrawl class */ class ArenaBrawl { /** * @param {object} data ArenaBrawl data + * @example */ constructor(data) { /** @@ -23,17 +35,6 @@ class ArenaBrawl { }; } } -// eslint-disable-next-line require-jsdoc -function generateModeStats(data, mode) { - return { - kills: data[`kills_${mode}`] || 0, - deaths: data[`deaths_${mode}`] || 0, - KDRatio: divide(data[`kills_${mode}`], data[`deaths_${mode}`]), - wins: data[`wins_${mode}`] || 0, - losses: data[`losses_${mode}`] || 0, - WLRatio: divide(data[`wins_${mode}`], data[`losses_${mode}`]) - }; -} /** * @typedef {Object} ArenaBrawlStats * @property {ArenaBrawlModeStats} '1v1' ArenaBrawl 1v1 stats diff --git a/src/structures/MiniGames/BedWars.js b/src/structures/MiniGames/BedWars.js index e09537db..d915d29a 100644 --- a/src/structures/MiniGames/BedWars.js +++ b/src/structures/MiniGames/BedWars.js @@ -32,182 +32,9 @@ const generateStatsForMode = (data, mode) => { }; }; -/** - * BedWars class - */ -class BedWars { - /** - * @param {object} data BedWars data - */ - constructor(data) { - /** - * Tokens - * @type {number} - */ - this.tokens = data.coins || 0; - /** - * Level - * @type {number} - */ - this.level = data.Experience ? getLevelForExp(data.Experience) : 0; - /** - * Experience - * @type {number} - */ - this.experience = data.Experience || 0; - /** - * Prestige - * @type {BedWarsPrestige} - */ - this.prestige = data.Experience ? getBedWarsPrestige(getLevelForExp(data.Experience)) : 'Stone'; - /** - * Played games - * @type {number} - */ - this.playedGames = data.games_played_bedwars || 0; - /** - * Wins - * @type {number} - */ - this.wins = data.wins_bedwars || 0; - /** - * Winstreak - * @type {number} - */ - this.winstreak = data.winstreak || 0; - /** - * Kills - * @type {number} - */ - this.kills = data.kills_bedwars || 0; - /** - * Final kills - * @type {number} - */ - this.finalKills = data.final_kills_bedwars || 0; - /** - * Losses - * @type {number} - */ - this.losses = data.losses_bedwars || 0; - /** - * Deaths - * @type {number} - */ - this.deaths = data.deaths_bedwars || 0; - /** - * Final deaths - * @type {number} - */ - this.finalDeaths = data.final_deaths_bedwars || 0; - /** - * Collected items - * @type {BedWarsCollectedItems} - */ - this.collectedItemsTotal = { - iron: data.iron_resources_collected_bedwars || 0, - gold: data.gold_resources_collected_bedwars || 0, - diamond: data.diamond_resources_collected_bedwars || 0, - emerald: data.emerald_resources_collected_bedwars || 0 - }; - /** - * Beds lost/broken/BL Ratio - * @type {BedWarsBeds} - */ - this.beds = { - lost: data.beds_lost_bedwars || 0, - broken: data.beds_broken_bedwars || 0, - BLRatio: divide(data.beds_broken_bedwars, data.beds_lost_bedwars) - }; - /** - * Average Kills/Final kills/Beds broken - * @type {BedWarsAvg} - */ - this.avg = { - kills: divide(this.kills, this.playedGames), - finalKills: divide(this.finalKills, this.playedGames), - bedsBroken: divide(this.beds.broken, this.playedGames) - }; - /** - * Kill Death ratio - * @type {number} - */ - this.KDRatio = divide(this.kills, this.deaths); - /** - * Final kill death ratio - * @type {number} - */ - this.finalKDRatio = divide(this.finalKills, this.finalDeaths); - /** - * Win Loss ratio - * @type {number} - */ - this.WLRatio = divide(this.wins, this.losses); - /** - * BedWars Solo stats - * @type {BedWarsModeStats} - */ - this.solo = generateStatsForMode(data, 'eight_one'); - /** - * BedWars Doubles stats - * @type {BedWarsModeStats} - */ - this.doubles = generateStatsForMode(data, 'eight_two'); - /** - * BedWars 3v3v3v3 stats - * @type {BedWarsModeStats} - */ - this.threes = generateStatsForMode(data, 'four_three'); - /** - * BedWars 4v4v4v4 stats - * @type {BedWarsModeStats} - */ - this.fours = generateStatsForMode(data, 'four_four'); - /** - * BedWars 4v4 stats - * @type {BedWarsModeStats} - */ - this['4v4'] = generateStatsForMode(data, 'two_four'); - /** - * BedWars Dream Mode Stats - * @type {BedwarsDreamStats} - */ - this.dream = ['ultimate', 'rush', 'armed', 'lucky', 'voidless'].reduce( - (ac, mode) => ({ - [mode]: { - doubles: generateStatsForMode(data, `eight_two_${mode}`), - fours: generateStatsForMode(data, `four_four_${mode}`) - }, - ...ac - }), - {} - ); - /** - * BedWars Castle Stats - * @type {BedWarsModeStats} - */ - this.castle = generateStatsForMode(data, 'castle'); - /** - * BedWars Practice Stats - * @type {BedWarsPracticeStats} - */ - this.practice = generateStatsForPractice(data); - /** - * Bedwars Slumber Tickets - * @type {number} - */ - this.slumberTickets = data.slumber?.tickets ?? 0; - /** - * Bedwars Slumber Total Tickets - * @type {number} - */ - this.totalSlumberTicket = data.slumber?.total_tickets ?? 0; - } -} -// eslint-disable-next-line require-jsdoc +// eslint-disable-next-line jsdoc/require-jsdoc function getBedWarsPrestige(level) { - // eslint-disable-next-line max-len - if (level >= 5000) return 'Eternal'; + if (5000 <= level) return 'Eternal'; return ( [ 'Stone', @@ -270,9 +97,17 @@ const XP_PER_PRESTIGE = 96 * 5000 + EASY_LEVELS_XP; const LEVELS_PER_PRESTIGE = 100; const HIGHEST_PRESTIGE = 10; -// eslint-disable-next-line require-jsdoc +// eslint-disable-next-line jsdoc/require-jsdoc +function getLevelRespectingPrestige(level) { + if (level > HIGHEST_PRESTIGE * LEVELS_PER_PRESTIGE) { + return level - HIGHEST_PRESTIGE * LEVELS_PER_PRESTIGE; + } + return level % LEVELS_PER_PRESTIGE; +} + +// eslint-disable-next-line jsdoc/require-jsdoc function getExpForLevel(level) { - if (level === 0) return 0; + if (0 === level) return 0; const respectedLevel = getLevelRespectingPrestige(level); if (respectedLevel > EASY_LEVELS) return 5000; switch (respectedLevel) { @@ -284,18 +119,13 @@ function getExpForLevel(level) { return 2000; case 4: return 3500; - } - return 5000; -} -// eslint-disable-next-line require-jsdoc -function getLevelRespectingPrestige(level) { - if (level > HIGHEST_PRESTIGE * LEVELS_PER_PRESTIGE) { - return level - HIGHEST_PRESTIGE * LEVELS_PER_PRESTIGE; - } else { - return level % LEVELS_PER_PRESTIGE; + default: { + return 5000; + } } } -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function getLevelForExp(exp) { const prestiges = Math.floor(exp / XP_PER_PRESTIGE); let level = prestiges * LEVELS_PER_PRESTIGE; @@ -311,7 +141,8 @@ function getLevelForExp(exp) { } return level + Math.floor(expWithoutPrestiges / 5000); } -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function generateStatsForPractice(data) { return { selected: data?.practice?.selected || 'NONE', @@ -323,7 +154,7 @@ function generateStatsForPractice(data) { total: data?.practice?.bridging?.failed_attempts + data?.practice?.bridging?.successful_attempts }, records: { - '30Blocks': { + blocks30: { elevation: { none: { straight: data?.practice?.records?.['bridging_distance_30:elevation_NONE:angle_STRAIGHT:'] ?? 0, @@ -339,7 +170,7 @@ function generateStatsForPractice(data) { } } }, - '50Blocks': { + blocks50: { elevation: { none: { straight: data?.practice?.records?.['bridging_distance_50:elevation_NONE:angle_STRAIGHT:'] ?? 0, @@ -355,7 +186,7 @@ function generateStatsForPractice(data) { } } }, - '100Blocks': { + blocks100: { elevation: { none: { straight: data?.practice?.records?.['bridging_distance_100:elevation_NONE:angle_STRAIGHT:'] ?? 0, @@ -398,6 +229,179 @@ function generateStatsForPractice(data) { } }; } +/** + * BedWars class + */ +class BedWars { + /** + * @param {object} data BedWars data + * @example + */ + constructor(data) { + /** + * Tokens + * @type {number} + */ + this.tokens = data.coins || 0; + /** + * Level + * @type {number} + */ + this.level = data.Experience ? getLevelForExp(data.Experience) : 0; + /** + * Experience + * @type {number} + */ + this.experience = data.Experience || 0; + /** + * Prestige + * @type {BedWarsPrestige} + */ + this.prestige = data.Experience ? getBedWarsPrestige(getLevelForExp(data.Experience)) : 'Stone'; + /** + * Played games + * @type {number} + */ + this.playedGames = data.games_played_bedwars || 0; + /** + * Wins + * @type {number} + */ + this.wins = data.wins_bedwars || 0; + /** + * Winstreak + * @type {number} + */ + this.winstreak = data.winstreak || 0; + /** + * Kills + * @type {number} + */ + this.kills = data.kills_bedwars || 0; + /** + * Final kills + * @type {number} + */ + this.finalKills = data.final_kills_bedwars || 0; + /** + * Losses + * @type {number} + */ + this.losses = data.losses_bedwars || 0; + /** + * Deaths + * @type {number} + */ + this.deaths = data.deaths_bedwars || 0; + /** + * Final deaths + * @type {number} + */ + this.finalDeaths = data.final_deaths_bedwars || 0; + /** + * Collected items + * @type {BedWarsCollectedItems} + */ + this.collectedItemsTotal = { + iron: data.iron_resources_collected_bedwars || 0, + gold: data.gold_resources_collected_bedwars || 0, + diamond: data.diamond_resources_collected_bedwars || 0, + emerald: data.emerald_resources_collected_bedwars || 0 + }; + /** + * Beds lost/broken/BL Ratio + * @type {BedWarsBeds} + */ + this.beds = { + lost: data.beds_lost_bedwars || 0, + broken: data.beds_broken_bedwars || 0, + BLRatio: divide(data.beds_broken_bedwars, data.beds_lost_bedwars) + }; + /** + * Average Kills/Final kills/Beds broken + * @type {BedWarsAvg} + */ + this.avg = { + kills: divide(this.kills, this.playedGames), + finalKills: divide(this.finalKills, this.playedGames), + bedsBroken: divide(this.beds.broken, this.playedGames) + }; + /** + * Kill Death ratio + * @type {number} + */ + this.KDRatio = divide(this.kills, this.deaths); + /** + * Final kill death ratio + * @type {number} + */ + this.finalKDRatio = divide(this.finalKills, this.finalDeaths); + /** + * Win Loss ratio + * @type {number} + */ + this.WLRatio = divide(this.wins, this.losses); + /** + * BedWars Solo stats + * @type {BedWarsModeStats} + */ + this.solo = generateStatsForMode(data, 'eight_one'); + /** + * BedWars Doubles stats + * @type {BedWarsModeStats} + */ + this.doubles = generateStatsForMode(data, 'eight_two'); + /** + * BedWars 3v3v3v3 stats + * @type {BedWarsModeStats} + */ + this.threes = generateStatsForMode(data, 'four_three'); + /** + * BedWars 4v4v4v4 stats + * @type {BedWarsModeStats} + */ + this.fours = generateStatsForMode(data, 'four_four'); + /** + * BedWars 4v4 stats + * @type {BedWarsModeStats} + */ + this['4v4'] = generateStatsForMode(data, 'two_four'); + /** + * BedWars Dream Mode Stats + * @type {BedwarsDreamStats} + */ + this.dream = ['ultimate', 'rush', 'armed', 'lucky', 'voidless'].reduce( + (ac, mode) => ({ + [mode]: { + doubles: generateStatsForMode(data, `eight_two_${mode}`), + fours: generateStatsForMode(data, `four_four_${mode}`) + }, + ...ac + }), + {} + ); + /** + * BedWars Castle Stats + * @type {BedWarsModeStats} + */ + this.castle = generateStatsForMode(data, 'castle'); + /** + * BedWars Practice Stats + * @type {BedWarsPracticeStats} + */ + this.practice = generateStatsForPractice(data); + /** + * Bedwars Slumber Tickets + * @type {number} + */ + this.slumberTickets = data.slumber?.tickets ?? 0; + /** + * Bedwars Slumber Total Tickets + * @type {number} + */ + this.totalSlumberTicket = data.slumber?.total_tickets ?? 0; + } +} /** * @typedef {string} BedWarsPrestige * * `Stone` @@ -523,9 +527,9 @@ function generateStatsForPractice(data) { */ /** * @typedef {Object} BedWarsPracticeRecords - * @property {BedWarsPracticeRecord} 30Blocks 30 Blocks - * @property {BedWarsPracticeRecord} 50Blocks 50 Blocks - * @property {BedWarsPracticeRecord} 100Blocks 100 Blocks + * @property {BedWarsPracticeRecord} blocks30 30 Blocks + * @property {BedWarsPracticeRecord} blocks50 50 Blocks + * @property {BedWarsPracticeRecord} blocks100 100 Blocks */ /** * @typedef {Object} BedWarsPracticeBridging diff --git a/src/structures/MiniGames/BlitzSurvivalGames.js b/src/structures/MiniGames/BlitzSurvivalGames.js index c4ee9c0e..65bd2427 100644 --- a/src/structures/MiniGames/BlitzSurvivalGames.js +++ b/src/structures/MiniGames/BlitzSurvivalGames.js @@ -42,12 +42,37 @@ const kits = [ 'warrior', 'rambo' ]; + +// eslint-disable-next-line jsdoc/require-jsdoc +function generateKitStats(data) { + const stats = []; + for (let i = 0; i < kits.length; i++) { + if (data[kits[i]]) { + stats.push({ + name: kits[i], + games: data[`games_played_${kits[i]}`] || 0, + level: data[kits[i]] + 1 || 1, + experience: data[`exp_${kits[i]}`] || 0, + prestige: data[`p${kits[i]}`] || 0, + kills: data[`kills_${kits[i]}`] || 0, + deaths: data[`deaths_${kits[i]}`] || 0, + KDRatio: divide(data[`kills_${kits[i]}`], data[`deaths_${kits[i]}`]), + wins: data[`wins_${kits[i]}`] || 0, + losses: data[`losses_${kits[i]}`] || 0, + WLRatio: divide(data[`wins_${kits[i]}`], data[`losses_${kits[i]}`]), + timePlayed: data[`time_played_${kits[i]}`] || null + }); + } + } + return stats; +} /** * Blitz SG class */ class BlitzSurvivalGames { /** * @param {object} data Blitz SG data + * @example */ constructor(data) { /** @@ -87,29 +112,6 @@ class BlitzSurvivalGames { this.kitStats = generateKitStats(data); } } -// eslint-disable-next-line require-jsdoc -function generateKitStats(data) { - const stats = []; - for (let i = 0; i < kits.length; i++) { - if (data[kits[i]]) { - stats.push({ - name: kits[i], - games: data[`games_played_${kits[i]}`] || 0, - level: data[kits[i]] + 1 || 1, - experience: data[`exp_${kits[i]}`] || 0, - prestige: data[`p${kits[i]}`] || 0, - kills: data[`kills_${kits[i]}`] || 0, - deaths: data[`deaths_${kits[i]}`] || 0, - KDRatio: divide(data[`kills_${kits[i]}`], data[`deaths_${kits[i]}`]), - wins: data[`wins_${kits[i]}`] || 0, - losses: data[`losses_${kits[i]}`] || 0, - WLRatio: divide(data[`wins_${kits[i]}`], data[`losses_${kits[i]}`]), - timePlayed: data[`time_played_${kits[i]}`] || null - }); - } - } - return stats; -} /** * @typedef {string} BlitzSGKit * * `arachnologist` diff --git a/src/structures/MiniGames/BuildBattle.js b/src/structures/MiniGames/BuildBattle.js index 5ea9cbf3..24b1500e 100644 --- a/src/structures/MiniGames/BuildBattle.js +++ b/src/structures/MiniGames/BuildBattle.js @@ -4,6 +4,7 @@ class BuildBattle { /** * @param {object} data BuildBattle data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/CopsAndCrims.js b/src/structures/MiniGames/CopsAndCrims.js index 2815b24a..60b86aec 100644 --- a/src/structures/MiniGames/CopsAndCrims.js +++ b/src/structures/MiniGames/CopsAndCrims.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class CopsAndCrims { /** * @param {object} data Cops and crims data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Duels.js b/src/structures/MiniGames/Duels.js index 8ed41a8a..7e92460d 100644 --- a/src/structures/MiniGames/Duels.js +++ b/src/structures/MiniGames/Duels.js @@ -1,13 +1,10 @@ -/* eslint-disable max-len */ -const divide = require('../../utils/divide'); +const { duelsDivisions } = require('../../utils/Constants'); const romanize = require('../../utils/romanize'); -// eslint-disable-next-line camelcase -const { duels_divisions } = require('../../utils/Constants'); +const divide = require('../../utils/divide'); -// eslint-disable-next-line require-jsdoc +// eslint-disable-next-line jsdoc/require-jsdoc function getDivision(data, mode = null) { - // eslint-disable-next-line camelcase - for (const div of duels_divisions.slice().reverse()) { + for (const div of duelsDivisions.slice().reverse()) { const prestige = data[`${mode ? mode : 'all_modes'}_${div.key}_title_prestige`]; if (prestige) { return `${div.name} ${romanize(prestige)}`; @@ -15,14 +12,15 @@ function getDivision(data, mode = null) { } return null; } -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function getTotalKillsDeaths(data) { let totalDeaths = 0; let totalKills = 0; for (const [k, v] of Object.entries(data)) { - if (k.includes('deaths') && k !== 'deaths') { + if (k.includes('deaths') && 'deaths' !== k) { totalDeaths += v; - } else if (k.includes('kills') && k !== 'kills') { + } else if (k.includes('kills') && 'kills' !== k) { totalKills += v; } } @@ -37,6 +35,7 @@ function getTotalKillsDeaths(data) { class Duels { /** * @param {object} data Duels data + * @example */ constructor(data) { /** @@ -576,7 +575,7 @@ class Duels { playedGames: data.bridge_four_rounds_played || 0, goals: data.bridge_four_goals || 0 }, - // eslint-disable-next-line quote-props + ctf: { division: getDivision(data, 'bridge'), kills: data.capture_threes_bridge_kills || 0, diff --git a/src/structures/MiniGames/MegaWalls.js b/src/structures/MiniGames/MegaWalls.js index 51c928cc..bedcd545 100644 --- a/src/structures/MiniGames/MegaWalls.js +++ b/src/structures/MiniGames/MegaWalls.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class MegaWalls { /** * @param {object} data MegaWalls data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/MurderMystery.js b/src/structures/MiniGames/MurderMystery.js index 680216a0..35652e84 100644 --- a/src/structures/MiniGames/MurderMystery.js +++ b/src/structures/MiniGames/MurderMystery.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class MurderMystery { /** * @param {object} data MurderMystery data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Paintball.js b/src/structures/MiniGames/Paintball.js index 1b8a8efc..2bd3b972 100644 --- a/src/structures/MiniGames/Paintball.js +++ b/src/structures/MiniGames/Paintball.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class Paintball { /** * @param {object} data Paintball data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Pit.js b/src/structures/MiniGames/Pit.js index 96c5f7a7..6b644008 100644 --- a/src/structures/MiniGames/Pit.js +++ b/src/structures/MiniGames/Pit.js @@ -12,6 +12,7 @@ class Pit { /** * Constructor * @param {Record} data Data from API + * @example */ constructor(data) { const stats = data.pit_stats_ptl || {}; @@ -30,7 +31,7 @@ class Pit { * @type {number} */ this.level = - Pit.calcLevel(this.prestige, this.prestige > 0 ? this.xp - Prestiges[this.prestige - 1].SumXp : this.xp).level ?? + Pit.calcLevel(this.prestige, 0 < this.prestige ? this.xp - Prestiges[this.prestige - 1].SumXp : this.xp).level ?? 0; /** * Kills @@ -154,6 +155,7 @@ class Pit { /** * Pit Player Inv * @return {Promise} + * @example */ this.getInventory = async () => { let inventory = data.profile.inv_contents; @@ -169,13 +171,14 @@ class Pit { edited.push(new PitInventoryItem(inventory[i])); } return edited; - } catch (e) { + } catch { return []; } }; /** * Pit Player Ender Chest * @return {Promise} + * @example */ this.getEnterChest = async () => { let chest = data.profile.inv_enderchest; @@ -191,13 +194,14 @@ class Pit { edited.push(new PitInventoryItem(chest[i])); } return edited; - } catch (e) { + } catch { return []; } }; /** * Pit Player Armor * @return {Promise} + * @example */ this.getArmor = async () => { const base64 = data.profile.inv_armor; @@ -217,11 +221,12 @@ class Pit { * @param {number} prestige Prestige Level * @param {number} xp Current xp into the prestige * @return {number} + * @example */ static calcLevel(prestige, xp) { const multiplier = Prestiges[prestige].Multiplier; let level = 0; - while (xp > 0 && level < 120) { + while (0 < xp && 120 > level) { const levelXp = Levels[Math.floor(level / 10)].Xp * multiplier; if (xp >= levelXp * 10) { xp -= levelXp * 10; @@ -229,7 +234,6 @@ class Pit { } else { const gain = Math.floor(xp / levelXp); level += gain; - xp -= gain * levelXp; xp = 0; } } diff --git a/src/structures/MiniGames/PitInventoryItem.js b/src/structures/MiniGames/PitInventoryItem.js index 411b7390..a3a9378f 100644 --- a/src/structures/MiniGames/PitInventoryItem.js +++ b/src/structures/MiniGames/PitInventoryItem.js @@ -4,6 +4,7 @@ class PitInventoryItem { /** * @param {object} data Item data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Quakecraft.js b/src/structures/MiniGames/Quakecraft.js index 1d9a9faa..175c6624 100644 --- a/src/structures/MiniGames/Quakecraft.js +++ b/src/structures/MiniGames/Quakecraft.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class Quakecraft { /** * @param {object} data Quakecraft data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/SkyWars.js b/src/structures/MiniGames/SkyWars.js index 5fef9874..0dd765b8 100644 --- a/src/structures/MiniGames/SkyWars.js +++ b/src/structures/MiniGames/SkyWars.js @@ -1,7 +1,9 @@ +const { removeSnakeCaseString } = require('../../utils/removeSnakeCase'); const { SkyWarsPrestigeIcons } = require('../../utils/Constants'); const divide = require('../../utils/divide'); -const { removeSnakeCaseString } = require('../../utils/removeSnakeCase'); -const generateStatsForMode = (data, mode) => { + +// eslint-disable-next-line jsdoc/require-jsdoc +function generateStatsForMode(data, mode) { return { kills: data[`kills_${mode}`] || 0, deaths: data[`deaths_${mode}`] || 0, @@ -10,13 +12,209 @@ const generateStatsForMode = (data, mode) => { KDRatio: divide(data[`kills_${mode}`], data[`deaths_${mode}`]), WLRatio: divide(data[`wins_${mode}`], data[`losses_${mode}`]) }; -}; +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function getSkyWarsPrestige(level) { + if (60 <= level) return 'Mythic'; + return ( + ['Iron', 'Iron', 'Gold', 'Diamond', 'Emerald', 'Sapphire', 'Ruby', 'Crystal', 'Opal', 'Amethyst', 'Rainbow'][ + Math.floor(level / 5) + ] || 'Iron' + ); +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function getSkyWarsLevel(xp) { + const totalXp = [0, 2, 7, 15, 25, 50, 100, 200, 350, 600, 1000, 1500]; + if (15000 <= xp) return Math.floor((xp - 15000) / 10000 + 12); + const level = totalXp.findIndex((x) => 0 < x * 10 - xp); + return level; +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function getSkyWarsLevelProgress(xp) { + const totalXp = [0, 2, 7, 15, 25, 50, 100, 200, 350, 600, 1000, 1500]; + const xpToNextLvl = [0, 2, 5, 8, 10, 25, 50, 100, 150, 250, 400, 500]; + let percent; + let xpToNextLevel; + let currentLevelXp = xp; + if (15000 <= xp) { + currentLevelXp -= 15000; + if (0 === currentLevelXp) return { currentLevelXp: 0, xpToNextLevel: 10000, percent: 0, xpNextLevel: 10000 }; + if (10000 < currentLevelXp) { + do { + currentLevelXp -= 10000; + } while (10000 <= currentLevelXp); + } + xpToNextLevel = 10000 - currentLevelXp; + percent = Math.round(currentLevelXp) / 100; + const percentRemaining = Math.round((100 - percent) * 100) / 100; + return { + currentLevelXp, + xpToNextLevel, + percent, + xpNextLevel: 10000, + percentRemaining + }; + } + const totalXptoNextLevel = xpToNextLvl[totalXp.findIndex((x) => 0 < x * 10 - xp)] * 10; + for (let i = 0; i < xpToNextLvl.length; i++) { + if (0 > currentLevelXp - xpToNextLvl[i] * 10) break; + currentLevelXp -= xpToNextLvl[i] * 10; + } + xpToNextLevel = totalXptoNextLevel - currentLevelXp; + percent = Math.round((currentLevelXp / totalXptoNextLevel) * 10000) / 100; + return { + currentLevelXp, + xpToNextLevel, + percent, + xpNextLevel: totalXptoNextLevel + }; +} + +/** + * Parses SkyWars Kit + */ +class SkywarsKit { + /** + * Constructor + * @param {string} kit Kit + * @example + */ + constructor(kit) { + /** + * Kit data + * @private + * @type {string[] | null} + */ + this.kitData = kit.match(/^kit_([a-z]+)_([a-z]+)_([a-z]+)$/); + /** + * Is this a kit + * @type {boolean} + */ + this.isKit = Boolean(this.kitData); + if (!this.kitData) return; + /** + * Game mode the kit is for + * @type {KitGameModes} + */ + this.gameMode = this.kitData[2]; + /** + * Kit type + * @type {KitType} + */ + this.kitType = this.kitData[1]; + /** + * Kit name in camelCase + * @type {string} + */ + this.kitName = removeSnakeCaseString(this.kitData[3]); + } +} + +/** + * Parses SkyWars Kits + */ +class SkywarsKits { + /** + * Constructor + * @param {SkywarsKit[]} kits Potential Kits + * @example + */ + constructor(kits) { + this.kits = kits.map((kit) => new SkywarsKit(kit)).filter((kit) => kit.isKit); + } + /** + * Get kit by type/gameMode + * @param {KitGameModes} [gameMode] Kits in said game mode + * @param {KitType} [type] Kits corresponding to this type + * @returns {SkywarsKit[]} + * @example + */ + get(gameMode = '', type = '') { + return this.kits.filter((kit) => kit.gameMode.startsWith(gameMode) && kit.kitType.startsWith(type)); + } +} +/** + * Skywars Packages - parses every package player has + */ +class SkywarsPackages { + /** + * Constructor + * @param {string[]} data data from API + * @example + */ + constructor(data) { + // TODO : a lot more + /** + * Raw Packages, as received from the API + * @type {string[]} + */ + this.rawPackages = Array.from(data); + /** + * Cages + * @type {string[]} + */ + this.cages = this.parseCages(); + /** + * Kits + * @type {SkywarsKits} + */ + this.kits = new SkywarsKits(data); + /** + * Achievements included in packages, under the form of name0 + * @type {string[]} + */ + this.achievements = this.rawPackages + .map((pkg) => pkg.match(/^([A-Za-z]+)_?achievement([0-9]?)$/)) + .filter((x) => x) + .map((x) => x.slice(1).join('')); + } + /** + * Parses cages + * @returns {string[]} + * @example + */ + parseCages() { + return this.rawPackages + .map((pkg) => pkg.match(/^cage_([A-Za-z]+)-cage$/)) + .filter((x) => x) + .map((x) => x[1].replace(/-[a-z]/g, (x) => x[1].toUpperCase())); + } +} + +/** + * @typedef {string} KitType + * * basic + * * supporting + * * mining + * * defending + * * attacking + * * advanced + * * enderchest + */ +/** + * @typedef {string} KitGameModes + * * solo + * * team + */ + +/** + * @typedef {Object} SkyWarsShardsInMode + * @property {number} solo Solo shards + * @property {number} team Team shards + * @property {number} mega Mega shards + * @property {number} lab Lab shards + */ + /** * SkyWars class */ class SkyWars { /** * @param {object} data SkyWars data + * @example */ constructor(data) { /** @@ -331,183 +529,3 @@ class SkyWars { * @property {SkyWarsModeStats} doubles Mega Doubles Stats */ module.exports = SkyWars; -// eslint-disable-next-line require-jsdoc -function getSkyWarsPrestige(level) { - if (level >= 60) return 'Mythic'; - return ( - ['Iron', 'Iron', 'Gold', 'Diamond', 'Emerald', 'Sapphire', 'Ruby', 'Crystal', 'Opal', 'Amethyst', 'Rainbow'][ - Math.floor(level / 5) - ] || 'Iron' - ); -} -// eslint-disable-next-line require-jsdoc -function getSkyWarsLevel(xp) { - const totalXp = [0, 2, 7, 15, 25, 50, 100, 200, 350, 600, 1000, 1500]; - if (xp >= 15000) return Math.floor((xp - 15000) / 10000 + 12); - const level = totalXp.findIndex((x) => x * 10 - xp > 0); - return level; /* + (xp - (totalXp[level - 1] * 10 || 0)) / (totalXp[level] - totalXp[level - 1]) / 10*/ -} -// eslint-disable-next-line require-jsdoc -function getSkyWarsLevelProgress(xp) { - const totalXp = [0, 2, 7, 15, 25, 50, 100, 200, 350, 600, 1000, 1500]; - const xpToNextLvl = [0, 2, 5, 8, 10, 25, 50, 100, 150, 250, 400, 500]; // * 10 - let percent; - let xpToNextLevel; - let currentLevelXp = xp; - if (xp >= 15000) { - currentLevelXp -= 15000; - if (currentLevelXp === 0) return { currentLevelXp: 0, xpToNextLevel: 10000, percent: 0, xpNextLevel: 10000 }; - if (currentLevelXp > 10000) { - do { - currentLevelXp -= 10000; - } while (currentLevelXp >= 10000); - } - xpToNextLevel = 10000 - currentLevelXp; - percent = Math.round(currentLevelXp) / 100; - const percentRemaining = Math.round((100 - percent) * 100) / 100; - return { - currentLevelXp, - xpToNextLevel, - percent, - xpNextLevel: 10000, - percentRemaining - }; - } - const totalXptoNextLevel = xpToNextLvl[totalXp.findIndex((x) => x * 10 - xp > 0)] * 10; - for (let i = 0; i < xpToNextLvl.length; i++) { - if (currentLevelXp - xpToNextLvl[i] * 10 < 0) break; - currentLevelXp -= xpToNextLvl[i] * 10; - } - xpToNextLevel = totalXptoNextLevel - currentLevelXp; - percent = Math.round((currentLevelXp / totalXptoNextLevel) * 10000) / 100; - return { - currentLevelXp, - xpToNextLevel, - percent, - xpNextLevel: totalXptoNextLevel - }; -} -const ratingRegex = /^SkyWars_skywars_rating_(\d{1,2})_(\d{1,2})_(position|rating)$/; - -/** - * Skywars Packages - parses every package player has - */ -class SkywarsPackages { - /** - * Constructor - * @param {string[]} data data from API - */ - constructor(data) { - // TODO : a lot more - /** - * Raw Packages, as received from the API - * @type {string[]} - */ - this.rawPackages = Array.from(data); - /** - * Cages - * @type {string[]} - */ - this.cages = this._parseCages(); - /** - * Kits - * @type {SkywarsKits} - */ - this.kits = new SkywarsKits(data); - /** - * Achievements included in packages, under the form of name0 - * @type {string[]} - */ - this.achievements = this.rawPackages - .map((pkg) => pkg.match(/^([A-z]+)_?achievement([0-9]?)$/)) - .filter((x) => x) - .map((x) => x.slice(1).join('')); - } - /** - * Parses cages - * @returns {string[]} - */ - _parseCages() { - return this.rawPackages - .map((pkg) => pkg.match(/^cage_([A-z]+)-cage$/)) - .filter((x) => x) - .map((x) => x[1].replace(/-[a-z]/g, (x) => x[1].toUpperCase())); - } -} - -/** - * Parses SkyWars Kits - */ -class SkywarsKit { - /** - * Constructor - * @param {string} kit Kit - */ - constructor(kit) { - /** - * Kit data - * @private - * @type {string[] | null} - */ - this._kitData = kit.match(/^kit_([a-z]+)_([a-z]+)_([a-z]+)$/); - /** - * Is this a kit - * @type {boolean} - */ - this.isKit = !!this._kitData; - if (!this._kitData) return; - /** - * Game mode the kit is for - * @type {KitGameModes} - */ - this.gameMode = this._kitData[2]; - /** - * Kit type - * @type {KitType} - */ - this.kitType = this._kitData[1]; - /** - * Kit name in camelCase - * @type {string} - */ - this.kitName = removeSnakeCaseString(this._kitData[3]); - } -} - -/** - * Parses SkyWars Kits - */ -class SkywarsKits { - /** - * Constructor - * @param {SkywarsKit[]} kits Potential Kits - */ - constructor(kits) { - this.kits = kits.map((kit) => new SkywarsKit(kit)).filter((kit) => kit.isKit); - } - /** - * Get kit by type/gameMode - * @param {KitGameModes} [gameMode] Kits in said game mode - * @param {KitType} [type] Kits corresponding to this type - * @returns {SkywarsKit[]} - */ - get(gameMode = '', type = '') { - return this.kits.filter((kit) => kit.gameMode.startsWith(gameMode) && kit.kitType.startsWith(type)); - } -} - -/** - * @typedef {string} KitType - * * basic - * * supporting - * * mining - * * defending - * * attacking - * * advanced - * * enderchest - */ -/** - * @typedef {string} KitGameModes - * * solo - * * team - */ diff --git a/src/structures/MiniGames/SmashHeroes.js b/src/structures/MiniGames/SmashHeroes.js index 3b6577db..5bece5bc 100644 --- a/src/structures/MiniGames/SmashHeroes.js +++ b/src/structures/MiniGames/SmashHeroes.js @@ -1,10 +1,47 @@ const divide = require('../../utils/divide'); + +// eslint-disable-next-line jsdoc/require-jsdoc +function generateModeStats(data, mode) { + return { + kills: data[`kills_${mode}`] || 0, + deaths: data[`deaths_${mode}`] || 0, + KDRatio: divide(data[`kills_${mode}`], data[`deaths_${mode}`]), + wins: data[`wins_${mode}`] || 0, + losses: data[`losses_${mode}`] || 0, + WLRatio: divide(data[`wins_${mode}`], data[`losses_${mode}`]) + }; +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function generateHeroStats(data) { + const stats = []; + for (const hero in data.class_stats) { + if (Object.prototype.hasOwnProperty.call(data.class_stats, hero)) { + stats.push({ + name: hero, + level: data[`lastLevel_${hero}`] || 0, + xp: data[`xp_${hero}`] || 0, + prestige: data[`pg_${hero}`] || 0, + playedGames: data.class_stats[hero].games || 0, + kills: data.class_stats[hero].kills || 0, + deaths: data.class_stats[hero].deaths || 0, + KDRatio: divide(data.class_stats[hero].kills, data.class_stats[hero].deaths), + wins: data.class_stats[hero].wins || 0, + losses: data.class_stats[hero].losses || 0, + WLRatio: divide(data.class_stats[hero].wins, data.class_stats[hero].losses) + }); + } + } + return stats; +} + /** * SmashHeroes class */ class SmashHeroes { /** * @param {object} data SmashHeroes data + * @example */ constructor(data) { /** @@ -78,40 +115,6 @@ class SmashHeroes { this.heroStats = data.class_stats ? generateHeroStats(data) : null; } } -// eslint-disable-next-line require-jsdoc -function generateModeStats(data, mode) { - return { - kills: data[`kills_${mode}`] || 0, - deaths: data[`deaths_${mode}`] || 0, - KDRatio: divide(data[`kills_${mode}`], data[`deaths_${mode}`]), - wins: data[`wins_${mode}`] || 0, - losses: data[`losses_${mode}`] || 0, - WLRatio: divide(data[`wins_${mode}`], data[`losses_${mode}`]) - }; -} -// eslint-disable-next-line require-jsdoc -function generateHeroStats(data) { - // eslint-disable-next-line no-useless-return - const stats = []; - for (const hero in data.class_stats) { - if (Object.prototype.hasOwnProperty.call(data.class_stats, hero)) { - stats.push({ - name: hero, - level: data[`lastLevel_${hero}`] || 0, - xp: data[`xp_${hero}`] || 0, - prestige: data[`pg_${hero}`] || 0, - playedGames: data.class_stats[hero].games || 0, - kills: data.class_stats[hero].kills || 0, - deaths: data.class_stats[hero].deaths || 0, - KDRatio: divide(data.class_stats[hero].kills, data.class_stats[hero].deaths), - wins: data.class_stats[hero].wins || 0, - losses: data.class_stats[hero].losses || 0, - WLRatio: divide(data.class_stats[hero].wins, data.class_stats[hero].losses) - }); - } - } - return stats; -} /** * @typedef {object} SmashHeroesModes * @property {SmashHeroesModeStats} '1v1v1v1' 1v1v1v1 diff --git a/src/structures/MiniGames/SpeedUHC.js b/src/structures/MiniGames/SpeedUHC.js index 88b4b1b8..add46574 100644 --- a/src/structures/MiniGames/SpeedUHC.js +++ b/src/structures/MiniGames/SpeedUHC.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class SpeedUHC { /** * @param {object} data Speed UHC data + * @example */ constructor(data) { /** @@ -92,8 +93,8 @@ class SpeedUHC { wins: data.wins_solo || 0, losses: data.losses_solo || 0, playedGames: data.games_solo || 0, - winstreak: data.win_streak_solo || 0, - killstreak: data.killstreak_solo || 0, + winStreak: data.win_streak_solo || 0, + killStreak: data.killstreak_solo || 0, assists: data.assists_solo || 0 }; /** @@ -106,10 +107,23 @@ class SpeedUHC { wins: data.wins_team || 0, losses: data.losses_team || 0, playedGames: data.games_team || 0, - winstreak: data.win_streak_team || 0, - killstreak: data.killstreak_team || 0, + winStreak: data.win_streak_team || 0, + killStreak: data.killstreak_team || 0, assists: data.assists_team || 0 }; } } + +/** + * @typedef {object} SpeedUHCModeStats + * @property {number} kills Kills + * @property {number} deaths Deaths + * @property {number} wins Wins + * @property {number} losses Losses + * @property {number} playedGames Played games + * @property {number} winStreak Win streak + * @property {number} killStreak Kill streak + * @property {number} assists Assists + */ + module.exports = SpeedUHC; diff --git a/src/structures/MiniGames/TNTGames.js b/src/structures/MiniGames/TNTGames.js index ecb68e79..877d1d06 100644 --- a/src/structures/MiniGames/TNTGames.js +++ b/src/structures/MiniGames/TNTGames.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class TNTGames { /** * @param {object} data TNT Games data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/TurboKartRacers.js b/src/structures/MiniGames/TurboKartRacers.js index 20259e9f..b4dbdec5 100644 --- a/src/structures/MiniGames/TurboKartRacers.js +++ b/src/structures/MiniGames/TurboKartRacers.js @@ -4,6 +4,7 @@ class TurboKartRacers { /** * @param {object} data TurboKartRacers data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/UHC.js b/src/structures/MiniGames/UHC.js index 45653ea2..c76585a7 100644 --- a/src/structures/MiniGames/UHC.js +++ b/src/structures/MiniGames/UHC.js @@ -1,11 +1,37 @@ -/* eslint-disable max-len */ const divide = require('../../utils/divide'); + +// eslint-disable-next-line jsdoc/require-jsdoc +function getStarLevel(data) { + const kills = + (data.kills || 0) + + (data.kills_solo || 0) + + (data['kills_red vs blue'] || 0) + + (data['kills_no diamonds'] || 0) + + (data.kills_brawl || 0) + + (data['kills_solo brawl'] || 0) + + (data['kills_duo brawl'] || 0); + const wins = + (data.wins || 0) + + (data.wins_solo || 0) + + (data['wins_red vs blue'] || 0) + + (data['wins_no diamonds'] || 0) + + (data.wins_brawl || 0) + + (data['wins_solo brawl'] || 0) + + (data['wins_duo brawl'] || 0); + const sum = Number(kills) + wins * 10; + let starLevel = 1; + const sums = [0, 1, 6, 21, 46, 96, 171, 271, 521, 1021, 1321, 1621, 1921, 2221, 2521, Infinity]; + starLevel += sums.map((x) => x * 10 - sum).findIndex((x) => 0 < x) - 1; + return starLevel; +} + /** * UHC class */ class UHC { /** * @param {object} data UHC data + * @example */ constructor(data) { /** @@ -148,30 +174,6 @@ class UHC { }; } } -// eslint-disable-next-line require-jsdoc -function getStarLevel(data) { - const kills = - (data.kills || 0) + - (data.kills_solo || 0) + - (data['kills_red vs blue'] || 0) + - (data['kills_no diamonds'] || 0) + - (data.kills_brawl || 0) + - (data['kills_solo brawl'] || 0) + - (data['kills_duo brawl'] || 0); - const wins = - (data.wins || 0) + - (data.wins_solo || 0) + - (data['wins_red vs blue'] || 0) + - (data['wins_no diamonds'] || 0) + - (data.wins_brawl || 0) + - (data['wins_solo brawl'] || 0) + - (data['wins_duo brawl'] || 0); - const sum = kills * 1 + wins * 10; - let starLevel = 1; - const sums = [0, 1, 6, 21, 46, 96, 171, 271, 521, 1021, 1321, 1621, 1921, 2221, 2521, Infinity]; - starLevel += sums.map((x) => x * 10 - sum).findIndex((x) => x > 0) - 1; - return starLevel; -} /** * @typedef {object} UHCModeStats * @property {number} kills Kills diff --git a/src/structures/MiniGames/VampireZ.js b/src/structures/MiniGames/VampireZ.js index 60e2073e..723c91dd 100644 --- a/src/structures/MiniGames/VampireZ.js +++ b/src/structures/MiniGames/VampireZ.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class VampireZ { /** * @param {object} data VampireZ data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Walls.js b/src/structures/MiniGames/Walls.js index 25bcdf60..47dbbeb2 100644 --- a/src/structures/MiniGames/Walls.js +++ b/src/structures/MiniGames/Walls.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class Walls { /** * @param {object} data Walls data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/Warlords.js b/src/structures/MiniGames/Warlords.js index b2e8f9b2..a4f75ca4 100644 --- a/src/structures/MiniGames/Warlords.js +++ b/src/structures/MiniGames/Warlords.js @@ -5,6 +5,7 @@ const divide = require('../../utils/divide'); class Warlords { /** * @param {object} data Warlords data + * @example */ constructor(data) { /** diff --git a/src/structures/MiniGames/WoolWars.js b/src/structures/MiniGames/WoolWars.js index f069cdeb..2ee6e13e 100644 --- a/src/structures/MiniGames/WoolWars.js +++ b/src/structures/MiniGames/WoolWars.js @@ -7,6 +7,7 @@ class WoolWars { /** * Constructor * @param {Record} data Data from API + * @example */ constructor(data) { /** @@ -48,7 +49,6 @@ class WoolWars { engineer: WoolWars.generateStatsFor(data.wool_wars?.stats, 'engineer'), archer: WoolWars.generateStatsFor(data.wool_wars?.stats, 'archer') }; - // Misc fields ig /** * Owned Cosmetics * @type {string[]} @@ -64,26 +64,30 @@ class WoolWars { * Converts XP to Level * @param {number} exp xp * @return {number} + * @example */ static convertXPToLevel(exp) { - const minimalExp = [0, 1e3, 3e3, 6e3, 1e4, 15e3]; // NB: progression is 1k, 2k, 3k, 4k, 5k + const minimalExp = [0, 1e3, 3e3, 6e3, 1e4, 15e3]; const baseLevel = minimalExp.length; const baseExp = minimalExp[minimalExp.length - 1]; const expToLevel100 = 49e4; if (exp < baseExp) return minimalExp.findIndex((x) => exp < x); const theoreticalLevel = (exp - baseExp) / 5e3 + baseLevel; - if (theoreticalLevel > 100) return 100 + this.convertXPToLevel(exp - expToLevel100); + if (100 < theoreticalLevel) return 100 + this.convertXPToLevel(exp - expToLevel100); return theoreticalLevel; } /** * Generates stats per class/overall - * @param {Record} data data + * @param {Record} data data * @param {string} [_class=''] Class * @return {WoolWarsStats} + * @example */ static generateStatsFor(data, _class) { // N.B i called it _class instead of class because reserved keyword - const workingData = (_class ? data?.['classes']?.[_class] : data) || {}; + + // eslint-disable-next-line no-underscore-dangle + const workingData = (_class ? data?.classes?.[_class] : data) || {}; return { roundWins: workingData.wins || 0, gamesPlayed: workingData.games_played || 0, diff --git a/src/structures/Pet.js b/src/structures/Pet.js index 432958b9..8073e713 100644 --- a/src/structures/Pet.js +++ b/src/structures/Pet.js @@ -6,6 +6,7 @@ class Pet { /** * @param {string} name Name of pet * @param {object} data data + * @example */ constructor(name, data) { /** @@ -29,7 +30,7 @@ class Pet { * Stats of the pet, if any * @type {object} */ - if (!stats) return; // don't parse stats because there is none. + if (!stats) return; /** * Hunger value ( 100 is highest ) * @type {?number} diff --git a/src/structures/Pets.js b/src/structures/Pets.js index 445c6f47..238fa205 100644 --- a/src/structures/Pets.js +++ b/src/structures/Pets.js @@ -6,6 +6,7 @@ class Pets { /** * @param {string[]} pets Array of pets * @param {object} data data + * @example */ constructor(pets, data) { /** diff --git a/src/structures/Player.js b/src/structures/Player.js index 6cd11aaf..9a103c45 100644 --- a/src/structures/Player.js +++ b/src/structures/Player.js @@ -1,3 +1,10 @@ +const { + playerLevelProgress, + parseClaimedRewards, + getSocialMedia, + getPlayerLevel, + getRank +} = require('../utils/Player'); const SkyWars = require('./MiniGames/SkyWars'); const BedWars = require('./MiniGames/BedWars'); const UHC = require('./MiniGames/UHC'); @@ -24,6 +31,8 @@ const Walls = require('./MiniGames/Walls'); const Warlords = require('./MiniGames/Warlords'); const WoolWars = require('./MiniGames/WoolWars'); const Pit = require('./MiniGames/Pit'); +const Guild = require('./Guild/Guild'); +const RecentGame = require('./RecentGame'); /** * Player class */ @@ -31,6 +40,7 @@ class Player { /** * @param {object} data Player data * @param {Record} extraPayload extra data requested alongside player + * @example */ constructor(data, extraPayload) { /** @@ -93,7 +103,7 @@ class Player { * @type {Color|null} */ this.plusColor = - this.rank === 'MVP+' || this.rank === 'MVP++' + 'MVP+' === this.rank || 'MVP++' === this.rank ? data.rankPlusColor ? new Color(data.rankPlusColor) : new Color('RED') @@ -103,7 +113,7 @@ class Player { * @type {Color|null} */ this.prefixColor = - this.rank === 'MVP++' ? (data.monthlyRankColor ? new Color(data.monthlyRankColor) : new Color('GOLD')) : null; + 'MVP++' === this.rank ? (data.monthlyRankColor ? new Color(data.monthlyRankColor) : new Color('GOLD')) : null; /** * Player karma * @type {number} @@ -158,7 +168,7 @@ class Player { * Last time player claimed the daily reward * @type {Date | null} */ - this.lastDailyReward = new Date(data.lastAdsenseGenerateTime) || null; + this.lastDailyReward = data.lastAdsenseGenerateTime ? new Date(data.lastAdsenseGenerateTime) : null; /** * Last time player claimed the daily reward, as timestamp * @type {number | null} @@ -249,7 +259,7 @@ class Player { * Global Cosmetics a player owns * @type {PlayerCosmetics} */ - this.globalCosmetics = new PlayerCosmetics(data) || null; + this.globalCosmetics = data ? new PlayerCosmetics(data) : null; /** * Time at which the ranks were purchased. Can be all null if bought a long time ago, and some values can be null if player bought directly a rank above that * @type {RanksPurchaseTime} @@ -264,111 +274,12 @@ class Player { /** * Player Name ( at least last known to hypixel ) * @return {string} + * @example */ toString() { return this.nickname; } } - -// eslint-disable-next-line require-jsdoc -function getRank(player) { - let rank; - if (player.prefix) { - rank = player.prefix.replace(/§[0-9|a-z]|\[|\]/g, ''); - } else if (player.rank && player.rank !== 'NORMAL') { - switch (player.rank) { - case 'YOUTUBER': - rank = 'YouTube'; - break; - case 'GAME_MASTER': - rank = 'Game Master'; - break; - case 'ADMIN': - rank = 'Admin'; - break; - } - } else { - switch (player.newPackageRank) { - case 'MVP_PLUS': - rank = player.monthlyPackageRank && player.monthlyPackageRank === 'SUPERSTAR' ? 'MVP++' : 'MVP+'; - break; - case 'MVP': - rank = 'MVP'; - break; - case 'VIP_PLUS': - rank = 'VIP+'; - break; - case 'VIP': - rank = 'VIP'; - break; - default: - rank = player.monthlyPackageRank && player.monthlyPackageRank === 'SUPERSTAR' ? 'MVP++' : 'Default'; - } - } - return rank; -} -// eslint-disable-next-line require-jsdoc -function getPlayerLevel(exp) { - const base = 10000; - const growth = 2500; - const reversePqPrefix = -(base - 0.5 * growth) / growth; - const reverseConst = reversePqPrefix * reversePqPrefix; - const growthDivides2 = 2 / growth; - const num = 1 + reversePqPrefix + Math.sqrt(reverseConst + growthDivides2 * exp); - const level = Math.round(num * 100) / 100; - return level; -} -// eslint-disable-next-line require-jsdoc -function xpToNextLevel(player) { - const lvl = getPlayerLevel(player.networkExp); - const xpToNext = 2500 * Math.floor(lvl) + 5000; - if (player.networkExp < 10000) return 10000; - return xpToNext; -} -// eslint-disable-next-line require-jsdoc -function levelToXP(player) { - let level = Number(Math.floor(getPlayerLevel(player.networkExp))); - level = level - 1; - const xp = 1250 * level ** 2 + 8750 * level; - return xp; -} -// eslint-disable-next-line require-jsdoc -function playerLevelProgress(player) { - const xpFromLevel = levelToXP(player); - let currentXP = player.networkExp - xpFromLevel; - const xpToNext = xpToNextLevel(player); - const remainingXP = xpToNext - currentXP + 2500; - currentXP = currentXP - 2500; - const percent = Math.round((currentXP / xpToNext) * 100 * 100) / 100; - const percentRemaining = Math.round((100 - percent) * 100) / 100; - return { - xpToNext, - remainingXP, - currentXP, - percent, - percentRemaining - }; -} -// eslint-disable-next-line require-jsdoc -function getSocialMedia(data) { - if (!data) return null; - const links = data.links; - const formattedNames = ['Twitter', 'YouTube', 'Instagram', 'Twitch', 'Hypixel', 'Discord']; - const upperNames = ['TWITTER', 'YOUTUBE', 'INSTAGRAM', 'TWITCH', 'HYPIXEL', 'DISCORD']; - if (!links) return null; - return Object.keys(links) - .map((x) => upperNames.indexOf(x)) - .filter((x) => x !== -1) - .map((x) => ({ name: formattedNames[x], link: links[upperNames[x]], id: upperNames[x] })); -} -// eslint-disable-next-line require-jsdoc -function parseClaimedRewards(data) { - if (!data) return null; - return Object.keys(data) - .map((x) => x.match(/levelingReward_(\d+)/)) - .filter((x) => x) - .map((x) => parseInt(x[1], 10)); -} /** * @typedef {string} PlayerRank * * `Default` diff --git a/src/structures/PlayerCosmetics.js b/src/structures/PlayerCosmetics.js index 4558bf55..bfd0fb72 100644 --- a/src/structures/PlayerCosmetics.js +++ b/src/structures/PlayerCosmetics.js @@ -1,11 +1,12 @@ -const Pets = require('./Pets'); const { removeSnakeCaseString } = require('../utils/removeSnakeCase'); +const Pets = require('./Pets'); /** * Player Cosmetics class */ class PlayerCosmetics { /** * @param {object} data data + * @example */ constructor(data) { /** @@ -29,126 +30,126 @@ class PlayerCosmetics { * @type {string[]} */ get suits() { - if (!this._suits) { - this._suits = this.allCosmetics + if (!this.suits) { + this.suits = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('suit_')) .map((x) => removeSnakeCaseString(x.replace('suit_', ''))) || [] : []; } - return this._suits; + return this.suits; } /** * Hats * @type {string[]} */ get hats() { - if (!this._hats) { - this._hats = this.allCosmetics + if (!this.hats) { + this.hats = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('hat_')) .map((x) => removeSnakeCaseString(x.replace('hat_', ''))) || [] : []; } - return this._hats; + return this.hats; } /** * Gadgets * @type {string[]} */ get gadgets() { - if (!this._gadgets) { - this._gadgets = this.allCosmetics + if (!this.gadgets) { + this.gadgets = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('gadget_')) .map((x) => removeSnakeCaseString(x.replace('gadget_', ''))) || [] : []; } - return this._gadgets; + return this.gadgets; } /** * Morphs * @type {string[]} */ get morphs() { - if (!this._morphs) { - this._morphs = this.allCosmetics + if (!this.morphs) { + this.morphs = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('morph_')) .map((x) => removeSnakeCaseString(x.replace('morph_', ''))) || [] : []; } - return this._morphs; + return this.morphs; } /** * Cloaks * @type {string[]} */ get cloaks() { - if (!this._cloaks) { - this._cloaks = this.allCosmetics + if (!this.cloaks) { + this.cloaks = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('cloak_')) .map((x) => removeSnakeCaseString(x.replace('cloak_', ''))) || [] : []; } - return this._cloaks; + return this.cloaks; } /** * Taunts * @type {string[]} */ get taunts() { - if (!this._taunts) { - this._taunts = this.allCosmetics + if (!this.taunts) { + this.taunts = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('taunt_')) .map((x) => removeSnakeCaseString(x.replace('taunt_', ''))) || [] : []; } - return this._taunts; + return this.taunts; } /** * rankColors * @type {string[]} */ get rankColors() { - if (!this._rankcolors) { - this._rankcolors = this.allCosmetics + if (!this.rankColors) { + this.rankColors = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('rankcolor_')) .map((x) => removeSnakeCaseString(x.replace('rankcolor_', ''))) || [] : []; } - return this._rankcolors; + return this.rankColors; } /** * Particle Packs * @type {string[]} */ get particlePacks() { - if (!this._particle) { - this._particle = this.allCosmetics + if (!this.particle) { + this.particle = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('particlepack_')) .map((x) => removeSnakeCaseString(x.replace('particlepack_', ''))) || [] : []; } - return this._particlepacks; + return this.particlepacks; } /** * Click Effects * @type {string[]} */ get clickEffects() { - if (!this._clickfx) { - this._clickfx = this.allCosmetics + if (!this.clickfx) { + this.clickfx = this.allCosmetics ? this.allCosmetics .filter((x) => x.startsWith('clickeffects_')) .map((x) => removeSnakeCaseString(x.replace('clickeffects_', ''))) || [] : []; } - return this._clickfx; + return this.clickfx; } } module.exports = PlayerCosmetics; diff --git a/src/structures/RecentGame.js b/src/structures/RecentGame.js index 21f5fd9a..d33e0210 100644 --- a/src/structures/RecentGame.js +++ b/src/structures/RecentGame.js @@ -6,6 +6,7 @@ const Game = require('./Game'); class RecentGame extends Game { /** * @param {object} data Recent game data + * @example */ constructor(data) { super(data.gameType); @@ -49,6 +50,7 @@ class RecentGame extends Game { /** * Name of gamemode * @return {string} + * @example */ toString() { return this.mode; diff --git a/src/structures/ServerInfo.js b/src/structures/ServerInfo.js index 0ded1a8f..2b458dcb 100644 --- a/src/structures/ServerInfo.js +++ b/src/structures/ServerInfo.js @@ -6,6 +6,7 @@ class ServerInfo { * Constructor * @param {Object} data data parsed from packet * @param {number} ping Ping + * @example */ constructor(data, ping) { /** @@ -62,6 +63,7 @@ class ServerInfo { /** * toString override * @returns {string} + * @example */ toString() { return `${this.textMOTD} - ${this.players} Players (${this.ping} ms) - ${this.versionInfo}`; diff --git a/src/structures/SkyBlock/Auctions/Auction.js b/src/structures/SkyBlock/Auctions/Auction.js index 06f6c3f6..a8acc0e0 100644 --- a/src/structures/SkyBlock/Auctions/Auction.js +++ b/src/structures/SkyBlock/Auctions/Auction.js @@ -7,6 +7,7 @@ class Auction extends BaseAuction { /** * @param {object} data * @param {boolean} includeItemBytes + * @example */ constructor(data, includeItemBytes) { super(data, includeItemBytes); @@ -84,6 +85,7 @@ class Auction extends BaseAuction { /** * Item Name * @return {string} + * @example */ toString() { return this.item; diff --git a/src/structures/SkyBlock/Auctions/AuctionInfo.js b/src/structures/SkyBlock/Auctions/AuctionInfo.js index 003471c4..72c0a84c 100644 --- a/src/structures/SkyBlock/Auctions/AuctionInfo.js +++ b/src/structures/SkyBlock/Auctions/AuctionInfo.js @@ -1,10 +1,10 @@ -/* eslint-disable require-jsdoc */ /** * Auction info class */ class AuctionInfo { /** * @param {object} data Auction info data + * @example */ constructor(data) { /** @@ -36,6 +36,8 @@ class AuctionInfo { * Age * @type {number} */ + + // eslint-disable-next-line no-underscore-dangle this.age = parseInt(data._headers.get('age'), 10) || 0; } @@ -46,6 +48,7 @@ class AuctionInfo { /** * Current Page / Total Page * @return {string} + * @example */ toString() { return `${this.page} / ${this.totalPages}`; diff --git a/src/structures/SkyBlock/Auctions/BaseAuction.js b/src/structures/SkyBlock/Auctions/BaseAuction.js index 946d32b8..5dd79437 100644 --- a/src/structures/SkyBlock/Auctions/BaseAuction.js +++ b/src/structures/SkyBlock/Auctions/BaseAuction.js @@ -6,6 +6,7 @@ class BaseAuction { /** * @param {object} data Base auction data * @param {boolean} includeItemBytes + * @example */ constructor(data, includeItemBytes) { /** @@ -32,11 +33,12 @@ class BaseAuction { * Item bytes * @type {ItemBytes|null} */ - this.itemBytes = includeItemBytes ? new ItemBytes(data.item_bytes) || null : null; + this.itemBytes = includeItemBytes ? new ItemBytes(data.item_bytes) : null; } /** * Auction ID * @return {string} + * @example */ toString() { return this.auctionId; diff --git a/src/structures/SkyBlock/Auctions/Bid.js b/src/structures/SkyBlock/Auctions/Bid.js index dc884522..60df4070 100644 --- a/src/structures/SkyBlock/Auctions/Bid.js +++ b/src/structures/SkyBlock/Auctions/Bid.js @@ -4,6 +4,7 @@ class Bid { /** * @param {object} data Bid data + * @example */ constructor(data) { /** @@ -40,6 +41,7 @@ class Bid { /** * Bidder Name - Bid Amount * @return {string} + * @example */ toString() { return `${this.bidder} bid ${this.amount} coins`; diff --git a/src/structures/SkyBlock/Auctions/PartialAuction.js b/src/structures/SkyBlock/Auctions/PartialAuction.js index a6265710..b2d5aaad 100644 --- a/src/structures/SkyBlock/Auctions/PartialAuction.js +++ b/src/structures/SkyBlock/Auctions/PartialAuction.js @@ -7,6 +7,7 @@ class PartialAuction extends BaseAuction { /** * @param {object} data Partial auction data * @param {boolean} includeItemBytes + * @example */ constructor(data, includeItemBytes) { super(data, includeItemBytes); diff --git a/src/structures/SkyBlock/Bazzar/Order.js b/src/structures/SkyBlock/Bazzar/Order.js index bd17eff2..07efc297 100644 --- a/src/structures/SkyBlock/Bazzar/Order.js +++ b/src/structures/SkyBlock/Bazzar/Order.js @@ -4,6 +4,7 @@ class Order { /** * @param {object} data Order data + * @example */ constructor(data) { /** @@ -30,6 +31,7 @@ class Order { /** * Price as string * @return {string} + * @example */ toString() { return this.totalPrice; diff --git a/src/structures/SkyBlock/Bazzar/Product.js b/src/structures/SkyBlock/Bazzar/Product.js index 245aba18..d8a208b5 100644 --- a/src/structures/SkyBlock/Bazzar/Product.js +++ b/src/structures/SkyBlock/Bazzar/Product.js @@ -6,6 +6,7 @@ const Order = require('./Order'); class Product { /** * @param {object} data Product data + * @example */ constructor(data) { /** diff --git a/src/structures/SkyBlock/News/SkyblockNews.js b/src/structures/SkyBlock/News/SkyblockNews.js index 45cc5d0a..46c1e89a 100644 --- a/src/structures/SkyBlock/News/SkyblockNews.js +++ b/src/structures/SkyBlock/News/SkyblockNews.js @@ -1,11 +1,26 @@ -const dateRegExp = /(\d{1,2})(?:st|nd|rd|th|) ([A-z]+) (\d+)/; +const dateRegExp = /(\d{1,2})(?:st|nd|rd|th|) ([A-Za-z]+) (\d+)/; const versionRegExp = /v\d+(\.\d+){1,}/; + +// eslint-disable-next-line jsdoc/require-jsdoc +function parseDate(stringDate) { + const matched = stringDate.match(dateRegExp); + if (!matched) return null; + return new Date(matched.slice(1).join(' ')); +} + +// eslint-disable-next-line jsdoc/require-jsdoc +function parseVer(stringVer) { + const matches = versionRegExp.exec(stringVer); + if (!matches?.length) return null; + return matches[0]; +} /** * SkyblockNews */ class SkyblockNews { /** * @param {object} data + * @example */ constructor(data) { /** @@ -32,29 +47,16 @@ class SkyblockNews { * The version from the title (Skyblock v0.12.57673856757.327.2 => v0.12.57673856757.327.2) * @author linearaccelerator * @type {string | null} - * @version >6.0.1 */ this.version = parseVer(this.title); } /** * News title * @return {string} + * @example */ toString() { return this.title; } } -// eslint-disable-next-line require-jsdoc -function parseDate(stringDate) { - const matched = stringDate.match(dateRegExp); - if (!matched) return null; - return new Date(matched.slice(1).join(' ')); // Ok this is lazy, but should work -} - -// eslint-disable-next-line require-jsdoc -function parseVer(stringVer) { - const matches = versionRegExp.exec(stringVer); - if (!matches?.length) return null; // this shouldn't really happen - return matches[0]; -} module.exports = SkyblockNews; diff --git a/src/structures/SkyBlock/PlayerBingo.js b/src/structures/SkyBlock/PlayerBingo.js index 96467aeb..adc12215 100644 --- a/src/structures/SkyBlock/PlayerBingo.js +++ b/src/structures/SkyBlock/PlayerBingo.js @@ -1,6 +1,11 @@ +const { populateGoals } = require('../../utils/SkyblockUtils'); +// eslint-disable-next-line no-unused-vars +const BingoDataType = require('./Static/BingoData.js'); +// eslint-disable-next-line no-unused-vars +const BingoType = require('./Static/Bingo.js'); /** - * @typedef {require('./Static/BingoData.js')} BingoData - * @typedef {require('./Static/Bingo.js')} Bingo + * @typedef {BingoDataType} BingoData + * @typedef {BingoType} Bingo */ /** @@ -11,6 +16,7 @@ class PlayerBingo { * Constructor * @param {Object} data data * @param {BingoData|null} bingoData bingo data + * @example */ constructor(data, bingoData) { const events = data.success && Array.isArray(data.events) ? data.events : []; @@ -33,18 +39,6 @@ class PlayerBingo { } } -// eslint-disable-next-line require-jsdoc -function populateGoals(achieved, all) { - const populatedAchieved = []; - const unachieved = []; - for (const goal of all) { - if (achieved.find((str) => str === goal.name)) populatedAchieved.push(goal); - else unachieved.push(goal); - } - populatedAchieved.unachievedGoals = unachieved; - return populatedAchieved; -} - /** * @typedef {Object} PlayerBingoDataPerEvent * @property {number} eventId ID of event diff --git a/src/structures/SkyBlock/SkyblockInventoryItem.js b/src/structures/SkyBlock/SkyblockInventoryItem.js index 78d9f0fd..d781f0e2 100644 --- a/src/structures/SkyBlock/SkyblockInventoryItem.js +++ b/src/structures/SkyBlock/SkyblockInventoryItem.js @@ -1,9 +1,11 @@ +const { parseRarity, parseGearScore } = require('../../utils/SkyblockUtils'); /** * Item class */ class SkyblockInventoryItem { /** * @param {object} data Item data + * @example */ constructor(data) { /** @@ -21,7 +23,7 @@ class SkyblockInventoryItem { * @type {string} */ this.name = - data.tag.display.Name !== null ? data.tag.display.Name.toString().replace(/§([1-9]|[a-f])|§/gm, '') : null; + null !== data.tag.display.Name ? data.tag.display.Name.toString().replace(/§([1-9]|[a-f])|§/gm, '') : null; /** * Item lore * @type {string} @@ -58,7 +60,6 @@ class SkyblockInventoryItem { */ this.gemstones = data.tag.ExtraAttributes.gems ? Object.entries(data.tag.ExtraAttributes.gems).map((gem) => { - // eslint-disable-next-line no-new-object return new Object({ type: gem[0].split('_')[0], quality: gem[1] }); }) : null; @@ -71,7 +72,6 @@ class SkyblockInventoryItem { * What rarity the item has, as an uppercase string * @author linearaccelerator * @type {string} - * @version >6.0.1 */ this.rarity = parseRarity(this.loreArray[this.loreArray.length - 1]); /** @@ -94,7 +94,7 @@ class SkyblockInventoryItem { * Is the item soulbound * @type {boolean} */ - this.soulbound = data.tag.ExtraAttributes.donated_museum === 1; + this.soulbound = 1 === data.tag.ExtraAttributes.donated_museum; /** * Amount of art of war books applied to the item * @type {number} @@ -114,7 +114,7 @@ class SkyblockInventoryItem { * Is the item recombobulated * @type {boolean} */ - this.recombobulated = data.tag.ExtraAttributes.rarity_upgrades === 1; + this.recombobulated = 1 === data.tag.ExtraAttributes.rarity_upgrades; /** * Item attributes * @type {object} @@ -154,34 +154,12 @@ class SkyblockInventoryItem { /** * Item Name * @return {string} + * @example */ toString() { return this.name; } } -// eslint-disable-next-line require-jsdoc -function parseRarity(stringContainingRarity) { - const rarityArray = [ - 'COMMON', - 'UNCOMMON', - 'RARE', - 'EPIC', - 'LEGENDARY', - 'MYTHIC', - 'DIVINE', - 'SPECIAL', - 'VERY SPECIAL' - ]; - for (const rarity of rarityArray) { - if (stringContainingRarity.includes(rarity)) return rarity; - } -} -// eslint-disable-next-line require-jsdoc -function parseGearScore(lore) { - for (const line of lore) { - if (line.match(/Gear Score: §[0-9a-f](\d+)/)) return Number(line.match(/Gear Score: §d(\d+)/)[1]); - } -} /** * @typedef {object} SkyblockItemGemstone diff --git a/src/structures/SkyBlock/SkyblockMember.js b/src/structures/SkyBlock/SkyblockMember.js index 23aa3067..856d18ca 100644 --- a/src/structures/SkyBlock/SkyblockMember.js +++ b/src/structures/SkyBlock/SkyblockMember.js @@ -1,20 +1,29 @@ const { - decode, - getLevelByXp, - getSlayerLevel, + getTrophyFishRank, getMemberStats, - getTrophyFishRank + getLevelByXp, + decode, + getSkills, + getBestiaryLevel, + getSlayer, + getDungeons, + getJacobData, + getChocolateFactory, + getPetLevel } = require('../../utils/SkyblockUtils'); const SkyblockInventoryItem = require('./SkyblockInventoryItem'); const Constants = require('../../utils/Constants'); const skyhelper = require('skyhelper-networth'); const SkyblockPet = require('./SkyblockPet'); +const Player = require('../Player'); + /** * Skyblock member class */ class SkyblockMember { /** * @param {object} data Skyblock member data + * @example */ constructor(data) { /** @@ -72,7 +81,7 @@ class SkyblockMember { * Skyblock Level * @type {number} */ - this.level = this.experience / 100 ?? 0; + this.level = this.experience ? this.experience / 100 : 0; /** * Heart of the Mountain - MiningSkill * @type {number} @@ -151,6 +160,7 @@ class SkyblockMember { /** * Equipped armor * @return {Promise} + * @example */ this.getArmor = async () => { const base64 = data.m.inventory.inv_armor; @@ -165,20 +175,22 @@ class SkyblockMember { }; /** * Wardrobe contents - * @return {Promise} + * @return {Promise} + * @example */ this.getWardrobe = async () => { const base64 = data.m?.inventory?.wardrobe_contents?.data; if (!base64) return []; const decoded = await decode(base64); const armor = decoded - .filter((item) => Object.keys(item).length !== 0) + .filter((item) => 0 !== Object.keys(item).length) .map((item) => new SkyblockInventoryItem(item)); return armor; }; /** * Skyblock member enderchest * @return {Promise} + * @example */ this.getEnderChest = async () => { let chest = data.m.inventory.ender_chest_contents; @@ -194,13 +206,14 @@ class SkyblockMember { edited.push(new SkyblockInventoryItem(chest[i])); } return edited; - } catch (e) { + } catch { return []; } }; /** * Skyblock member inventory * @return {Promise} + * @example */ this.getInventory = async () => { let inventory = data.m.inventory.inv_contents; @@ -216,25 +229,26 @@ class SkyblockMember { edited.push(new SkyblockInventoryItem(inventory[i])); } return edited; - } catch (e) { + } catch { return []; } }; /** * Skyblock Member pet score * @return {number} + * @example */ this.getPetScore = () => { const highestRarity = {}; for (const pet of data.m.pets_data.pets) { - if (!(pet.type in highestRarity) || Constants.pet_score[pet.tier] > highestRarity[pet.type]) { - highestRarity[pet.type] = Constants.pet_score[pet.tier]; + if (!(pet.type in highestRarity) || Constants.petScore[pet.tier] > highestRarity[pet.type]) { + highestRarity[pet.type] = Constants.petScore[pet.tier]; } } const highestLevel = {}; for (const pet of data.m.pets_data.pets) { - const maxLevel = pet.type === 'GOLDEN_DRAGON' ? 200 : 100; + const maxLevel = 'GOLDEN_DRAGON' === pet.type ? 200 : 100; const petLevel = getPetLevel(pet.exp, pet.tier, maxLevel); if (!(pet.type in highestLevel) || petLevel.level > highestLevel[pet.type]) { @@ -253,6 +267,7 @@ class SkyblockMember { /** * Skyblock member equipment * @return {Promise} + * @example */ this.getEquipment = async () => { let equipment = data.m.inventory.equipment_contents; @@ -267,13 +282,14 @@ class SkyblockMember { necklace: equipment[0].id ? new SkyblockInventoryItem(equipment[0]) : null }; return playerEquipment; - } catch (e) { + } catch { return []; } }; /** * Skyblock member Personal Vault * @return {Promise} + * @example */ this.getPersonalVault = async () => { let vault = data.m.inventory.personal_vault_contents; @@ -289,13 +305,14 @@ class SkyblockMember { edited.push(new SkyblockInventoryItem(vault[i])); } return edited; - } catch (e) { + } catch { return []; } }; /** * Skyblock member networth (Credit to skyhelper-networth package) * @return {Promise} + * @example */ this.getNetworth = async () => { try { @@ -306,7 +323,7 @@ class SkyblockMember { museumData: data.museum?.raw ?? {} }); return nw; - } catch (e) { + } catch { return []; } }; @@ -314,280 +331,12 @@ class SkyblockMember { /** * UUID * @return {string} + * @example */ toString() { return this.uuid; } } -// eslint-disable-next-line require-jsdoc -function getSkills(data) { - const skillsObject = {}; - skillsObject['combat'] = getLevelByXp(data?.player_data?.experience?.SKILL_COMBAT ?? 0, 'combat'); - skillsObject['farming'] = getLevelByXp( - data?.player_data?.experience?.SKILL_FARMING ?? 0, - 'farming', - data?.m?.jacobs_contest?.perks?.farming_level_cap ?? 0 + 50 - ); - skillsObject['fishing'] = getLevelByXp(data?.player_data?.experience?.SKILL_FISHING ?? 0, 'fishing'); - skillsObject['mining'] = getLevelByXp(data?.player_data?.experience?.SKILL_MINING ?? 0, 'mining'); - skillsObject['foraging'] = getLevelByXp(data?.player_data?.experience?.SKILL_FORAGING ?? 0, 'foraging'); - skillsObject['enchanting'] = getLevelByXp(data?.player_data?.experience?.SKILL_ENCHANTING ?? 0, 'enchanting'); - skillsObject['alchemy'] = getLevelByXp(data?.player_data?.experience?.SKILL_ALCHEMY ?? 0, 'alchemy'); - skillsObject['carpentry'] = getLevelByXp(data?.player_data?.experience?.SKILL_CARPENTRY ?? 0, 'carpentry'); - skillsObject['runecrafting'] = getLevelByXp(data?.player_data?.experience?.SKILL_RUNECRAFTING ?? 0, 'runecrafting'); - skillsObject['taming'] = getLevelByXp(data?.player_data?.experience?.SKILL_TAMING ?? 0, 'taming'); - skillsObject['social'] = getLevelByXp(data?.player_data?.experience?.SKILL_SOCIAL ?? 0, 'social'); - const levels = Object.values(skillsObject) - .filter((skill) => skill.cosmetic !== true) - .map((skill) => skill.level); - skillsObject['average'] = levels.reduce((a, b) => a + b, 0) / levels.length; - return skillsObject; -} -// eslint-disable-next-line require-jsdoc -function formatBestiaryMobs(userProfile, mobs) { - const output = []; - for (const mob of mobs) { - const mobBracket = Constants.bestiaryBrackets[mob.bracket]; - - const totalKills = mob.mobs.reduce((acc, cur) => { - return acc + (userProfile.bestiary.kills[cur] ?? 0); - }, 0); - - const maxKills = mob.cap; - const nextTierKills = mobBracket.find((tier) => totalKills < tier && tier <= maxKills); - const tier = nextTierKills ? mobBracket.indexOf(nextTierKills) : mobBracket.indexOf(maxKills) + 1; - - output.push({ - tier: tier - }); - } - - return output; -} - -// eslint-disable-next-line require-jsdoc -function getBestiaryLevel(userProfile) { - try { - if (userProfile.bestiary?.kills === undefined) { - return null; - } - - const output = {}; - let tiersUnlocked = 0; - for (const [category, data] of Object.entries(Constants.bestiary)) { - const { mobs } = data; - output[category] = {}; - - if (category === 'fishing') { - for (const [key, value] of Object.entries(data)) { - output[category][key] = { - mobs: formatBestiaryMobs(userProfile, value.mobs) - }; - tiersUnlocked += output[category][key].mobs.reduce((acc, cur) => acc + cur.tier, 0); - } - } else { - output[category].mobs = formatBestiaryMobs(userProfile, mobs); - tiersUnlocked += output[category].mobs.reduce((acc, cur) => acc + cur.tier, 0); - } - } - - return tiersUnlocked / 10; - } catch (error) { - // eslint-disable-next-line no-console - console.log(error); - return null; - } -} -// eslint-disable-next-line require-jsdoc -function getSlayer(data) { - if (!data?.slayer?.slayer_bosses) return; - return { - zombie: getSlayerLevel(data?.slayer?.slayer_bosses?.zombie), - spider: getSlayerLevel(data?.slayer?.slayer_bosses?.spider), - wolf: getSlayerLevel(data?.slayer?.slayer_bosses?.wolf), - enderman: getSlayerLevel(data?.slayer?.slayer_bosses?.enderman), - blaze: getSlayerLevel(data?.slayer?.slayer_bosses?.blaze), - vampire: getSlayerLevel(data?.slayer?.slayer_bosses?.vampire) - }; -} -// eslint-disable-next-line require-jsdoc -function getDungeons(data) { - return { - types: { - catacombs: getLevelByXp( - data.dungeons?.dungeon_types?.catacombs ? data.dungeons.dungeon_types.catacombs.experience : null, - 'dungeons' - ) - }, - classes: { - healer: getLevelByXp( - data.dungeons?.player_classes?.healer ? data.dungeons.player_classes.healer.experience : null, - 'dungeons' - ), - mage: getLevelByXp( - data.dungeons?.player_classes?.mage ? data.dungeons.player_classes.mage.experience : null, - 'dungeons' - ), - berserk: getLevelByXp( - data.dungeons?.player_classes?.berserk ? data.dungeons.player_classes.berserk.experience : null, - 'dungeons' - ), - archer: getLevelByXp( - data.dungeons?.player_classes?.archer ? data.dungeons.player_classes.archer.experience : null, - 'dungeons' - ), - tank: getLevelByXp( - data.dungeons?.player_classes?.tank ? data.dungeons.player_classes.tank.experience : null, - 'dungeons' - ) - } - }; -} -// eslint-disable-next-line require-jsdoc -function getJacobData(data) { - if (!data.jacobs_contest) { - return { - medals: { - bronze: 0, - silver: 0, - gold: 0 - }, - perks: { - doubleDrops: 0, - farmingLevelCap: 0, - personalBests: false - }, - contests: {} - }; - } - return { - medals: data.jacobs_contest.medals_inv - ? { - bronze: data.jacobs_contest.medals_inv.bronze || 0, - silver: data.jacobs_contest.medals_inv.silver || 0, - gold: data.jacobs_contest.medals_inv.gold || 0 - } - : { bronze: 0, silver: 0, gold: 0 }, - perks: data.jacobs_contest.perks - ? { - doubleDrops: data.jacobs_contest.perks.double_drops || 0, - farmingLevelCap: data.jacobs_contest.perks.farming_level_cap || 0, - personalBests: data.jacobs_contest.perks.personal_bests || false - } - : { doubleDrops: 0, farmingLevelCap: 0, personalBests: false }, - contests: data.jacobs_contest.contests || {} - }; -} -// eslint-disable-next-line require-jsdoc -function getChocolateFactory(data) { - if (!data?.events?.easter) { - return { - employees: { - bro: 0, - cousin: 0, - sis: 0, - father: 0, - grandma: 0, - dog: 0, - uncle: 0 - }, - chocolate: { - current: 0, - total: 0, - sincePrestige: 0 - }, - timeTower: { - charges: 0, - level: 0 - }, - upgrades: { - click: 0, - multiplier: 0, - rabbitRarity: 0 - }, - goldenClick: { - amount: 0, - year: 0 - }, - barnCapacity: 0, - prestige: 0 - }; - } - return { - employees: { - bro: data?.events?.easter?.employees?.rabbit_bro || 0, - cousin: data?.events?.easter?.employees?.rabbit_cousin || 0, - sis: data?.events?.easter?.employees?.rabbit_sis || 0, - father: data?.events?.easter?.employees?.rabbit_father || 0, - grandma: data?.events?.easter?.employees?.rabbit_grandma || 0, - dog: data?.events?.easter?.employees?.rabbit_dog || 0, - uncle: data?.events?.easter?.employees?.rabbit_uncle || 0 - }, - chocolate: { - current: data?.events?.easter?.chocolate || 0, - total: data?.events?.easter?.total_chocolate || 0, - sincePrestige: data?.events?.easter?.chocolate_since_prestige || 0 - }, - timeTower: { - charges: data?.events?.easter?.time_tower?.charges || 0, - level: data?.events?.easter?.time_tower?.level || 0 - }, - upgrades: { - click: data?.events?.easter?.click_upgrades || 0, - multiplier: data?.events?.easter?.chocolate_multiplier_upgrades || 0, - rabbitRarity: data?.events?.easter?.rabbit_rarity_upgrades || 0 - }, - goldenClick: { - amount: data?.events?.easter?.golden_click_amount || 0, - year: data?.events?.easter?.golden_click_year || 0 - }, - barnCapacity: data?.events?.easter?.rabbit_barn_capacity_level || 0, - prestige: data?.events?.easter?.chocolate_level || 0 - }; -} -// eslint-disable-next-line require-jsdoc -function getPetLevel(petExp, offsetRarity, maxLevel) { - const rarityOffset = Constants.pet_rarity_offset[offsetRarity]; - const levels = Constants.pet_levels.slice(rarityOffset, rarityOffset + maxLevel - 1); - - const xpMaxLevel = levels.reduce((a, b) => a + b, 0); - let xpTotal = 0; - let level = 1; - - let xpForNext = Infinity; - - for (let i = 0; i < maxLevel; i++) { - xpTotal += levels[i]; - - if (xpTotal > petExp) { - xpTotal -= levels[i]; - break; - } else { - level++; - } - } - - let xpCurrent = Math.floor(petExp - xpTotal); - let progress; - - if (level < maxLevel) { - xpForNext = Math.ceil(levels[level - 1]); - progress = Math.max(0, Math.min(xpCurrent / xpForNext, 1)); - } else { - level = maxLevel; - xpCurrent = petExp - levels[maxLevel - 1]; - xpForNext = 0; - progress = 1; - } - - return { - level, - xpCurrent, - xpForNext, - progress, - xpMaxLevel - }; -} /** * @typedef {object} SkyblockMemberEquipment * @property {SkyblockInventoryItem|null} gauntlet Gauntlet diff --git a/src/structures/SkyBlock/SkyblockMuseum.js b/src/structures/SkyBlock/SkyblockMuseum.js index 8753275e..8c097412 100644 --- a/src/structures/SkyBlock/SkyblockMuseum.js +++ b/src/structures/SkyBlock/SkyblockMuseum.js @@ -6,6 +6,7 @@ const { decode } = require('../../utils/SkyblockUtils'); class SkyblockMuseum { /** * @param {object} data Skyblock member data + * @example */ constructor(data) { /** @@ -16,6 +17,7 @@ class SkyblockMuseum { /** * Normal Items * @returns {SkyblockMuseumItem[]} + * @example */ this.getItems = async () => { const keys = Object.keys(data.m.members[data.uuid].items); @@ -37,6 +39,7 @@ class SkyblockMuseum { /** * Special items * @returns {SkyblockMuseumItem[]} + * @example */ this.getSpecial = async () => { const items = []; diff --git a/src/structures/SkyBlock/SkyblockMuseumItem.js b/src/structures/SkyBlock/SkyblockMuseumItem.js index 2feba13c..01f9c466 100644 --- a/src/structures/SkyBlock/SkyblockMuseumItem.js +++ b/src/structures/SkyBlock/SkyblockMuseumItem.js @@ -5,6 +5,7 @@ const SkyblockInventoryItem = require('./SkyblockInventoryItem'); class SkyblockMuseumItem { /** * @param {object} data Item data + * @example */ constructor(data) { /** @@ -45,6 +46,7 @@ class SkyblockMuseumItem { /** * Item Name * @return {string} + * @example */ toString() { return this.name; diff --git a/src/structures/SkyBlock/SkyblockPet.js b/src/structures/SkyBlock/SkyblockPet.js index 1db58d21..4dd40613 100644 --- a/src/structures/SkyBlock/SkyblockPet.js +++ b/src/structures/SkyBlock/SkyblockPet.js @@ -1,5 +1,4 @@ -// eslint-disable-next-line camelcase -const { pet_score } = require('../../utils/Constants'); +const { petScore } = require('../../utils/Constants'); /** * Skyblock Pet class */ @@ -7,6 +6,7 @@ class SkyblockPet { /** * Skyblock pet data * @param {object} data + * @example */ constructor(data) { /** @@ -38,8 +38,8 @@ class SkyblockPet { * Skyblock Pet score * @type {number} */ - // eslint-disable-next-line camelcase - this.petScore = pet_score[data.tier] || 0; + + this.petScore = petScore[data.tier] || 0; /** * Skyblock Pet held item * @type {string|null} diff --git a/src/structures/SkyBlock/SkyblockProfile.js b/src/structures/SkyBlock/SkyblockProfile.js index 359785bf..18b37f89 100644 --- a/src/structures/SkyBlock/SkyblockProfile.js +++ b/src/structures/SkyBlock/SkyblockProfile.js @@ -6,6 +6,7 @@ class SkyblockProfile { /** * Skyblock profile data * @param {object} data + * @example */ constructor(data) { /** @@ -65,6 +66,7 @@ class SkyblockProfile { /** * Profile Name * @return {string} + * @example */ toString() { return this.profileName; diff --git a/src/structures/SkyBlock/Static/Bingo.js b/src/structures/SkyBlock/Static/Bingo.js index fcf0eee9..cf13e0aa 100644 --- a/src/structures/SkyBlock/Static/Bingo.js +++ b/src/structures/SkyBlock/Static/Bingo.js @@ -1,3 +1,9 @@ +// eslint-disable-next-line jsdoc/require-jsdoc +function parsePosition(position) { + const x = (position % 5) + 1; + const y = Math.floor(position / 5) + 1; + return [x, y]; +} /** * Bingo class */ @@ -6,6 +12,7 @@ class Bingo { * Constructor * @param {Object} data data * @param {number} position Position + * @example */ constructor(data, position = 0) { /** @@ -50,7 +57,7 @@ class Bingo { * Difference between each tier requirement, if it is constant * @type {number|null} */ - this.tierStep = this.#getTierStep(); + this.tierStep = this.getTierStep(); /** * Only available for ONE_TIERED bingos * @type {number|null} @@ -69,6 +76,7 @@ class Bingo { * As string * BEWARE this returns ID to assure compatibility with PlayerBingo * @return {string} + * @example */ toString() { return this.id; @@ -77,11 +85,12 @@ class Bingo { * Gets tier step, if constant * @private * @returns {number|null} + * @example */ - #getTierStep() { - if (this.type !== 'TIERED') return null; + getTierStep() { + if ('TIERED' !== this.type) return null; // No step possible - if (this.tiers.length < 2) return null; + if (2 > this.tiers.length) return null; const hypotheticStep = this.tiers[1] - this.tiers[0]; // Check if every 2 elements have the same step const isConstant = this.tiers.slice(1).every((el, index) => { @@ -92,11 +101,4 @@ class Bingo { } } -// eslint-disable-next-line require-jsdoc -function parsePosition(position) { - const x = (position % 5) + 1; - const y = Math.floor(position / 5) + 1; - return [x, y]; -} - module.exports = Bingo; diff --git a/src/structures/SkyBlock/Static/BingoData.js b/src/structures/SkyBlock/Static/BingoData.js index e82c2b0d..1667dc05 100644 --- a/src/structures/SkyBlock/Static/BingoData.js +++ b/src/structures/SkyBlock/Static/BingoData.js @@ -7,6 +7,7 @@ class BingoData { /** * constructor * @param {Object} data + * @example */ constructor(data) { /** @@ -35,9 +36,10 @@ class BingoData { * @param {number} column Column number (starts at 1) * @param {number} row Row number (starts at 1) * @returns {Bingo|undefined} + * @example */ getGoal(column, row) { - if (!this.goals || this.goals.length < 1) return; + if (!this.goals || 1 > this.goals.length) return; return this.goals.find((goal) => goal.row === row && goal.column === column); } } diff --git a/src/structures/SkyBlock/Static/Candidate.js b/src/structures/SkyBlock/Static/Candidate.js index a6478634..7cd3a785 100644 --- a/src/structures/SkyBlock/Static/Candidate.js +++ b/src/structures/SkyBlock/Static/Candidate.js @@ -7,6 +7,7 @@ class Candidate { * Constructor * @param {Object} data data * @param {boolean} [isMayor=false] if this candidate is the current mayor + * @example */ constructor(data, isMayor = false) { /** diff --git a/src/structures/SkyBlock/Static/FireSale.js b/src/structures/SkyBlock/Static/FireSale.js index 20dfa18c..bb415cbf 100644 --- a/src/structures/SkyBlock/Static/FireSale.js +++ b/src/structures/SkyBlock/Static/FireSale.js @@ -5,6 +5,7 @@ class FireSale { /** * constructor * @param {Object} data + * @example */ constructor(data) { /** @@ -46,6 +47,7 @@ class FireSale { /** * Item Id * @return {string|null} + * @example */ toString() { return this.itemId; diff --git a/src/structures/SkyBlock/Static/Government.js b/src/structures/SkyBlock/Static/Government.js index 9aeae4ca..6e12eb8e 100644 --- a/src/structures/SkyBlock/Static/Government.js +++ b/src/structures/SkyBlock/Static/Government.js @@ -7,6 +7,7 @@ class GovernmentData { /** * constructor * @param {Object} data + * @example */ constructor(data) { /** @@ -65,6 +66,7 @@ class GovernmentData { /** * Current Mayor * @return {string} + * @example */ toString() { return this.mayor.name; diff --git a/src/structures/SkyBlock/Static/Perk.js b/src/structures/SkyBlock/Static/Perk.js index cf3c00a4..d3ce5f5b 100644 --- a/src/structures/SkyBlock/Static/Perk.js +++ b/src/structures/SkyBlock/Static/Perk.js @@ -6,6 +6,7 @@ class Perk { * Constructor * @param {Object} data data * @param {boolean} [isMayor=false] if this candidate is the current mayor + * @example */ constructor(data) { /** diff --git a/src/structures/Static/Achievement.js b/src/structures/Static/Achievement.js index 235e48bd..eb7afe0f 100644 --- a/src/structures/Static/Achievement.js +++ b/src/structures/Static/Achievement.js @@ -1,5 +1,17 @@ const AchievementTier = require('./AchievementTier'); +// eslint-disable-next-line jsdoc/require-jsdoc +function collectAll(data) { + const mTier = data.maxTier; + let totalPoints = 0; + let totalAmount = 0; + for (let i = 1; i <= mTier; i++) { + totalPoints += data.getTier(i).pointsRewarded; + totalAmount += data.getTier(i).amountRequired; + } + return { totalPoints, totalAmount }; +} + /** * Achievement Class */ @@ -8,6 +20,7 @@ class Achievement { * constructor * @param {string} achievementName Name of achievement * @param {Object} data + * @example */ constructor(achievementName, data) { /** @@ -48,39 +61,29 @@ class Achievement { * ONLY AVAILABLE FOR TIERED * @type {AchievementTier|null} */ - this.tierInformation = this.type === 'TIERED' ? new AchievementTier(data.tiers) : null; + this.tierInformation = 'TIERED' === this.type ? new AchievementTier(data.tiers) : null; - const { totalPoints, totalAmount } = this.type === 'TIERED' ? collectAll(this.tierInformation) : {}; + const { totalPoints, totalAmount } = 'TIERED' === this.type ? collectAll(this.tierInformation) : {}; /** * Total points worth (sum of all tiers if tiered) * This is always 0 for Guild Achievements * @type {number} */ - this.points = this.type === 'ONE_TIME' ? parseInt(data.points, 10) : totalPoints; + this.points = 'ONE_TIME' === this.type ? parseInt(data.points, 10) : totalPoints; /** * Total amount required to reach max tier, only for tiered * @type {number|null} */ - this.totalAmountRequired = this.type === 'TIERED' ? totalAmount : null; + this.totalAmountRequired = 'TIERED' === this.type ? totalAmount : null; } /** * As string * @return {string} + * @example */ toString() { return this.achievementName; } } -// eslint-disable-next-line require-jsdoc -function collectAll(data) { - const mTier = data.maxTier; - let totalPoints = 0; - let totalAmount = 0; - for (let i = 1; i <= mTier; i++) { - totalPoints += data.getTier(i).pointsRewarded; - totalAmount += data.getTier(i).amountRequired; - } - return { totalPoints, totalAmount }; -} module.exports = Achievement; diff --git a/src/structures/Static/AchievementTier.js b/src/structures/Static/AchievementTier.js index 81f7a6a5..dbf267fa 100644 --- a/src/structures/Static/AchievementTier.js +++ b/src/structures/Static/AchievementTier.js @@ -4,6 +4,7 @@ class AchievementTier { /** * @param {Record} data + * @example */ constructor(data) { /** @@ -13,16 +14,17 @@ class AchievementTier { */ this.maxTier = data.length; // Still make sure it is well sorted - this._tierInfo = data.sort(({ tier: tierA }, { tier: tierB }) => Number(tierA) - Number(tierB)); + this.tierInfo = data.sort(({ tier: tierA }, { tier: tierB }) => Number(tierA) - Number(tierB)); } /** * Gets information for tier * @param {number} tier Tier number (1-indexed!) * @returns {Record<'pointsRewarded'|'amountRequired', number>} + * @example */ getTier(tier) { const index = tier - 1; - const info = this._tierInfo[index]; + const info = this.tierInfo[index]; return { pointsRewarded: parseInt(info.points, 10) || 0, amountRequired: parseInt(info.amount, 10) || 0 diff --git a/src/structures/Static/Achievements.js b/src/structures/Static/Achievements.js index f568dee2..aa9b988e 100644 --- a/src/structures/Static/Achievements.js +++ b/src/structures/Static/Achievements.js @@ -6,6 +6,7 @@ const GameAchievements = require('./GameAchievements.js'); class Achievements { /** * @param {object} data data + * @example */ constructor(data) { /** diff --git a/src/structures/Static/Challenges.js b/src/structures/Static/Challenges.js index dff19b1a..81bb7a53 100644 --- a/src/structures/Static/Challenges.js +++ b/src/structures/Static/Challenges.js @@ -5,6 +5,7 @@ const GameChallenges = require('./GameChallenges.js'); class Challenges { /** * @param {object} data data + * @example */ constructor(data) { /** diff --git a/src/structures/Static/GameAchievements.js b/src/structures/Static/GameAchievements.js index 17a3f563..82ba71e3 100644 --- a/src/structures/Static/GameAchievements.js +++ b/src/structures/Static/GameAchievements.js @@ -7,6 +7,7 @@ class GameAchievements { /** * @param {string} name game name * @param {object} data data + * @example */ constructor(name, data) { /** diff --git a/src/structures/Static/GameChallenges.js b/src/structures/Static/GameChallenges.js index 3254aa9f..5cca8ba6 100644 --- a/src/structures/Static/GameChallenges.js +++ b/src/structures/Static/GameChallenges.js @@ -5,6 +5,7 @@ class GameChallenges { /** * @param {string} name game name * @param {object} data data + * @example */ constructor(name, data) { /** diff --git a/src/structures/Static/GameQuests.js b/src/structures/Static/GameQuests.js index ae0af6c2..548d5ba6 100644 --- a/src/structures/Static/GameQuests.js +++ b/src/structures/Static/GameQuests.js @@ -7,6 +7,7 @@ class GameQuests { /** * @param {string} name game name * @param {object} data data + * @example */ constructor(name, data) { /** diff --git a/src/structures/Static/GuildAchievements.js b/src/structures/Static/GuildAchievements.js index bce03b92..046b9e9e 100644 --- a/src/structures/Static/GuildAchievements.js +++ b/src/structures/Static/GuildAchievements.js @@ -6,6 +6,7 @@ const Achievement = require('./Achievement.js'); class GuildAchievements { /** * @param {object} data data + * @example */ constructor(data) { /** diff --git a/src/structures/Static/Quest.js b/src/structures/Static/Quest.js index 1f402671..f9febe0b 100644 --- a/src/structures/Static/Quest.js +++ b/src/structures/Static/Quest.js @@ -5,6 +5,7 @@ class Quest { /** * constructor * @param {Object} data + * @example */ constructor(data) { /** @@ -26,14 +27,14 @@ class Quest { * Type of quest * @type {'DAILY'|'WEEKLY'} */ - this.type = data.requirements?.[0].type === 'DailyResetQuestRequirement' ? 'DAILY' : 'WEEKLY'; + this.type = 'DailyResetQuestRequirement' === data.requirements?.[0].type ? 'DAILY' : 'WEEKLY'; /** * Objectives * @type {Objective[]} */ this.objectives = data.objectives.map((objective) => ({ id: objective.id, - type: objective.type === 'IntegerObjective' ? 'Integer' : 'Boolean', + type: 'IntegerObjective' === objective.type ? 'Integer' : 'Boolean', amountNeeded: parseInt(objective.integer || '1', 10) })); /** @@ -45,6 +46,7 @@ class Quest { /** * As string * @return {string} + * @example */ toString() { return this.questName; diff --git a/src/structures/Status.js b/src/structures/Status.js index b858f1b0..584be5e3 100644 --- a/src/structures/Status.js +++ b/src/structures/Status.js @@ -5,6 +5,7 @@ const Game = require('./Game'); class Status { /** * @param {object} data Status data + * @example */ constructor(data) { /** @@ -33,6 +34,7 @@ class Status { /** * Online Status * @return {string} + * @example */ toString() { return this.online ? 'Online' : 'Offline'; diff --git a/src/structures/Watchdog/Stats.js b/src/structures/Watchdog/Stats.js index 1008e07a..8fa8bef1 100644 --- a/src/structures/Watchdog/Stats.js +++ b/src/structures/Watchdog/Stats.js @@ -4,6 +4,7 @@ class WatchdogStats { /** * @param {object} data Watchdog data + * @example */ constructor(data) { /** diff --git a/src/utils/Constants.js b/src/utils/Constants.js index dba22fa8..c202176f 100644 --- a/src/utils/Constants.js +++ b/src/utils/Constants.js @@ -1,7 +1,5 @@ module.exports = { - skyblock_year_0: 1.5602757e12, - - duels_divisions: [ + duelsDivisions: [ { name: 'Rookie', key: 'rookie' }, { name: 'Iron', key: 'iron' }, { name: 'Gold', key: 'gold' }, @@ -14,8 +12,7 @@ module.exports = { { name: 'WORLD MASTER', key: 'world_master' }, { name: "WORLD'S BEST", key: 'worlds_best' } ], - - leveling_xp: { + levelingXp: { 1: 50, 2: 125, 3: 200, @@ -67,8 +64,7 @@ module.exports = { 49: 3700000, 50: 4000000 }, - - xp_past_50: { + xpPast50: { 51: 4300000, 52: 4600000, 53: 4900000, @@ -80,8 +76,7 @@ module.exports = { 59: 6700000, 60: 7000000 }, - - runecrafting_xp: { + runecraftingXp: { 1: 50, 2: 100, 3: 125, @@ -108,32 +103,7 @@ module.exports = { 24: 15300, 25: 19050 }, - - skills: [ - 'farming', - 'mining', - 'combat', - 'foraging', - 'fishing', - 'enchanting', - 'alchemy', - 'taming', - 'carpentry', - 'runecrafting' - ], - - skills_achievements: { - farming: 'skyblockHarvester', - mining: 'skyblockExcavator', - combat: 'skyblockCombat', - foraging: 'skyblockGatherer', - fishing: 'skyblockAngler', - enchanting: 'skyblockAugmentation', - alchemy: 'skyblockConcoctor', - taming: 'skyblockDomesticator' - }, - - skills_cap: { + skillsCap: { taming: 50, farming: 60, mining: 60, @@ -144,10 +114,10 @@ module.exports = { alchemy: 50, carpentry: 50, runecrafting: 25, - dungeons: 50 + dungeons: 50, + social: 25 }, - - dungeon_xp: { + dungeonXp: { 1: 50, 2: 75, 3: 110, @@ -200,8 +170,7 @@ module.exports = { 50: 1.1625e8, 55: 1e9 }, - - hotm_xp: { + hotmXp: { 1: 0, 2: 3000, 3: 9000, @@ -210,8 +179,7 @@ module.exports = { 6: 100000, 7: 150000 }, - - social_xp: { + socialXp: { 1: 50, 2: 100, 3: 150, @@ -238,20 +206,7 @@ module.exports = { 24: 40000, 25: 50000 }, - - slayer_xp: { - 1: 5, - 2: 15, - 3: 200, - 4: 1000, - 5: 5000, - 6: 20000, - 7: 100000, - 8: 400000, - 9: 1000000 - }, - - pet_score: { + petScore: { COMMON: 1, UNCOMMON: 2, RARE: 3, @@ -259,8 +214,7 @@ module.exports = { LEGENDARY: 5, MYTHIC: 6 }, - - pet_rarity_offset: { + petRarityOffset: { COMMON: 0, UNCOMMON: 6, RARE: 11, @@ -268,8 +222,7 @@ module.exports = { LEGENDARY: 20, MYTHIC: 20 }, - - pet_levels: [ + petLevels: [ 100, 110, 120, 130, 145, 160, 175, 190, 210, 230, 250, 275, 300, 330, 360, 400, 440, 490, 540, 600, 660, 730, 800, 880, 960, 1050, 1150, 1260, 1380, 1510, 1650, 1800, 1960, 2130, 2310, 2500, 2700, 2920, 3160, 3420, 3700, 4000, 4350, 4750, 5200, 5700, 6300, 7000, 7800, 8700, 9700, 10800, 12000, 13300, 14700, 16200, 17800, 19500, 21300, 23200, @@ -286,463 +239,6 @@ module.exports = { 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700, 1886700 ], - - base_stats: { - damage: 0, - health: 100, - defense: 0, - effective_health: 100, - strength: 0, - damage_increase: 0, - speed: 100, - crit_chance: 20, - crit_damage: 50, - intelligence: 0 - }, - - stat_template: { - damage: 0, - health: 0, - defense: 0, - effective_health: 0, - strength: 0, - damage_increase: 0, - speed: 0, - crit_chance: 0, - crit_damage: 0, - intelligence: 0 - }, - - bonus_stats: { - taming_skill: { - 1: { - pet_luck: 1 - } - }, - fairy_souls: { - 5: { - health: 3, - defense: 1, - strength: 1, - speed: 0 - }, - 10: { - health: 3, - defense: 1, - strength: 1, - speed: 0 - }, - 15: { - health: 4, - defense: 1, - strength: 1, - speed: 0 - }, - 20: { - health: 4, - defense: 1, - strength: 1, - speed: 0 - }, - 25: { - health: 5, - defense: 2, - strength: 2, - speed: 0 - }, - 30: { - health: 5, - defense: 1, - strength: 1, - speed: 0 - }, - 35: { - health: 6, - defense: 1, - strength: 1, - speed: 0 - }, - 40: { - health: 6, - defense: 1, - strength: 1, - speed: 0 - }, - 45: { - health: 7, - defense: 1, - strength: 1, - speed: 0 - }, - 50: { - health: 7, - defense: 2, - strength: 2, - speed: 1 - }, - 55: { - health: 8, - defense: 1, - strength: 1, - speed: 0 - }, - 60: { - health: 8, - defense: 1, - strength: 1, - speed: 0 - }, - 65: { - health: 9, - defense: 1, - strength: 1, - speed: 0 - }, - 70: { - health: 9, - defense: 1, - strength: 1, - speed: 0 - }, - 75: { - health: 10, - defense: 2, - strength: 2, - speed: 0 - }, - 80: { - health: 10, - defense: 1, - strength: 1, - speed: 0 - }, - 85: { - health: 11, - defense: 1, - strength: 1, - speed: 0 - }, - 90: { - health: 11, - defense: 1, - strength: 1, - speed: 0 - }, - 95: { - health: 12, - defense: 1, - strength: 1, - speed: 0 - }, - 100: { - health: 12, - defense: 2, - strength: 2, - speed: 1 - }, - 105: { - health: 13, - defense: 1, - strength: 1, - speed: 0 - }, - 110: { - health: 13, - defense: 1, - strength: 1, - speed: 0 - }, - 115: { - health: 14, - defense: 1, - strength: 1, - speed: 0 - }, - 120: { - health: 14, - defense: 1, - strength: 1, - speed: 0 - }, - 125: { - health: 15, - defense: 2, - strength: 2, - speed: 0 - }, - 130: { - health: 15, - defense: 1, - strength: 1, - speed: 0 - }, - 135: { - health: 16, - defense: 1, - strength: 1, - speed: 0 - }, - 140: { - health: 16, - defense: 1, - strength: 1, - speed: 0 - }, - 145: { - health: 17, - defense: 1, - strength: 1, - speed: 0 - }, - 150: { - health: 17, - defense: 2, - strength: 2, - speed: 1 - }, - 155: { - health: 18, - defense: 1, - strength: 1, - speed: 0 - }, - 160: { - health: 18, - defense: 1, - strength: 1, - speed: 0 - }, - 165: { - health: 19, - defense: 1, - strength: 1, - speed: 0 - }, - 170: { - health: 19, - defense: 1, - strength: 1, - speed: 0 - }, - 175: { - health: 20, - defense: 2, - strength: 2, - speed: 0 - }, - 180: { - health: 20, - defense: 1, - strength: 1, - speed: 0 - }, - 185: { - health: 21, - defense: 1, - strength: 1, - speed: 0 - }, - 190: { - health: 21, - defense: 1, - strength: 1, - speed: 0 - } - }, - - farming_skill: { - 1: { - health: 2 - }, - 15: { - health: 3 - }, - 20: { - health: 4 - }, - 26: { - health: 5 - } - }, - - combat_skill: { - 1: { - crit_chance: 0.5, - damage_increase: 0.04 - } - }, - - mining_skill: { - 1: { - defense: 1 - }, - 15: { - defense: 2 - } - }, - - foraging_skill: { - 1: { - strength: 1 - }, - 15: { - strength: 2 - } - }, - - fishing_skill: { - 1: { - health: 2 - }, - 15: { - health: 3 - }, - 20: { - health: 4 - }, - 26: { - health: 5 - } - }, - - enchanting_skill: { - 1: { - intelligence: 1 - }, - 15: { - intelligence: 2 - } - }, - - alchemy_skill: { - 1: { - intelligence: 1 - }, - 15: { - intelligence: 2 - } - }, - - carpentry_skill: { - 1: {} - }, - - runecrafting_skill: { - 1: {} - }, - - zombie_slayer: { - 1: { - health: 2 - }, - 3: { - health: 3 - }, - 5: { - health: 4 - }, - 7: { - health: 5 - }, - 9: { - health: 6 - } - }, - - spider_slayer: { - 1: { - crit_damage: 1 - }, - 5: { - crit_damage: 2 - }, - 7: { - crit_damage: 0, - crit_chance: 1 - }, - 8: { - crit_chance: 0, - crit_damage: 3 - } - }, - - wolf_slayer: { - 1: { - speed: 1 - }, - 2: { - health: 2 - }, - 3: { - speed: 1 - }, - 4: { - health: 2 - }, - 5: { - crit_damage: 1 - }, - 6: { - health: 3 - }, - 7: { - crit_damage: 2 - }, - 8: { - speed: 1 - } - }, - - enchantments: { - sharpness: { - 1: { - damage_multiplicator: 0.05 - } - }, - - ender: { - 1: { - damage_multiplicator: 0.12 - } - }, - - giant_killer: { - 1: { - damage_multiplicator: 0.05 - } - }, - - cubism: { - 1: { - damage_multiplicator: 0.1 - } - }, - - impaling: { - 1: { - damage_multiplicator: 0.125 - } - }, - - critical: { - 1: { - crit_damage: 10 - } - }, - - first_strike: { - 1: { - damage_multiplicator: 0.25 - } - }, - - power: { - 1: { - damage_multiplicator: 0.08 - } - } - } - }, leaderboardNames: { ARENA: 'ARENA', COPS_AND_CRIMS: 'MCGO', @@ -805,6 +301,7 @@ module.exports = { WOOL_GAMES: 'Wool Wars' }, SkyWarsPrestigeIcons: { + /* eslint-disable camelcase */ default: '⋆', angel_1: '★', angel_2: '☆', @@ -830,6 +327,7 @@ module.exports = { rainbow_prestige: '✺', mythic_prestige: 'ಠ_ಠ', favor_of_the_angel_prestige: '⚔' + /* eslint-enable camelcase */ }, games: [ { name: 'Quake Craft', code: 'QUAKECRAFT', id: 2 }, @@ -869,6 +367,7 @@ module.exports = { { name: 'Idle', code: 'IDLE', id: -6 } ], + /* eslint-disable camelcase */ bestiary: { dynamic: { name: 'Private Island', @@ -3035,6 +2534,7 @@ module.exports = { ] } }, + /* eslint-enable camelcase */ bestiaryBrackets: { 1: [ 20, 40, 60, 100, 200, 400, 800, 1400, 2000, 3000, 6000, 12000, 20000, 30000, 40000, 50000, 60000, 72000, 86000, diff --git a/src/utils/guildExp.js b/src/utils/Guild.js similarity index 52% rename from src/utils/guildExp.js rename to src/utils/Guild.js index 5fba2095..5f4a27fc 100644 --- a/src/utils/guildExp.js +++ b/src/utils/Guild.js @@ -1,5 +1,13 @@ +/* eslint-disable jsdoc/require-jsdoc */ +const GuildMember = require('../structures/Guild/GuildMember'); +const GuildRank = require('../structures/Guild/GuildRank'); const dateRegExp = /(\d{4})-(\d{2})-(\d{2})/; -// eslint-disable-next-line require-jsdoc + +function parseDate(date) { + date[1] -= 1; + return new Date(Math.round(new Date(new Date().setUTCFullYear(...date)).setUTCHours(5, 0, 0) / 1000) * 1000); +} + function parseHistory(historyData) { return Object.entries(historyData).map((x, index) => ({ day: x[0], @@ -17,13 +25,6 @@ function parseHistory(historyData) { })); } -// eslint-disable-next-line require-jsdoc -function parseDate(date) { - date[1] -= 1; - return new Date(Math.round(new Date(new Date().setUTCFullYear(...date)).setUTCHours(5, 0, 0) / 1000) * 1000); -} - -// eslint-disable-next-line require-jsdoc function getGuildLevel(exp) { const EXP_NEEDED = [ 100000, 150000, 250000, 500000, 750000, 1000000, 1250000, 1500000, 2000000, 2500000, 2500000, 2500000, 2500000, @@ -32,15 +33,15 @@ function getGuildLevel(exp) { let level = 0; - for (let i = 0; i <= 1000; i += 1) { - let need = 0; + for (let i = 0; 1000 >= i; i += 1) { + let need; if (i >= EXP_NEEDED.length) { need = EXP_NEEDED[EXP_NEEDED.length - 1]; } else { need = EXP_NEEDED[i]; } - if (exp - need < 0) { + if (0 > exp - need) { return Math.round((level + exp / need) * 100) / 100; } level += 1; @@ -50,6 +51,38 @@ function getGuildLevel(exp) { return 1000; } +function members(data) { + return data.members.length ? data.members.map((m) => new GuildMember(m)) : []; +} + +function ranks(data) { + return data.ranks && data.ranks.length + ? data.ranks.map((r) => new GuildRank(r)).sort((a, b) => a.priority - b.priority) + : []; +} + +function totalWeeklyGexp(data) { + return members(data) + .map((m) => m.weeklyExperience) + .reduce((acc, cur) => acc + cur); +} + +function expLimit(exp) { + return 2e5 < exp ? (7e5 < exp ? 2.5e5 + Math.round(exp * 0.03) : 2e5 + Math.round((exp - 2e5) / 10)) : exp; +} + +function calculateExpHistory(data) { + const finalObj = {}; + for (const day of Object.keys(data.members[0].expHistory)) { + let gexp = 0; + for (const member of data.members) { + gexp += member.expHistory[day] || 0; + } + finalObj[day] = expLimit(gexp); + } + return parseHistory(finalObj); +} + /** * @typedef {object} ExpHistory * @property {string} day String Date ( unparsed ) @@ -57,4 +90,4 @@ function getGuildLevel(exp) { * @property {number} exp Experience of the day * @property {number} totalExp Experience earned from day 0 to this day */ -module.exports = { parseHistory, getGuildLevel }; +module.exports = { parseHistory, getGuildLevel, calculateExpHistory, totalWeeklyGexp, ranks, members }; diff --git a/src/utils/Player.js b/src/utils/Player.js new file mode 100644 index 00000000..d7eaae11 --- /dev/null +++ b/src/utils/Player.js @@ -0,0 +1,112 @@ +/* eslint-disable jsdoc/require-jsdoc */ +function getRank(player) { + let rank; + if (player.prefix) { + rank = player.prefix.replace(/§[0-9|a-z]|\[|\]/g, ''); + } else if (player.rank && 'NORMAL' !== player.rank) { + switch (player.rank) { + case 'YOUTUBER': + rank = 'YouTube'; + break; + case 'GAME_MASTER': + rank = 'Game Master'; + break; + case 'ADMIN': + rank = 'Admin'; + break; + default: + rank = ''; + break; + } + } else { + switch (player.newPackageRank) { + case 'MVP_PLUS': + rank = player.monthlyPackageRank && 'SUPERSTAR' === player.monthlyPackageRank ? 'MVP++' : 'MVP+'; + break; + case 'MVP': + rank = 'MVP'; + break; + case 'VIP_PLUS': + rank = 'VIP+'; + break; + case 'VIP': + rank = 'VIP'; + break; + default: + rank = player.monthlyPackageRank && 'SUPERSTAR' === player.monthlyPackageRank ? 'MVP++' : 'Default'; + } + } + return rank; +} + +function getPlayerLevel(exp) { + const base = 10000; + const growth = 2500; + const reversePqPrefix = -(base - 0.5 * growth) / growth; + const reverseConst = reversePqPrefix * reversePqPrefix; + const growthDivides2 = 2 / growth; + const num = 1 + reversePqPrefix + Math.sqrt(reverseConst + growthDivides2 * exp); + const level = Math.round(num * 100) / 100; + return level; +} + +function xpToNextLevel(player) { + const lvl = getPlayerLevel(player.networkExp); + const xpToNext = 2500 * Math.floor(lvl) + 5000; + if (10000 > player.networkExp) return 10000; + return xpToNext; +} + +function levelToXP(player) { + let level = Number(Math.floor(getPlayerLevel(player.networkExp))); + level = level - 1; + const xp = 1250 * level ** 2 + 8750 * level; + return xp; +} + +function playerLevelProgress(player) { + const xpFromLevel = levelToXP(player); + let currentXP = player.networkExp - xpFromLevel; + const xpToNext = xpToNextLevel(player); + const remainingXP = xpToNext - currentXP + 2500; + currentXP = currentXP - 2500; + const percent = Math.round((currentXP / xpToNext) * 100 * 100) / 100; + const percentRemaining = Math.round((100 - percent) * 100) / 100; + return { + xpToNext, + remainingXP, + currentXP, + percent, + percentRemaining + }; +} + +function getSocialMedia(data) { + if (!data) return null; + const links = data.links; + const formattedNames = ['Twitter', 'YouTube', 'Instagram', 'Twitch', 'Hypixel', 'Discord']; + const upperNames = ['TWITTER', 'YOUTUBE', 'INSTAGRAM', 'TWITCH', 'HYPIXEL', 'DISCORD']; + if (!links) return null; + return Object.keys(links) + .map((x) => upperNames.indexOf(x)) + .filter((x) => -1 !== x) + .map((x) => ({ name: formattedNames[x], link: links[upperNames[x]], id: upperNames[x] })); +} + +function parseClaimedRewards(data) { + if (!data) return null; + return Object.keys(data) + .map((x) => x.match(/levelingReward_(\d+)/)) + .filter((x) => x) + .map((x) => parseInt(x[1], 10)); +} + +module.exports = { + getRank, + getPlayerLevel, + xpToNextLevel, + levelToXP, + playerLevelProgress, + getSocialMedia, + parseClaimedRewards +}; diff --git a/src/utils/SkyblockUtils.js b/src/utils/SkyblockUtils.js index 087a55ff..727143b6 100644 --- a/src/utils/SkyblockUtils.js +++ b/src/utils/SkyblockUtils.js @@ -1,213 +1,470 @@ -/* eslint-disable camelcase */ +/* eslint-disable jsdoc/require-jsdoc */ const constants = require('./Constants'); -module.exports = { - async decode(base64, isBuffer = false) { - const nbt = require('prismarine-nbt'); - const parseNbt = require('util').promisify(nbt.parse); - const buffer = isBuffer ? base64 : Buffer.from(base64, 'base64'); - let data = await parseNbt(buffer); - data = nbt.simplify(data); - const newdata = []; - for (let i = 0; i < data.i.length; i++) { - newdata.push(data.i[i]); - } - return newdata; - }, - getLevelByXp(xp, type, levelCap) { - let xpTable; - switch (type) { - case 'runecrafting': - xpTable = constants.runecrafting_xp; - break; - case 'dungeons': - xpTable = constants.dungeon_xp; - break; - case 'hotm': - xpTable = constants.hotm_xp; - break; - case 'social': - xpTable = constants.social_xp; - break; - default: - xpTable = constants.leveling_xp; - } - let maxLevel = Math.max(...Object.keys(xpTable)); - if ((constants.skills_cap[type] ?? maxLevel) > maxLevel) { - xpTable = Object.assign(constants.xp_past_50, xpTable); - maxLevel = typeof levelCap === 'number' ? maxLevel + levelCap : Math.max(...Object.keys(xpTable)); - } - if (isNaN(xp)) { - return { - xp: 0, - level: 0, - maxLevel, - xpCurrent: 0, - xpForNext: xpTable[1], - progress: 0, - cosmetic: type === 'runecrafting' || type === 'social' ? true : false - }; - } - let xpTotal = 0; - let level = 0; - let xpForNext = 0; - for (let x = 1; x <= maxLevel; x++) { - if (!xpTable[x]) continue; - xpTotal += xpTable[x]; - if (xpTotal > xp) { - xpTotal -= xpTable[x]; - break; - } else { - level = x; - } - } - const xpCurrent = Math.floor(xp - xpTotal); - if (level < maxLevel) xpForNext = Math.ceil(xpTable[level + 1]); - const progress = Math.floor(Math.max(0, Math.min(xpCurrent / xpForNext, 1)) * 100 * 10) / 10; +async function decode(base64, isBuffer = false) { + const nbt = require('prismarine-nbt'); + const parseNbt = require('util').promisify(nbt.parse); + const buffer = isBuffer ? base64 : Buffer.from(base64, 'base64'); + let data = await parseNbt(buffer); + data = nbt.simplify(data); + const newdata = []; + for (let i = 0; i < data.i.length; i++) { + newdata.push(data.i[i]); + } + return newdata; +} + +function getLevelByXp(xp, type, levelCap) { + let xpTable; + switch (type) { + case 'runecrafting': + xpTable = constants.runecraftingXp; + break; + case 'dungeons': + xpTable = constants.dungeonXp; + break; + case 'hotm': + xpTable = constants.hotmXp; + break; + case 'social': + xpTable = constants.socialXp; + break; + default: + xpTable = constants.levelingXp; + } + let maxLevel = Math.max(...Object.keys(xpTable)); + if ((constants.skillsCap[type] ?? maxLevel) > maxLevel) { + xpTable = Object.assign(constants.xpPast50, xpTable); + maxLevel = 'number' === typeof levelCap ? maxLevel + levelCap : Math.max(...Object.keys(xpTable)); + } + if (isNaN(xp)) { return { - xp: xp, - level: level, - maxLevel: maxLevel, - xpCurrent: xpCurrent, - xpForNext: xpForNext, - progress: progress, - cosmetic: type === 'runecrafting' || type === 'social' ? true : false - }; - }, - getLevelByAchievement(achievementLevel, type) { - let xpTable = constants.leveling_xp; - let maxLevel = Math.max(...Object.keys(xpTable)); - if (constants.skills_cap[type] > maxLevel && type in constants.skills_achievements) { - xpTable = Object.assign(constants.xp_past_50, xpTable); - maxLevel = Math.max(...Object.keys(xpTable)); - } - if (isNaN(achievementLevel)) { - return { - xp: 0, - level: 0, - maxLevel, - xpCurrent: 0, - xpForNext: xpTable[1], - progress: 0 - }; - } - let xpTotal = 0; - let xpForNext = 0; - for (let x = 1; x <= achievementLevel; x++) { - xpTotal += xpTable[x]; - } - if (achievementLevel < maxLevel) xpForNext = Math.ceil(xpTable[achievementLevel + 1]); - return { - xp: xpTotal, - level: achievementLevel, + xp: 0, + level: 0, maxLevel, xpCurrent: 0, - xpForNext, - progress: 0 + xpForNext: xpTable[1], + progress: 0, + cosmetic: Boolean('runecrafting' === type || 'social' === type) }; - }, - getSlayerLevel(slayer) { - if (!slayer) { - return { - xp: 0, - tier1: 0, - tier2: 0, - tier3: 0, - tier4: 0, - tier5: 0, - level: 0 - }; - } - const { claimed_levels } = slayer; - let level = 0; - for (const level_name in claimed_levels) { - if (Object.prototype.hasOwnProperty.call(claimed_levels, level_name)) { - const _level = parseInt(level_name.replace('_special', '').split('_').pop(), 10); - if (_level > level) { - level = _level; - } - } + } + let xpTotal = 0; + let level = 0; + let xpForNext = 0; + for (let x = 1; x <= maxLevel; x++) { + if (!xpTable[x]) continue; + xpTotal += xpTable[x]; + if (xpTotal > xp) { + xpTotal -= xpTable[x]; + break; + } else { + level = x; } + } + const xpCurrent = Math.floor(xp - xpTotal); + if (level < maxLevel) xpForNext = Math.ceil(xpTable[level + 1]); + const progress = Math.floor(Math.max(0, Math.min(xpCurrent / xpForNext, 1)) * 100 * 10) / 10; + + return { + xp: xp, + level: level, + maxLevel: maxLevel, + xpCurrent: xpCurrent, + xpForNext: xpForNext, + progress: progress, + cosmetic: Boolean('runecrafting' === type || 'social' === type) + }; +} + +function getSlayerLevel(slayer) { + if (!slayer) { return { - xp: slayer.xp || 0, - tier1: slayer.boss_kills_tier_0 || 0, - tier2: slayer.boss_kills_tier_1 || 0, - tier3: slayer.boss_kills_tier_2 || 0, - tier4: slayer.boss_kills_tier_3 || 0, - tier5: slayer.boss_kills_tier_4 || 0, - level + xp: 0, + tier1: 0, + tier2: 0, + tier3: 0, + tier4: 0, + tier5: 0, + level: 0 }; - }, - getSlayerLevelByXp(xp) { - const { slayer_xp } = constants; - const maxLevel = Math.max(...Object.keys(slayer_xp)); - let level = 0; - for (let x = 1; x <= maxLevel && slayer_xp[x] <= xp; x++) { - level = x; + } + + // eslint-disable-next-line camelcase + const { claimed_levels } = slayer; + let level = 0; + + // eslint-disable-next-line camelcase + for (const levelName in claimed_levels) { + if (Object.prototype.hasOwnProperty.call(claimed_levels, levelName)) { + const newLevel = parseInt(levelName.replace('_special', '').split('_').pop(), 10); + if (newLevel > level) { + level = newLevel; + } } - return level; - }, - getBonusStat(level, skill, max, incremention) { - const skill_stats = constants.bonus_stats[skill]; - const steps = Object.keys(skill_stats) - .sort((a, b) => Number(a) - Number(b)) - .map((a) => Number(a)); - const bonus = Object.assign({}, constants.stat_template); - for (let x = steps[0]; x <= max; x += incremention) { - if (level < x) { - break; + } + return { + xp: slayer.xp || 0, + tier1: slayer.boss_kills_tier_0 || 0, + tier2: slayer.boss_kills_tier_1 || 0, + tier3: slayer.boss_kills_tier_2 || 0, + tier4: slayer.boss_kills_tier_3 || 0, + tier5: slayer.boss_kills_tier_4 || 0, + level + }; +} + +function getMemberStats(obj) { + return Object.keys(obj).reduce( + (result, currentKey) => { + const key = currentKey.replace(/_[a-z]/gi, (match) => match[1].toUpperCase()); + + if (currentKey.startsWith('kills') || currentKey.startsWith('deaths')) { + const category = currentKey.startsWith('kills') ? 'kills' : 'deaths'; + const subKey = key === category ? 'total' : key; + + result[category][ + subKey.replace(category, (sub, _, key) => { + return key[sub.length].toLowerCase() + key.slice(sub.length + 1); + }) + ] = obj[currentKey]; + } else { + result[key] = obj[currentKey]; } - const skill_step = steps - .slice() - .reverse() - .find((a) => a <= x); - const skill_bonus = skill_stats[skill_step]; - for (const skill in skill_bonus) { - if (Object.prototype.hasOwnProperty.call(skill_bonus, skill)) { - bonus[skill] += skill_bonus[skill]; + + return result; + }, + { kills: {}, deaths: {} } + ); +} + +function getTrophyFishRank(level) { + if (1 === level) { + return 'Bronze'; + } else if (2 === level) { + return 'Silver'; + } else if (3 === level) { + return 'Gold'; + } else if (4 === level) { + return 'Diamond'; + } + return 'Bronze'; +} + +function getSkills(data) { + const skillsObject = {}; + skillsObject.combat = getLevelByXp(data?.player_data?.experience?.SKILL_COMBAT ?? 0, 'combat'); + skillsObject.farming = getLevelByXp( + data?.player_data?.experience?.SKILL_FARMING ?? 0, + 'farming', + data?.m?.jacobs_contest?.perks?.farming_level_cap ?? 0 + 50 + ); + skillsObject.fishing = getLevelByXp(data?.player_data?.experience?.SKILL_FISHING ?? 0, 'fishing'); + skillsObject.mining = getLevelByXp(data?.player_data?.experience?.SKILL_MINING ?? 0, 'mining'); + skillsObject.foraging = getLevelByXp(data?.player_data?.experience?.SKILL_FORAGING ?? 0, 'foraging'); + skillsObject.enchanting = getLevelByXp(data?.player_data?.experience?.SKILL_ENCHANTING ?? 0, 'enchanting'); + skillsObject.alchemy = getLevelByXp(data?.player_data?.experience?.SKILL_ALCHEMY ?? 0, 'alchemy'); + skillsObject.carpentry = getLevelByXp(data?.player_data?.experience?.SKILL_CARPENTRY ?? 0, 'carpentry'); + skillsObject.runecrafting = getLevelByXp(data?.player_data?.experience?.SKILL_RUNECRAFTING ?? 0, 'runecrafting'); + skillsObject.taming = getLevelByXp(data?.player_data?.experience?.SKILL_TAMING ?? 0, 'taming'); + skillsObject.social = getLevelByXp(data?.player_data?.experience?.SKILL_SOCIAL ?? 0, 'social'); + const levels = Object.values(skillsObject) + .filter((skill) => true !== skill.cosmetic) + .map((skill) => skill.level); + skillsObject.average = levels.reduce((a, b) => a + b, 0) / levels.length; + return skillsObject; +} + +function formatBestiaryMobs(userProfile, mobs) { + const output = []; + for (const mob of mobs) { + const mobBracket = constants.bestiaryBrackets[mob.bracket]; + + const totalKills = mob.mobs.reduce((acc, cur) => { + return acc + (userProfile.bestiary.kills[cur] ?? 0); + }, 0); + + const maxKills = mob.cap; + const nextTierKills = mobBracket.find((tier) => totalKills < tier && tier <= maxKills); + const tier = nextTierKills ? mobBracket.indexOf(nextTierKills) : mobBracket.indexOf(maxKills) + 1; + + output.push({ + tier: tier + }); + } + + return output; +} + +function getBestiaryLevel(userProfile) { + try { + if (userProfile.bestiary?.kills === undefined) { + return null; + } + + const output = {}; + let tiersUnlocked = 0; + for (const [category, data] of Object.entries(constants.bestiary)) { + const { mobs } = data; + output[category] = {}; + + if ('fishing' === category) { + for (const [key, value] of Object.entries(data)) { + output[category][key] = { + mobs: formatBestiaryMobs(userProfile, value.mobs) + }; + tiersUnlocked += output[category][key].mobs.reduce((acc, cur) => acc + cur.tier, 0); } + } else { + output[category].mobs = formatBestiaryMobs(userProfile, mobs); + tiersUnlocked += output[category].mobs.reduce((acc, cur) => acc + cur.tier, 0); } } - return bonus; - }, - getEffectiveHealth(health, defense) { - if (defense <= 0) return health; - return Math.round(health * (1 + defense / 100)); - }, - getMemberStats(obj) { - return Object.keys(obj).reduce( - (result, currentKey) => { - const key = currentKey.replace(/_[a-z]/gi, (match) => match[1].toUpperCase()); - - if (currentKey.startsWith('kills') || currentKey.startsWith('deaths')) { - const category = currentKey.startsWith('kills') ? 'kills' : 'deaths'; - const subKey = key === category ? 'total' : key; - - result[category][ - subKey.replace(category, (sub, _, key) => { - return key[sub.length].toLowerCase() + key.slice(sub.length + 1); - }) - ] = obj[currentKey]; - } else { - result[key] = obj[currentKey]; + + return tiersUnlocked / 10; + } catch (error) { + // eslint-disable-next-line no-console + console.log(error); + return null; + } +} + +function getSlayer(data) { + if (!data?.slayer?.slayer_bosses) return; + return { + zombie: getSlayerLevel(data?.slayer?.slayer_bosses?.zombie), + spider: getSlayerLevel(data?.slayer?.slayer_bosses?.spider), + wolf: getSlayerLevel(data?.slayer?.slayer_bosses?.wolf), + enderman: getSlayerLevel(data?.slayer?.slayer_bosses?.enderman), + blaze: getSlayerLevel(data?.slayer?.slayer_bosses?.blaze), + vampire: getSlayerLevel(data?.slayer?.slayer_bosses?.vampire) + }; +} + +function getDungeons(data) { + return { + types: { + catacombs: getLevelByXp( + data.dungeons?.dungeon_types?.catacombs ? data.dungeons.dungeon_types.catacombs.experience : null, + 'dungeons' + ) + }, + classes: { + healer: getLevelByXp( + data.dungeons?.player_classes?.healer ? data.dungeons.player_classes.healer.experience : null, + 'dungeons' + ), + mage: getLevelByXp( + data.dungeons?.player_classes?.mage ? data.dungeons.player_classes.mage.experience : null, + 'dungeons' + ), + berserk: getLevelByXp( + data.dungeons?.player_classes?.berserk ? data.dungeons.player_classes.berserk.experience : null, + 'dungeons' + ), + archer: getLevelByXp( + data.dungeons?.player_classes?.archer ? data.dungeons.player_classes.archer.experience : null, + 'dungeons' + ), + tank: getLevelByXp( + data.dungeons?.player_classes?.tank ? data.dungeons.player_classes.tank.experience : null, + 'dungeons' + ) + } + }; +} + +function getJacobData(data) { + if (!data.jacobs_contest) { + return { + medals: { + bronze: 0, + silver: 0, + gold: 0 + }, + perks: { + doubleDrops: 0, + farmingLevelCap: 0, + personalBests: false + }, + contests: {} + }; + } + return { + medals: data.jacobs_contest.medals_inv + ? { + bronze: data.jacobs_contest.medals_inv.bronze || 0, + silver: data.jacobs_contest.medals_inv.silver || 0, + gold: data.jacobs_contest.medals_inv.gold || 0 + } + : { bronze: 0, silver: 0, gold: 0 }, + perks: data.jacobs_contest.perks + ? { + doubleDrops: data.jacobs_contest.perks.double_drops || 0, + farmingLevelCap: data.jacobs_contest.perks.farming_level_cap || 0, + personalBests: data.jacobs_contest.perks.personal_bests || false } + : { doubleDrops: 0, farmingLevelCap: 0, personalBests: false }, + contests: data.jacobs_contest.contests || {} + }; +} - return result; +function getChocolateFactory(data) { + if (!data?.events?.easter) { + return { + employees: { + bro: 0, + cousin: 0, + sis: 0, + father: 0, + grandma: 0, + dog: 0, + uncle: 0 + }, + chocolate: { + current: 0, + total: 0, + sincePrestige: 0 + }, + timeTower: { + charges: 0, + level: 0 + }, + upgrades: { + click: 0, + multiplier: 0, + rabbitRarity: 0 + }, + goldenClick: { + amount: 0, + year: 0 }, - { kills: {}, deaths: {} } - ); - }, - getTrophyFishRank(level) { - if (level === 1) { - return 'Bronze'; - } else if (level === 2) { - return 'Silver'; - } else if (level === 3) { - return 'Gold'; - } else if (level === 4) { - return 'Diamond'; + barnCapacity: 0, + prestige: 0 + }; + } + return { + employees: { + bro: data?.events?.easter?.employees?.rabbit_bro || 0, + cousin: data?.events?.easter?.employees?.rabbit_cousin || 0, + sis: data?.events?.easter?.employees?.rabbit_sis || 0, + father: data?.events?.easter?.employees?.rabbit_father || 0, + grandma: data?.events?.easter?.employees?.rabbit_grandma || 0, + dog: data?.events?.easter?.employees?.rabbit_dog || 0, + uncle: data?.events?.easter?.employees?.rabbit_uncle || 0 + }, + chocolate: { + current: data?.events?.easter?.chocolate || 0, + total: data?.events?.easter?.total_chocolate || 0, + sincePrestige: data?.events?.easter?.chocolate_since_prestige || 0 + }, + timeTower: { + charges: data?.events?.easter?.time_tower?.charges || 0, + level: data?.events?.easter?.time_tower?.level || 0 + }, + upgrades: { + click: data?.events?.easter?.click_upgrades || 0, + multiplier: data?.events?.easter?.chocolate_multiplier_upgrades || 0, + rabbitRarity: data?.events?.easter?.rabbit_rarity_upgrades || 0 + }, + goldenClick: { + amount: data?.events?.easter?.golden_click_amount || 0, + year: data?.events?.easter?.golden_click_year || 0 + }, + barnCapacity: data?.events?.easter?.rabbit_barn_capacity_level || 0, + prestige: data?.events?.easter?.chocolate_level || 0 + }; +} + +function getPetLevel(petExp, offsetRarity, maxLevel) { + const rarityOffset = constants.petRarityOffset[offsetRarity]; + const levels = constants.petLevels.slice(rarityOffset, rarityOffset + maxLevel - 1); + + const xpMaxLevel = levels.reduce((a, b) => a + b, 0); + let xpTotal = 0; + let level = 1; + + let xpForNext; + + for (let i = 0; i < maxLevel; i++) { + xpTotal += levels[i]; + + if (xpTotal > petExp) { + xpTotal -= levels[i]; + break; } else { - return 'Bronze'; + level++; } } + + let xpCurrent = Math.floor(petExp - xpTotal); + let progress; + + if (level < maxLevel) { + xpForNext = Math.ceil(levels[level - 1]); + progress = Math.max(0, Math.min(xpCurrent / xpForNext, 1)); + } else { + level = maxLevel; + xpCurrent = petExp - levels[maxLevel - 1]; + xpForNext = 0; + progress = 1; + } + + return { + level, + xpCurrent, + xpForNext, + progress, + xpMaxLevel + }; +} + +function parseRarity(stringContainingRarity) { + const rarityArray = [ + 'COMMON', + 'UNCOMMON', + 'RARE', + 'EPIC', + 'LEGENDARY', + 'MYTHIC', + 'DIVINE', + 'SPECIAL', + 'VERY SPECIAL' + ]; + for (const rarity of rarityArray) { + if (stringContainingRarity.includes(rarity)) return rarity; + } +} + +function parseGearScore(lore) { + for (const line of lore) { + if (line.match(/Gear Score: §[0-9a-f](\d+)/)) return Number(line.match(/Gear Score: §d(\d+)/)[1]); + } +} + +function populateGoals(achieved, all) { + const populatedAchieved = []; + const unachieved = []; + for (const goal of all) { + if (achieved.find((str) => str === goal.name)) populatedAchieved.push(goal); + else unachieved.push(goal); + } + populatedAchieved.unachievedGoals = unachieved; + return populatedAchieved; +} + +module.exports = { + decode, + getLevelByXp, + getMemberStats, + getTrophyFishRank, + getSkills, + getBestiaryLevel, + getSlayer, + getDungeons, + getJacobData, + getChocolateFactory, + getPetLevel, + parseRarity, + parseGearScore, + populateGoals }; diff --git a/src/utils/arrayTools.js b/src/utils/arrayTools.js index d06b1157..cdd18497 100644 --- a/src/utils/arrayTools.js +++ b/src/utils/arrayTools.js @@ -1,4 +1,4 @@ module.exports = { - isStrArray: (input) => Array.isArray(input) || typeof input === 'string', + isStrArray: (input) => Array.isArray(input) || 'string' === typeof input, strToArray: (input) => [input].flat() }; diff --git a/src/utils/divide.js b/src/utils/divide.js index 759c68bc..416f28ef 100644 --- a/src/utils/divide.js +++ b/src/utils/divide.js @@ -1,5 +1,5 @@ module.exports = (a = 0, b = 1) => { - const out = +((a || 0) / (b || 0)).toFixed(2) || 0; + const out = Number(((a || 0) / (b || 0)).toFixed(2)) || 0; if (isFinite(out)) return out; return a; }; diff --git a/src/utils/isGuildID.js b/src/utils/isGuildID.js index a01ddf5e..e3ec9568 100644 --- a/src/utils/isGuildID.js +++ b/src/utils/isGuildID.js @@ -1,3 +1,3 @@ module.exports = (id) => { - return id.length === 24; + return 24 === id.length; }; diff --git a/src/utils/oscillation.js b/src/utils/oscillation.js index ec086cdf..84190263 100644 --- a/src/utils/oscillation.js +++ b/src/utils/oscillation.js @@ -1,13 +1,15 @@ // See https://github.com/HypixelDev/PublicAPI/blob/db26b5fd3b7bb29da14e40e6d211143ec44a4519/Documentation/misc/Oscillation.md // Month oscillation started in December 2014, so every month that is pair ( odd in js!! ) is month A // Weekly oscillation started... just refer to the code in the docs -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function monthAB(date = Date.now()) { return new Date(date).getMonth() % 2 ? 'a' : 'b'; } const weeklyOscillationStart = 1417237200000; -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function weekAB(date = Date.now()) { return (Math.abs(new Date(date).getTime() - weeklyOscillationStart) / 604800000) % 2 ? 'a' : 'b'; } diff --git a/src/utils/removeSnakeCase.js b/src/utils/removeSnakeCase.js index 5aebd8fe..6806b742 100644 --- a/src/utils/removeSnakeCase.js +++ b/src/utils/removeSnakeCase.js @@ -1,11 +1,13 @@ -// eslint-disable-next-line require-jsdoc -const single = (obj) => +const single = (obj) => { Object.keys(obj).reduce((pV, cV) => ({ ...pV, [cV.replace(/_[a-z]/gi, (x) => x[1].toUpperCase())]: obj[cV] }), {}); -// eslint-disable-next-line require-jsdoc +}; + +// eslint-disable-next-line jsdoc/require-jsdoc function validateJSON(obj) { - return typeof obj === 'object' && JSON.stringify(obj)[0] === '{'; + return 'object' === typeof obj && '{' === JSON.stringify(obj)[0]; } -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function recursive(obj, lowerCase = false) { if (!validateJSON(obj)) return obj; return Object.keys(obj).reduce( @@ -16,11 +18,13 @@ function recursive(obj, lowerCase = false) { {} ); } -// eslint-disable-next-line require-jsdoc + +// eslint-disable-next-line jsdoc/require-jsdoc function removeSnakeCaseString(str) { - if (typeof str !== 'string') return null; + if ('string' !== typeof str) return null; return str.toLowerCase().replace(/_[a-z]/gi, (x) => x[1].toUpperCase()); } + module.exports = { single, recursive, diff --git a/src/utils/rgbToHexColor.js b/src/utils/rgbToHexColor.js index 6dd84a40..6709170a 100644 --- a/src/utils/rgbToHexColor.js +++ b/src/utils/rgbToHexColor.js @@ -2,7 +2,7 @@ module.exports = (rgb) => { let hexCode = '#'; for (const num of rgb) { const hex = Number(num).toString(16); - hexCode += hex.length === 1 ? '0' + hex : hex; + hexCode += 1 === hex.length ? '0' + hex : hex; } return hexCode; }; diff --git a/src/utils/romanize.js b/src/utils/romanize.js index a6160014..e4e176fc 100644 --- a/src/utils/romanize.js +++ b/src/utils/romanize.js @@ -1,6 +1,6 @@ module.exports = (num) => { if (isNaN(num)) return NaN; - const digits = String(+num).split(''); + const digits = String(Number(num)).split(''); const key = [ '', 'C', @@ -36,7 +36,7 @@ module.exports = (num) => { let roman = ''; let i = 3; while (i--) { - roman = (key[+digits.pop() + i * 10] || '') + roman; + roman = (key[Number(digits.pop()) + i * 10] || '') + roman; } - return Array(+digits.join('') + 1).join('M') + roman; + return Array(Number(digits.join('')) + 1).join('M') + roman; }; diff --git a/src/utils/toIGN.js b/src/utils/toIGN.js deleted file mode 100644 index fe136dbd..00000000 --- a/src/utils/toIGN.js +++ /dev/null @@ -1,24 +0,0 @@ -const fetch = require('../Private/uuidCache.js'); -const isUUID = require('./isUUID.js'); -const Errors = require('../Errors'); - -module.exports = async (input, useThirdPartyAPI = '') => { - if (!input) throw new Error(Errors.NO_NICKNAME_UUID); - if (typeof input !== 'string') throw new Error(Errors.UUID_NICKNAME_MUST_BE_A_STRING); - if (isUUID(input)) input = input.replace(/-/g, ''); - else throw new Error(Errors.MALFORMED_UUID); - try { - const customUrl = useThirdPartyAPI === true ? 'https://api.minetools.eu/uuid/' : useThirdPartyAPI; - const url = useThirdPartyAPI ? `${customUrl}${input}` : `https://mowojang.matdoes.dev/${input}`; - const res = await fetch(url, input); - const parsedRes = await res.json(); - if (parsedRes.error) { - return Promise.reject(new Error(Errors.MALFORMED_UUID)); - } - return parsedRes.name; - } catch { - // 2nd try - if (!useThirdPartyAPI) return module.exports(input, cacheTime, true); - throw new Error(Errors.PLAYER_DOES_NOT_EXIST); - } -}; diff --git a/src/utils/toUuid.js b/src/utils/toUuid.js index eb63aa89..f1a46af5 100644 --- a/src/utils/toUuid.js +++ b/src/utils/toUuid.js @@ -4,15 +4,15 @@ const Errors = require('../Errors'); module.exports = async (input, cacheTime = 600, useThirdPartyAPI = '') => { if (!input) throw new Error(Errors.NO_NICKNAME_UUID); - if (typeof input !== 'string') throw new Error(Errors.UUID_NICKNAME_MUST_BE_A_STRING); + if ('string' !== typeof input) throw new Error(Errors.UUID_NICKNAME_MUST_BE_A_STRING); if (isUUID(input)) return input.replace(/-/g, ''); try { - const customUrl = useThirdPartyAPI === true ? 'https://api.minetools.eu/uuid/' : useThirdPartyAPI; + const customUrl = true === useThirdPartyAPI ? 'https://api.minetools.eu/uuid/' : useThirdPartyAPI; const url = useThirdPartyAPI ? `${customUrl}${input}` : `https://mowojang.matdoes.dev/${input}`; const res = await fetch(url, input, cacheTime); - if (res.status === 404) { + if (404 === res.status) { return Promise.reject(new Error(Errors.PLAYER_DOES_NOT_EXIST)); - } else if (res.status !== 200) { + } else if (200 !== res.status) { throw new Error('Unknown Error whilst retrieving player information'); } return res.id; diff --git a/src/utils/varInt.js b/src/utils/varInt.js index 7103c3b9..c186fe0e 100644 --- a/src/utils/varInt.js +++ b/src/utils/varInt.js @@ -1,4 +1,4 @@ -// eslint-disable-next-line require-jsdoc +// eslint-disable-next-line jsdoc/require-jsdoc function readVarInt(bytes) { let numRead = 0; let result = 0; @@ -7,7 +7,7 @@ function readVarInt(bytes) { const value = read & 0b01111111; result |= value << (7 * numRead); numRead++; - if (numRead > 5) { + if (5 < numRead) { return NaN; } } while (numRead < bytes.length); diff --git a/typings/index.d.ts b/typings/index.d.ts index f26cd516..aab44775 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,7 +1,7 @@ /* eslint-disable indent */ /* eslint-disable max-len */ /* eslint-disable camelcase */ -/* eslint-disable require-jsdoc */ +/* eslint-disable jsdoc/require-jsdoc */ // Minimum TypeScript Version: 3.6 import { NetworthResult } from 'skyhelper-networth'; @@ -410,8 +410,7 @@ declare module 'hypixel-api-reborn' { strToArray(input: string): string[]; }; Constants: { - skyblock_year_0: 1.5602757e12; - duels_divisions: [ + duelsDivisions: [ { name: 'Rookie'; key: 'rookie' }, { name: 'Iron'; key: 'iron' }, { name: 'Gold'; key: 'gold' }, @@ -424,7 +423,7 @@ declare module 'hypixel-api-reborn' { { name: 'WORLD MASTER'; key: 'world_master' }, { name: "WORLD'S BEST"; key: 'worlds_best' } ]; - leveling_xp: { + levelingXp: { 1: 50; 2: 125; 3: 200; @@ -476,7 +475,7 @@ declare module 'hypixel-api-reborn' { 49: 3700000; 50: 4000000; }; - xp_past_50: { + xpPast50: { 51: 4300000; 52: 4600000; 53: 4900000; @@ -488,7 +487,7 @@ declare module 'hypixel-api-reborn' { 59: 6700000; 60: 7000000; }; - runecrafting_xp: { + runecraftingXp: { 1: 50; 2: 100; 3: 125; @@ -515,29 +514,7 @@ declare module 'hypixel-api-reborn' { 24: 15300; 25: 19050; }; - skills: [ - 'farming', - 'mining', - 'combat', - 'foraging', - 'fishing', - 'enchanting', - 'alchemy', - 'taming', - 'carpentry', - 'runecrafting' - ]; - skills_achievements: { - farming: 'skyblockHarvester'; - mining: 'skyblockExcavator'; - combat: 'skyblockCombat'; - foraging: 'skyblockGatherer'; - fishing: 'skyblockAngler'; - enchanting: 'skyblockAugmentation'; - alchemy: 'skyblockConcoctor'; - taming: 'skyblockDomesticator'; - }; - skills_cap: { + skillsCap: { taming: 50; farming: 60; mining: 60; @@ -549,8 +526,9 @@ declare module 'hypixel-api-reborn' { carpentry: 50; runecrafting: 25; dungeons: 50; + social: 25; }; - dungeon_xp: { + dungeonXp: { 1: 50; 2: 75; 3: 110; @@ -602,18 +580,43 @@ declare module 'hypixel-api-reborn' { 49: 9.3e7; 50: 1.1625e8; }; - slayer_xp: { - 1: 5; - 2: 15; - 3: 200; - 4: 1000; - 5: 5000; - 6: 20000; - 7: 100000; - 8: 400000; - 9: 1000000; + hotmXp: { + 1: 0; + 2: 3000; + 3: 9000; + 4: 25000; + 5: 60000; + 6: 100000; + 7: 150000; + }; + socialXp: { + 1: 50; + 2: 100; + 3: 150; + 4: 250; + 5: 500; + 6: 750; + 7: 1000; + 8: 1250; + 9: 1500; + 10: 2000; + 11: 2500; + 12: 3000; + 13: 3750; + 14: 4500; + 15: 6000; + 16: 8000; + 17: 10000; + 18: 12500; + 19: 15000; + 20: 20000; + 21: 25000; + 22: 30000; + 23: 35000; + 24: 40000; + 25: 50000; }; - pet_score: { + petScore: { COMMON: 1; UNCOMMON: 2; RARE: 3; @@ -621,125 +624,235 @@ declare module 'hypixel-api-reborn' { LEGENDARY: 5; MYTHIC: 6; }; - base_stats: { - damage: 0; - health: 100; - defense: 0; - effective_health: 100; - strength: 0; - damage_increase: 0; - speed: 100; - crit_chance: 20; - crit_damage: 50; - intelligence: 0; - }; - stat_template: { - damage: 0; - health: 0; - defense: 0; - effective_health: 0; - strength: 0; - damage_increase: 0; - speed: 0; - crit_chance: 0; - crit_damage: 0; - intelligence: 0; - }; - bonus_stats: { - taming_skill: { 1: { pet_luck: 1 } }; - fairy_souls: { - 5: { health: 3; defense: 1; strength: 1; speed: 0 }; - 10: { health: 3; defense: 1; strength: 1; speed: 0 }; - 15: { health: 4; defense: 1; strength: 1; speed: 0 }; - 20: { health: 4; defense: 1; strength: 1; speed: 0 }; - 25: { health: 5; defense: 2; strength: 2; speed: 0 }; - 30: { health: 5; defense: 1; strength: 1; speed: 0 }; - 35: { health: 6; defense: 1; strength: 1; speed: 0 }; - 40: { health: 6; defense: 1; strength: 1; speed: 0 }; - 45: { health: 7; defense: 1; strength: 1; speed: 0 }; - 50: { health: 7; defense: 2; strength: 2; speed: 1 }; - 55: { health: 8; defense: 1; strength: 1; speed: 0 }; - 60: { health: 8; defense: 1; strength: 1; speed: 0 }; - 65: { health: 9; defense: 1; strength: 1; speed: 0 }; - 70: { health: 9; defense: 1; strength: 1; speed: 0 }; - 75: { health: 10; defense: 2; strength: 2; speed: 0 }; - 80: { health: 10; defense: 1; strength: 1; speed: 0 }; - 85: { health: 11; defense: 1; strength: 1; speed: 0 }; - 90: { health: 11; defense: 1; strength: 1; speed: 0 }; - 95: { health: 12; defense: 1; strength: 1; speed: 0 }; - 100: { health: 12; defense: 2; strength: 2; speed: 1 }; - 105: { health: 13; defense: 1; strength: 1; speed: 0 }; - 110: { health: 13; defense: 1; strength: 1; speed: 0 }; - 115: { health: 14; defense: 1; strength: 1; speed: 0 }; - 120: { health: 14; defense: 1; strength: 1; speed: 0 }; - 125: { health: 15; defense: 2; strength: 2; speed: 0 }; - 130: { health: 15; defense: 1; strength: 1; speed: 0 }; - 135: { health: 16; defense: 1; strength: 1; speed: 0 }; - 140: { health: 16; defense: 1; strength: 1; speed: 0 }; - 145: { health: 17; defense: 1; strength: 1; speed: 0 }; - 150: { health: 17; defense: 2; strength: 2; speed: 1 }; - 155: { health: 18; defense: 1; strength: 1; speed: 0 }; - 160: { health: 18; defense: 1; strength: 1; speed: 0 }; - 165: { health: 19; defense: 1; strength: 1; speed: 0 }; - 170: { health: 19; defense: 1; strength: 1; speed: 0 }; - 175: { health: 20; defense: 2; strength: 2; speed: 0 }; - 180: { health: 20; defense: 1; strength: 1; speed: 0 }; - 185: { health: 21; defense: 1; strength: 1; speed: 0 }; - 190: { health: 21; defense: 1; strength: 1; speed: 0 }; - }; - farming_skill: { - 1: { health: 2 }; - 15: { health: 3 }; - 20: { health: 4 }; - 26: { health: 5 }; - }; - combat_skill: { 1: { crit_chance: 0.5; damage_increase: 0.04 } }; - mining_skill: { 1: { defense: 1 }; 15: { defense: 2 } }; - foraging_skill: { 1: { strength: 1 }; 15: { strength: 2 } }; - fishing_skill: { - 1: { health: 2 }; - 15: { health: 3 }; - 20: { health: 4 }; - 26: { health: 5 }; - }; - enchanting_skill: { 1: { intelligence: 1 }; 15: { intelligence: 2 } }; - alchemy_skill: { 1: { intelligence: 1 }; 15: { intelligence: 2 } }; - carpentry_skill: { 1: Record }; - runecrafting_skill: { 1: Record }; - zombie_slayer: { - 1: { health: 2 }; - 3: { health: 3 }; - 5: { health: 4 }; - 7: { health: 5 }; - 9: { health: 6 }; - }; - spider_slayer: { - 1: { crit_damage: 1 }; - 5: { crit_damage: 2 }; - 7: { crit_damage: 0; crit_chance: 1 }; - 8: { crit_chance: 0; crit_damage: 3 }; - }; - wolf_slayer: { - 1: { speed: 1 }; - 2: { health: 2 }; - 3: { speed: 1 }; - 4: { health: 2 }; - 5: { crit_damage: 1 }; - 6: { health: 3 }; - 7: { crit_damage: 2 }; - 8: { speed: 1 }; - }; - enchantments: { - sharpness: { 1: { damage_multiplicator: 0.05 } }; - ender: { 1: { damage_multiplicator: 0.12 } }; - giant_killer: { 1: { damage_multiplicator: 0.05 } }; - cubism: { 1: { damage_multiplicator: 0.1 } }; - impaling: { 1: { damage_multiplicator: 0.125 } }; - critical: { 1: { crit_damage: 10 } }; - first_strike: { 1: { damage_multiplicator: 0.25 } }; - power: { 1: { damage_multiplicator: 0.08 } }; - }; + petRarityOffset: { + COMMON: 0; + UNCOMMON: 6; + RARE: 11; + EPIC: 16; + LEGENDARY: 20; + MYTHIC: 20; }; + petLevels: [ + 100, + 110, + 120, + 130, + 145, + 160, + 175, + 190, + 210, + 230, + 250, + 275, + 300, + 330, + 360, + 400, + 440, + 490, + 540, + 600, + 660, + 730, + 800, + 880, + 960, + 1050, + 1150, + 1260, + 1380, + 1510, + 1650, + 1800, + 1960, + 2130, + 2310, + 2500, + 2700, + 2920, + 3160, + 3420, + 3700, + 4000, + 4350, + 4750, + 5200, + 5700, + 6300, + 7000, + 7800, + 8700, + 9700, + 10800, + 12000, + 13300, + 14700, + 16200, + 17800, + 19500, + 21300, + 23200, + 25200, + 27400, + 29800, + 32400, + 35200, + 38200, + 41400, + 44800, + 48400, + 52200, + 56200, + 60400, + 64800, + 69400, + 74200, + 79200, + 84700, + 90700, + 97200, + 104200, + 111700, + 119700, + 128200, + 137200, + 146700, + 156700, + 167700, + 179700, + 192700, + 206700, + 221700, + 237700, + 254700, + 272700, + 291700, + 311700, + 333700, + 357700, + 383700, + 411700, + 441700, + 476700, + 516700, + 561700, + 611700, + 666700, + 726700, + 791700, + 861700, + 936700, + 1016700, + 1101700, + 1191700, + 1286700, + 1386700, + 1496700, + 1616700, + 1746700, + 1886700, + 0, + 5555, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700, + 1886700 + ]; leaderboardNames: { ARENA: 'ARENA'; COPS_AND_CRIMS: 'MCGO'; @@ -966,7 +1079,6 @@ declare module 'hypixel-api-reborn' { /** * @description Returns all cache entries */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any readonly cache: Map; /** * @description Allows you to get statistics of player @@ -2261,7 +2373,6 @@ declare module 'hypixel-api-reborn' { tank: SKYBLOCK_SKILL_DATA; }; }; - // eslint-disable-next-line @typescript-eslint/no-explicit-any collections: any; purse: number; stats?: { @@ -3925,7 +4036,6 @@ declare module 'hypixel-api-reborn' { /** * @description Reads the bytes as a NBT tag */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any readNBT(): Promise; } class ServerInfo {