Commit eb73da32 authored by nanahira's avatar nanahira

rework

parent ba8c7d86
......@@ -113,3 +113,4 @@ Dockerfile
/config.yaml
.idea
stack
/dict.txt
......@@ -107,3 +107,4 @@ dist
/output
/config.yaml
.idea
/dict.txt
export const messageWaitForRegister = '请输入“/register <密码> <再输入一次以确定密码>”以注册';
export const messageWaitForLogin = '请输入“/login <密码>”以登录';
export const messageRegisterFailed = [
'当前IP注册量达到上限,如果是校园网玩家请联系服主解决!',
'此用户名还未注册过'
];
export const messageLoginFailed = [
'错误的密码'
];
export const messageLoggedIn = '已成功登录!';
import { Bot, ChatMessage, createBot } from "mineflayer";
import crypto from "crypto";
import { delay } from "q";
import { messageLoggedIn, messageRegisterFailed, messageWaitForLogin, messageWaitForRegister } from "./constants";
let exitCode = 1;
function randomString(len: number) {
return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len);
};
function getChatMessageTexts(rawMessage: ChatMessage): string[] {
const messageObjects = (rawMessage.json as any).extra as any[];
if (!messageObjects) {
return [];
}
return messageObjects.map(messageObject => messageObject.text as string);
}
type MessageQueueMap = Map<string, (message: string) => void>;
function waitForMessage(messageWaitQueue: MessageQueueMap, messageToResolve: string, messagesToReject?: string[]): Promise<string> {
return new Promise((resolve, reject) => {
messageWaitQueue.set(messageToResolve, (message: string) => {
resolve(message);
});
if (messagesToReject) {
for (let messageToReject of messagesToReject) {
messageWaitQueue.set(messageToReject, (message: string) => {
reject(message);
});
}
}
});
}
async function runOnce(targetUser: string) {
const username = randomString(10);
const password = randomString(8);
const messageWaitQueue: MessageQueueMap = new Map();
console.error(`Creating bot ${username} ${password}.`);
const bot = createBot({
username,
host: 'wolfxmc.org',
port: 25565
});
bot.on('message', (message) => {
const messageLines = getChatMessageTexts(message);
for (let line of messageLines) {
console.error(`Message: ${line}`);
if (line.match(/已发送到/)) {
line = '_send_success';
}
if (messageWaitQueue.has(line)) {
const fun = messageWaitQueue.get(line);
messageWaitQueue.delete(line);
fun(line);
}
}
});
bot.on('end', () => {
console.error(`Bot disconnected.`);
process.exit(exitCode);
});
//await waitBotLogin(bot);
//await delay(1000);
try {
console.error(`Waiting for connect.`);
await waitForMessage(messageWaitQueue, messageWaitForRegister, [messageWaitForLogin]);
console.error(`Registering.`);
bot.chat(`/reg ${password} ${password}`);
await waitForMessage(messageWaitQueue, messageLoggedIn, messageRegisterFailed);
console.error(`Paying 1000 to ${targetUser}.`);
bot.chat(`/pay ${targetUser} 1000`);
await waitForMessage(messageWaitQueue, '_send_success');
console.log(`Success.`);
exitCode = 0;
} catch (e) {
console.log(`Failed: ${e.toString()}`);
exitCode = 2;
} finally {
bot.end();
console.error(`Finished.`);
}
}
runOnce(process.argv[2]);
import { Bot, BotOptions, ChatMessage, createBot } from "mineflayer";
import Bunyan from "bunyan";
export type MessageQueueMap = Map<string, (message: string) => void>;
export interface MinecraftConfig {
}
function getChatMessageTexts(rawMessage: ChatMessage): string[] {
const messageObjects = (rawMessage.json as any).extra as any[];
if (!messageObjects) {
return [];
}
return messageObjects.map(messageObject => messageObject.text as string);
}
export class Minecraft {
options: BotOptions;
bot: Bot;
log: Bunyan;
messageWaitQueue: MessageQueueMap;
messageRejectQueue: MessageQueueMap;
spawnCallback: () => void;
disconnectCallback: (message: string) => void;
died: boolean;
resolveQueue(line: string) {
for (let queue of [this.messageWaitQueue]) {
if (this.messageWaitQueue.has(line)) {
const fun = this.messageWaitQueue.get(line);
this.messageWaitQueue.delete(line);
fun(line);
}
}
}
constructor(options: BotOptions) {
this.log = Bunyan.createLogger({ name: options.username });
this.options = options;
this.bot = createBot(options);
this.messageWaitQueue = new Map();
this.messageRejectQueue = new Map();
this.bot.once("spawn", () => {
this.log.info("connected");
if (this.spawnCallback) {
this.spawnCallback();
}
});
this.bot.once("end", () => {
this.log.info("disconnected");
if (this.disconnectCallback) {
this.disconnectCallback("disconnected");
}
this.died = true;
for (let fun of this.messageRejectQueue.values()) {
fun("disconnected");
}
this.messageRejectQueue.clear();
});
this.bot.on('message', (message) => {
const messageLines = getChatMessageTexts(message);
for (let line of messageLines) {
this.log.info(`Message: ${line}`);
if (line.match(/已发送到/)) {
line = '_send_success';
}
this.resolveQueue(line);
}
});
this.died = false;
}
waitForConnect() {
return new Promise<void>((resolve, reject) => {
this.spawnCallback = resolve;
this.disconnectCallback = reject;
});
}
waitForMessage(messageToResolve: string, messagesToReject?: string[]): Promise<string> {
return new Promise((resolve, reject) => {
this.messageWaitQueue.set(messageToResolve, (message: string) => {
this.messageRejectQueue.delete(messageToResolve);
for (let messageToReject of messagesToReject) {
this.messageWaitQueue.delete(messageToReject);
}
resolve(message);
});
this.messageRejectQueue.set(messageToResolve, (message: string) => {
reject(message);
});
if (messagesToReject) {
for (let messageToReject of messagesToReject) {
this.messageWaitQueue.set(messageToReject, (message: string) => {
this.messageWaitQueue.delete(messageToResolve);
this.messageRejectQueue.delete(messageToResolve);
for (let messageToReject2 of messagesToReject) {
this.messageWaitQueue.delete(messageToReject2);
}
reject(message);
});
}
}
});
}
}
......@@ -40,6 +40,14 @@
"fastq": "^1.6.0"
}
},
"@types/bunyan": {
"version": "1.8.6",
"resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.6.tgz",
"integrity": "sha512-YiozPOOsS6bIuz31ilYqR5SlLif4TBWsousN2aCWLi5233nZSX19tFbcQUPdR7xJ8ypPyxkCGNxg0CIV5n9qxQ==",
"requires": {
"@types/node": "*"
}
},
"@types/lodash": {
"version": "4.14.167",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz",
......@@ -172,6 +180,12 @@
"follow-redirects": "^1.10.0"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"optional": true
},
"bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
......@@ -180,6 +194,16 @@
"tweetnacl": "^0.14.3"
}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
......@@ -193,6 +217,17 @@
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
"integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74="
},
"bunyan": {
"version": "1.8.15",
"resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz",
"integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==",
"requires": {
"dtrace-provider": "~0.8",
"moment": "^2.19.3",
"mv": "~2",
"safe-json-stringify": "~1"
}
},
"byline": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz",
......@@ -243,6 +278,12 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"optional": true
},
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
......@@ -294,6 +335,15 @@
"resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
"integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo="
},
"dtrace-provider": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
"integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==",
"optional": true,
"requires": {
"nan": "^2.14.0"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
......@@ -483,6 +533,19 @@
"assert-plus": "^1.0.0"
}
},
"glob": {
"version": "6.0.4",
"resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz",
"integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=",
"optional": true,
"requires": {
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "2 || 3",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"glob-parent": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
......@@ -551,6 +614,16 @@
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz",
"integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw=="
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"optional": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
......@@ -764,6 +837,15 @@
"vec3": "^0.1.6"
}
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
......@@ -785,6 +867,12 @@
"nearley": "^2.19.5"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"optional": true
},
"moo": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz",
......@@ -838,6 +926,29 @@
"resolved": "https://registry.npmjs.org/mustache/-/mustache-4.1.0.tgz",
"integrity": "sha512-0FsgP/WVq4mKyjolIyX+Z9Bd+3WS8GOwoUTyKXT5cTYMGeauNTi2HPCwERqseC1IHAy0Z7MDZnJBfjabd4O8GQ=="
},
"mv": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz",
"integrity": "sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI=",
"optional": true,
"requires": {
"mkdirp": "~0.5.1",
"ncp": "~2.0.0",
"rimraf": "~2.4.0"
}
},
"nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
"optional": true
},
"ncp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
"optional": true
},
"nearley": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
......@@ -867,6 +978,15 @@
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"optional": true,
"requires": {
"wrappy": "1"
}
},
"optionator": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
......@@ -895,6 +1015,12 @@
"resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-4.1.0.tgz",
"integrity": "sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"optional": true
},
"path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
......@@ -1200,6 +1326,15 @@
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
},
"rimraf": {
"version": "2.4.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
"optional": true,
"requires": {
"glob": "^6.0.1"
}
},
"run-parallel": {
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz",
......@@ -1210,6 +1345,12 @@
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
},
"safe-json-stringify": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz",
"integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==",
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
......@@ -1444,6 +1585,12 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"optional": true
},
"yggdrasil": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/yggdrasil/-/yggdrasil-1.4.0.tgz",
......
......@@ -22,12 +22,14 @@
"author": "Nanahira",
"license": "AGPL-3.0",
"dependencies": {
"@types/bunyan": "^1.8.6",
"@types/lodash": "^4.14.167",
"@types/mustache": "^4.1.0",
"@types/node": "^14.14.20",
"@types/q": "^1.5.4",
"@types/underscore": "^1.10.24",
"axios": "^0.21.1",
"bunyan": "^1.8.15",
"lodash": "^4.17.20",
"mineflayer": "^2.40.1",
"mustache": "^4.1.0",
......
import { Bot, ChatMessage, createBot } from "mineflayer";
import crypto from "crypto";
import { delay } from "q";
import { messageLoggedIn, messageRegisterFailed, messageWaitForLogin, messageWaitForRegister } from "./constants";
import { Minecraft } from "./minecraft";
let exitCode = 1;
const messageWaitForRegister = '请输入“/register <密码> <再输入一次以确定密码>”以注册';
const messageWaitForLogin = '请输入“/login <密码>”以登录';
const messageRegisterFailed = [
'当前IP注册量达到上限,如果是校园网玩家请联系服主解决!',
'此用户名还未注册过'
];
const messageLoggedIn = '已成功登录!';
function randomString(len: number) {
return crypto.randomBytes(Math.ceil(len / 2)).toString('hex').slice(0, len);
};
function getChatMessageTexts(rawMessage: ChatMessage): string[] {
const messageObjects = (rawMessage.json as any).extra as any[];
if (!messageObjects) {
return [];
}
return messageObjects.map(messageObject => messageObject.text as string);
}
type MessageQueueMap = Map<string, (message: string) => void>;
function waitForMessage(messageWaitQueue: MessageQueueMap, messageToResolve: string, messagesToReject?: string[]): Promise<string> {
return new Promise((resolve, reject) => {
messageWaitQueue.set(messageToResolve, (message: string) => {
resolve(message);
});
if (messagesToReject) {
for (let messageToReject of messagesToReject) {
messageWaitQueue.set(messageToReject, (message: string) => {
reject(message);
});
}
}
});
}
async function runOnce(targetUser: string) {
const username = randomString(10);
const password = randomString(8);
const messageWaitQueue: MessageQueueMap = new Map();
console.error(`Creating bot ${username} ${password}.`);
const bot = createBot({
const mc = new Minecraft({
username,
host: 'wolfxmc.org',
port: 25565
});
bot.on('message', (message) => {
const messageLines = getChatMessageTexts(message);
for (let line of messageLines) {
console.error(`Message: ${line}`);
if (line.match(/已发送到/)) {
line = '_send_success';
}
if (messageWaitQueue.has(line)) {
const fun = messageWaitQueue.get(line);
messageWaitQueue.delete(line);
fun(line);
}
}
});
bot.on('end', () => {
console.error(`Bot disconnected.`);
process.exit(exitCode);
});
//await waitBotLogin(bot);
//await delay(1000);
try {
console.error(`Waiting for connect.`);
await waitForMessage(messageWaitQueue, messageWaitForRegister, [messageWaitForLogin]);
await mc.waitForMessage(messageWaitForRegister, [messageWaitForLogin]);
console.error(`Registering.`);
bot.chat(`/reg ${password} ${password}`);
await waitForMessage(messageWaitQueue, messageLoggedIn, messageRegisterFailed);
mc.bot.chat(`/reg ${password} ${password}`);
await mc.waitForMessage(messageLoggedIn, messageRegisterFailed);
console.error(`Paying 1000 to ${targetUser}.`);
bot.chat(`/pay ${targetUser} 1000`);
await waitForMessage(messageWaitQueue, '_send_success');
mc.bot.chat(`/pay ${targetUser} 1000`);
await mc.waitForMessage('_send_success', ["玩家未在线(或不存在)"]);
console.log(`Success.`);
exitCode = 0;
} catch (e) {
console.log(`Failed: ${e.toString()}`);
exitCode = 2;
} finally {
bot.end();
mc.bot.end();
console.error(`Finished.`);
}
}
......
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