diff --git a/README.md b/README.md index e47ac78..091bbfa 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,8 @@ ReviewMe requires a config file. A simple config looks something like: * **botIcon** An image url to use for the bot avatar * **showAppIcon** Determines if app icon will be displayed (overrides botIcon) * **channel** Overrides the default Slack channel messages will be posted to -* **interval** The interval (in seconds) to check for new reviews. Default: `300`. +* **interval** The interval (in seconds) to check for new reviews. Default: 300. +* **cronStyleSchedule** CronJob style schedule to check for new reviews(Can be used instead of interval). Default: `00 * * * *`. * **apps** A list of apps to fetch reviews for. See App Options below * **publisherKey** *Android Only* The path to a Google Play Publisher private key (`.json` file). Used for accessing the Google Play Publisher API. diff --git a/appstorereviews.js b/appstorereviews.js index 9bf40c5..a8d933b 100644 --- a/appstorereviews.js +++ b/appstorereviews.js @@ -1,6 +1,7 @@ const controller = require('./reviews'); const fs = require('fs'); var request = require('request'); +var schedule = require('node-schedule'); require('./constants'); exports.startReview = function (config, first_run) { @@ -16,8 +17,8 @@ exports.startReview = function (config, first_run) { config.regions = ["us"]; } - if (!config.interval) { - config.interval = DEFAULT_INTERVAL_SECONDS + if (!config.schedule) { + config.schedule = DEFAULT_INTERVAL_SECONDS; } // Find the app information to get a icon URL @@ -50,15 +51,23 @@ exports.startReview = function (config, first_run) { } //calculate the interval with an offset, to avoid spamming the server - var interval_seconds = config.interval + (i * 10); + var interval_seconds = typeof config.schedule === 'number' ? config.schedule + (i * 10) : i * 10; - setInterval(function (config, appInformation) { + var fetch = function (config, appInformation) { if (config.verbose) console.log("INFO: [" + config.appId + "] Fetching App Store reviews"); exports.fetchAppStoreReviews(config, appInformation, function (reviews) { exports.handleFetchedAppStoreReviews(config, appInformation, reviews); }); - }, interval_seconds * 1000, config, appInformation); + }; + + if (typeof config.schedule === 'number') { + setInterval(fetch, interval_seconds * 1000, config, appInformation); + } else { + schedule.scheduleJob(config.schedule, function () { + setTimeout(fetch, interval_seconds * 1000, config, appInformation); + }); + } }); } }); diff --git a/googleplayreviews.js b/googleplayreviews.js index f194667..885b36c 100644 --- a/googleplayreviews.js +++ b/googleplayreviews.js @@ -37,17 +37,24 @@ exports.startReview = function (config, first_run) { exports.handleFetchedGooglePlayReviews(config, appInformation, reviews); } - var interval_seconds = config.interval ? config.interval : DEFAULT_INTERVAL_SECONDS; + if (!config.schedule) { + config.schedule = DEFAULT_INTERVAL_SECONDS; + } - setInterval(function (config, appInformation) { + var fetch = function (config, appInformation) { if (config.verbose) console.log("INFO: [" + config.appId + "] Fetching Google Play reviews"); exports.fetchGooglePlayReviews(config, appInformation, function (reviews) { exports.handleFetchedGooglePlayReviews(config, appInformation, reviews); }); - }, interval_seconds * 1000, config, appInformation); - }); + } + if (typeof config.schedule === 'number') { + setInterval(fetch, config.schedule * 1000, config, appInformation); + } else { + schedule.scheduleJob(config.schedule, fetch(config, appInformation)); + } + }); }); }; diff --git a/index.js b/index.js index f20003b..b84badb 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ module.exports.start = function start(config) { slackHook: config.slackHook, verbose: config.verbose, dryRun: config.dryRun, - interval: config.interval, + schedule: config.interval || config.cronStyleSchedule, botIcon: app.botIcon || config.botIcon, showAppIcon: app.showAppIcon || config.showAppIcon, channel: app.channel || config.channel, diff --git a/package-lock.json b/package-lock.json index 887dab6..f47633c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -274,6 +274,15 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, + "cron-parser": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-2.17.0.tgz", + "integrity": "sha512-oTmzVEwlurRe51HqTm4afshVr8Rkxy9kFiWxh5e6SmrY2o9NDYU4S6SduanBZYXLgkLy0skA98y7/tztW/DmjQ==", + "requires": { + "is-nan": "^1.3.0", + "moment-timezone": "^0.5.31" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -339,6 +348,14 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=" }, + "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==", + "requires": { + "object-keys": "^1.0.12" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -803,11 +820,11 @@ } }, "google-p12-pem": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.2.tgz", - "integrity": "sha512-tbjzndQvSIHGBLzHnhDs3cL4RBjLbLXc2pYvGH+imGVu5b4RMAttUTdnmW2UH0t11QeBTXZ7wlXPS7hrypO/tg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.3.tgz", + "integrity": "sha512-wS0ek4ZtFx/ACKYF3JhyGe5kzH7pgiQ7J5otlumqR9psmWMYc+U9cErKlCYVYHoUaidXHdZ2xbo34kB+S+24hA==", "requires": { - "node-forge": "^0.9.0" + "node-forge": "^0.10.0" } }, "google-play-scraper": { @@ -1019,6 +1036,14 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" }, + "is-nan": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.0.tgz", + "integrity": "sha512-z7bbREymOqt2CCaZVly8aC4ML3Xhfi0ekuOnjO2L8vKdl+CttdVoGZQhd4adMFAsxQ5VeRVwORs4tU8RH+HFtQ==", + "requires": { + "define-properties": "^1.1.3" + } + }, "is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -1202,6 +1227,11 @@ "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" }, + "long-timeout": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/long-timeout/-/long-timeout-0.1.1.tgz", + "integrity": "sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=" + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -1277,6 +1307,19 @@ "minimist": "^1.2.5" } }, + "moment": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", + "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" + }, + "moment-timezone": { + "version": "0.5.32", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.32.tgz", + "integrity": "sha512-Z8QNyuQHQAmWucp8Knmgei8YNo28aLjJq6Ma+jy1ZSpSk5nyfRT8xgUbSQvD2+2UajISfenndwvFuH3NGS+nvA==", + "requires": { + "moment": ">= 2.9.0" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1308,9 +1351,19 @@ "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-forge": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz", - "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==" + }, + "node-schedule": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-schedule/-/node-schedule-1.3.2.tgz", + "integrity": "sha512-GIND2pHMHiReSZSvS6dpZcDH7pGPGFfWBIEud6S00Q8zEIzAs9ommdyRK1ZbQt8y1LyZsJYZgPnyi7gpU2lcdw==", + "requires": { + "cron-parser": "^2.7.3", + "long-timeout": "0.1.1", + "sorted-array-functions": "^1.0.0" + } }, "nth-check": { "version": "1.0.2", @@ -1320,6 +1373,11 @@ "boolbase": "~1.0.0" } }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1595,6 +1653,11 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "sorted-array-functions": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz", + "integrity": "sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==" + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", diff --git a/package.json b/package.json index 979b750..aaae557 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "commander": "^4.1.1", "google-play-scraper": "^8.0.2", "googleapis": "^52.1.0", + "node-schedule": "^1.3.2", "request": "^2.88.0" } }