diff --git a/package-lock.json b/package-lock.json index 1c90872..b334b13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@google/clasp": "^2.4.0", "@types/google-apps-script": "^1.0.37", "@typescript-eslint/eslint-plugin": "^4.29.0", - "@typescript-eslint/parser": "^4.28.5", + "@typescript-eslint/parser": "^4.29.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", @@ -354,53 +354,6 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", - "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", - "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", - "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -440,80 +393,6 @@ "eslint": "*" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", - "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", - "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", - "dev": true, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz", - "integrity": "sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0", - "debug": "^4.3.1", - "globby": "^11.0.3", - "is-glob": "^4.0.1", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", - "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "4.29.0", - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^8.10.0 || ^10.13.0 || >=11.10.1" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", @@ -532,30 +411,15 @@ "eslint": ">=5" } }, - "node_modules/@typescript-eslint/experimental-utils/node_modules/semver": { - "version": "7.3.5", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", - "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", - "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.0.tgz", + "integrity": "sha512-+92YRNHFdXgq+GhWQPT2bmjX09X7EH36JfgN2/4wmhtwV/HPxozpCNst8jrWcngLtEVd/4zAwA6BKojAlf+YqA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", + "@typescript-eslint/scope-manager": "4.29.0", + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/typescript-estree": "4.29.0", "debug": "^4.3.1" }, "engines": { @@ -575,13 +439,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", - "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", + "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/visitor-keys": "4.29.0" }, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -592,9 +456,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", - "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", + "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", "dev": true, "engines": { "node": "^8.10.0 || ^10.13.0 || >=11.10.1" @@ -605,13 +469,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", - "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz", + "integrity": "sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/visitor-keys": "4.29.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -647,12 +511,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", - "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", + "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.0", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -4500,32 +4364,6 @@ "tsutils": "^3.21.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", - "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0" - } - }, - "@typescript-eslint/types": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", - "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", - "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.0", - "eslint-visitor-keys": "^2.0.0" - } - }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -4551,47 +4389,6 @@ "eslint-utils": "^3.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", - "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0" - } - }, - "@typescript-eslint/types": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", - "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz", - "integrity": "sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/visitor-keys": "4.29.0", - "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.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", - "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", - "dev": true, - "requires": { - "@typescript-eslint/types": "4.29.0", - "eslint-visitor-keys": "^2.0.0" - } - }, "eslint-utils": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", @@ -4600,54 +4397,45 @@ "requires": { "eslint-visitor-keys": "^2.0.0" } - }, - "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" - } } } }, "@typescript-eslint/parser": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.28.5.tgz", - "integrity": "sha512-NPCOGhTnkXGMqTznqgVbA5LqVsnw+i3+XA1UKLnAb+MG1Y1rP4ZSK9GX0kJBmAZTMIktf+dTwXToT6kFwyimbw==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.0.tgz", + "integrity": "sha512-+92YRNHFdXgq+GhWQPT2bmjX09X7EH36JfgN2/4wmhtwV/HPxozpCNst8jrWcngLtEVd/4zAwA6BKojAlf+YqA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "4.28.5", - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/typescript-estree": "4.28.5", + "@typescript-eslint/scope-manager": "4.29.0", + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/typescript-estree": "4.29.0", "debug": "^4.3.1" } }, "@typescript-eslint/scope-manager": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.28.5.tgz", - "integrity": "sha512-PHLq6n9nTMrLYcVcIZ7v0VY1X7dK309NM8ya9oL/yG8syFINIMHxyr2GzGoBYUdv3NUfCOqtuqps0ZmcgnZTfQ==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.0.tgz", + "integrity": "sha512-HPq7XAaDMM3DpmuijxLV9Io8/6pQnliiXMQUcAdjpJJSR+fdmbD/zHCd7hMkjJn04UQtCQBtshgxClzg6NIS2w==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/visitor-keys": "4.29.0" } }, "@typescript-eslint/types": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.28.5.tgz", - "integrity": "sha512-MruOu4ZaDOLOhw4f/6iudyks/obuvvZUAHBDSW80Trnc5+ovmViLT2ZMDXhUV66ozcl6z0LJfKs1Usldgi/WCA==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.0.tgz", + "integrity": "sha512-2YJM6XfWfi8pgU2HRhTp7WgRw78TCRO3dOmSpAvIQ8MOv4B46JD2chnhpNT7Jq8j0APlIbzO1Bach734xxUl4A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.28.5.tgz", - "integrity": "sha512-FzJUKsBX8poCCdve7iV7ShirP8V+ys2t1fvamVeD1rWpiAnIm550a+BX/fmTHrjEpQJ7ZAn+Z7ZZwJjytk9rZw==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.0.tgz", + "integrity": "sha512-8ZpNHDIOyqzzgZrQW9+xQ4k5hM62Xy2R4RPO3DQxMc5Rq5QkCdSpk/drka+DL9w6sXNzV5nrdlBmf8+x495QXQ==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.0", + "@typescript-eslint/visitor-keys": "4.29.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -4667,12 +4455,12 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "4.28.5", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.28.5.tgz", - "integrity": "sha512-dva/7Rr+EkxNWdJWau26xU/0slnFlkh88v3TsyTgRS/IIYFi5iIfpCFM4ikw0vQTFUR9FYSSyqgK4w64gsgxhg==", + "version": "4.29.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.0.tgz", + "integrity": "sha512-LoaofO1C/jAJYs0uEpYMXfHboGXzOJeV118X4OsZu9f7rG7Pr9B3+4HTU8+err81rADa4xfQmAxnRnPAI2jp+Q==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.0", "eslint-visitor-keys": "^2.0.0" } }, diff --git a/package.json b/package.json index d5fec10..285482d 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@google/clasp": "^2.4.0", "@types/google-apps-script": "^1.0.37", "@typescript-eslint/eslint-plugin": "^4.29.0", - "@typescript-eslint/parser": "^4.28.5", + "@typescript-eslint/parser": "^4.29.0", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", diff --git a/src/i18n.js b/src/i18n.js index 39b25e6..2e5342c 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -22,6 +22,7 @@ const MESSAGES = { menuTriggers: 'Triggers', menuSetStatusCheckTrigger: 'Set Status Check Trigger', menuSetLogExtractionTrigger: 'Set Log Extraction Trigger', + menuSetReminderTrigger: 'Set Reminder Trigger', menuDeleteTriggers: 'Delete Triggers', menuCheckStatus: 'Check Status', menuExtractStatusLogs: 'Extract Status Logs', @@ -38,6 +39,8 @@ const MESSAGES = { alertTitleCompleteTriggerSetup: 'Complete ({{handlerFunction}})', alertMessageCompleteTriggerSetup: 'Trigger set at {{frequency}}-{{frequencyUnit}} interval.', + alertMessageCompleteReminderTriggerSetup: + 'Monthly reminder to notify {{myEmail}} of the website status settings is now set up. You will be notified of the monitoring status on the first day of each month.', alertTitleContinueTriggerDelete: 'Deleting All Triggers', alertMessageContinueTriggerDelete: 'Deleting all existing trigger(s) on this spreadsheet/script set by {{myEmail}}. Are you sure you want to continue?', @@ -55,7 +58,7 @@ const MESSAGES = { '\nChanges to website status have been emailed to {{myEmail}}', alertTitleCompleteStatusCheck: '[Website Status] Complete: Status Check', mailSubErrorStatusCheck: '[Website Status] Error: Status Check', - mailBodyErrorStatusCheck: + mailBodyError: '{{errorStack}}\n\n-----\nThis notice is managed by the following spreadsheet:\n{{spreadsheetUrl}}', alertTitleError: 'ERROR', errorHeaderNameTargetUrlNotFound: @@ -70,12 +73,21 @@ const MESSAGES = { '[Website Status] Error in Status Log Extraction:\n{{errorStack}}', errorInvalidResponseCode: 'Invalid response code "{{code}}" at ALLOWED_RESPONSE_CODES or ERROR_RESPONSE_CODES.', + mailSubSendReminderPrefix: '[Website Status] ', + mailSubSendReminder: 'Reminder: Active Triggers', + mailBodySendReminder: + 'This is a monthly reminder, sent automatically, of the time-based triggers set for this website monitoring script:\n\n{{triggerInfo}}\nSee the managing spreadsheet for details on the latest website status.\n\n-----\nThis notice is managed by the following spreadsheet:\n{{spreadsheetUrl}}', + mailSubErrorSendReminder: 'Error: Send Reminder', + messageMonitoredSitesPrefix: 'Monitored Websites', + messageTriggerLogExtractionIsSet: + 'Trigger for periodical status log extraction is set.', }, ja_JP: { menuTitle: 'サイト公開ステータス', menuTriggers: 'トリガー', menuSetStatusCheckTrigger: 'トリガー設定(ステータス確認)', menuSetLogExtractionTrigger: 'トリガー設定(ログ抽出)', + menuSetReminderTrigger: 'トリガー設定(リマインダー)', menuDeleteTriggers: 'トリガー削除', menuCheckStatus: 'ステータス確認', menuExtractStatusLogs: '確認ログを抽出', @@ -93,6 +105,8 @@ const MESSAGES = { alertTitleCompleteTriggerSetup: '完了({{handlerFunction}})', alertMessageCompleteTriggerSetup: 'トリガー設定完了:{{frequency}}-{{frequencyUnit}}間隔.', + alertMessageCompleteReminderTriggerSetup: + '{{myEmail}}宛にサイト公開ステータス監視の設定状況をリマインドするトリガーの設定が完了しました。毎月1日に、公開監視状況の設定が通知されます。', alertTitleContinueTriggerDelete: '全てのトリガーを削除します', alertMessageContinueTriggerDelete: 'このスプレッドシート/スクリプトで {{myEmail}} によって設定された全てのトリガーを削除します。このまま続けますか?', @@ -112,7 +126,7 @@ const MESSAGES = { alertTitleCompleteStatusCheck: '[サイト公開ステータス] 完了:ステータス確認', mailSubErrorStatusCheck: '[サイト公開ステータス] エラー:ステータス確認', - mailBodyErrorStatusCheck: + mailBodyError: '{{errorStack}}\n\n-----\nこの通知は次のGoogleスプレッドシートによって管理されています:\n{{spreadsheetUrl}}', alertTitleError: 'エラー', errorHeaderNameTargetUrlNotFound: @@ -127,6 +141,14 @@ const MESSAGES = { '[サイト公開ステータス] ログ抽出エラー:\n{{errorStack}}', errorInvalidResponseCode: '無効なレスポンスコード「{{code}}」が ALLOWED_RESPONSE_CODES または ERROR_RESPONSE_CODES にて指定されています。', + mailSubSendReminderPrefix: '[サイト公開ステータス] ', + mailSubSendReminder: 'リマインダー:設定されているトリガー', + mailBodySendReminder: + 'これは、サイト公開ステータス監視のトリガー設定状況をお知らせするため、毎月1日に自動的に送信されるリマインダーです。\n\n{{triggerInfo}}\n最新のサイト公開ステータスについては、管理スプレッドシートをご確認ください。\n\n-----\nこの通知は次のGoogleスプレッドシートによって管理されています:\n{{spreadsheetUrl}}', + mailSubErrorSendReminder: 'エラー:リマインダー送信', + messageMonitoredSitesPrefix: '公開ステータスの監視対象サイト', + messageTriggerLogExtractionIsSet: + '公開ステータスログを定期的に抽出するトリガーが設定されています。', }, }; @@ -324,13 +346,13 @@ class LocalizedMessage { return text; } /** - * Replace placeholder string in this.messageList.mailBodyErrorStatusCheck + * Replace placeholder string in this.messageList.mailBodyError * @param {String} errorStack * @param {String} spreadsheetUrl * @returns {String} The replaced text. */ - replaceMailBodyErrorStatusCheck(errorStack, spreadsheetUrl) { - let text = this.messageList.mailBodyErrorStatusCheck; + replaceMailBodyError(errorStack, spreadsheetUrl) { + let text = this.messageList.mailBodyError; let placeholderValues = [ { regexp: '{{errorStack}}', @@ -424,4 +446,41 @@ class LocalizedMessage { text = this.replacePlaceholders_(text, placeholderValues); return text; } + /** + * Replace placeholder string in this.messageList.alertMessageCompleteReminderTriggerSetup + * @param {String} myEmail + * @returns {String} The replaced text. + */ + replaceAlertMessageCompleteReminderTriggerSetup(myEmail) { + let text = this.messageList.alertMessageCompleteReminderTriggerSetup; + let placeholderValues = [ + { + regexp: '{{myEmail}}', + value: myEmail, + }, + ]; + text = this.replacePlaceholders_(text, placeholderValues); + return text; + } + /** + * Replace placeholder string in this.messageList.mailBodySendReminder + * @param {String} triggerInfo + * @param {String} spreadsheetUrl + * @returns {String} The replaced text. + */ + replaceMailBodySendReminder(triggerInfo, spreadsheetUrl) { + let text = this.messageList.mailBodySendReminder; + let placeholderValues = [ + { + regexp: '{{triggerInfo}}', + value: triggerInfo, + }, + { + regexp: '{{spreadsheetUrl}}', + value: spreadsheetUrl, + }, + ]; + text = this.replacePlaceholders_(text, placeholderValues); + return text; + } } diff --git a/src/websiteMonitoring.js b/src/websiteMonitoring.js index bb32082..a57f7f7 100644 --- a/src/websiteMonitoring.js +++ b/src/websiteMonitoring.js @@ -19,7 +19,9 @@ deleteTimeBasedTriggers, extractStatusLogsTriggered, onOpen, +sendReminder, setupLogExtractionTrigger, +setupReminderTrigger, setupStatusCheckTrigger, websiteMonitoringTriggered */ @@ -62,6 +64,10 @@ function onOpen() { localMessage.messageList.menuSetLogExtractionTrigger, 'setupLogExtractionTrigger' ) + .addItem( + localMessage.messageList.menuSetReminderTrigger, + 'setupReminderTrigger' + ) .addSeparator() .addItem( localMessage.messageList.menuDeleteTriggers, @@ -84,7 +90,7 @@ function setupStatusCheckTrigger() { const handlerFunction = 'websiteMonitoringTriggered'; const frequencyKey = 'TRIGGER_MINUTE_FREQUENCY_STATUS_CHECK'; const frequencyUnit = 'minute'; - setupTrigger(handlerFunction, frequencyKey, frequencyUnit); + setupTrigger_(handlerFunction, frequencyKey, frequencyUnit); } /** @@ -95,7 +101,7 @@ function setupLogExtractionTrigger() { const handlerFunction = 'extractStatusLogsTriggered'; const frequencyKey = 'TRIGGER_DAYS_FREQUENCY_LOG_EXTRACTION'; const frequencyUnit = 'day'; - setupTrigger(handlerFunction, frequencyKey, frequencyUnit); + setupTrigger_(handlerFunction, frequencyKey, frequencyUnit); } /** @@ -105,7 +111,7 @@ function setupLogExtractionTrigger() { * @param {String} frequencyKey Key in the options sheet that refers to the trigger frequency for this handler function. * @param {String} frequencyUnit Unit of the value of frequencyKey, i.e., minute, hour, day, or week. */ -function setupTrigger(handlerFunction, frequencyKey, frequencyUnit) { +function setupTrigger_(handlerFunction, frequencyKey, frequencyUnit) { const ui = SpreadsheetApp.getUi(); const myEmail = Session.getActiveUser().getEmail(); const ss = SpreadsheetApp.getActiveSpreadsheet(); @@ -200,6 +206,34 @@ function setupTrigger(handlerFunction, frequencyKey, frequencyUnit) { } } +/** + * Set time-based trigger for sending monthly reminders + * of active time-based triggers set by this user in this script. + * Trigger will be set for the first day of each month. + */ +function setupReminderTrigger() { + const ui = SpreadsheetApp.getUi(); + const localMessage = new LocalizedMessage( + SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetLocale() + ); + const handlerFunction = 'sendReminder'; + // Delete existing trigger for the same handler function. + ScriptApp.getProjectTriggers().forEach((trigger) => { + if (trigger.getHandlerFunction() === handlerFunction) { + ScriptApp.deleteTrigger(trigger); + } + }); + // Set new trigger + ScriptApp.newTrigger(handlerFunction).timeBased().onMonthDay(1).create(); + ui.alert( + localMessage.replaceAlertTitleCompleteTriggerSetup(handlerFunction), + localMessage.replaceAlertMessageCompleteReminderTriggerSetup( + Session.getActiveUser().getEmail() + ), + ui.ButtonSet.OK + ); +} + /** * Delete existing trigger(s). */ @@ -540,10 +574,7 @@ function websiteMonitoring(triggered = false) { 'NA', ]); let messageSub = localMessage.messageList.mailSubErrorStatusCheck; - let messageBody = localMessage.replaceMailBodyErrorStatusCheck( - e.stack, - ss.getUrl() - ); + let messageBody = localMessage.replaceMailBodyError(e.stack, ss.getUrl()); if (options.ENABLE_CHAT_NOTIFICATION) { // Post on Google Chat postToChat_( @@ -740,6 +771,99 @@ function extractStatusLogs(triggered = false) { } } +/** + * Send a reminder to the user on the website status monitoring settings. + */ +function sendReminder() { + const triggers = ScriptApp.getProjectTriggers(); + if ( + triggers.length > 0 && + !( + triggers.length === 1 && + triggers[0].getHandlerFunction() === 'sendReminder' + ) + ) { + const ss = SpreadsheetApp.getActiveSpreadsheet(); + const localMessage = new LocalizedMessage(ss.getSpreadsheetLocale()); + const myEmail = Session.getActiveUser().getEmail(); + // Parse options data from spreadsheet + const optionsArr = ss + .getSheetByName(SHEET_NAME_OPTIONS) + .getDataRange() + .getValues(); + optionsArr.shift(); + const options = optionsArr.reduce((obj, row) => { + let [key, value] = [row[1], row[2]]; // Assuming that the keys and their options are set in columns B and C, respectively. + if (key) { + obj[key] = value; + } + return obj; + }, {}); + var messageSub = localMessage.messageList.mailSubSendReminderPrefix; + var messageBody = ''; + try { + let triggerInfo = triggers + .reduce((info, trigger) => { + if (trigger.getHandlerFunction() === 'websiteMonitoringTriggered') { + // Get the list of target websites to monitor + const targetWebsitesSheet = ss.getSheetByName(SHEET_NAME_DASHBOARD); + const targetWebsitesArr = targetWebsitesSheet + .getRange( + TARGET_WEBSITES_RANGE_POSITION.row, + TARGET_WEBSITES_RANGE_POSITION.col, + targetWebsitesSheet.getLastRow() - + TARGET_WEBSITES_RANGE_POSITION.row + + 1, + TARGET_WEBSITES_COL_NUM + ) + .getValues(); + targetWebsitesArr.shift(); + info.push( + `${ + localMessage.messageList.messageMonitoredSitesPrefix + }:\n${targetWebsitesArr + .map((website) => `- ${website.join(' ')}`) + .join('\n')}` + ); + } else if ( + trigger.getHandlerFunction() === 'extractStatusLogsTriggered' + ) { + info.push( + localMessage.messageList.messageTriggerLogExtractionIsSet + ); + } + return info; + }, []) + .join('\n'); + messageSub += localMessage.messageList.mailSubSendReminder; + messageBody = localMessage.replaceMailBodySendReminder( + triggerInfo, + ss.getUrl() + ); + } catch (e) { + console.error(e.stack); + messageSub += localMessage.messageList.mailSubErrorSendReminder; + messageBody = localMessage.replaceMailBodyError(e.stack, ss.getUrl()); + } finally { + if (options.ENABLE_CHAT_NOTIFICATION) { + // Post on Google Chat + postToChat_( + options.CHAT_WEBHOOK_URL, + `*${messageSub}*\n\n${messageBody}` + ); + } + if ( + !options.ENABLE_CHAT_NOTIFICATION || + !options.DISABLE_MAIL_NOTIFICATION + ) { + // If chat notification is disabled OR mail notification is NOT disabled + // send email notification + MailApp.sendEmail(myEmail, messageSub, messageBody); + } + } + } +} + /** * Parse a given array of HTTP reponse codes (in strings) into actual codes. * For example, ["201", "30x"] will be converted into the following array of codes: