diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 842de61..5cfb56c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,7 +14,7 @@ updates: commit-message: prefix: 'github-actions' include: 'scope' - target-branch: 'dev' + target-branch: 'main' - package-ecosystem: 'npm' directory: '/' schedule: @@ -24,4 +24,4 @@ updates: commit-message: prefix: 'npm' include: 'scope' - target-branch: 'dev' + target-branch: 'main' diff --git a/README.md b/README.md index c0bc295..b85ae1c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Website Status Monitoring -[![GitHub Super-Linter](https://github.com/ttsukagoshi/website-monitoring-by-gas/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) [![clasp](https://img.shields.io/badge/built%20with-clasp-4285f4.svg?style=flat-square)](https://github.com/google/clasp) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) +[![clasp](https://img.shields.io/badge/built%20with-clasp-4285f4.svg?style=flat-square)](https://github.com/google/clasp) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) [![CodeQL](https://github.com/ttsukagoshi/website-monitoring-by-gas/workflows/CodeQL/badge.svg)](https://github.com/ttsukagoshi/website-monitoring-by-gas/actions?query=workflow%3ACodeQL) [![GitHub Super-Linter](https://github.com/ttsukagoshi/website-monitoring-by-gas/workflows/Lint%20Code%20Base/badge.svg)](https://github.com/marketplace/actions/super-linter) Website status monitoring using Google Sheets and Google Apps Script. diff --git a/package-lock.json b/package-lock.json index 1c90872..f469bf8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,8 @@ "devDependencies": { "@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/eslint-plugin": "^4.29.1", + "@typescript-eslint/parser": "^4.29.1", "eslint": "^7.32.0", "eslint-config-prettier": "^8.3.0", "eslint-plugin-prettier": "^3.4.0", @@ -324,13 +324,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.0.tgz", - "integrity": "sha512-eiREtqWRZ8aVJcNru7cT/AMVnYd9a2UHsfZT8MR1dW3UUEg6jDv9EQ9Cq4CUPZesyQ58YUpoAADGv71jY8RwgA==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.1.tgz", + "integrity": "sha512-AHqIU+SqZZgBEiWOrtN94ldR3ZUABV5dUG94j8Nms9rQnHFc8fvDOue/58K4CFz6r8OtDDc35Pw9NQPWo0Ayrw==", "dev": true, "dependencies": { - "@typescript-eslint/experimental-utils": "4.29.0", - "@typescript-eslint/scope-manager": "4.29.0", + "@typescript-eslint/experimental-utils": "4.29.1", + "@typescript-eslint/scope-manager": "4.29.1", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.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", @@ -417,15 +370,15 @@ } }, "node_modules/@typescript-eslint/experimental-utils": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.0.tgz", - "integrity": "sha512-FpNVKykfeaIxlArLUP/yQfv/5/3rhl1ov6RWgud4OgbqWLkEq7lqgQU9iiavZRzpzCRQV4XddyFz3wFXdkiX9w==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.1.tgz", + "integrity": "sha512-kl6QG6qpzZthfd2bzPNSJB2YcZpNOrP6r9jueXupcZHnL74WiuSjaft7WSu17J9+ae9zTlk0KJMXPUj0daBxMw==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.29.0", - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/typescript-estree": "4.29.0", + "@typescript-eslint/scope-manager": "4.29.1", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/typescript-estree": "4.29.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", + "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", "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.1", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/typescript-estree": "4.29.1", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", + "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/visitor-keys": "4.29.1" }, "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", + "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", + "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/visitor-keys": "4.29.1", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", + "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", "dev": true, "dependencies": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.1", "eslint-visitor-keys": "^2.0.0" }, "engines": { @@ -4486,13 +4350,13 @@ } }, "@typescript-eslint/eslint-plugin": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.0.tgz", - "integrity": "sha512-eiREtqWRZ8aVJcNru7cT/AMVnYd9a2UHsfZT8MR1dW3UUEg6jDv9EQ9Cq4CUPZesyQ58YUpoAADGv71jY8RwgA==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.29.1.tgz", + "integrity": "sha512-AHqIU+SqZZgBEiWOrtN94ldR3ZUABV5dUG94j8Nms9rQnHFc8fvDOue/58K4CFz6r8OtDDc35Pw9NQPWo0Ayrw==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "4.29.0", - "@typescript-eslint/scope-manager": "4.29.0", + "@typescript-eslint/experimental-utils": "4.29.1", + "@typescript-eslint/scope-manager": "4.29.1", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.1.0", @@ -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", @@ -4538,60 +4376,19 @@ } }, "@typescript-eslint/experimental-utils": { - "version": "4.29.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.0.tgz", - "integrity": "sha512-FpNVKykfeaIxlArLUP/yQfv/5/3rhl1ov6RWgud4OgbqWLkEq7lqgQU9iiavZRzpzCRQV4XddyFz3wFXdkiX9w==", + "version": "4.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.29.1.tgz", + "integrity": "sha512-kl6QG6qpzZthfd2bzPNSJB2YcZpNOrP6r9jueXupcZHnL74WiuSjaft7WSu17J9+ae9zTlk0KJMXPUj0daBxMw==", "dev": true, "requires": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.29.0", - "@typescript-eslint/types": "4.29.0", - "@typescript-eslint/typescript-estree": "4.29.0", + "@typescript-eslint/scope-manager": "4.29.1", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/typescript-estree": "4.29.1", "eslint-scope": "^5.1.1", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.29.1.tgz", + "integrity": "sha512-3fL5iN20hzX3Q4OkG7QEPFjZV2qsVGiDhEwwh+EkmE/w7oteiOvUNzmpu5eSwGJX/anCryONltJ3WDmAzAoCMg==", "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.1", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/typescript-estree": "4.29.1", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.29.1.tgz", + "integrity": "sha512-Hzv/uZOa9zrD/W5mftZa54Jd5Fed3tL6b4HeaOpwVSabJK8CJ+2MkDasnX/XK4rqP5ZTWngK1ZDeCi6EnxPQ7A==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5" + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/visitor-keys": "4.29.1" } }, "@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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.29.1.tgz", + "integrity": "sha512-Jj2yu78IRfw4nlaLtKjVaGaxh/6FhofmQ/j8v3NXmAiKafbIqtAPnKYrf0sbGjKdj0hS316J8WhnGnErbJ4RCA==", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.29.1.tgz", + "integrity": "sha512-lIkkrR9E4lwZkzPiRDNq0xdC3f2iVCUjw/7WPJ4S2Sl6C3nRWkeE1YXCQ0+KsiaQRbpY16jNaokdWnm9aUIsfw==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", - "@typescript-eslint/visitor-keys": "4.28.5", + "@typescript-eslint/types": "4.29.1", + "@typescript-eslint/visitor-keys": "4.29.1", "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.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.29.1.tgz", + "integrity": "sha512-zLqtjMoXvgdZY/PG6gqA73V8BjqPs4af1v2kiiETBObp+uC6gRYnJLmJHxC0QyUrrHDLJPIWNYxoBV3wbcRlag==", "dev": true, "requires": { - "@typescript-eslint/types": "4.28.5", + "@typescript-eslint/types": "4.29.1", "eslint-visitor-keys": "^2.0.0" } }, diff --git a/package.json b/package.json index d5fec10..f780209 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "devDependencies": { "@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/eslint-plugin": "^4.29.1", + "@typescript-eslint/parser": "^4.29.1", "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..5c45b0e 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,8 @@ 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) { + console.info(`[setupTrigger_] Setting trigger for ${handlerFunction}...`); const ui = SpreadsheetApp.getUi(); const myEmail = Session.getActiveUser().getEmail(); const ss = SpreadsheetApp.getActiveSpreadsheet(); @@ -187,6 +194,9 @@ function setupTrigger(handlerFunction, frequencyKey, frequencyUnit) { localMessage.replaceErrorInvalidFrequencyUnit(frequencyUnit) ); } + // Set up a trigger for monthly reminders + setupReminderTrigger(true); + console.info('[setupTrigger_] Trigger set up complete.'); ui.alert( localMessage.replaceAlertTitleCompleteTriggerSetup(handlerFunction), localMessage.replaceAlertMessageCompleteTriggerSetup( @@ -196,14 +206,62 @@ function setupTrigger(handlerFunction, frequencyKey, frequencyUnit) { ui.ButtonSet.OK ); } catch (e) { + console.error(e.stack); ui.alert(e.stack); } } +/** + * 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. + * @param {Boolean} muteUi Will not show any UI alerts when true. Defaults to false. + */ +function setupReminderTrigger(muteUi = false) { + console.info( + '[setupReminderTrigger] Setting trigger for the monthly reminder...' + ); + if (!muteUi) { + var ui = SpreadsheetApp.getUi(); + } + const localMessage = new LocalizedMessage( + SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetLocale() + ); + const handlerFunction = 'sendReminder'; + try { + // 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(); + console.info('[setupReminderTrigger] Trigger set up complete.'); + if (!muteUi) { + ui.alert( + localMessage.replaceAlertTitleCompleteTriggerSetup(handlerFunction), + localMessage.replaceAlertMessageCompleteReminderTriggerSetup( + Session.getActiveUser().getEmail() + ), + ui.ButtonSet.OK + ); + } + } catch (e) { + console.error(e.stack); + if (!muteUi) { + ui.alert(e.stack); + } else { + throw e; + } + } +} + /** * Delete existing trigger(s). */ function deleteTimeBasedTriggers() { + console.info('[deleteTimeBasedTriggers] Deleting triggers...'); const ui = SpreadsheetApp.getUi(); const myEmail = Session.getActiveUser().getEmail(); const localMessage = new LocalizedMessage( @@ -222,12 +280,14 @@ function deleteTimeBasedTriggers() { ScriptApp.getProjectTriggers().forEach((trigger) => ScriptApp.deleteTrigger(trigger) ); + console.info('[deleteTimeBasedTriggers] Deleted triggers.'); ui.alert( localMessage.messageList.alertTitleComplete, localMessage.messageList.alertMessageTriggerDelete, ui.ButtonSet.OK ); } catch (e) { + console.error(e.stack); ui.alert(e.stack); } } @@ -368,7 +428,6 @@ function websiteMonitoring(triggered = false) { RESPONSE_CODE_WILDCARD, spreadsheetLocale ); - console.log(JSON.stringify(options)); ////////////////// // Get the actual HTTP response codes let dashboardStatus = []; // Array to record on the dashboard worksheet let statusChange = targetWebsites.reduce( @@ -440,7 +499,6 @@ function websiteMonitoring(triggered = false) { .shift(); latestStatusSheet.getDataRange().clearContent(); dashboardStatus = [existingStatusHeader].concat(dashboardStatus); - console.log(dashboardStatus); latestStatusSheet .getRange(1, 1, dashboardStatus.length, dashboardStatus[0].length) .setValues(dashboardStatus); @@ -540,10 +598,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 +795,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: