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
2023-01-20 16:45:13 +08:00

81 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import sys
from core.exceptions import NoReportException
from core.builtins.message import MessageSession
from core.component import on_command
import asyncio
import subprocess
from core.logger import Logger
c = on_command('calc', developers=[
'Dianliang233'], desc='安全地计算 Python ast 表达式。')
@c.handle('<math_expression>', options_desc={'+': '和/正数1 + 2 -> 3',
'-': '差/负数3 - 1 -> 2',
'/': '6 / 3 -> 2',
'//': '整除7 // 4 -> 1',
'*': '2 * 3 -> 6',
'**': 'x 的 y 次幂(由于性能问题,结果不得超过 4e+62 ** 3 -> 8',
'%': '取模5 % 2 -> 1',
'==': '等于1 == 1 -> True',
'<': '小于1 < 2 -> True',
'>': '大于2 > 1 -> True',
'<=': '小于等于1 <= 2 -> True',
'>>': 'x 右移 y 位(相当于 x / (2 ** y)y < 1000032 >> 5 -> 1',
'<<': 'x 左移 y 位(相当于 x * (2 ** y)y < 100001 << 5 -> 32',
'&': '按位与1 & 1 -> 1',
'|': '按位或1 | 1 -> 1',
'^': '按位异或1 ^ 1 -> 0',
'~': '按位取反:~1 -> -2',
'in': 'x 在 y 中:"hat" in "what" -> True',
'not': 'not True -> False',
'is': 'x 与 y 是同一个对象1 is 1 -> True',
'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"',
'complex()': '转换为复数complex(1) -> (1 + 0j)',
'更多数学函数(无需前缀)': 'https://docs.python.org/zh-cn/3/library/math.html',
'更多统计函数(无需前缀)': 'https://docs.python.org/zh-cn/3/library/statistics.html',
'更多复数运算函数(需要 cmath. 前缀)': 'https://docs.python.org/zh-cn/3/library/cmath.html',
})
async def _(msg: MessageSession):
if sys.platform == 'win32' and sys.version_info.minor < 10:
try:
res = subprocess.check_output(
['python', os.path.abspath("./modules/calc/calc.py"), msg.parsed_msg["<math_expression>"]], timeout=10, shell=False).decode('utf-8')
if res[0:6] == 'Result':
await msg.finish(f'{(msg.parsed_msg["<math_expression>"])} = {res[7:]}')
else:
await msg.finish(f'表达式无效:{res[7:]}')
except subprocess.TimeoutExpired:
raise NoReportException('计算超时。')
else:
try:
p = await asyncio.create_subprocess_shell(f'python "{os.path.abspath("./modules/calc/calc.py")}" "{msg.parsed_msg["<math_expression>"]}"',
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')
if res[0:6] == 'Result':
await msg.finish(f'{(msg.parsed_msg["<math_expression>"])} = {res[7:]}')
else:
await msg.finish(f'表达式无效:{res[7:]}')
else:
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)