diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..d2f689c7 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +/src/thirdParty/ +node_modules \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..39e9cac9 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + env: { + browser: true, + es2021: true, + webextensions: true, + jquery: true + }, + extends: ['standard'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 12, + sourceType: 'module' + }, + plugins: ['@typescript-eslint'], + rules: {} +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..2354a257 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2048 @@ +{ + "name": "tufast_tud", + "version": "5.6.4", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.15.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz", + "integrity": "sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "@eslint/eslintrc": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", + "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "@humanwhocodes/config-array": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", + "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/object-schema": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", + "dev": true + }, + "@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, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@types/json-schema": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz", + "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==", + "dev": true + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.31.2.tgz", + "integrity": "sha512-w63SCQ4bIwWN/+3FxzpnWrDjQRXVEGiTt9tJTRptRXeFvdZc/wLiz3FQUwNQ2CVoRGI6KUWMNUj/pk63noUfcA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.31.2", + "@typescript-eslint/scope-manager": "4.31.2", + "debug": "^4.3.1", + "functional-red-black-tree": "^1.0.1", + "regexpp": "^3.1.0", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/experimental-utils": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.31.2.tgz", + "integrity": "sha512-3tm2T4nyA970yQ6R3JZV9l0yilE2FedYg8dcXrTar34zC9r6JB7WyBQbpIVongKPlhEMjhQ01qkwrzWy38Bk1Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.7", + "@typescript-eslint/scope-manager": "4.31.2", + "@typescript-eslint/types": "4.31.2", + "@typescript-eslint/typescript-estree": "4.31.2", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/parser": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.31.2.tgz", + "integrity": "sha512-EcdO0E7M/sv23S/rLvenHkb58l3XhuSZzKf6DBvLgHqOYdL6YFMYVtreGFWirxaU2mS1GYDby3Lyxco7X5+Vjw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.31.2", + "@typescript-eslint/types": "4.31.2", + "@typescript-eslint/typescript-estree": "4.31.2", + "debug": "^4.3.1" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.31.2.tgz", + "integrity": "sha512-2JGwudpFoR/3Czq6mPpE8zBPYdHWFGL6lUNIGolbKQeSNv4EAiHaR5GVDQaLA0FwgcdcMtRk+SBJbFGL7+La5w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.31.2", + "@typescript-eslint/visitor-keys": "4.31.2" + } + }, + "@typescript-eslint/types": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.31.2.tgz", + "integrity": "sha512-kWiTTBCTKEdBGrZKwFvOlGNcAsKGJSBc8xLvSjSppFO88AqGxGNYtF36EuEYG6XZ9vT0xX8RNiHbQUKglbSi1w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.31.2.tgz", + "integrity": "sha512-ieBq8U9at6PvaC7/Z6oe8D3czeW5d//Fo1xkF/s9394VR0bg/UaMYPdARiWyKX+lLEjY3w/FNZJxitMsiWv+wA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.31.2", + "@typescript-eslint/visitor-keys": "4.31.2", + "debug": "^4.3.1", + "globby": "^11.0.3", + "is-glob": "^4.0.1", + "semver": "^7.3.5", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.31.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.31.2.tgz", + "integrity": "sha512-PrBId7EQq2Nibns7dd/ch6S6/M4/iwLM9McbgeEbCXfxdwRUNxJ4UNreJ6Gh3fI2GNKNrWnQxKL7oCPmngKBug==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.31.2", + "eslint-visitor-keys": "^2.0.0" + } + }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-includes": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz", + "integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2", + "get-intrinsic": "^1.1.1", + "is-string": "^1.0.5" + } + }, + "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 + }, + "array.prototype.flat": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz", + "integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.1" + } + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "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, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.18.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.6.tgz", + "integrity": "sha512-kAeIT4cku5eNLNuUKhlmtuk1/TRZvQoYccn6TO0cSVdf1kzB0T7+dYuVK9MWM7l+/53W2Q8M7N2c6MQvhXFcUQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "get-symbol-description": "^1.0.0", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "internal-slot": "^1.0.3", + "is-callable": "^1.2.4", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.4", + "is-string": "^1.0.7", + "object-inspect": "^1.11.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "7.32.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz", + "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==", + "dev": true, + "requires": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + } + } + }, + "eslint-config-standard": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-16.0.3.tgz", + "integrity": "sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz", + "integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "resolve": "^1.20.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz", + "integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "pkg-dir": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.24.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.2.tgz", + "integrity": "sha512-hNVtyhiEtZmpsabL4neEj+6M5DCLgpYyG9nzJY8lZQeQXEn5UPW1DpUdsMHMXsq98dbNm7nt1w9ZMSVpfJdi8Q==", + "dev": true, + "requires": { + "array-includes": "^3.1.3", + "array.prototype.flat": "^1.2.4", + "debug": "^2.6.9", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-module-utils": "^2.6.2", + "find-up": "^2.0.0", + "has": "^1.0.3", + "is-core-module": "^2.6.0", + "minimatch": "^3.0.4", + "object.values": "^1.1.4", + "pkg-up": "^2.0.0", + "read-pkg-up": "^3.0.0", + "resolve": "^1.20.0", + "tsconfig-paths": "^3.11.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", + "dev": true, + "requires": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "dependencies": { + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz", + "integrity": "sha512-NGmI6BH5L12pl7ScQHbg7tvtk4wPxxj8yPHH47NvSmMtFneC077PSeY3huFj06ZWZvtbfxSPt3RuOQD5XcR4ng==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "requires": { + "@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" + } + }, + "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", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "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==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.2.tgz", + "integrity": "sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.11.0.tgz", + "integrity": "sha512-08/xrJ7wQjK9kkkRoI3OFUBbLx4f+6x3SGwcPvQ0QH6goFDrOU2oyAWrmh3dJezu65buo+HBMzAMQy6rovVC3g==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "globby": { + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.4.tgz", + "integrity": "sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "dev": true + }, + "is-core-module": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz", + "integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.2.tgz", + "integrity": "sha512-ZZTOjRcDjuAAAv2cTBQP/lL59ZTArx77+7UzHdWW/XB1mrfp7DEaVpKmZ0XIzx+M7AxfhKcqV+nMetUQmFifwg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz", + "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.merge": { + "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 + }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", + "dev": true + }, + "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, + "requires": { + "yallist": "^4.0.0" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "object-inspect": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz", + "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.values": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "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 + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", + "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "dependencies": { + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + } + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "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 + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", + "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ajv": { + "version": "8.6.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.3.tgz", + "integrity": "sha512-SMJOdDP6LqTkD0Uq8qLi+gMwSt0imXLSV080qFVwJCpH9U6Mb+SUGHAXM0KNbcBPguytWyvFxcHgMLe2D2XSpw==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "tsconfig-paths": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.11.0.tgz", + "integrity": "sha512-7ecdYDnIdmv639mmDwslG6KQg1Z9STTz1j7Gcz0xa+nshh/gKDAHcPxRbWOsA3SPp0tXP2leTcY9Kw+NAkfZzA==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.1", + "minimist": "^1.2.0", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "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 + }, + "typescript": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.3.tgz", + "integrity": "sha512-4xfscpisVgqqDfPaJo5vkd+Qd/ItkoagnHpufr+i2QCHBsNYp+G7UAoyFl8aPtx879u38wPV65rZ8qbGZijalA==" + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } +} diff --git a/package.json b/package.json index 4882ed4f..257b6e08 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Browser Extension for higher productivity with TU Dresden IT-Services 🚀", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "lint": "npx eslint --fix .", + "test": "npm run lint" }, "repository": { "type": "git", @@ -30,5 +31,17 @@ "bugs": { "url": "https://github.com/TUfast-TUD/TUfast_TUD/issues" }, - "homepage": "https://github.com/TUfast-TUD/TUfast_TUD#readme" + "homepage": "https://github.com/TUfast-TUD/TUfast_TUD#readme", + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^4.31.2", + "@typescript-eslint/parser": "^4.31.2", + "eslint": "^7.32.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.24.2", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-promise": "^5.1.0" + }, + "dependencies": { + "typescript": "^4.4.3" + } } diff --git a/src/background.js b/src/background.js index 75b13f89..3e53310b 100644 --- a/src/background.js +++ b/src/background.js @@ -1,33 +1,38 @@ +/* eslint-disable no-async-promise-executor */ 'use strict' -//start fetchOWA if activated and user data exists +// eslint-disable-next-line no-unused-vars +const isChrome = navigator.userAgent.includes('Chrome/') // attention: no failsave browser detection | also for new edge! +const isFirefox = navigator.userAgent.includes('Firefox/') // attention: no failsave browser detection + +// start fetchOWA if activated and user data exists chrome.storage.local.get(['enabledOWAFetch', 'NumberOfUnreadMails'], (resp) => { - userDataExists().then((userDataExists) => { - if (userDataExists && resp.enabledOWAFetch) { - enableOWAFetch() //start owa fetch - setBadgeUnreadMails(resp.NumberOfUnreadMails) //read number of unread mails from storage and display badge - console.log("Activated OWA fetch.") - } else { console.log("No OWAfetch registered") } - }) + userDataExists().then((userDataExists) => { + if (userDataExists && resp.enabledOWAFetch) { + enableOWAFetch() // start owa fetch + setBadgeUnreadMails(resp.NumberOfUnreadMails) // read number of unread mails from storage and display badge + console.log('Activated OWA fetch.') + } else { console.log('No OWAfetch registered') } + }) }) -//enable rating -chrome.storage.local.set({ratingEnabledFlag: true}, function () {}) +// disable star rating +chrome.storage.local.set({ ratingEnabledFlag: false }, function () {}) -//DOESNT WORK IN RELEASE VERSION +// DOESNT WORK IN RELEASE VERSION chrome.storage.local.get(['openSettingsOnReload'], (resp) => { - if (resp.openSettingsOnReload) openSettingsPage() - chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) + if (resp.openSettingsOnReload) openSettingsPage() + chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) }) -//set browserIcon +// set browserIcon chrome.storage.local.get(['selectedRocketIcon'], (resp) => { - try { - let r = JSON.parse(resp.selectedRocketIcon) - chrome.browserAction.setIcon({ - path: r.link - }) - } catch (e) { console.log("Cannot set rocket icon: " + e) } + try { + const r = JSON.parse(resp.selectedRocketIcon) + chrome.browserAction.setIcon({ + path: r.link + }) + } catch (e) { console.log('Cannot set rocket icon: ' + e) } }) console.log('Loaded TUfast') @@ -43,404 +48,392 @@ chrome.storage.local.set({ loggedOutCloudstore: false }, function () { }) chrome.storage.local.set({ loggedOutTex: false }, function () { }) chrome.storage.local.set({ loggedOutTumed: false }, function () { }) chrome.storage.local.set({ loggedOutGitlab: false }, function () { }) -chrome.storage.local.get(["pdfInNewTab"], function (result) { - if (result.pdfInNewTab) { - enableHeaderListener(true) - } +chrome.storage.local.get(['pdfInNewTab'], function (result) { + if (result.pdfInNewTab) { + enableHeaderListener(true) + } }) - chrome.runtime.onInstalled.addListener(async (details) => { - const reason = details.reason - switch (reason) { - case 'install': - console.log('TUfast installed.') - openSettingsPage("first_visit") //open settings page - chrome.storage.local.set({ installed: true }, function () { }) - chrome.storage.local.set({ showed_50_clicks: false }, function () { }) - chrome.storage.local.set({ showed_100_clicks: false }, function () { }) - chrome.storage.local.set({ isEnabled: false }, function () { }) - chrome.storage.local.set({ fwdEnabled: true }, function () { }) - chrome.storage.local.set({ mostLiklySubmittedReview: false }, function () { }) - chrome.storage.local.set({ removedReviewBanner: false }, function () { }) - chrome.storage.local.set({ neverShowedReviewBanner: true }, function () { }) - chrome.storage.local.set({ encryption_level: 2 }, function () { }) - chrome.storage.local.set({ meine_kurse: false }, function () { }) - chrome.storage.local.set({ favoriten: false }, function () { }) - //chrome.storage.local.set({openSettingsPageParam: false}, function() {}) - chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: 0 }, function () { }) - chrome.storage.local.set({ dashboardDisplay: "favoriten" }, function () { }) - chrome.storage.local.set({ additionalNotificationOnNewMail: false }) - chrome.storage.local.set({ NumberOfUnreadMails: "undefined" }) - chrome.storage.local.set({ removedOpalBanner: false }, function () { }) - chrome.storage.local.set({ nameIsTUfast: true }, function () { }) - chrome.storage.local.set({ enabledOWAFetch: false }, function () { }) - chrome.storage.local.set({ colorfulRocket: "black" }, function () { }) - chrome.storage.local.set({ PRObadge: false }, function () { }) - chrome.storage.local.set({ flakeState: false }, function () { }) - chrome.storage.local.set({ availableRockets: ["RI_default"] }, function () { }) - chrome.storage.local.set({ foundEasteregg: false }, function () { }) - chrome.storage.local.set({ hisqisPimpedTable: true }, function () { }) - chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) - chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI_default", "link": "assets/icons/RocketIcons/default_128px.png"}' }, function () { }) - chrome.storage.local.set({ pdfInInline: false }, function () { }) - chrome.storage.local.set({ pdfInNewTab: false }, function () { }) - chrome.storage.local.set({ studiengang: "general" }, function () { }) - chrome.storage.local.set({ updateCustomizeStudiengang: false }, function () { }) - chrome.storage.local.set({ TUfastCampInvite1: false }, function () { }) - chrome.storage.local.set({ theme: 'system' }) - break - case 'update': - //check if encryption is already on level 2. This should be the case for every install now. But I'll leave this here anyway - chrome.storage.local.get(['encryption_level'], (resp) => { - if (!(resp.encryption_level === 2)) { - console.log('Upgrading encryption standard to level 2...') - chrome.storage.local.get(['asdf', 'fdsa'], function (result) { - setUserData({ asdf: atob(result.asdf), fdsa: atob(result.fdsa) }) - chrome.storage.local.set({ encryption_level: 2 }, function () { }) - }) - } - }) - //check if the type of courses is selected which should be display in the dasbhaord. If not, set to default - chrome.storage.local.get(['dashboardDisplay'], (resp) => { - if (resp.dashboardDisplay === null || resp.dashboardDisplay === undefined || resp.dashboardDisplay === "") { - chrome.storage.local.set({ dashboardDisplay: "favoriten" }, function () { }) - } - }) - //check if mostLiklySubmittedReview - chrome.storage.local.get(['mostLiklySubmittedReview'], (resp) => { - if (resp.mostLiklySubmittedReview === null || resp.mostLiklySubmittedReview === undefined || resp.mostLiklySubmittedReview === "") { - chrome.storage.local.set({ mostLiklySubmittedReview: false }, function () { }) - } - }) - //check if removedReviewBanner - chrome.storage.local.get(['removedReviewBanner'], (resp) => { - if (resp.removedReviewBanner === null || resp.removedReviewBanner === undefined || resp.removedReviewBanner === "") { - chrome.storage.local.set({ removedReviewBanner: false }, function () { }) - } - }) - //check if neverShowedReviewBanner - chrome.storage.local.get(['neverShowedReviewBanner'], (resp) => { - if (resp.neverShowedReviewBanner === null || resp.neverShowedReviewBanner === undefined || resp.neverShowedReviewBanner === "") { - chrome.storage.local.set({ neverShowedReviewBanner: true }, function () { }) - } - }) - //check if seenInOpalAfterDashbaordUpdate exists - chrome.storage.local.get(['seenInOpalAfterDashbaordUpdate'], (resp) => { - if (resp.seenInOpalAfterDashbaordUpdate === null || resp.seenInOpalAfterDashbaordUpdate === undefined || resp.seenInOpalAfterDashbaordUpdate === "") { - chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: 0 }, function () { }) - } - }) - //check if enabledOWAFetch exists - chrome.storage.local.get(['enabledOWAFetch'], (resp) => { - if (resp.enabledOWAFetch === null || resp.enabledOWAFetch === undefined || resp.enabledOWAFetch === "") { - chrome.storage.local.set({ enabledOWAFetch: false }, function () { }) - chrome.storage.local.set({ NumberOfUnreadMails: "undefined" }) - chrome.storage.local.set({ additionalNotificationOnNewMail: false }) - } - }) - //check, whether flake state exists. If not, initialize with false. - chrome.storage.local.get(['flakeState'], function (result) { - if (result.flakeState === undefined || result.flakeState === null) { //set to true, so that state will be false! - chrome.storage.local.set({ flakeState: false }, function () { }) - } - }) - //check if ShowedFirefoxBanner - chrome.storage.local.get(['showedFirefoxBanner'], function (result) { - if (result.showedFirefoxBanner === undefined || result.showedFirefoxBanner === null) { - chrome.storage.local.set({ showedFirefoxBanner: false }, function () { }) - } - }) - //check if showedUnreadMailCounterBanner - chrome.storage.local.get(['showedUnreadMailCounterBanner'], function (result) { - if (result.showedUnreadMailCounterBanner === undefined || result.showedUnreadMailCounterBanner === null) { - chrome.storage.local.set({ showedUnreadMailCounterBanner: false }, function () { }) - } - }) - //check if openSettingsOnReload - chrome.storage.local.get(['openSettingsOnReload'], function (result) { - if (result.openSettingsOnReload === undefined || result.openSettingsOnReload === null) { - chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) - } - }) - //check if availableRockets - chrome.storage.local.get(['availableRockets'], function (result) { - if (result.availableRockets === undefined || result.availableRockets === null) { - chrome.storage.local.set({ availableRockets: ["RI_default"] }, function () { }) - } - }) - //check if selectedRocketIcon - chrome.storage.local.get(['selectedRocketIcon'], function (result) { - if (result.selectedRocketIcon === undefined || result.selectedRocketIcon === null) { - chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI_default", "link": "assets/icons/RocketIcons/default_128px.png"}' }, function () { }) - } - }) - //check if hisqisPimpedTable - chrome.storage.local.get(['hisqisPimpedTable'], function (result) { - if (result.hisqisPimpedTable === undefined || result.hisqisPimpedTable === null) { - chrome.storage.local.set({ hisqisPimpedTable: true }, function () { }) - } - }) - //if easteregg was discovered in an earlier version: enable and select specific rocket! - chrome.storage.local.get(['Rocket', "foundEasteregg", "saved_click_counter", "availableRockets"], function (result) { - let avRockets = result.availableRockets - if (result.saved_click_counter > 250 && !avRockets.includes("RI4")) avRockets.push("RI4") - if (result.saved_click_counter > 2500 && !avRockets.includes("RI5")) avRockets.push("RI5") - if (result.Rocket === "colorful" && result.foundEasteregg === undefined) { - chrome.storage.local.set({ foundEasteregg: true }, function () { }) - chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI3", "link": "assets/icons/RocketIcons/3_120px.png"}' }, function () { }) - avRockets.push("RI3") - chrome.browserAction.setIcon({ - path: "assets/icons/RocketIcons/3_120px.png" - }) - } - chrome.storage.local.set({ "availableRockets": avRockets }) - - }) - //seen customized studiengang - chrome.storage.local.get(['updateCustomizeStudiengang'], function (result) { - if (result.updateCustomizeStudiengang === undefined || result.updateCustomizeStudiengang === null) { - chrome.storage.local.set({ updateCustomizeStudiengang: false }, function () { }) - } - }) - //selected studiengang - chrome.storage.local.get(['studiengang'], function (result) { - if (result.studiengang === undefined || result.studiengang === null) { - chrome.storage.local.set({ studiengang: "general" }, function () { }) - } - }) - //selected theme - chrome.storage.local.get(['theme'], (res) => { - if (res.theme === undefined || res.theme === null) { - chrome.storage.local.set({ theme: 'system' }) - } - }) - //if not yet invite shown: show, and set shown to true - //chrome.storage.local.get(['TUfastCampInvite1'], (res) => { - // let today = new Date(); - // let max_invite_date = new Date(2021, 8, 30) //27.09.2021; month is zero based - // if (!res.TUfastCampInvite1 === true && today < max_invite_date) { - // chrome.storage.local.set({ TUfastCampInvite1: true }, function () { }) - // chrome.tabs.create(({ url: "TUfastCamp.html" })) - // } - // }) - - - break - default: - console.log('Other install events within the browser for TUfast.') - break - } + const reason = details.reason + switch (reason) { + case 'install': + console.log('TUfast installed.') + openSettingsPage('first_visit') // open settings page + chrome.storage.local.set({ installed: true }, function () { }) + chrome.storage.local.set({ showed_50_clicks: false }, function () { }) + chrome.storage.local.set({ showed_100_clicks: false }, function () { }) + chrome.storage.local.set({ isEnabled: false }, function () { }) + chrome.storage.local.set({ fwdEnabled: true }, function () { }) + chrome.storage.local.set({ mostLiklySubmittedReview: false }, function () { }) + chrome.storage.local.set({ removedReviewBanner: false }, function () { }) + chrome.storage.local.set({ neverShowedReviewBanner: true }, function () { }) + chrome.storage.local.set({ encryption_level: 2 }, function () { }) + chrome.storage.local.set({ meine_kurse: false }, function () { }) + chrome.storage.local.set({ favoriten: false }, function () { }) + // chrome.storage.local.set({openSettingsPageParam: false}, function() {}) + chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: 0 }, function () { }) + chrome.storage.local.set({ dashboardDisplay: 'favoriten' }, function () { }) + chrome.storage.local.set({ additionalNotificationOnNewMail: false }) + chrome.storage.local.set({ NumberOfUnreadMails: 'undefined' }) + chrome.storage.local.set({ removedOpalBanner: false }, function () { }) + chrome.storage.local.set({ nameIsTUfast: true }, function () { }) + chrome.storage.local.set({ enabledOWAFetch: false }, function () { }) + chrome.storage.local.set({ colorfulRocket: 'black' }, function () { }) + chrome.storage.local.set({ PRObadge: false }, function () { }) + chrome.storage.local.set({ flakeState: false }, function () { }) + chrome.storage.local.set({ availableRockets: ['RI_default'] }, function () { }) + chrome.storage.local.set({ foundEasteregg: false }, function () { }) + chrome.storage.local.set({ hisqisPimpedTable: true }, function () { }) + chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) + chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI_default", "link": "assets/icons/RocketIcons/default_128px.png"}' }, function () { }) + chrome.storage.local.set({ pdfInInline: false }, function () { }) + chrome.storage.local.set({ pdfInNewTab: false }, function () { }) + chrome.storage.local.set({ studiengang: 'general' }, function () { }) + chrome.storage.local.set({ updateCustomizeStudiengang: false }, function () { }) + chrome.storage.local.set({ TUfastCampInvite1: false }, function () { }) + chrome.storage.local.set({ theme: 'system' }) + break + case 'update': + // check if encryption is already on level 2. This should be the case for every install now. But I'll leave this here anyway + chrome.storage.local.get(['encryption_level'], (resp) => { + if (!(resp.encryption_level === 2)) { + console.log('Upgrading encryption standard to level 2...') + chrome.storage.local.get(['asdf', 'fdsa'], function (result) { + setUserData({ asdf: atob(result.asdf), fdsa: atob(result.fdsa) }) + chrome.storage.local.set({ encryption_level: 2 }, function () { }) + }) + } + }) + // check if the type of courses is selected which should be display in the dasbhaord. If not, set to default + chrome.storage.local.get(['dashboardDisplay'], (resp) => { + if (resp.dashboardDisplay === null || resp.dashboardDisplay === undefined || resp.dashboardDisplay === '') { + chrome.storage.local.set({ dashboardDisplay: 'favoriten' }, function () { }) + } + }) + // check if mostLiklySubmittedReview + chrome.storage.local.get(['mostLiklySubmittedReview'], (resp) => { + if (resp.mostLiklySubmittedReview === null || resp.mostLiklySubmittedReview === undefined || resp.mostLiklySubmittedReview === '') { + chrome.storage.local.set({ mostLiklySubmittedReview: false }, function () { }) + } + }) + // check if removedReviewBanner + chrome.storage.local.get(['removedReviewBanner'], (resp) => { + if (resp.removedReviewBanner === null || resp.removedReviewBanner === undefined || resp.removedReviewBanner === '') { + chrome.storage.local.set({ removedReviewBanner: false }, function () { }) + } + }) + // check if neverShowedReviewBanner + chrome.storage.local.get(['neverShowedReviewBanner'], (resp) => { + if (resp.neverShowedReviewBanner === null || resp.neverShowedReviewBanner === undefined || resp.neverShowedReviewBanner === '') { + chrome.storage.local.set({ neverShowedReviewBanner: true }, function () { }) + } + }) + // check if seenInOpalAfterDashbaordUpdate exists + chrome.storage.local.get(['seenInOpalAfterDashbaordUpdate'], (resp) => { + if (resp.seenInOpalAfterDashbaordUpdate === null || resp.seenInOpalAfterDashbaordUpdate === undefined || resp.seenInOpalAfterDashbaordUpdate === '') { + chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: 0 }, function () { }) + } + }) + // check if enabledOWAFetch exists + chrome.storage.local.get(['enabledOWAFetch'], (resp) => { + if (resp.enabledOWAFetch === null || resp.enabledOWAFetch === undefined || resp.enabledOWAFetch === '') { + chrome.storage.local.set({ enabledOWAFetch: false }, function () { }) + chrome.storage.local.set({ NumberOfUnreadMails: 'undefined' }) + chrome.storage.local.set({ additionalNotificationOnNewMail: false }) + } + }) + // check, whether flake state exists. If not, initialize with false. + chrome.storage.local.get(['flakeState'], function (result) { + if (result.flakeState === undefined || result.flakeState === null) { // set to true, so that state will be false! + chrome.storage.local.set({ flakeState: false }, function () { }) + } + }) + // check if ShowedFirefoxBanner + chrome.storage.local.get(['showedFirefoxBanner'], function (result) { + if (result.showedFirefoxBanner === undefined || result.showedFirefoxBanner === null) { + chrome.storage.local.set({ showedFirefoxBanner: false }, function () { }) + } + }) + // check if showedUnreadMailCounterBanner + chrome.storage.local.get(['showedUnreadMailCounterBanner'], function (result) { + if (result.showedUnreadMailCounterBanner === undefined || result.showedUnreadMailCounterBanner === null) { + chrome.storage.local.set({ showedUnreadMailCounterBanner: false }, function () { }) + } + }) + // check if openSettingsOnReload + chrome.storage.local.get(['openSettingsOnReload'], function (result) { + if (result.openSettingsOnReload === undefined || result.openSettingsOnReload === null) { + chrome.storage.local.set({ openSettingsOnReload: false }, function () { }) + } + }) + // check if availableRockets + chrome.storage.local.get(['availableRockets'], function (result) { + if (result.availableRockets === undefined || result.availableRockets === null) { + chrome.storage.local.set({ availableRockets: ['RI_default'] }, function () { }) + } + }) + // check if selectedRocketIcon + chrome.storage.local.get(['selectedRocketIcon'], function (result) { + if (result.selectedRocketIcon === undefined || result.selectedRocketIcon === null) { + chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI_default", "link": "assets/icons/RocketIcons/default_128px.png"}' }, function () { }) + } + }) + // check if hisqisPimpedTable + chrome.storage.local.get(['hisqisPimpedTable'], function (result) { + if (result.hisqisPimpedTable === undefined || result.hisqisPimpedTable === null) { + chrome.storage.local.set({ hisqisPimpedTable: true }, function () { }) + } + }) + // if easteregg was discovered in an earlier version: enable and select specific rocket! + chrome.storage.local.get(['Rocket', 'foundEasteregg', 'saved_click_counter', 'availableRockets'], function (result) { + const avRockets = result.availableRockets + if (result.saved_click_counter > 250 && !avRockets.includes('RI4')) avRockets.push('RI4') + if (result.saved_click_counter > 2500 && !avRockets.includes('RI5')) avRockets.push('RI5') + if (result.Rocket === 'colorful' && result.foundEasteregg === undefined) { + chrome.storage.local.set({ foundEasteregg: true }, function () { }) + chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI3", "link": "assets/icons/RocketIcons/3_120px.png"}' }, function () { }) + avRockets.push('RI3') + chrome.browserAction.setIcon({ + path: 'assets/icons/RocketIcons/3_120px.png' + }) + } + chrome.storage.local.set({ availableRockets: avRockets }) + }) + // seen customized studiengang + chrome.storage.local.get(['updateCustomizeStudiengang'], function (result) { + if (result.updateCustomizeStudiengang === undefined || result.updateCustomizeStudiengang === null) { + chrome.storage.local.set({ updateCustomizeStudiengang: false }, function () { }) + } + }) + // selected studiengang + chrome.storage.local.get(['studiengang'], function (result) { + if (result.studiengang === undefined || result.studiengang === null) { + chrome.storage.local.set({ studiengang: 'general' }, function () { }) + } + }) + // selected theme + chrome.storage.local.get(['theme'], (res) => { + if (res.theme === undefined || res.theme === null) { + chrome.storage.local.set({ theme: 'system' }) + } + }) + // if not yet invite shown: show, and set shown to true + // chrome.storage.local.get(['TUfastCampInvite1'], (res) => { + // const today = new Date() + // const max_invite_date = new Date(2021, 8, 30) // 27.09.2021; month is zero based + // if (!res.TUfastCampInvite1 === true && today < max_invite_date) { + // chrome.storage.local.set({ TUfastCampInvite1: true }, function () { }) + // chrome.tabs.create(({ url: 'TUfastCamp.html' })) + // } + // }) + + break + default: + console.log('Other install events within the browser for TUfast.') + break + } }) -//checks, if user currently uses owa in browser -function owaIsOpened() { - return new Promise(async (resolve, reject) => { - let uri = "msx.tu-dresden.de" - let tabs = await getAllChromeTabs() - tabs.forEach(function (tab) { - if ((tab.url).includes(uri)) { - console.log("currentyl opened owa") - resolve(true) - } - }) - resolve(false) - }) +// checks, if user currently uses owa in browser +function owaIsOpened () { + return new Promise(async (resolve, reject) => { + const uri = 'msx.tu-dresden.de' + const tabs = await getAllChromeTabs() + tabs.forEach(function (tab) { + if ((tab.url).includes(uri)) { + console.log('currentyl opened owa') + resolve(true) + } + }) + resolve(false) + }) } -function getAllChromeTabs() { - return new Promise(async (res, rej) => { - await chrome.tabs.query({}, function (tabs) { - res(tabs) - }) - }) +function getAllChromeTabs () { + return new Promise(async (resolve, reject) => { + await chrome.tabs.query({}, function (tabs) { + resolve(tabs) + }) + }) } -//check if user stored login data -async function loginDataExists() { - getUserData().then((userData) => { - if (userData.asdf === undefined || userData.fdsa === undefined) { - return false - } else { - return true - } - }) +// check if user stored login data +// eslint-disable-next-line no-unused-vars +async function loginDataExists () { + getUserData().then((userData) => { + if (userData.asdf === undefined || userData.fdsa === undefined) { + return false + } else { + return true + } + }) } - -//start OWA fetch funtion based on interval -function enableOWAFetch() { - //first, clear all alarms - console.log("starting to fetch from owa...") - owaFetch() - chrome.alarms.clearAll(() => { - chrome.alarms.create("fetchOWAAlarm", { delayInMinutes: 1, periodInMinutes: 5 }) - chrome.alarms.onAlarm.addListener(async (alarm) => { - owaFetch() - }) - }) +// start OWA fetch funtion based on interval +function enableOWAFetch () { + // first, clear all alarms + console.log('starting to fetch from owa...') + owaFetch() + chrome.alarms.clearAll(() => { + chrome.alarms.create('fetchOWAAlarm', { delayInMinutes: 1, periodInMinutes: 5 }) + chrome.alarms.onAlarm.addListener(async (alarm) => { + owaFetch() + }) + }) } -async function owaFetch() { - //dont logout if user is currently using owa in browser - let logout = true - if (await owaIsOpened()) { - logout = false - } - - console.log("executing fetch ...") - - //get user data - let asdf = "" - let fdsa = "" - - await getUserData().then((userData) => { - asdf = userData.asdf - fdsa = userData.fdsa - }) - - //call fetch - let mailInfoJson = await fetchOWA(asdf, fdsa, logout) - - //check # of unread mails - let numberUnreadMails = await countUnreadMsg(mailInfoJson) - console.log("Unread mails in OWA: " + numberUnreadMails) - - //alert on new Mail - await chrome.storage.local.get(['NumberOfUnreadMails', "additionalNotificationOnNewMail"], (result) => { - if (!(result.NumberOfUnreadMails === undefined || result.NumberOfUnreadMails === "undefined") && result.additionalNotificationOnNewMail) { - if (result.NumberOfUnreadMails < numberUnreadMails) { - if (confirm("Neue Mail in deinem TU Dresden Postfach!\nDruecke 'Ok' um OWA zu oeffnen.")) { - let URL = "https://msx.tu-dresden.de/owa/auth/logon.aspx?url=https%3a%2f%2fmsx.tu-dresden.de%2fowa&reason=0" - chrome.tabs.create({ url: URL }) - } - } - } - }) - - //set badge and local storage - await chrome.storage.local.set({ NumberOfUnreadMails: numberUnreadMails }) - setBadgeUnreadMails(numberUnreadMails) +async function owaFetch () { + // dont logout if user is currently using owa in browser + let logout = true + if (await owaIsOpened()) { + logout = false + } + + console.log('executing fetch ...') + + // get user data + let asdf = '' + let fdsa = '' + + await getUserData().then((userData) => { + asdf = userData.asdf + fdsa = userData.fdsa + }) + + // call fetch + const mailInfoJson = await fetchOWA(asdf, fdsa, logout) + + // check # of unread mails + const numberUnreadMails = await countUnreadMsg(mailInfoJson) + console.log('Unread mails in OWA: ' + numberUnreadMails) + + // alert on new Mail + await chrome.storage.local.get(['NumberOfUnreadMails', 'additionalNotificationOnNewMail'], (result) => { + if (!(result.NumberOfUnreadMails === undefined || result.NumberOfUnreadMails === 'undefined') && result.additionalNotificationOnNewMail) { + if (result.NumberOfUnreadMails < numberUnreadMails) { + if (confirm("Neue Mail in deinem TU Dresden Postfach!\nDruecke 'Ok' um OWA zu oeffnen.")) { + const URL = 'https://msx.tu-dresden.de/owa/auth/logon.aspx?url=https%3a%2f%2fmsx.tu-dresden.de%2fowa&reason=0' + chrome.tabs.create({ url: URL }) + } + } + } + }) + + // set badge and local storage + await chrome.storage.local.set({ NumberOfUnreadMails: numberUnreadMails }) + setBadgeUnreadMails(numberUnreadMails) } -function disableOwaFetch() { - console.log("stopped owa connection") - setBadgeUnreadMails(0) - chrome.storage.local.set({ NumberOfUnreadMails: "undefined" }) - chrome.alarms.clearAll(() => { }) +function disableOwaFetch () { + console.log('stopped owa connection') + setBadgeUnreadMails(0) + chrome.storage.local.set({ NumberOfUnreadMails: 'undefined' }) + chrome.alarms.clearAll(() => { }) } -function readMailOWA(NrUnreadMails) { - //set badge and local storage - chrome.storage.local.set({ NumberOfUnreadMails: NrUnreadMails }) - setBadgeUnreadMails(NrUnreadMails) +function readMailOWA (NrUnreadMails) { + // set badge and local storage + chrome.storage.local.set({ NumberOfUnreadMails: NrUnreadMails }) + setBadgeUnreadMails(NrUnreadMails) } -function setBadgeUnreadMails(numberUnreadMails) { - //set badge - if (numberUnreadMails == 0) { - show_badge("", '#4cb749') - } - else if (numberUnreadMails > 99) { - show_badge("99+", '#4cb749') - } - else { - show_badge(numberUnreadMails.toString(), '#4cb749') - } +function setBadgeUnreadMails (numberUnreadMails) { + // set badge + if (numberUnreadMails === 0) { + showBadge('', '#4cb749') + } else if (numberUnreadMails > 99) { + showBadge('99+', '#4cb749') + } else { + showBadge(numberUnreadMails.toString(), '#4cb749') + } } -//show badge when extension is triggered +// show badge when extension is triggered chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - switch (request.cmd) { - case 'show_ok_badge': - //show_badge('Login', '#4cb749', request.timeout) - break - case 'no_login_data': - //alert("Bitte gib deinen Nutzernamen und Passwort in der TUfast Erweiterung an! Klicke dafür auf das Erweiterungssymbol oben rechts.") - //show_badge("Error", '#ff0000', 10000) - break - case 'perform_login': - break - case 'clear_badge': - //show_badge("", "#ffffff", 0) - break - case 'save_clicks': - save_clicks(request.click_count) - break - case 'get_user_data': - getUserData().then((userData) => sendResponse(userData)) - break - case 'set_user_data': - setUserData(request.userData) - break - case 'read_mail_owa': - readMailOWA(request.NrUnreadMails) - break - case 'logged_out': - loggedOut(request.portal) - break - case "enable_owa_fetch": - enableOWAFetch() - break - case "disable_owa_fetch": - disableOwaFetch() - break - case 'reload_extension': - chrome.runtime.reload() - break - case 'save_courses': - saveCourses(request.course_list) - break - case 'open_settings_page': - openSettingsPage(request.params) - break - case 'open_share_page': - openSharePage() - break - case 'register_addition_content_scripts': - regAddContentScripts() - break - case 'open_shortcut_settings': - let isChrome = navigator.userAgent.includes("Chrome/") //attention: no failsave browser detection | also for new edge! - let isFirefox = navigator.userAgent.includes("Firefox/") //attention: no failsave browser detection - if (isFirefox) { chrome.tabs.create({ url: "https://support.mozilla.org/de/kb/tastenkombinationen-fur-erweiterungen-verwalten" }) } - else { chrome.tabs.create({ url: "chrome://extensions/shortcuts" }) } //for chrome and everything else - break - case 'toggle_pdf_inline_setting': - enableHeaderListener(request.enabled) - break - case "update_rocket_logo_easteregg": - chrome.browserAction.setIcon({ - path: "assets/icons/RocketIcons/3_120px.png" - }) - break - default: - console.log('Cmd not found!') - break - } - return true //required for async sendResponse - + switch (request.cmd) { + case 'show_ok_badge': + // show_badge('Login', '#4cb749', request.timeout) + break + case 'no_login_data': + // alert("Bitte gib deinen Nutzernamen und Passwort in der TUfast Erweiterung an! Klicke dafür auf das Erweiterungssymbol oben rechts.") + // show_badge("Error", '#ff0000', 10000) + break + case 'perform_login': + break + case 'clear_badge': + // show_badge("", "#ffffff", 0) + break + case 'save_clicks': + saveClicks(request.click_count) + break + case 'get_user_data': + getUserData().then((userData) => sendResponse(userData)) + break + case 'set_user_data': + setUserData(request.userData) + break + case 'read_mail_owa': + readMailOWA(request.NrUnreadMails) + break + case 'logged_out': + loggedOut(request.portal) + break + case 'enable_owa_fetch': + enableOWAFetch() + break + case 'disable_owa_fetch': + disableOwaFetch() + break + case 'reload_extension': + chrome.runtime.reload() + break + case 'save_courses': + saveCourses(request.course_list) + break + case 'open_settings_page': + openSettingsPage(request.params) + break + case 'open_share_page': + openSharePage() + break + case 'open_shortcut_settings': + if (isFirefox) { chrome.tabs.create({ url: 'https://support.mozilla.org/de/kb/tastenkombinationen-fur-erweiterungen-verwalten' }) } else { chrome.tabs.create({ url: 'chrome://extensions/shortcuts' }) } // for chrome and everything else + break + case 'toggle_pdf_inline_setting': + enableHeaderListener(request.enabled) + break + case 'update_rocket_logo_easteregg': + chrome.browserAction.setIcon({ + path: 'assets/icons/RocketIcons/3_120px.png' + }) + break + default: + console.log('Cmd not found!') + break + } + return true // required for async sendResponse }) - -//register hotkeys +// register hotkeys chrome.commands.onCommand.addListener(function (command) { - console.log('Detected command: ' + command) - switch (command) { - case 'open_opal_hotkey': - chrome.tabs.update({ url: "https://bildungsportal.sachsen.de/opal/home/" }) - save_clicks(2) - break - case 'open_owa_hotkey': - save_clicks(2) - chrome.tabs.update({ url: "https://msx.tu-dresden.de/owa/" }) - break - case 'open_jexam_hotkey': - chrome.tabs.update({ url: "https://jexam.inf.tu-dresden.de/" }) - save_clicks(2) - default: - break - } + console.log('Detected command: ' + command) + switch (command) { + case 'open_opal_hotkey': + chrome.tabs.update({ url: 'https://bildungsportal.sachsen.de/opal/home/' }) + saveClicks(2) + break + case 'open_owa_hotkey': + saveClicks(2) + chrome.tabs.update({ url: 'https://msx.tu-dresden.de/owa/' }) + break + case 'open_jexam_hotkey': + chrome.tabs.update({ url: 'https://jexam.inf.tu-dresden.de/' }) + saveClicks(2) + break + default: + break + } }) /** @@ -448,387 +441,382 @@ chrome.commands.onCommand.addListener(function (command) { * modify http header from opal, to view pdf in browser without the need to download it * @param {true} enabled flag to enable/ disable listener */ -function enableHeaderListener(enabled) { - if (enabled) { - chrome.webRequest.onHeadersReceived.addListener( - headerListenerFunc, - { - urls: [ - "https://bildungsportal.sachsen.de/opal/downloadering*", - "https://bildungsportal.sachsen.de/opal/*.pdf", - ], - }, - ["blocking", "responseHeaders"] - ) - } else { - chrome.webRequest.onHeadersReceived.removeListener(headerListenerFunc) - } +function enableHeaderListener (enabled) { + if (enabled) { + chrome.webRequest.onHeadersReceived.addListener( + headerListenerFunc, + { + urls: [ + 'https://bildungsportal.sachsen.de/opal/downloadering*', + 'https://bildungsportal.sachsen.de/opal/*.pdf' + ] + }, + ['blocking', 'responseHeaders'] + ) + } else { + chrome.webRequest.onHeadersReceived.removeListener(headerListenerFunc) + } } -function headerListenerFunc(details) { - let header = details.responseHeaders.find( - e => e.name.toLowerCase() === "content-disposition" - ) - if (!header.value.includes(".pdf")) return //only for pdf - header.value = "inline" - return { responseHeaders: details.responseHeaders } +function headerListenerFunc (details) { + const header = details.responseHeaders.find( + e => e.name.toLowerCase() === 'content-disposition' + ) + if (!header.value.includes('.pdf')) return // only for pdf + header.value = 'inline' + return { responseHeaders: details.responseHeaders } } -//open settings (=options) page, if required set params -function openSettingsPage(params) { - if (params) { - chrome.storage.local.set({ openSettingsPageParam: params }, function () { - chrome.runtime.openOptionsPage() - }) - } else { - chrome.runtime.openOptionsPage() - } - return +// open settings (=options) page, if required set params +function openSettingsPage (params) { + if (params) { + chrome.storage.local.set({ openSettingsPageParam: params }, function () { + chrome.runtime.openOptionsPage() + }) + } else { + chrome.runtime.openOptionsPage() + } } -function openSharePage() { - chrome.tabs.create(({ url: "share.html" })) +function openSharePage () { + chrome.tabs.create(({ url: 'share.html' })) } -//timeout is 2000 default -function loggedOut(portal) { - let timeout = 2000 - if (portal === "loggedOutCloudstore") { timeout = 7000 } - let loggedOutPortal = {} - loggedOutPortal[portal] = true - chrome.storage.local.set(loggedOutPortal, function () { }) - setTimeout(function () { - loggedOutPortal[portal] = false - chrome.storage.local.set(loggedOutPortal, function () { }) - }, timeout) +// timeout is 2000 default +function loggedOut (portal) { + let timeout = 2000 + if (portal === 'loggedOutCloudstore') { timeout = 7000 } + const loggedOutPortal = {} + loggedOutPortal[portal] = true + chrome.storage.local.set(loggedOutPortal, function () { }) + setTimeout(function () { + loggedOutPortal[portal] = false + chrome.storage.local.set(loggedOutPortal, function () { }) + }, timeout) } -//show badge -function show_badge(Text, Color, timeout) { - chrome.browserAction.setBadgeText({ text: Text }) - chrome.browserAction.setBadgeBackgroundColor({ color: Color }) - //setTimeout(function() { - // chrome.browserAction.setBadgeText({text: ""}); - //}, timeout); +// show badge +function showBadge (Text, Color, timeout) { + chrome.browserAction.setBadgeText({ text: Text }) + chrome.browserAction.setBadgeBackgroundColor({ color: Color }) + // setTimeout(function() { + // chrome.browserAction.setBadgeText({text: ""}); + // }, timeout); } -//save_click_counter -function save_clicks(counter) { - //load number of saved clicks and add counter! - var saved_clicks = 0 - chrome.storage.local.get(['saved_click_counter'], (result) => { - saved_clicks = (result.saved_click_counter === undefined) ? 0 : result.saved_click_counter - chrome.storage.local.set({ saved_click_counter: saved_clicks + counter }, function () { - console.log('You just saved yourself ' + counter + " clicks!") - }) - //make rocketIcons available if appropriate - chrome.storage.local.get(["availableRockets"], (resp) => { - let avRockets = resp.availableRockets - if (result.saved_click_counter > 250 && !avRockets.includes("RI4")) avRockets.push("RI4") - if (result.saved_click_counter > 2500 && !avRockets.includes("RI5")) avRockets.push("RI5") - chrome.storage.local.set({ "availableRockets": avRockets }) - }) - }) +// save_click_counter +function saveClicks (counter) { + // load number of saved clicks and add counter! + let savedClicks = 0 + chrome.storage.local.get(['saved_click_counter'], (result) => { + savedClicks = (result.saved_click_counter === undefined) ? 0 : result.saved_click_counter + chrome.storage.local.set({ saved_click_counter: savedClicks + counter }, function () { + console.log('You just saved yourself ' + counter + ' clicks!') + }) + // make rocketIcons available if appropriate + chrome.storage.local.get(['availableRockets'], (resp) => { + const avRockets = resp.availableRockets + if (result.saved_click_counter > 250 && !avRockets.includes('RI4')) avRockets.push('RI4') + if (result.saved_click_counter > 2500 && !avRockets.includes('RI5')) avRockets.push('RI5') + chrome.storage.local.set({ availableRockets: avRockets }) + }) + }) } -//////////////// FUNCTIONS FOR ENCRYPTION AND USERDATA HANDLING //////////////// +/// ///////////// FUNCTIONS FOR ENCRYPTION AND USERDATA HANDLING //////////////// // info: asdf = username | fdsa = password -//create hash from input-string (can also be json of course) -//output hash is always of same length and is of type buffer -function hashDigest(string) { - return new Promise(async (resolve, reject) => { - const encoder = new TextEncoder() - const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(string)) - resolve(hashBuffer) - }) -} - -//get key for encryption (format: buffer) -function getKeyBuffer() { - return new Promise((resolve, reject) => { - let sysInfo = "" - let isChrome = navigator.userAgent.includes("Chrome/") //attention: no failsave browser detection | also for new edge! - let isFirefox = navigator.userAgent.includes("Firefox/") //attention: no failsave browser detection - - //key differs between browsers, because different APIs - if (isFirefox) { - sysInfo = sysInfo + window.navigator.hardwareConcurrency - chrome.runtime.getPlatformInfo(async (info) => { - sysInfo = sysInfo + JSON.stringify(info) - //create key - let keyBuffer = await crypto.subtle.importKey('raw', await hashDigest(sysInfo), - { name: "AES-CBC", }, - false, - ['encrypt', 'decrypt']) - resolve(keyBuffer) - }) - //chrome, edge and everything else - } else { - chrome.system.cpu.getInfo(info => { - delete info['processors'] - delete info['temperatures'] - sysInfo = sysInfo + JSON.stringify(info) - chrome.runtime.getPlatformInfo(async (info) => { - sysInfo = sysInfo + JSON.stringify(info) - //create key - let keyBuffer = await crypto.subtle.importKey('raw', await hashDigest(sysInfo), - { name: "AES-CBC", }, - false, - ['encrypt', 'decrypt']) - resolve(keyBuffer) - }) - }) - } - }) +// create hash from input-string (can also be json of course) +// output hash is always of same length and is of type buffer +function hashDigest (string) { + return new Promise(async (resolve, reject) => { + const encoder = new TextEncoder() + const hashBuffer = await crypto.subtle.digest('SHA-256', encoder.encode(string)) + resolve(hashBuffer) + }) } -//this functions saved user login-data locally. -//user data is encrypted using the crpyto-js library (aes-cbc). The encryption key is created from pc-information with system.cpu -//a lot of encoding and transforming needs to be done, in order to provide all values in the right format. -async function setUserData(userData) { - //collect all required information for encryption in the right format - let userDataConcat = userData.asdf + '@@@@@' + userData.fdsa - let encoder = new TextEncoder() - let userDataEncoded = encoder.encode(userDataConcat) - let keyBuffer = await getKeyBuffer() - let iv = crypto.getRandomValues(new Uint8Array(16)) - - //encrypt - let userDataEncrypted = await crypto.subtle.encrypt( - { - name: "AES-CBC", - iv: iv - }, - keyBuffer, - userDataEncoded - ) - - //adjust format to save encrypted data in lokal storage - userDataEncrypted = Array.from(new Uint8Array(userDataEncrypted)) - userDataEncrypted = userDataEncrypted.map(byte => String.fromCharCode(byte)).join('') - userDataEncrypted = btoa(userDataEncrypted) - iv = Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') - chrome.storage.local.set({ Data: iv + userDataEncrypted }, function () { }) +// get key for encryption (format: buffer) +function getKeyBuffer () { + return new Promise((resolve, reject) => { + let sysInfo = '' + // key differs between browsers, because different APIs + if (isFirefox) { + sysInfo = sysInfo + window.navigator.hardwareConcurrency + chrome.runtime.getPlatformInfo(async (info) => { + sysInfo = sysInfo + JSON.stringify(info) + // create key + const keyBuffer = await crypto.subtle.importKey('raw', await hashDigest(sysInfo), + { name: 'AES-CBC' }, + false, + ['encrypt', 'decrypt']) + resolve(keyBuffer) + }) + // chrome, edge and everything else + } else { + chrome.system.cpu.getInfo(info => { + delete info.processors + delete info.temperatures + sysInfo = sysInfo + JSON.stringify(info) + chrome.runtime.getPlatformInfo(async (info) => { + sysInfo = sysInfo + JSON.stringify(info) + // create key + const keyBuffer = await crypto.subtle.importKey('raw', await hashDigest(sysInfo), + { name: 'AES-CBC' }, + false, + ['encrypt', 'decrypt']) + resolve(keyBuffer) + }) + }) + } + }) } -//check if username, password exist -function userDataExists() { - return new Promise(async (resolve, reject) => { - let userData = await getUserData() - if (userData.asdf === undefined || userData.fdsa === undefined) { - resolve(false) - return - } - resolve(true) - return - }) +// this functions saved user login-data locally. +// user data is encrypted using the crpyto-js library (aes-cbc). The encryption key is created from pc-information with system.cpu +// a lot of encoding and transforming needs to be done, in order to provide all values in the right format. +async function setUserData (userData) { + // collect all required information for encryption in the right format + const userDataConcat = userData.asdf + '@@@@@' + userData.fdsa + const encoder = new TextEncoder() + const userDataEncoded = encoder.encode(userDataConcat) + const keyBuffer = await getKeyBuffer() + let iv = crypto.getRandomValues(new Uint8Array(16)) + + // encrypt + let userDataEncrypted = await crypto.subtle.encrypt( + { + name: 'AES-CBC', + iv: iv + }, + keyBuffer, + userDataEncoded + ) + + // adjust format to save encrypted data in lokal storage + userDataEncrypted = Array.from(new Uint8Array(userDataEncrypted)) + userDataEncrypted = userDataEncrypted.map(byte => String.fromCharCode(byte)).join('') + userDataEncrypted = btoa(userDataEncrypted) + iv = Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') + chrome.storage.local.set({ Data: iv + userDataEncrypted }, function () { }) } -//return {asdf: "", fdsa: ""} -//decrypt and return user data -//a lot of encoding and transforming needs to be done, in order to provide all values in the right format -async function getUserData() { - return new Promise(async (resolve, reject) => { - //get required data for decryption - let keyBuffer = await getKeyBuffer() - chrome.storage.local.get(['Data'], async (Data) => { - //check if Data exists, else return - if (Data.Data === undefined || Data.Data === "undefined" || Data.Data === null) { - resolve({ asdf: undefined, fdsa: undefined }) - return - } - let iv = await Data.Data.slice(0, 32).match(/.{2}/g).map(byte => parseInt(byte, 16)) - iv = new Uint8Array(iv) - let userDataEncrypted = atob(Data.Data.slice(32)) - userDataEncrypted = new Uint8Array(userDataEncrypted.match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) - - //decrypt - let UserData = await crypto.subtle.decrypt( - { - name: "AES-CBC", - iv: iv - }, - keyBuffer, - userDataEncrypted - ) - - //adjust to useable format - UserData = new TextDecoder().decode(UserData) - UserData = UserData.split("@@@@@") - resolve({ asdf: UserData[0], fdsa: UserData[1] }) - }) - }) +// check if username, password exist +function userDataExists () { + return new Promise(async (resolve, reject) => { + const userData = await getUserData() + if (userData.asdf === undefined || userData.fdsa === undefined) { + resolve(false) + return + } + resolve(true) + }) } -//////////////// END FUNCTIONS FOR ENCRYPTION AND USERDATA HANDLING //////////////// - -//save parsed courses -//course_list = {type:"", list:[{link:link, name: name}, ...]} -function saveCourses(course_list) { - course_list.list.sort((a, b) => (a.name > b.name) ? 1 : -1) - switch (course_list.type) { - case 'favoriten': - chrome.storage.local.set({ favoriten: JSON.stringify(course_list.list) }, function () { }) - console.log('saved Favoriten in TUfast') - break - case 'meine_kurse': - chrome.storage.local.set({ meine_kurse: JSON.stringify(course_list.list) }, function () { }) - console.log('saved Meine Kurse in TUfast') - break - default: - break - } +// return {asdf: "", fdsa: ""} +// decrypt and return user data +// a lot of encoding and transforming needs to be done, in order to provide all values in the right format +async function getUserData () { + return new Promise(async (resolve, reject) => { + // get required data for decryption + const keyBuffer = await getKeyBuffer() + chrome.storage.local.get(['Data'], async (Data) => { + // check if Data exists, else return + if (Data.Data === undefined || Data.Data === 'undefined' || Data.Data === null) { + resolve({ asdf: undefined, fdsa: undefined }) + return + } + let iv = await Data.Data.slice(0, 32).match(/.{2}/g).map(byte => parseInt(byte, 16)) + iv = new Uint8Array(iv) + let userDataEncrypted = atob(Data.Data.slice(32)) + userDataEncrypted = new Uint8Array(userDataEncrypted.match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) + + // decrypt + let UserData = await crypto.subtle.decrypt( + { + name: 'AES-CBC', + iv: iv + }, + keyBuffer, + userDataEncrypted + ) + + // adjust to useable format + UserData = new TextDecoder().decode(UserData) + UserData = UserData.split('@@@@@') + resolve({ asdf: UserData[0], fdsa: UserData[1] }) + }) + }) } -//get parsed courses -//return course_list = [{link:link, name: name}, ...] -function loadCourses(type) { - switch (type) { - case "favoriten": - chrome.storage.local.get(['favoriten'], function (result) { - console.log(JSON.parse(result.favoriten)) - }) - break - case "meine_kurse": - chrome.storage.local.get(['meine_kurse'], function (result) { - console.log(JSON.parse(result.meine_kurse)) - }) - break - default: - break - } +/// ///////////// END FUNCTIONS FOR ENCRYPTION AND USERDATA HANDLING //////////////// + +// save parsed courses +// course_list = {type:"", list:[{link:link, name: name}, ...]} +function saveCourses (courseList) { + courseList.list.sort((a, b) => (a.name > b.name) ? 1 : -1) + switch (courseList.type) { + case 'favoriten': + chrome.storage.local.set({ favoriten: JSON.stringify(courseList.list) }, function () { }) + console.log('saved Favoriten in TUfast') + break + case 'meine_kurse': + chrome.storage.local.set({ meine_kurse: JSON.stringify(courseList.list) }, function () { }) + console.log('saved Meine Kurse in TUfast') + break + default: + break + } } -//function for custom URIEncoding -function customURIEncoding(string) { - string = encodeURIComponent(string) - string = string.replace("!", "%21").replace("'", "%27").replace("(", "%28").replace(")", "%29").replace("~", "%7E") - return string +// get parsed courses +// return course_list = [{link:link, name: name}, ...] +// function loadCourses (type) { +// switch (type) { +// case 'favoriten': +// chrome.storage.local.get(['favoriten'], function (result) { +// console.log(JSON.parse(result.favoriten)) +// }) +// break +// case 'meine_kurse': +// chrome.storage.local.get(['meine_kurse'], function (result) { +// console.log(JSON.parse(result.meine_kurse)) +// }) +// break +// default: +// break +// } +// } + +// function for custom URIEncoding +function customURIEncoding (string) { + string = encodeURIComponent(string) + string = string.replace('!', '%21').replace("'", '%27').replace('(', '%28').replace(')', '%29').replace('~', '%7E') + return string } -//function to log msx.tu-dresden.de/owa/ and retrieve the .json containing information about EMails -function fetchOWA(username, password, logout) { - return new Promise((resolve, reject) => { - - //encodeURIComponent and encodeURI are not working for all chars. See documentation. Thats why I implemented custom encoding. - username = customURIEncoding(username) - password = customURIEncoding(password) - - var mailInfoJson = new Object() //contains all required info - - //login - fetch("https://msx.tu-dresden.de/owa/auth.owa", { - "headers": { - "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", - "accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5", - "cache-control": "max-age=0", - "content-type": "application/x-www-form-urlencoded", - "Access-Control-Allow-Origin": "*", - "sec-fetch-dest": "document", - "sec-fetch-mode": "navigate", - "sec-fetch-site": "same-origin", - "sec-fetch-user": "?1", - "upgrade-insecure-requests": "1" - }, - "referrer": "https://msx.tu-dresden.de/owa/auth/logon.aspx?replaceCurrent=1&url=https%3a%2f%2fmsx.tu-dresden.de%2fowa%2f%23authRedirect%3dtrue", - "referrerPolicy": "strict-origin-when-cross-origin", - "Access-Control-Allow-Origin": "*", - "body": "destination=https%3A%2F%2Fmsx.tu-dresden.de%2Fowa%2F%23authRedirect%3Dtrue&flags=4&forcedownlevel=0&username=" + username + "%40msx.tu-dresden.de&password=" + password + "&passwordText=&isUtf8=1", - "method": "POST", - "mode": "no-cors", - "credentials": "include" - }) - .then(() => { - //get clientID and correlationID - fetch("https://msx.tu-dresden.de/owa/", { - "headers": { - "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", - "accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5", - "cache-control": "max-age=0", - "sec-fetch-dest": "document", - "sec-fetch-mode": "navigate", - "Access-Control-Allow-Origin": "*", - "sec-fetch-site": "same-origin", - "sec-fetch-user": "?1", - "upgrade-insecure-requests": "1" - }, - "referrer": "https://msx.tu-dresden.de/owa/auth/logon.aspx?replaceCurrent=1&url=https%3a%2f%2fmsx.tu-dresden.de%2fowa", - "referrerPolicy": "strict-origin-when-cross-origin", - "body": null, - "method": "GET", - "Access-Control-Allow-Origin": "*", - "mode": "cors", - "credentials": "include" - }) - //extract x-owa-correlationid. correlation id is - .then(resp => resp.text()).then(respText => { - let temp = respText.split("window.clientId = '")[1] - let clientId = temp.split("'")[0] - let corrId = clientId + "_" + (new Date()).getTime() - console.log("corrID: " + corrId) - }) - //getAllInfo - .then(corrId => { - fetch("https://msx.tu-dresden.de/owa/sessiondata.ashx?appcacheclient=0", { - "headers": { - "accept": "*/*", - "accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5", - "sec-fetch-dest": "empty", - "sec-fetch-mode": "cors", - "Access-Control-Allow-Origin": "*", - "sec-fetch-site": "same-origin", - "x-owa-correlationid": corrId, - "x-owa-smimeinstalled": "1" - }, - "referrer": "https://msx.tu-dresden.de/owa/", - "referrerPolicy": "strict-origin-when-cross-origin", - "Access-Control-Allow-Origin": "*", - "body": null, - "method": "POST", - "mode": "cors", - "credentials": "include" - }) - .then(resp => resp.json()).then(respJson => { - mailInfoJson = respJson - }) - //logout - .then(() => { - //only logout, if user is not using owa in browser session - if (logout) { - console.log("Logging out from owa..") - fetch("https://msx.tu-dresden.de/owa/logoff.owa", { - "headers": { - "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", - "accept-language": "de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5", - "sec-fetch-dest": "document", - "Access-Control-Allow-Origin": "*", - "sec-fetch-mode": "navigate", - "sec-fetch-site": "same-origin", - "sec-fetch-user": "?1", - "upgrade-insecure-requests": "1" - }, - "referrer": "https://msx.tu-dresden.de/owa/", - "referrerPolicy": "strict-origin-when-cross-origin", - "Access-Control-Allow-Origin": "*", - "body": null, - "method": "GET", - "mode": "cors", - "credentials": "include" - }) - } - }) - .then(() => resolve(mailInfoJson)) - }) - }) - }) +// function to log msx.tu-dresden.de/owa/ and retrieve the .json containing information about EMails +function fetchOWA (username, password, logout) { + return new Promise((resolve, reject) => { + // encodeURIComponent and encodeURI are not working for all chars. See documentation. Thats why I implemented custom encoding. + username = customURIEncoding(username) + password = customURIEncoding(password) + + // eslint-disable-next-line no-new-object + let mailInfoJson = new Object() // contains all required info + + // login + fetch('https://msx.tu-dresden.de/owa/auth.owa', { + headers: { + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'accept-language': 'de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5', + 'cache-control': 'max-age=0', + 'content-type': 'application/x-www-form-urlencoded', + 'Access-Control-Allow-Origin': '*', + 'sec-fetch-dest': 'document', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-site': 'same-origin', + 'sec-fetch-user': '?1', + 'upgrade-insecure-requests': '1' + }, + referrer: 'https://msx.tu-dresden.de/owa/auth/logon.aspx?replaceCurrent=1&url=https%3a%2f%2fmsx.tu-dresden.de%2fowa%2f%23authRedirect%3dtrue', + referrerPolicy: 'strict-origin-when-cross-origin', + 'Access-Control-Allow-Origin': '*', + body: 'destination=https%3A%2F%2Fmsx.tu-dresden.de%2Fowa%2F%23authRedirect%3Dtrue&flags=4&forcedownlevel=0&username=' + username + '%40msx.tu-dresden.de&password=' + password + '&passwordText=&isUtf8=1', + method: 'POST', + mode: 'no-cors', + credentials: 'include' + }) + .then(() => { + // get clientID and correlationID + fetch('https://msx.tu-dresden.de/owa/', { + headers: { + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'accept-language': 'de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5', + 'cache-control': 'max-age=0', + 'sec-fetch-dest': 'document', + 'sec-fetch-mode': 'navigate', + 'Access-Control-Allow-Origin': '*', + 'sec-fetch-site': 'same-origin', + 'sec-fetch-user': '?1', + 'upgrade-insecure-requests': '1' + }, + referrer: 'https://msx.tu-dresden.de/owa/auth/logon.aspx?replaceCurrent=1&url=https%3a%2f%2fmsx.tu-dresden.de%2fowa', + referrerPolicy: 'strict-origin-when-cross-origin', + body: null, + method: 'GET', + 'Access-Control-Allow-Origin': '*', + mode: 'cors', + credentials: 'include' + }) + // extract x-owa-correlationid. correlation id is + .then(resp => resp.text()).then(respText => { + const temp = respText.split("window.clientId = '")[1] + const clientId = temp.split("'")[0] + const corrId = clientId + '_' + (new Date()).getTime() + console.log('corrID: ' + corrId) + }) + // getAllInfo + .then(corrId => { + fetch('https://msx.tu-dresden.de/owa/sessiondata.ashx?appcacheclient=0', { + headers: { + accept: '*/*', + 'accept-language': 'de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5', + 'sec-fetch-dest': 'empty', + 'sec-fetch-mode': 'cors', + 'Access-Control-Allow-Origin': '*', + 'sec-fetch-site': 'same-origin', + 'x-owa-correlationid': corrId, + 'x-owa-smimeinstalled': '1' + }, + referrer: 'https://msx.tu-dresden.de/owa/', + referrerPolicy: 'strict-origin-when-cross-origin', + 'Access-Control-Allow-Origin': '*', + body: null, + method: 'POST', + mode: 'cors', + credentials: 'include' + }) + .then(resp => resp.json()).then(respJson => { + mailInfoJson = respJson + }) + // logout + .then(() => { + // only logout, if user is not using owa in browser session + if (logout) { + console.log('Logging out from owa..') + fetch('https://msx.tu-dresden.de/owa/logoff.owa', { + headers: { + accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9', + 'accept-language': 'de-DE,de;q=0.9,en-DE;q=0.8,en-GB;q=0.7,en-US;q=0.6,en;q=0.5', + 'sec-fetch-dest': 'document', + 'Access-Control-Allow-Origin': '*', + 'sec-fetch-mode': 'navigate', + 'sec-fetch-site': 'same-origin', + 'sec-fetch-user': '?1', + 'upgrade-insecure-requests': '1' + }, + referrer: 'https://msx.tu-dresden.de/owa/', + referrerPolicy: 'strict-origin-when-cross-origin', + 'Access-Control-Allow-Origin': '*', + body: null, + method: 'GET', + mode: 'cors', + credentials: 'include' + }) + } + }) + .then(() => resolve(mailInfoJson)) + }) + }) + }) } -//extract number of unread messages in owa -function countUnreadMsg(json) { - return new Promise((resolve, reject) => { - json.findFolders.Body.ResponseMessages.Items[0].RootFolder.Folders.forEach(obj => { - if (obj.DisplayName === "Inbox" || obj.DisplayName === "Posteingang") resolve(obj.UnreadCount) - }) - }) +// extract number of unread messages in owa +function countUnreadMsg (json) { + return new Promise((resolve, reject) => { + json.findFolders.Body.ResponseMessages.Items[0].RootFolder.Folders.forEach(obj => { + if (obj.DisplayName === 'Inbox' || obj.DisplayName === 'Posteingang') resolve(obj.UnreadCount) + }) + }) } diff --git a/src/contentScripts/bildungsportal.js b/src/contentScripts/bildungsportal.js index c4e18468..7b17995f 100644 --- a/src/contentScripts/bildungsportal.js +++ b/src/contentScripts/bildungsportal.js @@ -1,30 +1,30 @@ chrome.storage.local.get(['isEnabled', 'loggedOutOpal'], function (result) { - if (/*result.isEnabled &&*/ !(result.loggedOutOpal)) { - //when pop-up shows - document.addEventListener("DOMNodeInserted", function (e) { - //select TU Dresden from selector - if (document.getElementsByName("content:container:login:shibAuthForm:wayfselection")[0]) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - let selectionList = document.getElementsByName("content:container:login:shibAuthForm:wayfselection")[0] - for (let el of selectionList) { - if (el.textContent === "TU Dresden" || el.textContent === "Technsiche Universität Dresden") { - document.getElementsByName("content:container:login:shibAuthForm:wayfselection")[0].value = el.value + if (/* result.isEnabled && */ !(result.loggedOutOpal)) { + // when pop-up shows + document.addEventListener('DOMNodeInserted', function (e) { + // select TU Dresden from selector + if (document.getElementsByName('content:container:login:shibAuthForm:wayfselection')[0]) { + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + const selectionList = document.getElementsByName('content:container:login:shibAuthForm:wayfselection')[0] + for (const el of selectionList) { + if (el.textContent === 'TU Dresden' || el.textContent === 'Technsiche Universität Dresden') { + document.getElementsByName('content:container:login:shibAuthForm:wayfselection')[0].value = el.value } } } - //submit selected - if (document.getElementsByName("content:container:login:shibAuthForm:shibLogin")[0]) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 4000 }) - document.getElementsByName("content:container:login:shibAuthForm:shibLogin")[0].click() + // submit selected + if (document.getElementsByName('content:container:login:shibAuthForm:shibLogin')[0]) { + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 4000 }) + document.getElementsByName('content:container:login:shibAuthForm:shibLogin')[0].click() } - }, false); + }, false) - //start login process - window.addEventListener("load", function () { + // start login process + window.addEventListener('load', function () { if (document.getElementsByClassName('btn btn-sm')[1].innerText.includes('Login')) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 4000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 4000 }) document.getElementsByClassName('btn btn-sm')[1].click() } }, true) diff --git a/src/contentScripts/bildungsportal_insertLogo.js b/src/contentScripts/bildungsportal_insertLogo.js index 7c84940c..78a74cd5 100644 --- a/src/contentScripts/bildungsportal_insertLogo.js +++ b/src/contentScripts/bildungsportal_insertLogo.js @@ -1,320 +1,313 @@ /* { selectedRocketIcon: '{"id": "RI_default", "link": "RocketIcons/default_128px"}' } */ -chrome.storage.local.get(['isEnabled', 'fwdEnabled', 'PRObadge', 'flakeState', "selectedRocketIcon", "foundEasteregg"], function (result) { - if (result.isEnabled || result.fwdEnabled) { - //parse selectedRocketIcon - let selectedRocketIcon = JSON.parse(result.selectedRocketIcon) - - //decide which overlay to show - let christmasTime = false - let d = new Date() - let month = d.getMonth() + 1 //starts at 0 - let day = d.getDate() - if (month === 12 && day > 15 && day < 27) christmasTime = true - - //switch flakeState to false in november - if (month === 11) chrome.storage.local.set({ flakeState: false }, function () { }) - - if (christmasTime) { - //on load - document.addEventListener("DOMNodeInserted", function (e) { - if (!document.getElementById("flake")) insertFlakeSwitch(result.flakeState) - }) - //on document changes - window.addEventListener("load", function () { - if (!document.getElementById("flake")) insertFlakeSwitch(result.flakeState) - if (!document.getElementById("snowflakes") && result.flakeState) insertFlakes() - }, true) - //standard rocket logo - } else { - //on load - document.addEventListener("DOMNodeInserted", function (e) { - if (!document.getElementById("TUFastLogo")) { insertRocket(selectedRocketIcon, result.PRObadge, result.foundEasteregg) } - }) - //on document changes - window.addEventListener("load", function () { - if (!document.getElementById("TUFastLogo")) { insertRocket(selectedRocketIcon, result.PRObadge, result.foundEasteregg) } - }, true) - } +chrome.storage.local.get(['isEnabled', 'fwdEnabled', 'PRObadge', 'flakeState', 'selectedRocketIcon', 'foundEasteregg'], function (result) { + if (result.isEnabled || result.fwdEnabled) { + // parse selectedRocketIcon + const selectedRocketIcon = JSON.parse(result.selectedRocketIcon) + + // decide which overlay to show + let christmasTime = false + const d = new Date() + const month = d.getMonth() + 1 // starts at 0 + const day = d.getDate() + if (month === 12 && day > 15 && day < 27) christmasTime = true + + // switch flakeState to false in november + if (month === 11) chrome.storage.local.set({ flakeState: false }, function () { }) + + if (christmasTime) { + // on load + document.addEventListener('DOMNodeInserted', function (e) { + if (!document.getElementById('flake')) insertFlakeSwitch(result.flakeState) + }) + // on document changes + window.addEventListener('load', function () { + if (!document.getElementById('flake')) insertFlakeSwitch(result.flakeState) + if (!document.getElementById('snowflakes') && result.flakeState) insertFlakes() + }, true) + // standard rocket logo + } else { + // on load + document.addEventListener('DOMNodeInserted', function (e) { + if (!document.getElementById('TUFastLogo')) { insertRocket(selectedRocketIcon, result.PRObadge, result.foundEasteregg) } + }) + // on document changes + window.addEventListener('load', function () { + if (!document.getElementById('TUFastLogo')) { insertRocket(selectedRocketIcon, result.PRObadge, result.foundEasteregg) } + }, true) } + } }) // variables required for rocket logo easteregg -var GLOBAL_counter = 0 //count clicks on icon -var coutdownRemoveScreenOverlay //timer -var timeout = 1000 //timeout for timer -var blocker = false //block icon click -var timeUp = true //true, when time is up -var display_value //number of text, which shows on screen -var typeOfMsg = "" //type of message which is displayed - -function updateRocketLogo(iconPath) { - let timestamp = new Date().getTime(); - chrome.runtime.sendMessage({ cmd: 'update_rocket_logo_easteregg'}, function (result) { }) - document.querySelectorAll("#TUFastLogo img")[0].src = chrome.runtime.getURL("" + iconPath) + "?t =" + timestamp; -} - -function setProBadge() { - document.getElementById("TUFastLogo").parentNode.removeChild(document.getElementById("TUFastLogo")) - chrome.storage.local.set({ PRObadge: "PRO" }, function () { }) - insertRocket("colorful", "PRO") +let globalCounter = 0 // count clicks on icon +let coutdownRemoveScreenOverlay // timer +let timeout = 1000 // timeout for timer +let blocker = false // block icon click +let timeUp = true // true, when time is up +let displayValue // number of text, which shows on screen +let typeOfMsg = '' // type of message which is displayed + +function updateRocketLogo (iconPath) { + const timestamp = new Date().getTime() + chrome.runtime.sendMessage({ cmd: 'update_rocket_logo_easteregg' }, function (result) { }) + document.querySelectorAll('#TUFastLogo img')[0].src = chrome.runtime.getURL('' + iconPath) + '?t =' + timestamp } -function insertScreenOverlay() { - try { - if (!document.getElementById('counter')) { - let body = document.getElementsByTagName("body")[0] - let counter = document.createElement("div") - let container = document.createElement("div") - container.style.position = "relative" - counter.id = "counter" - counter.style.opacity = "1" - counter.style.fontSize = "150px" - counter.style.position = 'absolute' - counter.style.color = "#000000" - counter.style.top = "50%" - counter.style.left = "50%" - counter.style.marginRight = "-50%" - counter.style.transform = "translate(-50%, -50%)" - counter.style.zIndex = "99" - - container.appendChild(counter) - body.prepend(counter) - } - } catch (e) { console.log("cannot insert overlay:" + e) } -} - -async function logoOnClickEasteregg() { - - //block counting up when text is promted - if (blocker && !timeUp) return - - GLOBAL_counter++ +// function setProBadge() { +// document.getElementById('TUFastLogo').parentNode.removeChild(document.getElementById('TUFastLogo')) +// chrome.storage.local.set({ PRObadge: 'PRO' }, function () { }) +// insertRocket('colorful', 'PRO') +// } - //show screen overlay +function insertScreenOverlay () { + try { if (!document.getElementById('counter')) { - //insert overlay - insertScreenOverlay() - } else { - //remove existing timeout - clearTimeout(coutdownRemoveScreenOverlay) + const body = document.getElementsByTagName('body')[0] + const counter = document.createElement('div') + const container = document.createElement('div') + container.style.position = 'relative' + counter.id = 'counter' + counter.style.opacity = '1' + counter.style.fontSize = '150px' + counter.style.position = 'absolute' + counter.style.color = '#000000' + counter.style.top = '50%' + counter.style.left = '50%' + counter.style.marginRight = '-50%' + counter.style.transform = 'translate(-50%, -50%)' + counter.style.zIndex = '99' + + container.appendChild(counter) + body.prepend(counter) } + } catch (e) { console.log('cannot insert overlay:' + e) } +} +async function logoOnClickEasteregg () { + // block counting up when text is promted + if (blocker && !timeUp) return + + globalCounter++ + + // show screen overlay + if (!document.getElementById('counter')) { + // insert overlay + insertScreenOverlay() + } else { + // remove existing timeout + clearTimeout(coutdownRemoveScreenOverlay) + } + + let counter = document.getElementById('counter') + counter.style.color = funnyColor(counter.style.color, 80) + + // trigger actions based on counter + switch (globalCounter) { + case 10: + // easteregg finished + displayValue = '🚀 🚀 🚀' + typeOfMsg = 'text' + // enable rocketIcon, set selected rocketIcon (RI3) + chrome.storage.local.set({ foundEasteregg: true }, function () { }) + chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI3", "link": "../assets/icons/RocketIcons/7_128px.png"}' }, function () { }) + chrome.storage.local.get(['availableRockets'], (resp) => { + const avRockets = resp.availableRockets + avRockets.push('RI3') + chrome.storage.local.set({ availableRockets: avRockets }) + }) + // live-update the logo + updateRocketLogo('../assets/icons/RocketIcons/7_128px.png') + // change the onclick function + document.getElementById('TUFastLogo').onclick = logoOnClick + break + default: + typeOfMsg = 'number' + displayValue = globalCounter + } + + // decide how to show text + switch (typeOfMsg) { + case 'number': + timeout = 1000 + blocker = false + counter.style.fontSize = '150px' + break + case 'text': + counter.style.fontSize = '100px' + timeout = 3000 + blocker = true + break + default: + // same as number + timeout = 1000 + blocker = false + counter.style.fontSize = '150px' + } + + // populate screen overlay with value + counter.innerHTML = displayValue + + timeUp = false + + coutdownRemoveScreenOverlay = setTimeout(function () { counter = document.getElementById('counter') - counter.style.color = funnyColor(counter.style.color, 80) - - //trigger actions based on counter - switch (GLOBAL_counter) { - case 10: - //easteregg finished - display_value = "🚀 🚀 🚀" - typeOfMsg = "text" - //enable rocketIcon, set selected rocketIcon (RI3) - chrome.storage.local.set({ foundEasteregg: true }, function () { }) - chrome.storage.local.set({ selectedRocketIcon: '{"id": "RI3", "link": "../assets/icons/RocketIcons/7_128px.png"}' }, function () { }) - chrome.storage.local.get(["availableRockets"], (resp) => { - let avRockets = resp.availableRockets - avRockets.push("RI3") - chrome.storage.local.set({ "availableRockets": avRockets }) - }) - //live-update the logo - updateRocketLogo("../assets/icons/RocketIcons/7_128px.png") - //change the onclick function - document.getElementById("TUFastLogo").onclick = logoOnClick - break - default: - typeOfMsg = "number" - display_value = GLOBAL_counter - } - - //decide how to show text - switch (typeOfMsg) { - case "number": - timeout = 1000 - blocker = false - counter.style.fontSize = "150px" - break - case "text": - counter.style.fontSize = "100px" - timeout = 3000 - blocker = true - break - default: - //same as number - timeout = 1000 - blocker = false - counter.style.fontSize = "150px" - } - - //populate screen overlay with value - counter.innerHTML = display_value - - timeUp = false - - coutdownRemoveScreenOverlay = setTimeout(function () { - counter = document.getElementById('counter') - counter.parentNode.removeChild(counter) - timeUp = true - }, timeout) + counter.parentNode.removeChild(counter) + timeUp = true + }, timeout) } -function logoOnClick() { - console.log("here") - if (timeUp) chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'rocket_icons_settings' }, function (result) { }) +function logoOnClick () { + console.log('here') + if (timeUp) chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'rocket_icons_settings' }, function (result) { }) } -function funnyColor(color, step) { - rgb = color.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) - rgb[1] = parseInt(rgb[1]) - rgb[2] = parseInt(rgb[2]) - rgb[3] = parseInt(rgb[3]) - if (rgb[1] < 255 - step && rgb[2] < 255 - step && rgb[3] < 150 - step) rgb[1] += step - else if (rgb[2] < 255 - step && rgb[3] < 150 - step) rgb[2] += step - else if (rgb[3] < 150 - step) rgb[3] += step - else if (rgb[1] > 0 + step) rgb[1] -= step - else if (rgb[2] > 0 + step) rgb[2] -= step - else if (rgb[3] > 0 + step) rgb[3] -= step - color = "rgb(" + rgb[1] + "," + rgb[2] + "," + rgb[3] + ")" - return color; +function funnyColor (color, step) { + const rgb = color.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/) + rgb[1] = parseInt(rgb[1]) + rgb[2] = parseInt(rgb[2]) + rgb[3] = parseInt(rgb[3]) + if (rgb[1] < 255 - step && rgb[2] < 255 - step && rgb[3] < 150 - step) rgb[1] += step + else if (rgb[2] < 255 - step && rgb[3] < 150 - step) rgb[2] += step + else if (rgb[3] < 150 - step) rgb[3] += step + else if (rgb[1] > 0 + step) rgb[1] -= step + else if (rgb[2] > 0 + step) rgb[2] -= step + else if (rgb[3] > 0 + step) rgb[3] -= step + color = 'rgb(' + rgb[1] + ',' + rgb[2] + ',' + rgb[3] + ')' + return color }; -function insertRocket(selectedRocketIcon, PRObadge = false, foundEasteregg) { - let imgUrl, header, logo_node, logo_link, logo_img, badge - try { - if (document.getElementsByClassName("page-header")[0] != undefined) { - header = document.getElementsByClassName("page-header")[0] - logo_node = document.createElement("h1") - logo_link = document.createElement("a") - logo_img = document.createElement("img") - logo_link.href = "javascript:void(0)" - logo_node.id = "TUFastLogo" - logo_link.title = "powered by TUFast. Enjoy :)" - - //onclick function depends on whether easteregg was already found! - if (foundEasteregg) { - logo_node.onclick = logoOnClick - } else { - logo_node.onclick = logoOnClickEasteregg - } - - //create rocket icon - imgUrl = chrome.runtime.getURL("../" + selectedRocketIcon.link) - logo_img.style.display = "inline-block" - logo_img.style.width = "37px" - logo_img.src = imgUrl - logo_link.appendChild(logo_img) - - //add badge - switch (PRObadge) { - case "PRO": - logo_link.style.position = "relative" - badge = document.createElement("span") - badge.classList.add("badge") - badge.innerHTML = "PRO" - badge.style.fontSize = "0.3em" - badge.style.position = "absolute" - badge.style.bottom = "0px" - badge.style.left = "20px" - logo_link.appendChild(badge) - break - default: - break - } - - //append to header - logo_node.appendChild(logo_link) - header.append(logo_node) - } - } - catch (e) { - console.log("Error inserting logo: " + e) - } -} - +function insertRocket (selectedRocketIcon, PRObadge = false, foundEasteregg) { + let imgUrl, header, logoNode, logoLink, logoImg, badge + try { + if (document.getElementsByClassName('page-header')[0] !== undefined) { + header = document.getElementsByClassName('page-header')[0] + logoNode = document.createElement('h1') + logoLink = document.createElement('a') + logoImg = document.createElement('img') + logoLink.href = 'javascript:void(0)' + logoNode.id = 'TUFastLogo' + logoLink.title = 'powered by TUFast. Enjoy :)' + + // onclick function depends on whether easteregg was already found! + if (foundEasteregg) { + logoNode.onclick = logoOnClick + } else { + logoNode.onclick = logoOnClickEasteregg + } + + // create rocket icon + imgUrl = chrome.runtime.getURL('../' + selectedRocketIcon.link) + logoImg.style.display = 'inline-block' + logoImg.style.width = '37px' + logoImg.src = imgUrl + logoLink.appendChild(logoImg) + + // add badge + switch (PRObadge) { + case 'PRO': + logoLink.style.position = 'relative' + badge = document.createElement('span') + badge.classList.add('badge') + badge.innerHTML = 'PRO' + badge.style.fontSize = '0.3em' + badge.style.position = 'absolute' + badge.style.bottom = '0px' + badge.style.left = '20px' + logoLink.appendChild(badge) + break + default: + break + } -//toggle flake state -function flakesSwitchOnClick() { - chrome.storage.local.get(['flakeState'], function (result) { - chrome.storage.local.set({ flakeState: !(result.flakeState) }, function () { }) - //careful: this has to be negated, as its toggled - if (!result.flakeState) { - document.getElementById("flakeLink").style.color = "black" - insertFlakes() - } - else if (result.flakeState) { - document.getElementById("flakeLink").style.color = "Grey" - removeFlakes() - } - }) + // append to header + logoNode.appendChild(logoLink) + header.append(logoNode) + } + } catch (e) { + console.log('Error inserting logo: ' + e) + } } -function removeFlakes() { - try { - document.getElementById("snowflakes").parentNode.removeChild(document.getElementById("snowflakes")) - } catch (e) { console.log("No snowflakes!: " + e) } +// toggle flake state +function flakesSwitchOnClick () { + chrome.storage.local.get(['flakeState'], function (result) { + chrome.storage.local.set({ flakeState: !(result.flakeState) }, function () { }) + // careful: this has to be negated, as its toggled + if (!result.flakeState) { + document.getElementById('flakeLink').style.color = 'black' + insertFlakes() + } else if (result.flakeState) { + document.getElementById('flakeLink').style.color = 'Grey' + removeFlakes() + } + }) } -function insertFlakes() { - try { - if (!document.getElementById("snowflakes")) { - //create snowflake css - let snowflakeCss = ".snowflake {color: #fff;font-size: 1em;font-family: Arial, sans-serif;text-shadow: 0 0 5px #000;}@-webkit-keyframes snowflakes-fall{0%{top:-10%}100%{top:100%}}@-webkit-keyframes snowflakes-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(80px);transform:translateX(80px)}}@keyframes snowflakes-fall{0%{top:-10%}100%{top:100%}}@keyframes snowflakes-shake{0%,100%{transform:translateX(0)}50%{transform:translateX(80px)}}.snowflake{position:fixed;top:-10%;z-index:9999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default;-webkit-animation-name:snowflakes-fall,snowflakes-shake;-webkit-animation-duration:10s,3s;-webkit-animation-timing-function:linear,ease-in-out;-webkit-animation-iteration-count:infinite,infinite;-webkit-animation-play-state:running,running;animation-name:snowflakes-fall,snowflakes-shake;animation-duration:10s,3s;animation-timing-function:linear,ease-in-out;animation-iteration-count:infinite,infinite;animation-play-state:running,running}.snowflake:nth-of-type(0){left:1%;-webkit-animation-delay:0s,0s;animation-delay:0s,0s}.snowflake:nth-of-type(1){left:10%;-webkit-animation-delay:1s,1s;animation-delay:1s,1s}.snowflake:nth-of-type(2){left:20%;-webkit-animation-delay:6s,.5s;animation-delay:6s,.5s}.snowflake:nth-of-type(3){left:30%;-webkit-animation-delay:4s,2s;animation-delay:4s,2s}.snowflake:nth-of-type(4){left:40%;-webkit-animation-delay:2s,2s;animation-delay:2s,2s}.snowflake:nth-of-type(5){left:50%;-webkit-animation-delay:8s,3s;animation-delay:8s,3s}.snowflake:nth-of-type(6){left:60%;-webkit-animation-delay:6s,2s;animation-delay:6s,2s}.snowflake:nth-of-type(7){left:70%;-webkit-animation-delay:2.5s,1s;animation-delay:2.5s,1s}.snowflake:nth-of-type(8){left:80%;-webkit-animation-delay:1s,0s;animation-delay:1s,0s}.snowflake:nth-of-type(9){left:90%;-webkit-animation-delay:3s,1.5s;animation-delay:3s,1.5s}.snowflake:nth-of-type(10){left:25%;-webkit-animation-delay:2s,0s;animation-delay:2s,0s}.snowflake:nth-of-type(11){left:65%;-webkit-animation-delay:4s,2.5s;animation-delay:4s,2.5s}" - let snowflakeStyle = document.createElement('style') - - //add css to snowflage tag - if (snowflakeStyle.styleSheet) { - snowflakeStyle.styleSheet.cssText = snowflakeCss; - } else { - snowflakeStyle.appendChild(document.createTextNode(snowflakeCss)); - } - - //add snowflage style tag to website head - document.getElementsByTagName("Head")[0].appendChild(snowflakeStyle) - - //create snowflake div - let snowflakes = document.createElement("div") - snowflakes.classList.add("snowflakes") - snowflakes.id = "snowflakes" - snowflakes.setAttribute('aria-hidden', 'true'); - snowflakes.innerHTML = '
' - - //add snowflake div to website body - document.getElementsByTagName("Body")[0].prepend(snowflakes) - } - } catch (e) { console.log("cannot insert snowFlakes: " + e) } +function removeFlakes () { + try { + document.getElementById('snowflakes').parentNode.removeChild(document.getElementById('snowflakes')) + } catch (e) { console.log('No snowflakes!: ' + e) } } -function insertFlakeSwitch(currentlyActivated) { - if (currentlyActivated === undefined) currentlyActivated = true - try { - if (document.getElementsByClassName("page-header")[0] != undefined) { - header = document.getElementsByClassName("page-header")[0] - flake = document.createElement("h1") - flake_link = document.createElement("a") - flake_link.id = "flakeLink" - flake_link.style.textDecoration = "none" - flake_link.href = "javascript:void(0)" - flake.id = "flake" - flake_link.title = "Click me. Winter powered by TUfast." - flake.onclick = flakesSwitchOnClick - flake.style.paddingTop = "2px" - flake.style.paddingLeft = "3px" - - if (currentlyActivated) flake_link.style.color = "black" - if (!currentlyActivated) flake_link.style.color = "Grey" - - - flake_link.innerHTML = "❅" - flake_link.fontSize = "30px" - - //append to header - flake.appendChild(flake_link) - header.append(flake) - } - } - catch (e) { - console.log("Error inserting flakeSwitch: " + e) +function insertFlakes () { + try { + if (!document.getElementById('snowflakes')) { + // create snowflake css + const snowflakeCss = '.snowflake {color: #fff;font-size: 1em;font-family: Arial, sans-serif;text-shadow: 0 0 5px #000;}@-webkit-keyframes snowflakes-fall{0%{top:-10%}100%{top:100%}}@-webkit-keyframes snowflakes-shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}50%{-webkit-transform:translateX(80px);transform:translateX(80px)}}@keyframes snowflakes-fall{0%{top:-10%}100%{top:100%}}@keyframes snowflakes-shake{0%,100%{transform:translateX(0)}50%{transform:translateX(80px)}}.snowflake{position:fixed;top:-10%;z-index:9999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default;-webkit-animation-name:snowflakes-fall,snowflakes-shake;-webkit-animation-duration:10s,3s;-webkit-animation-timing-function:linear,ease-in-out;-webkit-animation-iteration-count:infinite,infinite;-webkit-animation-play-state:running,running;animation-name:snowflakes-fall,snowflakes-shake;animation-duration:10s,3s;animation-timing-function:linear,ease-in-out;animation-iteration-count:infinite,infinite;animation-play-state:running,running}.snowflake:nth-of-type(0){left:1%;-webkit-animation-delay:0s,0s;animation-delay:0s,0s}.snowflake:nth-of-type(1){left:10%;-webkit-animation-delay:1s,1s;animation-delay:1s,1s}.snowflake:nth-of-type(2){left:20%;-webkit-animation-delay:6s,.5s;animation-delay:6s,.5s}.snowflake:nth-of-type(3){left:30%;-webkit-animation-delay:4s,2s;animation-delay:4s,2s}.snowflake:nth-of-type(4){left:40%;-webkit-animation-delay:2s,2s;animation-delay:2s,2s}.snowflake:nth-of-type(5){left:50%;-webkit-animation-delay:8s,3s;animation-delay:8s,3s}.snowflake:nth-of-type(6){left:60%;-webkit-animation-delay:6s,2s;animation-delay:6s,2s}.snowflake:nth-of-type(7){left:70%;-webkit-animation-delay:2.5s,1s;animation-delay:2.5s,1s}.snowflake:nth-of-type(8){left:80%;-webkit-animation-delay:1s,0s;animation-delay:1s,0s}.snowflake:nth-of-type(9){left:90%;-webkit-animation-delay:3s,1.5s;animation-delay:3s,1.5s}.snowflake:nth-of-type(10){left:25%;-webkit-animation-delay:2s,0s;animation-delay:2s,0s}.snowflake:nth-of-type(11){left:65%;-webkit-animation-delay:4s,2.5s;animation-delay:4s,2.5s}' + const snowflakeStyle = document.createElement('style') + + // add css to snowflage tag + if (snowflakeStyle.styleSheet) { + snowflakeStyle.styleSheet.cssText = snowflakeCss + } else { + snowflakeStyle.appendChild(document.createTextNode(snowflakeCss)) + } + + // add snowflage style tag to website head + document.getElementsByTagName('Head')[0].appendChild(snowflakeStyle) + + // create snowflake div + const snowflakes = document.createElement('div') + snowflakes.classList.add('snowflakes') + snowflakes.id = 'snowflakes' + snowflakes.setAttribute('aria-hidden', 'true') + snowflakes.innerHTML = '
' + + // add snowflake div to website body + document.getElementsByTagName('Body')[0].prepend(snowflakes) } + } catch (e) { console.log('cannot insert snowFlakes: ' + e) } } +function insertFlakeSwitch (currentlyActivated) { + if (currentlyActivated === undefined) currentlyActivated = true + try { + if (document.getElementsByClassName('page-header')[0] !== undefined) { + const header = document.getElementsByClassName('page-header')[0] + const flake = document.createElement('h1') + const flakeLink = document.createElement('a') + flakeLink.id = 'flakeLink' + flakeLink.style.textDecoration = 'none' + flakeLink.href = 'javascript:void(0)' + flake.id = 'flake' + flakeLink.title = 'Click me. Winter powered by TUfast.' + flake.onclick = flakesSwitchOnClick + flake.style.paddingTop = '2px' + flake.style.paddingLeft = '3px' + + if (currentlyActivated) flakeLink.style.color = 'black' + if (!currentlyActivated) flakeLink.style.color = 'Grey' + + flakeLink.innerHTML = '❅' + flakeLink.fontSize = '30px' + + // append to header + flake.appendChild(flakeLink) + header.append(flake) + } + } catch (e) { + console.log('Error inserting flakeSwitch: ' + e) + } +}; diff --git a/src/contentScripts/bildungsportal_main.js b/src/contentScripts/bildungsportal_main.js index 3fb17e13..96da4d8b 100644 --- a/src/contentScripts/bildungsportal_main.js +++ b/src/contentScripts/bildungsportal_main.js @@ -1,22 +1,22 @@ chrome.storage.local.get(['isEnabled', 'loggedOutOpal'], function (result) { - if (/*result.isEnabled &&*/ !(result.loggedOutOpal)) { - document.addEventListener('DOMContentLoaded', function () { - //select TU Dresden from selector - if (document.getElementsByName("wayfselection")[0]) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - let selectionList = document.getElementsByName("wayfselection")[0] - for (let el of selectionList) { - if (el.textContent === "TU Dresden" || el.textContent === "Technsiche Universität Dresden") { - document.getElementsByName("wayfselection")[0].value = el.value - } - } - } - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 4000 }); - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - document.getElementsByClassName("btn-highlight")[0].click() - }) - console.log('Auto Login to Opal.') - } else if (result.loggedOutOpal) { - chrome.storage.local.set({ loggedOutOpal: false }, function () { }) - } + if (/* result.isEnabled && */ !(result.loggedOutOpal)) { + document.addEventListener('DOMContentLoaded', function () { + // select TU Dresden from selector + if (document.getElementsByName('wayfselection')[0]) { + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + const selectionList = document.getElementsByName('wayfselection')[0] + for (const el of selectionList) { + if (el.textContent === 'TU Dresden' || el.textContent === 'Technsiche Universität Dresden') { + document.getElementsByName('wayfselection')[0].value = el.value + } + } + } + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 4000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + document.getElementsByClassName('btn-highlight')[0].click() + }) + console.log('Auto Login to Opal.') + } else if (result.loggedOutOpal) { + chrome.storage.local.set({ loggedOutOpal: false }, function () { }) + } }) diff --git a/src/contentScripts/bildungsportal_other.js b/src/contentScripts/bildungsportal_other.js index 715effa8..9c81e478 100644 --- a/src/contentScripts/bildungsportal_other.js +++ b/src/contentScripts/bildungsportal_other.js @@ -1,57 +1,53 @@ document.addEventListener('DOMContentLoaded', function () { - if (document.querySelectorAll('.btn.btn-sm[title="Abmelden"]')[0]) { - document.querySelectorAll('.btn.btn-sm[title="Abmelden"]')[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOpal' }) - }) - } + if (document.querySelectorAll('.btn.btn-sm[title="Abmelden"]')[0]) { + document.querySelectorAll('.btn.btn-sm[title="Abmelden"]')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOpal' }) + }) + } }) -chrome.storage.local.get(['isEnabled', "availableRockets", "removedUnlockRocketsBanner", "showedOpalCustomizeBanner", "unlockRocketsFirstPrompt", "saved_click_counter", "showedUnreadMailCounterBanner", "showedFirefoxBanner", "mostLiklySubmittedReview", "removedReviewBanner", "neverShowedReviewBanner", "showedKeyboardBanner2", "nameIsTUfast"], function (result) { - //decide whether to show review banner - let showReviewBanner = false - let showKeyboardUpdate = false - //let showImplementationForFirefox = false - let showUnreadMailCounter = false - let showUnlockRocketsFirstPrompt = false - let showOpalCustomize = false - let showUnlockRockets = false - - let mod200Clicks = result.saved_click_counter % 200 - let mod100Clicks = result.saved_click_counter % 100 - let isFirefox = navigator.userAgent.includes("Firefox/") //attention: no failsave browser detection - - //not shown right now - //reviews only required in FF - //if (isFirefox && !result.mostLiklySubmittedReview && mod200Clicks < 15 && !result.removedReviewBanner && result.saved_click_counter > 200) { - // showReviewBanner = true - //} - //if (mod200Clicks > 15) { - // chrome.storage.local.set({ removedReviewBanner: false }, function () { }) - //} - //if (isFirefox && result.neverShowedReviewBanner && result.saved_click_counter > 300) { - // showReviewBanner = true - //} - - - //show implementationForFirefox not longer required - //if (!showKeyboardUpdate && !showReviewBanner && !result.showedFirefoxBanner && result.saved_click_counter > 50) { - // let isChrome = navigator.userAgent.includes("Chrome/") //attention: no failsave browser detection | also for new edge! - // if(isChrome) showImplementationForFirefox = true - //} - - if (result.saved_click_counter > 50 && !result.showedUnreadMailCounterBanner) { - showUnreadMailCounter = true - } - else if (result.saved_click_counter > 100 && !result.showedKeyboardBanner2) { - showKeyboardUpdate = true - } - else if (result.saved_click_counter > 150 && !result.showedOpalCustomizeBanner) { - showOpalCustomize = true - } - else if (result.saved_click_counter > 250 && !result.unlockRocketsFirstPrompt) { - showUnlockRocketsFirstPrompt = true - } - /* +chrome.storage.local.get(['isEnabled', 'availableRockets', 'removedUnlockRocketsBanner', 'showedOpalCustomizeBanner', 'unlockRocketsFirstPrompt', 'saved_click_counter', 'showedUnreadMailCounterBanner', 'showedFirefoxBanner', 'mostLiklySubmittedReview', 'removedReviewBanner', 'neverShowedReviewBanner', 'showedKeyboardBanner2', 'nameIsTUfast'], function (result) { + // decide whether to show review banner + const showReviewBanner = false + let showKeyboardUpdate = false + // let showImplementationForFirefox = false + let showUnreadMailCounter = false + let showUnlockRocketsFirstPrompt = false + let showOpalCustomize = false + const showUnlockRockets = false + + // const mod200Clicks = result.saved_click_counter % 200 + const mod100Clicks = result.saved_click_counter % 100 + // const isFirefox = navigator.userAgent.includes('Firefox/') // attention: no failsave browser detection + + // not shown right now + // reviews only required in FF + // if (isFirefox && !result.mostLiklySubmittedReview && mod200Clicks < 15 && !result.removedReviewBanner && result.saved_click_counter > 200) { + // showReviewBanner = true + // } + // if (mod200Clicks > 15) { + // chrome.storage.local.set({ removedReviewBanner: false }, function () { }) + // } + // if (isFirefox && result.neverShowedReviewBanner && result.saved_click_counter > 300) { + // showReviewBanner = true + // } + + // show implementationForFirefox not longer required + // if (!showKeyboardUpdate && !showReviewBanner && !result.showedFirefoxBanner && result.saved_click_counter > 50) { + // let isChrome = navigator.userAgent.includes("Chrome/") //attention: no failsave browser detection | also for new edge! + // if(isChrome) showImplementationForFirefox = true + // } + + if (result.saved_click_counter > 50 && !result.showedUnreadMailCounterBanner) { + showUnreadMailCounter = true + } else if (result.saved_click_counter > 100 && !result.showedKeyboardBanner2) { + showKeyboardUpdate = true + } else if (result.saved_click_counter > 150 && !result.showedOpalCustomizeBanner) { + showOpalCustomize = true + } else if (result.saved_click_counter > 250 && !result.unlockRocketsFirstPrompt) { + showUnlockRocketsFirstPrompt = true + } + /* else if (result.saved_click_counter > 300 && result.unlockRocketsFirstPrompt && mod100Clicks < 7 && !result.removedUnlockRocketsBanner) { //dont show banner, if all rockets are already unlocked if (!result.availableRockets.includes("RI1") || !result.availableRockets.includes("RI2")) { @@ -60,230 +56,226 @@ chrome.storage.local.get(['isEnabled', "availableRockets", "removedUnlockRockets } */ - //reset unlock rockets banner - if (mod100Clicks > 7) { chrome.storage.local.set({ removedUnlockRocketsBanner: false }, function () { }) } + // reset unlock rockets banner + if (mod100Clicks > 7) { chrome.storage.local.set({ removedUnlockRocketsBanner: false }, function () { }) } - window.addEventListener("load", async function (e) { - if (showReviewBanner) { showLeaveReviewBanner() } - if (showKeyboardUpdate) { showKeyboardShortcutUpdate() } - //if (showImplementationForFirefox) { showImplementationForFirefoxBanner() } - if (showUnreadMailCounter) { showUnreadMailCounterBanner() } - if (showUnlockRocketsFirstPrompt) { showUnlockRocketsFirstBanner() } - if (showOpalCustomize) { showOpalCustomizeBanner() } - if (showUnlockRockets) { showUnlockRocketsBanner() } + window.addEventListener('load', async function (e) { + if (showReviewBanner) { showLeaveReviewBanner() } + if (showKeyboardUpdate) { showKeyboardShortcutUpdate() } + // if (showImplementationForFirefox) { showImplementationForFirefoxBanner() } + if (showUnreadMailCounter) { showUnreadMailCounterBanner() } + if (showUnlockRocketsFirstPrompt) { showUnlockRocketsFirstBanner() } + if (showOpalCustomize) { showOpalCustomizeBanner() } + if (showUnlockRockets) { showUnlockRocketsBanner() } - if (this.document.getElementById("removeReviewBanner")) { - this.document.getElementById("removeReviewBanner").onclick = removeReviewBanner - } - if (this.document.getElementById("webstoreLink")) { - this.document.getElementById("webstoreLink").onclick = clickedWebstoreLink - } - if (this.document.getElementById("openKeyboardShortcutSettings")) { - this.document.getElementById("openKeyboardShortcutSettings").onclick = openKeyboardShortcutSettings - } - if (this.document.getElementById("OpenOpalCustomizeSettings")) { - this.document.getElementById("OpenOpalCustomizeSettings").onclick = openOpalCustomizeSettings - } - if (this.document.getElementById("removeKeyboardShortcutSettings")) { - this.document.getElementById("removeKeyboardShortcutSettings").onclick = removeKeyboardShortcutSettings - } - if (this.document.getElementById("RemoveShowOpalCustomizeBanner")) { - this.document.getElementById("RemoveShowOpalCustomizeBanner").onclick = removeOpenOpalCustomizeSettings - } - if (this.document.getElementById("removeNameBanner")) { - this.document.getElementById("removeNameBanner").onclick = removeNameBanner - } - if (this.document.getElementById("RemoveShowImplementationForFirefoxBanner")) { - this.document.getElementById("RemoveShowImplementationForFirefoxBanner").onclick = RemoveShowImplementationForFirefoxBanner - this.document.getElementById("LinkShowImplementationForFirefoxBanner").onclick = RemoveShowImplementationForFirefoxBanner - } - if (this.document.getElementById("showUnreadMailCounterBanner")) { - this.document.getElementById("OpenUnreadMailCounterSettings").onclick = openSettingsUnreadMail - this.document.getElementById("RemoveShowUnreadMailCounterBanner").onclick = RemoveShowUnreadMailCounterBanner - } - if (this.document.getElementById("unlockRocketsFirstPrompt")) { - this.document.getElementById("openMoreRocketIcons").onclick = openMoreRocketIconsSettingsFirstPrompt - document.getElementById("removeMoreRocketIconsFirst").onclick = removeFirstRocketBanner - } - if (this.document.getElementById("unlockRocketsPrompt")) { - this.document.getElementById("openMoreRocketIcons").onclick = openMoreRocketIconsSettings - this.document.getElementById("removeMoreRocketIcons").onclick = RemoveMoreRocketIcons - } - }) + if (this.document.getElementById('removeReviewBanner')) { + this.document.getElementById('removeReviewBanner').onclick = removeReviewBanner + } + if (this.document.getElementById('webstoreLink')) { + this.document.getElementById('webstoreLink').onclick = clickedWebstoreLink + } + if (this.document.getElementById('openKeyboardShortcutSettings')) { + this.document.getElementById('openKeyboardShortcutSettings').onclick = openKeyboardShortcutSettings + } + if (this.document.getElementById('OpenOpalCustomizeSettings')) { + this.document.getElementById('OpenOpalCustomizeSettings').onclick = openOpalCustomizeSettings + } + if (this.document.getElementById('removeKeyboardShortcutSettings')) { + this.document.getElementById('removeKeyboardShortcutSettings').onclick = removeKeyboardShortcutSettings + } + if (this.document.getElementById('RemoveShowOpalCustomizeBanner')) { + this.document.getElementById('RemoveShowOpalCustomizeBanner').onclick = removeOpenOpalCustomizeSettings + } + if (this.document.getElementById('removeNameBanner')) { + this.document.getElementById('removeNameBanner').onclick = removeNameBanner + } + if (this.document.getElementById('RemoveShowImplementationForFirefoxBanner')) { + this.document.getElementById('RemoveShowImplementationForFirefoxBanner').onclick = RemoveShowImplementationForFirefoxBanner + this.document.getElementById('LinkShowImplementationForFirefoxBanner').onclick = RemoveShowImplementationForFirefoxBanner + } + if (this.document.getElementById('showUnreadMailCounterBanner')) { + this.document.getElementById('OpenUnreadMailCounterSettings').onclick = openSettingsUnreadMail + this.document.getElementById('RemoveShowUnreadMailCounterBanner').onclick = RemoveShowUnreadMailCounterBanner + } + if (this.document.getElementById('unlockRocketsFirstPrompt')) { + this.document.getElementById('openMoreRocketIcons').onclick = openMoreRocketIconsSettingsFirstPrompt + document.getElementById('removeMoreRocketIconsFirst').onclick = removeFirstRocketBanner + } + if (this.document.getElementById('unlockRocketsPrompt')) { + this.document.getElementById('openMoreRocketIcons').onclick = openMoreRocketIconsSettings + this.document.getElementById('removeMoreRocketIcons').onclick = RemoveMoreRocketIcons + } + }) }) -function RemoveMoreRocketIcons() { - if (document.getElementById("unlockRocketsPrompt")) { - document.getElementById("unlockRocketsPrompt").remove() - chrome.storage.local.set({ removedUnlockRocketsBanner: true }, function () { }) - } +function RemoveMoreRocketIcons () { + if (document.getElementById('unlockRocketsPrompt')) { + document.getElementById('unlockRocketsPrompt').remove() + chrome.storage.local.set({ removedUnlockRocketsBanner: true }, function () { }) + } } -function showUnlockRocketsBanner() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "unlockRocketsPrompt" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = 'Unterstütze TUfast und schalte coole neue Raketen frei! 🔥🔥🔥 Nein' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +function showUnlockRocketsBanner () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'unlockRocketsPrompt' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = 'Unterstütze TUfast und schalte coole neue Raketen frei! 🔥🔥🔥 Nein' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } -function RemoveShowUnreadMailCounterBanner() { - if (document.getElementById("showUnreadMailCounterBanner")) { - document.getElementById("showUnreadMailCounterBanner").remove() - chrome.storage.local.set({ showedUnreadMailCounterBanner: true }, function () { }) - } +function RemoveShowUnreadMailCounterBanner () { + if (document.getElementById('showUnreadMailCounterBanner')) { + document.getElementById('showUnreadMailCounterBanner').remove() + chrome.storage.local.set({ showedUnreadMailCounterBanner: true }, function () { }) + } } -function openSettingsUnreadMail() { - chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: "mailFetchSettings" }, function (result) { }) - if (document.getElementById("showUnreadMailCounterBanner")) { - document.getElementById("showUnreadMailCounterBanner").remove() - chrome.storage.local.set({ showedUnreadMailCounterBanner: true }, function () { }) - } +function openSettingsUnreadMail () { + chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'mailFetchSettings' }, function (result) { }) + if (document.getElementById('showUnreadMailCounterBanner')) { + document.getElementById('showUnreadMailCounterBanner').remove() + chrome.storage.local.set({ showedUnreadMailCounterBanner: true }, function () { }) + } } -function removeReviewBanner() { - if (document.getElementById("reviewBanner")) { - document.getElementById("reviewBanner").remove() - chrome.storage.local.set({ removedReviewBanner: true }, function () { }) - chrome.storage.local.set({ neverShowedReviewBanner: false }, function () { }) - } +function removeReviewBanner () { + if (document.getElementById('reviewBanner')) { + document.getElementById('reviewBanner').remove() + chrome.storage.local.set({ removedReviewBanner: true }, function () { }) + chrome.storage.local.set({ neverShowedReviewBanner: false }, function () { }) + } } -function RemoveShowImplementationForFirefoxBanner() { - chrome.storage.local.set({ showedFirefoxBanner: true }, function () { }) - if (document.getElementById("showImplementationForFirefoxBanner")) { - document.getElementById("showImplementationForFirefoxBanner").remove() - } +function RemoveShowImplementationForFirefoxBanner () { + chrome.storage.local.set({ showedFirefoxBanner: true }, function () { }) + if (document.getElementById('showImplementationForFirefoxBanner')) { + document.getElementById('showImplementationForFirefoxBanner').remove() + } } -function openKeyboardShortcutSettings() { - if (document.getElementById("keyboardBanner")) { - chrome.runtime.sendMessage({ cmd: 'open_shortcut_settings' }, function (result) { }) - } +function openKeyboardShortcutSettings () { + if (document.getElementById('keyboardBanner')) { + chrome.runtime.sendMessage({ cmd: 'open_shortcut_settings' }, function (result) { }) + } } -function removeFirstRocketBanner() { - if (document.getElementById("unlockRocketsFirstPrompt")) { - document.getElementById("unlockRocketsFirstPrompt").remove() - chrome.storage.local.set({ unlockRocketsFirstPrompt: true }, function () { }) - } +function removeFirstRocketBanner () { + if (document.getElementById('unlockRocketsFirstPrompt')) { + document.getElementById('unlockRocketsFirstPrompt').remove() + chrome.storage.local.set({ unlockRocketsFirstPrompt: true }, function () { }) + } } - -function openMoreRocketIconsSettingsFirstPrompt() { - if (document.getElementById("unlockRocketsFirstPrompt")) { - chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: "rocket_icons_settings" }, function (result) { }) - document.getElementById("unlockRocketsFirstPrompt").remove() - chrome.storage.local.set({ unlockRocketsFirstPrompt: true }, function () { }) - } +function openMoreRocketIconsSettingsFirstPrompt () { + if (document.getElementById('unlockRocketsFirstPrompt')) { + chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'rocket_icons_settings' }, function (result) { }) + document.getElementById('unlockRocketsFirstPrompt').remove() + chrome.storage.local.set({ unlockRocketsFirstPrompt: true }, function () { }) + } } -function openMoreRocketIconsSettings() { - if (document.getElementById("unlockRocketsPrompt")) { - chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: "rocket_icons_settings" }, function (result) { }) - document.getElementById("unlockRocketsPrompt").remove() - chrome.storage.local.set({ removedUnlockRocketsBanner: true }, function () { }) - } +function openMoreRocketIconsSettings () { + if (document.getElementById('unlockRocketsPrompt')) { + chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'rocket_icons_settings' }, function (result) { }) + document.getElementById('unlockRocketsPrompt').remove() + chrome.storage.local.set({ removedUnlockRocketsBanner: true }, function () { }) + } } -function openOpalCustomizeSettings() { - chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: "opalCustomize" }, function (result) { }) - if (document.getElementById("showOpalCustomizeBanner")) { - document.getElementById("showOpalCustomizeBanner").remove() - chrome.storage.local.set({ showedOpalCustomizeBanner: true }, function () { }) - } +function openOpalCustomizeSettings () { + chrome.runtime.sendMessage({ cmd: 'open_settings_page', params: 'opalCustomize' }, function (result) { }) + if (document.getElementById('showOpalCustomizeBanner')) { + document.getElementById('showOpalCustomizeBanner').remove() + chrome.storage.local.set({ showedOpalCustomizeBanner: true }, function () { }) + } } -function removeKeyboardShortcutSettings() { - chrome.storage.local.set({ showedKeyboardBanner2: true }, function () { }) - if (document.getElementById("keyboardBanner")) { - document.getElementById("keyboardBanner").remove() - } +function removeKeyboardShortcutSettings () { + chrome.storage.local.set({ showedKeyboardBanner2: true }, function () { }) + if (document.getElementById('keyboardBanner')) { + document.getElementById('keyboardBanner').remove() + } } -function removeOpenOpalCustomizeSettings() { - chrome.storage.local.set({ showedOpalCustomizeBanner: true }, function () { }) - if (document.getElementById("showOpalCustomizeBanner")) { - document.getElementById("showOpalCustomizeBanner").remove() - } +function removeOpenOpalCustomizeSettings () { + chrome.storage.local.set({ showedOpalCustomizeBanner: true }, function () { }) + if (document.getElementById('showOpalCustomizeBanner')) { + document.getElementById('showOpalCustomizeBanner').remove() + } } -function removeNameBanner() { - chrome.storage.local.set({ nameIsTUfast: true }, function () { }) - if (document.getElementById("nameBanner")) { - document.getElementById("nameBanner").remove() - } +function removeNameBanner () { + chrome.storage.local.set({ nameIsTUfast: true }, function () { }) + if (document.getElementById('nameBanner')) { + document.getElementById('nameBanner').remove() + } } - -function clickedWebstoreLink() { - if (document.getElementById("reviewBanner")) { - document.getElementById("reviewBanner").remove() - chrome.storage.local.set({ mostLiklySubmittedReview: true }, function () { }) - chrome.storage.local.set({ neverShowedReviewBanner: false }, function () { }) - } +function clickedWebstoreLink () { + if (document.getElementById('reviewBanner')) { + document.getElementById('reviewBanner').remove() + chrome.storage.local.set({ mostLiklySubmittedReview: true }, function () { }) + chrome.storage.local.set({ neverShowedReviewBanner: false }, function () { }) + } } -function showKeyboardShortcutUpdate() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "keyboardBanner" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = ' Supergeil: TUfast Shortcuts! Öffne z.B. das Dashboard mit Alt+QAlle Shortcuts ansehenX' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +function showKeyboardShortcutUpdate () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'keyboardBanner' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = ' Supergeil: TUfast Shortcuts! Öffne z.B. das Dashboard mit Alt+QAlle Shortcuts ansehenX' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } -function showUnlockRocketsFirstBanner() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "unlockRocketsFirstPrompt" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = 'Dir gefällt TUfast ? Unterstütze das Projekt, empfehle es deinen Freunden und schalte coole neue Raketen frei! 🔥🔥🔥 Nein' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +function showUnlockRocketsFirstBanner () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'unlockRocketsFirstPrompt' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = 'Dir gefällt TUfast ? Unterstütze das Projekt, empfehle es deinen Freunden und schalte coole neue Raketen frei! 🔥🔥🔥 Nein' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } -function showImplementationForFirefoxBanner() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "showImplementationForFirefoxBanner" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = 'Supergeil und Brandneu: TUfast für Firefox! 🔥🔥🔥Schließen' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +// function showImplementationForFirefoxBanner () { +// const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') +// const banner = this.document.createElement('div') +// banner.id = 'showImplementationForFirefoxBanner' +// banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' +// banner.innerHTML = 'Supergeil und Brandneu: TUfast für Firefox! 🔥🔥🔥Schließen' +// this.document.body.insertBefore(banner, document.body.childNodes[0]) +// } + +function showOpalCustomizeBanner () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'showOpalCustomizeBanner' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = 'Mit TUfast kannst du OPAL Personalisieren und Verbessern. Gleich ausprobieren! 🔥🔥🔥Schließen X' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } -function showOpalCustomizeBanner() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "showOpalCustomizeBanner" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = 'Mit TUfast kannst du OPAL Personalisieren und Verbessern. Gleich ausprobieren! 🔥🔥🔥Schließen X' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +function showUnreadMailCounterBanner () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'showUnreadMailCounterBanner' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = 'Neu: mit TUfast verpasst du keine Mails aus deinem TU Dresden Postfach. Jetzt probieren.Schließen' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } -function showUnreadMailCounterBanner() { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "showUnreadMailCounterBanner" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = 'Neu: mit TUfast verpasst du keine Mails aus deinem TU Dresden Postfach. Jetzt probieren.Schließen' - this.document.body.insertBefore(banner, document.body.childNodes[0]) +function showLeaveReviewBanner () { + // webstore link depends on browser! + const isChrome = navigator.userAgent.includes('Chrome/') // attention: no failsave browser detection | also for new edge! + const isFirefox = navigator.userAgent.includes('Firefox/') // attention: no failsave browser detection + let webstoreLink = '' + if (isChrome) { webstoreLink = 'https://chrome.google.com/webstore/detail/tufast-tu-dresden/aheogihliekaafikeepfjngfegbnimbk?hl=de' } else if (isFirefox) { webstoreLink = 'https://addons.mozilla.org/de/firefox/addon/tufast/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search' } else { webstoreLink = 'https://www.tu-fast.de' } + + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const banner = this.document.createElement('div') + banner.id = 'reviewBanner' + banner.style = 'font-size:22px; height:55px; line-height:55px;text-align:center' + banner.innerHTML = ' Dir gefällt TUfast ⭐⭐⭐⭐⭐ ? Hinterlasse uns eine Bewertung im Webstore!Nein, danke :(' + this.document.body.insertBefore(banner, document.body.childNodes[0]) } - -function showLeaveReviewBanner() { - //webstore link depends on browser! - let isChrome = navigator.userAgent.includes("Chrome/") //attention: no failsave browser detection | also for new edge! - let isFirefox = navigator.userAgent.includes("Firefox/") //attention: no failsave browser detection - let webstoreLink = "" - if (isChrome) { webstoreLink = "https://chrome.google.com/webstore/detail/tufast-tu-dresden/aheogihliekaafikeepfjngfegbnimbk?hl=de" } - else if (isFirefox) { webstoreLink = "https://addons.mozilla.org/de/firefox/addon/tufast/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search" } - else { webstoreLink = "https://www.tu-fast.de" } - - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let banner = this.document.createElement("div") - banner.id = "reviewBanner" - banner.style = "font-size:22px; height:55px; line-height:55px;text-align:center" - banner.innerHTML = ' Dir gefällt TUfast ⭐⭐⭐⭐⭐ ? Hinterlasse uns eine Bewertung im Webstore!Nein, danke :(' - this.document.body.insertBefore(banner, document.body.childNodes[0]) -} \ No newline at end of file diff --git a/src/contentScripts/bildungsportal_viewPDFinBrowser.js b/src/contentScripts/bildungsportal_viewPDFinBrowser.js index 8a764a3a..f8e7012c 100644 --- a/src/contentScripts/bildungsportal_viewPDFinBrowser.js +++ b/src/contentScripts/bildungsportal_viewPDFinBrowser.js @@ -1,59 +1,59 @@ -chrome.storage.local.get(["pdfInNewTab"], function (result) { - if (result.pdfInNewTab) { - //on load - document.addEventListener("DOMNodeInserted", function (e) { - modifyPdfLinks(); - }); - //on document loaded - window.addEventListener( - "load", - function () { - modifyPdfLinks(); - pdfButtonExternalReload(); - }, - true - ); - } -}); +chrome.storage.local.get(['pdfInNewTab'], function (result) { + if (result.pdfInNewTab) { + // on load + document.addEventListener('DOMNodeInserted', function (e) { + modifyPdfLinks() + }) + // on document loaded + window.addEventListener( + 'load', + function () { + modifyPdfLinks() + pdfButtonExternalReload() + }, + true + ) + } +}) -function modifyPdfLinks() { - //Modify js so that link is opened in new tab - let links = document.getElementsByTagName("a"); - for (let idx = 0; idx < links.length; idx++) { - if (links[idx].href.includes(".pdf")) { - links[idx].onclick = function (event) { - event.stopImmediatePropagation(); //prevents OPAL to load in the same tab - window.open(this.href, "_blank"); - return false; - }; - } +function modifyPdfLinks () { + // Modify js so that link is opened in new tab + const links = document.getElementsByTagName('a') + for (let idx = 0; idx < links.length; idx++) { + if (links[idx].href.includes('.pdf')) { + links[idx].onclick = function (event) { + event.stopImmediatePropagation() // prevents OPAL to load in the same tab + window.open(this.href, '_blank') + return false + } } + } } -function pdfButtonExternalReload() { - // Only run logic if URL path includes 'downloadering'. - // This is the page Opal requests on click on - let's call it - a 'document button'. - if (document.documentURI.includes('downloadering')) { - // The fiber code gets auto genereted, it seems kind of random. - // It doesn't identify a document, I saw two codes for the same PDF. +function pdfButtonExternalReload () { + // Only run logic if URL path includes 'downloadering'. + // This is the page Opal requests on click on - let's call it - a 'document button'. + if (document.documentURI.includes('downloadering')) { + // The fiber code gets auto genereted, it seems kind of random. + // It doesn't identify a document, I saw two codes for the same PDF. - const fibercode_query = 'fibercode='; - const fibercode_pos = document.documentURI.lastIndexOf(fibercode_query); + const fibercodeQuery = 'fibercode=' + const fibercodePos = document.documentURI.lastIndexOf(fibercodeQuery) - const fibercode = document.documentURI.slice(fibercode_pos+fibercode_query.length); + const fibercode = document.documentURI.slice(fibercodePos + fibercodeQuery.length) - // check if fibercode is already present to not reload the same page forever - chrome.storage.local.get(['fibercode'], (result) => { - if (result.fibercode === fibercode) { - // remove fibercode again after page opened in new tab (runs in new tab) - chrome.storage.local.set({fibercode: ''}); - } else { - // set the fibercode if it doesn't exist in db (runs on button click) - chrome.storage.local.set({fibercode: fibercode}, () => { - open(document.documentURI, '_blank'); - history.back(); - }); - } - }); - } -} \ No newline at end of file + // check if fibercode is already present to not reload the same page forever + chrome.storage.local.get(['fibercode'], (result) => { + if (result.fibercode === fibercode) { + // remove fibercode again after page opened in new tab (runs in new tab) + chrome.storage.local.set({ fibercode: '' }) + } else { + // set the fibercode if it doesn't exist in db (runs on button click) + chrome.storage.local.set({ fibercode: fibercode }, () => { + open(document.documentURI, '_blank') + history.back() + }) + } + }) + } +} diff --git a/src/contentScripts/cloudstore.js b/src/contentScripts/cloudstore.js index e5d768d1..a05abe42 100644 --- a/src/contentScripts/cloudstore.js +++ b/src/contentScripts/cloudstore.js @@ -1,30 +1,29 @@ chrome.storage.local.get(['isEnabled', 'loggedOutCloudstore'], function (result) { - if (result.isEnabled && !result.loggedOutCloudstore) { - document.addEventListener('DOMContentLoaded', function () { - if (document.getElementById('user') && document.getElementById('password')) { - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { - if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - document.getElementById('user').value = (result.asdf) - document.getElementById('password').value = (result.fdsa) - document.getElementById('submit-form').click() - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); - } - }); - } - if (document.querySelectorAll('[data-id="logout"] > a')[0]) { - document.querySelectorAll('[data-id="logout"] > a')[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutCloudstore' }) - }) - } + if (result.isEnabled && !result.loggedOutCloudstore) { + document.addEventListener('DOMContentLoaded', function () { + if (document.getElementById('user') && document.getElementById('password')) { + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { + if (!(result.asdf === undefined || result.fdsa === undefined)) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + document.getElementById('user').value = (result.asdf) + document.getElementById('password').value = (result.fdsa) + document.getElementById('submit-form').click() + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } }) - console.log('Auto Login to Cloudstore.') - } - else if (result.loggedOutCloudstore) { - chrome.storage.local.set({ loggedOutCloudstore: false }, function () { }) - } -}) \ No newline at end of file + } + if (document.querySelectorAll('[data-id="logout"] > a')[0]) { + document.querySelectorAll('[data-id="logout"] > a')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutCloudstore' }) + }) + } + }) + console.log('Auto Login to Cloudstore.') + } else if (result.loggedOutCloudstore) { + chrome.storage.local.set({ loggedOutCloudstore: false }, function () { }) + } +}) diff --git a/src/contentScripts/elearningMED.js b/src/contentScripts/elearningMED.js index 72f36e05..6f528ea5 100644 --- a/src/contentScripts/elearningMED.js +++ b/src/contentScripts/elearningMED.js @@ -1,37 +1,37 @@ chrome.storage.local.get(['loggedOutElearningMED'], function (result) { - if (!result.loggedOutElearningMED) { - if (document.readyState !== 'loading') { - loginElearningMED(result.loggedOutElearningMED) - } else { - document.addEventListener('DOMContentLoaded', function () { - loginElearningMED(result.loggedOutElearningMED) - }) - } - console.log('Auto Login to elearning.med.') + if (!result.loggedOutElearningMED) { + if (document.readyState !== 'loading') { + loginElearningMED(result.loggedOutElearningMED) + } else { + document.addEventListener('DOMContentLoaded', function () { + loginElearningMED(result.loggedOutElearningMED) + }) } + console.log('Auto Login to elearning.med.') + } }) -function loginElearningMED(loggedOutElearningMED) { - if (document.getElementsByTagName("a")[0].textContent === "Moodle" && location.href === "https://elearning.med.tu-dresden.de/") { - document.getElementsByTagName("a")[0].click() - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - } else if (location.href === "https://elearning.med.tu-dresden.de/moodle/academiLogin.html" && document.querySelectorAll('[href="https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php"]')[0]) { - document.querySelectorAll('[href="https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php"]')[0].click() - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - } +function loginElearningMED (loggedOutElearningMED) { + if (document.getElementsByTagName('a')[0].textContent === 'Moodle' && location.href === 'https://elearning.med.tu-dresden.de/') { + document.getElementsByTagName('a')[0].click() + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + } else if (location.href === 'https://elearning.med.tu-dresden.de/moodle/academiLogin.html' && document.querySelectorAll('[href="https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php"]')[0]) { + document.querySelectorAll('[href="https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php"]')[0].click() + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + } - //second login screen (or it was just changed?!) - if (location.href.includes("elearning.med.tu-dresden.de/moodle/login")) { - if (document.querySelectorAll("a[title='ZIH-Login']")[0].href = "https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php") { - document.querySelectorAll("a[title='ZIH-Login']")[0].click() - } + // second login screen (or it was just changed?!) + if (location.href.includes('elearning.med.tu-dresden.de/moodle/login')) { + if (document.querySelectorAll("a[title='ZIH-Login']")[0].href === 'https://elearning.med.tu-dresden.de/moodle/auth/shibboleth/index.php') { + document.querySelectorAll("a[title='ZIH-Login']")[0].click() } + } - //detecting logout - if (document.getElementById("actionmenuaction-6")) { - document.getElementById("actionmenuaction-6").addEventListener('click', function () { - console.log("logout detected!") - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutElearningMED' }) - }) - } -} \ No newline at end of file + // detecting logout + if (document.getElementById('actionmenuaction-6')) { + document.getElementById('actionmenuaction-6').addEventListener('click', function () { + console.log('logout detected!') + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutElearningMED' }) + }) + } +} diff --git a/src/contentScripts/fwd_cloudstore.js b/src/contentScripts/fwd_cloudstore.js index ca46a843..5568e998 100644 --- a/src/contentScripts/fwd_cloudstore.js +++ b/src/contentScripts/fwd_cloudstore.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to cloudstore") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://cloudstore.zih.tu-dresden.de/index.php/login") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to cloudstore') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://cloudstore.zih.tu-dresden.de/index.php/login') + } +}) diff --git a/src/contentScripts/fwd_hisqis.js b/src/contentScripts/fwd_hisqis.js index 4d1fb8b1..1f00f799 100644 --- a/src/contentScripts/fwd_hisqis.js +++ b/src/contentScripts/fwd_hisqis.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to hisqis") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to hisqis') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news') + } +}) diff --git a/src/contentScripts/fwd_jexam.js b/src/contentScripts/fwd_jexam.js index 7d2688bf..423903f4 100644 --- a/src/contentScripts/fwd_jexam.js +++ b/src/contentScripts/fwd_jexam.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to jexam") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to jexam') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome') + } +}) diff --git a/src/contentScripts/fwd_magma.js b/src/contentScripts/fwd_magma.js index 320d5903..b04e781b 100644 --- a/src/contentScripts/fwd_magma.js +++ b/src/contentScripts/fwd_magma.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to magma") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://bildungsportal.sachsen.de/magma/") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to magma') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://bildungsportal.sachsen.de/magma/') + } +}) diff --git a/src/contentScripts/fwd_matrix.js b/src/contentScripts/fwd_matrix.js index 4598434e..ee7614c2 100644 --- a/src/contentScripts/fwd_matrix.js +++ b/src/contentScripts/fwd_matrix.js @@ -1,11 +1,11 @@ chrome.storage.local.get(['fwdEnabled', 'isEnabled'], function (result) { - if (result.fwdEnabled && result.isEnabled) { - console.log("fwd to matrix") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://matrix.tu-dresden.de/#/login") - } else if (result.fwdEnabled && !result.isEnabled) { - console.log("fwd to matrix") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://matrix.tu-dresden.de/#/") - } + if (result.fwdEnabled && result.isEnabled) { + console.log('fwd to matrix') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://matrix.tu-dresden.de/#/login') + } else if (result.fwdEnabled && !result.isEnabled) { + console.log('fwd to matrix') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://matrix.tu-dresden.de/#/') + } }) diff --git a/src/contentScripts/fwd_opal.js b/src/contentScripts/fwd_opal.js index 3e100055..42f92a64 100644 --- a/src/contentScripts/fwd_opal.js +++ b/src/contentScripts/fwd_opal.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled & !(location.href.includes("exam"))) { //dont fwd if user wants to get to exam.zih.tu-dresden.de - console.log("fwd to opal") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://bildungsportal.sachsen.de/opal/shiblogin?0") - } -}) \ No newline at end of file + if (result.fwdEnabled & !(location.href.includes('exam'))) { // dont fwd if user wants to get to exam.zih.tu-dresden.de + console.log('fwd to opal') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://bildungsportal.sachsen.de/opal/shiblogin?0') + } +}) diff --git a/src/contentScripts/fwd_opalError.js b/src/contentScripts/fwd_opalError.js index 8301cd75..a4ac1cdd 100644 --- a/src/contentScripts/fwd_opalError.js +++ b/src/contentScripts/fwd_opalError.js @@ -1,11 +1,10 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to opal from opal error") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - //click on forward to opal, which should be first element in list - if (document.querySelectorAll("li>a")[0].text.includes("OPAL")) { - document.querySelectorAll("li>a")[0].click() - } - + if (result.fwdEnabled) { + console.log('fwd to opal from opal error') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + // click on forward to opal, which should be first element in list + if (document.querySelectorAll('li>a')[0].text.includes('OPAL')) { + document.querySelectorAll('li>a')[0].click() } -}) \ No newline at end of file + } +}) diff --git a/src/contentScripts/fwd_owa.js b/src/contentScripts/fwd_owa.js index 517acda9..a08e890a 100644 --- a/src/contentScripts/fwd_owa.js +++ b/src/contentScripts/fwd_owa.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to owa") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://msx.tu-dresden.de/owa/#path=/mail") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to owa') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://msx.tu-dresden.de/owa/#path=/mail') + } +}) diff --git a/src/contentScripts/fwd_qwant.js b/src/contentScripts/fwd_qwant.js index c68186a9..17b6e220 100644 --- a/src/contentScripts/fwd_qwant.js +++ b/src/contentScripts/fwd_qwant.js @@ -1,54 +1,54 @@ chrome.storage.local.get(['fwdEnabled', 'isEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("register fwds in qwant") - let searchForm = document.querySelector('form[data-testid="mainSearchBar"]') - let searchInput = searchForm.querySelector('input[name="q"]') - searchForm.addEventListener("submit", event => fwdOnSearch(event, searchInput.value, result.isEnabled)) - } + if (result.fwdEnabled) { + console.log('register fwds in qwant') + const searchForm = document.querySelector('form[data-testid="mainSearchBar"]') + const searchInput = searchForm.querySelector('input[name="q"]') + searchForm.addEventListener('submit', event => fwdOnSearch(event, searchInput.value, result.isEnabled)) + } }) -function fwdOnSearch(event, value, isEnabled) { - console.log(value) - console.log(isEnabled) - let link = ""; - let fwd = true; - switch(value) { - case "opal": - link = "https://bildungsportal.sachsen.de/opal/shiblogin?0" - break - case "jexam": - link = "https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome" - break - case "tustore": - case "tucloud": - link = "https://cloudstore.zih.tu-dresden.de/index.php/login" - break - case "tumail": - case "tudmail": - link = "https://msx.tu-dresden.de/owa/#path=/mail" - break - case "hisqis": - link = "https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news" - break - case "tumed": - link = "https://eportal.med.tu-dresden.de/login" - break - case "selma": - link = "https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen" - break - case "tumatrix": - link = isEnabled ? "https://matrix.tu-dresden.de/#/login" : "https://matrix.tu-dresden.de/#/" - break - case "magma": - link = "https://bildungsportal.sachsen.de/magma/" - break - default: - fwd = false - } - if(fwd) { - event.preventDefault() - console.log(`fwd to ${link}`) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace(link) - } -} \ No newline at end of file +function fwdOnSearch (event, value, isEnabled) { + console.log(value) + console.log(isEnabled) + let link = '' + let fwd = true + switch (value) { + case 'opal': + link = 'https://bildungsportal.sachsen.de/opal/shiblogin?0' + break + case 'jexam': + link = 'https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome' + break + case 'tustore': + case 'tucloud': + link = 'https://cloudstore.zih.tu-dresden.de/index.php/login' + break + case 'tumail': + case 'tudmail': + link = 'https://msx.tu-dresden.de/owa/#path=/mail' + break + case 'hisqis': + link = 'https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news' + break + case 'tumed': + link = 'https://eportal.med.tu-dresden.de/login' + break + case 'selma': + link = 'https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen' + break + case 'tumatrix': + link = isEnabled ? 'https://matrix.tu-dresden.de/#/login' : 'https://matrix.tu-dresden.de/#/' + break + case 'magma': + link = 'https://bildungsportal.sachsen.de/magma/' + break + default: + fwd = false + } + if (fwd) { + event.preventDefault() + console.log(`fwd to ${link}`) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace(link) + } +} diff --git a/src/contentScripts/fwd_selma.js b/src/contentScripts/fwd_selma.js index 19a2009e..44b04888 100644 --- a/src/contentScripts/fwd_selma.js +++ b/src/contentScripts/fwd_selma.js @@ -1,8 +1,8 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log('fwd to selma') - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - //There is a unique session url. That is why user always has to be fwd to login page :/ - window.location.replace("https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to selma') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + // There is a unique session url. That is why user always has to be fwd to login page :/ + window.location.replace('https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen') + } +}) diff --git a/src/contentScripts/fwd_startpage.js b/src/contentScripts/fwd_startpage.js index 1dcc005e..5c684bf4 100644 --- a/src/contentScripts/fwd_startpage.js +++ b/src/contentScripts/fwd_startpage.js @@ -1,54 +1,54 @@ chrome.storage.local.get(['fwdEnabled', 'isEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("register fwds in startpage") - let searchForm = document.getElementById("search") - let searchInput = document.getElementById("q") - searchForm.addEventListener("submit", event => fwdOnSearch(event, searchInput.value, result.isEnabled)) - } + if (result.fwdEnabled) { + console.log('register fwds in startpage') + const searchForm = document.getElementById('search') + const searchInput = document.getElementById('q') + searchForm.addEventListener('submit', event => fwdOnSearch(event, searchInput.value, result.isEnabled)) + } }) -function fwdOnSearch(event, value, isEnabled) { - console.log(value) - console.log(isEnabled) - let link = ""; - let fwd = true; - switch(value) { - case "opal": - link = "https://bildungsportal.sachsen.de/opal/shiblogin?0" - break - case "jexam": - link = "https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome" - break - case "tustore": - case "tucloud": - link = "https://cloudstore.zih.tu-dresden.de/index.php/login" - break - case "tumail": - case "tudmail": - link = "https://msx.tu-dresden.de/owa/#path=/mail" - break - case "hisqis": - link = "https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news" - break - case "tumed": - link = "https://eportal.med.tu-dresden.de/login" - break - case "selma": - link = "https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen" - break - case "tumatrix": - link = isEnabled ? "https://matrix.tu-dresden.de/#/login" : "https://matrix.tu-dresden.de/#/" - break - case "magma": - link = "https://bildungsportal.sachsen.de/magma/" - break - default: - fwd = false - } - if(fwd) { - event.preventDefault() - console.log(`fwd to ${link}`) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace(link) - } -} \ No newline at end of file +function fwdOnSearch (event, value, isEnabled) { + console.log(value) + console.log(isEnabled) + let link = '' + let fwd = true + switch (value) { + case 'opal': + link = 'https://bildungsportal.sachsen.de/opal/shiblogin?0' + break + case 'jexam': + link = 'https://jexam.inf.tu-dresden.de/de.jexam.web.v4.5/spring/welcome' + break + case 'tustore': + case 'tucloud': + link = 'https://cloudstore.zih.tu-dresden.de/index.php/login' + break + case 'tumail': + case 'tudmail': + link = 'https://msx.tu-dresden.de/owa/#path=/mail' + break + case 'hisqis': + link = 'https://qis.dez.tu-dresden.de/qisserver/servlet/de.his.servlet.RequestDispatcherServlet?state=template&template=user/news' + break + case 'tumed': + link = 'https://eportal.med.tu-dresden.de/login' + break + case 'selma': + link = 'https://selma.tu-dresden.de/APP/EXTERNALPAGES/-N000000000000001,-N000155,-AEXT_willkommen' + break + case 'tumatrix': + link = isEnabled ? 'https://matrix.tu-dresden.de/#/login' : 'https://matrix.tu-dresden.de/#/' + break + case 'magma': + link = 'https://bildungsportal.sachsen.de/magma/' + break + default: + fwd = false + } + if (fwd) { + event.preventDefault() + console.log(`fwd to ${link}`) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace(link) + } +} diff --git a/src/contentScripts/fwd_tumed.js b/src/contentScripts/fwd_tumed.js index 601f1ef5..f5971fd1 100644 --- a/src/contentScripts/fwd_tumed.js +++ b/src/contentScripts/fwd_tumed.js @@ -1,7 +1,7 @@ chrome.storage.local.get(['fwdEnabled'], function (result) { - if (result.fwdEnabled) { - console.log("fwd to https://eportal.med.tu-dresden.de/login") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - window.location.replace("https://eportal.med.tu-dresden.de/login") - } -}) \ No newline at end of file + if (result.fwdEnabled) { + console.log('fwd to https://eportal.med.tu-dresden.de/login') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + window.location.replace('https://eportal.med.tu-dresden.de/login') + } +}) diff --git a/src/contentScripts/gitlab.js b/src/contentScripts/gitlab.js index ece8ace9..41fdf026 100644 --- a/src/contentScripts/gitlab.js +++ b/src/contentScripts/gitlab.js @@ -1,27 +1,27 @@ chrome.storage.local.get(['isEnabled', 'loggedOutGitlab'], function (result) { - if (result.isEnabled && !result.loggedOutGitlab) { - document.addEventListener('DOMContentLoaded', function () { - if (document.getElementById('username') && document.getElementById("password")) { - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { - if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - document.getElementById('username').value = (result.asdf) - document.getElementById('password').value = (result.fdsa) - document.getElementsByTagName('input')[4].click() - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }) - } - }) - } - if (document.querySelectorAll(".sign-out-link")[0]) { - document.querySelectorAll(".sign-out-link")[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutGitlab' }) - }) - } + if (result.isEnabled && !result.loggedOutGitlab) { + document.addEventListener('DOMContentLoaded', function () { + if (document.getElementById('username') && document.getElementById('password')) { + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { + if (!(result.asdf === undefined || result.fdsa === undefined)) { + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + document.getElementById('username').value = (result.asdf) + document.getElementById('password').value = (result.fdsa) + document.getElementsByTagName('input')[4].click() + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } }) - console.log('Auto Login to gitlab.') - } else if (result.loggedOutGitlab) { - chrome.storage.local.set({ loggedOutGitlab: false }, function () { }) - } -}) \ No newline at end of file + } + if (document.querySelectorAll('.sign-out-link')[0]) { + document.querySelectorAll('.sign-out-link')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutGitlab' }) + }) + } + }) + console.log('Auto Login to gitlab.') + } else if (result.loggedOutGitlab) { + chrome.storage.local.set({ loggedOutGitlab: false }, function () { }) + } +}) diff --git a/src/contentScripts/idp.js b/src/contentScripts/idp.js index 6d4224cf..9efffde2 100644 --- a/src/contentScripts/idp.js +++ b/src/contentScripts/idp.js @@ -1,4 +1,4 @@ -console.log("injected login script successfully ...") +console.log('injected login script successfully ...') chrome.storage.local.get(['isEnabled'], function (result) { if (document.readyState !== 'loading') { logInQis(result.isEnabled) @@ -10,34 +10,28 @@ chrome.storage.local.get(['isEnabled'], function (result) { } }) -function logInQis(enabled) { - if (document.getElementById("username")) { - if (enabled) { //yes, this if-statements need to be nested! +function logInQis (enabled) { + if (document.getElementById('username')) { + if (enabled) { // yes, this if-statements need to be nested! chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { if (!(result.fdsa === undefined || result.asdf === undefined)) { - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) document.getElementById('username').value = (result.asdf) document.getElementById('password').value = (result.fdsa) - document.getElementsByName("_eventId_proceed")[0].click() + document.getElementsByName('_eventId_proceed')[0].click() } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) } }) } - } else if (document.getElementsByName("_eventId_proceed")[0]) { - document.getElementsByName("_eventId_proceed")[0].click() - chrome.runtime.sendMessage({ cmd: "perform_login" }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) + } else if (document.getElementsByName('_eventId_proceed')[0]) { + document.getElementsByName('_eventId_proceed')[0].click() + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) } else if (document.querySelectorAll('body > div:nth-child(2) > div:nth-child(1) > b')[0]) { - if (document.querySelectorAll('body > div:nth-child(2) > div:nth-child(1) > b')[0].innerHTML === "TUD - TU Dresden - Single Sign On - Veraltete Anfrage" || - document.querySelectorAll('body > div:nth-child(2) > div:nth-child(1) > b')[0].innerHTML === "TUD - TU Dresden - Single Sign On - Stale Request") { - window.location.replace("https://bildungsportal.sachsen.de/opal/login") + if (document.querySelectorAll('body > div:nth-child(2) > div:nth-child(1) > b')[0].innerHTML === 'TUD - TU Dresden - Single Sign On - Veraltete Anfrage' || + document.querySelectorAll('body > div:nth-child(2) > div:nth-child(1) > b')[0].innerHTML === 'TUD - TU Dresden - Single Sign On - Stale Request') { + window.location.replace('https://bildungsportal.sachsen.de/opal/login') } } } - - - - - - diff --git a/src/contentScripts/jexam.js b/src/contentScripts/jexam.js index fc909ac4..66c17984 100644 --- a/src/contentScripts/jexam.js +++ b/src/contentScripts/jexam.js @@ -1,28 +1,28 @@ chrome.storage.local.get(['isEnabled', 'loggedOutJexam'], function (result) { - if (result.isEnabled && !result.loggedOutJexam) { - document.addEventListener('DOMContentLoaded', function () { - if (document.getElementById('username') && document.getElementById("password")) { - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { - if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - document.getElementById('username').value = (result.asdf) - document.getElementById('password').value = (result.fdsa) - document.getElementsByTagName('input')[2].click() - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); - } - }); - } - if (document.getElementsByClassName("logout nav-entry animate-fade-in")[0]) { - document.getElementsByClassName("logout nav-entry animate-fade-in")[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutJexam' }) - }) - } + if (result.isEnabled && !result.loggedOutJexam) { + document.addEventListener('DOMContentLoaded', function () { + if (document.getElementById('username') && document.getElementById('password')) { + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { + if (!(result.asdf === undefined || result.fdsa === undefined)) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + document.getElementById('username').value = (result.asdf) + document.getElementById('password').value = (result.fdsa) + document.getElementsByTagName('input')[2].click() + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } }) - console.log('Auto Login to jexam.') - } else if (result.loggedOutJexam) { - chrome.storage.local.set({ loggedOutJexam: false }, function () { }) - } -}) \ No newline at end of file + } + if (document.getElementsByClassName('logout nav-entry animate-fade-in')[0]) { + document.getElementsByClassName('logout nav-entry animate-fade-in')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutJexam' }) + }) + } + }) + console.log('Auto Login to jexam.') + } else if (result.loggedOutJexam) { + chrome.storage.local.set({ loggedOutJexam: false }, function () { }) + } +}) diff --git a/src/contentScripts/magma.js b/src/contentScripts/magma.js index 4b8cae01..13ad8075 100644 --- a/src/contentScripts/magma.js +++ b/src/contentScripts/magma.js @@ -1,25 +1,24 @@ chrome.storage.local.get(['isEnabled', 'loggedOutMagma'], function (result) { - if (result.isEnabled && !result.loggedOutMagma) { - document.addEventListener("DOMContentLoaded", function () { - if (document.getElementsByName("loginButton")[0] && document.getElementsByName("wayfSelect")[0]) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - document.getElementsByName("wayfSelect")[0].value = "11" - document.getElementsByName("loginButton")[0].click() - } - if (document.querySelectorAll('#page > div:nth-child(3) > section > div:nth-child(3) > form > button')[0]) { - document.querySelectorAll('#page > div:nth-child(3) > section > div:nth-child(3) > form > button')[0].click() - } - //logout - if (document.querySelectorAll('#page > header > div:nth-child(2) > div > a')[0]) { - document.querySelectorAll('#page > header > div:nth-child(2) > div > a')[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutMagma' }) - }) - } + if (result.isEnabled && !result.loggedOutMagma) { + document.addEventListener('DOMContentLoaded', function () { + if (document.getElementsByName('loginButton')[0] && document.getElementsByName('wayfSelect')[0]) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + document.getElementsByName('wayfSelect')[0].value = '11' + document.getElementsByName('loginButton')[0].click() + } + if (document.querySelectorAll('#page > div:nth-child(3) > section > div:nth-child(3) > form > button')[0]) { + document.querySelectorAll('#page > div:nth-child(3) > section > div:nth-child(3) > form > button')[0].click() + } + // logout + if (document.querySelectorAll('#page > header > div:nth-child(2) > div > a')[0]) { + document.querySelectorAll('#page > header > div:nth-child(2) > div > a')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutMagma' }) }) - console.log("Auto Login to magma.") - } - else if (result.loggedOutMagma) { - chrome.storage.local.set({ loggedOutMagma: false }, function () { }) - } -}) \ No newline at end of file + } + }) + console.log('Auto Login to magma.') + } else if (result.loggedOutMagma) { + chrome.storage.local.set({ loggedOutMagma: false }, function () { }) + } +}) diff --git a/src/contentScripts/matrix.js b/src/contentScripts/matrix.js index 0e784ecb..73e67464 100644 --- a/src/contentScripts/matrix.js +++ b/src/contentScripts/matrix.js @@ -1,61 +1,62 @@ -//Mainly contributed by Daniel: https://github.com/C0ntroller +// Mainly contributed by Daniel: https://github.com/C0ntroller -function loginMatrix() { - //check if already loked in. - if (localStorage.getItem("mx_access_token")) { - var hash = window.location.hash; - //forward to home page, if already logged in - if (hash === '#/login') { - console.log("Already logged into matrix. Fwd to home page") - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - //window.location.replace("https://matrix.tu-dresden.de/") - window.location.hash = "#/home"; - location.reload() - } - return; +function loginMatrix () { + // check if already loked in. + if (localStorage.getItem('mx_access_token')) { + const hash = window.location.hash + // forward to home page, if already logged in + if (hash === '#/login') { + console.log('Already logged into matrix. Fwd to home page') + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + // window.location.replace("https://matrix.tu-dresden.de/") + window.location.hash = '#/home' + location.reload() } - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { - if (!(result.asdf === undefined || result.fdsa === undefined)) { - var url = 'https://matrix.tu-dresden.de/_matrix/client/r0/login'; - var params = '{"type":"m.login.password","password":"' + (result.fdsa) + '","identifier":{"type":"m.id.user","user":"' + (result.asdf) + '"},"initial_device_display_name":"Chrome Autologin"}'; + return + } + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { + if (!(result.asdf === undefined || result.fdsa === undefined)) { + const url = 'https://matrix.tu-dresden.de/_matrix/client/r0/login' + const params = '{"type":"m.login.password","password":"' + (result.fdsa) + '","identifier":{"type":"m.id.user","user":"' + (result.asdf) + '"},"initial_device_display_name":"Chrome Autologin"}' - var http = new XMLHttpRequest(); - http.open('POST', url, true); - http.setRequestHeader('Content-type', 'application/json; charset=utf-8'); - http.setRequestHeader('authority', 'matrix.tu-dresden.de'); - http.setRequestHeader('accept', 'application/json'); - http.setRequestHeader('content-type', 'application/json'); + const http = new XMLHttpRequest() + http.open('POST', url, true) + http.setRequestHeader('Content-type', 'application/json; charset=utf-8') + http.setRequestHeader('authority', 'matrix.tu-dresden.de') + http.setRequestHeader('accept', 'application/json') + http.setRequestHeader('content-type', 'application/json') - http.onreadystatechange = function () { - if (http.readyState == 4 && http.status == 200) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - console.log('Auto Login to matrix') + http.onreadystatechange = function () { + if (http.readyState === 4 && http.status === 200) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + console.log('Auto Login to matrix') - response = JSON.parse(http.responseText); - localStorage.setItem("mx_hs_url", "https://matrix.tu-dresden.de/"); - localStorage.setItem("mx_is_url", "https://matrix.tu-dresden.de/"); - localStorage.setItem("mx_device_id", response.device_id); - localStorage.setItem("mx_user_id", response.user_id); - localStorage.setItem("mx_access_token", response.access_token); - localStorage.setItem("mx_is_guest", "false"); + const response = JSON.parse(http.responseText) + localStorage.setItem('mx_hs_url', 'https://matrix.tu-dresden.de/') + localStorage.setItem('mx_is_url', 'https://matrix.tu-dresden.de/') + localStorage.setItem('mx_device_id', response.device_id) + localStorage.setItem('mx_user_id', response.user_id) + localStorage.setItem('mx_access_token', response.access_token) + localStorage.setItem('mx_is_guest', 'false') - window.location.replace("https://matrix.tu-dresden.de/") - } - } - http.send(params); - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); + window.location.replace('https://matrix.tu-dresden.de/') } - }); + } + http.send(params) + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } + }) } chrome.storage.local.get(['isEnabled'], function (result) { - if (result.isEnabled) { - var ctx = document.getElementById("matrixchat") - ctx.addEventListener("DOMSubtreeModified", function () { - this.removeEventListener("DOMSubtreeModified", arguments.callee); - loginMatrix(); - }); - } -}) \ No newline at end of file + if (result.isEnabled) { + const ctx = document.getElementById('matrixchat') + ctx.addEventListener('DOMSubtreeModified', function () { + // eslint-disable-next-line no-caller + this.removeEventListener('DOMSubtreeModified', arguments.callee) + loginMatrix() + }) + } +}) diff --git a/src/contentScripts/owa.js b/src/contentScripts/owa.js index 06fb7f38..c787735d 100644 --- a/src/contentScripts/owa.js +++ b/src/contentScripts/owa.js @@ -1,109 +1,108 @@ chrome.storage.local.get(['isEnabled', 'loggedOutOwa'], function (result) { - if (result.isEnabled && !result.loggedOutOwa) { - if (document.readyState !== 'loading') { - loginOWA(result.loggedOutOwa) - } else { - document.addEventListener('DOMContentLoaded', function () { - loginOWA(result.loggedOutOwa) - }) - } - console.log('Auto Login to OWA.') + if (result.isEnabled && !result.loggedOutOwa) { + if (document.readyState !== 'loading') { + loginOWA(result.loggedOutOwa) + } else { + document.addEventListener('DOMContentLoaded', function () { + loginOWA(result.loggedOutOwa) + }) } - //sometimes it reloades the page, sometimes it doesnt... - //else if(result.loggedOutOwa) { - // chrome.storage.local.set({loggedOutOwa: undefined}, function() {}) - // setTimeout(() => { chrome.storage.local.set({loggedOutOwa: false}, function() {}) }, 2000); - //} else if(result.loggedOutOwa === undefined) { - // chrome.storage.local.set({loggedOutOwa: false}, function() {}) - //} + console.log('Auto Login to OWA.') + } + // sometimes it reloades the page, sometimes it doesnt... + // else if(result.loggedOutOwa) { + // chrome.storage.local.set({loggedOutOwa: undefined}, function() {}) + // setTimeout(() => { chrome.storage.local.set({loggedOutOwa: false}, function() {}) }, 2000); + // } else if(result.loggedOutOwa === undefined) { + // chrome.storage.local.set({loggedOutOwa: false}, function() {}) + // } }) -//detecting logout -document.addEventListener("DOMNodeInserted", function (e) { - // old owa version - if (document.querySelectorAll('[aria-label="Abmelden"]')[0]) { - document.querySelectorAll('[aria-label="Abmelden"]')[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) - }) - } - // new owa version - if (document.querySelectorAll("[autoid='_ho2_2']")[1] && document.querySelectorAll("[autoid='_ho2_2']")[1].innerHTML == "Abmelden") { - document.querySelectorAll('[aria-label="Abmelden"]')[1].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) - }) - } -}, false); +// detecting logout +document.addEventListener('DOMNodeInserted', function (e) { + // old owa version + if (document.querySelectorAll('[aria-label="Abmelden"]')[0]) { + document.querySelectorAll('[aria-label="Abmelden"]')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) + }) + } + // new owa version + if (document.querySelectorAll("[autoid='_ho2_2']")[1] && document.querySelectorAll("[autoid='_ho2_2']")[1].innerHTML === 'Abmelden') { + document.querySelectorAll('[aria-label="Abmelden"]')[1].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) + }) + } +}, false) -function loginOWA(loggedOutOwa) { - if (document.getElementById('username') && document.getElementById('password') && !loggedOutOwa) { - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { - if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - document.getElementById('username').value = (result.asdf) + "@msx.tu-dresden.de" - document.getElementById('password').value = (result.fdsa) - document.getElementsByClassName('signinbutton')[0].click() - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); - } - }); - } - //detecting logout - if (document.querySelectorAll('[aria-label="Abmelden"]')[0]) { - document.querySelectorAll('[aria-label="Abmelden"]')[0].addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) - }) - } +function loginOWA (loggedOutOwa) { + if (document.getElementById('username') && document.getElementById('password') && !loggedOutOwa) { + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { + if (!(result.asdf === undefined || result.fdsa === undefined)) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + document.getElementById('username').value = (result.asdf) + '@msx.tu-dresden.de' + document.getElementById('password').value = (result.fdsa) + document.getElementsByClassName('signinbutton')[0].click() + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } + }) + } + // detecting logout + if (document.querySelectorAll('[aria-label="Abmelden"]')[0]) { + document.querySelectorAll('[aria-label="Abmelden"]')[0].addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutOwa' }) + }) + } } window.onload = function () { - chrome.storage.local.get(['enabledOWAFetch'], (resp) => { - if (resp.enabledOWAFetch) { - //check if all mails are loaded | also check for new owa version - let checkForNode = setInterval(() => { - this.console.log("checking") - if ((document.querySelectorAll("[autoid='_n_x1']")[1] && document.querySelectorAll("[autoid='_n_x1']")[1].textContent != "") || - (document.querySelectorAll("[autoid='_n_41']")[1] && document.querySelectorAll("[autoid='_n_41']")[1].textContent != "")) { - readMailObserver() - clearInterval(checkForNode) - } - }, 100); + chrome.storage.local.get(['enabledOWAFetch'], (resp) => { + if (resp.enabledOWAFetch) { + // check if all mails are loaded | also check for new owa version + const checkForNode = setInterval(() => { + this.console.log('checking') + if ((document.querySelectorAll("[autoid='_n_x1']")[1] && document.querySelectorAll("[autoid='_n_x1']")[1].textContent !== '') || + (document.querySelectorAll("[autoid='_n_41']")[1] && document.querySelectorAll("[autoid='_n_41']")[1].textContent !== '')) { + readMailObserver() + clearInterval(checkForNode) } - }) + }, 100) + } + }) } -function readMailObserver() { - //use mutation observer to detect page changes - const config = { attributes: true, childList: true, subtree: true, characterData: true } - const callback = function (mutationsList, observer) { - - //check again, if enabled - chrome.storage.local.get(['enabledOWAFetch'], (resp) => { - if (resp.enabledOWAFetch) { - - //get number of unread messages | also check for new owa version - try { - var NrUnreadMails = parseInt(document.querySelectorAll("[autoid='_n_x1']")[1].textContent) - } catch { - var NrUnreadMails = parseInt(document.querySelectorAll("[autoid='_n_41']")[1].textContent) - } +function readMailObserver () { + // use mutation observer to detect page changes + const config = { attributes: true, childList: true, subtree: true, characterData: true } + let nrUnreadMails + const callback = function (mutationsList, observer) { + // check again, if enabled + chrome.storage.local.get(['enabledOWAFetch'], (resp) => { + if (resp.enabledOWAFetch) { + // get number of unread messages | also check for new owa version - if (isNaN(NrUnreadMails)) NrUnreadMails = 0 + try { + nrUnreadMails = parseInt(document.querySelectorAll("[autoid='_n_x1']")[1].textContent) + } catch { + nrUnreadMails = parseInt(document.querySelectorAll("[autoid='_n_41']")[1].textContent) + } - console.log("Number of unread mails: " + NrUnreadMails) + if (isNaN(nrUnreadMails)) nrUnreadMails = 0 - chrome.runtime.sendMessage({ cmd: "read_mail_owa", NrUnreadMails: NrUnreadMails }) - } - }) + console.log('Number of unread mails: ' + nrUnreadMails) - } + chrome.runtime.sendMessage({ cmd: 'read_mail_owa', NrUnreadMails: nrUnreadMails }) + } + }) + } - //node containing unreadCount | also check new owa version - let unreadCountNode = document.querySelectorAll("[autoid='_n_41']")[1] - if (unreadCountNode == undefined) unreadCountNode = document.querySelectorAll("[autoid='_n_c']")[0] + // node containing unreadCount | also check new owa version + let unreadCountNode = document.querySelectorAll("[autoid='_n_41']")[1] + if (unreadCountNode === undefined) unreadCountNode = document.querySelectorAll("[autoid='_n_c']")[0] - const observer = new MutationObserver(callback); - observer.observe(unreadCountNode, config); + const observer = new MutationObserver(callback) + observer.observe(unreadCountNode, config) } diff --git a/src/contentScripts/parseOpal.js b/src/contentScripts/parseOpal.js index bc4db4a7..23f84d68 100644 --- a/src/contentScripts/parseOpal.js +++ b/src/contentScripts/parseOpal.js @@ -1,143 +1,138 @@ -chrome.storage.local.get(['isEnabled', 'seenInOpalAfterDashbaordUpdate', "removedOpalBanner", "saved_click_counter", "mostLiklySubmittedReview", "removedReviewBanner", "neverShowedReviewBanner"], function (result) { - - //decide whether to show dashbaord banner - let showDashboardBanner = false - if (result.seenInOpalAfterDashbaordUpdate < 5 && !result.removedOpalBanner) { showDashboardBanner = true } - chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: result.seenInOpalAfterDashbaordUpdate + 1 }, function () { }) - - - //wait until full page is loaded - window.addEventListener("load", async function (e) { - - let oldLocationHref = location.href - let parsedCourses = false +chrome.storage.local.get(['isEnabled', 'seenInOpalAfterDashbaordUpdate', 'removedOpalBanner', 'saved_click_counter', 'mostLiklySubmittedReview', 'removedReviewBanner', 'neverShowedReviewBanner'], function (result) { + // decide whether to show dashbaord banner + let showDashboardBanner = false + if (result.seenInOpalAfterDashbaordUpdate < 5 && !result.removedOpalBanner) { showDashboardBanner = true } + chrome.storage.local.set({ seenInOpalAfterDashbaordUpdate: result.seenInOpalAfterDashbaordUpdate + 1 }, function () { }) + + // wait until full page is loaded + window.addEventListener('load', async function (e) { + let oldLocationHref = location.href + let parsedCourses = false + + // show banner + if (showDashboardBanner) { showDashboardBannerFunc() } + // + + // if all courses loaded --> parse + if (!document.getElementsByClassName('pager-showall')[0]) { + chrome.runtime.sendMessage({ cmd: 'save_courses', course_list: parseCoursesFromWebPage() }) + parsedCourses = true + // if not --> load all courses + } else { + document.getElementsByClassName('pager-showall')[0].click() + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + parsedCourses = false + } - // show banner - if (showDashboardBanner) { showDashboardBannerFunc() } - // + // close banner buttons + if (this.document.getElementById('closeOpalBanner')) { + this.document.getElementById('closeOpalBanner').onclick = closeOpalBanner + } - //if all courses loaded --> parse - if (!document.getElementsByClassName("pager-showall")[0]) { - chrome.runtime.sendMessage({ cmd: "save_courses", course_list: parseCoursesFromWebPage() }) - parsedCourses = true - //if not --> load all courses - } else { - document.getElementsByClassName("pager-showall")[0].click() - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - parsedCourses = false + // use mutation observer to detect page changes + const config = { attributes: true, childList: true, subtree: true } + const callback = function (mutationsList, observer) { + // detect new page + if (location.href !== oldLocationHref) { + oldLocationHref = location.href + // all courses loaded already --> parse directly + if (!document.getElementsByClassName('pager-showall')[0]) { + const courseList = parseCoursesFromWebPage() + chrome.runtime.sendMessage({ cmd: 'save_courses', course_list: courseList }) + parsedCourses = true } - - //close banner buttons - if (this.document.getElementById("closeOpalBanner")) { - this.document.getElementById("closeOpalBanner").onclick = closeOpalBanner + // not all courses loaded already --> load all courses + if (document.getElementsByClassName('pager-showall')[0].innerText === 'alle anzeigen') { + document.getElementsByClassName('pager-showall')[0].click() + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + parsedCourses = false } + } - //use mutation observer to detect page changes - const config = { attributes: true, childList: true, subtree: true } - const callback = function (mutationsList, observer) { - - //detect new page - if (location.href != oldLocationHref) { - oldLocationHref = location.href - //all courses loaded already --> parse directly - if (!document.getElementsByClassName("pager-showall")[0]) { - let course_list = parseCoursesFromWebPage() - chrome.runtime.sendMessage({ cmd: "save_courses", course_list: course_list }) - parsedCourses = true - } - //not all courses loaded already --> load all courses - if (document.getElementsByClassName("pager-showall")[0].innerText === "alle anzeigen") { - document.getElementsByClassName("pager-showall")[0].click() - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - parsedCourses = false - } - } - - //parse courses - if (document.getElementsByClassName("pager-showall")[0]) { - if (document.getElementsByClassName("pager-showall")[0].innerText === "Seiten" && !parsedCourses) { - chrome.runtime.sendMessage({ cmd: "save_courses", course_list: parseCoursesFromWebPage() }) - parsedCourses = true - } - } + // parse courses + if (document.getElementsByClassName('pager-showall')[0]) { + if (document.getElementsByClassName('pager-showall')[0].innerText === 'Seiten' && !parsedCourses) { + chrome.runtime.sendMessage({ cmd: 'save_courses', course_list: parseCoursesFromWebPage() }) + parsedCourses = true } - const observer = new MutationObserver(callback); - observer.observe(document.body, config); - }, true) + } + } + const observer = new MutationObserver(callback) + observer.observe(document.body, config) + }, true) }) -function closeOpalBanner() { - if (document.getElementById("opalBanner")) { - document.getElementById("opalBanner").remove() - chrome.storage.local.set({ removedOpalBanner: true }, function () { }) - } +function closeOpalBanner () { + if (document.getElementById('opalBanner')) { + document.getElementById('opalBanner').remove() + chrome.storage.local.set({ removedOpalBanner: true }, function () { }) + } } // CSS found in banner.css -function showDashboardBannerFunc() { - // create banner div - const banner = document.createElement("div") - banner.classList.add("banner") - // create image for rocket - const img = document.createElement("img") - img.classList.add("banner__icon") - img.src = chrome.runtime.getURL("../assets/icons/RocketIcons/default_128px.png") - // create title - const title = document.createElement("h2") - title.classList.add("banner__title") - title.innerHTML = "Hier Dashboard öffnen oder Alt + Q drücken" - // create close button - const button = document.createElement("button") - button.classList.add("banner__close") - button.innerHTML = "×" - button.addEventListener("click", () => { - banner.remove() - chrome.storage.local.set({ removedOpalBanner: true }, () => {}) - }) - - banner.appendChild(img) - banner.appendChild(title) - banner.appendChild(button) - document.body.appendChild(banner) +function showDashboardBannerFunc () { + // create banner div + const banner = document.createElement('div') + banner.classList.add('banner') + // create image for rocket + const img = document.createElement('img') + img.classList.add('banner__icon') + img.src = chrome.runtime.getURL('../assets/icons/RocketIcons/default_128px.png') + // create title + const title = document.createElement('h2') + title.classList.add('banner__title') + title.innerHTML = 'Hier Dashboard öffnen oder Alt + Q drücken' + // create close button + const button = document.createElement('button') + button.classList.add('banner__close') + button.innerHTML = '×' + button.addEventListener('click', () => { + banner.remove() + chrome.storage.local.set({ removedOpalBanner: true }, () => {}) + }) + + banner.appendChild(img) + banner.appendChild(title) + banner.appendChild(button) + document.body.appendChild(banner) } -function parseCoursesFromWebPage() { - let course_list = { type: "", list: [] } - if (location.pathname === "/opal/auth/resource/courses") { course_list.type = "meine_kurse" } - if (location.pathname === "/opal/auth/resource/favorites") { course_list.type = "favoriten" } - //there are two options, how the coursse-overview table can be build. - //They are simply tried out - try { - let tableEntries = document.getElementsByClassName("table-panel")[0].getElementsByTagName("tbody")[0].children - for (let item of tableEntries) { - let name = item.children[2].children[0].getAttribute("title") - let link = item.children[2].children[0].getAttribute("href") - course_list.list.push({ name: name, link: link }) - } - //There is a reported case, where no error is thrown and course_list has entries, but all of them are empty - //Of course this is not wanted. So in this case, also throw an error - let getAllNullEntries = course_list.list.filter(el => !el.link && !el.name) //this contains all entries, where link and name is false (i.e. null) - if (getAllNullEntries.length > 2) { //when more than two null-entries: most likely unwanted case - course_list = { type: "", list: [] } //reset course list - throw 'most likely parsing error'; //throw error - } - } catch { - let tableEntries = document.getElementsByClassName("table-panel")[0].getElementsByClassName("content-preview-container")[0].getElementsByClassName("list-unstyled")[0].getElementsByClassName("content-preview content-preview-horizontal") - for (let item of tableEntries) { - try { - let name = item.getElementsByClassName("content-preview-title")[0].innerHTML - let link = item.children[3].getAttribute("href") - course_list.list.push({ name: name, link: link }) - } - catch (e) {console.log("Error in parsing course list. Could not parse course list: " + e) } - } +function parseCoursesFromWebPage () { + let courseList = { type: '', list: [] } + if (location.pathname === '/opal/auth/resource/courses') { courseList.type = 'meine_kurse' } + if (location.pathname === '/opal/auth/resource/favorites') { courseList.type = 'favoriten' } + // there are two options, how the coursse-overview table can be build. + // They are simply tried out + try { + const tableEntries = document.getElementsByClassName('table-panel')[0].getElementsByTagName('tbody')[0].children + for (const item of tableEntries) { + const name = item.children[2].children[0].getAttribute('title') + const link = item.children[2].children[0].getAttribute('href') + courseList.list.push({ name: name, link: link }) + } + // There is a reported case, where no error is thrown and course_list has entries, but all of them are empty + // Of course this is not wanted. So in this case, also throw an error + const getAllNullEntries = courseList.list.filter(el => !el.link && !el.name) // this contains all entries, where link and name is false (i.e. null) + if (getAllNullEntries.length > 2) { // when more than two null-entries: most likely unwanted case + courseList = { type: '', list: [] } // reset course list + throw new Error('most likely parsing error') // throw error + } + } catch { + const tableEntries = document.getElementsByClassName('table-panel')[0].getElementsByClassName('content-preview-container')[0].getElementsByClassName('list-unstyled')[0].getElementsByClassName('content-preview content-preview-horizontal') + for (const item of tableEntries) { + try { + const name = item.getElementsByClassName('content-preview-title')[0].innerHTML + const link = item.children[3].getAttribute('href') + courseList.list.push({ name: name, link: link }) + } catch (e) { console.log('Error in parsing course list. Could not parse course list: ' + e) } } + } - //alert, if still null-entries found - let getAllNullEntriesFinal = course_list.list.filter(el => !el.link && !el.name) - if(getAllNullEntriesFinal.length > 0) {console.log("Possible Error in parsing courses. Found null entries.")} - //if present, remove all null entries - course_list.list = course_list.list.filter(el => !(!el.link && !el.name)) + // alert, if still null-entries found + const getAllNullEntriesFinal = courseList.list.filter(el => !el.link && !el.name) + if (getAllNullEntriesFinal.length > 0) { console.log('Possible Error in parsing courses. Found null entries.') } + // if present, remove all null entries + courseList.list = courseList.list.filter(el => !(!el.link && !el.name)) - return course_list + return courseList } diff --git a/src/contentScripts/pimpHISQIS.js b/src/contentScripts/pimpHISQIS.js index f694b04a..b0882631 100644 --- a/src/contentScripts/pimpHISQIS.js +++ b/src/contentScripts/pimpHISQIS.js @@ -1,135 +1,135 @@ -console.log("Pimping up hisqis...") +console.log('Pimping up hisqis...') chrome.storage.local.get(['isEnabled'], function (result) { - //if (result.isEnabled) { - document.addEventListener("DOMContentLoaded", function () { - let imgUrl = chrome.runtime.getURL("../assets/images/tufast48.png") - let rawGrades = parseGrades() - $("table[summary!='Liste der Stammdaten des Studierenden']").parent().eq(2).children().eq(3).after( - '

