eval
This commit is contained in:
parent
4904b1d305
commit
030594b51e
3 changed files with 167 additions and 16 deletions
|
|
@ -9,6 +9,9 @@
|
||||||
"check": "tsc"
|
"check": "tsc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@types/node": "^22.14.0",
|
||||||
|
"acorn": "^8.14.1",
|
||||||
|
"astring": "^1.9.0",
|
||||||
"canvas": "^3.1.0",
|
"canvas": "^3.1.0",
|
||||||
"discord.js": "^14.17.2",
|
"discord.js": "^14.17.2",
|
||||||
"sharp": "git+ssh://git@github.com/lovell/sharp.git",
|
"sharp": "git+ssh://git@github.com/lovell/sharp.git",
|
||||||
|
|
|
||||||
47
pnpm-lock.yaml
generated
47
pnpm-lock.yaml
generated
|
|
@ -13,6 +13,15 @@ importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^22.14.0
|
||||||
|
version: 22.14.0
|
||||||
|
acorn:
|
||||||
|
specifier: ^8.14.1
|
||||||
|
version: 8.14.1
|
||||||
|
astring:
|
||||||
|
specifier: ^1.9.0
|
||||||
|
version: 1.9.0
|
||||||
canvas:
|
canvas:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
|
|
@ -24,7 +33,7 @@ importers:
|
||||||
version: https://codeload.github.com/lovell/sharp/tar.gz/03e1b19764719d1b031045420223e78160db9bd0(patch_hash=aec393aef46aa4fa39e5c8d152bbe386c4b9df13f70cc0a46ee371547d7395dc)
|
version: https://codeload.github.com/lovell/sharp/tar.gz/03e1b19764719d1b031045420223e78160db9bd0(patch_hash=aec393aef46aa4fa39e5c8d152bbe386c4b9df13f70cc0a46ee371547d7395dc)
|
||||||
ts-node:
|
ts-node:
|
||||||
specifier: ^10.9.2
|
specifier: ^10.9.2
|
||||||
version: 10.9.2(@types/node@22.10.5)(typescript@5.7.2)
|
version: 10.9.2(@types/node@22.14.0)(typescript@5.7.2)
|
||||||
zod:
|
zod:
|
||||||
specifier: ^3.24.2
|
specifier: ^3.24.2
|
||||||
version: 3.24.2
|
version: 3.24.2
|
||||||
|
|
@ -214,8 +223,8 @@ packages:
|
||||||
'@tsconfig/node16@1.0.4':
|
'@tsconfig/node16@1.0.4':
|
||||||
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
|
||||||
|
|
||||||
'@types/node@22.10.5':
|
'@types/node@22.14.0':
|
||||||
resolution: {integrity: sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==}
|
resolution: {integrity: sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==}
|
||||||
|
|
||||||
'@types/ws@8.5.13':
|
'@types/ws@8.5.13':
|
||||||
resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==}
|
resolution: {integrity: sha512-osM/gWBTPKgHV8XkTunnegTRIsvF6owmf5w+JtAfOw472dptdm0dlGv4xCt6GwQRcC2XVOvvRE/0bAoQcL2QkA==}
|
||||||
|
|
@ -228,14 +237,18 @@ packages:
|
||||||
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
|
resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
|
|
||||||
acorn@8.14.0:
|
acorn@8.14.1:
|
||||||
resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
|
resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==}
|
||||||
engines: {node: '>=0.4.0'}
|
engines: {node: '>=0.4.0'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
arg@4.1.3:
|
arg@4.1.3:
|
||||||
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
|
||||||
|
|
||||||
|
astring@1.9.0:
|
||||||
|
resolution: {integrity: sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
base64-js@1.5.1:
|
base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
|
||||||
|
|
@ -435,8 +448,8 @@ packages:
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
undici-types@6.20.0:
|
undici-types@6.21.0:
|
||||||
resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
|
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||||
|
|
||||||
undici@6.19.8:
|
undici@6.19.8:
|
||||||
resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==}
|
resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==}
|
||||||
|
|
@ -632,24 +645,26 @@ snapshots:
|
||||||
|
|
||||||
'@tsconfig/node16@1.0.4': {}
|
'@tsconfig/node16@1.0.4': {}
|
||||||
|
|
||||||
'@types/node@22.10.5':
|
'@types/node@22.14.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.20.0
|
undici-types: 6.21.0
|
||||||
|
|
||||||
'@types/ws@8.5.13':
|
'@types/ws@8.5.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.10.5
|
'@types/node': 22.14.0
|
||||||
|
|
||||||
'@vladfrangu/async_event_emitter@2.4.6': {}
|
'@vladfrangu/async_event_emitter@2.4.6': {}
|
||||||
|
|
||||||
acorn-walk@8.3.4:
|
acorn-walk@8.3.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.14.0
|
acorn: 8.14.1
|
||||||
|
|
||||||
acorn@8.14.0: {}
|
acorn@8.14.1: {}
|
||||||
|
|
||||||
arg@4.1.3: {}
|
arg@4.1.3: {}
|
||||||
|
|
||||||
|
astring@1.9.0: {}
|
||||||
|
|
||||||
base64-js@1.5.1: {}
|
base64-js@1.5.1: {}
|
||||||
|
|
||||||
bl@4.1.0:
|
bl@4.1.0:
|
||||||
|
|
@ -863,15 +878,15 @@ snapshots:
|
||||||
|
|
||||||
ts-mixer@6.0.4: {}
|
ts-mixer@6.0.4: {}
|
||||||
|
|
||||||
ts-node@10.9.2(@types/node@22.10.5)(typescript@5.7.2):
|
ts-node@10.9.2(@types/node@22.14.0)(typescript@5.7.2):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@cspotcode/source-map-support': 0.8.1
|
'@cspotcode/source-map-support': 0.8.1
|
||||||
'@tsconfig/node10': 1.0.11
|
'@tsconfig/node10': 1.0.11
|
||||||
'@tsconfig/node12': 1.0.11
|
'@tsconfig/node12': 1.0.11
|
||||||
'@tsconfig/node14': 1.0.3
|
'@tsconfig/node14': 1.0.3
|
||||||
'@tsconfig/node16': 1.0.4
|
'@tsconfig/node16': 1.0.4
|
||||||
'@types/node': 22.10.5
|
'@types/node': 22.14.0
|
||||||
acorn: 8.14.0
|
acorn: 8.14.1
|
||||||
acorn-walk: 8.3.4
|
acorn-walk: 8.3.4
|
||||||
arg: 4.1.3
|
arg: 4.1.3
|
||||||
create-require: 1.1.1
|
create-require: 1.1.1
|
||||||
|
|
@ -889,7 +904,7 @@ snapshots:
|
||||||
|
|
||||||
typescript@5.7.2: {}
|
typescript@5.7.2: {}
|
||||||
|
|
||||||
undici-types@6.20.0: {}
|
undici-types@6.21.0: {}
|
||||||
|
|
||||||
undici@6.19.8: {}
|
undici@6.19.8: {}
|
||||||
|
|
||||||
|
|
|
||||||
133
src/commands/eval.ts
Normal file
133
src/commands/eval.ts
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
import {
|
||||||
|
ApplicationCommandType,
|
||||||
|
ContextMenuCommandBuilder,
|
||||||
|
ContextMenuCommandInteraction, escapeCodeBlock,
|
||||||
|
InteractionContextType,
|
||||||
|
Message,
|
||||||
|
Snowflake,
|
||||||
|
User, UserResolvable
|
||||||
|
} from "discord.js";
|
||||||
|
import { parse as acornParse } from 'acorn'
|
||||||
|
import { ContextCommand } from "../command.ts";
|
||||||
|
import {ModuleDeclaration, Statement} from "acorn";
|
||||||
|
import {generate} from "astring";
|
||||||
|
import {inspect} from "node:util";
|
||||||
|
|
||||||
|
|
||||||
|
function transformLastInBlock<T extends Statement | ModuleDeclaration>(
|
||||||
|
array: Array<T | Statement>) {
|
||||||
|
if (array) {
|
||||||
|
array[array.length - 1] = transformStatement<T | Statement>(array[array.length - 1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function transformStatement<T extends Statement | ModuleDeclaration>(
|
||||||
|
ast: T): T | Statement {
|
||||||
|
switch (ast.type) {
|
||||||
|
case 'ExpressionStatement':
|
||||||
|
return {
|
||||||
|
type: 'ExpressionStatement',
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
expression: {
|
||||||
|
type: 'AssignmentExpression',
|
||||||
|
operator: '=',
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
left: {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
type: 'Identifier',
|
||||||
|
name: '__ret'
|
||||||
|
},
|
||||||
|
right: ast.expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'BlockStatement':
|
||||||
|
transformLastInBlock(ast.body)
|
||||||
|
break
|
||||||
|
case 'ForStatement':
|
||||||
|
case "WhileStatement":
|
||||||
|
case 'ForOfStatement':
|
||||||
|
case 'ForInStatement':
|
||||||
|
case 'DoWhileStatement':
|
||||||
|
case 'WithStatement':
|
||||||
|
ast.body = transformStatement(ast.body)
|
||||||
|
break
|
||||||
|
case 'IfStatement':
|
||||||
|
ast.consequent = transformStatement(ast.consequent)
|
||||||
|
if (ast.alternate)
|
||||||
|
ast.alternate = transformStatement(ast.alternate)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default class Mock extends ContextCommand<Message> {
|
||||||
|
targetType: ApplicationCommandType.Message = ApplicationCommandType.Message;
|
||||||
|
contextDefinition: ContextMenuCommandBuilder =
|
||||||
|
new ContextMenuCommandBuilder()
|
||||||
|
.setName('eval')
|
||||||
|
.setType(ApplicationCommandType.Message)
|
||||||
|
async run(interaction: ContextMenuCommandInteraction, target: Message): Promise<void> {
|
||||||
|
await interaction.deferReply();
|
||||||
|
const match = target.content.match(/```js\n(.*?)```/s)
|
||||||
|
if (!match) {
|
||||||
|
await interaction.followUp("no codeblock found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const code = match[1];
|
||||||
|
let ast = acornParse(code, {
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
allowReturnOutsideFunction: true,
|
||||||
|
allowAwaitOutsideFunction: true,
|
||||||
|
})
|
||||||
|
if (ast.body) {
|
||||||
|
ast.body.unshift({
|
||||||
|
type: 'VariableDeclaration',
|
||||||
|
kind: 'let',
|
||||||
|
end: 0, start: 0,
|
||||||
|
declarations: [{
|
||||||
|
end: 0, start: 0,
|
||||||
|
id: {
|
||||||
|
start: 0,
|
||||||
|
end: 0,
|
||||||
|
type: 'Identifier',
|
||||||
|
name: '__ret'
|
||||||
|
},
|
||||||
|
type: "VariableDeclarator"
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
transformLastInBlock(ast.body)
|
||||||
|
ast.body.push({
|
||||||
|
type: 'ReturnStatement',
|
||||||
|
end: 0, start: 0,
|
||||||
|
argument: {
|
||||||
|
type: 'Identifier',
|
||||||
|
end: 0,
|
||||||
|
start: 0,
|
||||||
|
name: '__ret'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const mappedCode = generate(ast)
|
||||||
|
|
||||||
|
const bindings: { name: string, value: any }[] = [
|
||||||
|
{ name: 'add100', value: (x: number) => x + 100 },
|
||||||
|
{ name: 'client', value: interaction.client },
|
||||||
|
{ name: 'interaction', value: interaction },
|
||||||
|
{ name: 'getUser', value: (snowflake: UserResolvable) => interaction.client.users.fetch(snowflake) },
|
||||||
|
]
|
||||||
|
const func = new Function(...bindings.map(it => it.name), `"use strict";\nreturn (async () => {\n${mappedCode}\n})();`,)
|
||||||
|
|
||||||
|
await interaction.editReply("running...")
|
||||||
|
let result
|
||||||
|
result = await func(...bindings.map(it => it.value))
|
||||||
|
if (typeof result === "undefined") {
|
||||||
|
await interaction.editReply("result was undefined, did you forget to return?")
|
||||||
|
} else {
|
||||||
|
await interaction.editReply('```js\n' + escapeCodeBlock(inspect(result)) + "\n```")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue