From 393d5f689887bf1d6f30a37eea163b2e6bbd4efa Mon Sep 17 00:00:00 2001 From: Mark Dietzer Date: Sat, 19 Sep 2020 14:02:00 -0700 Subject: [PATCH] feat(notification): add telegram (#71) --- .editorconfig | 5 + .env.example | 3 + README.md | 5 +- package-lock.json | 169 ++++++++++++++++++++++++++++--- package.json | 1 + src/config.ts | 9 +- src/notification/notification.ts | 7 +- src/notification/telegram.ts | 21 ++++ src/store/lookup.ts | 23 ++++- src/store/model/amazon.ts | 24 +++-- src/store/model/bestbuy.ts | 1 - src/store/model/newegg.ts | 15 ++- src/store/model/store.ts | 1 + 13 files changed, 252 insertions(+), 32 deletions(-) create mode 100644 .editorconfig create mode 100644 src/notification/telegram.ts diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..65f6a0f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true +[*] +end_of_line = lf +insert_final_newline = true +indent_style = tab diff --git a/.env.example b/.env.example index 46e30f7..374eb99 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,6 @@ PUSHOVER_USER="123pushover-user-key" OPEN_BROWSER="true" PLAY_SOUND="false" SCREENSHOT="true" +TELEGRAM_ACCESS_TOKEN="" +TELEGRAM_CHAT_ID="1234" +SHOW_ONLY_BRANDS="evga" diff --git a/README.md b/README.md index 13d7a62..e889b53 100644 --- a/README.md +++ b/README.md @@ -72,11 +72,14 @@ First, you're going to need to copy the `.env.example` to `.env`. The current op | `PHONE_CARRIER` | [Supported carriers](#supported-carriers) for SMS; optional, email configuration required | | `RATE_LIMIT_TIMEOUT` | Rate limit timeout for each full store cycle; optional, default: `5000` | | `SLACK_CHANNEL` | Slack channel for posting (e.g., `update`); optional | -| `SLACK_TOKEN` | Slack API token; optional +| `SLACK_TOKEN` | Slack API token; optional | | `STORES` | [Supported stores](#supported-stores) you want to be scraped; optional, default: `nvidia` | | `OPEN_BROWSER` | Toggle for whether or not the browser should open when item is found, default: `true` | | `PLAY_SOUND` | Play this sound notification if a card is found.; optional | | `SCREENSHOT` | Capture screenshot of page on successful hit; optional, default `true` | +| `TELEGRAM_ACCESS_TOKEN` | Telegram access token; optional | +| `TELEGRAM_CHAT_ID` | Telegram chat ID; optional | +| `SHOW_ONLY_BRANDS` | If set, will only show specified brands, seperated by `,` | > :point_right: If you have multi-factor authentication (MFA), you will need to create an [app password](https://myaccount.google.com/apppasswords) and use this instead of your Gmail password. diff --git a/package-lock.json b/package-lock.json index 3de8c95..5d3ed01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -230,6 +230,11 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==" + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -267,6 +272,11 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/lodash": { + "version": "4.14.161", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz", + "integrity": "sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==" + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -326,6 +336,16 @@ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", "dev": true }, + "@types/url-join": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/url-join/-/url-join-4.0.0.tgz", + "integrity": "sha512-awrJu8yML4E/xTwr2EMatC+HBnHGoDxc2+ImA9QyeUELI1S7dOCIZcyjki1rkwoA8P2D2NVgLAJLjnclkdLtAw==" + }, + "@types/warning": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz", + "integrity": "sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=" + }, "@types/yauzl": { "version": "2.9.1", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz", @@ -649,11 +669,26 @@ "version": "0.19.2", "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "dev": true, "requires": { "follow-redirects": "1.5.10" } }, + "axios-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/axios-error/-/axios-error-1.0.0.tgz", + "integrity": "sha512-1JlcEEdTDeadLJ9+ImZd9eQudqqpAStpHzh9/Rb2q2UsWC+dJyQrFMTAHOzSJoFknWZ9IbVvW5gga9lG7CKLqQ==", + "requires": { + "axios": "^0.19.2", + "type-fest": "^0.15.1" + }, + "dependencies": { + "type-fest": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.15.1.tgz", + "integrity": "sha512-n+UXrN8i5ioo7kqT/nF8xsEzLaqFra7k32SEsSPwvXVGyAcRgV/FUQN/sgfptJTR1oRmmq7z4IXMFSM7im7C9A==" + } + } + }, "babel-eslint": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", @@ -1043,6 +1078,15 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "camel-case": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", + "requires": { + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" + } + }, "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", @@ -1578,6 +1622,15 @@ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "dot-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz", + "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, "dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -2779,7 +2832,6 @@ "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, "requires": { "debug": "=3.1.0" }, @@ -2788,7 +2840,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, "requires": { "ms": "2.0.0" } @@ -2796,8 +2847,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" } } }, @@ -3555,8 +3605,7 @@ "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 + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-types": { "version": "1.0.0", @@ -3719,8 +3768,7 @@ "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", - "dev": true + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lodash.get": { "version": "4.4.2", @@ -3801,6 +3849,22 @@ "triple-beam": "^1.3.0" } }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", + "requires": { + "tslib": "^1.10.0" + } + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -3833,8 +3897,7 @@ "map-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", - "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", - "dev": true + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==" }, "map-visit": { "version": "1.0.0", @@ -3934,6 +3997,39 @@ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true }, + "messaging-api-common": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/messaging-api-common/-/messaging-api-common-1.0.0.tgz", + "integrity": "sha512-4bHqgnzrR2F97V+WnxVKS6EmjElkURa9jhy0/Tv7B+Xmcl3BDEW2krFpr5LfJDwFFiaDqj8Poel81hTOoWO/Lw==", + "requires": { + "@types/debug": "^4.1.5", + "@types/lodash": "^4.14.156", + "@types/url-join": "^4.0.0", + "axios": "^0.19.2", + "camel-case": "^4.1.1", + "debug": "^4.1.1", + "lodash": "^4.17.15", + "map-obj": "^4.1.0", + "pascal-case": "^3.1.1", + "snake-case": "^3.0.3", + "url-join": "^4.0.1" + } + }, + "messaging-api-telegram": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/messaging-api-telegram/-/messaging-api-telegram-1.0.0.tgz", + "integrity": "sha512-hA2LFclQV5sVGGIYosdYvhap0GrPD73GuNjYi/T9rKZhn9qA5wTihrHNXdJHmUI7QOTT3JnA3QRdkwc9wkFZuA==", + "requires": { + "@types/lodash": "^4.14.156", + "@types/warning": "^3.0.0", + "axios": "^0.19.2", + "axios-error": "^1.0.0", + "lodash": "^4.17.15", + "messaging-api-common": "^1.0.0", + "ts-invariant": "^0.4.4", + "warning": "^4.0.3" + } + }, "micro-spelling-correcter": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/micro-spelling-correcter/-/micro-spelling-correcter-1.1.1.tgz", @@ -4151,6 +4247,15 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "no-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", + "requires": { + "lower-case": "^2.0.1", + "tslib": "^1.10.0" + } + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -4565,6 +4670,15 @@ "lines-and-columns": "^1.1.6" } }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz", + "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==", + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, "pascalcase": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", @@ -5236,6 +5350,15 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "snake-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.3.tgz", + "integrity": "sha512-WM1sIXEO+rsAHBKjGf/6R1HBBcgbncKS08d2Aqec/mrDSpU80SiOU41hO7ny6DToHSyrlwTYzQBIK1FPSx4Y3Q==", + "requires": { + "dot-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", @@ -5831,6 +5954,14 @@ "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, + "ts-invariant": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.4.4.tgz", + "integrity": "sha512-uEtWkFM/sdZvRNNDL3Ehu4WVpwaulhwQszV8mrtcdeE8nN00BV9mAmQ88RkrBhFgl9gMgvjJLAQcZbnPXI9mlA==", + "requires": { + "tslib": "^1.9.3" + } + }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -5857,8 +5988,7 @@ "tslib": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", - "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", - "dev": true + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" }, "tsutils": { "version": "3.17.1", @@ -6087,6 +6217,11 @@ } } }, + "url-join": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", + "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==" + }, "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", @@ -6146,6 +6281,14 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 9fe5404..eb52ec1 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "homepage": "https://github.com/jef/nvidia-snatcher#readme", "dependencies": { "dotenv": "^8.2.0", + "messaging-api-telegram": "^1.0.0", "nodemailer": "^6.4.11", "open": "^7.2.1", "puppeteer": "^5.3.0", diff --git a/src/config.ts b/src/config.ts index e844e26..d8fc260 100644 --- a/src/config.ts +++ b/src/config.ts @@ -29,6 +29,10 @@ const notifications = { token: process.env.PUSHOVER_TOKEN, user: process.env.PUSHOVER_USER }, + telegram: { + botToken: process.env.TELEGRAM_ACCESS_TOKEN ?? '', + chatId: process.env.TELEGRAM_CHAT_ID ?? '' + }, test: process.env.NOTIFICATION_TEST ?? 'false', playSound: process.env.PLAY_SOUND ?? 'false' }; @@ -47,10 +51,13 @@ const stores = process.env.STORES ?? 'nvidia'; const openBrowser = process.env.OPEN_BROWSER ?? 'true'; +const showOnlyBrands = process.env.SHOW_ONLY_BRANDS ? process.env.SHOW_ONLY_BRANDS.split(',') : []; + export const Config = { notifications, rateLimitTimeout, page, stores, - openBrowser + openBrowser, + showOnlyBrands }; diff --git a/src/notification/notification.ts b/src/notification/notification.ts index d7eb4c7..0575509 100644 --- a/src/notification/notification.ts +++ b/src/notification/notification.ts @@ -4,6 +4,7 @@ import {sendSMS} from './sms'; import {playSound} from './sound'; import {sendSlackMessage} from './slack'; import sendPushoverNotification from './pushover'; +import {sendTelegramMessage} from './telegram'; export function sendNotification(cartUrl: string) { if (Config.notifications.email.username && Config.notifications.email.password) { @@ -14,6 +15,10 @@ export function sendNotification(cartUrl: string) { sendSlackMessage(cartUrl); } + if (Config.notifications.telegram.botToken && Config.notifications.telegram.chatId) { + sendTelegramMessage(cartUrl); + } + if (Config.notifications.phone.number) { const carrier = Config.notifications.phone.carrier.toLowerCase(); if (carrier && Config.notifications.phone.availableCarriers.has(carrier)) { @@ -25,7 +30,7 @@ export function sendNotification(cartUrl: string) { sendPushoverNotification(cartUrl); } - if (Config.notifications.playSound) { + if (Config.notifications.playSound !== 'false') { playSound(); } } diff --git a/src/notification/telegram.ts b/src/notification/telegram.ts new file mode 100644 index 0000000..c56964b --- /dev/null +++ b/src/notification/telegram.ts @@ -0,0 +1,21 @@ +import {Config} from '../config'; +import {Logger} from '../logger'; +import {TelegramClient} from 'messaging-api-telegram'; + +const chatId = Config.notifications.telegram.chatId; +const accessToken = Config.notifications.telegram.botToken; + +const client = new TelegramClient({ + accessToken +}); + +export function sendTelegramMessage(text: string) { + (async () => { + try { + await client.sendMessage(chatId, text); + Logger.info(`✔ telegram message sent to '${chatId}': ${text}`); + } catch (error) { + Logger.error(error); + } + })(); +} diff --git a/src/store/lookup.ts b/src/store/lookup.ts index 55e45fa..58e6b75 100644 --- a/src/store/lookup.ts +++ b/src/store/lookup.ts @@ -4,7 +4,20 @@ import {Logger} from '../logger'; import open from 'open'; import {Store} from './model'; import {sendNotification} from '../notification'; -import {isOutOfStock} from './out-of-stock'; +import {isOutOfStock as includesLabels} from './out-of-stock'; + +/** + * Returns true if the brand should be checked for stock + * + * @param brand The brand of the GPU + */ +function filterBrand(brand: string) { + if (Config.showOnlyBrands.length === 0) { + return true; + } + + return Config.showOnlyBrands.includes(brand); +} /** * Responsible for looking up information about a each product within @@ -16,6 +29,10 @@ import {isOutOfStock} from './out-of-stock'; export async function lookup(store: Store) { /* eslint-disable no-await-in-loop */ for (const link of store.links) { + if (!filterBrand(link.brand)) { + continue; + } + const browser = await puppeteer.launch(); const page = await browser.newPage(); page.setDefaultNavigationTimeout(Config.page.navigationTimeout); @@ -40,8 +57,10 @@ export async function lookup(store: Store) { Logger.debug(textContent); - if (isOutOfStock(textContent, link.oosLabels)) { + if (includesLabels(textContent, link.oosLabels)) { Logger.info(`✖ [${store.name}] ${graphicsCard} is still out of stock`); + } else if (link.captchaLabels && includesLabels(textContent, link.captchaLabels)) { + Logger.warn(`✖ [${store.name}] ${graphicsCard} gave us a CAPTCHA`); } else { Logger.info(`🚀🚀🚀 [${store.name}] ${graphicsCard} IN STOCK 🚀🚀🚀`); Logger.info(link.url); diff --git a/src/store/model/amazon.ts b/src/store/model/amazon.ts index 7161a94..3b9737e 100644 --- a/src/store/model/amazon.ts +++ b/src/store/model/amazon.ts @@ -7,49 +7,57 @@ export const Amazon: Store = { brand: 'pny', model: 'xlr8', url: 'https://www.amazon.com/PNY-GeForce-Gaming-Epic-X-Graphics/dp/B08HBR7QBM?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'msi', model: 'gaming trio', url: 'https://www.amazon.com/MSI-GeForce-RTX-3080-10G/dp/B08HR7SV3M?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'evga', model: 'ftw3', url: 'https://www.amazon.com/EVGA-10G-P5-3897-KR-GeForce-Technology-Backplate/dp/B08HR3Y5GQ?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'evga', model: 'xc3', url: 'https://www.amazon.com/EVGA-10G-P5-3885-KR-GeForce-Cooling-Backplate/dp/B08HR55YB5?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'gigabyte', model: 'windforce', url: 'https://www.amazon.com/GIGABYTE-GeForce-Graphics-WINDFORCE-GV-N3080GAMING/dp/B08HJTH61J?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'gigabyte', model: 'windforce eagle', url: 'https://www.amazon.com/GIGABYTE-GeForce-Graphics-WINDFORCE-GV-N3080EAGLE/dp/B08HJS2JLJ?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'asus', model: 'tuf', url: 'https://www.amazon.com/ASUS-Graphics-DisplayPort-Military-Grade-Certification/dp/B08HH5WF97?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] }, { brand: 'msi', model: 'ventus', url: 'https://www.amazon.com/MSI-GeForce-RTX-3080-10G/dp/B08HR5SXPS?ref_=ast_sto_dp', - oosLabels: ['currently unavailable', 'enter the characters you see below'] + oosLabels: ['currently unavailable'], + captchaLabels: ['enter the characters you see below'] } ], name: 'amazon' diff --git a/src/store/model/bestbuy.ts b/src/store/model/bestbuy.ts index 280db56..8496e82 100644 --- a/src/store/model/bestbuy.ts +++ b/src/store/model/bestbuy.ts @@ -33,7 +33,6 @@ export const BestBuy: Store = { url: 'https://www.bestbuy.com/site/gigabyte-geforce-rtx-3080-10g-gddr6x-pci-express-4-0-graphics-card-black/6430621.p?skuId=6430621', oosLabels: ['sold out', 'coming soon'] }, - { brand: 'msi', model: 'ventus 3x', diff --git a/src/store/model/newegg.ts b/src/store/model/newegg.ts index b85145e..5c945b1 100644 --- a/src/store/model/newegg.ts +++ b/src/store/model/newegg.ts @@ -7,31 +7,36 @@ export const NewEgg: Store = { brand: 'asus', model: 'tuf', url: 'https://www.newegg.com/asus-geforce-rtx-3080-tuf-rtx3080-10g-gaming/p/N82E16814126453', - oosLabels: ['auto notify', 'out of stock'] + oosLabels: ['auto notify', 'out of stock'], + captchaLabels: ['are you a human?'] }, { brand: 'evga', model: 'black gaming', url: 'https://www.newegg.com/evga-geforce-rtx-3080-10g-p5-3881-kr/p/N82E16814487522', - oosLabels: ['auto notify', 'out of stock'] + oosLabels: ['auto notify', 'out of stock'], + captchaLabels: ['are you a human?'] }, { brand: 'evga', model: 'argb led icx3', url: 'https://www.newegg.com/evga-geforce-rtx-3080-10g-p5-3883-kr/p/N82E16814487521', - oosLabels: ['auto notify', 'out of stock'] + oosLabels: ['auto notify', 'out of stock'], + captchaLabels: ['are you a human?'] }, { brand: 'evga', model: 'xc3 ultra gaming', url: 'https://www.newegg.com/evga-geforce-rtx-3080-10g-p5-3885-kr/p/N82E16814487520', - oosLabels: ['auto notify', 'out of stock'] + oosLabels: ['auto notify', 'out of stock'], + captchaLabels: ['are you a human?'] }, { brand: 'msi', model: 'ventus', url: 'https://www.newegg.com/msi-geforce-rtx-3080-rtx-3080-ventus-3x-10g/p/N82E16814137600', - oosLabels: ['auto notify', 'out of stock'] + oosLabels: ['auto notify', 'out of stock'], + captchaLabels: ['are you a human?'] } ], name: 'newegg' diff --git a/src/store/model/store.ts b/src/store/model/store.ts index d2c189c..7f5649f 100644 --- a/src/store/model/store.ts +++ b/src/store/model/store.ts @@ -3,6 +3,7 @@ interface Link { model: string; url: string; oosLabels: string[]; + captchaLabels?: string[]; } export interface Store {