Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d7e620c1a7 | |||
| 5fbb891245 | |||
| 6d53970dba | |||
| 20f0f09e31 | |||
| c77f90e951 | |||
| fadb558f75 | |||
| c5e10a8592 |
@@ -1,7 +0,0 @@
|
|||||||
RETRIES=3
|
|
||||||
BOT_BROWSER='uc'
|
|
||||||
REPORT_WEBHOOK=''
|
|
||||||
BOT_CONSOLE_WEBHOOK=''
|
|
||||||
BOT_CONSOLE_WEBHOOK_NAME='Microsoft Rewards Bot'
|
|
||||||
MANAGER_WEBHOOK=''
|
|
||||||
MANAGER_WEBHOOK_NAME='Microsoft Rewards Bot Manager'
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2021,
|
|
||||||
"sourceType": "module",
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"jsx": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"arrow-spacing": ["warn", { "before": true, "after": true }],
|
|
||||||
"brace-style": ["error", "stroustrup", { "allowSingleLine": true }],
|
|
||||||
"comma-dangle": ["error", "always-multiline"],
|
|
||||||
"comma-spacing": "error",
|
|
||||||
"comma-style": "error",
|
|
||||||
"curly": ["error", "multi-line", "consistent"],
|
|
||||||
"dot-location": ["error", "property"],
|
|
||||||
"handle-callback-err": "off",
|
|
||||||
"indent": ["error", "tab"],
|
|
||||||
"keyword-spacing": "error",
|
|
||||||
"max-nested-callbacks": ["error", { "max": 4 }],
|
|
||||||
"max-statements-per-line": ["error", { "max": 2 }],
|
|
||||||
"no-console": "off",
|
|
||||||
"no-empty-function": "error",
|
|
||||||
"no-floating-decimal": "error",
|
|
||||||
"no-inline-comments": "error",
|
|
||||||
"no-lonely-if": "error",
|
|
||||||
"no-multi-spaces": "error",
|
|
||||||
"no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1, "maxBOF": 0 }],
|
|
||||||
"no-shadow": ["error", { "allow": ["err", "resolve", "reject"] }],
|
|
||||||
"no-trailing-spaces": ["error"],
|
|
||||||
"no-var": "error",
|
|
||||||
"object-curly-spacing": ["error", "always"],
|
|
||||||
"prefer-const": "error",
|
|
||||||
"quotes": ["error", "single"],
|
|
||||||
"semi": ["error", "always"],
|
|
||||||
"space-before-blocks": "error",
|
|
||||||
"space-before-function-paren": ["error", {
|
|
||||||
"anonymous": "never",
|
|
||||||
"named": "never",
|
|
||||||
"asyncArrow": "always"
|
|
||||||
}],
|
|
||||||
"space-in-parens": "error",
|
|
||||||
"space-infix-ops": "error",
|
|
||||||
"space-unary-ops": "error",
|
|
||||||
"spaced-comment": "error",
|
|
||||||
"yoda": "error"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,6 +1,3 @@
|
|||||||
vpn/
|
vpn/
|
||||||
accounts/
|
|
||||||
Microsoft-Rewards-bot/
|
Microsoft-Rewards-bot/
|
||||||
node_modules/
|
config.txt
|
||||||
.env
|
|
||||||
batch_logs.json
|
|
||||||
16
README.md
16
README.md
@@ -17,8 +17,8 @@ This repo contains the script to manage multiple mcr bot on a single VM/Containe
|
|||||||
│ ├── name2.json
|
│ ├── name2.json
|
||||||
│ ├── ...
|
│ ├── ...
|
||||||
├── vpn
|
├── vpn
|
||||||
│ ├── name1.ovpn
|
│ ├── vpnname1.ovpn
|
||||||
│ ├── name2.ovpn
|
│ ├── vpnname2.ovpn
|
||||||
│ ├── ...
|
│ ├── ...
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -27,10 +27,10 @@ This repo contains the script to manage multiple mcr bot on a single VM/Containe
|
|||||||
Start the setup script with either curl, wget or by pasting script content to your terminal.
|
Start the setup script with either curl, wget or by pasting script content to your terminal.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
curl -sSL https://git.justw.tf/Lightemerald/mcr-bot/raw/branch/main/setup-linux.sh | bash
|
curl -sSL https://git.justw.tf/Lightemerald/mcr-bot/raw/branch/legacy/setup-linux.sh | bash
|
||||||
```
|
```
|
||||||
```bash
|
```bash
|
||||||
wget -O- https://git.justw.tf/Lightemerald/mcr-bot/raw/branch/main/setup-linux.sh | bash
|
wget -O- https://git.justw.tf/Lightemerald/mcr-bot/raw/branch/legacy/setup-linux.sh | bash
|
||||||
```
|
```
|
||||||
|
|
||||||
Add your VPN files (.ovpn) to `./vpn` then run
|
Add your VPN files (.ovpn) to `./vpn` then run
|
||||||
@@ -42,13 +42,7 @@ bash setup-vpn.sh
|
|||||||
Copy your accounts file named as [vpnname].json in the Bot folder then run
|
Copy your accounts file named as [vpnname].json in the Bot folder then run
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
node main --all
|
bash start.sh
|
||||||
```
|
|
||||||
|
|
||||||
For single run of a specific VPN/Account file
|
|
||||||
|
|
||||||
```bash
|
|
||||||
node main --accounts [name]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### If using LXC
|
### If using LXC
|
||||||
|
|||||||
5
config.txt.sample
Normal file
5
config.txt.sample
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
interval=300
|
||||||
|
schedule=("01:00" "03:15" "05:30" "07:45" "10:00" "12:15" "14:30" "16:45" "19:00" "21:15")
|
||||||
|
retries=3
|
||||||
|
webhook=''
|
||||||
|
print_log_to_webhook=0
|
||||||
@@ -37,21 +37,21 @@ if [[ -z $CTID || -z $CONTAINER_NAME || -z $DISTRO || -z $ROOTPASS ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
template=$(pveam available | grep "$DISTRO" | sort -rV | head -n 1 | awk '{print $2}')
|
template=$(pveam available | grep $DISTRO | sort -rV | head -n 1 | awk '{print $2}')
|
||||||
|
|
||||||
if [[ -z $template ]]; then
|
if [[ -z $template ]]; then
|
||||||
echo "$DISTRO template not found."
|
echo "$DISTRO template not found."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
template=$(pveam list local | grep "$template" | awk '{print $1}')
|
template=$(pveam list local | grep $template | awk '{print $1}')
|
||||||
if [[ -z $template ]]; then
|
if [[ -z $template ]]; then
|
||||||
echo "$DISTRO template not found. Downloading..."
|
echo "$DISTRO template not found. Downloading..."
|
||||||
pveam download local "$template"
|
pveam download local $template
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pct create "$CTID" "$template" --hostname "$CONTAINER_NAME" --memory 1024 --storage local-lvm --net0 name=eth0,bridge=vmbr0,firewall=1,ip=dhcp --unprivileged --ostype "$DISTRO" --password="$ROOTPASS"
|
pct create $CTID $template --hostname $CONTAINER_NAME --memory 1024 --storage local-lvm --net0 name=eth0,bridge=vmbr0,firewall=1,ip=dhcp --unprivileged --ostype $DISTRO --password="$ROOTPASS"
|
||||||
echo -e "lxc.cgroup.devices.allow: c 10:200 rwm\nlxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >> /etc/pve/lxc/"$CTID".conf
|
echo -e "lxc.cgroup.devices.allow: c 10:200 rwm\nlxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file" >> /etc/pve/lxc/$CTID.conf
|
||||||
pct start "$CTID"
|
pct start $CTID
|
||||||
pct status "$CTID" | grep "status: running" || sleep 10
|
pct status $CTID | grep "status: running" || sleep 10
|
||||||
echo lxc now running
|
echo lxc now running
|
||||||
324
index.js
324
index.js
@@ -1,324 +0,0 @@
|
|||||||
import { execSync, spawn } from 'child_process';
|
|
||||||
import { publicIpv4 } from 'public-ip';
|
|
||||||
import dotenv from 'dotenv';
|
|
||||||
import fs from 'fs';
|
|
||||||
import os from 'os';
|
|
||||||
|
|
||||||
const host = os.hostname();
|
|
||||||
const args = process.argv.slice(2);
|
|
||||||
|
|
||||||
const reportWebhook = process.env.REPORT_WEBHOOK;
|
|
||||||
const botConsoleWebhook = process.env.BOT_CONSOLE_WEBHOOK;
|
|
||||||
const botConsoleWebhookName = process.env.BOT_CONSOLE_WEBHOOK_NAME || 'Microsoft Rewards Bot';
|
|
||||||
const managerWebhook = process.env.MANAGER_WEBHOOK;
|
|
||||||
const managerWebhookName = process.env.MANAGER_WEBHOOK_NAME || 'Microsoft Rewards Bot Manager';
|
|
||||||
|
|
||||||
async function logManager(message, type) {
|
|
||||||
if (type === 'info') console.log(`\x1b[34m${message}\x1b[0m`);
|
|
||||||
else if (type === 'error') console.log(`\x1b[31m${message}\x1b[0m`);
|
|
||||||
else console.log(`\x1b[37m${message}\x1b[0m`);
|
|
||||||
|
|
||||||
if (managerWebhook) {
|
|
||||||
const payload = {
|
|
||||||
content: message,
|
|
||||||
username: managerWebhookName,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
await fetch(managerWebhook, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(`[${host}] Error sending webhook message: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function logBotConsole(message) {
|
|
||||||
console.log(message);
|
|
||||||
|
|
||||||
if (botConsoleWebhook) {
|
|
||||||
const payload = {
|
|
||||||
content: message,
|
|
||||||
username: botConsoleWebhookName,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
await fetch(botConsoleWebhook, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
console.error(`[${host}] Error sending webhook message: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function checkUpdate() {
|
|
||||||
try {
|
|
||||||
execSync('git fetch');
|
|
||||||
const currentHead = execSync('git rev-parse HEAD').toString().trim();
|
|
||||||
const remoteHead = execSync('git rev-parse "@{u}"').toString().trim();
|
|
||||||
if (currentHead !== remoteHead) {
|
|
||||||
logManager(`[${host}] Updates available! Please run the updater script.`, 'info');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
logManager('[${host}] Failed to check for updates.', 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function vpnConnect(vpnName) {
|
|
||||||
if (!vpnName) return logManager(`[${host}] Please provide the VPN name as an argument.`, 'error');
|
|
||||||
|
|
||||||
logManager(`[${host}] Disconnecting from VPNs`, 'info');
|
|
||||||
await vpnDisconnect();
|
|
||||||
|
|
||||||
const maxAttempts = process.env.RETRIES;
|
|
||||||
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
||||||
await execSync(`nmcli connection up "${vpnName}"`);
|
|
||||||
|
|
||||||
const status = await execSync('nmcli connection show --active').toString().includes(vpnName);
|
|
||||||
if (!status) {
|
|
||||||
logManager(`[${host}] Failed to connect to VPN: ${vpnName}. Retrying (attempt ${attempt} of ${maxAttempts})...`, 'error');
|
|
||||||
await sleep(1000);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
await logManager(`[${host}] VPN connection successfully established to ${vpnName} (IP: ${await publicIpv4() || 'Unknown'}).`, 'info');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logManager(`[${host}] Maximum number of connection attempts reached. Failed to connect to VPN: ${vpnName}`, 'error');
|
|
||||||
await vpnDisconnect();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function vpnDisconnect() {
|
|
||||||
const vpnConnection = execSync('nmcli connection show --active | awk \'/vpn/ {print $1}\'').toString().trim();
|
|
||||||
if (!vpnConnection) {
|
|
||||||
logManager(`[${host}] Successfully disconnected from all VPNs.`, 'info');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
execSync(`nmcli connection down "${vpnConnection}"`);
|
|
||||||
const status = execSync('nmcli connection show --active | awk \'/vpn/ {print $1}\'').toString().trim();
|
|
||||||
if (!status) {
|
|
||||||
logManager(`[${host}] Successfully disconnected from all VPNs.`, 'info');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logManager(`[${host}] Failed to disconnect from all VPNs.`, 'error');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
logManager(`[${host}] Failed to disconnect from all VPNs.`, 'error');
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function startBot(accountName) {
|
|
||||||
const accountPath = `./accounts/${accountName}.json`;
|
|
||||||
if (fs.existsSync(accountPath)) {
|
|
||||||
let commandSuffix = '';
|
|
||||||
|
|
||||||
if (reportWebhook === '1') {
|
|
||||||
commandSuffix += ` --discord ${reportWebhook}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.BOT_BROWSER) {
|
|
||||||
commandSuffix += ' --browser ' + process.env.BOT_BROWSER;
|
|
||||||
}
|
|
||||||
|
|
||||||
let commandPrefix = `python -u ./Microsoft-Rewards-bot/ms_rewards_farmer.py --accounts-file ../accounts/${accountName}.json --dont-check-for-updates --shuffle --session --superfast --on-finish exit --no-webdriver-manager --skip-unusual`;
|
|
||||||
logManager(`[${host}] Script started for ${accountName}`);
|
|
||||||
|
|
||||||
if (isRootUser()) {
|
|
||||||
const containerEnv = fs.readFileSync('/proc/1/environ', 'utf8');
|
|
||||||
const isLXCContainer = containerEnv.includes('container=lxc') || containerEnv.includes('container=lxc-libvirt');
|
|
||||||
if (isLXCContainer) commandPrefix += ' --virtual-display';
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const childProcess = spawn('bash', ['-c', `${commandPrefix} ${commandSuffix}`], { stdio: ['pipe', 'pipe', 'pipe'] });
|
|
||||||
|
|
||||||
childProcess.stdout.on('data', (data) => {
|
|
||||||
const output = data.toString().trim();
|
|
||||||
logBotConsole(`[${host}][${accountName}] STDOUT: ${output}`);
|
|
||||||
if (output.includes('Press enter') || output.includes('Press any key')) {
|
|
||||||
setTimeout(() => { childProcess.stdin.write('\n'); }, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.stderr.on('data', (data) => {
|
|
||||||
const output = data.toString().trim();
|
|
||||||
logBotConsole(`[${host}][${accountName}] STDERR: ${output}`);
|
|
||||||
if (output.includes('Press enter') || output.includes('Press any key')) {
|
|
||||||
setTimeout(() => { childProcess.stdin.write('\n'); }, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.on('exit', (code) => {
|
|
||||||
if (code !== 0) {
|
|
||||||
logManager(`[${host}] Bot process for ${accountName} exited with code ${code}. Restarting...`, 'error');
|
|
||||||
startBot(accountName).then(resolve).catch(reject);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const currentDate = new Date();
|
|
||||||
const formattedDate = `${currentDate.getDate()}-${currentDate.getMonth() + 1}-${currentDate.getFullYear()}`;
|
|
||||||
const logEntry = { accountName: accountName, date: formattedDate };
|
|
||||||
|
|
||||||
fs.readFile('batch_logs.json', 'utf8', (err, data) => {
|
|
||||||
if (err) {
|
|
||||||
logManager(`Failed to read batch_logs.json: ${err}`, 'error');
|
|
||||||
return resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
let logEntries = [];
|
|
||||||
try {
|
|
||||||
logEntries = JSON.parse(data);
|
|
||||||
}
|
|
||||||
catch (parseError) {
|
|
||||||
logManager(`Failed to parse batch_logs.json: ${parseError}`, 'error');
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingEntryIndex = logEntries.findIndex(entry => entry.accountName === accountName);
|
|
||||||
if (existingEntryIndex !== -1) logEntries[existingEntryIndex] = logEntry;
|
|
||||||
else logEntries.push(logEntry);
|
|
||||||
|
|
||||||
fs.writeFile('batch_logs.json', JSON.stringify(logEntries, null, 2), err => {
|
|
||||||
if (err) logManager(`Failed to write to batch_logs.json: ${err}`, 'error');
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.on('close', (code) => {
|
|
||||||
logManager(`[${accountName}] Bot process exited with code ${code}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
childProcess.on('error', (err) => {
|
|
||||||
logManager(`[${host}] Failed to start bot for ${accountName}.`, 'error');
|
|
||||||
reject(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
logManager(`[${host}] Bot process for ${accountName} exceeded the timeout. Killing the process...`, 'error');
|
|
||||||
childProcess.kill();
|
|
||||||
}, 150 * 60 * 1000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logManager(`[${host}] File ${accountPath} does not exist, skipping starting bot for this VPN!`, 'error');
|
|
||||||
return Promise.resolve({ error: `File ${accountPath} does not exist.` });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sleep(ms) {
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
setTimeout(resolve, ms);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function isRootUser() {
|
|
||||||
return process.getuid && process.getuid() === 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runAll() {
|
|
||||||
await checkUpdate();
|
|
||||||
const vpns = execSync('nmcli connection show | awk \'/vpn/ {print $1}\'').toString().trim().split('\n');
|
|
||||||
|
|
||||||
for (const vpn of vpns) {
|
|
||||||
const currentDate = new Date();
|
|
||||||
const formattedDate = `${currentDate.getDate()}-${currentDate.getMonth() + 1}-${currentDate.getFullYear()}`;
|
|
||||||
const logEntries = JSON.parse(fs.readFileSync('batch_logs.json', 'utf8'));
|
|
||||||
const entry = logEntries.find(entries => entries.accountName === vpn) || false;
|
|
||||||
if (entry && entry.date === formattedDate) {
|
|
||||||
logManager(`[${host}] ${vpn} already ran today!`, 'info');
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
logManager(`[${host}] Switching to VPN: [${vpn}]`, 'info');
|
|
||||||
const con = await vpnConnect(vpn);
|
|
||||||
if (con) continue;
|
|
||||||
await startBot(vpn);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function runBatch(vpn) {
|
|
||||||
logManager(`[${host}] Connecting to VPN: [${vpn}]`, 'info');
|
|
||||||
const con = await vpnConnect(vpn);
|
|
||||||
if (con) return 1;
|
|
||||||
await startBot(vpn);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
(async () => {
|
|
||||||
await checkUpdate();
|
|
||||||
if (fs.existsSync('.env')) {
|
|
||||||
dotenv.config({ path: '.env' });
|
|
||||||
logManager(`[${host}] Config file: .env.`, 'info');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logManager(`[${host}] Config file: not found.`, 'error');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
logManager(`[${host}] Bot Console Webhook: ${botConsoleWebhook ? 'True' : 'False'}\n[${host}] Bot Report Webhook: ${reportWebhook ? 'True' : 'False'}\n[${host}] Bot Manager Webhook: ${managerWebhook ? 'True' : 'False'}`);
|
|
||||||
logManager(`[${host}] Starting mcr-bot on host: ${host}`, 'info');
|
|
||||||
|
|
||||||
if (!fs.existsSync('batch_logs.json')) {
|
|
||||||
fs.writeFile('batch_logs.json', '[]', err => {
|
|
||||||
if (err) {
|
|
||||||
logManager(`Failed to create batch_logs.json: ${err}`, 'error');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const fileContent = await fs.readFile('batch_logs.json', 'utf-8');
|
|
||||||
try {
|
|
||||||
JSON.parse(fileContent);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
logManager(`[${host}] Existing log file is not in proper JSON format: ${error}`, 'error');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logManager(`[${host}] Log file: batch_logs.json`, 'info');
|
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i++) {
|
|
||||||
if (args[i].startsWith('--')) {
|
|
||||||
if (args[i] === '--accounts' && i + 1 < args.length) {
|
|
||||||
const accounts = args[i + 1];
|
|
||||||
return await runBatch(accounts);
|
|
||||||
}
|
|
||||||
else if (args[i] === '--all') {
|
|
||||||
const n = true;
|
|
||||||
while (n) {
|
|
||||||
try {
|
|
||||||
await runAll();
|
|
||||||
await sleep(1000);
|
|
||||||
}
|
|
||||||
catch (error) {
|
|
||||||
logManager(`[${host}] An error occurred: ${error.message}`, 'error');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logManager(`[${host}] Missing arguments`);
|
|
||||||
})();
|
|
||||||
2797
package-lock.json
generated
2797
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
24
package.json
24
package.json
@@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "mcr-bot",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "This repo contains the script to manage multiple mcr bot on a single VM/Container.",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
|
||||||
"start": "node index.js --all"
|
|
||||||
},
|
|
||||||
"type": "module",
|
|
||||||
"repository": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://git.justw.tf/Lightemerald/mcr-bot.git"
|
|
||||||
},
|
|
||||||
"author": "Lightemerald",
|
|
||||||
"dependencies": {
|
|
||||||
"child_process": "^1.0.2",
|
|
||||||
"dotenv": "^16.3.1",
|
|
||||||
"eslint": "^8.43.0",
|
|
||||||
"node-fetch": "^3.3.1",
|
|
||||||
"pino": "^8.14.1",
|
|
||||||
"public-ip": "^6.0.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,22 +30,21 @@ update_package_manager() {
|
|||||||
|
|
||||||
install_requirements() {
|
install_requirements() {
|
||||||
if command -v apt-get &>/dev/null; then
|
if command -v apt-get &>/dev/null; then
|
||||||
sudo apt install chromium chromium-driver network-manager network-manager-openvpn openvpn python3 python3-pip python3-tk xvfb git wget curl unzip nano nodejs -y
|
sudo apt install chromium chromium-driver network-manager network-manager-openvpn openvpn python3 python3-pip python3-tk xvfb git wget curl unzip nano -y
|
||||||
elif command -v dnf &>/dev/null; then
|
elif command -v dnf &>/dev/null; then
|
||||||
sudo dnf install chromium chrom*driver NetworkManager NetworkManager-openvpn openvpn python python*-pip python*-tkinter xorg-x11-server-Xvfb git wget unzip nano nodejs -y
|
sudo dnf install chromium chrom*driver NetworkManager NetworkManager-openvpn openvpn python python*-pip python*-tkinter xorg-x11-server-Xvfb git wget unzip nano -y
|
||||||
elif command -v pacman &>/dev/null; then
|
elif command -v pacman &>/dev/null; then
|
||||||
sudo pacman -Sy chromium networkmanager networkmanager-openvpn openvpn python python-pip xorg-server-xvfb git curl wget unzip nano base-devel nodejs --noconfirm
|
sudo pacman -Sy chromium networkmanager networkmanager-openvpn openvpn python python-pip xorg-server-xvfb git curl wget unzip nano base-devel --noconfirm
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
update_package_manager
|
update_package_manager
|
||||||
install_requirements
|
install_requirements
|
||||||
|
|
||||||
git clone https://git.justw.tf/Lightemerald/mcr-bot && cd mcr-bot
|
git clone https://git.justw.tf/Lightemerald/mcr-bot && cd mcr-bot && git checkout legacy
|
||||||
git clone https://git.justw.tf/Lightemerald/Microsoft-Rewards-bot && cd Microsoft-Rewards-bot && pip install -r requirements.txt
|
git clone https://git.justw.tf/Lightemerald/Microsoft-Rewards-bot && cd Microsoft-Rewards-bot && pip install -r requirements.txt
|
||||||
cd .. && mkdir vpn && mkdir accounts
|
cd .. && mkdir vpn
|
||||||
cp ./.env.sample .env
|
cp ./config.txt.sample config.txt
|
||||||
npm i
|
|
||||||
chmod +x ./*.sh
|
chmod +x ./*.sh
|
||||||
clear
|
clear
|
||||||
echo -e "Edit config.txt\nAdd your VPN files (.ovpn) in ./vpn\nThen run setup-vpn.sh\nAdd your accounts files (.json) with the same name as the VPN in ./accounts\nFinally, run 'npm start''"
|
echo -e "Edit config.txt\nAdd your VPN files (.ovpn) in ./vpn\nThen run setup-vpn.sh\nAdd your accounts files (.json) with the same name as the VPN in ./Microsoft-Rewards-bot\nFinally, run start.sh"
|
||||||
165
start.sh
Normal file
165
start.sh
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ "$(ps -o comm= $PPID)" != "kgx" ]
|
||||||
|
then
|
||||||
|
echo "Script is running under $(ps -o comm= $PPID)"
|
||||||
|
if command -v kgx >/dev/null; then
|
||||||
|
echo "gnome-console is already installed"
|
||||||
|
else
|
||||||
|
echo "Installing gnome-console"
|
||||||
|
if command -v dnf >/dev/null; then
|
||||||
|
sudo dnf install gnome-console -y
|
||||||
|
elif command -v apt-get >/dev/null; then
|
||||||
|
sudo apt-get install kgx -y
|
||||||
|
elif command -v pacman >/dev/null; then
|
||||||
|
sudo pacman -Sy gnome-console --noconfirm
|
||||||
|
else
|
||||||
|
echo "Unsupported package manager, install gnome console (kgx) on your own."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Restarting script in gnome-console..."
|
||||||
|
if grep -q "container=lxc" /proc/1/environ || grep -q "container=lxc-libvirt" /proc/1/environ; then
|
||||||
|
Xvfb :1 -screen 0 1024x768x16 &
|
||||||
|
DISPLAY=:1.0 kgx -e "/bin/bash -c 'cd $(dirname "$(readlink -f "$0")"); ./$(basename "$0")'" &
|
||||||
|
else
|
||||||
|
kgx -e "/bin/bash -c 'cd $(dirname "$(readlink -f "$0")"); ./$(basename "$0")'" &
|
||||||
|
fi
|
||||||
|
|
||||||
|
read -t 2
|
||||||
|
pkill -f "gnome-terminal"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
function send_webhook() {
|
||||||
|
local message="$1"
|
||||||
|
if [ -z "$webhook" ]; then
|
||||||
|
echo "$message"
|
||||||
|
else
|
||||||
|
echo "$message"
|
||||||
|
curl --silent -i -H "Accept: application/json" -H "Content-Type:application/json" -X POST --data "{\"content\": \"$message\", \"username\": \"Microsoft Rewards Bot Manager\"}" "$webhook"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
vpns=$(nmcli connection show | grep vpn | awk '{print $1}')
|
||||||
|
host=$(hostname -f)
|
||||||
|
|
||||||
|
config_file="config.txt"
|
||||||
|
if [ -f "$config_file" ]; then
|
||||||
|
source "$config_file"
|
||||||
|
else
|
||||||
|
echo "Config file not found."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$webhook" ]; then
|
||||||
|
echo "Webhook not set! Updates won't be sent to it"
|
||||||
|
else
|
||||||
|
echo "Webhook set!"
|
||||||
|
send_webhook "Starting mcr-bot on host: $host"
|
||||||
|
fi
|
||||||
|
|
||||||
|
while true
|
||||||
|
do
|
||||||
|
current_time=$(date +%H:%M)
|
||||||
|
next_index=-1
|
||||||
|
for i in "${!schedule[@]}"
|
||||||
|
do
|
||||||
|
if [[ "$current_time" < "${schedule[$i]}" ]]
|
||||||
|
then
|
||||||
|
next_index=$i
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $next_index -eq -1 ]
|
||||||
|
then
|
||||||
|
next_index=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
next_time="${schedule[$next_index]}"
|
||||||
|
|
||||||
|
if [[ "$current_time" > "${schedule[$next_index]}" ]]
|
||||||
|
then
|
||||||
|
next_seconds=$(($(date -d "$next_time +1 day" +%s) - $(date +%s)))
|
||||||
|
else
|
||||||
|
next_seconds=$(($(date -d "$next_time" +%s) - $(date +%s)))
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ $next_seconds -lt 0 ]
|
||||||
|
then
|
||||||
|
send_webhook "[$host] ERROR: Schedules are not setup correctly!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
send_webhook "[$host] Next schedule: $next_time"
|
||||||
|
|
||||||
|
while [ $next_seconds -gt 0 ]
|
||||||
|
do
|
||||||
|
echo -ne "\033[0K\rWaiting for $next_time... (in $next_seconds s) "
|
||||||
|
read -t 1
|
||||||
|
next_seconds=$(( $next_seconds - 1 ))
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
next_vpn_index=$(( $next_index + 1 ))
|
||||||
|
vpn=$(echo "$vpns" | sed -n "${next_vpn_index}p")
|
||||||
|
send_webhook "[$host] Switching to VPN: [$next_vpn_index] - $vpn"
|
||||||
|
|
||||||
|
if [ "$vpn" != "" ]
|
||||||
|
then
|
||||||
|
send_webhook "[$host] Killing potential previous bot..."
|
||||||
|
pkill -f "gnome-terminal"
|
||||||
|
send_webhook "[$host] Switching VPN..."
|
||||||
|
nmcli connection down $(nmcli connection show --active | grep vpn | awk '{print $1}')
|
||||||
|
attempt=1
|
||||||
|
while [ $attempt -le $retries ]
|
||||||
|
do
|
||||||
|
nmcli connection up $vpn
|
||||||
|
read -t 2
|
||||||
|
if nmcli connection show --active | grep -q $vpn
|
||||||
|
then
|
||||||
|
ip=$(curl -s https://api.ipify.org)
|
||||||
|
send_webhook "[$host] VPN connection successfully established (IP: $ip).\nStarting script..."
|
||||||
|
if [ -f "./accounts/$vpn.json" ]
|
||||||
|
then
|
||||||
|
if [ -z "$webhook" ]; then
|
||||||
|
command_suffix="--accounts-file $vpn.json"
|
||||||
|
else
|
||||||
|
if [[ "$print_log_to_webhook" == 1 ]]; then
|
||||||
|
command_suffix="--accounts-file ../accounts/$vpn.json --discord $webhook --print-to-webhook"
|
||||||
|
else
|
||||||
|
command_suffix="--accounts-file ../accounts/$vpn.json --discord $webhook"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if grep -q "container=lxc" /proc/1/environ || grep -q "container=lxc-libvirt" /proc/1/environ; then
|
||||||
|
command_prefix="cd Microsoft-Rewards-bot && python ms_rewards_farmer.py --dont-check-for-updates --shuffle --session --superfast --on-finish exit --no-webdriver-manager --browser uc --skip-unusual --virtual-display"
|
||||||
|
else
|
||||||
|
command_prefix="cd Microsoft-Rewards-bot && python ms_rewards_farmer.py --dont-check-for-updates --shuffle --session --superfast --on-finish exit --no-webdriver-manager --browser uc --skip-unusual"
|
||||||
|
fi
|
||||||
|
gnome-terminal -- sh -c "$command_prefix $command_suffix; exit; exec bash" &
|
||||||
|
read -t 2
|
||||||
|
send_webhook "[$host] Script started"
|
||||||
|
read -t 1
|
||||||
|
break
|
||||||
|
else
|
||||||
|
send_webhook "[$host] ERROR: File ./Microsoft-Rewards-bot/$vpn.json does not exist, skipping starting bot for this VPN"
|
||||||
|
read -t 3
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
send_webhook "[$host] ERROR: Failed to establish VPN connection (attempt $attempt of $retries)"
|
||||||
|
if [ $attempt -eq $retries ]
|
||||||
|
then
|
||||||
|
send_webhook "[$host] ERROR: Max retries reached, switching to the next schedule"
|
||||||
|
fi
|
||||||
|
read -t 1
|
||||||
|
fi
|
||||||
|
attempt=$(( $attempt + 1 ))
|
||||||
|
done
|
||||||
|
else
|
||||||
|
send_webhook "[$host] ERROR: VPN name is empty"
|
||||||
|
fi
|
||||||
|
done
|
||||||
@@ -20,10 +20,9 @@ if [ ! -d "Microsoft-Rewards-bot" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
sudo dnf up -y
|
sudo dnf up -y
|
||||||
cd Microsoft-Rewards-bot || exit
|
cd Microsoft-Rewards-bot && git fetch
|
||||||
git fetch
|
|
||||||
if [ "$(git rev-parse HEAD)" != "$(git rev-parse "@{u}")" ]; then
|
if [ "$(git rev-parse HEAD)" != "$(git rev-parse "@{u}")" ]; then
|
||||||
git stash && git pull && git checkout master && pip install -r requirements.txt
|
git stash && git pull && pip install -r requirements.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd .. && chmod +x ./*.sh
|
cd .. && chmod +x ./*.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user