mirror of
https://github.com/opelly27/streetmerchant.git
synced 2026-05-20 02:57:34 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fcb279d5de | |||
| 5c9e0b6d06 | |||
| 6c3cd01685 | |||
| d907092b44 | |||
| 7cfc7c7442 | |||
| 971fec20e4 | |||
| d73449dd7f | |||
| edf17e926f | |||
| faad3e68ef | |||
| 131dda4d5a | |||
| 2246ecedf2 | |||
| 5a3636bcb6 | |||
| ec2108f4b9 | |||
| fad9ea04c7 | |||
| 643045c7e0 | |||
| 7d7bd18b4d | |||
| ec98602d5b | |||
| a2fb97333c | |||
| c0a881a16e | |||
| c2a210cc81 | |||
| aa856c7121 | |||
| f0560ce72b | |||
| 00ede13501 | |||
| feed4ed6e4 | |||
| a152f8a5cc | |||
| 00a0687d3e | |||
| d3ec4bc85e | |||
| 1a13c03250 | |||
| 6c6503219f | |||
| efe799b8b9 | |||
| 4a5886782b | |||
| e1a90c931d | |||
| eb4f5e0341 |
@@ -1,3 +1,11 @@
|
||||
EMAIL_USERNAME="youremail@gmail.com"
|
||||
EMAIL_PASSWORD="secretpassword"
|
||||
NOTIFICATION_TEST="false"
|
||||
PAGE_TIMEOUT="30000"
|
||||
RATE_LIMIT_TIMEOUT="5000"
|
||||
SLACK_CHANNEL="SlackChannelName"
|
||||
SLACK_TOKEN="slack-token"
|
||||
STORES="bestbuy,bandh,nvidia"
|
||||
PHONE_NUMBER="1234567890"
|
||||
PHONE_CARRIER="tmobile"
|
||||
SCREENSHOT="true"
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<!-- Please use Conventional Commits to label your title -->
|
||||
<!-- https://www.conventionalcommits.org/en/v1.0.0/ -->
|
||||
<!-- Example: feat: allow provided config object to extend other configs -->
|
||||
|
||||
### Description
|
||||
|
||||
<!-- Fixes #(issue) -->
|
||||
|
||||
@@ -4,7 +4,7 @@ on:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
lint:
|
||||
build-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
@@ -16,7 +16,10 @@ jobs:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: ${{ runner.os }}-node-
|
||||
- name: Add problem matcher
|
||||
run: echo "::add-matcher::.github/xo-problem-matcher.json"
|
||||
- name: Pull dependencies
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
npm run lint
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "xo",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\s+(.*):(\\d+):(\\d+)$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "^\\s+✖\\s+(\\d+):(\\d+)\\s+(.*)\\s+(.*)$",
|
||||
"line": 1,
|
||||
"column": 2,
|
||||
"message": 3,
|
||||
"code": 4,
|
||||
"loop": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
.idea/
|
||||
.vs/
|
||||
.vscode/
|
||||
build/
|
||||
node_modules/
|
||||
|
||||
.env
|
||||
success-*.png
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
# Changelog
|
||||
|
||||
## [1.3.0](https://www.github.com/jef/nvidia-snatcher/compare/v1.2.0...v1.3.0) (2020-09-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **logging:** add timestamp ([#48](https://www.github.com/jef/nvidia-snatcher/issues/48)) ([6c3cd01](https://www.github.com/jef/nvidia-snatcher/commit/6c3cd016850d03a6c6a894cab24ba2d3781a9af1))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **store:** amazon captcha false-positives ([#54](https://www.github.com/jef/nvidia-snatcher/issues/54)) ([5c9e0b6](https://www.github.com/jef/nvidia-snatcher/commit/5c9e0b6d06bd7e1223a7587fec067c8e79c9cfd6))
|
||||
* evga xc3 ultra link ([#56](https://www.github.com/jef/nvidia-snatcher/issues/56)) ([d907092](https://www.github.com/jef/nvidia-snatcher/commit/d907092b443b056605e09cb2ca3e94e6ca811d9e))
|
||||
* screenshot size, add screenshot config setting ([#53](https://www.github.com/jef/nvidia-snatcher/issues/53)) ([7cfc7c7](https://www.github.com/jef/nvidia-snatcher/commit/7cfc7c74429c808fa14468cdd497eb9f9aeb922c))
|
||||
* sms carrier config, add google carrier ([#44](https://www.github.com/jef/nvidia-snatcher/issues/44)) ([971fec2](https://www.github.com/jef/nvidia-snatcher/commit/971fec20e441e2b12a38d5c8d17d2d4cb5e64d6b))
|
||||
|
||||
## [1.2.0](https://www.github.com/jef/nvidia-snatcher/compare/v1.1.0...v1.2.0) (2020-09-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **ci:** add `npm run build` ([faad3e6](https://www.github.com/jef/nvidia-snatcher/commit/faad3e68efafaab135b77080b02af83429b6eca6))
|
||||
* **store:** microcenter ([#39](https://www.github.com/jef/nvidia-snatcher/issues/39)) ([edf17e9](https://www.github.com/jef/nvidia-snatcher/commit/edf17e926f3d186e7630da2834d78de3e540a956))
|
||||
* add Amazon links ([#26](https://www.github.com/jef/nvidia-snatcher/issues/26)) ([f0560ce](https://www.github.com/jef/nvidia-snatcher/commit/f0560ce72bfbfdd6360b85e23edaa875d58f228f))
|
||||
* add email test, fix memory leak ([#24](https://www.github.com/jef/nvidia-snatcher/issues/24)) ([a2fb973](https://www.github.com/jef/nvidia-snatcher/commit/a2fb97333c6eb81250b24ccb6859e9356acded21))
|
||||
* more Best Buy AIBs ([#41](https://www.github.com/jef/nvidia-snatcher/issues/41)) ([7d7bd18](https://www.github.com/jef/nvidia-snatcher/commit/7d7bd18b4dd656ec01ef2fb2d8519e2a7f34ef70))
|
||||
* page timeout ([#22](https://www.github.com/jef/nvidia-snatcher/issues/22)) ([643045c](https://www.github.com/jef/nvidia-snatcher/commit/643045c7e0158fb6526bd09427b96cce7958bcea))
|
||||
* slack integration ([#34](https://www.github.com/jef/nvidia-snatcher/issues/34)) ([c0a881a](https://www.github.com/jef/nvidia-snatcher/commit/c0a881a16ebb573bf35b7f29cb27e5b3c2e1fe78))
|
||||
* sms notification for usa carriers ([#40](https://www.github.com/jef/nvidia-snatcher/issues/40)) ([5a3636b](https://www.github.com/jef/nvidia-snatcher/commit/5a3636bcb639bb33bc586af96264f5df2f3a8307))
|
||||
* update to check if FE in-stock via Digital River ([#29](https://www.github.com/jef/nvidia-snatcher/issues/29)) ([00ede13](https://www.github.com/jef/nvidia-snatcher/commit/00ede13501082f530ea672a349816be1d31621a8))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* small error in `isOutOfStock` logic ([#33](https://www.github.com/jef/nvidia-snatcher/issues/33)) ([c2a210c](https://www.github.com/jef/nvidia-snatcher/commit/c2a210cc815c3aa06f6f14d33954f65577d95954))
|
||||
|
||||
## [1.1.0](https://www.github.com/jef/nvidia-snatcher/compare/v1.0.0...v1.1.0) (2020-09-18)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add conventional commits ([#14](https://www.github.com/jef/nvidia-snatcher/issues/14)) ([eb4f5e0](https://www.github.com/jef/nvidia-snatcher/commit/eb4f5e034176a286eabe381c98ced77cd197d7fb))
|
||||
* add evga ([#17](https://www.github.com/jef/nvidia-snatcher/issues/17)) ([#18](https://www.github.com/jef/nvidia-snatcher/issues/18)) ([6c65032](https://www.github.com/jef/nvidia-snatcher/commit/6c6503219f7c188783c24a44f7052b276a4b39a3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* exception handling `TimeoutError` ([#20](https://www.github.com/jef/nvidia-snatcher/issues/20)) ([#21](https://www.github.com/jef/nvidia-snatcher/issues/21)) ([00a0687](https://www.github.com/jef/nvidia-snatcher/commit/00a0687d3eba6a8fca871161b447529be00c8896))
|
||||
|
||||
## 1.0.0 (2020-09-18)
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
# nvidia-snatcher [](https://github.com/jef/nvidia-snatcher/actions?query=workflow%3Aci)
|
||||
|
||||
The purpose of this bot is to get an Nvidia card. It does multiple things to try to do that.
|
||||
[FAQ](#FAQ) | [Discord](https://discord.gg/3duFzwk) | [Issues](https://github.com/jef/nvidia-snatcher/issues) | [Wiki](https://github.com/jef/nvidia-snatcher/wiki)
|
||||
|
||||
The purpose of this bot is to get an Nvidia card. It tries multiple things to do that.
|
||||
|
||||
- Currently, `nvidia-snatcher` is not capable of purchasing a card for you
|
||||
- Scrapes multiple websites for patterns of being stocked
|
||||
- API requests are a work in progress (very soon)
|
||||
- Opens browser when stock is available
|
||||
- Send email to you when away from computer
|
||||
- Must have Gmail
|
||||
- Sends an email to you when stock is avaiable (must have Gmail)
|
||||
|
||||
<details>
|
||||
<summary>What you may see if you're lucky</summary>
|
||||
@@ -24,17 +26,15 @@ The purpose of this bot is to get an Nvidia card. It does multiple things to try
|
||||
|
||||
</details>
|
||||
|
||||
> :point_right: You may get false positives from time to time, so I apologize for that. The library currently waits for all calls to be completed before parsing, but sometimes this can unknown behavior. Patience is a virtue :)
|
||||
> :point_right: You may get false positives from time to time, so I apologize for that. The library currently waits for all calls to be completed before parsing, but sometimes this can have unknown behavior. Patience is a virtue :)
|
||||
|
||||
| | **Best Buy** | **B&H** | **Newegg** | **Nvidia** |
|
||||
|:---:|:---:|:---:|:---:|:---:|
|
||||
| **3070**| | | | |
|
||||
| **3080** | `✔` | `✔` | `ℹ` | `✔` |
|
||||
| **3090** | | | | |
|
||||
| | **Best Buy** | **B&H** | **Newegg** | **Nvidia** | **EVGA** | **Amazon** |
|
||||
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||
| **3070**| | | | | | |
|
||||
| **3080** | `✔` | `✔` | `ℹ` | `✔` | `✔` | `✔` |
|
||||
| **3090** | | | | | | |
|
||||
|
||||
> :point_right: (`ℹ`) In the process of getting working. Catchpa problems are intermittent. Use if you'd like, but expect problems.
|
||||
|
||||
[FAQ](#FAQ) | [Discord](https://discord.gg/3duFzwk) | [Issues](https://github.com/jef/nvidia-snatcher/issues)
|
||||
> :point_right: (`ℹ`) Work in progress. Catchpa problems are intermittent. Use if you'd like, but expect problems.
|
||||
|
||||
## Installation and prerequisites
|
||||
|
||||
@@ -42,15 +42,19 @@ Linux, macOS, and Windows are all capable operating systems.
|
||||
|
||||
You do not need any computer skills, smarts, or anything of that nature. You are very capable as you have made it this far. Some basic understanding how a terminal, git, and or Node.js is a bonus, but that does not limit you to getting `nvidia-snatcher` running!
|
||||
|
||||
- Download [Node.js 14](https://nodejs.org/en/)
|
||||
- Download [git](https://git-scm.com/)
|
||||
- Clone this project `https://github.com/jef/nvidia-snatcher.git`
|
||||
- Run `npm install`
|
||||
- Edit the `.env` file to your liking
|
||||
- More on this in [customization](#Customization)
|
||||
- Run `npm run start`
|
||||
### Quick overview
|
||||
|
||||
Then watch the magic happen!
|
||||
- [Node.js 14](https://nodejs.org/en/)
|
||||
- [git](https://git-scm.com/)
|
||||
- Clone this project `git clone https://github.com/jef/nvidia-snatcher.git`
|
||||
- Run `npm install`
|
||||
- Copy `.env.example` to a new file `.env` and edit the `.env` file to your liking using your [favorite text editor](https://code.visualstudio.com/)
|
||||
- More on this in [customization](#Customization)
|
||||
- Run `npm run start` to start
|
||||
|
||||
At any point you want the program to stop, use <kbd>Ctrl</kbd> + <kbd>C</kbd>.
|
||||
|
||||
> :point_right: Please visit the [wiki](https://github.com/jef/nvidia-snatcher/wiki) if you need more help with installation.
|
||||
|
||||
### Customization
|
||||
|
||||
@@ -60,12 +64,34 @@ First, you're going to need to copy the `.env.example` to `.env`. The current op
|
||||
|
||||
| **Environment variable** | **Description** |
|
||||
|:---:|:---:|
|
||||
| `EMAIL_USERNAME` | Gmail address; e.g. `jensen.robbed.us@gmail.com` |
|
||||
| `EMAIL_PASSWORD` | Gmail password; see below if you have MFA |
|
||||
| `STORES` | List of stores you want to be scraped; optional, default: `nvidia` |
|
||||
| `EMAIL_USERNAME` | Gmail address (e.g., `jensen.robbed.us@gmail.com`); optional |
|
||||
| `EMAIL_PASSWORD` | Gmail password; see below if you have MFA; optional |
|
||||
| `NOTIFICATION_TEST` | Test all the notifications configured; optional, default: `false` |
|
||||
| `PAGE_TIMEOUT` | Navigation Timeout in milliseconds (`0` for infinite); optional, default: `30000` |
|
||||
| `PHONE_NUMBER` | 10 digit phone number, only USA, SMS may apply (e.g., `1234567890`); optional, email configuration required |
|
||||
| `PHONE_CARRIER` | Service provider for SMS, supports `["sprint", "tmobile", "att", "verizon", "google"]`; 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
|
||||
| `STORES` | List of [stores](#Supported-stores) you want to be scraped; optional, default: `nvidia` |
|
||||
| `SCREENSHOT` | Capture screenshot of page on successful hit; optional, default `true` |
|
||||
|
||||
> :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.
|
||||
|
||||
#### Supported stores
|
||||
|
||||
| **Store name** | **Store name environment variable** |
|
||||
|:---:|:---:|
|
||||
| Best Buy | `bestbuy`|
|
||||
| Amazon | `amazon`|
|
||||
| B&H | `bandh`|
|
||||
| EVGA | `evga`|
|
||||
| Micro Center | `microcenter`|
|
||||
| Newegg | `newegg`|
|
||||
| Nvidia | `nvidia`|
|
||||
|
||||
> :point_right: Look at [`.env.example`](.env.example) for an example for `.env`.
|
||||
|
||||
## FAQ
|
||||
|
||||
**Q: What's Node.js and how do I install it?** Visit [their website](https://nodejs.org/en/) and download and install it. Very straight forward. Otherwise, Google more information related to your system needs.
|
||||
|
||||
Generated
+174
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nvidia-snatcher",
|
||||
"version": "1.0.0",
|
||||
"version": "1.3.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -173,6 +173,48 @@
|
||||
"integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@slack/logger": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/logger/-/logger-2.0.0.tgz",
|
||||
"integrity": "sha512-OkIJpiU2fz6HOJujhlhfIGrc8hB4ibqtf7nnbJQDerG0BqwZCfmgtK5sWzZ0TkXVRBKD5MpLrTmCYyMxoMCgPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": ">=8.9.0"
|
||||
}
|
||||
},
|
||||
"@slack/types": {
|
||||
"version": "1.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/types/-/types-1.9.0.tgz",
|
||||
"integrity": "sha512-RmwgMWqOtzd2JPXdiaD/tyrDD0vtjjRDFdxN1I3tAxwBbg4aryzDUVqFc8na16A+3Xik/UN8X1hvVTw8J4EB9w==",
|
||||
"dev": true
|
||||
},
|
||||
"@slack/web-api": {
|
||||
"version": "5.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@slack/web-api/-/web-api-5.12.0.tgz",
|
||||
"integrity": "sha512-ygSnNHVid7PltGo7W36f2SNVHyliemkzxn9uSwgnWNF7CHmWBKWAylU/eoDml9l5K7akMOxbousiurOw4XqOFg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@slack/logger": ">=1.0.0 <3.0.0",
|
||||
"@slack/types": "^1.7.0",
|
||||
"@types/is-stream": "^1.1.0",
|
||||
"@types/node": ">=8.9.0",
|
||||
"@types/p-queue": "^2.3.2",
|
||||
"axios": "^0.19.0",
|
||||
"eventemitter3": "^3.1.0",
|
||||
"form-data": "^2.5.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"p-queue": "^2.4.2",
|
||||
"p-retry": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
|
||||
@@ -204,6 +246,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha512-jkZatu4QVbR60mpIzjINmtS1ZF4a/FqdTUTBeQDVOQ2PYyidtwFKr0B5G6ERukKwliq+7mIXvxyppwzG5EgRYg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/json-schema": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz",
|
||||
@@ -248,6 +299,12 @@
|
||||
"integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/p-queue": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/p-queue/-/p-queue-2.3.2.tgz",
|
||||
"integrity": "sha512-eKAv5Ql6k78dh3ULCsSBxX6bFNuGjTmof5Q/T6PiECDq0Yf8IIn46jCyp3RJvCi8owaEmm3DZH1PEImjBMd/vQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
|
||||
@@ -263,6 +320,12 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/yauzl": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||
@@ -564,6 +627,12 @@
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
|
||||
"integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
},
|
||||
"at-least-node": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
|
||||
@@ -576,6 +645,15 @@
|
||||
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
|
||||
"dev": true
|
||||
},
|
||||
"axios": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"babel-eslint": {
|
||||
"version": "10.1.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
|
||||
@@ -1116,6 +1194,15 @@
|
||||
"text-hex": "1.0.x"
|
||||
}
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"commondir": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||
@@ -1410,6 +1497,12 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"des.js": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
|
||||
@@ -2316,6 +2409,12 @@
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
|
||||
"integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
|
||||
"dev": true
|
||||
},
|
||||
"events": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz",
|
||||
@@ -2670,12 +2769,49 @@
|
||||
"resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz",
|
||||
"integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="
|
||||
},
|
||||
"follow-redirects": {
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"debug": {
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
|
||||
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.6",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fragment-cache": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||
@@ -3866,6 +4002,21 @@
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz",
|
||||
"integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.44.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz",
|
||||
"integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==",
|
||||
"dev": true
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.27",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz",
|
||||
"integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mime-db": "1.44.0"
|
||||
}
|
||||
},
|
||||
"mimic-response": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
|
||||
@@ -4321,12 +4472,28 @@
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-queue": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz",
|
||||
"integrity": "sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng==",
|
||||
"dev": true
|
||||
},
|
||||
"p-reduce": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-2.1.0.tgz",
|
||||
"integrity": "sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==",
|
||||
"dev": true
|
||||
},
|
||||
"p-retry": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.2.0.tgz",
|
||||
"integrity": "sha512-jPH38/MRh263KKcq0wBNOGFJbm+U6784RilTmHjB/HM9kH9V8WlCpVUcdOmip9cjXOh6MxZ5yk1z2SjDUJfWmA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/retry": "^0.12.0",
|
||||
"retry": "^0.12.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
@@ -4890,6 +5057,12 @@
|
||||
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
|
||||
"dev": true
|
||||
},
|
||||
"retry": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
|
||||
"integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nvidia-snatcher",
|
||||
"version": "1.0.0",
|
||||
"version": "1.3.0",
|
||||
"description": "🔮 For all your Nvidia needs",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
@@ -28,6 +28,7 @@
|
||||
"winston": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@slack/web-api": "^5.12.0",
|
||||
"@types/node": "^14.11.1",
|
||||
"@types/nodemailer": "^6.4.0",
|
||||
"@types/puppeteer": "^3.0.2",
|
||||
|
||||
+22
-11
@@ -3,27 +3,38 @@ import {config} from 'dotenv';
|
||||
|
||||
config({path: resolve(__dirname, '../.env')});
|
||||
|
||||
const email = {
|
||||
username: process.env.EMAIL_USERNAME,
|
||||
password: process.env.EMAIL_PASSWORD
|
||||
};
|
||||
|
||||
const notifications = {
|
||||
email: email.username && email.password
|
||||
email: {
|
||||
username: process.env.EMAIL_USERNAME ?? '',
|
||||
password: process.env.EMAIL_PASSWORD ?? ''
|
||||
},
|
||||
phone: {
|
||||
availableCarriers: ['sprint', 'verizon', 'tmobile', 'att', 'google'],
|
||||
carrier: process.env.PHONE_CARRIER,
|
||||
number: process.env.PHONE_NUMBER
|
||||
},
|
||||
slack: {
|
||||
channel: process.env.SLACK_CHANNEL ?? '',
|
||||
token: process.env.SLACK_TOKEN ?? ''
|
||||
},
|
||||
test: process.env.NOTIFICATION_TEST ?? 'false'
|
||||
};
|
||||
|
||||
const page = {
|
||||
height: 1920,
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
|
||||
width: 1080
|
||||
capture: process.env.SCREENSHOT ?? 'true',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
navigationTimeout: Number(process.env.PAGE_TIMEOUT) ?? 30000,
|
||||
userAgent: 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'
|
||||
};
|
||||
|
||||
const rateLimitTimeout = Number(process.env.RATE_LIMIT_TIMEOUT) ?? 5000;
|
||||
|
||||
const stores = process.env.STORES ?? 'nvidia';
|
||||
|
||||
export const Config = {
|
||||
email,
|
||||
notifications,
|
||||
rateLimitTimeout,
|
||||
page,
|
||||
rateLimitTimeout: 5000,
|
||||
stores
|
||||
};
|
||||
|
||||
+22
-11
@@ -5,6 +5,13 @@ import open from 'open';
|
||||
import sendNotification from './notification';
|
||||
import {Logger} from './logger';
|
||||
|
||||
/**
|
||||
* Send test email.
|
||||
*/
|
||||
if (Config.notifications.test === 'true') {
|
||||
sendNotification('test');
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the bot.
|
||||
*/
|
||||
@@ -33,29 +40,38 @@ async function lookup(store: Store) {
|
||||
for (const link of store.links) {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
page.setDefaultNavigationTimeout(Config.page.navigationTimeout);
|
||||
await page.setUserAgent(Config.page.userAgent);
|
||||
await page.setViewport({
|
||||
height: Config.page.height,
|
||||
width: Config.page.width
|
||||
});
|
||||
|
||||
await page.goto(link.url, {waitUntil: 'networkidle0'});
|
||||
const graphicsCard = `${link.brand} ${link.model}`;
|
||||
|
||||
try {
|
||||
await page.goto(link.url, {waitUntil: 'networkidle0'});
|
||||
} catch {
|
||||
Logger.error(`✖ [${store.name}] ${graphicsCard} skipping; timed out`);
|
||||
await browser.close();
|
||||
return;
|
||||
}
|
||||
|
||||
const bodyHandle = await page.$('body');
|
||||
const textContent = await page.evaluate(body => body.textContent, bodyHandle);
|
||||
|
||||
Logger.debug(textContent);
|
||||
|
||||
const graphicsCard = `${link.brand} ${link.model}`;
|
||||
|
||||
if (isOutOfStock(textContent, link.oosLabels)) {
|
||||
Logger.info(`✖ [${store.name}] ${graphicsCard} is still out of stock`);
|
||||
} else {
|
||||
Logger.info(`🚀🚀🚀 [${store.name}] ${graphicsCard} IN STOCK 🚀🚀🚀`);
|
||||
Logger.info(link.url);
|
||||
|
||||
Logger.debug('ℹ saving screenshot');
|
||||
await page.screenshot({path: `success-${Date.now()}.png`});
|
||||
if (Config.page.capture === 'true') {
|
||||
Logger.debug('ℹ saving screenshot');
|
||||
await page.screenshot({path: `success-${Date.now()}.png`});
|
||||
}
|
||||
|
||||
const givenUrl = store.cartUrl ? store.cartUrl : link.url;
|
||||
await open(givenUrl);
|
||||
@@ -75,12 +91,7 @@ async function lookup(store: Store) {
|
||||
*/
|
||||
function isOutOfStock(domText: string, oosLabels: string[]) {
|
||||
const domTextLowerCase = domText.toLowerCase();
|
||||
let result = false;
|
||||
for (const oosLabel of oosLabels) {
|
||||
result = domTextLowerCase.includes(oosLabel.toLowerCase());
|
||||
}
|
||||
|
||||
return result;
|
||||
return oosLabels.some(label => domTextLowerCase.includes(label));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-1
@@ -1,11 +1,13 @@
|
||||
import winston, {format} from 'winston';
|
||||
|
||||
const prettyJson = format.printf(info => {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
|
||||
if (typeof info.message === 'object') {
|
||||
info.message = JSON.stringify(info.message, null, 4);
|
||||
}
|
||||
|
||||
return `${info.level} :: ${info.message}`;
|
||||
return `[${timestamp}] ${info.level} :: ${info.message}`;
|
||||
});
|
||||
|
||||
export const Logger = winston.createLogger({
|
||||
|
||||
@@ -8,14 +8,14 @@ const subject = 'NVIDIA - BUY NOW';
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: 'gmail',
|
||||
auth: {
|
||||
user: Config.email.username,
|
||||
pass: Config.email.password
|
||||
user: Config.notifications.email.username,
|
||||
pass: Config.notifications.email.password
|
||||
}
|
||||
});
|
||||
|
||||
const mailOptions: Mail.Options = {
|
||||
from: Config.email.username,
|
||||
to: Config.email.username,
|
||||
from: Config.notifications.email.username,
|
||||
to: Config.notifications.email.username,
|
||||
subject
|
||||
};
|
||||
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
import {Config} from '../config';
|
||||
import sendEmail from './email';
|
||||
import sendSlaskMessage from './slack';
|
||||
import sendSMS from './sms';
|
||||
|
||||
export default function sendNotification(cartUrl: string) {
|
||||
if (Config.notifications.email) {
|
||||
if (Config.notifications.email.username && Config.notifications.email.password) {
|
||||
sendEmail(cartUrl);
|
||||
}
|
||||
|
||||
if (Config.notifications.slack.channel && Config.notifications.slack.token) {
|
||||
sendSlaskMessage(cartUrl);
|
||||
}
|
||||
|
||||
if (Config.notifications.phone.number) {
|
||||
const carrier = Config.notifications.phone.carrier?.toLowerCase();
|
||||
if (carrier && Config.notifications.phone.availableCarriers.includes(carrier)) {
|
||||
sendSMS(cartUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import {WebClient} from '@slack/web-api';
|
||||
import {Config} from '../config';
|
||||
import {Logger} from '../logger';
|
||||
|
||||
const channel = Config.notifications.slack.channel;
|
||||
const token = Config.notifications.slack.token;
|
||||
const web = new WebClient(token);
|
||||
|
||||
export default function sendSlackMessage(text: string) {
|
||||
(async () => {
|
||||
try {
|
||||
const result = await web.chat.postMessage({text, channel});
|
||||
if (!result.ok) {
|
||||
Logger.error(result.error);
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.info(`✔ slack message sent to '${channel}': ${text}`);
|
||||
} catch (error) {
|
||||
Logger.error(error);
|
||||
}
|
||||
})();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
import Mail from 'nodemailer/lib/mailer';
|
||||
import {Config} from '../config';
|
||||
import {Logger} from '../logger';
|
||||
|
||||
const subject = 'NVIDIA - BUY NOW';
|
||||
|
||||
enum carrierAddress {
|
||||
sprint = 'messaging.sprintpcs.com',
|
||||
verizon = 'vtext.com',
|
||||
tmobile = 'tmomail.net',
|
||||
att = 'txt.att.net',
|
||||
google = 'msg.fi.google.com'
|
||||
}
|
||||
|
||||
const transporter = nodemailer.createTransport({
|
||||
service: 'gmail',
|
||||
auth: {
|
||||
user: Config.notifications.email.username,
|
||||
pass: Config.notifications.email.password
|
||||
}
|
||||
});
|
||||
|
||||
const mailOptions: Mail.Options = {
|
||||
from: Config.notifications.email.username,
|
||||
to: generateAddress(),
|
||||
subject
|
||||
};
|
||||
|
||||
export default function sendSMS(text: string) {
|
||||
mailOptions.text = text;
|
||||
|
||||
transporter.sendMail(mailOptions, (error, info) => {
|
||||
if (error) {
|
||||
Logger.error(error);
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
||||
Logger.info(`✔ sms sent: ${info.response}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateAddress() {
|
||||
const carrier = Config.notifications.phone.carrier?.toLowerCase();
|
||||
if (carrier && Object.keys(carrierAddress).includes(carrier)) {
|
||||
// @ts-expect-error
|
||||
return [Config.notifications.phone.number, carrierAddress[carrier]].join('@');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
import {Store} from './store';
|
||||
|
||||
export const Amazon: Store = {
|
||||
cartUrl: '',
|
||||
links: [
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
},
|
||||
{
|
||||
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']
|
||||
}
|
||||
],
|
||||
name: 'amazon'
|
||||
};
|
||||
+36
-5
@@ -4,16 +4,47 @@ export const BestBuy: Store = {
|
||||
cartUrl: '',
|
||||
links: [
|
||||
{
|
||||
brand: 'nvidia',
|
||||
model: 'founder edition',
|
||||
url: 'https://www.bestbuy.com/site/nvidia-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-graphics-card-titanium-and-black/6429440.p?skuId=6429440',
|
||||
oosLabels: ['sold out']
|
||||
brand: 'asus',
|
||||
model: 'rog strix',
|
||||
url: 'https://www.bestbuy.com/site/asus-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-strix-graphics-card-black/6432445.p?skuId=6432445',
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
},
|
||||
{
|
||||
brand: 'evga',
|
||||
model: 'xc3 black',
|
||||
url: 'https://www.bestbuy.com/site/evga-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-graphics-card/6432399.p?skuId=6432399',
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
},
|
||||
{
|
||||
brand: 'evga',
|
||||
model: 'xc3 ultra',
|
||||
url: 'https://www.bestbuy.com/site/evga-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-graphics-card/6432400.p?skuId=6432400',
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
},
|
||||
{
|
||||
brand: 'gigabyte',
|
||||
model: 'black',
|
||||
url: 'https://www.bestbuy.com/site/gigabyte-geforce-rtx-3080-10g-gddr6x-pci-express-4-0-graphics-card-black/6430620.p?acampID=0&cmp=RMX&loc=Hatch&ref=198&skuId=6430620',
|
||||
oosLabels: ['sold out']
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
},
|
||||
{
|
||||
brand: 'gigabyte',
|
||||
model: 'eagle',
|
||||
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',
|
||||
url: 'https://www.bestbuy.com/site/msi-geforce-rtx-3080-ventus-3x-10g-oc-bv-gddr6x-pci-express-4-0-graphic-card-black-silver/6430175.p?skuId=6430175',
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
},
|
||||
{
|
||||
brand: 'nvidia',
|
||||
model: 'founder edition',
|
||||
url: 'https://www.bestbuy.com/site/nvidia-geforce-rtx-3080-10gb-gddr6x-pci-express-4-0-graphics-card-titanium-and-black/6429440.p?skuId=6429440',
|
||||
oosLabels: ['sold out', 'coming soon']
|
||||
}
|
||||
],
|
||||
name: 'bestbuy'
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import {Store} from './store';
|
||||
|
||||
export const Evga: Store = {
|
||||
cartUrl: '',
|
||||
links: [
|
||||
{
|
||||
brand: 'evga',
|
||||
model: 'ftw3, xc3 black, xc3 gaming, xc3 ultra gaming',
|
||||
url: 'https://www.evga.com/products/productlist.aspx?type=0&family=GeForce+30+Series+Family&chipset=RTX+3080',
|
||||
oosLabels: ['out of stock']
|
||||
}
|
||||
],
|
||||
name: 'evga'
|
||||
};
|
||||
+11
-13
@@ -1,30 +1,28 @@
|
||||
import {BestBuy} from './bestbuy';
|
||||
import {BAndH} from './bandh';
|
||||
import {Evga} from './evga';
|
||||
import {NewEgg} from './newegg';
|
||||
import {Nvidia} from './nvidia';
|
||||
import {Amazon} from './amazon';
|
||||
import {MicroCenter} from './microcenter';
|
||||
import {Config} from '../config';
|
||||
|
||||
const list = new Map([
|
||||
const masterList = new Map([
|
||||
['amazon', Amazon],
|
||||
['bestbuy', BestBuy],
|
||||
['bandh', BAndH],
|
||||
['evga', Evga],
|
||||
['microcenter', MicroCenter],
|
||||
['newegg', NewEgg],
|
||||
['nvidia', Nvidia]
|
||||
]);
|
||||
|
||||
if (!Config.stores.toLowerCase().includes('bestbuy')) {
|
||||
list.delete('bestbuy');
|
||||
}
|
||||
const list = new Map();
|
||||
|
||||
if (!Config.stores.toLowerCase().includes('bandh')) {
|
||||
list.delete('bandh');
|
||||
}
|
||||
const storeArray = Config.stores.split(',');
|
||||
|
||||
if (!Config.stores.toLowerCase().includes('newegg')) {
|
||||
list.delete('newegg');
|
||||
}
|
||||
|
||||
if (!Config.stores.toLowerCase().includes('nvidia')) {
|
||||
list.delete('nvidia');
|
||||
for (const name of storeArray) {
|
||||
list.set(name, masterList.get(name));
|
||||
}
|
||||
|
||||
export const Stores = Array.from(list.values());
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import {Store} from './store';
|
||||
|
||||
export const MicroCenter: Store = {
|
||||
cartUrl: '',
|
||||
links: [
|
||||
{
|
||||
brand: 'evga',
|
||||
model: 'xc3 ultra gaming',
|
||||
url: 'https://www.microcenter.com/product/628344/evga-geforce-rtx-3080-xc3-ultra-gaming-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
},
|
||||
{
|
||||
brand: 'msi',
|
||||
model: 'ventus 3x overclocked',
|
||||
url: 'https://www.microcenter.com/product/628331/msi-geforce-rtx-3080-ventus-3x-overclocked-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
},
|
||||
{
|
||||
brand: 'asus',
|
||||
model: 'tuf gaming',
|
||||
url: 'https://www.microcenter.com/product/628303/asus-geforce-rtx-3080-tuf-gaming-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
},
|
||||
{
|
||||
brand: 'msi',
|
||||
model: 'gaming x trio',
|
||||
url: 'https://www.microcenter.com/product/628330/msi-geforce-rtx-3080-gaming-x-trio-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
},
|
||||
{
|
||||
brand: 'evga',
|
||||
model: 'xc3 black',
|
||||
url: 'https://www.microcenter.com/product/628340/evga-geforce-rtx-3080-xc3-black-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
},
|
||||
{
|
||||
brand: 'zotac',
|
||||
model: 'trinity overclocked',
|
||||
url: 'https://www.microcenter.com/product/628607/zotac-geforce-rtx-3080-trinity-overclocked-triple-fan-10gb-gddr6x-pcie-40-graphics-card',
|
||||
oosLabels: ['sold out']
|
||||
}
|
||||
],
|
||||
name: 'microcenter'
|
||||
};
|
||||
+3
-9
@@ -1,19 +1,13 @@
|
||||
import {Store} from './store';
|
||||
|
||||
export const Nvidia: Store = {
|
||||
cartUrl: 'https://store.nvidia.com/store/nvidia/en_US/buy/productID.5438481700/clearCart.yes/nextPage.QuickBuyCartPage',
|
||||
cartUrl: '',
|
||||
links: [
|
||||
{
|
||||
brand: 'nvidia',
|
||||
model: 'founders edition',
|
||||
url: 'https://www.nvidia.com/en-us/geforce/buy/',
|
||||
oosLabels: ['out of stock']
|
||||
},
|
||||
{
|
||||
brand: 'nvidia',
|
||||
model: 'founders edition',
|
||||
url: 'https://www.nvidia.com/en-us/shop/geforce/?page=1&limit=9&locale=en-us&search=3080',
|
||||
oosLabels: ['out of stock']
|
||||
url: 'https://api.digitalriver.com/v1/shoppers/me/products/5438481700/inventory-status?apiKey=9485fa7b159e42edb08a83bde0d83dia',
|
||||
oosLabels: ['product_inventory_out_of_stock']
|
||||
}
|
||||
],
|
||||
name: 'nvidia'
|
||||
|
||||
Reference in New Issue
Block a user