0
0
mirror of https://gitflic.ru/project/maks1ms/ocab.git synced 2025-03-13 22:03:50 +03:00

завершен standard.create_report_apps

This commit is contained in:
Maxim Slipenko 2024-07-14 13:57:48 +03:00
parent c53f6025ae
commit 51f5290017
6 changed files with 282 additions and 30 deletions

View File

@ -7,3 +7,4 @@ from .public_api import (
register_router, register_router,
set_my_commands, set_my_commands,
) )
from .utils import Utils

View File

@ -0,0 +1,12 @@
import re
CLEAN_HTML = re.compile("<.*?>")
class Utils:
@staticmethod
def code_format(code: str, lang: str):
if lang:
return f'<pre><code class="language-{lang}">{code}</code></pre>'
else:
return f"<pre>{code}</pre>"

View File

@ -15,7 +15,7 @@ from RestrictedPython.Guards import (
safer_getattr, safer_getattr,
) )
from ocab_core.logger import log_new from ocab_core.logger import log
from ocab_core.modules_system.safe.zope_guards import extra_safe_builtins from ocab_core.modules_system.safe.zope_guards import extra_safe_builtins
@ -89,7 +89,7 @@ ALLOWED_IMPORTS = [
def safes_getattr(object, name, default=None, getattr=safer_getattr): def safes_getattr(object, name, default=None, getattr=safer_getattr):
if isinstance(object, Bot) and name == "token": if isinstance(object, Bot) and name == "token":
log_new("Bot.token is not allowed") log("Bot.token is not allowed")
raise Exception("Bot.token is not allowed") raise Exception("Bot.token is not allowed")
return getattr(object, name, default) return getattr(object, name, default)

View File

@ -109,3 +109,117 @@ def guarded_all(seq):
extra_safe_builtins["all"] = guarded_all extra_safe_builtins["all"] = guarded_all
valid_inplace_types = (list, set)
inplace_slots = {
"+=": "__iadd__",
"-=": "__isub__",
"*=": "__imul__",
"/=": (1 / 2 == 0) and "__idiv__" or "__itruediv__",
"//=": "__ifloordiv__",
"%=": "__imod__",
"**=": "__ipow__",
"<<=": "__ilshift__",
">>=": "__irshift__",
"&=": "__iand__",
"^=": "__ixor__",
"|=": "__ior__",
}
def __iadd__(x, y):
x += y
return x
def __isub__(x, y):
x -= y
return x
def __imul__(x, y):
x *= y
return x
def __idiv__(x, y):
x /= y
return x
def __ifloordiv__(x, y):
x //= y
return x
def __imod__(x, y):
x %= y
return x
def __ipow__(x, y):
x **= y
return x
def __ilshift__(x, y):
x <<= y
return x
def __irshift__(x, y):
x >>= y
return x
def __iand__(x, y):
x &= y
return x
def __ixor__(x, y):
x ^= y
return x
def __ior__(x, y):
x |= y
return x
inplace_ops = {
"+=": __iadd__,
"-=": __isub__,
"*=": __imul__,
"/=": __idiv__,
"//=": __ifloordiv__,
"%=": __imod__,
"**=": __ipow__,
"<<=": __ilshift__,
">>=": __irshift__,
"&=": __iand__,
"^=": __ixor__,
"|=": __ior__,
}
def protected_inplacevar(op, var, expr):
"""Do an inplace operation
If the var has an inplace slot, then disallow the operation
unless the var an instance of ``valid_inplace_types``.
"""
if hasattr(var, inplace_slots[op]) and not isinstance(var, valid_inplace_types):
try:
cls = var.__class__
except AttributeError:
cls = type(var)
raise TypeError(
"Augmented assignment to %s objects is not allowed"
" in untrusted code" % cls.__name__
)
return inplace_ops[op](var, expr)
extra_safe_builtins["_inplacevar_"] = protected_inplacevar

View File

@ -1,64 +1,136 @@
from aiogram import Bot, Router from aiogram import Bot, Router
from aiogram.enums import ParseMode
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup from aiogram.fsm.state import State, StatesGroup
from aiogram.types import BufferedInputFile, Message from aiogram.types import (
BufferedInputFile,
KeyboardButton,
Message,
ReplyKeyboardMarkup,
ReplyKeyboardRemove,
)
from ocab_core.modules_system.public_api import get_fsm_context from ocab_core.modules_system.public_api import Utils, get_fsm_context
from .report import Report
router = Router() router = Router()
class ReportState(StatesGroup): class ReportState(StatesGroup):
input_kernel_info = State() input_system_info = State()
input_app_name = State() input_app_name = State()
input_problem_step_by_step = State() input_problem_step_by_step = State()
input_actual_result = State()
input_expected_result = State()
input_additional_info = State()
system_info_code = """echo "SESSION_TYPE: ${XDG_SESSION_TYPE:-Unknown}"
[ -f /etc/os-release ] && grep "^PRETTY_NAME=" /etc/os-release | cut -d= -f2 \
| tr -d '"' | xargs echo "OS: "
echo "Kernel: $(uname -r)"
echo "DE: ${XDG_CURRENT_DESKTOP:-Unknown}"
grep "^model name" /proc/cpuinfo | head -n1 | cut -d: -f2 \
| xargs echo "CPU: "
lspci | grep "VGA compatible controller" | cut -d: -f3 \
| xargs -I{} echo "GPU: {}"
"""
system_info_message = """Укажите параметры свой системы.
Собрать информацию о системе можно с помощью данного скрипта:
""" + Utils.code_format(
system_info_code,
"shell",
)
async def start_report(chat_id: int, bot: Bot): async def start_report(chat_id: int, bot: Bot):
await bot.send_message( await bot.send_message(
chat_id=chat_id, chat_id=chat_id,
text="Какая версия ядра у тебя на " text=system_info_message,
"текущий момент? Можно узнать " parse_mode=ParseMode.HTML,
"командой `uname -rm`", reply_markup=ReplyKeyboardRemove(),
parse_mode="Markdown",
) )
state = await get_fsm_context(chat_id, chat_id) state = await get_fsm_context(chat_id, chat_id)
await state.set_state(ReportState.input_kernel_info) await state.set_state(ReportState.input_system_info)
@router.message(ReportState.input_kernel_info) app_info_message = """Укажите название и версию приложения.
async def kernel_version_entered(message: Message, state: FSMContext): Узнать можно с помощью данной команды:""" + Utils.code_format(
await state.update_data(kernel=message.text) "rpm -qa | grep -i НАЗВАНИЕРИЛОЖЕНИЯ", "shell"
await message.answer(text="В каком приложении возникла проблема?") )
@router.message(ReportState.input_system_info)
async def system_entered(message: Message, state: FSMContext):
await state.update_data(system=message.text)
await message.answer(
text=app_info_message,
parse_mode=ParseMode.HTML,
)
await state.set_state(ReportState.input_app_name) await state.set_state(ReportState.input_app_name)
step_by_step_message = (
"""Опиши проблему пошагово, что ты делал, что происходило, что не так."""
)
@router.message(ReportState.input_app_name) @router.message(ReportState.input_app_name)
async def app_name_entered(message: Message, state: FSMContext): async def app_name_entered(message: Message, state: FSMContext):
await state.update_data(app_name=message.text) await state.update_data(app=message.text)
await message.answer( await message.answer(text=step_by_step_message)
text="Опиши проблему пошагово, что ты делал, что происходило, что не так"
)
await state.set_state(ReportState.input_problem_step_by_step) await state.set_state(ReportState.input_problem_step_by_step)
@router.message(ReportState.input_problem_step_by_step) @router.message(ReportState.input_problem_step_by_step)
async def problem_step_by_step_entered(message: Message, state: FSMContext): async def problem_step_by_step_entered(message: Message, state: FSMContext):
await state.update_data(problem_step_by_step=message.text) await state.update_data(problem_step_by_step=message.text)
await message.answer(text="Вот твой отчет сообщением, а также файлом:") await message.answer(text="Опиши, что произошло (фактический результат).")
await state.set_state(ReportState.input_actual_result)
@router.message(ReportState.input_actual_result)
async def actual_result_entered(message: Message, state: FSMContext):
await state.update_data(actual=message.text)
await message.answer(text="Опиши ожидаемый результат.")
await state.set_state(ReportState.input_expected_result)
@router.message(ReportState.input_expected_result)
async def expected_result_entered(message: Message, state: FSMContext):
await state.update_data(expected=message.text)
await message.answer(
text="Если есть дополнительная информация, то напиши ее.",
reply_markup=ReplyKeyboardMarkup(
resize_keyboard=True,
keyboard=[
[KeyboardButton(text="Дополнительной информации нет")],
],
),
)
await state.set_state(ReportState.input_additional_info)
@router.message(ReportState.input_additional_info)
async def additional_info_entered(message: Message, state: FSMContext):
if message.text == "Дополнительной информации нет":
additional_info = ""
else:
additional_info = message.text
await state.update_data(additional=additional_info)
await message.answer(
text="Вот твой отчет сообщением, а также файлом:",
reply_markup=ReplyKeyboardRemove(),
)
data = await state.get_data() data = await state.get_data()
report = f"""Стенд с ошибкой: report = Report(data)
# uname -rm file_report = report.export(html=False).encode()
{data['kernel']}
Шаги, приводящие к ошибке: await message.answer(text=report.export(html=True), parse_mode=ParseMode.HTML)
await message.answer_document(document=BufferedInputFile(file_report, "report.txt"))
{data['problem_step_by_step']}
"""
await message.answer(text=report)
await message.answer_document(
document=BufferedInputFile(report.encode(), "report.txt")
)
await state.clear() await state.clear()

View File

@ -0,0 +1,53 @@
import aiogram
class ReportFormatter:
def __init__(self, html=True):
self.html = html
def bold(self, string):
if self.html:
return f"<b>{self.text(string)}</b>"
return self.text(string)
def text(self, string):
if self.html:
return aiogram.html.quote(string)
return string
class Report:
def __init__(self, data: dict):
self.data = data
def export(self, html=True):
data = self.data
f = ReportFormatter(html)
report = f"""{f.bold("Стенд с ошибкой:")}
{f.text(data['system'])}
{f.bold("Версия программы:")}
{f.text(data['app'])}
{f.bold("Шаги, приводящие к ошибке:")}
{f.text(data['problem_step_by_step'])}
{f.bold("Результат:")}
{f.text(data['actual'])}
{f.bold("Ожидаемый результат:")}
{f.text(data['expected'])}
"""
if data["additional"] != "":
report += f"""{f.bold("Дополнительно:")}
{f.text(data['additional'])}
"""
return report