mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-18 05:53:57 +00:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
64048e35d7 | ||
|
|
cf7f7ac790 | ||
|
|
f7aa5039f9 | ||
|
|
e082fb03f0 | ||
|
|
0303b8c605 | ||
|
|
2fea17c415 | ||
|
|
c5beccb54b | ||
|
|
b566ccaece | ||
|
|
15b2b827eb | ||
|
|
02518ee4ba | ||
|
|
69819b5631 | ||
|
|
b389b87792 |
43
Dockerfile
Normal file
43
Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Use an official Node.js runtime as a base image
|
||||||
|
FROM node:18
|
||||||
|
|
||||||
|
# Set the working directory in the container
|
||||||
|
WORKDIR /usr/src/microsoft-rewards-script
|
||||||
|
|
||||||
|
# Install jq
|
||||||
|
RUN apt-get update && apt-get install -y jq
|
||||||
|
|
||||||
|
|
||||||
|
# Copy all files to the working directory
|
||||||
|
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
|
||||||
|
RUN apt-get install -y \
|
||||||
|
xvfb \
|
||||||
|
libgbm-dev \
|
||||||
|
libnss3 \
|
||||||
|
libasound2 \
|
||||||
|
libxss1 \
|
||||||
|
libatk-bridge2.0-0 \
|
||||||
|
libgtk-3-0 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Install application dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Build the script
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Install playwright chromium
|
||||||
|
RUN npx playwright install chromium
|
||||||
|
|
||||||
|
# Define the command to run your application
|
||||||
|
CMD ["npm", "start"]
|
||||||
29
README.md
29
README.md
@@ -12,9 +12,36 @@ Under development, however mainly for personal use!
|
|||||||
6. Run `npm run start` to start the built script
|
6. Run `npm run start` to start the built script
|
||||||
|
|
||||||
## Notes ##
|
## Notes ##
|
||||||
- If you end the script without closing the browser window first (only with headless as false), you'll be left with hanging chrome instances using resources. Use taskmanager to kill these or use the included `npm run chrome-kill-win` script. (Windows)
|
- If you end the script without closing the browser window first (only with headless as false), you'll be left with hanging chrome instances using resources. Use taskmanager to kill these or use the included `npm run kill-chrome-win` script. (Windows)
|
||||||
- If you automate this script, set it to run at least 2 times a day to make sure it picked up all tasks, set `"runOnZeroPoints": false` so it doesn't run when no points are found.
|
- If you automate this script, set it to run at least 2 times a day to make sure it picked up all tasks, set `"runOnZeroPoints": false` so it doesn't run when no points are found.
|
||||||
|
|
||||||
|
## Docker (Experimental) ##
|
||||||
|
1. Download the source code
|
||||||
|
2. Make changes to your `accounts.json` and/or `config.json`
|
||||||
|
3. Run `docker build -t microsoft-rewards-script-docker .`
|
||||||
|
- Docker container has to be recreated for any changes regarding the `config.json` and/or `accounts.json`!
|
||||||
|
|
||||||
|
## Config ##
|
||||||
|
| Setting | Description | Default |
|
||||||
|
| :------------- |:-------------| :-----|
|
||||||
|
| baseURL | MS Rewards page | `https://rewards.bing.com` |
|
||||||
|
| sessionPath | Path to where you want sessions/fingerprints to be stored | `sessions` (In ./browser/sessions) |
|
||||||
|
| headless | If the browser window should be visible be ran in the background | `false` (Browser is visible) |
|
||||||
|
| runOnZeroPoints | Run the rest of the script if 0 points can be earned | `false` (Will not run on 0 points) |
|
||||||
|
| clusters | Amount of instances ran on launch, 1 per account | `1` (Will run 1 account at the time) |
|
||||||
|
| saveFingerprint | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) |
|
||||||
|
| workers.doDailySet | Complete daily set items | `true` |
|
||||||
|
| workers.doMorePromotions | Complete promotional items | `true` |
|
||||||
|
| workers.doPunchCards | Complete punchcards | `true` |
|
||||||
|
| workers.doDesktopSearch | Complete daily desktop searches | `true` |
|
||||||
|
| workers.doMobileSearch | Complete daily mobile searches | `true` |
|
||||||
|
| searchSettings.useGeoLocaleQueries | Generate search queries based on your geo-location | `false` (Uses EN-US generated queries) |
|
||||||
|
| scrollRandomResults | Scroll randomly in search results | `true` |
|
||||||
|
| searchSettings.clickRandomResults | Visit random website from search result| `true` |
|
||||||
|
| searchSettings.searchDelay | Minimum and maximum time in miliseconds between search queries | `min: 10000` (10 seconds) `max: 20000` (20 seconds) |
|
||||||
|
| searchSettings.retryMobileSearch | Keep retrying mobile searches until completed (indefinite)| `false` |
|
||||||
|
| webhook.enabled | Enable or disable your set webhook | `false` |
|
||||||
|
| webhook.url | Your Discord webhook URL | `null` |
|
||||||
|
|
||||||
## Features ##
|
## Features ##
|
||||||
- [x] Multi-Account Support
|
- [x] Multi-Account Support
|
||||||
|
|||||||
17
package.json
17
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "microsoft-rewards-script",
|
"name": "microsoft-rewards-script",
|
||||||
"version": "1.4.0",
|
"version": "1.4.5",
|
||||||
"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": {
|
||||||
@@ -11,7 +11,8 @@
|
|||||||
"start": "node ./dist/index.js",
|
"start": "node ./dist/index.js",
|
||||||
"ts-start": "ts-node ./src/index.ts",
|
"ts-start": "ts-node ./src/index.ts",
|
||||||
"dev": "ts-node ./src/index.ts -dev",
|
"dev": "ts-node ./src/index.ts -dev",
|
||||||
"kill-chrome-win": "powershell -Command \"Get-Process | Where-Object { $_.MainModule.FileVersionInfo.FileDescription -eq 'Google Chrome for Testing' } | ForEach-Object { Stop-Process -Id $_.Id -Force }\""
|
"kill-chrome-win": "powershell -Command \"Get-Process | Where-Object { $_.MainModule.FileVersionInfo.FileDescription -eq 'Google Chrome for Testing' } | ForEach-Object { Stop-Process -Id $_.Id -Force }\"",
|
||||||
|
"create-docker": "docker build -t microsoft-rewards-script-docker ."
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"Bing Rewards",
|
"Bing Rewards",
|
||||||
@@ -25,17 +26,17 @@
|
|||||||
"author": "Netsky",
|
"author": "Netsky",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.0",
|
"@typescript-eslint/eslint-plugin": "^6.20.0",
|
||||||
"eslint": "^8.54.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-plugin-modules-newline": "^0.0.6",
|
"eslint-plugin-modules-newline": "^0.0.6",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.7",
|
||||||
"cheerio": "^1.0.0-rc.12",
|
"cheerio": "^1.0.0-rc.12",
|
||||||
"fingerprint-generator": "^2.1.46",
|
"fingerprint-generator": "^2.1.49",
|
||||||
"fingerprint-injector": "^2.1.46",
|
"fingerprint-injector": "^2.1.49",
|
||||||
"playwright": "^1.40.1",
|
"playwright": "^1.42.0",
|
||||||
"ts-node": "^10.9.2"
|
"ts-node": "^10.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,13 +95,13 @@ export default class BrowserFunc {
|
|||||||
const scripts = Array.from(document.querySelectorAll('script'))
|
const scripts = Array.from(document.querySelectorAll('script'))
|
||||||
const targetScript = scripts.find(script => script.innerText.includes('var dashboard'))
|
const targetScript = scripts.find(script => script.innerText.includes('var dashboard'))
|
||||||
|
|
||||||
if (targetScript) {
|
return targetScript?.innerText ? targetScript.innerText : null
|
||||||
return targetScript.innerText
|
|
||||||
} else {
|
|
||||||
throw this.bot.log('GET-DASHBOARD-DATA', 'Script containing dashboard data not found', 'error')
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!scriptContent) {
|
||||||
|
throw this.bot.log('GET-DASHBOARD-DATA', 'Dashboard data not found within script', 'error')
|
||||||
|
}
|
||||||
|
|
||||||
// Extract the dashboard object from the script content
|
// Extract the dashboard object from the script content
|
||||||
const dashboardData = await this.bot.homePage.evaluate(scriptContent => {
|
const dashboardData = await this.bot.homePage.evaluate(scriptContent => {
|
||||||
// Extract the dashboard object using regex
|
// Extract the dashboard object using regex
|
||||||
@@ -110,11 +110,13 @@ export default class BrowserFunc {
|
|||||||
|
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
return JSON.parse(match[1])
|
return JSON.parse(match[1])
|
||||||
} else {
|
|
||||||
throw this.bot.log('GET-DASHBOARD-DATA', 'Dashboard data not found within script', 'error')
|
|
||||||
}
|
}
|
||||||
}, scriptContent)
|
}, scriptContent)
|
||||||
|
|
||||||
|
if (!dashboardData) {
|
||||||
|
throw this.bot.log('GET-DASHBOARD-DATA', 'Unable to parse dashboard script', 'error')
|
||||||
|
}
|
||||||
|
|
||||||
return dashboardData
|
return dashboardData
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +142,9 @@ export default class BrowserFunc {
|
|||||||
let totalEarnablePoints = 0
|
let totalEarnablePoints = 0
|
||||||
|
|
||||||
// Desktop Search Points
|
// Desktop Search Points
|
||||||
data.userStatus.counters.pcSearch.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
if (data.userStatus.counters.pcSearch?.length) {
|
||||||
|
data.userStatus.counters.pcSearch.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
||||||
|
}
|
||||||
|
|
||||||
// Mobile Search Points
|
// Mobile Search Points
|
||||||
if (data.userStatus.counters.mobileSearch?.length) {
|
if (data.userStatus.counters.mobileSearch?.length) {
|
||||||
@@ -151,12 +155,14 @@ export default class BrowserFunc {
|
|||||||
data.dailySetPromotions[this.bot.utils.getFormattedDate()]?.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
data.dailySetPromotions[this.bot.utils.getFormattedDate()]?.forEach(x => totalEarnablePoints += (x.pointProgressMax - x.pointProgress))
|
||||||
|
|
||||||
// More Promotions
|
// More Promotions
|
||||||
data.morePromotions.forEach(x => {
|
if (data.morePromotions?.length) {
|
||||||
// Only count points from supported activities
|
data.morePromotions.forEach(x => {
|
||||||
if (['quiz', 'urlreward'].includes(x.activityType)) {
|
// Only count points from supported activities
|
||||||
totalEarnablePoints += (x.pointProgressMax - x.pointProgress)
|
if (['quiz', 'urlreward'].includes(x.activityType)) {
|
||||||
}
|
totalEarnablePoints += (x.pointProgressMax - x.pointProgress)
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return totalEarnablePoints
|
return totalEarnablePoints
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export default class BrowserUtil {
|
|||||||
|
|
||||||
async tryDismissAllMessages(page: Page): Promise<boolean> {
|
async tryDismissAllMessages(page: Page): Promise<boolean> {
|
||||||
const buttons = [
|
const buttons = [
|
||||||
|
{ selector: '#acceptButton', label: 'AcceptButton' },
|
||||||
{ selector: '#iLandingViewAction', label: 'iLandingViewAction' },
|
{ selector: '#iLandingViewAction', label: 'iLandingViewAction' },
|
||||||
{ selector: '#iShowSkip', label: 'iShowSkip' },
|
{ selector: '#iShowSkip', label: 'iShowSkip' },
|
||||||
{ selector: '#iNext', label: 'iNext' },
|
{ selector: '#iNext', label: 'iNext' },
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"baseURL": "https://rewards.bing.com",
|
"baseURL": "https://rewards.bing.com",
|
||||||
"sessionPath": "sessions",
|
"sessionPath": "sessions",
|
||||||
"headless": false,
|
"headless": false,
|
||||||
"runOnZeroPoints": true,
|
"runOnZeroPoints": false,
|
||||||
"clusters": 1,
|
"clusters": 1,
|
||||||
"saveFingerprint": false,
|
"saveFingerprint": false,
|
||||||
"workers": {
|
"workers": {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { Page } from 'playwright'
|
|||||||
import readline from 'readline'
|
import readline from 'readline'
|
||||||
|
|
||||||
import { MicrosoftRewardsBot } from '../index'
|
import { MicrosoftRewardsBot } from '../index'
|
||||||
|
import { saveSessionData } from '../util/Load'
|
||||||
|
|
||||||
const rl = readline.createInterface({
|
const rl = readline.createInterface({
|
||||||
input: process.stdin,
|
input: process.stdin,
|
||||||
@@ -26,14 +27,12 @@ export class Login {
|
|||||||
|
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
// Check if account is locked
|
// Check if account is locked
|
||||||
const isLocked = await page.waitForSelector('.serviceAbusePageContainer', { state: 'visible', timeout: 10_000 }).then(() => true).catch(() => false)
|
const isLocked = await page.waitForSelector('.serviceAbusePageContainer', { state: 'visible', timeout: 1000 }).then(() => true).catch(() => false)
|
||||||
if (isLocked) {
|
if (isLocked) {
|
||||||
this.bot.log('LOGIN', 'This account has been locked!', 'error')
|
this.bot.log('LOGIN', 'This account has been locked!', 'error')
|
||||||
throw new Error('Account has been locked!')
|
throw new Error('Account has been locked!')
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.waitForSelector('#loginHeader', { state: 'visible', timeout: 10_000 })
|
|
||||||
|
|
||||||
await this.execLogin(page, email, password)
|
await this.execLogin(page, email, password)
|
||||||
this.bot.log('LOGIN', 'Logged into Microsoft successfully')
|
this.bot.log('LOGIN', 'Logged into Microsoft successfully')
|
||||||
} else {
|
} else {
|
||||||
@@ -43,6 +42,9 @@ export class Login {
|
|||||||
// Check if logged in to bing
|
// Check if logged in to bing
|
||||||
await this.checkBingLogin(page)
|
await this.checkBingLogin(page)
|
||||||
|
|
||||||
|
// Save session
|
||||||
|
await saveSessionData(this.bot.config.sessionPath, page.context(), email, this.bot.isMobile)
|
||||||
|
|
||||||
// We're done logging in
|
// We're done logging in
|
||||||
this.bot.log('LOGIN', 'Logged in successfully')
|
this.bot.log('LOGIN', 'Logged in successfully')
|
||||||
|
|
||||||
@@ -53,35 +55,41 @@ export class Login {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async execLogin(page: Page, email: string, password: string) {
|
private async execLogin(page: Page, email: string, password: string) {
|
||||||
await page.type('#i0116', email)
|
|
||||||
await page.click('#idSIButton9')
|
|
||||||
|
|
||||||
this.bot.log('LOGIN', 'Email entered successfully')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await page.waitForSelector('#i0118', { state: 'visible', timeout: 2000 })
|
// Enter email
|
||||||
await this.bot.utils.wait(2000)
|
await page.fill('#i0116', email)
|
||||||
|
|
||||||
await page.type('#i0118', password)
|
|
||||||
await page.click('#idSIButton9')
|
await page.click('#idSIButton9')
|
||||||
|
|
||||||
// When erroring at this stage it means a 2FA code is required
|
this.bot.log('LOGIN', 'Email entered successfully')
|
||||||
} catch (error) {
|
|
||||||
this.bot.log('LOGIN', '2FA code required')
|
|
||||||
|
|
||||||
// Wait for user input
|
try {
|
||||||
const code = await new Promise<string>((resolve) => {
|
// Enter password
|
||||||
rl.question('Enter 2FA code:\n', (input) => {
|
await page.waitForSelector('#i0118', { state: 'visible', timeout: 2000 })
|
||||||
rl.close()
|
await this.bot.utils.wait(2000)
|
||||||
resolve(input)
|
|
||||||
|
await page.fill('#i0118', password)
|
||||||
|
await page.click('#idSIButton9')
|
||||||
|
|
||||||
|
// When erroring at this stage it means a 2FA code is required
|
||||||
|
} catch (error) {
|
||||||
|
this.bot.log('LOGIN', '2FA code required')
|
||||||
|
|
||||||
|
// Wait for user input
|
||||||
|
const code = await new Promise<string>((resolve) => {
|
||||||
|
rl.question('Enter 2FA code:\n', (input) => {
|
||||||
|
rl.close()
|
||||||
|
resolve(input)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
await page.type('input[name="otc"]', code)
|
await page.fill('input[name="otc"]', code)
|
||||||
await page.keyboard.press('Enter')
|
await page.keyboard.press('Enter')
|
||||||
|
}
|
||||||
|
|
||||||
} finally {
|
|
||||||
this.bot.log('LOGIN', 'Password entered successfully')
|
this.bot.log('LOGIN', 'Password entered successfully')
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
this.bot.log('LOGIN', 'An error occurred:' + error, 'error')
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentURL = new URL(page.url())
|
const currentURL = new URL(page.url())
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export class Workers {
|
|||||||
// Punch Card
|
// Punch Card
|
||||||
async doPunchCard(page: Page, data: DashboardData) {
|
async doPunchCard(page: Page, data: DashboardData) {
|
||||||
|
|
||||||
const punchCardsUncompleted = data.punchCards?.filter(x => !x.parentPromotion.complete) ?? [] // Only return uncompleted punch cards
|
const punchCardsUncompleted = data.punchCards?.filter(x => !x.parentPromotion?.complete) ?? [] // Only return uncompleted punch cards
|
||||||
|
|
||||||
if (!punchCardsUncompleted.length) {
|
if (!punchCardsUncompleted.length) {
|
||||||
this.bot.log('PUNCH-CARD', 'All "Punch Cards" have already been completed')
|
this.bot.log('PUNCH-CARD', 'All "Punch Cards" have already been completed')
|
||||||
@@ -95,7 +95,7 @@ export class Workers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Solve Activities
|
// Solve Activities
|
||||||
this.bot.log('MORE-PROMOTIONS', 'Started solving "More Promotions" item')
|
this.bot.log('MORE-PROMOTIONS', 'Started solving "More Promotions" items')
|
||||||
|
|
||||||
page = await this.bot.browser.utils.getLatestTab(page)
|
page = await this.bot.browser.utils.getLatestTab(page)
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Page } from 'playwright'
|
import { Page } from 'playwright'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import { platform } from 'os'
|
||||||
|
|
||||||
import { Workers } from '../Workers'
|
import { Workers } from '../Workers'
|
||||||
|
|
||||||
@@ -128,17 +129,25 @@ export class Search extends Workers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async bingSearch(searchPage: Page, query: string) {
|
private async bingSearch(searchPage: Page, query: string) {
|
||||||
|
const platformControlKey = platform() === 'darwin' ? 'Meta' : 'Control'
|
||||||
|
|
||||||
// Try a max of 5 times
|
// Try a max of 5 times
|
||||||
for (let i = 0; i < 5; i++) {
|
for (let i = 0; i < 5; i++) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
// Go to top of the page
|
||||||
|
await searchPage.evaluate(() => {
|
||||||
|
window.scrollTo(0, 0)
|
||||||
|
})
|
||||||
|
|
||||||
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
|
||||||
await this.bot.utils.wait(500)
|
await this.bot.utils.wait(500)
|
||||||
await searchPage.keyboard.down('Control')
|
await searchPage.keyboard.down(platformControlKey)
|
||||||
await searchPage.keyboard.press('A')
|
await searchPage.keyboard.press('A')
|
||||||
await searchPage.keyboard.press('Backspace')
|
await searchPage.keyboard.press('Backspace')
|
||||||
await searchPage.keyboard.up('Control')
|
await searchPage.keyboard.up(platformControlKey)
|
||||||
await searchPage.keyboard.type(query)
|
await searchPage.keyboard.type(query)
|
||||||
await searchPage.keyboard.press('Enter')
|
await searchPage.keyboard.press('Enter')
|
||||||
|
|
||||||
@@ -152,6 +161,7 @@ export class Search extends Workers {
|
|||||||
await this.clickRandomLink(searchPage)
|
await this.clickRandomLink(searchPage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delay between searches
|
||||||
await this.bot.utils.wait(Math.floor(this.bot.utils.randomNumber(this.bot.config.searchSettings.searchDelay.min, this.bot.config.searchSettings.searchDelay.max)))
|
await this.bot.utils.wait(Math.floor(this.bot.utils.randomNumber(this.bot.config.searchSettings.searchDelay.min, this.bot.config.searchSettings.searchDelay.max)))
|
||||||
|
|
||||||
return await this.bot.browser.func.getSearchPoints()
|
return await this.bot.browser.func.getSearchPoints()
|
||||||
@@ -248,10 +258,11 @@ export class Search extends Workers {
|
|||||||
|
|
||||||
private async randomScroll(page: Page) {
|
private async randomScroll(page: Page) {
|
||||||
try {
|
try {
|
||||||
// Press the arrow down key to scroll
|
const scrollAmount = this.bot.utils.randomNumber(5, 5000)
|
||||||
for (let i = 0; i < this.bot.utils.randomNumber(5, 400); i++) {
|
|
||||||
await page.keyboard.press('ArrowDown')
|
await page.evaluate((scrollAmount) => {
|
||||||
}
|
window.scrollBy(0, scrollAmount)
|
||||||
|
}, scrollAmount)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.bot.log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
this.bot.log('SEARCH-RANDOM-SCROLL', 'An error occurred:' + error, 'error')
|
||||||
|
|||||||
@@ -125,6 +125,8 @@ export class MicrosoftRewardsBot {
|
|||||||
|
|
||||||
// Desktop
|
// Desktop
|
||||||
async Desktop(account: Account) {
|
async Desktop(account: Account) {
|
||||||
|
this.isMobile = false
|
||||||
|
|
||||||
const browser = await this.browserFactory.createBrowser(account.proxy, account.email)
|
const browser = await this.browserFactory.createBrowser(account.proxy, account.email)
|
||||||
this.homePage = await browser.newPage()
|
this.homePage = await browser.newPage()
|
||||||
|
|
||||||
@@ -176,8 +178,7 @@ export class MicrosoftRewardsBot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save cookies
|
// Save cookies
|
||||||
const cookies = await browser.cookies()
|
await saveSessionData(this.config.sessionPath, browser, account.email, this.isMobile)
|
||||||
await saveSessionData(this.config.sessionPath, account.email, this.isMobile, cookies)
|
|
||||||
|
|
||||||
// Close desktop browser
|
// Close desktop browser
|
||||||
return await this.closeBrowser(browser, account.email)
|
return await this.closeBrowser(browser, account.email)
|
||||||
@@ -245,8 +246,7 @@ export class MicrosoftRewardsBot {
|
|||||||
|
|
||||||
private async closeBrowser(browser: BrowserContext, email: string) {
|
private async closeBrowser(browser: BrowserContext, email: string) {
|
||||||
// Save cookies
|
// Save cookies
|
||||||
const cookies = await browser.cookies()
|
await saveSessionData(this.config.sessionPath, browser, email, this.isMobile)
|
||||||
await saveSessionData(this.config.sessionPath, email, this.isMobile, cookies)
|
|
||||||
|
|
||||||
// Close browser
|
// Close browser
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Cookie } from 'playwright'
|
import { BrowserContext, Cookie } from 'playwright'
|
||||||
import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
|
import { BrowserFingerprintWithHeaders } from 'fingerprint-generator'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
@@ -67,8 +67,10 @@ export async function loadSessionData(sessionPath: string, email: string, isMobi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveSessionData(sessionPath: string, email: string, isMobile: boolean, cookies: Cookie[]): Promise<string> {
|
export async function saveSessionData(sessionPath: string, browser: BrowserContext, email: string, isMobile: boolean): Promise<string> {
|
||||||
try {
|
try {
|
||||||
|
const cookies = await browser.cookies()
|
||||||
|
|
||||||
// Fetch path
|
// Fetch path
|
||||||
const sessionDir = path.join(__dirname, '../browser/', sessionPath, email)
|
const sessionDir = path.join(__dirname, '../browser/', sessionPath, email)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user