discord.js - 我将如何在 discord.js 中执行执行 bot 命令?
问题描述
我正在尝试制作一个机器人命令(.e args),它允许您使用机器人命令执行任何代码。我该怎么做?我试过了:
cmd = message.content.slice(2);
cmd;
但是当我尝试输入 Discord 时它没有做任何事情,例如, .e message.channel.send("Hello world!") 我将如何使它工作?
解决方案
首先我想说这是一个非常糟糕的主意,我真的希望你知道你在做什么。
然而,我已经将这个我自己作为我大学的 CTF(夺旗)挑战(由其他学生解决)。您可以在此处找到完整的源代码。
现在,首先,您可以使用eval(cmd)
,但这是一个可怕的想法,因为这会使服务器暴露于代码注入攻击。因此,为避免这种情况,我们将使用 VM(虚拟机)。在这种情况下,我决定使用包vm2
。最重要的是,我决定要授予对文件系统的访问权限(用于 CTF 挑战),但是授予对真正 FS 模块的访问权限会带来灾难,因此我决定使用memfs
在内存中模拟 FS 模块。
注意:以下代码是用 typescript 编写的,它是 javascript 的超集。
// index.ts
import { Client, Message } from 'discord.js';
import * as fs from 'fs';
import { vol as mfs} from 'memfs';
import * as path from 'path';
import { VM } from 'vm2';
const fakeFileSystemRoot = path.join(__dirname, '..', 'fake_file_system');
mfs.fromJSON(
fs.readdirSync(fakeFileSystemRoot)
.map((fileName) => [fileName, fs.readFileSync(path.join(fakeFileSystemRoot, fileName)).toString('utf8')])
.reduce((res, [fileName, file]) => ({...res, [fileName]: file}), {}),
);
const secrets = require(path.resolve(__dirname, '..', 'secrets.json'));
const client = new Client();
const handleMessage = (message: Message) => {
if (message.channel.type.toLowerCase() !== 'dm') {
return;
}
if (message.author.bot) {
return;
}
const recursiveCatch = (cb) => {
try {
cb();
} catch (err) {
recursiveCatch(() => {
const msg = String(err) || 'error message cannot be empty';
message.channel.send(msg);
console.log('Err:', msg);
});
}
};
recursiveCatch(() => {
const out = [];
const vm = new VM({
eval: false,
wasm: false,
timeout: 100,
sandbox: {
console: {
log: (...args: any[]) => out.push(args.map(String).join('')),
info: (...args: any[]) => out.push(args.map(String).join('')),
warn: (...args: any[]) => out.push(args.map(String).join('')),
error: (...args: any[]) => out.push(args.map(String).join('')),
debug: (...args: any[]) => out.push(args.map(String).join('')),
},
fs: {
readSync: mfs.readSync.bind(mfs),
readFileSync: mfs.readFileSync.bind(mfs),
readdirSync: mfs.readdirSync.bind(mfs),
statSync: mfs.statSync.bind(mfs),
fstatSync: mfs.fstatSync.bind(mfs),
lstatSync: mfs.lstatSync.bind(mfs),
},
},
});
console.log('In:', message.content);
const returnValue = vm.run(message.content);
out.push(returnValue);
const outStr = out.join('\n');
if (outStr.length > 0) {
message.channel.send(outStr);
console.log('Out:', outStr);
}
});
};
client.on('ready', () => {
client.on('message', (message: Message) => handleMessage(message));
client.on('messageUpdate', (oldMessage, newMessage: Message) => handleMessage(newMessage));
});
client.login(secrets.discord_token)
.then(() => {
console.info(`Login successful`);
})
.catch((err) => {
console.error(`Login failed`);
throw err;
});
推荐阅读
- laravel - 如何在 Laravel Jetstream 上使用 REST API 管理用户
- python - Tkinter filedialog.asksaveasfilename() 不保存文件
- c# - rb.AddForce(Vector2.up * jumpVelocity); 不会使角色跳跃(Unity2D)
- vb.net - ADD 函数将提供动态位置和动态分隔符
- sql - 统计有条件的一段时间的人数
- python - 欢迎留言 - Discord.py
- python - 撤消python列表理解
- ruby-on-rails - Ransack 搜索表单将搜索替换为“占位符”
- php - Nette 框架 - Nette\Database\ResultSet 仅实现一种方式迭代器
- android - react-native-webview 中的 Google 登录似乎不起作用。大佬们有什么解决办法吗?