7 Commits

Author SHA1 Message Date
Netsky
b630c3ddda Update README.md 2025-02-24 15:52:53 +01:00
Netsky
287e3897da Update README.md 2025-02-24 15:51:08 +01:00
Netsky
fcf6aba446 Bump version 2025-02-24 15:49:45 +01:00
AariaX
1102f2ca94 Google API Update (1.5.1) (#247)
* switch to google internal api

* A bit of tidying up

* A bit more of tidying up

* A bit more of tidying up

* Pre 1.5.1

- Add proxy exclusions
- Update ReadMe
- Update config Interface

---------

Co-authored-by: TheNetsky <56271887+TheNetsky@users.noreply.github.com>
2025-02-24 15:49:19 +01:00
1OSA
82a896e83f added webhooklogexcludefunc (#240) 2025-02-20 23:21:46 +01:00
Netsky
b0bd1f52c4 Update queries.json 2025-02-19 19:32:45 +01:00
Netsky
7e4121e01b Update run_daily.sh 2025-02-19 15:29:51 +01:00
9 changed files with 257 additions and 69 deletions

View File

@@ -57,9 +57,11 @@ A basic docker `compose.yaml` is provided. Follow these steps to configure and r
| baseURL | MS Rewards page | `https://rewards.bing.com` | | baseURL | MS Rewards page | `https://rewards.bing.com` |
| 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) |
| 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) |
| parallel | If you want mobile and desktop taks to run parallel or sequential| `true` |
| 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) |
| 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) |
| saveFingerprint | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) | | saveFingerprint.mobile | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) |
| saveFingerprint.desktop | Re-use the same fingerprint each time | `false` (Will generate a new fingerprint each time) |
| workers.doDailySet | Complete daily set items | `true` | | workers.doDailySet | Complete daily set items | `true` |
| workers.doMorePromotions | Complete promotional items | `true` | | workers.doMorePromotions | Complete promotional items | `true` |
| workers.doPunchCards | Complete punchcards | `true` | | workers.doPunchCards | Complete punchcards | `true` |
@@ -67,17 +69,19 @@ A basic docker `compose.yaml` is provided. Follow these steps to configure and r
| workers.doMobileSearch | Complete daily mobile searches | `true` | | workers.doMobileSearch | Complete daily mobile searches | `true` |
| workers.doDailyCheckIn | Complete daily check-in activity | `true` | | workers.doDailyCheckIn | Complete daily check-in activity | `true` |
| workers.doReadToEarn | Complete read to earn activity | `true` | | workers.doReadToEarn | Complete read to earn activity | `true` |
| searchOnBingLocalQueries | Complete the activity "search on Bing" using the `queries.json` or fetched from this repo | `false` (Will fetch from this repo) |
| globalTimeout | The length before the action gets timeout | `30s` | | globalTimeout | The length before the action gets timeout | `30s` |
| searchSettings.useGeoLocaleQueries | Generate search queries based on your geo-location | `true` (Uses EN-US generated queries) | | searchSettings.useGeoLocaleQueries | Generate search queries based on your geo-location | `false` (Uses EN-US generated queries) |
| scrollRandomResults | Scroll randomly in search results | `true` | | searchSettings.scrollRandomResults | Scroll randomly in search results | `true` |
| searchSettings.clickRandomResults | Visit random website from search result| `true` | | searchSettings.clickRandomResults | Visit random website from search result| `true` |
| searchSettings.searchDelay | Minimum and maximum time in miliseconds between search queries | `min: 1min` `max: 2min` | | searchSettings.searchDelay | Minimum and maximum time in miliseconds between search queries | `min: 1min` `max: 2min` |
| searchSettings.retryMobileSearchAmount | Keep retrying mobile searches for specified amount | `3` | | searchSettings.retryMobileSearchAmount | Keep retrying mobile searches for specified amount | `3` |
| logExcludeFunc | Functions to exclude out of the logs and webhooks | `SEARCH-CLOSE-TABS` | | logExcludeFunc | Functions to exclude out of the logs and webhooks | `SEARCH-CLOSE-TABS` |
| webhookLogExcludeFunc | Functions to exclude out of the webhooks log | `SEARCH-CLOSE-TABS` |
| proxy.proxyGoogleTrends | Enable or disable proxying the request via set proxy | `true` (will be proxied) |
| proxy.proxyBingTerms | Enable or disable proxying the request via set proxy | `true` (will be proxied) |
| webhook.enabled | Enable or disable your set webhook | `false` | | webhook.enabled | Enable or disable your set webhook | `false` |
| webhook.url | Your Discord webhook URL | `null` | | webhook.url | Your Discord webhook URL | `null` |
| cronStartTime | Scheduled script run-time, *only available for docker implementation* | `0 5,11 * * *` (5:00 am, 11:00 am daily) |
| | Run the script immediately when the Docker container starts | `true` |
## Features ## ## Features ##
- [x] Multi-Account Support - [x] Multi-Account Support
@@ -112,4 +116,4 @@ A basic docker `compose.yaml` is provided. Follow these steps to configure and r
## 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!
<br /> <br />
Use this script at your own risk! Use this script at your own risk!

