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-02-05 22:33:33 +08:00

81 lines
4.5 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 asyncio
import os
import subprocess
import sys
from core.builtins import Bot
from core.component import on_command
from core.exceptions import NoReportException
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',
'*': '2 * 3 -> 6',
'**': 'x 的 y 次幂(由于性能问题,指数不得超过 4e+62 ** 3 -> 8',
'%': '取模5 % 2 -> 1',
'==': '等于1 == 1 -> True',
'<=': '小于等于1 <= 2 -> True',
'>=': '大于等于1 >= 2 -> False',
'>>': 'x 右移 y 位(相当于 x / (2 ** y)y < 1000032 >> 5 -> 1',
'<<': 'x 左移 y 位(相当于 x * (2 ** y)y < 100001 << 5 -> 32',
'^': '按位异或1 ^ 1 -> 0',
'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)',
'bool()': '转换为布尔值bool(1) -> True',
'bin()': '转换为二进制bin(268) -> 0b100001100',
'oct()': '转换为八进制oct(268) -> 0o414',
'hex()': '转换为十六进制hex(268) -> 0x10c',
'更多可用运算符和函数': 'https://bot.teahouse.team/-/340',
})
async def _(msg: Bot.MessageSession):
expr = msg.asDisplay().split(' ', 1)[1]
if sys.platform == 'win32' and sys.version_info.minor < 10:
try:
res = subprocess.check_output(
['python', os.path.abspath("./modules/calc/calc.py"), expr], timeout=10, shell=False).decode('utf-8')
if res[0:6] == 'Result':
await msg.finish(f'{(expr)} = {res[7:]}')
else:
await msg.finish(f'表达式无效:{res[7:]}')
except subprocess.TimeoutExpired:
raise NoReportException('计算超时。')
else:
try:
p = await asyncio.create_subprocess_exec('python', os.path.abspath("./modules/calc/calc.py"), expr,
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'{(expr)} = {res[7:]}')
else:
await msg.finish(f'表达式无效:{res[7:]}')
else:
Logger.error(f'calc.py exited with code {p.returncode}')
try:
Logger.error(
f'calc.py stderr: {stderr_data.decode("utf-8")}')
except UnicodeDecodeError:
Logger.error(
f'calc.py stderr: {stderr_data.decode("gbk")}')
except Exception as e:
raise NoReportException(e)