mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-18 14:03:58 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6ab80fe54 | ||
|
|
9b1eed526f | ||
|
|
9a144b2e60 | ||
|
|
28b1881642 | ||
|
|
ef6ad569ff | ||
|
|
da9ba91c5c | ||
|
|
deb2d58b1b | ||
|
|
66a82c2584 | ||
|
|
8a022d5983 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -5,4 +5,5 @@ package-lock.json
|
|||||||
accounts.json
|
accounts.json
|
||||||
notes
|
notes
|
||||||
accounts.dev.json
|
accounts.dev.json
|
||||||
accounts.main.json
|
accounts.main.json
|
||||||
|
.DS_Store
|
||||||
|
|||||||
23
Dockerfile
23
Dockerfile
@@ -4,21 +4,12 @@ FROM node:18
|
|||||||
# Set the working directory in the container
|
# Set the working directory in the container
|
||||||
WORKDIR /usr/src/microsoft-rewards-script
|
WORKDIR /usr/src/microsoft-rewards-script
|
||||||
|
|
||||||
# Install jq
|
# Install jq, cron, and gettext-base
|
||||||
RUN apt-get update && apt-get install -y jq
|
RUN apt-get update && apt-get install -y jq cron gettext-base
|
||||||
|
|
||||||
|
|
||||||
# Copy all files to the working directory
|
# Copy all files to the working directory
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Check if "headless" is set to "true" in the config.json file
|
|
||||||
# DELETE BELOW IF YOU WANT TO RUN THE DOCKER SCRIPT HEADFULL!
|
|
||||||
RUN HEADLESS=$(cat src/config.json | jq -r .headless) \
|
|
||||||
&& if [ "$HEADLESS" != "true" ]; then \
|
|
||||||
echo "Error: 'headless' in src/config.json is not true."; \
|
|
||||||
exit 1; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install dependencies including Playwright
|
# Install dependencies including Playwright
|
||||||
RUN apt-get install -y \
|
RUN apt-get install -y \
|
||||||
xvfb \
|
xvfb \
|
||||||
@@ -39,5 +30,11 @@ RUN npm run build
|
|||||||
# Install playwright chromium
|
# Install playwright chromium
|
||||||
RUN npx playwright install chromium
|
RUN npx playwright install chromium
|
||||||
|
|
||||||
# Define the command to run your application
|
# Copy cron file to cron directory
|
||||||
CMD ["npm", "start"]
|
COPY src/crontab.template /etc/cron.d/microsoft-rewards-cron.template
|
||||||
|
|
||||||
|
# Create the log file to be able to run tail
|
||||||
|
RUN touch /var/log/cron.log
|
||||||
|
|
||||||
|
# Define the command to run your application with cron optionally
|
||||||
|
CMD sh -c 'echo "$TZ" > /etc/timezone && dpkg-reconfigure -f noninteractive tzdata && if [ "$RUN_ON_START" = "true" ]; then npm start; fi && envsubst < /etc/cron.d/microsoft-rewards-cron.template > /etc/cron.d/microsoft-rewards-cron && crontab /etc/cron.d/microsoft-rewards-cron && cron && tail -f /var/log/cron.log'
|
||||||
83
README.md
83
README.md
@@ -17,31 +17,66 @@ Under development, however mainly for personal use!
|
|||||||
|
|
||||||
## Docker (Experimental) ##
|
## Docker (Experimental) ##
|
||||||
1. Download the source code
|
1. Download the source code
|
||||||
2. Make changes to your `accounts.json` and/or `config.json`
|
2. Make changes to your `accounts.json`
|
||||||
3. Run `docker build -t microsoft-rewards-script-docker .`
|
3. **Headless mode must be enabled when using Docker.** You can do this using the `HEADLESS=true` environmental variable in docker run or docker compose.yaml (see below). Environmental variables are always prioritized over the values in config.json.
|
||||||
- Docker container has to be recreated for any changes regarding the `config.json` and/or `accounts.json`!
|
4. The container will run scheduled. Customize your schedule using the `CRON_START_TIME` environmental variable. Use [crontab.guru](crontab.guru) if you're unsure how to create a cron schedule.
|
||||||
|
5. **Note:** the container will add between 5 and 50 minutes of randomized variability to your scheduled start times.
|
||||||
|
### Option 1: build and run with docker run
|
||||||
|
|
||||||
|
1. Build or re-build the container image with: `docker build -t microsoft-rewards-script-docker .`
|
||||||
|
|
||||||
|
2. Run the container with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run --name netsky -d \
|
||||||
|
-e TZ=America/New_York \
|
||||||
|
-e HEADLESS=true \
|
||||||
|
-e SEARCH_DELAY_MIN=10000 \
|
||||||
|
-e SEARCH_DELAY_MAX=20000 \
|
||||||
|
-e CLUSTERS=1 \
|
||||||
|
-e CRON_START_TIME="0 5,11 * * *" \
|
||||||
|
microsoft-rewards-script-docker
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Optionally, change any environmental variables other than `HEADLESS`, which must stay `=true`
|
||||||
|
|
||||||
|
4. You can view logs with `docker logs netsky`.
|
||||||
|
|
||||||
|
### Option 2: use docker compose
|
||||||
|
|
||||||
|
1. A basic docker compose.yaml has been provided.
|
||||||
|
|
||||||
|
2. Optionally, change any environmental variables other than `HEADLESS`, which must stay `=true`
|
||||||
|
|
||||||
|
3. Build or rebuild and start the container using `docker compose up -d --build`
|
||||||
|
|
||||||
|
4. You can view logs with `docker logs netsky`
|
||||||
|
|
||||||
|
|
||||||
## Config ##
|
## Config ##
|
||||||
| Setting | Description | Default |
|
| Setting | Description | Default | Docker Environmental Variable |
|
||||||
| :------------- |:-------------| :-----|
|
| :------------- |:-------------| :-----| :-----|
|
||||||
| baseURL | MS Rewards page | `https://rewards.bing.com` |
|
| baseURL | MS Rewards page | `https://rewards.bing.com` | BASE_URL |
|
||||||
| sessionPath | Path to where you want sessions/fingerprints to be stored | `sessions` (In ./browser/sessions) |
|
| sessionPath | Path to where you want sessions/fingerprints to be stored | `sessions` (In ./browser/sessions) | SESSION_PATH |
|
||||||
| headless | If the browser window should be visible be ran in the background | `false` (Browser is visible) |
|
| headless | If the browser window should be visible be ran in the background | `false` (Browser is visible) | HEADLESS *(must be set to `=true` for docker)* |
|
||||||
| runOnZeroPoints | Run the rest of the script if 0 points can be earned | `false` (Will not run on 0 points) |
|
| runOnZeroPoints | Run the rest of the script if 0 points can be earned | `false` (Will not run on 0 points) | RUN_ON_ZERO_POINTS |
|
||||||
| clusters | Amount of instances ran on launch, 1 per account | `1` (Will run 1 account at the time) |
|
| clusters | Amount of instances ran on launch, 1 per account | `1` (Will run 1 account at the time) | CLUSTERS |
|
||||||
| saveFingerprint | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) |
|
| saveFingerprint | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) | SAVE_FINGERPRINT |
|
||||||
| workers.doDailySet | Complete daily set items | `true` |
|
| workers.doDailySet | Complete daily set items | `true` | WORKERS_DO_DAILY_SET |
|
||||||
| workers.doMorePromotions | Complete promotional items | `true` |
|
| workers.doMorePromotions | Complete promotional items | `true` | WORKERS_DO_MORE_PROMOTIONS |
|
||||||
| workers.doPunchCards | Complete punchcards | `true` |
|
| workers.doPunchCards | Complete punchcards | `true` | WORKERS_DO_PUNCH_CARDS |
|
||||||
| workers.doDesktopSearch | Complete daily desktop searches | `true` |
|
| workers.doDesktopSearch | Complete daily desktop searches | `true` | WORKERS_DO_DESKTOP_SEARCH |
|
||||||
| workers.doMobileSearch | Complete daily mobile searches | `true` |
|
| workers.doMobileSearch | Complete daily mobile searches | `true` | WORKERS_DO_MOBILE_SEARCH |
|
||||||
| searchSettings.useGeoLocaleQueries | Generate search queries based on your geo-location | `false` (Uses EN-US generated queries) |
|
| globalTimeout | The length before the action gets timeout | `30000` (30 seconds) | GLOBAL_TIMEOUT |
|
||||||
| scrollRandomResults | Scroll randomly in search results | `true` |
|
| searchSettings.useGeoLocaleQueries | Generate search queries based on your geo-location | `false` (Uses EN-US generated queries) | SEARCH_SETTINGS_USE_GEO_LOCALE_QUERIES |
|
||||||
| searchSettings.clickRandomResults | Visit random website from search result| `true` |
|
| scrollRandomResults | Scroll randomly in search results | `true` | SEARCH_SETTINGS_SCROLL_RANDOM_RESULTS |
|
||||||
| searchSettings.searchDelay | Minimum and maximum time in miliseconds between search queries | `min: 10000` (10 seconds) `max: 20000` (20 seconds) |
|
| searchSettings.clickRandomResults | Visit random website from search result| `true` | SEARCH_SETTINGS_CLICK_RANDOM_RESULTS |
|
||||||
| searchSettings.retryMobileSearch | Keep retrying mobile searches until completed (indefinite)| `false` |
|
| searchSettings.searchDelay | Minimum and maximum time in miliseconds between search queries | `min: 10000` (10 seconds) `max: 20000` (20 seconds) | SEARCH_DELAY_MIN SEARCH_DELAY_MAX |
|
||||||
| webhook.enabled | Enable or disable your set webhook | `false` |
|
| searchSettings.retryMobileSearch | Keep retrying mobile searches until completed (indefinite)| `false` | SEARCH_SETTINGS_RETRY_MOBILE_SEARCH |
|
||||||
| webhook.url | Your Discord webhook URL | `null` |
|
| webhook.enabled | Enable or disable your set webhook | `false` | WEBHOOK_ENABLED |
|
||||||
|
| webhook.url | Your Discord webhook URL | `null` | WEBHOOK_URL="" |
|
||||||
|
| cronStartTime | Scheduled script run-time, *only available for docker implementation* | `0 5,11 * * *` (5:00 am, 11:00 am daily) | CRON_START_TIME="" |
|
||||||
|
| | Run the script immediately when the Docker container starts | `true` | RUN_ON_START |
|
||||||
|
|
||||||
## Features ##
|
## Features ##
|
||||||
- [x] Multi-Account Support
|
- [x] Multi-Account Support
|
||||||
@@ -69,6 +104,8 @@ Under development, however mainly for personal use!
|
|||||||
- [ ] Completing Gaming Tab
|
- [ ] Completing Gaming Tab
|
||||||
- [x] Clustering Support
|
- [x] Clustering Support
|
||||||
- [x] Proxy Support
|
- [x] Proxy Support
|
||||||
|
- [x] Docker Support (experimental)
|
||||||
|
- [x] Automatic scheduling (via Docker)
|
||||||
|
|
||||||
## Disclaimer ##
|
## Disclaimer ##
|
||||||
Your account may be at risk of getting banned or suspended using this script, you've been warned!
|
Your account may be at risk of getting banned or suspended using this script, you've been warned!
|
||||||
|
|||||||
34
compose.yaml
Normal file
34
compose.yaml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
services:
|
||||||
|
microsoft-rewards-script:
|
||||||
|
build: .
|
||||||
|
container_name: netsky
|
||||||
|
environment:
|
||||||
|
- TZ=America/Toronto #change to your local timezone
|
||||||
|
- NODE_ENV=production
|
||||||
|
- HEADLESS=true #do not change
|
||||||
|
### the following are optional, you only need to include them if you want to enter a custom value, removing them will use the default values
|
||||||
|
- BASE_URL=https://rewards.bing.com
|
||||||
|
- SESSION_PATH=sessions
|
||||||
|
- RUN_ON_ZERO_POINTS=false
|
||||||
|
- CLUSTERS=1
|
||||||
|
- SAVE_FINGERPRINT=false
|
||||||
|
- WORKERS_DO_DAILY_SET=true
|
||||||
|
- WORKERS_DO_MORE_PROMOTIONS=true
|
||||||
|
- WORKERS_DO_PUNCH_CARDS=true
|
||||||
|
- WORKERS_DO_DESKTOP_SEARCH=true
|
||||||
|
- WORKERS_DO_MOBILE_SEARCH=true
|
||||||
|
- SEARCH_SETTINGS_USE_GEO_LOCALE_QUERIES=false
|
||||||
|
- SEARCH_SETTINGS_SCROLL_RANDOM_RESULTS=true
|
||||||
|
- SEARCH_SETTINGS_CLICK_RANDOM_RESULTS=true
|
||||||
|
- SEARCH_SETTINGS_SEARCH_DELAY_MIN=10000 # Set the search delay longer, e.g. MIN=180000 and MAX=270000 if you live in a region where MS enforces a search cooldown
|
||||||
|
- SEARCH_SETTINGS_SEARCH_DELAY_MAX=20000
|
||||||
|
- SEARCH_SETTINGS_RETRY_MOBILE_SEARCH=true
|
||||||
|
- WEBHOOK_ENABLED=false
|
||||||
|
- WEBHOOK_URL=
|
||||||
|
### Customize your run schedule, default 5:00 am and 11:00 am, use crontab.guru if you're not sure
|
||||||
|
- CRON_START_TIME=0 5,11 * * *
|
||||||
|
### Run on start, set as false to only run the script per the cron schedule
|
||||||
|
- RUN_ON_START=true
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- .:/usr/src/microsoft-rewards-script
|
||||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "microsoft-rewards-script",
|
"name": "microsoft-rewards-script",
|
||||||
"version": "1.4.5",
|
"version": "1.4.7",
|
||||||
"description": "Automatically do tasks for Microsoft Rewards but in TS!",
|
"description": "Automatically do tasks for Microsoft Rewards but in TS!",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -26,17 +26,17 @@
|
|||||||
"author": "Netsky",
|
"author": "Netsky",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
"@typescript-eslint/eslint-plugin": "^7.11.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-modules-newline": "^0.0.6",
|
"eslint-plugin-modules-newline": "^0.0.6",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.4.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.7.2",
|
||||||
"cheerio": "^1.0.0-rc.12",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"fingerprint-generator": "^2.1.49",
|
"fingerprint-generator": "^2.1.51",
|
||||||
"fingerprint-injector": "^2.1.49",
|
"fingerprint-injector": "^2.1.51",
|
||||||
"playwright": "^1.42.0",
|
"playwright": "^1.44.1",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ class Browser {
|
|||||||
|
|
||||||
const context = await newInjectedContext(browser, { fingerprint: fingerpint })
|
const context = await newInjectedContext(browser, { fingerprint: fingerpint })
|
||||||
|
|
||||||
|
// Set timeout to preferred amount
|
||||||
|
context.setDefaultTimeout(this.bot.config?.globalTimeout ?? 30_000)
|
||||||
|
|
||||||
await context.addCookies(sessionData.cookies)
|
await context.addCookies(sessionData.cookies)
|
||||||
|
|
||||||
if (this.bot.config.saveFingerprint) {
|
if (this.bot.config.saveFingerprint) {
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ export default class BrowserFunc {
|
|||||||
if (data.morePromotions?.length) {
|
if (data.morePromotions?.length) {
|
||||||
data.morePromotions.forEach(x => {
|
data.morePromotions.forEach(x => {
|
||||||
// Only count points from supported activities
|
// Only count points from supported activities
|
||||||
if (['quiz', 'urlreward'].includes(x.activityType)) {
|
if (['quiz', 'urlreward'].includes(x.promotionType)) {
|
||||||
totalEarnablePoints += (x.pointProgressMax - x.pointProgress)
|
totalEarnablePoints += (x.pointProgressMax - x.pointProgress)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"doDesktopSearch": true,
|
"doDesktopSearch": true,
|
||||||
"doMobileSearch": true
|
"doMobileSearch": true
|
||||||
},
|
},
|
||||||
|
"globalTimeout": 30000,
|
||||||
"searchSettings": {
|
"searchSettings": {
|
||||||
"useGeoLocaleQueries": false,
|
"useGeoLocaleQueries": false,
|
||||||
"scrollRandomResults": true,
|
"scrollRandomResults": true,
|
||||||
@@ -25,5 +26,6 @@
|
|||||||
"webhook": {
|
"webhook": {
|
||||||
"enabled": false,
|
"enabled": false,
|
||||||
"url": ""
|
"url": ""
|
||||||
}
|
},
|
||||||
}
|
"cronStartTime": "0 5,11 * * *"
|
||||||
|
}
|
||||||
1
src/crontab.template
Normal file
1
src/crontab.template
Normal file
@@ -0,0 +1 @@
|
|||||||
|
${CRON_START_TIME} /bin/bash /usr/src/microsoft-rewards-script/src/run_daily.sh >> /var/log/cron.log 2>&1
|
||||||
@@ -140,6 +140,8 @@ export class Search extends Workers {
|
|||||||
window.scrollTo(0, 0)
|
window.scrollTo(0, 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
await this.bot.utils.wait(500)
|
||||||
|
|
||||||
const searchBar = '#sb_form_q'
|
const searchBar = '#sb_form_q'
|
||||||
await searchPage.waitForSelector(searchBar, { state: 'visible', timeout: 10_000 })
|
await searchPage.waitForSelector(searchBar, { state: 'visible', timeout: 10_000 })
|
||||||
await searchPage.click(searchBar) // Focus on the textarea
|
await searchPage.click(searchBar) // Focus on the textarea
|
||||||
|
|||||||
@@ -181,7 +181,8 @@ export class MicrosoftRewardsBot {
|
|||||||
await saveSessionData(this.config.sessionPath, browser, account.email, this.isMobile)
|
await saveSessionData(this.config.sessionPath, browser, account.email, this.isMobile)
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
return await this.closeBrowser(browser, account.email)
|
await this.closeBrowser(browser, account.email)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mobile
|
// Mobile
|
||||||
@@ -241,7 +242,8 @@ export class MicrosoftRewardsBot {
|
|||||||
log('MAIN-POINTS', `The script collected ${this.collectedPoints} points today`)
|
log('MAIN-POINTS', `The script collected ${this.collectedPoints} points today`)
|
||||||
|
|
||||||
// Close mobile browser
|
// Close mobile browser
|
||||||
return await this.closeBrowser(browser, account.email)
|
await this.closeBrowser(browser, account.email)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
private async closeBrowser(browser: BrowserContext, email: string) {
|
private async closeBrowser(browser: BrowserContext, email: string) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export interface Config {
|
|||||||
runOnZeroPoints: boolean;
|
runOnZeroPoints: boolean;
|
||||||
clusters: number;
|
clusters: number;
|
||||||
workers: Workers;
|
workers: Workers;
|
||||||
|
globalTimeout: number;
|
||||||
searchSettings: SearchSettings;
|
searchSettings: SearchSettings;
|
||||||
webhook: Webhook;
|
webhook: Webhook;
|
||||||
saveFingerprint: boolean;
|
saveFingerprint: boolean;
|
||||||
|
|||||||
29
src/run_daily.sh
Normal file
29
src/run_daily.sh
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Set up environment variables
|
||||||
|
export PATH=$PATH:/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
|
||||||
|
|
||||||
|
# Change directory to the application directory
|
||||||
|
cd /usr/src/microsoft-rewards-script
|
||||||
|
|
||||||
|
# Define the minimum and maximum wait times in seconds
|
||||||
|
MINWAIT=$((5*60)) # 5 minutes
|
||||||
|
MAXWAIT=$((50*60)) # 50 minutes
|
||||||
|
|
||||||
|
# Calculate a random sleep time within the specified range
|
||||||
|
SLEEPTIME=$((MINWAIT + RANDOM % (MAXWAIT - MINWAIT)))
|
||||||
|
|
||||||
|
# Convert the sleep time to minutes for logging
|
||||||
|
SLEEP_MINUTES=$((SLEEPTIME / 60))
|
||||||
|
|
||||||
|
# Log the sleep duration
|
||||||
|
echo "Sleeping for $SLEEP_MINUTES minutes ($SLEEPTIME seconds)..."
|
||||||
|
|
||||||
|
# Sleep for the calculated time
|
||||||
|
sleep $SLEEPTIME
|
||||||
|
|
||||||
|
# Log the start of the script
|
||||||
|
echo "Starting script..."
|
||||||
|
|
||||||
|
# Execute the Node.js script directly
|
||||||
|
npm run start
|
||||||
Reference in New Issue
Block a user