feat(notification): add pushbullet, add url with notifications (#226)

Co-authored-by: Jef LeCompte <jeffreylec@gmail.com>
This commit is contained in:
fuckingrobot
2020-09-23 10:45:04 -04:00
committed by GitHub
parent 20656805c1
commit 74490eae3a
11 changed files with 106 additions and 8 deletions
+1
View File
@@ -11,6 +11,7 @@ PAGE_TIMEOUT="30000"
PHONE_NUMBER="1234567890" PHONE_NUMBER="1234567890"
PHONE_CARRIER="tmobile" PHONE_CARRIER="tmobile"
PLAY_SOUND="notification.mp3" PLAY_SOUND="notification.mp3"
PUSHBULLET="o.pushbulletTokendbjVjvJHVhcg"
PUSHOVER_TOKEN="123pushover-token456" PUSHOVER_TOKEN="123pushover-token456"
PUSHOVER_USER="123pushover-user-key" PUSHOVER_USER="123pushover-user-key"
PAGE_SLEEP_MIN="5000" PAGE_SLEEP_MIN="5000"
+1
View File
@@ -76,6 +76,7 @@ Here is a list of variables that you can use to customize your newly copied `.en
| `PHONE_NUMBER` | 10 digit phone number | E.g.: `1234567890`, email configuration required | | `PHONE_NUMBER` | 10 digit phone number | E.g.: `1234567890`, email configuration required |
| `PHONE_CARRIER` | [Supported carriers](#supported-carriers) for SMS | Email configuration required | | `PHONE_CARRIER` | [Supported carriers](#supported-carriers) for SMS | Email configuration required |
| `PLAY_SOUND` | Play this sound notification if a card is found | E.g.: `path/to/notification.wav`, relative path accepted, valid formats: wav, mp3, flac, [free sounds available](https://notificationsounds.com/) | | `PLAY_SOUND` | Play this sound notification if a card is found | E.g.: `path/to/notification.wav`, relative path accepted, valid formats: wav, mp3, flac, [free sounds available](https://notificationsounds.com/) |
| `PUSHBULLET` | PushBullet API key | Get at https://www.pushbullet.com/#settings/account |
| `PUSHOVER_TOKEN` | Pushover access token | Generate at https://pushover.net/apps/build | | `PUSHOVER_TOKEN` | Pushover access token | Generate at https://pushover.net/apps/build |
| `PUSHOVER_USER` | Pushover username | | `PUSHOVER_USER` | Pushover username |
| `PAGE_SLEEP_MIN` | Minimum sleep time between queries of the same store | Default: `5000` | | `PAGE_SLEEP_MIN` | Minimum sleep time between queries of the same store | Default: `5000` |
+61
View File
@@ -879,6 +879,11 @@
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
}, },
"async-limiter": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
"integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
},
"asynckit": { "asynckit": {
"version": "0.4.0", "version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -1427,6 +1432,11 @@
"integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==",
"dev": true "dev": true
}, },
"clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
},
"clone-deep": { "clone-deep": {
"version": "0.2.4", "version": "0.2.4",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz",
@@ -4821,6 +4831,11 @@
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
}, },
"node-forge": {
"version": "0.7.6",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz",
"integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw=="
},
"node-libs-browser": { "node-libs-browser": {
"version": "2.2.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
@@ -5636,6 +5651,29 @@
} }
} }
}, },
"pushbullet": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/pushbullet/-/pushbullet-2.4.0.tgz",
"integrity": "sha512-9CkgzAmBOv/ekxI4oqlFXdFIdKEMQgv1NBUbQYYxo/OsGYdnM2D9xEtWLQLkMAkpZUwbNr9lHq7a27082+eQMw==",
"requires": {
"clone": "^2.1.2",
"mime": "^2.4.0",
"node-forge": "^0.7.6",
"request": "^2.88.0",
"request-promise-native": "^1.0.5",
"ws": "^6.1.2"
},
"dependencies": {
"ws": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
"integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
"requires": {
"async-limiter": "~1.0.0"
}
}
}
},
"pushover-notifications": { "pushover-notifications": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/pushover-notifications/-/pushover-notifications-1.2.2.tgz", "resolved": "https://registry.npmjs.org/pushover-notifications/-/pushover-notifications-1.2.2.tgz",
@@ -5913,6 +5951,24 @@
} }
} }
}, },
"request-promise-core": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz",
"integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==",
"requires": {
"lodash": "^4.17.19"
}
},
"request-promise-native": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz",
"integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==",
"requires": {
"request-promise-core": "1.1.4",
"stealthy-require": "^1.1.1",
"tough-cookie": "^2.3.3"
}
},
"reserved-words": { "reserved-words": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz", "resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz",
@@ -6396,6 +6452,11 @@
} }
} }
}, },
"stealthy-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
},
"stream-browserify": { "stream-browserify": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+1
View File
@@ -31,6 +31,7 @@
"puppeteer-extra": "^3.1.15", "puppeteer-extra": "^3.1.15",
"puppeteer-extra-plugin-adblocker": "^2.11.6", "puppeteer-extra-plugin-adblocker": "^2.11.6",
"puppeteer-extra-plugin-stealth": "^2.6.1", "puppeteer-extra-plugin-stealth": "^2.6.1",
"pushbullet": "^2.4.0",
"pushover-notifications": "^1.2.2", "pushover-notifications": "^1.2.2",
"twitter": "^1.7.1", "twitter": "^1.7.1",
"winston": "^3.3.3" "winston": "^3.3.3"
+1
View File
@@ -37,6 +37,7 @@ const notifications = {
number: process.env.PHONE_NUMBER ?? '' number: process.env.PHONE_NUMBER ?? ''
}, },
playSound: process.env.PLAY_SOUND ?? '', playSound: process.env.PLAY_SOUND ?? '',
pushBulletApiKey: process.env.PUSHBULLET ?? '',
pushover: { pushover: {
token: process.env.PUSHOVER_TOKEN ?? '', token: process.env.PUSHOVER_TOKEN ?? '',
username: process.env.PUSHOVER_USER ?? '' username: process.env.PUSHOVER_USER ?? ''
+5
View File
@@ -4,6 +4,7 @@ import {playSound} from './sound';
import {sendDesktopNotification} from './desktop'; import {sendDesktopNotification} from './desktop';
import {sendDiscordMessage} from './discord'; import {sendDiscordMessage} from './discord';
import {sendEmail} from './email'; import {sendEmail} from './email';
import {sendPushBulletNotification} from './pushbullet';
import {sendPushoverNotification} from './pushover'; import {sendPushoverNotification} from './pushover';
import {sendSMS} from './sms'; import {sendSMS} from './sms';
import {sendSlackMessage} from './slack'; import {sendSlackMessage} from './slack';
@@ -36,6 +37,10 @@ export function sendNotification(cartUrl: string, link: Link) {
} }
} }
if (notifications.pushBulletApiKey) {
sendPushBulletNotification(cartUrl, link);
}
if (notifications.pushover.token && notifications.pushover.username) { if (notifications.pushover.token && notifications.pushover.username) {
sendPushoverNotification(cartUrl); sendPushoverNotification(cartUrl);
} }
+19
View File
@@ -0,0 +1,19 @@
import {Config} from '../config';
import {Link} from '../store/model';
import {Logger} from '../logger';
import PushBullet from 'pushbullet';
const pushBulletApiKey = Config.notifications.pushBulletApiKey;
export function sendPushBulletNotification(cartUrl: string, link: Link) {
const pusher = new PushBullet(pushBulletApiKey);
const title = `🚨 ${link.brand} ${link.model} ${link.series} 👀`;
pusher.note({}, title, cartUrl, (err: Error, result: string) => {
if (err) {
Logger.error(err);
} else {
Logger.info(`↗ pushbullet notification sent: ${result}`);
}
});
}
+2 -2
View File
@@ -88,13 +88,13 @@ async function lookupCard(browser: Browser, store: Store, page: Page, link: Link
await page.screenshot({path: link.screenshot}); await page.screenshot({path: link.screenshot});
} }
const givenUrl = link.cartUrl ? link.cartUrl : link.url; let givenUrl = link.cartUrl ? link.cartUrl : link.url;
if (Config.browser.open) { if (Config.browser.open) {
if (link.openCartAction === undefined) { if (link.openCartAction === undefined) {
await open(givenUrl); await open(givenUrl);
} else { } else {
link.openCartAction(browser); givenUrl = await link.openCartAction(browser);
} }
} }
+13 -5
View File
@@ -67,8 +67,11 @@ export function generateSetupAction() {
const accessToken = data.access_token; const accessToken = data.access_token;
Logger.info('[nvidia] you can log into your cart now...'); Logger.info('[nvidia] you can log into your cart now...');
Logger.info(checkoutUrl(drLocale, accessToken)); const cartUrl = checkoutUrl(drLocale, accessToken);
await open(checkoutUrl(drLocale, accessToken)); Logger.info(cartUrl);
if (Config.browser.open) {
await open(cartUrl);
}
} catch (error) { } catch (error) {
Logger.debug(error); Logger.debug(error);
Logger.error('✖ [nvidia] cannot generate cart/session token, continuing without, auto-"add to cart" may not work...'); Logger.error('✖ [nvidia] cannot generate cart/session token, continuing without, auto-"add to cart" may not work...');
@@ -83,6 +86,7 @@ export function generateOpenCartAction(id: number, nvidiaLocale: string, drLocal
const page = await browser.newPage(); const page = await browser.newPage();
Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, starting auto add to cart... 🚀🚀🚀`); Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, starting auto add to cart... 🚀🚀🚀`);
let response: Response | null; let response: Response | null;
let cartUrl: string;
try { try {
Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, getting access token... 🚀🚀🚀`); Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, getting access token... 🚀🚀🚀`);
response = await page.goto(nvidiaSessionUrl(nvidiaLocale), {waitUntil: 'networkidle0'}); response = await page.goto(nvidiaSessionUrl(nvidiaLocale), {waitUntil: 'networkidle0'});
@@ -97,15 +101,19 @@ export function generateOpenCartAction(id: number, nvidiaLocale: string, drLocal
response = await page.goto(addToCartUrl(id, drLocale, accessToken), {waitUntil: 'networkidle0'}); response = await page.goto(addToCartUrl(id, drLocale, accessToken), {waitUntil: 'networkidle0'});
Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, opening checkout page... 🚀🚀🚀`); Logger.info(`🚀🚀🚀 [nvidia] ${cardName}, opening checkout page... 🚀🚀🚀`);
Logger.info(checkoutUrl(drLocale, accessToken)); cartUrl = checkoutUrl(drLocale, accessToken);
await open(checkoutUrl(drLocale, accessToken)); Logger.info(cartUrl);
await open(cartUrl);
} catch (error) { } catch (error) {
Logger.debug(error); Logger.debug(error);
Logger.error(`✖ [nvidia] ${cardName} could not automatically add to cart, opening page`); Logger.error(`✖ [nvidia] ${cardName} could not automatically add to cart, opening page`);
await open(fallbackCartUrl(nvidiaLocale)); cartUrl = fallbackCartUrl(nvidiaLocale);
await open(cartUrl);
} }
await page.close(); await page.close();
return cartUrl;
}; };
} }
+1 -1
View File
@@ -11,7 +11,7 @@ export interface Link {
model: string; model: string;
url: string; url: string;
cartUrl?: string; cartUrl?: string;
openCartAction?: (browser: Browser) => void; openCartAction?: (browser: Browser) => Promise<string>;
screenshot?: string; screenshot?: string;
} }
+1
View File
@@ -0,0 +1 @@
declare module 'pushbullet';