Formatting + General Improvements

- Added cookie header function
- Added failback to html parsing for dashboard data
- Removed some logs
This commit is contained in:
TheNetsky
2026-01-21 22:48:28 +01:00
parent 7e51bff52b
commit 175ba45543
23 changed files with 252 additions and 390 deletions

View File

@@ -3,6 +3,7 @@
--- ---
## Table of Contents ## Table of Contents
- [Quick Setup](#quick-setup) - [Quick Setup](#quick-setup)
- [Nix Setup](#nix-setup) - [Nix Setup](#nix-setup)
- [Configuration Options](#configuration-options) - [Configuration Options](#configuration-options)
@@ -11,20 +12,25 @@
- [Disclaimer](#disclaimer) - [Disclaimer](#disclaimer)
--- ---
## Quick Setup ## Quick Setup
**Requirements:** Node.js >= 24 and Git **Requirements:** Node.js >= 24 and Git
Works on Windows, Linux, macOS, and WSL. Works on Windows, Linux, macOS, and WSL.
### Get the script ### Get the script
```bash ```bash
git clone https://github.com/TheNetsky/Microsoft-Rewards-Script.git git clone https://github.com/TheNetsky/Microsoft-Rewards-Script.git
cd Microsoft-Rewards-Script cd Microsoft-Rewards-Script
``` ```
Or, download the latest release ZIP and extract it. Or, download the latest release ZIP and extract it.
### Create an account.json and config.json ### Create an account.json and config.json
Copy, rename, and edit your account and configuration files before deploying the script. Copy, rename, and edit your account and configuration files before deploying the script.
- Copy or rename `src/accounts.example.json` to `src/accounts.json` and add your credentials - Copy or rename `src/accounts.example.json` to `src/accounts.json` and add your credentials
- Copy or rename `src/config.example.json` to `src/config.json` and customize your preferences. - Copy or rename `src/config.example.json` to `src/config.json` and customize your preferences.
@@ -36,6 +42,7 @@ Copy, rename, and edit your account and configuration files before deploying the
> You must rebuild your script after making any changes to accounts.json and config.json. > You must rebuild your script after making any changes to accounts.json and config.json.
### Build and run the script (bare metal version) ### Build and run the script (bare metal version)
```bash ```bash
npm run pre-build npm run pre-build
npm run build npm run build
@@ -43,6 +50,7 @@ npm run start
``` ```
### Build and run the script (docker version) ### Build and run the script (docker version)
```bash ```bash
docker compose up -d docker compose up -d
``` ```
@@ -53,6 +61,7 @@ docker compose up -d
> [!TIP] > [!TIP]
> When headeless, monitor logs with `docker logs microsoft-rewards-script` (for example, to view passwordless codes), or enable a webhook service in the `src/config.json`. > When headeless, monitor logs with `docker logs microsoft-rewards-script` (for example, to view passwordless codes), or enable a webhook service in the `src/config.json`.
--- ---
## Nix Setup ## Nix Setup
@@ -69,8 +78,9 @@ Edit `src/config.json` to customize behavior. Below are all currently available
> Rebuild the script after all changes. > Rebuild the script after all changes.
### Core ### Core
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | -------------------------- | ------- | ---------------------------- | ------------------------------------- |
| `baseURL` | string | `"https://rewards.bing.com"` | Microsoft Rewards base URL | | `baseURL` | string | `"https://rewards.bing.com"` | Microsoft Rewards base URL |
| `sessionPath` | string | `"sessions"` | Directory to store browser sessions | | `sessionPath` | string | `"sessions"` | Directory to store browser sessions |
| `headless` | boolean | `false` | Run browser invisibly | | `headless` | boolean | `false` | Run browser invisibly |
@@ -84,8 +94,9 @@ Edit `src/config.json` to customize behavior. Below are all currently available
> Set `headless` to `true` when using docker > Set `headless` to `true` when using docker
### Workers ### Workers
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | ----------------------------- | ------- | ------- | --------------------------- |
| `workers.doDailySet` | boolean | `true` | Complete daily set | | `workers.doDailySet` | boolean | `true` | Complete daily set |
| `workers.doSpecialPromotions` | boolean | `true` | Complete special promotions | | `workers.doSpecialPromotions` | boolean | `true` | Complete special promotions |
| `workers.doMorePromotions` | boolean | `true` | Complete more promotions | | `workers.doMorePromotions` | boolean | `true` | Complete more promotions |
@@ -97,8 +108,9 @@ Edit `src/config.json` to customize behavior. Below are all currently available
| `workers.doReadToEarn` | boolean | `true` | Complete Read-to-Earn | | `workers.doReadToEarn` | boolean | `true` | Complete Read-to-Earn |
### Search Settings ### Search Settings
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | -------------------------------------- | -------- | -------------------------------------------- | ----------------------------------- |
| `searchSettings.scrollRandomResults` | boolean | `false` | Scroll randomly on results | | `searchSettings.scrollRandomResults` | boolean | `false` | Scroll randomly on results |
| `searchSettings.clickRandomResults` | boolean | `false` | Click random links | | `searchSettings.clickRandomResults` | boolean | `false` | Click random links |
| `searchSettings.parallelSearching` | boolean | `true` | Run searches in parallel | | `searchSettings.parallelSearching` | boolean | `true` | Run searches in parallel |
@@ -110,8 +122,9 @@ Edit `src/config.json` to customize behavior. Below are all currently available
| `searchSettings.readDelay.max` | string | `"1min"` | Maximum delay for reading | | `searchSettings.readDelay.max` | string | `"1min"` | Maximum delay for reading |
### Logging ### Logging
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | -------------------------------- | -------- | ---------------------- | --------------------------------- |
| `debugLogs` | boolean | `false` | Enable debug logging | | `debugLogs` | boolean | `false` | Enable debug logging |
| `consoleLogFilter.enabled` | boolean | `false` | Enable console log filtering | | `consoleLogFilter.enabled` | boolean | `false` | Enable console log filtering |
| `consoleLogFilter.mode` | string | `"whitelist"` | Filter mode (whitelist/blacklist) | | `consoleLogFilter.mode` | string | `"whitelist"` | Filter mode (whitelist/blacklist) |
@@ -120,13 +133,15 @@ Edit `src/config.json` to customize behavior. Below are all currently available
| `consoleLogFilter.regexPatterns` | string[] | `[]` | Regex patterns for filtering | | `consoleLogFilter.regexPatterns` | string[] | `[]` | Regex patterns for filtering |
### Proxy ### Proxy
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | ------------------- | ------- | ------- | --------------------------- |
| `proxy.queryEngine` | boolean | `true` | Proxy query engine requests | | `proxy.queryEngine` | boolean | `true` | Proxy query engine requests |
### Webhooks ### Webhooks
| Setting | Type | Default | Description | | Setting | Type | Default | Description |
|----------|------|----------|-------------| | ---------------------------------------- | -------- | ---------------------------------------------------- | --------------------------------- |
| `webhook.discord.enabled` | boolean | `false` | Enable Discord webhook | | `webhook.discord.enabled` | boolean | `false` | Enable Discord webhook |
| `webhook.discord.url` | string | `""` | Discord webhook URL | | `webhook.discord.url` | string | `""` | Discord webhook URL |
| `webhook.ntfy.enabled` | boolean | `false` | Enable ntfy notifications | | `webhook.ntfy.enabled` | boolean | `false` | Enable ntfy notifications |
@@ -142,9 +157,8 @@ Edit `src/config.json` to customize behavior. Below are all currently available
| `webhook.webhookLogFilter.keywords` | string[] | `["starting account", "select number", "collected"]` | Keywords to filter | | `webhook.webhookLogFilter.keywords` | string[] | `["starting account", "select number", "collected"]` | Keywords to filter |
| `webhook.webhookLogFilter.regexPatterns` | string[] | `[]` | Regex patterns for filtering | | `webhook.webhookLogFilter.regexPatterns` | string[] | `[]` | Regex patterns for filtering |
> [!WARNING] > [!WARNING]
> **NTFY** users set the `webhookLogFilter` to `enabled`, or you will receive push notifications for *all* logs. > **NTFY** users set the `webhookLogFilter` to `enabled`, or you will receive push notifications for _all_ logs.
> When enabled, only account start, 2FA codes, and account completion summaries are delivered as push notifcations. > When enabled, only account start, 2FA codes, and account completion summaries are delivered as push notifcations.
> Customize which notifications you receive with the `keywords` options. > Customize which notifications you receive with the `keywords` options.
@@ -208,6 +222,7 @@ Edit `src/accounts.json`.
> When using 2FA login, adding your `totpSecret` will enable the script to automatically generate and enter the timed 6 digit code to login. To get your `totpSecret` in your Microsoft Security settings, click 'Manage how you sign in'. Add Authenticator app, when shown the QR code, select 'enter code manually'. Use this code in the `accounts.json`. > When using 2FA login, adding your `totpSecret` will enable the script to automatically generate and enter the timed 6 digit code to login. To get your `totpSecret` in your Microsoft Security settings, click 'Manage how you sign in'. Add Authenticator app, when shown the QR code, select 'enter code manually'. Use this code in the `accounts.json`.
--- ---
## Troubleshooting ## Troubleshooting
> [!TIP] > [!TIP]

View File

@@ -1,12 +1,6 @@
import path from 'path' import path from 'path'
import fs from 'fs' import fs from 'fs'
import { import { getDirname, getProjectRoot, log, loadJsonFile, safeRemoveDirectory } from '../utils.js'
getDirname,
getProjectRoot,
log,
loadJsonFile,
safeRemoveDirectory
} from '../utils.js'
const __dirname = getDirname(import.meta.url) const __dirname = getDirname(import.meta.url)
const projectRoot = getProjectRoot(__dirname) const projectRoot = getProjectRoot(__dirname)

View File

@@ -94,10 +94,7 @@ export function loadJsonFile(possiblePaths, required = true) {
export function loadConfig(projectRoot, isDev = false) { export function loadConfig(projectRoot, isDev = false) {
const possiblePaths = isDev const possiblePaths = isDev
? [path.join(projectRoot, 'src', 'config.json')] ? [path.join(projectRoot, 'src', 'config.json')]
: [ : [path.join(projectRoot, 'dist', 'config.json'), path.join(projectRoot, 'config.json')]
path.join(projectRoot, 'dist', 'config.json'),
path.join(projectRoot, 'config.json')
]
const result = loadJsonFile(possiblePaths, true) const result = loadJsonFile(possiblePaths, true)
@@ -131,7 +128,10 @@ export function loadAccounts(projectRoot, isDev = false) {
export function findAccountByEmail(accounts, email) { export function findAccountByEmail(accounts, email) {
if (!email || typeof email !== 'string') return null if (!email || typeof email !== 'string') return null
return accounts.find(a => a?.email && typeof a.email === 'string' && a.email.toLowerCase() === email.toLowerCase()) || null return (
accounts.find(a => a?.email && typeof a.email === 'string' && a.email.toLowerCase() === email.toLowerCase()) ||
null
)
} }
export function getRuntimeBase(projectRoot, isDev = false) { export function getRuntimeBase(projectRoot, isDev = false) {

View File

@@ -1,5 +1,5 @@
import type { BrowserContext, Cookie } from 'patchright' import type { BrowserContext, Cookie } from 'patchright'
import type { AxiosRequestConfig, AxiosResponse } from 'axios' import type { AxiosRequestConfig } from 'axios'
import type { MicrosoftRewardsBot } from '../index' import type { MicrosoftRewardsBot } from '../index'
import { saveSessionData } from '../util/Load' import { saveSessionData } from '../util/Load'
@@ -23,45 +23,56 @@ export default class BrowserFunc {
*/ */
async getDashboardData(): Promise<DashboardData> { async getDashboardData(): Promise<DashboardData> {
try { try {
const allowedDomains = ['bing.com', 'live.com', 'microsoftonline.com'];
const cookieHeader = [
...new Map(
this.bot.cookies.mobile
.filter(
(c: { name: string; value: string; domain?: string }) =>
typeof c.domain === 'string' &&
allowedDomains.some(d =>
c.domain && c.domain.toLowerCase().endsWith(d)
)
)
.map(c => [c.name, c]) // dedupe by name, keep last
).values()
]
.map(c => `${c.name}=${c.value}`)
.join('; ');
const request: AxiosRequestConfig = { const request: AxiosRequestConfig = {
url: 'https://rewards.bing.com/api/getuserinfo?type=1', url: 'https://rewards.bing.com/api/getuserinfo?type=1',
method: 'GET', method: 'GET',
headers: { headers: {
...(this.bot.fingerprint?.headers ?? {}), ...(this.bot.fingerprint?.headers ?? {}),
Cookie: cookieHeader, Cookie: this.buildCookieHeader(this.bot.cookies.mobile, [
'bing.com',
'live.com',
'microsoftonline.com'
]),
Referer: 'https://rewards.bing.com/', Referer: 'https://rewards.bing.com/',
Origin: 'https://rewards.bing.com' Origin: 'https://rewards.bing.com'
} }
} }
const response = await this.bot.axios.request(request) const response = await this.bot.axios.request(request)
if (response.data?.dashboard) {
return response.data.dashboard as DashboardData return response.data.dashboard as DashboardData
}
throw new Error('Dashboard data missing from API response')
} catch (error) { } catch (error) {
this.bot.logger.info( this.bot.logger.warn(this.bot.isMobile, 'GET-DASHBOARD-DATA', 'API failed, trying HTML fallback')
this.bot.isMobile,
'GET-DASHBOARD-DATA', // Try using script from dashboard page
`Error fetching dashboard data: ${error instanceof Error ? error.message : String(error)}` try {
) const request: AxiosRequestConfig = {
throw error url: this.bot.config.baseURL,
method: 'GET',
headers: {
...(this.bot.fingerprint?.headers ?? {}),
Cookie: this.buildCookieHeader(this.bot.cookies.mobile),
Referer: 'https://rewards.bing.com/',
Origin: 'https://rewards.bing.com'
}
}
const response = await this.bot.axios.request(request)
const match = response.data.match(/var\s+dashboard\s*=\s*({.*?});/s)
if (!match?.[1]) {
throw new Error('Dashboard script not found in HTML')
}
return JSON.parse(match[1]) as DashboardData
} catch (fallbackError) {
// If both fail
this.bot.logger.error(this.bot.isMobile, 'GET-DASHBOARD-DATA', 'Failed to get dashboard data')
throw fallbackError
}
} }
} }
@@ -84,7 +95,7 @@ export default class BrowserFunc {
const response = await this.bot.axios.request(request) const response = await this.bot.axios.request(request)
return response.data as AppDashboardData return response.data as AppDashboardData
} catch (error) { } catch (error) {
this.bot.logger.info( this.bot.logger.error(
this.bot.isMobile, this.bot.isMobile,
'GET-APP-DASHBOARD-DATA', 'GET-APP-DASHBOARD-DATA',
`Error fetching dashboard data: ${error instanceof Error ? error.message : String(error)}` `Error fetching dashboard data: ${error instanceof Error ? error.message : String(error)}`
@@ -112,7 +123,7 @@ export default class BrowserFunc {
const response = await this.bot.axios.request(request) const response = await this.bot.axios.request(request)
return response.data as XboxDashboardData return response.data as XboxDashboardData
} catch (error) { } catch (error) {
this.bot.logger.info( this.bot.logger.error(
this.bot.isMobile, this.bot.isMobile,
'GET-XBOX-DASHBOARD-DATA', 'GET-XBOX-DASHBOARD-DATA',
`Error fetching dashboard data: ${error instanceof Error ? error.message : String(error)}` `Error fetching dashboard data: ${error instanceof Error ? error.message : String(error)}`
@@ -308,141 +319,21 @@ export default class BrowserFunc {
} }
} }
mergeCookies(response: AxiosResponse, currentCookieHeader: string = '', whitelist?: string[]): string { buildCookieHeader(cookies: Cookie[], allowedDomains?: string[]): string {
const cookieMap = new Map<string, string>( return [
currentCookieHeader ...new Map(
.split(';') cookies
.map(pair => pair.split('=').map(s => s.trim())) .filter(c => {
.filter(([name, value]) => name && value) if (!allowedDomains || allowedDomains.length === 0) return true
.map(([name, value]) => [name, value] as [string, string]) return (
typeof c.domain === 'string' &&
allowedDomains.some(d => c.domain.toLowerCase().endsWith(d.toLowerCase()))
) )
})
const setCookieList = [response.headers['set-cookie']].flat().filter(Boolean) as string[] .map(c => [c.name, c])
const cookiesByName = new Map(this.bot.cookies.mobile.map(c => [c.name, c])) ).values()
]
for (const setCookie of setCookieList) { .map(c => `${c.name}=${c.value}`)
const [nameValue, ...attributes] = setCookie.split(';').map(s => s.trim()) .join('; ')
if (!nameValue) continue
const [name, value] = nameValue.split('=').map(s => s.trim())
if (!name) continue
if (whitelist && !whitelist?.includes(name)) {
continue
}
const attrs = this.parseAttributes(attributes)
const existing = cookiesByName.get(name)
if (!value) {
if (existing) {
cookiesByName.delete(name)
this.bot.cookies.mobile = this.bot.cookies.mobile.filter(c => c.name !== name)
}
cookieMap.delete(name)
continue
}
if (attrs.expires !== undefined && attrs.expires < Date.now() / 1000) {
if (existing) {
cookiesByName.delete(name)
this.bot.cookies.mobile = this.bot.cookies.mobile.filter(c => c.name !== name)
}
cookieMap.delete(name)
continue
}
cookieMap.set(name, value)
if (existing) {
this.updateCookie(existing, value, attrs)
} else {
this.bot.cookies.mobile.push(this.createCookie(name, value, attrs))
}
}
return Array.from(cookieMap, ([name, value]) => `${name}=${value}`).join('; ')
}
private parseAttributes(attributes: string[]) {
const attrs: {
domain?: string
path?: string
expires?: number
httpOnly?: boolean
secure?: boolean
sameSite?: Cookie['sameSite']
} = {}
for (const attr of attributes) {
const [key, val] = attr.split('=').map(s => s?.trim())
const lowerKey = key?.toLowerCase()
switch (lowerKey) {
case 'domain':
case 'path': {
if (val) attrs[lowerKey] = val
break
}
case 'expires': {
if (val) {
const ts = Date.parse(val)
if (!isNaN(ts)) attrs.expires = Math.floor(ts / 1000)
}
break
}
case 'max-age': {
if (val) {
const maxAge = Number(val)
if (!isNaN(maxAge)) attrs.expires = Math.floor(Date.now() / 1000) + maxAge
}
break
}
case 'httponly': {
attrs.httpOnly = true
break
}
case 'secure': {
attrs.secure = true
break
}
case 'samesite': {
const normalized = val?.toLowerCase()
if (normalized && ['lax', 'strict', 'none'].includes(normalized)) {
attrs.sameSite = (normalized.charAt(0).toUpperCase() +
normalized.slice(1)) as Cookie['sameSite']
}
break
}
}
}
return attrs
}
private updateCookie(cookie: Cookie, value: string, attrs: ReturnType<typeof this.parseAttributes>) {
cookie.value = value
if (attrs.domain) cookie.domain = attrs.domain
if (attrs.path) cookie.path = attrs.path
//if (attrs.expires !== undefined) cookie.expires = attrs.expires
//if (attrs.httpOnly) cookie.httpOnly = true
//if (attrs.secure) cookie.secure = true
//if (attrs.sameSite) cookie.sameSite = attrs.sameSite
}
private createCookie(name: string, value: string, attrs: ReturnType<typeof this.parseAttributes>): Cookie {
return {
name,
value,
domain: attrs.domain || '.bing.com',
path: attrs.path || '/'
/*
...(attrs.expires !== undefined && { expires: attrs.expires }),
...(attrs.httpOnly && { httpOnly: true }),
...(attrs.secure && { secure: true }),
...(attrs.sameSite && { sameSite: attrs.sameSite })
*/
} as Cookie
} }
} }

View File

@@ -220,14 +220,14 @@ export default class BrowserUtils {
) )
// Wait for selector to exist before clicking // Wait for selector to exist before clicking
await page.waitForSelector(selector, { timeout: 10000 }) await page.waitForSelector(selector, { timeout: 1000 }).catch(() => {})
const cursor = createCursor(page as any) const cursor = createCursor(page as any)
await cursor.click(selector, options) await cursor.click(selector, options)
return true return true
} catch (error) { } catch (error) {
this.bot.logger.error( this.bot.logger.warn(
this.bot.isMobile, this.bot.isMobile,
'GHOST-CLICK', 'GHOST-CLICK',
`Failed for ${selector}: ${error instanceof Error ? error.message : String(error)}` `Failed for ${selector}: ${error instanceof Error ? error.message : String(error)}`

View File

@@ -502,7 +502,11 @@ export class Login {
} }
case 'OTP_CODE_ENTRY': { case 'OTP_CODE_ENTRY': {
this.bot.logger.info(this.bot.isMobile, 'LOGIN', 'OTP code entry page detected, attempting to find password option') this.bot.logger.info(
this.bot.isMobile,
'LOGIN',
'OTP code entry page detected, attempting to find password option'
)
// My Fix: Click "Use your password" footer // My Fix: Click "Use your password" footer
const footerLink = await page const footerLink = await page

View File

@@ -45,7 +45,7 @@ export function promptInput(options: PromptOptions): Promise<string | null> {
export async function getSubtitleMessage(page: Page): Promise<string | null> { export async function getSubtitleMessage(page: Page): Promise<string | null> {
const message = await page const message = await page
.waitForSelector('[data-testid="subtitle"]', { state: 'visible', timeout: 1000 }) .waitForSelector('[data-testid="subtitle"], div#oneTimeCodeDescription', { state: 'visible', timeout: 1000 })
.catch(() => null) .catch(() => null)
if (!message) return null if (!message) return null

View File

@@ -22,12 +22,7 @@
"scrollRandomResults": false, "scrollRandomResults": false,
"clickRandomResults": false, "clickRandomResults": false,
"parallelSearching": true, "parallelSearching": true,
"queryEngines": [ "queryEngines": ["google", "wikipedia", "reddit", "local"],
"google",
"wikipedia",
"reddit",
"local"
],
"searchResultVisitTime": "10sec", "searchResultVisitTime": "10sec",
"searchDelay": { "searchDelay": {
"min": "30sec", "min": "30sec",
@@ -42,13 +37,8 @@
"consoleLogFilter": { "consoleLogFilter": {
"enabled": false, "enabled": false,
"mode": "whitelist", "mode": "whitelist",
"levels": [ "levels": ["error", "warn"],
"error", "keywords": ["starting account"],
"warn"
],
"keywords": [
"starting account"
],
"regexPatterns": [] "regexPatterns": []
}, },
"proxy": { "proxy": {
@@ -65,23 +55,14 @@
"topic": "", "topic": "",
"token": "", "token": "",
"title": "Microsoft-Rewards-Script", "title": "Microsoft-Rewards-Script",
"tags": [ "tags": ["bot", "notify"],
"bot",
"notify"
],
"priority": 3 "priority": 3
}, },
"webhookLogFilter": { "webhookLogFilter": {
"enabled": false, "enabled": false,
"mode": "whitelist", "mode": "whitelist",
"levels": [ "levels": ["error"],
"error" "keywords": ["starting account", "select number", "collected"],
],
"keywords": [
"starting account",
"select number",
"collected"
],
"regexPatterns": [] "regexPatterns": []
} }
} }

View File

@@ -77,7 +77,6 @@ export class QueryCore {
const baseTopics = this.normalizeAndDedupe(topicLists.flat()) const baseTopics = this.normalizeAndDedupe(topicLists.flat())
if (!baseTopics.length) { if (!baseTopics.length) {
this.bot.logger.warn(this.bot.isMobile, 'QUERY-MANAGER', 'No queries')
this.bot.logger.debug(this.bot.isMobile, 'QUERY-MANAGER', 'No base topics found (all sources empty)') this.bot.logger.debug(this.bot.isMobile, 'QUERY-MANAGER', 'No base topics found (all sources empty)')
return [] return []
} }
@@ -115,7 +114,6 @@ export class QueryCore {
) )
if (!finalQueries.length) { if (!finalQueries.length) {
this.bot.logger.warn(this.bot.isMobile, 'QUERY-MANAGER', 'No queries')
this.bot.logger.debug(this.bot.isMobile, 'QUERY-MANAGER', 'finalQueries deduped to 0') this.bot.logger.debug(this.bot.isMobile, 'QUERY-MANAGER', 'finalQueries deduped to 0')
return [] return []
} }
@@ -124,7 +122,6 @@ export class QueryCore {
return finalQueries return finalQueries
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'QUERY-MANAGER', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'QUERY-MANAGER', 'QUERY-MANAGER',
@@ -216,7 +213,6 @@ export class QueryCore {
const response = await this.bot.axios.request(request, this.bot.config.proxy.queryEngine) const response = await this.bot.axios.request(request, this.bot.config.proxy.queryEngine)
const trendsData = this.extractJsonFromResponse(response.data) const trendsData = this.extractJsonFromResponse(response.data)
if (!trendsData) { if (!trendsData) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'No queries')
this.bot.logger.debug(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'No trendsData parsed from response') this.bot.logger.debug(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'No trendsData parsed from response')
return [] return []
} }
@@ -234,7 +230,6 @@ export class QueryCore {
}) })
} }
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-GOOGLE-TRENDS', 'SEARCH-GOOGLE-TRENDS',
@@ -277,7 +272,6 @@ export class QueryCore {
response.data.suggestionGroups?.[0]?.searchSuggestions?.map((x: { query: any }) => x.query) ?? [] response.data.suggestionGroups?.[0]?.searchSuggestions?.map((x: { query: any }) => x.query) ?? []
if (!suggestions.length) { if (!suggestions.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-SUGGESTIONS', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-SUGGESTIONS', 'SEARCH-BING-SUGGESTIONS',
@@ -287,7 +281,6 @@ export class QueryCore {
return suggestions return suggestions
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-SUGGESTIONS', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-SUGGESTIONS', 'SEARCH-BING-SUGGESTIONS',
@@ -314,7 +307,6 @@ export class QueryCore {
const out = Array.isArray(related) ? related : [] const out = Array.isArray(related) ? related : []
if (!out.length) { if (!out.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-RELATED', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-RELATED', 'SEARCH-BING-RELATED',
@@ -324,7 +316,6 @@ export class QueryCore {
return out return out
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-RELATED', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-RELATED', 'SEARCH-BING-RELATED',
@@ -359,7 +350,6 @@ export class QueryCore {
) ?? [] ) ?? []
if (!topics.length) { if (!topics.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-TRENDING', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-TRENDING', 'SEARCH-BING-TRENDING',
@@ -369,7 +359,6 @@ export class QueryCore {
return topics return topics
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-BING-TRENDING', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-BING-TRENDING', 'SEARCH-BING-TRENDING',
@@ -402,7 +391,6 @@ export class QueryCore {
const out = articles.slice(0, 50).map(a => a.article.replace(/_/g, ' ')) const out = articles.slice(0, 50).map(a => a.article.replace(/_/g, ' '))
if (!out.length) { if (!out.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-WIKIPEDIA-TRENDING', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-WIKIPEDIA-TRENDING', 'SEARCH-WIKIPEDIA-TRENDING',
@@ -412,7 +400,6 @@ export class QueryCore {
return out return out
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-WIKIPEDIA-TRENDING', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-WIKIPEDIA-TRENDING', 'SEARCH-WIKIPEDIA-TRENDING',
@@ -441,7 +428,6 @@ export class QueryCore {
const out = posts.filter(p => !p.data.over_18).map(p => p.data.title) const out = posts.filter(p => !p.data.over_18).map(p => p.data.title)
if (!out.length) { if (!out.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-REDDIT-TRENDING', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-REDDIT-TRENDING', 'SEARCH-REDDIT-TRENDING',
@@ -451,7 +437,6 @@ export class QueryCore {
return out return out
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-REDDIT', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-REDDIT', 'SEARCH-REDDIT',
@@ -476,7 +461,6 @@ export class QueryCore {
) )
if (!out.length) { if (!out.length) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-LOCAL-QUERY-LIST', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-LOCAL-QUERY-LIST', 'SEARCH-LOCAL-QUERY-LIST',
@@ -486,7 +470,6 @@ export class QueryCore {
return out return out
} catch (error) { } catch (error) {
this.bot.logger.warn(this.bot.isMobile, 'SEARCH-LOCAL-QUERY-LIST', 'No queries')
this.bot.logger.debug( this.bot.logger.debug(
this.bot.isMobile, this.bot.isMobile,
'SEARCH-LOCAL-QUERY-LIST', 'SEARCH-LOCAL-QUERY-LIST',

View File

@@ -21,9 +21,9 @@ export class DoubleSearchPoints extends Workers {
return return
} }
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop) this.cookieHeader = this.bot.browser.func.buildCookieHeader(
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`) this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop
.join('; ') )
const fingerprintHeaders = { ...this.bot.fingerprint.headers } const fingerprintHeaders = { ...this.bot.fingerprint.headers }
delete fingerprintHeaders['Cookie'] delete fingerprintHeaders['Cookie']

View File

@@ -25,9 +25,9 @@ export class FindClippy extends Workers {
return return
} }
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop) this.cookieHeader = this.bot.browser.func.buildCookieHeader(
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`) this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop
.join('; ') )
const fingerprintHeaders = { ...this.bot.fingerprint.headers } const fingerprintHeaders = { ...this.bot.fingerprint.headers }
delete fingerprintHeaders['Cookie'] delete fingerprintHeaders['Cookie']

View File

@@ -23,9 +23,9 @@ export class Quiz extends Workers {
) )
try { try {
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop) this.cookieHeader = this.bot.browser.func.buildCookieHeader(
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`) this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop
.join('; ') )
const fingerprintHeaders = { ...this.bot.fingerprint.headers } const fingerprintHeaders = { ...this.bot.fingerprint.headers }
delete fingerprintHeaders['Cookie'] delete fingerprintHeaders['Cookie']

View File

@@ -30,9 +30,9 @@ export class UrlReward extends Workers {
) )
try { try {
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop) this.cookieHeader = this.bot.browser.func.buildCookieHeader(
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`) this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop
.join('; ') )
const fingerprintHeaders = { ...this.bot.fingerprint.headers } const fingerprintHeaders = { ...this.bot.fingerprint.headers }
delete fingerprintHeaders['Cookie'] delete fingerprintHeaders['Cookie']

View File

@@ -53,7 +53,7 @@ export class Search extends Workers {
queries = [...new Set(queries.map(q => q.trim()).filter(Boolean))] queries = [...new Set(queries.map(q => q.trim()).filter(Boolean))]
this.bot.logger.debug(isMobile, 'SEARCH-BING', `Query pool ready | count=${queries.length}`) this.bot.logger.info(isMobile, 'SEARCH-BING', `Search query pool ready | count=${queries.length}`)
// Go to bing // Go to bing
const targetUrl = this.searchPageURL ? this.searchPageURL : this.bingHome const targetUrl = this.searchPageURL ? this.searchPageURL : this.bingHome
@@ -169,10 +169,10 @@ export class Search extends Workers {
const newPool = [...new Set(merged)] const newPool = [...new Set(merged)]
queries = this.bot.utils.shuffleArray(newPool) queries = this.bot.utils.shuffleArray(newPool)
this.bot.logger.debug( this.bot.logger.info(
isMobile, isMobile,
'SEARCH-BING-EXTRA', 'SEARCH-BING-EXTRA',
`New query pool generated | count=${queries.length}` `New search query pool generated | count=${queries.length}`
) )
for (const query of queries) { for (const query of queries) {

View File

@@ -32,9 +32,9 @@ export class SearchOnBing extends Workers {
) )
try { try {
this.cookieHeader = (this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop) this.cookieHeader = this.bot.browser.func.buildCookieHeader(
.map((c: { name: string; value: string }) => `${c.name}=${c.value}`) this.bot.isMobile ? this.bot.cookies.mobile : this.bot.cookies.desktop
.join('; ') )
const fingerprintHeaders = { ...this.bot.fingerprint.headers } const fingerprintHeaders = { ...this.bot.fingerprint.headers }
delete fingerprintHeaders['Cookie'] delete fingerprintHeaders['Cookie']

View File

@@ -40,12 +40,8 @@
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */ /* Module Resolution Options */
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
"types": [ "types": ["node"],
"node" "typeRoots": ["./node_modules/@types"],
],
"typeRoots": [
"./node_modules/@types"
],
// Keep explicit typeRoots to ensure resolution in environments that don't auto-detect before full install. // Keep explicit typeRoots to ensure resolution in environments that don't auto-detect before full install.
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
@@ -76,7 +72,5 @@
"src/functions/bing-search-activity-queries.json", "src/functions/bing-search-activity-queries.json",
"src/functions/search-queries.json" "src/functions/search-queries.json"
], ],
"exclude": [ "exclude": ["node_modules"]
"node_modules"
]
} }