mirror of
https://github.com/opelly27/streetmerchant.git
synced 2026-05-20 05:17:35 +00:00
feat: multiple discord roles and webhooks, qol for envs (#260)
This commit is contained in:
@@ -58,16 +58,16 @@ At any point you want the program to stop, use <kbd>Ctrl</kbd> + <kbd>C</kbd>.
|
||||
|
||||
### Customization
|
||||
|
||||
To customize `nvidia-snatcher`, make a copy of `.env-example` as `.env` and make any changes to your liking. _Note that all environment variables are **optional**._
|
||||
To customize `nvidia-snatcher`, make a copy of `.env-example` as `.env` and make any changes to your liking. _All environment variables are **optional**._
|
||||
|
||||
Here is a list of variables that you can use to customize your newly copied `.env` file:
|
||||
|
||||
| **Environment variable** | **Description** | **Notes** |
|
||||
|:---:|---|---|
|
||||
| `BROWSER_TRUSTED` | Skip Chromium Sandbox | Useful for containerized environments, default: `false` |
|
||||
| `DESKTOP_NOTIFICATIONS` | Display desktop notifications using [node-notifier](https://www.npmjs.com/package/node-notifier); optional | Default: `false` |
|
||||
| `DISCORD_NOTIFY_GROUP` | Discord group you would like to notify; optional | E.g.: `<@2834729847239842>` |
|
||||
| `DISCORD_WEB_HOOK` | Discord Web Hook URL | |
|
||||
| `DESKTOP_NOTIFICATIONS` | Display desktop notifications using [node-notifier](https://www.npmjs.com/package/node-notifier) | Default: `false` |
|
||||
| `DISCORD_NOTIFY_GROUP` | Discord group you would like to notify | Can be comma separated, use role ID, E.g.: `<@2834729847239842>` |
|
||||
| `DISCORD_WEB_HOOK` | Discord Web Hook URL | Can be comma separated, use whole webhook URL |
|
||||
| `EMAIL_USERNAME` | Gmail address | E.g.: `jensen.robbed.us@gmail.com` |
|
||||
| `EMAIL_PASSWORD` | Gmail password | See below if you have MFA |
|
||||
| `HEADLESS` | Puppeteer to run headless or not | Debugging related, default: `true` |
|
||||
|
||||
+72
-33
@@ -6,12 +6,52 @@ import path from 'path';
|
||||
|
||||
config({path: path.resolve(__dirname, '../.env')});
|
||||
|
||||
/**
|
||||
* Returns environment variable, given array, or default array.
|
||||
*
|
||||
* @param environment Interested environment variable.
|
||||
* @param array Default array. If not set, is `[]`.
|
||||
*/
|
||||
function envOrArray(environment: string | undefined, array?: string[]): string[] {
|
||||
return environment ? environment.split(',') : (array ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns environment variable, given boolean, or default boolean.
|
||||
*
|
||||
* @param environment Interested environment variable.
|
||||
* @param boolean Default boolean. If not set, is `true`.
|
||||
*/
|
||||
function envOrBoolean(environment: string | undefined, boolean?: boolean): boolean {
|
||||
return environment ? environment === 'true' : (boolean ?? true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns environment variable, given string, or default string.
|
||||
*
|
||||
* @param environment Interested environment variable.
|
||||
* @param string Default string. If not set, is `''`.
|
||||
*/
|
||||
function envOrString(environment: string | undefined, string?: string): string {
|
||||
return environment ? environment : (string ?? '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns environment variable, given number, or default number.
|
||||
*
|
||||
* @param environment Interested environment variable.
|
||||
* @param number Default number. If not set, is `0`.
|
||||
*/
|
||||
function envOrNumber(environment: string | undefined, number?: number): number {
|
||||
return Number(environment ?? (number ?? 0));
|
||||
}
|
||||
|
||||
const browser = {
|
||||
isHeadless: process.env.HEADLESS ? process.env.HEADLESS === 'true' : true,
|
||||
isTrusted: process.env.BROWSER_TRUSTED ? process.env.BROWSER_TRUSTED === 'true' : false,
|
||||
maxSleep: Number(process.env.PAGE_SLEEP_MAX ?? 10000),
|
||||
minSleep: Number(process.env.PAGE_SLEEP_MIN ?? 5000),
|
||||
open: process.env.OPEN_BROWSER ? process.env.OPEN_BROWSER === 'true' : true
|
||||
isHeadless: envOrBoolean(process.env.HEADLESS),
|
||||
isTrusted: envOrBoolean(process.env.BROWSER_TRUSTED, false),
|
||||
maxSleep: envOrNumber(process.env.PAGE_SLEEP_MAX, 10000),
|
||||
minSleep: envOrNumber(process.env.PAGE_SLEEP_MIN, 5000),
|
||||
open: envOrBoolean(process.env.OPEN_BROWSER)
|
||||
};
|
||||
|
||||
const logLevel = process.env.LOG_LEVEL ?? 'info';
|
||||
@@ -19,12 +59,12 @@ const logLevel = process.env.LOG_LEVEL ?? 'info';
|
||||
const notifications = {
|
||||
desktop: process.env.DESKTOP_NOTIFICATIONS === 'true',
|
||||
discord: {
|
||||
notifyGroup: process.env.DISCORD_NOTIFY_GROUP ?? '',
|
||||
webHookUrl: process.env.DISCORD_WEB_HOOK ?? ''
|
||||
notifyGroup: envOrArray(process.env.DISCORD_NOTIFY_GROUP),
|
||||
webHookUrl: envOrArray(process.env.DISCORD_WEB_HOOK)
|
||||
},
|
||||
email: {
|
||||
password: process.env.EMAIL_PASSWORD ?? '',
|
||||
username: process.env.EMAIL_USERNAME ?? ''
|
||||
password: envOrString(process.env.EMAIL_PASSWORD),
|
||||
username: envOrString(process.env.EMAIL_USERNAME)
|
||||
},
|
||||
phone: {
|
||||
availableCarriers: new Map([
|
||||
@@ -36,47 +76,46 @@ const notifications = {
|
||||
['tmobile', 'tmomail.net'],
|
||||
['verizon', 'vtext.com']
|
||||
]),
|
||||
carrier: process.env.PHONE_CARRIER ?? '',
|
||||
number: process.env.PHONE_NUMBER ?? ''
|
||||
carrier: envOrString(process.env.PHONE_CARRIER),
|
||||
number: envOrString(process.env.PHONE_NUMBER)
|
||||
},
|
||||
playSound: process.env.PLAY_SOUND ?? '',
|
||||
pushBulletApiKey: process.env.PUSHBULLET ?? '',
|
||||
playSound: envOrString(process.env.PLAY_SOUND),
|
||||
pushBulletApiKey: envOrString(process.env.PUSHBULLET),
|
||||
pushover: {
|
||||
token: process.env.PUSHOVER_TOKEN ?? '',
|
||||
username: process.env.PUSHOVER_USER ?? ''
|
||||
token: envOrString(process.env.PUSHOVER_TOKEN),
|
||||
username: envOrString(process.env.PUSHOVER_USER)
|
||||
},
|
||||
slack: {
|
||||
channel: process.env.SLACK_CHANNEL ?? '',
|
||||
token: process.env.SLACK_TOKEN ?? ''
|
||||
channel: envOrString(process.env.SLACK_CHANNEL),
|
||||
token: envOrString(process.env.SLACK_TOKEN)
|
||||
},
|
||||
telegram: {
|
||||
accessToken: process.env.TELEGRAM_ACCESS_TOKEN ?? '',
|
||||
chatId: process.env.TELEGRAM_CHAT_ID ?? ''
|
||||
accessToken: envOrString(process.env.TELEGRAM_ACCESS_TOKEN),
|
||||
chatId: envOrString(process.env.TELEGRAM_CHAT_ID)
|
||||
},
|
||||
test: process.env.NOTIFICATION_TEST === 'true',
|
||||
twitter: {
|
||||
accessTokenKey: process.env.TWITTER_ACCESS_TOKEN_KEY ?? '',
|
||||
accessTokenSecret: process.env.TWITTER_ACCESS_TOKEN_SECRET ?? '',
|
||||
consumerKey: process.env.TWITTER_CONSUMER_KEY ?? '',
|
||||
consumerSecret: process.env.TWITTER_CONSUMER_SECRET ?? '',
|
||||
tweetTags: process.env.TWITTER_TWEET_TAGS ?? ''
|
||||
accessTokenKey: envOrString(process.env.TWITTER_ACCESS_TOKEN_KEY),
|
||||
accessTokenSecret: envOrString(process.env.TWITTER_ACCESS_TOKEN_SECRET),
|
||||
consumerKey: envOrString(process.env.TWITTER_CONSUMER_KEY),
|
||||
consumerSecret: envOrString(process.env.TWITTER_CONSUMER_SECRET),
|
||||
tweetTags: envOrString(process.env.TWITTER_TWEET_TAGS)
|
||||
}
|
||||
};
|
||||
|
||||
const page = {
|
||||
capture: process.env.SCREENSHOT ? process.env.SCREENSHOT === 'true' : 'true',
|
||||
height: 1080,
|
||||
inStockWaitTime: Number(process.env.IN_STOCK_WAIT_TIME ?? 0),
|
||||
navigationTimeout: Number(process.env.PAGE_TIMEOUT ?? 30000),
|
||||
userAgent: process.env.USER_AGENT ?? 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
|
||||
inStockWaitTime: envOrNumber(process.env.IN_STOCK_WAIT_TIME),
|
||||
navigationTimeout: envOrNumber(process.env.PAGE_TIMEOUT, 30000),
|
||||
screenshot: envOrBoolean(process.env.SCREENSHOT),
|
||||
userAgent: envOrString(process.env.USER_AGENT, 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'),
|
||||
width: 1920
|
||||
};
|
||||
|
||||
const store = {
|
||||
country: process.env.COUNTRY ?? 'usa',
|
||||
showOnlyBrands: process.env.SHOW_ONLY_BRANDS ? process.env.SHOW_ONLY_BRANDS.split(',') : [],
|
||||
showOnlySeries: process.env.SHOW_ONLY_SERIES ? process.env.SHOW_ONLY_SERIES.split(',') : ['3070', '3080', '3090'],
|
||||
stores: process.env.STORES ? process.env.STORES.split(',') : ['nvidia']
|
||||
country: envOrString(process.env.COUNTRY, 'usa'),
|
||||
showOnlyBrands: envOrArray(process.env.SHOW_ONLY_BRANDS),
|
||||
showOnlySeries: envOrArray(process.env.SHOW_ONLY_SERIES, ['3070', '3080', '3090']),
|
||||
stores: envOrArray(process.env.STORES, ['nvidia'])
|
||||
};
|
||||
|
||||
export const Config = {
|
||||
|
||||
@@ -3,7 +3,7 @@ import {MessageBuilder, Webhook} from 'discord-webhook-node';
|
||||
import {Config} from '../config';
|
||||
import {Logger} from '../logger';
|
||||
|
||||
const hook = new Webhook(Config.notifications.discord.webHookUrl);
|
||||
const hooks = Config.notifications.discord.webHookUrl;
|
||||
const notifyGroup = Config.notifications.discord.notifyGroup;
|
||||
|
||||
export function sendDiscordMessage(link: Link, store: Store) {
|
||||
@@ -17,12 +17,18 @@ export function sendDiscordMessage(link: Link, store: Store) {
|
||||
embed.addField('Model', link.model, true);
|
||||
|
||||
if (notifyGroup) {
|
||||
embed.setText(notifyGroup);
|
||||
embed.setText(notifyGroup.join(' '));
|
||||
}
|
||||
|
||||
embed.setColor(0x76B900);
|
||||
embed.setTimestamp();
|
||||
await hook.send(embed);
|
||||
|
||||
const promises = [];
|
||||
for (const hook of hooks) {
|
||||
promises.push(new Webhook(hook).send(embed));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
Logger.info('✔ discord message sent');
|
||||
} catch (error) {
|
||||
|
||||
+2
-1
@@ -39,6 +39,7 @@ function filterSeries(series: Link['series']) {
|
||||
* Responsible for looking up information about a each product within
|
||||
* a `Store`. It's important that we ignore `no-await-in-loop` here
|
||||
* because we don't want to get rate limited within the same store.
|
||||
*
|
||||
* @param browser Puppeteer browser.
|
||||
* @param store Vendor of graphics cards.
|
||||
*/
|
||||
@@ -94,7 +95,7 @@ async function lookupCard(browser: Browser, store: Store, page: Page, link: Link
|
||||
}, 1000 * Config.page.inStockWaitTime);
|
||||
}
|
||||
|
||||
if (Config.page.capture) {
|
||||
if (Config.page.screenshot) {
|
||||
Logger.debug('ℹ saving screenshot');
|
||||
|
||||
link.screenshot = `success-${Date.now()}.png`;
|
||||
|
||||
Reference in New Issue
Block a user