Archived
1
0
Fork 0
This repository has been archived on 2024-04-26. You can view files and clone it, but cannot push or open issues or pull requests.
akari-bot/modules/calc/__init__.py

76 lines
4.3 KiB
Python
Raw Normal View History

2023-01-19 15:10:08 +00:00
import os
2023-01-20 07:43:52 +00:00
import sys
2023-01-19 15:10:08 +00:00
2023-01-19 11:27:31 +00:00
from core.exceptions import NoReportException
2023-01-17 02:59:22 +00:00
from core.builtins.message import MessageSession
from core.component import on_command
2023-01-19 11:52:05 +00:00
2023-01-19 17:13:11 +00:00
import asyncio
2023-01-20 07:43:52 +00:00
import subprocess
2023-01-19 07:28:01 +00:00
2023-01-19 17:21:08 +00:00
from core.logger import Logger
2023-01-17 02:59:22 +00:00
c = on_command('calc', developers=[
2023-01-19 15:10:08 +00:00
'Dianliang233'], desc='安全地计算 Python ast 表达式。')
2023-01-17 02:59:22 +00:00
@c.handle('<math_expression>', options_desc={'+': '和/正数1 + 2 -> 3',
'-': '差/负数3 - 1 -> 2',
2023-01-17 02:59:22 +00:00
'/': '6 / 3 -> 2',
'*': '2 * 3 -> 6',
2023-01-20 14:47:39 +00:00
'**': 'x 的 y 次幂(由于性能问题,指数不得超过 4e+62 ** 3 -> 8',
2023-01-17 02:59:22 +00:00
'%': '取模5 % 2 -> 1',
'==': '等于1 == 1 -> True',
'<=': '小于等于1 <= 2 -> True',
2023-01-20 14:47:39 +00:00
'>=': '大于等于1 >= 2 -> False',
2023-01-17 02:59:22 +00:00
'>>': 'x 右移 y 位(相当于 x / (2 ** y)y < 1000032 >> 5 -> 1',
'<<': 'x 左移 y 位(相当于 x * (2 ** y)y < 100001 << 5 -> 32',
2023-01-20 08:37:18 +00:00
'^': '按位异或1 ^ 1 -> 0',
'not': 'not True -> False',
'is': 'x 与 y 是同一个对象1 is 1 -> True',
2023-01-17 02:59:22 +00:00
'randint(x)': '小于 x 的随机整数randint(6) -> 5',
'rand()': '0 与 1 之间的随机浮点数rand() -> 0.5789015836448923',
'int()': '转换为整数int(1.5) -> 1',
'float()': '转换为浮点数float(1) -> 1.0',
'str()': '转换为字符串str(1) -> "1"',
2023-01-20 08:45:13 +00:00
'complex()': '转换为复数complex(1) -> (1 + 0j)',
2023-01-20 14:47:39 +00:00
'abs()': '绝对值复数abs(-1) -> 1',
'bool()': '转换为布尔值bool(1) -> True',
'更多可用运算符和函数': 'https://bot.teahouse.team/-/340',
2023-01-17 02:59:22 +00:00
})
async def _(msg: MessageSession):
2023-01-20 08:01:07 +00:00
if sys.platform == 'win32' and sys.version_info.minor < 10:
2023-01-19 17:13:11 +00:00
try:
2023-01-20 07:43:52 +00:00
res = subprocess.check_output(
2023-01-20 08:25:42 +00:00
['python', os.path.abspath("./modules/calc/calc.py"), msg.parsed_msg["<math_expression>"]], timeout=10, shell=False).decode('utf-8')
2023-01-20 07:43:52 +00:00
if res[0:6] == 'Result':
2023-01-20 07:46:05 +00:00
await msg.finish(f'{(msg.parsed_msg["<math_expression>"])} = {res[7:]}')
2023-01-20 07:43:52 +00:00
else:
2023-01-20 07:46:05 +00:00
await msg.finish(f'表达式无效:{res[7:]}')
2023-01-20 07:43:52 +00:00
except subprocess.TimeoutExpired:
2023-01-19 17:13:11 +00:00
raise NoReportException('计算超时。')
2023-01-20 07:43:52 +00:00
else:
try:
2023-01-20 08:00:11 +00:00
p = await asyncio.create_subprocess_shell(f'python "{os.path.abspath("./modules/calc/calc.py")}" "{msg.parsed_msg["<math_expression>"]}"',
2023-01-20 07:43:52 +00:00
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)
try:
await asyncio.wait_for(p.wait(), timeout=10)
except asyncio.TimeoutError:
p.kill()
raise NoReportException('计算超时。')
stdout_data, stderr_data = await p.communicate()
if p.returncode == 0:
res = stdout_data.decode('utf-8')
2023-01-19 17:13:11 +00:00
2023-01-20 07:43:52 +00:00
if res[0:6] == 'Result':
2023-01-20 07:46:05 +00:00
await msg.finish(f'{(msg.parsed_msg["<math_expression>"])} = {res[7:]}')
2023-01-20 07:43:52 +00:00
else:
2023-01-20 07:46:05 +00:00
await msg.finish(f'表达式无效:{res[7:]}')
2023-01-19 17:13:11 +00:00
else:
2023-01-20 07:43:52 +00:00
Logger.error(f'calc.py exited with code {p.returncode}')
Logger.error(f'calc.py stderr: {stderr_data.decode("utf-8")}')
except Exception as e:
raise NoReportException(e)