Deine Durchschnittnote (nach CP gewichtet): ' + getWeightedAverage(rawGrades) + '

Anzahl Module: ' + rawGrades.filter(x => x.isModule).length + '

Anzahl Prüfungen: ' + rawGrades.filter(x => !x.isModule).length + '

powered by TUfast (entwickelt von Noxdor, Daniel)

Wechsle zur ... nocht nicht für Firefox!

' - ) - var ctx = document.getElementById('myChart').getContext('2d') - ctx.canvas.width = 500 - ctx.canvas.height = 250 - var myChart = new Chart(ctx, { - type: 'bar', - data: { - labels: ['1', '2', '3', '4', 'nicht bestanden'], - datasets: [{ - data: countGrades(rawGrades.filter(x => !x.isModule)), - backgroundColor: [ - '#0b2a51', - '#0b2a51', - '#0b2a51', - '#0b2a51', - '#0b2a51', - ], - borderColor: [ - '#0b2a51', - ], - borderWidth: 1 - }] - }, - options: { - responsive: false, - maintainAspectRatio: false, - legend: { - display: false, - }, - scales: { - yAxes: [{ - ticks: { - beginAtZero: true - } - }], - xAxes: [{ - scaleLabel: { - //display: true, - //labelString: "here" - } - }] - } + // if (result.isEnabled) { + document.addEventListener('DOMContentLoaded', function () { + const imgUrl = chrome.runtime.getURL('../assets/images/tufast48.png') + const rawGrades = parseGrades() + $("table[summary!='Liste der Stammdaten des Studierenden']").parent().eq(2).children().eq(3).after( + '

