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

97 lines
4.9 KiB
Python
Raw Normal View History

2023-05-10 15:26:04 +00:00
import asyncio
import os
import subprocess
import sys
import time
2023-06-26 15:56:00 +00:00
from core.builtins import Bot
2023-05-10 15:26:04 +00:00
from core.component import module
from core.exceptions import NoReportException
from core.logger import Logger
2023-05-10 15:48:59 +00:00
calc_dir = os.path.dirname(os.path.abspath(__file__))
2023-05-10 15:26:04 +00:00
c = module('calc', developers=[
2023-05-21 03:48:33 +00:00
'Dianliang233'], desc='{calc.help.calc.desc}')
2023-05-10 15:26:04 +00:00
2023-06-07 08:26:44 +00:00
@c.command('<math_expression>', options_desc={'+': '{calc.help.calc.option.plus}',
'-': '{calc.help.calc.option.minus}',
'/': '{calc.help.calc.option.multiply}',
'*': '{calc.help.calc.option.divide}',
'**': '{calc.help.calc.option.power}',
'%': '{calc.help.calc.option.modulo}',
'==': '{calc.help.calc.option.equal}',
'<=': '{calc.help.calc.option.less_equal}',
'>=': '{calc.help.calc.option.greater_equal}',
'>>': '{calc.help.calc.option.move_right}',
'<<': '{calc.help.calc.option.move_left}',
'^': '{calc.help.calc.option.xor}',
'not': '{calc.help.calc.option.not}',
'is': '{calc.help.calc.option.is}',
'randint(x)': '{calc.help.calc.option.randint}',
'rand()': '{calc.help.calc.option.rand}',
'int()': '{calc.help.calc.option.int}',
'float()': '{calc.help.calc.option.float}',
'str()': '{calc.help.calc.option.str}',
'complex()': '{calc.help.calc.option.complex}',
'bool()': '{calc.help.calc.option.bool}',
'bin()': '{calc.help.calc.option.bin}',
'oct()': '{calc.help.calc.option.oct}',
'hex()': '{calc.help.calc.option.hex}',
'{calc.help.calc.option.more}': 'https://bot.teahouse.team/-/340',
2023-05-10 15:26:04 +00:00
})
async def _(msg: Bot.MessageSession):
expr = msg.asDisplay().split(' ', 1)[1]
2023-05-11 15:19:55 +00:00
start = time.perf_counter_ns()
res = await spawn_subprocess('/calc.py', expr, msg)
stop = time.perf_counter_ns()
delta = (stop - start) / 1000000
if res[:6] == 'Result':
if msg.target.senderFrom == "Discord|Client":
m = f'`{(expr)}` = {res[7:]}'
else:
m = f'{(expr)} = {res[7:]}'
if msg.checkSuperUser():
m += '\n' + msg.locale.t("calc.message.running_time", time=delta)
await msg.finish(m)
else:
2023-05-21 03:48:33 +00:00
await msg.finish(msg.locale.t("calc.message.calc.invalid", expr={res[7:]}))
2023-05-11 15:19:55 +00:00
2023-05-12 10:58:03 +00:00
async def spawn_subprocess(file: str, arg: str, msg: Bot.MessageSession) -> str:
2023-05-11 17:18:00 +00:00
envs = os.environ.copy()
2023-05-10 15:26:04 +00:00
if sys.platform == 'win32' and sys.version_info.minor < 10:
try:
2023-05-11 15:19:55 +00:00
return subprocess.check_output(
2023-05-12 10:58:03 +00:00
[sys.executable, calc_dir + file, arg], timeout=10, shell=False,
2023-05-11 17:18:00 +00:00
cwd=os.path.abspath('.'), env=envs) \
2023-05-10 15:26:04 +00:00
.decode('utf-8')
2023-05-11 15:31:12 +00:00
except subprocess.TimeoutExpired as e:
2023-05-14 01:18:23 +00:00
raise NoReportException(msg.locale.t("calc.message.time_out")) from e
2023-05-10 15:26:04 +00:00
else:
try:
2023-05-11 15:19:55 +00:00
p = await asyncio.create_subprocess_exec(sys.executable, calc_dir + file,
2023-05-12 10:58:03 +00:00
arg,
2023-05-10 15:26:04 +00:00
stdout=asyncio.subprocess.PIPE,
2023-05-11 17:18:00 +00:00
stderr=asyncio.subprocess.PIPE,
cwd=os.path.abspath('.'), env=envs
2023-05-10 15:26:04 +00:00
)
try:
await asyncio.wait_for(p.wait(), timeout=10)
2023-05-11 15:31:12 +00:00
except asyncio.TimeoutError as e:
2023-05-10 15:26:04 +00:00
p.kill()
2023-05-11 15:31:12 +00:00
raise NoReportException(msg.locale.t("calc.message.time_out")) from e
2023-05-10 15:26:04 +00:00
stdout_data, stderr_data = await p.communicate()
2023-05-11 15:19:55 +00:00
if p.returncode != 0:
2023-05-11 15:31:12 +00:00
Logger.error(f'{file} exited with code {p.returncode}')
2023-05-10 15:26:04 +00:00
try:
Logger.error(
2023-05-11 15:31:12 +00:00
f'{file} stderr: {stderr_data.decode("utf-8")}')
2023-05-10 15:26:04 +00:00
except UnicodeDecodeError:
Logger.error(
2023-05-11 15:31:12 +00:00
f'{file} stderr: {stderr_data.decode("gbk")}')
2023-05-11 15:19:55 +00:00
return stdout_data.decode('utf-8')
2023-05-10 15:26:04 +00:00
except Exception as e:
2023-05-11 15:31:12 +00:00
raise NoReportException(e) from e