View File

@@ -1,6 +1,6 @@
{ {
"name": "microsoft-rewards-script", "name": "microsoft-rewards-script",
"version": "1.5.0", "version": "1.5.1",
"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": {

View File

@@ -1,7 +1,7 @@
{ {
"baseURL": "https://rewards.bing.com", "baseURL": "https://rewards.bing.com",
"sessionPath": "sessions", "sessionPath": "sessions",
"headless": true, "headless": false,
"parallel": true, "parallel": true,
"runOnZeroPoints": false, "runOnZeroPoints": false,
"clusters": 1, "clusters": 1,
@@ -33,6 +33,13 @@
"logExcludeFunc": [ "logExcludeFunc": [
"SEARCH-CLOSE-TABS" "SEARCH-CLOSE-TABS"
], ],
"webhookLogExcludeFunc": [
"SEARCH-CLOSE-TABS"
],
"proxy": {
"proxyGoogleTrends": true,
"proxyBingTerms": true
},
"webhook": { "webhook": {
"enabled": false, "enabled": false,
"url": "" "url": ""

View File

@@ -4,9 +4,17 @@ import { platform } from 'os'
import { Workers } from '../Workers' import { Workers } from '../Workers'
import { Counters, DashboardData } from '../../interface/DashboardData' import { Counters, DashboardData } from '../../interface/DashboardData'
import { GoogleTrends } from '../../interface/GoogleDailyTrends'
import { GoogleSearch } from '../../interface/Search' import { GoogleSearch } from '../../interface/Search'
import { AxiosRequestConfig } from 'axios'
type GoogleTrendsResponse = [
string,
[
string,
...null[],
[string, ...string[]]
][]
];
export class Search extends Workers { export class Search extends Workers {
private bingHome = 'https://bing.com' private bingHome = 'https://bing.com'
@@ -26,7 +34,7 @@ export class Search extends Workers {
} }
// Generate search queries // Generate search queries
let googleSearchQueries = await this.getGoogleTrends(data.userProfile.attributes.country, missingPoints) let googleSearchQueries = await this.getGoogleTrends(this.bot.config.searchSettings.useGeoLocaleQueries ? data.userProfile.attributes.country : 'US')
googleSearchQueries = this.bot.utils.shuffleArray(googleSearchQueries) googleSearchQueries = this.bot.utils.shuffleArray(googleSearchQueries)
// Deduplicate the search terms // Deduplicate the search terms
@@ -203,49 +211,64 @@ export class Search extends Workers {
return await this.bot.browser.func.getSearchPoints() return await this.bot.browser.func.getSearchPoints()
} }
private async getGoogleTrends(geoLocale: string, queryCount: number): Promise<GoogleSearch[]> { private async getGoogleTrends(geoLocale: string = 'US'): Promise<GoogleSearch[]> {
const queryTerms: GoogleSearch[] = [] const queryTerms: GoogleSearch[] = []
let i = 0
geoLocale = (this.bot.config.searchSettings.useGeoLocaleQueries && geoLocale.length === 2) ? geoLocale.toUpperCase() : 'US'
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', `Generating search queries, can take a while! | GeoLocale: ${geoLocale}`) this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', `Generating search queries, can take a while! | GeoLocale: ${geoLocale}`)
while (queryCount > queryTerms.length) { try {
i += 1 const request: AxiosRequestConfig = {
const date = new Date() url: 'https://trends.google.com/_/TrendsUi/data/batchexecute',
date.setDate(date.getDate() - i) method: 'POST',
const formattedDate = this.formatDate(date) headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
try { },
const request = { data: `f.req=[[[i0OFE,"[null, null, \\"${geoLocale}\\", 0, null, 48]"]]]`
url: `https://trends.google.com/trends/api/dailytrends?geo=${geoLocale}&hl=en&ed=${formattedDate}&ns=15`,
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}
const response = await this.bot.axios.request(request)
const data: GoogleTrends = JSON.parse((await response.data).slice(5))
for (const topic of data.default.trendingSearchesDays[0]?.trendingSearches ?? []) {
queryTerms.push({
topic: topic.title.query.toLowerCase(),
related: topic.relatedQueries.map(x => x.query.toLowerCase())
})
}
} catch (error) {
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
break
} }
const response = await this.bot.axios.request(request, this.bot.config.proxy.proxyGoogleTrends)
const rawText = response.data
const trendsData = this.extractJsonFromResponse(rawText)
if (!trendsData) {
throw this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'Failed to parse Google Trends response', 'error')
}
const mappedTrendsData = trendsData.map(query => [query[0], query[9]!.slice(1)])
if (mappedTrendsData.length < 90) {
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'Insufficient search queries, falling back to US', 'warn')
return this.getGoogleTrends()
}
for (const [topic, relatedQueries] of mappedTrendsData) {
queryTerms.push({
topic: topic as string,
related: relatedQueries as string[]
})
}
} catch (error) {
this.bot.log(this.bot.isMobile, 'SEARCH-GOOGLE-TRENDS', 'An error occurred:' + error, 'error')
} }
return queryTerms return queryTerms
} }
private extractJsonFromResponse(text: string): GoogleTrendsResponse[1] | null {
const lines = text.split('\n')
for (const line of lines) {
const trimmed = line.trim()
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
try {
return JSON.parse(JSON.parse(trimmed)[0][2])[1]
} catch {
continue
}
}
}
return null
}
private async getRelatedTerms(term: string): Promise<string[]> { private async getRelatedTerms(term: string): Promise<string[]> {
try { try {
const request = { const request = {
@@ -256,7 +279,7 @@ export class Search extends Workers {
} }
} }
const response = await this.bot.axios.request(request) const response = await this.bot.axios.request(request, this.bot.config.proxy.proxyBingTerms)
return response.data[1] as string[] return response.data[1] as string[]
} catch (error) { } catch (error) {
@@ -266,14 +289,6 @@ export class Search extends Workers {
return [] return []
} }
private formatDate(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}${month}${day}`
}
private async randomScroll(page: Page) { private async randomScroll(page: Page) {
try { try {
const viewportHeight = await page.evaluate(() => window.innerHeight) const viewportHeight = await page.evaluate(() => window.innerHeight)

View File

@@ -134,5 +134,156 @@
"Japan time", "Japan time",
"New York time" "New York time"
] ]
},
{
"title": "Maisons près de chez vous",
"queries": [
"Maisons près de chez moi"
]
},
{
"title": "Vous ressentez des symptômes ?",
"queries": [
"Éruption cutanée sur l'avant-bras",
"Nez bouché",
"Toux chatouilleuse"
]
},
{
"title": "Faites vos achats plus vite",
"queries": [
"Acheter une PS5",
"Acheter une Xbox",
"Offres sur les chaises"
]
},
{
"title": "Traduisez tout !",
"queries": [
"Traduction bienvenue à la maison en coréen",
"Traduction bienvenue à la maison en japonais",
"Traduction au revoir en japonais"
]
},
{
"title": "Rechercher paroles de chanson",
"queries": [
"Paroles de Debarge rhythm of the night"
]
},
{
"title": "Et si nous regardions ce film une nouvelle fois?",
"queries": [
"Alien film",
"Film Aliens",
"Film Alien 3",
"Film Predator"
]
},
{
"title": "Planifiez une petite escapade",
"queries": [
"Vols Amsterdam-Tokyo",
"Vols New York-Tokyo"
]
},
{
"title": "Consulter postes à pourvoir",
"queries": [
"emplois chez Microsoft",
"Offres d'emploi Microsoft",
"Emplois près de chez moi",
"emplois chez Boeing"
]
},
{
"title": "Vous pouvez suivre votre colis",
"queries": [
"Suivi Chronopost"
]
},
{
"title": "Trouver un endroit à découvrir",
"queries": [
"Itinéraire vers Berlin",
"Itinéraire vers Tokyo",
"Itinéraire vers New York"
]
},
{
"title": "Trop fatigué pour cuisiner ce soir ?",
"queries": [
"KFC près de chez moi",
"Burger King près de chez moi",
"McDonalds près de chez moi"
]
},
{
"title": "Convertissez rapidement votre argent",
"queries": [
"convertir 250 EUR en yen",
"convertir 500 EUR en yen"
]
},
{
"title": "Apprenez à cuisiner une nouvelle recette",
"queries": [
"Comment faire cuire la ratatouille",
"Comment faire cuire les lasagnes"
]
},
{
"title": "Trouvez des emplacements pour rester!",
"queries": [
"Hôtels Berlin Allemagne",
"Hôtels Amsterdam Pays-Bas"
]
},
{
"title": "Comment se porte l'économie ?",
"queries": [
"CAC 40"
]
},
{
"title": "Qui a gagné ?",
"queries": [
"score du Paris Saint-Germain"
]
},
{
"title": "Temps de jeu",
"queries": [
"Jeu vidéo Overwatch",
"Jeu vidéo Call of Duty"
]
},
{
"title": "Enrichissez votre vocabulaire",
"queries": [
"definition definition"
]
},
{
"title": "Quelle heure est-il ?",
"queries": [
"Heure du Japon",
"Heure de New York"
]
},
{
"title": "Vérifier la météo",
"queries": [
"Météo de Paris",
"Météo de la France"
]
},
{
"title": "Tenez-vous informé des sujets d'actualité",
"queries": [
"Augmentation Impots",
"Mort célébrité"
]
} }
] ]

View File

@@ -5,13 +5,15 @@ export interface Config {
parallel: boolean; parallel: boolean;
runOnZeroPoints: boolean; runOnZeroPoints: boolean;
clusters: number; clusters: number;
workers: Workers; saveFingerprint: ConfigSaveFingerprint;
workers: ConfigWorkers;
searchOnBingLocalQueries: boolean; searchOnBingLocalQueries: boolean;
globalTimeout: number | string; globalTimeout: number | string;
searchSettings: SearchSettings; searchSettings: ConfigSearchSettings;
webhook: Webhook;
logExcludeFunc: string[]; logExcludeFunc: string[];
saveFingerprint: ConfigSaveFingerprint; webhookLogExcludeFunc: string[];
proxy: ConfigProxy;
webhook: ConfigWebhook;
} }
export interface ConfigSaveFingerprint { export interface ConfigSaveFingerprint {
@@ -19,25 +21,30 @@ export interface ConfigSaveFingerprint {
desktop: boolean; desktop: boolean;
} }
export interface SearchSettings { export interface ConfigSearchSettings {
useGeoLocaleQueries: boolean; useGeoLocaleQueries: boolean;
scrollRandomResults: boolean; scrollRandomResults: boolean;
clickRandomResults: boolean; clickRandomResults: boolean;
searchDelay: SearchDelay; searchDelay: ConfigSearchDelay;
retryMobileSearchAmount: number; retryMobileSearchAmount: number;
} }
export interface SearchDelay { export interface ConfigSearchDelay {
min: number | string; min: number | string;
max: number | string; max: number | string;
} }
export interface Webhook { export interface ConfigWebhook {
enabled: boolean; enabled: boolean;
url: string; url: string;
} }
export interface Workers { export interface ConfigProxy {
proxyGoogleTrends: boolean;
proxyBingTerms: boolean;
}
export interface ConfigWorkers {
doDailySet: boolean; doDailySet: boolean;
doMorePromotions: boolean; doMorePromotions: boolean;
doPunchCards: boolean; doPunchCards: boolean;

View File

@@ -28,8 +28,5 @@ sleep $SLEEPTIME
# Log the start of the script # Log the start of the script
echo "Starting script..." echo "Starting script..."
# Update config with environment variables before running the script
node src/updateConfig.js
# Execute the Node.js script directly # Execute the Node.js script directly
npm run start npm run start

View File

@@ -36,7 +36,12 @@ class AxiosClient {
} }
// Generic method to make any Axios request // Generic method to make any Axios request
public async request(config: AxiosRequestConfig): Promise<AxiosResponse> { public async request(config: AxiosRequestConfig, bypassProxy = false): Promise<AxiosResponse> {
if (bypassProxy) {
const bypassInstance = axios.create()
return bypassInstance.request(config)
}
return this.instance.request(config) return this.instance.request(config)
} }
} }

View File

@@ -19,7 +19,9 @@ export function log(isMobile: boolean | 'main', title: string, message: string,
const cleanStr = `[${currentTime}] [PID: ${process.pid}] [${type.toUpperCase()}] ${platformText} [${title}] ${message}` const cleanStr = `[${currentTime}] [PID: ${process.pid}] [${type.toUpperCase()}] ${platformText} [${title}] ${message}`
// Send the clean string to the Webhook // Send the clean string to the Webhook
Webhook(configData, cleanStr) if (!configData.webhookLogExcludeFunc.some(x => x.toLowerCase() === title.toLowerCase())) {
Webhook(configData, cleanStr)
}
// Formatted string with chalk for terminal logging // Formatted string with chalk for terminal logging
const str = `[${currentTime}] [PID: ${process.pid}] [${type.toUpperCase()}] ${chalkedPlatform} [${title}] ${message}` const str = `[${currentTime}] [PID: ${process.pid}] [${type.toUpperCase()}] ${chalkedPlatform} [${title}] ${message}`
@@ -40,4 +42,4 @@ export function log(isMobile: boolean | 'main', title: string, message: string,
applyChalk ? console.log(applyChalk(str)) : console.log(str) applyChalk ? console.log(applyChalk(str)) : console.log(str)
break break
} }
} }