Deine Durchschnittnote (nach CP gewichtet): ' + getWeightedAverage(rawGrades) + '

Anzahl Module: ' + rawGrades.filter(x => x.isModule).length + '

Anzahl Prüfungen: ' + rawGrades.filter(x => !x.isModule).length + '

powered by TUfast (entwickelt von Noxdor, Daniel)

Wechsle zur ... nocht nicht für Firefox!

' + ) + const ctx = document.getElementById('myChart').getContext('2d') + ctx.canvas.width = 500 + ctx.canvas.height = 250 + // eslint-disable-next-line no-unused-vars, no-undef + const myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: ['1', '2', '3', '4', 'nicht bestanden'], + datasets: [{ + data: countGrades(rawGrades.filter(x => !x.isModule)), + backgroundColor: [ + '#0b2a51', + '#0b2a51', + '#0b2a51', + '#0b2a51', + '#0b2a51' + ], + borderColor: [ + '#0b2a51' + ], + borderWidth: 1 + }] + }, + options: { + responsive: false, + maintainAspectRatio: false, + legend: { + display: false + }, + scales: { + yAxes: [{ + ticks: { + beginAtZero: true } - }) - + }], + xAxes: [{ + scaleLabel: { + // display: true, + // labelString: "here" + } + }] + } + } }) - //} + }) + // } }) -//returns: [{grade: X.X, isModule: true}] -//only count subjects (not modules!) -function parseGrades() { - var grades = [] - var $ = this.$ - - $("table[summary!='Liste der Stammdaten des Studierenden'] > tbody").children().each(function () { +// returns: [{grade: X.X, isModule: true}] +// only count subjects (not modules!) +function parseGrades () { + const grades = [] + const $ = this.$ - //Skip stuff - if ($(this).children().attr('class') === 'Konto' || + $("table[summary!='Liste der Stammdaten des Studierenden'] > tbody").children().each(function () { + // Skip stuff + if ($(this).children().attr('class') === 'Konto' || $(this).children().attr('class') === 'tabelleheader' || $(this).children().eq(1).text().trim() === 'Zurück' || $(this).children().eq(1).attr('bgcolor') === '#ADADAD' - ) { return true } + ) { return true } - let grade = $(this).children().eq(3).text().trim() - let isModule = $(this).children().eq(1).attr('bgcolor') == '#DDDDDD' - let exam = $(this).children().eq(1).text().trim() - let weight = isModule ? parseInt($(this).children().eq(7).text().trim()) : 0 + let grade = $(this).children().eq(3).text().trim() + const isModule = $(this).children().eq(1).attr('bgcolor') === '#DDDDDD' + const exam = $(this).children().eq(1).text().trim() + let weight = isModule ? parseInt($(this).children().eq(7).text().trim()) : 0 + if (isNaN(weight)) { weight = 0 } - //Skip more stuff - if (exam === '') { return true } - if (exam === 'Gesamtnote Zwischenprüfung') { return } - if (grade === "") { return } - else { grade = parseFloat(grade.replace(",", ".")) } + // Skip more stuff + if (exam === '') { return true } + if (exam === 'Gesamtnote Zwischenprüfung') { return } + if (grade === '') { return } else { grade = parseFloat(grade.replace(',', '.')) } - grades.push({ 'grade': grade, 'isModule': isModule, 'weight': weight }) - }) - return grades + grades.push({ grade: grade, isModule: isModule, weight: weight }) + }) + return grades } -//return counted number of rounded grades for display -//also showing failed exams which were passed later -function countGrades(rawGrades) { - var gradesCount = [0, 0, 0, 0, 0] - rawGrades.forEach(function (info) { - let grade = Math.round(info.grade) - switch (grade) { - case 1: - gradesCount[0] = gradesCount[0] + 1 - break - case 2: - gradesCount[1] = gradesCount[1] + 1 - break - case 3: - gradesCount[2] = gradesCount[2] + 1 - break - case 4: - gradesCount[3] = gradesCount[3] + 1 - break - case 5: - gradesCount[4] = gradesCount[4] + 1 - break - default: - break - } - }) - return gradesCount +// return counted number of rounded grades for display +// also showing failed exams which were passed later +function countGrades (rawGrades) { + const gradesCount = [0, 0, 0, 0, 0] + rawGrades.forEach(function (info) { + const grade = Math.round(info.grade) + switch (grade) { + case 1: + gradesCount[0] = gradesCount[0] + 1 + break + case 2: + gradesCount[1] = gradesCount[1] + 1 + break + case 3: + gradesCount[2] = gradesCount[2] + 1 + break + case 4: + gradesCount[3] = gradesCount[3] + 1 + break + case 5: + gradesCount[4] = gradesCount[4] + 1 + break + default: + break + } + }) + return gradesCount } -//return arithmetic grade average -//not counting failed exams! -function getArithAverage(rawGrades) { - //first get all grade-objects that aren't failed, then map it directly as number - let grades = rawGrades.filter(x => x.grade !== 5.0 && !x.isModule).map(x => x.grade) - return grades.length ? (grades.reduce((acc, value) => acc + value, 0) / grades.length).toFixed(1) : 0 -} +// return arithmetic grade average +// not counting failed exams! +// function getArithAverage (rawGrades) { +// // first get all grade-objects that aren't failed, then map it directly as number +// const grades = rawGrades.filter(x => x.grade !== 5.0 && !x.isModule).map(x => x.grade) +// return grades.length ? (grades.reduce((acc, value) => acc + value, 0) / grades.length).toFixed(1) : 0 +// } -//return weighted grade average -//not counting failed modules! -function getWeightedAverage(rawGrades) { - let grades = rawGrades.filter(x => x.grade !== 5.0 && x.isModule) - let totalWeight = grades.reduce((acc, value) => acc + value.weight, 0) - return totalWeight ? (grades.reduce((acc, value) => acc + value.grade * value.weight, 0) / totalWeight).toFixed(1) : 0 +// return weighted grade average +// not counting failed modules! +function getWeightedAverage (rawGrades) { + const grades = rawGrades.filter(x => x.grade !== 5.0 && x.isModule) + const totalWeight = grades.reduce((acc, value) => acc + value.weight, 0) // BUG: + return totalWeight ? (grades.reduce((acc, value) => acc + value.grade * value.weight, 0) / totalWeight).toFixed(1) : 0 } -undefined \ No newline at end of file +// eslint-disable-next-line no-unused-expressions +undefined diff --git a/src/contentScripts/pimpHISQIS_table.js b/src/contentScripts/pimpHISQIS_table.js index 639c55a9..83e5383d 100644 --- a/src/contentScripts/pimpHISQIS_table.js +++ b/src/contentScripts/pimpHISQIS_table.js @@ -1,107 +1,114 @@ -console.log("pimping table ... maybe :)") +console.log('pimping table ... maybe :)') -//this needs to be done first -let oldTable = document.getElementsByTagName('table')[2] -let changeTableLink = document.getElementById("changeTableLink") +// this needs to be done first +const oldTable = document.getElementsByTagName('table')[2] +const changeTableLink = document.getElementById('changeTableLink') -//insert pimped table with style display:none +// insert pimped table with style display:none getGradesFromTable() -let pimpedTable = document.getElementById('pimpedTable') +const pimpedTable = document.getElementById('pimpedTable') -//check if hisqisPimpedTable is activated +// check if hisqisPimpedTable is activated chrome.storage.local.get(['hisqisPimpedTable'], function (result) { - result.hisqisPimpedTable ? setPimpedTable() : setOldTable() + result.hisqisPimpedTable ? setPimpedTable() : setOldTable() }) -//listen for event for switching table +// listen for event for switching table changeTableLink.onclick = function () { - let pimpedTableActivated = pimpedTable.style.display == "none" ? false : true + const pimpedTableActivated = pimpedTable.style.display !== 'none' - //switch table - pimpedTableActivated ? setOldTable() : setPimpedTable() - //store permanently - chrome.storage.local.set({ hisqisPimpedTable: !pimpedTableActivated }, function () { }) + // switch table + pimpedTableActivated ? setOldTable() : setPimpedTable() + // store permanently + chrome.storage.local.set({ hisqisPimpedTable: !pimpedTableActivated }, function () { }) } -function setPimpedTable() { - oldTable.style.display = "none" - pimpedTable.style.display = "block" - changeTableLink.innerHTML = "langweiligen, alten Tabelle." +function setPimpedTable () { + oldTable.style.display = 'none' + pimpedTable.style.display = 'block' + changeTableLink.innerHTML = 'langweiligen, alten Tabelle.' } -function setOldTable() { - oldTable.style.display = "block" - pimpedTable.style.display = "none" - changeTableLink.innerHTML = "neuen, coolen TUfast-Tabelle 🔥 (Beta)." +function setOldTable () { + oldTable.style.display = 'block' + pimpedTable.style.display = 'none' + changeTableLink.innerHTML = 'neuen, coolen TUfast-Tabelle 🔥 (Beta).' } -function getGradesFromTable() { - // create container for vuejs table - const container = document.createElement('div') - container.id = 'container' - const atable = document.getElementsByTagName('table')[2] - // console.log(atable); - atable.insertAdjacentElement('afterend', container) - container.innerHTML = table_html - - let table = [] - // second table is the grade table - // first table row index with useful information: 2 - const tableRows = [...document.getElementsByTagName('tbody')[2].getElementsByTagName('tr')] - - // collect all data from the table - tableRows.forEach((row) => { - let new_row = []; - [...row.cells].forEach((table_data) => { - if (table_data.lastElementChild === null) { - new_row.push(table_data.innerHTML.trim().replace(/&.*;/, '')) - } else { - new_row.push(table_data.lastElementChild.innerHTML.trim().replace(/&.*;/, '')) - } - }) - table.push(new_row) +function getGradesFromTable () { + // create container for vuejs table + const container = document.createElement('div') + container.id = 'container' + const atable = document.getElementsByTagName('table')[2] + // console.log(atable); + atable.insertAdjacentElement('afterend', container) + container.innerHTML = table_html + + const table = [] + // second table is the grade table + // first table row index with useful information: 2 + const tableRows = [...document.getElementsByTagName('tbody')[2].getElementsByTagName('tr')] + + // collect all data from the table + tableRows.forEach((row) => { + const newRow = []; + [...row.cells].forEach((tableData) => { + if (tableData.lastElementChild === null) { + newRow.push(tableData.innerHTML.trim().replace(/&.*;/, '')) + } else { + newRow.push(tableData.lastElementChild.innerHTML.trim().replace(/&.*;/, '')) + } }) - - //if first row is Prüfungsnr., then we need to add dummy row[0] - //this is required, because there are two different views of the hisqis table, dependent on how you navigate there - if (table[0][0] == "Prüfungsnr.") table.unshift(["dummy"]) - - // remove that ugly table from the page - oldTable.style.display = 'none' - - let levels = { - mainLevel: [], - moduleLevel: [], - examLevel: [] - } + table.push(newRow) + }) + + // if first row is Prüfungsnr., then we need to add dummy row[0] + // this is required, because there are two different views of the hisqis table, dependent on how you navigate there + if (table[0][0] === 'Prüfungsnr.') table.unshift(['dummy']) + + // remove that ugly table from the page + oldTable.style.display = 'none' - // Logic to figure out which row is a section, module or exam - table.filter((row, index) => row[0][1] === '0' || parseInt(row[0]) < 1000 ? levels.mainLevel.push(index) : []) - table.filter((row, index) => row[0].slice(-2)[0] === '0' && levels.mainLevel.indexOf(index) < 0 ? levels.moduleLevel.push(index) : []) - table.filter((row, index) => levels.mainLevel.indexOf(index) < 0 && levels.moduleLevel.indexOf(index) < 0 && index > 2 ? levels.examLevel.push(index) : []) + const levels = { + mainLevel: [], + moduleLevel: [], + examLevel: [] + } - runVue(table, levels) + // Logic to figure out which row is a section, module or exam + table.filter((row, index) => row[0][1] === '0' || parseInt(row[0]) < 1000 ? levels.mainLevel.push(index) : []) + table.filter((row, index) => row[0].slice(-2)[0] === '0' && levels.mainLevel.indexOf(index) < 0 ? levels.moduleLevel.push(index) : []) + table.filter((row, index) => levels.mainLevel.indexOf(index) < 0 && levels.moduleLevel.indexOf(index) < 0 && index > 2 ? levels.examLevel.push(index) : []) + + runVue(table, levels) } // Vue.js logic, attaches Vue to the new container under the old table and draws the new table -function runVue(table, levels) { - new Vue({ - el: '#container', - data: { - table, - levels, - }, - methods: { - getColour(row_index, row) { - row_index += 2 - const passedText = row[5] - return this.levels.mainLevel.indexOf(row_index) > -1 ? 'dark' : - this.levels.moduleLevel.indexOf(row_index) > -1 ? 'primary' : - passedText === '' ? 'dark' : passedText === 'bestanden' ? 'success' : - passedText === 'in Bearbeitung' ? 'warn' : 'danger' - } - } - }) +function runVue (table, levels) { + // eslint-disable-next-line no-new, no-undef + new Vue({ + el: '#container', + data: { + table, + levels + }, + methods: { + getColour (rowIndex, row) { + rowIndex += 2 + const passedText = row[5] + return this.levels.mainLevel.indexOf(rowIndex) > -1 + ? 'dark' + : this.levels.moduleLevel.indexOf(rowIndex) > -1 + ? 'primary' + : passedText === '' + ? 'dark' + : passedText === 'bestanden' + ? 'success' + : passedText === 'in Bearbeitung' ? 'warn' : 'danger' + } + } + }) } +// eslint-disable-next-line no-unused-expressions undefined diff --git a/src/contentScripts/qis.js b/src/contentScripts/qis.js index 37f1c2af..37418476 100644 --- a/src/contentScripts/qis.js +++ b/src/contentScripts/qis.js @@ -13,30 +13,28 @@ chrome.storage.local.get(['isEnabled', 'loggedOutQis'], function (result) { } }) -function loginQis(isEnabled) { - if (document.getElementsByTagName('a')[4].innerText === "Ich habe die Nutzungsbedingungen gelesen, verstanden und akzeptiert. >>>") { +function loginQis (isEnabled) { + if (document.getElementsByTagName('a')[4].innerText === 'Ich habe die Nutzungsbedingungen gelesen, verstanden und akzeptiert. >>>') { document.getElementsByTagName('a')[4].click() - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - } else if (document.getElementById("asdf") && isEnabled) { + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + } else if (document.getElementById('asdf') && isEnabled) { chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) document.getElementById('asdf').value = result.asdf document.getElementById('fdsa').value = result.fdsa document.getElementsByName('submit')[0].click() } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) } - }); + }) } - //abmelden button + // abmelden button if (document.querySelectorAll('#visual-footer-wrapper :nth-child(5)')[0]) { document.querySelectorAll('#visual-footer-wrapper :nth-child(5)')[0].addEventListener('click', function () { chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutQis' }) }) } } - - diff --git a/src/contentScripts/selma.js b/src/contentScripts/selma.js index 3762c699..a0731ce8 100644 --- a/src/contentScripts/selma.js +++ b/src/contentScripts/selma.js @@ -1,32 +1,32 @@ chrome.storage.local.get(['isEnabled', 'loggedOutSelma'], function (result) { - if (result.isEnabled && !result.loggedOutSelma) { - document.addEventListener('DOMContentLoaded', function () { - if (document.getElementById('field_user')) { - chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (response) { - if (!(response.asdf === undefined || response.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 1 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - document.getElementById('field_user').value = response.asdf - document.getElementById('field_pass').value = response.fdsa - document.getElementById('logIn_btn').click() - } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); - } - }) - } - //abmelden button - if (document.getElementById('logOut_btn')) { - document.getElementById('logOut_btn').addEventListener('click', function () { - chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutSelma' }) - }) - } + if (result.isEnabled && !result.loggedOutSelma) { + document.addEventListener('DOMContentLoaded', function () { + if (document.getElementById('field_user')) { + chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (response) { + if (!(response.asdf === undefined || response.fdsa === undefined)) { + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 1 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + document.getElementById('field_user').value = response.asdf + document.getElementById('field_pass').value = response.fdsa + document.getElementById('logIn_btn').click() + } else { + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) + } }) - console.log('Auto Login to Selma.') - //page is reloaded two times - } else if (result.loggedOutSelma) { - chrome.storage.local.set({ loggedOutSelma: undefined }, function () { }) - } else if (result.loggedOutSelma === undefined) { - chrome.storage.local.set({ loggedOutSelma: false }, function () { }) - } -}) \ No newline at end of file + } + // abmelden button + if (document.getElementById('logOut_btn')) { + document.getElementById('logOut_btn').addEventListener('click', function () { + chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutSelma' }) + }) + } + }) + console.log('Auto Login to Selma.') + // page is reloaded two times + } else if (result.loggedOutSelma) { + chrome.storage.local.set({ loggedOutSelma: undefined }, function () { }) + } else if (result.loggedOutSelma === undefined) { + chrome.storage.local.set({ loggedOutSelma: false }, function () { }) + } +}) diff --git a/src/contentScripts/tex.js b/src/contentScripts/tex.js index f67c32ca..455a86bd 100644 --- a/src/contentScripts/tex.js +++ b/src/contentScripts/tex.js @@ -1,31 +1,30 @@ -chrome.storage.local.get(["loggedOutTex"], function (result) { - if (!result.loggedOutTex) { - //there is only a button and no reason to not click - document.addEventListener('DOMContentLoaded', function () { - document.querySelectorAll("a[href='/saml/login/go']")[0].click(); - console.log("Auto Login to tex."); - }) - } else if (result.loggedOutTex) { - chrome.storage.local.set({ loggedOutTex: false }, function () { }); - } -}); +chrome.storage.local.get(['loggedOutTex'], function (result) { + if (!result.loggedOutTex) { + // there is only a button and no reason to not click + document.addEventListener('DOMContentLoaded', function () { + document.querySelectorAll("a[href='/saml/login/go']")[0].click() + console.log('Auto Login to tex.') + }) + } else if (result.loggedOutTex) { + chrome.storage.local.set({ loggedOutTex: false }, function () { }) + } +}) document.addEventListener('DOMContentLoaded', function () { - //add event listener for log-out button - var buttons = document.querySelectorAll( - "button.btn-link.text-left.dropdown-menu-button" - ); - for (var i = 0; i < buttons.length; i++) { - if (buttons[i].innerHTML.indexOf("Log Out") != -1) { - //listen for click - buttons[i].addEventListener("click", function () { - chrome.runtime.sendMessage({ - cmd: "logged_out", - portal: "loggedOutTex", - }); - console.log("Logged out Tex") - }); - } + // add event listener for log-out button + const buttons = document.querySelectorAll( + 'button.btn-link.text-left.dropdown-menu-button' + ) + for (let i = 0; i < buttons.length; i++) { + if (buttons[i].innerHTML.indexOf('Log Out') !== -1) { + // listen for click + buttons[i].addEventListener('click', function () { + chrome.runtime.sendMessage({ + cmd: 'logged_out', + portal: 'loggedOutTex' + }) + console.log('Logged out Tex') + }) } + } }) - diff --git a/src/contentScripts/tumed.js b/src/contentScripts/tumed.js index c8af80af..ea69a9f0 100644 --- a/src/contentScripts/tumed.js +++ b/src/contentScripts/tumed.js @@ -1,23 +1,24 @@ chrome.storage.local.get(['isEnabled', 'loggedOutTumed'], function (result) { if (result.isEnabled && !result.loggedOutTumed) { document.addEventListener('DOMContentLoaded', function () { - if (document.querySelectorAll(`label[for=__ac_name]`)[0].textContent === "Benutzername" && document.querySelectorAll(`label[for=__ac_password]`)[0].textContent === "Passwort" && document.getElementById("__ac_name") && document.getElementById("__ac_password")) + if (document.querySelectorAll('label[for=__ac_name]')[0].textContent === 'Benutzername' && document.querySelectorAll('label[for=__ac_password]')[0].textContent === 'Passwort' && document.getElementById('__ac_name') && document.getElementById('__ac_password')) { chrome.runtime.sendMessage({ cmd: 'get_user_data' }, function (result) { if (!(result.asdf === undefined || result.fdsa === undefined)) { - chrome.runtime.sendMessage({ cmd: "show_ok_badge", timeout: 2000 }) - chrome.runtime.sendMessage({ cmd: "save_clicks", click_count: 2 }) - chrome.runtime.sendMessage({ cmd: "perform_login" }) - document.getElementById("__ac_name").value = result.asdf - document.getElementById("__ac_password").value = result.fdsa - document.querySelectorAll(`input[value=Anmelden]`)[0].click() + chrome.runtime.sendMessage({ cmd: 'show_ok_badge', timeout: 2000 }) + chrome.runtime.sendMessage({ cmd: 'save_clicks', click_count: 2 }) + chrome.runtime.sendMessage({ cmd: 'perform_login' }) + document.getElementById('__ac_name').value = result.asdf + document.getElementById('__ac_password').value = result.fdsa + document.querySelectorAll('input[value=Anmelden]')[0].click() } else { - chrome.runtime.sendMessage({ cmd: "no_login_data" }); + chrome.runtime.sendMessage({ cmd: 'no_login_data' }) } }) + } - //abmelden button - if (document.getElementById("personaltools-logout")) { - document.getElementById("personaltools-logout").addEventListener('click', function () { + // abmelden button + if (document.getElementById('personaltools-logout')) { + document.getElementById('personaltools-logout').addEventListener('click', function () { chrome.runtime.sendMessage({ cmd: 'logged_out', portal: 'loggedOutTumed' }) }) } @@ -26,4 +27,4 @@ chrome.storage.local.get(['isEnabled', 'loggedOutTumed'], function (result) { } else if (result.loggedOutTumed) { chrome.storage.local.set({ loggedOutTumed: false }, function () { }) } -}) \ No newline at end of file +}) diff --git a/src/freshContent/gradeTable.js b/src/freshContent/gradeTable.js index 06dec4c5..6463be6a 100644 --- a/src/freshContent/gradeTable.js +++ b/src/freshContent/gradeTable.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + const table_html = '