Commit ba8c7d86 authored by nanahira's avatar nanahira

next generation?

parent ed18056f
FROM node:buster-slim FROM node:buster-slim
RUN apt update && apt -y install python3 build-essential && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* RUN apt update && apt -y install python3 build-essential proxychains4 && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY ./package*.json ./ COPY ./package*.json ./
RUN npm ci RUN npm ci
COPY . ./ COPY . ./
RUN npm run build RUN npm run build
ENV USERNAME Irrlicht ENV USERNAME Ayane
CMD ["./run.sh"] CMD ["./run.sh"]
import { exec } from "child_process";
import { promises as fs } from "fs";
import { render } from "mustache";
import { cpus, tmpdir } from "os";
import { promisify } from "util";
import timeout from "p-timeout";
import { ProxyFetcher } from "./proxy";
import _ from "lodash";
import axios from "axios";
const execAsync = promisify(exec);
const targetUsername = process.argv[2];
let proxychainsTemplate: string;
//const processMax = cpus().length;
const processMax = 200;
const maxMs = 60000;
async function runWithProxy(proxyHost: string, proxyPort: number) {
console.error(`${proxyHost}:${proxyPort} START`);
try { // test it first
await axios.get('http://mirrors.aliyun.com', {
timeout: 5000,
responseType: "arraybuffer",
proxy: {
host: proxyHost,
port: proxyPort
},
validateStatus: () => true
});
} catch (e) {
console.error(`${proxyHost}:${proxyPort} BAD => ${e.toString()}`);
return false;
}
const proxyChainsFile = `${tmpdir()}/proxychains-${proxyHost}_${proxyPort}.conf`;
await fs.writeFile(proxyChainsFile, render(proxychainsTemplate, { host: proxyHost, port: proxyPort }));
try {
console.error(`${proxyHost}:${proxyPort} CONNECT`);
const { stdout, stderr } = await timeout(execAsync(`proxychains -f ${proxyChainsFile} node build/run.js ${targetUsername}`), maxMs);
console.error(`${proxyHost}:${proxyPort} SUCCESS => ${stdout}`);
return true;
} catch (e) {
console.error(`${proxyHost}:${proxyPort} FAIL => ${e.stdout || e.toString()}`);
return false;
}
}
async function mainLoop() {
const proxyLauncher = new ProxyFetcher({
proxySource: ["http://www.89ip.cn/tqdl.html?api=1&num=9999", "http://www.66ip.cn/mo.php?tqsl=9999"],
useProxy: true,
timeout: maxMs
});
while (true) {
if (proxyLauncher.proxies.length < processMax) {
console.log(`Loading Proxies.`);
await proxyLauncher.initProxies();
}
await Promise.all(_.range(processMax).map(async () => {
const { proxyIndex, proxy } = proxyLauncher.pickProxy();
for (let i = 0; i < 3; ++i) {
const result = await runWithProxy(proxy.host, proxy.port);
if (!result) {
proxyLauncher.proxies.splice(proxyIndex, 1);
break;
}
}
}));
}
}
async function main() {
proxychainsTemplate = await fs.readFile("./proxychains4.conf.mustache", "utf-8");
await mainLoop();
}
main();
...@@ -40,6 +40,16 @@ ...@@ -40,6 +40,16 @@
"fastq": "^1.6.0" "fastq": "^1.6.0"
} }
}, },
"@types/lodash": {
"version": "4.14.167",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz",
"integrity": "sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw=="
},
"@types/mustache": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.1.0.tgz",
"integrity": "sha512-dj4gq0BwsONZw/jqEf1qDBkAhAdBfIb7K+RDEQQvGfd6uTkfzKNxjz6NCeg50bveU0ydi8DruGp/9+FgIxli5w=="
},
"@types/node": { "@types/node": {
"version": "14.14.20", "version": "14.14.20",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.20.tgz",
...@@ -67,6 +77,32 @@ ...@@ -67,6 +77,32 @@
"requires": { "requires": {
"@xboxreplay/errors": "^0.1.0", "@xboxreplay/errors": "^0.1.0",
"axios": "^0.19.2" "axios": "^0.19.2"
},
"dependencies": {
"axios": {
"version": "0.19.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==",
"requires": {
"follow-redirects": "1.5.10"
}
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"requires": {
"debug": "=3.1.0"
}
}
} }
}, },
"aes-js": { "aes-js": {
...@@ -129,11 +165,11 @@ ...@@ -129,11 +165,11 @@
"integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA=="
}, },
"axios": { "axios": {
"version": "0.19.2", "version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": { "requires": {
"follow-redirects": "1.5.10" "follow-redirects": "^1.10.0"
} }
}, },
"bcrypt-pbkdf": { "bcrypt-pbkdf": {
...@@ -367,22 +403,9 @@ ...@@ -367,22 +403,9 @@
} }
}, },
"follow-redirects": { "follow-redirects": {
"version": "1.5.10", "version": "1.13.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", "integrity": "sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg=="
"requires": {
"debug": "=3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"requires": {
"ms": "2.0.0"
}
}
}
}, },
"forever-agent": { "forever-agent": {
"version": "0.6.1", "version": "0.6.1",
...@@ -631,6 +654,11 @@ ...@@ -631,6 +654,11 @@
"type-check": "~0.3.2" "type-check": "~0.3.2"
} }
}, },
"lodash": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
},
"lodash.get": { "lodash.get": {
"version": "4.4.2", "version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
...@@ -805,6 +833,11 @@ ...@@ -805,6 +833,11 @@
} }
} }
}, },
"mustache": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.1.0.tgz",
"integrity": "sha512-0FsgP/WVq4mKyjolIyX+Z9Bd+3WS8GOwoUTyKXT5cTYMGeauNTi2HPCwERqseC1IHAy0Z7MDZnJBfjabd4O8GQ=="
},
"nearley": { "nearley": {
"version": "2.20.1", "version": "2.20.1",
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
...@@ -857,6 +890,11 @@ ...@@ -857,6 +890,11 @@
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz", "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-3.0.0.tgz",
"integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==" "integrity": "sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ=="
}, },
"p-timeout": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw=="
},
"path-parse": { "path-parse": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
......
...@@ -22,10 +22,16 @@ ...@@ -22,10 +22,16 @@
"author": "Nanahira", "author": "Nanahira",
"license": "AGPL-3.0", "license": "AGPL-3.0",
"dependencies": { "dependencies": {
"@types/lodash": "^4.14.167",
"@types/mustache": "^4.1.0",
"@types/node": "^14.14.20", "@types/node": "^14.14.20",
"@types/q": "^1.5.4", "@types/q": "^1.5.4",
"@types/underscore": "^1.10.24", "@types/underscore": "^1.10.24",
"axios": "^0.21.1",
"lodash": "^4.17.20",
"mineflayer": "^2.40.1", "mineflayer": "^2.40.1",
"mustache": "^4.1.0",
"p-timeout": "^4.1.0",
"pkg": "^4.4.9", "pkg": "^4.4.9",
"q": "^1.5.1", "q": "^1.5.1",
"typescript": "^4.1.3", "typescript": "^4.1.3",
......
import axios, { AxiosProxyConfig, AxiosRequestConfig } from "axios";
//const proxySourceList = [
// "http://www.89ip.cn/tqdl.html?api=1&num=9999", "http://www.66ip.cn/mo.php?tqsl=9999"
//]
//for (let i = 1; i <= 2000; ++i) {
// proxySourceList.push(`http://www.xiladaili.com/http/${i}`);
//}
export interface ProxyConfig {
useProxy: boolean,
proxySource: string[],
timeout: number
}
const agentList = [
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
]
async function testProxy(proxy: AxiosProxyConfig) {
await axios.get("http://mirrors.aliyun.com/debian/pool", {
proxy,
headers: {
"User-Agent": agentList[4]
},
timeout: this.config.timeout,
});
return proxy;
}
async function checkProxy(proxy: AxiosProxyConfig) {
let isProxyUsable = false;
try {
await testProxy(proxy);
//console.log(`Proxy ${proxy.host} is ok.`);
isProxyUsable = true;
} catch (e) {
//console.error(`Proxy ${proxy.host} is broken: ${e.toString()}`);
}
return isProxyUsable;
}
async function filterProxies(proxies: AxiosProxyConfig[]) {
const proxiesUsableList = await Promise.all(proxies.map(checkProxy));
return proxies.filter((proxy, index) => {
return proxiesUsableList[index];
});
}
//async function findFirstUsableProxy(proxies: AxiosProxyConfig[]) {
// return [await Promise.any(proxies.map(testProxy))];
//}
export class ProxyFetcher {
proxies: AxiosProxyConfig[];
counter: number;
config: ProxyConfig;
constructor(config: ProxyConfig) {
this.config = config;
this.proxies = [];
this.counter = 0;
}
async initProxiesFrom(url: string) {
if (!this.config.useProxy) {
return;
}
console.log(`Fetching proxies from ${url}.`)
while (true) {
try {
const proxyPage: string = (await axios.get(url, {
responseType: "document",
})).data;
const proxies: AxiosProxyConfig[] = proxyPage.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5}/g).map(proxyString => {
const [host, _port] = proxyString.split(":");
const port = parseInt(_port);
const proxy = { host, port };
return proxy;
});
//const usableProxies = await filterProxies(proxies);
for (let proxy of proxies) {
this.proxies.push(proxy);
}
console.error(`Got ${proxies.length} proxies from ${url}.`);
return;
} catch (e) {
console.error(`Failed fetching proxy list from ${url}: ${e.toString()}`)
}
}
}
async initProxies() {
await Promise.all(this.config.proxySource.map((m) => {
return this.initProxiesFrom(m);
}));
}
pickProxy() {
const proxyIndex = !this.config.useProxy ? null : (++this.counter) % this.proxies.length;
//const proxyIndex = 0;
const proxy = !this.config.useProxy ? null : this.proxies[proxyIndex];
return {proxyIndex, proxy};
}
async getWithProxy(url: string, options: AxiosRequestConfig) {
while (true) {
if (this.config.useProxy && !this.proxies.length) {
await this.initProxies();
}
const {proxyIndex, proxy} = this.pickProxy();
try {
const data = (await axios.get(url, {
proxy,
headers: {
"User-Agent": agentList[this.counter % agentList.length]
},
timeout: this.config.timeout,
...options
})).data;
return data;
} catch (e) {
if (this.config.useProxy) {
this.proxies.splice(proxyIndex, 1);
}
console.error(`Failed fetching data from ${url}: ${e.toString()} ${this.proxies.length} proxies left.`)
}
}
}
}
strict_chain
# proxy_dns
remote_dns_subnet 224
tcp_read_time_out 30000
tcp_connect_time_out 15000
localnet 10.0.0.0/255.0.0.0
localnet 172.16.0.0/255.240.0.0
localnet 192.168.0.0/255.255.0.0
[ProxyList]
http {{host}} {{port}}
...@@ -2,6 +2,8 @@ import { Bot, ChatMessage, createBot } from "mineflayer"; ...@@ -2,6 +2,8 @@ import { Bot, ChatMessage, createBot } from "mineflayer";
import crypto from "crypto"; import crypto from "crypto";
import { delay } from "q"; import { delay } from "q";
let exitCode = 1;
const messageWaitForRegister = '请输入“/register <密码> <再输入一次以确定密码>”以注册'; const messageWaitForRegister = '请输入“/register <密码> <再输入一次以确定密码>”以注册';
const messageWaitForLogin = '请输入“/login <密码>”以登录'; const messageWaitForLogin = '请输入“/login <密码>”以登录';
const messageRegisterFailed = [ const messageRegisterFailed = [
...@@ -43,7 +45,7 @@ async function runOnce(targetUser: string) { ...@@ -43,7 +45,7 @@ async function runOnce(targetUser: string) {
const username = randomString(10); const username = randomString(10);
const password = randomString(8); const password = randomString(8);
const messageWaitQueue: MessageQueueMap = new Map(); const messageWaitQueue: MessageQueueMap = new Map();
console.log(`Creating bot ${username} ${password}.`); console.error(`Creating bot ${username} ${password}.`);
const bot = createBot({ const bot = createBot({
username, username,
host: 'wolfxmc.org', host: 'wolfxmc.org',
...@@ -52,7 +54,7 @@ async function runOnce(targetUser: string) { ...@@ -52,7 +54,7 @@ async function runOnce(targetUser: string) {
bot.on('message', (message) => { bot.on('message', (message) => {
const messageLines = getChatMessageTexts(message); const messageLines = getChatMessageTexts(message);
for (let line of messageLines) { for (let line of messageLines) {
console.log(`Message: ${line}`); console.error(`Message: ${line}`);
if (line.match(/已发送到/)) { if (line.match(/已发送到/)) {
line = '_send_success'; line = '_send_success';
} }
...@@ -65,24 +67,27 @@ async function runOnce(targetUser: string) { ...@@ -65,24 +67,27 @@ async function runOnce(targetUser: string) {
}); });
bot.on('end', () => { bot.on('end', () => {
console.error(`Bot disconnected.`); console.error(`Bot disconnected.`);
process.exit(exitCode);
}); });
//await waitBotLogin(bot); //await waitBotLogin(bot);
//await delay(1000); //await delay(1000);
try { try {
console.log(`Waiting for connect.`); console.error(`Waiting for connect.`);
await waitForMessage(messageWaitQueue, messageWaitForRegister, [messageWaitForLogin]); await waitForMessage(messageWaitQueue, messageWaitForRegister, [messageWaitForLogin]);
console.log(`Registering.`); console.error(`Registering.`);
bot.chat(`/reg ${password} ${password}`); bot.chat(`/reg ${password} ${password}`);
await waitForMessage(messageWaitQueue, messageLoggedIn, messageRegisterFailed); await waitForMessage(messageWaitQueue, messageLoggedIn, messageRegisterFailed);
console.log(`Paying 1000 to ${targetUser}.`); console.error(`Paying 1000 to ${targetUser}.`);
bot.chat(`/pay ${targetUser} 1000`); bot.chat(`/pay ${targetUser} 1000`);
await waitForMessage(messageWaitQueue, '_send_success'); await waitForMessage(messageWaitQueue, '_send_success');
console.log(`Success.`); console.log(`Success.`);
exitCode = 0;
} catch (e) { } catch (e) {
console.error(`Failed: ${e.toString()}`); console.log(`Failed: ${e.toString()}`);
exitCode = 2;
} finally { } finally {
bot.end(); bot.end();
console.log(`Finished.`); console.error(`Finished.`);
} }
} }
runOnce(process.argv[2]); runOnce(process.argv[2]);
...@@ -4,4 +4,4 @@ services: ...@@ -4,4 +4,4 @@ services:
image: ccr.ccs.tencentyun.com/nanahira/wolfx:latest image: ccr.ccs.tencentyun.com/nanahira/wolfx:latest
scale: 5 scale: 5
environment: environment:
USERNAME: irrlicht USERNAME: Ayane
...@@ -4,4 +4,4 @@ services: ...@@ -4,4 +4,4 @@ services:
image: nanahira/wolfx-money image: nanahira/wolfx-money
scale: 5 scale: 5
environment: environment:
USERNAME: Irrlicht USERNAME: Ayane
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment