style: refactor and translate comments

This commit is contained in:
x1z53 2024-08-27 16:43:14 +03:00
parent 5950fa3bb8
commit a6c0433569
22 changed files with 62 additions and 62 deletions

View File

@ -4,7 +4,7 @@ RUN pip install poetry
RUN mkdir -p /app RUN mkdir -p /app
COPY . /app COPY . /app
# Фикс # Fix
RUN sed -i '/karkas-core = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \ RUN sed -i '/karkas-core = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \
sed -i '/karkas-blocks = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \ sed -i '/karkas-blocks = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \

View File

@ -7,11 +7,11 @@ from karkas_core import Karkas
async def main(): async def main():
karkas = Karkas() karkas = Karkas()
# Argument `safe` has a value `False` because of `super().__init__()`
await karkas.init_app( await karkas.init_app(
[ [
block_loader("standard", "config", safe=False), block_loader("standard", "config", safe=False),
block_loader("standard", "command_helper"), block_loader("standard", "command_helper"),
# safe=False из-за super().__init__()
block_loader("standard", "filters", safe=False), block_loader("standard", "filters", safe=False),
block_loader("standard", "report"), block_loader("standard", "report"),
block_loader("standard", "welcome", safe=False), block_loader("standard", "welcome", safe=False),

View File

@ -4,7 +4,7 @@ RUN pip install poetry
RUN mkdir -p /app RUN mkdir -p /app
COPY . /app COPY . /app
# Фикс # Fix
RUN sed -i '/karkas-core = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \ RUN sed -i '/karkas-core = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \
sed -i '/karkas-blocks = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \ sed -i '/karkas-blocks = {/{s/, develop = true//}' /app/src/altlinux/pyproject.toml && \

View File

@ -20,6 +20,7 @@ async def main():
block_loader("external", "create_report_apps"), block_loader("external", "create_report_apps"),
block_loader("standard", "info"), block_loader("standard", "info"),
block_loader("standard", "help"), block_loader("standard", "help"),
# block_loader("external", "yandexgpt", safe=False), # block_loader("external", "yandexgpt", safe=False),
# #
# block_loader("standard", "admin"), # block_loader("standard", "admin"),

View File

@ -4,7 +4,8 @@ from aiogram import F, Router
from .handlers import answer_to_message from .handlers import answer_to_message
router = Router() router = Router()
# Если сообщение содержит в начале текст "Гномик" или "гномик" или отвечает на сообщение бота, то вызывается функция answer_to_message
# If the message starts with the word "Гномик" ("гномик") or responds to a bot message, `answer_to_message` is called
router.message.register( router.message.register(
answer_to_message, F.text.startswith("Гномик") | F.text.startswith("гномик") answer_to_message, F.text.startswith("Гномик") | F.text.startswith("гномик")
) )

View File

@ -72,7 +72,7 @@ class YandexGPT:
response = await self.async_request( response = await self.async_request(
url=url, headers=headers, prompt=request url=url, headers=headers, prompt=request
) )
except Exception as e: # TODO: Переделать обработку ошибок except Exception as e: # TODO: Recreate error handling
# print(e) # print(e)
log(f"Error: {e}") log(f"Error: {e}")
@ -216,17 +216,22 @@ class YandexGPT:
self, text, voice, emotion, speed, format, quality self, text, voice, emotion, speed, format, quality
): ):
tts = "tts.api.cloud.yandex.net/speech/v1/tts:synthesize" tts = "tts.api.cloud.yandex.net/speech/v1/tts:synthesize"
# TODO: Сделать функцию TTS # TODO: Make TTS function
return 0 return 0
async def async_yandex_cloud_vision(self, image, features, language): async def async_yandex_cloud_vision(self, image, features, language):
# TODO: Сделать функцию Vision # TODO: Make Vision function
return 0 return 0
async def collect_messages(self, message_id, chat_id): async def collect_messages(self, message_id, chat_id):
# Collect a chain of messages in the format:
#
# [
# {"role": "user", "text": "<USER_NAME>: Hello!"},
# {"role": "assistant", "text": "Hello!"}
# ]
messages = [] messages = []
# Собираем цепочку сообщений в формате: [{"role": "user", "text": "<Имя_пользователя>: Привет!"},
# {"role": "assistant", "text": "Привет!"}]
while True: while True:
message = db_api.get_message_text(chat_id, message_id) message = db_api.get_message_text(chat_id, message_id)
if db_api.get_message_ai_model(chat_id, message_id) != None: if db_api.get_message_ai_model(chat_id, message_id) != None:
@ -244,9 +249,14 @@ class YandexGPT:
async def collecting_messages_for_history( async def collecting_messages_for_history(
self, start_message_id, end_message_id, chat_id self, start_message_id, end_message_id, chat_id
): ):
# Collect a chain of messages in the format:
#
# [
# {"role": "user", "text": "<USER_NAME>: Hello!"},
# {"role": "assistant", "text": "Hello!"}
# ]
messages = [] messages = []
# Собираем цепочку сообщений в формате: [{"role": "user", "text": "<Имя_пользователя>: Привет!"},
# {"role": "assistant", "text": "Привет!"}]
while True: while True:
message = db_api.get_message_text(chat_id, start_message_id) message = db_api.get_message_text(chat_id, start_message_id)
if db_api.get_message_ai_model(chat_id, start_message_id) != None: if db_api.get_message_ai_model(chat_id, start_message_id) != None:

View File

@ -41,23 +41,23 @@ async def chat_not_in_approve_list(message: Message, bot: Bot):
async def mute_user(chat_id: int, user_id: int, time: int, bot: Bot): async def mute_user(chat_id: int, user_id: int, time: int, bot: Bot):
# *, can_send_messages: bool | None = None, can_send_audios: bool | None = None, can_send_documents: bool | None = None, can_send_photos: bool | None = None, can_send_videos: bool | None = None, can_send_video_notes: bool | None = None, can_send_voice_notes: bool | None = None, can_send_polls: bool | None = None, can_send_other_messages: bool | None = None, can_add_web_page_previews: bool | None = None, can_change_info: bool | None = None, can_invite_users: bool | None = None, can_pin_messages: bool | None = None, can_manage_topics: bool | None = None, **extra_data: Any) # TODO: type variable using `typing`
mutePermissions = { mutePermissions = {
"can_send_messages": False, "can_send_messages": False, # bool | None
"can_send_audios": False, "can_send_audios": False, # bool | None
"can_send_documents": False, "can_send_documents": False, # bool | None
"can_send_photos": False, "can_send_photos": False, # bool | None
"can_send_videos": False, "can_send_videos": False, # bool | None
"can_send_video_notes": False, "can_send_video_notes": False, # bool | None
"can_send_voice_notes": False, "can_send_voice_notes": False, # bool | None
"can_send_polls": False, "can_send_polls": False, # bool | None
"can_send_other_messages": False, "can_send_other_messages": False, # bool | None
"can_add_web_page_previews": False, "can_add_web_page_previews": False, # bool | None
"can_change_info": False, "can_change_info": False, # bool | None
"can_invite_users": False, "can_invite_users": False, # bool | None
"can_pin_messages": False, "can_pin_messages": False, # bool | None
"can_manage_topics": False, "can_manage_topics": False, # bool | None
# **extra_data: Any
} }
end_time = time + int(time.time()) end_time = time + int(time.time())
await bot.restrict_chat_member( await bot.restrict_chat_member(

View File

@ -17,7 +17,7 @@ from .handlers import (
router = Router() router = Router()
# Если сообщение содержит какой либо текст и выполняется фильтр ChatNotInApproveFilter, то вызывается функция chat_not_in_approve_list # If message is not empty and the `ChatNotInApproveFilter` is applied, then the `chat_not_in_approve_list` function is called
router.message.register(chat_not_in_approve_list, ChatNotInApproveFilter(), F.text) router.message.register(chat_not_in_approve_list, ChatNotInApproveFilter(), F.text)
router.message.register(get_chat_id, ChatModerOrAdminFilter(), Command("chatID")) router.message.register(get_chat_id, ChatModerOrAdminFilter(), Command("chatID"))

View File

@ -74,7 +74,7 @@ class ConfigManager:
for key, value in updates.items(): for key, value in updates.items():
self._check_rights(key, module_id, "set") self._check_rights(key, module_id, "set")
if key in self._metadata: if key in self._metadata:
# TODO: add checks to validate the type and value based on metadata # TODO: add metadata-based type and value validation
self._config[key] = value self._config[key] = value
else: else:
raise KeyError(f"Key {key} is not registered.") raise KeyError(f"Key {key} is not registered.")

View File

@ -206,7 +206,7 @@ def get_miniapp_blueprint(config: "ConfigManager", prefix: str):
"-", "-",
) )
# TODO: добавить валидацию значений # TODO: add values validation
updated_settings = {} updated_settings = {}
for value, id_dict in zip(values, keys): for value, id_dict in zip(values, keys):
@ -217,7 +217,8 @@ def get_miniapp_blueprint(config: "ConfigManager", prefix: str):
meta = config.get_meta(key) meta = config.get_meta(key)
if meta["type"] == "password": if meta["type"] == "password":
if value: # Only update if a new value is provided # Is updated only if new value is specified
if value:
updated_settings[key] = value updated_settings[key] = value
else: else:
updated_settings[key] = value updated_settings[key] = value

View File

@ -94,7 +94,7 @@ class ChatIDFilter(BaseFilter):
approved_chats = self.approved_chats or get_approved_chat_id() approved_chats = self.approved_chats or get_approved_chat_id()
# Если список для фильтрации пуст - разрешаем всем. # If filtering list is empty, allow anything
if len(approved_chats) == 0: if len(approved_chats) == 0:
return True return True

View File

@ -26,8 +26,6 @@ except Exception:
COMMAND_HELPER_MODULE_LOADED = False COMMAND_HELPER_MODULE_LOADED = False
pass pass
# Уважительная просьба не удалять и не изменять нижеизложенный текст
# без согласия команды проекта «Каркас».
# We kindly ask you not to delete or change the following text without # We kindly ask you not to delete or change the following text without
# the consent of the «Karkas» project team. # the consent of the «Karkas» project team.
FOOTER = """=============== FOOTER = """===============

View File

@ -28,9 +28,6 @@ async def get_info_answer_by_id(message: Message, bot: Bot, user_id: int):
async def get_user_info(message: Message, bot: Bot): async def get_user_info(message: Message, bot: Bot):
# Проверяем содержимое сообщения, если содержит вторым элементом тег пользователя, то выводим информацию о нем
# Если сообщение отвечает на другое сообщение, то выводим информацию о пользователе, на чье сообщение был ответ
# Если это бот то выводим информацию, что это бот и какая модель yandexgpt используется
try: try:
if message.reply_to_message: if message.reply_to_message:
user_id = message.reply_to_message.from_user.id user_id = message.reply_to_message.from_user.id

View File

@ -8,7 +8,7 @@ from flask import request
if TYPE_CHECKING: if TYPE_CHECKING:
from dash import Dash from dash import Dash
# TODO: добавить прокидывание BASE_PATH, т.к. это параметр из настроек # TODO: add `BASE_PATH` transfer, because this is a parameter from the settings
WEBAPP_LOADER_TEMPLATE = """ WEBAPP_LOADER_TEMPLATE = """
<!DOCTYPE html> <!DOCTYPE html>

View File

@ -56,7 +56,6 @@ def create_dash_app(requests_pathname_prefix: str = None) -> dash.Dash:
dbc.icons.BOOTSTRAP, dbc.icons.BOOTSTRAP,
], ],
external_scripts=[ external_scripts=[
#
"https://telegram.org/js/telegram-web-app.js" "https://telegram.org/js/telegram-web-app.js"
], ],
server=server, server=server,
@ -156,7 +155,7 @@ def create_dash_app(requests_pathname_prefix: str = None) -> dash.Dash:
setup_auth_clientcallbacks(app) setup_auth_clientcallbacks(app)
# Открытие на кнопку меню # Open on the menu button
app.clientside_callback( app.clientside_callback(
""" """
function(n_clicks) { function(n_clicks) {
@ -173,7 +172,7 @@ def create_dash_app(requests_pathname_prefix: str = None) -> dash.Dash:
Input("open-offcanvas", "n_clicks"), Input("open-offcanvas", "n_clicks"),
) )
# Закрываем offcanvas при клике на ссылку в меню # Closing `offcanvas` when clicking on the link in the menu
app.clientside_callback( app.clientside_callback(
""" """
function(n_clicks) { function(n_clicks) {

View File

@ -67,8 +67,10 @@ class TestRoles(unittest.IsolatedAsyncioTestCase):
) )
cls.assertEqual(await cls.roles.get_role_name(cls.roles.user_role_id), "USER") cls.assertEqual(await cls.roles.get_role_name(cls.roles.user_role_id), "USER")
cls.assertEqual(await cls.roles.get_role_name(cls.roles.bot_role_id), "BOT") cls.assertEqual(await cls.roles.get_role_name(cls.roles.bot_role_id), "BOT")
# Non-existent role ID
with cls.assertRaises(ValueError): with cls.assertRaises(ValueError):
await cls.roles.get_role_name(999) # Несуществующий ID роли await cls.roles.get_role_name(999)
@classmethod @classmethod
def tearDownClass(cls): def tearDownClass(cls):

View File

@ -9,9 +9,8 @@ class ChatStats(Table):
class Messages(Table): class Messages(Table):
# Временная мера, пока не примут # Key format: `{message_chat_id}-{message_id}`
# https://github.com/piccolo-orm/piccolo/pull/984 # (A temporary measure until https://github.com/piccolo-orm/piccolo/pull/984 is accepted)
# {message_chat_id}-{message_id}
key = Text(primary_key=True) key = Text(primary_key=True)
chat_id = Integer() chat_id = Integer()
@ -23,9 +22,8 @@ class Messages(Table):
class UserStats(Table): class UserStats(Table):
# Временная мера, пока не примут # Key format: `{chat_id}-{user_id}`
# https://github.com/piccolo-orm/piccolo/pull/984 # (A temporary measure until https://github.com/piccolo-orm/piccolo/pull/984 is accepted)
# {chat_id}-{user_id}
key = Text(primary_key=True) key = Text(primary_key=True)
chat_id = Integer() chat_id = Integer()

View File

@ -80,7 +80,7 @@ last_success = {}
async def new_member_handler(event: "ChatMemberUpdated", bot: Bot): async def new_member_handler(event: "ChatMemberUpdated", bot: Bot):
# НЕ СРАБОТАЕТ, ЕСЛИ ЧЕЛОВЕК УЖЕ ОГРАНИЧЕН В ПРАВАХ (RESTRICTED) # WARN: IT WON'T WORK IF THE PERSON IS ALREADY RESTRICTED
if event.new_chat_member.status == ChatMemberStatus.MEMBER: if event.new_chat_member.status == ChatMemberStatus.MEMBER:
task = task_manager.build_random_task(event, bot) task = task_manager.build_random_task(event, bot)
keys = await task.run() keys = await task.run()
@ -353,7 +353,7 @@ async def module_init():
handle_inline_button_verification handle_inline_button_verification
) )
# Нельзя применить ChatIDFilter из-за отстутсвия id чата # ChatIDFilter can't be applied because there is no chat ID
router.poll_answer()(handle_poll_verification) router.poll_answer()(handle_poll_verification)
register_router(router) register_router(router)

View File

@ -1,3 +1,4 @@
# TODO: rewrite for compatibility with English
def get_plural_form(number, singular, genitive_singular, plural): def get_plural_form(number, singular, genitive_singular, plural):
if 11 <= number % 100 <= 19: if 11 <= number % 100 <= 19:
return f"{number} {plural}" return f"{number} {plural}"
@ -11,14 +12,12 @@ def get_plural_form(number, singular, genitive_singular, plural):
class MultiKeyDict: class MultiKeyDict:
def __init__(self): def __init__(self):
self.value_to_keys = {} # Словарь значений и связанных с ними ключей self.value_to_keys = {}
self.key_to_value = {} # Словарь ключей и связанных с ними значений self.key_to_value = {}
def add(self, value, keys): def add(self, value, keys):
# Добавляем значение в словарь с множеством ключей
self.value_to_keys[value] = set(keys) self.value_to_keys[value] = set(keys)
# Для каждого ключа создаем запись в словаре key_to_value
for key in keys: for key in keys:
self.key_to_value[key] = value self.key_to_value[key] = value

View File

@ -39,6 +39,7 @@ class UnsafeFSLoader(AbstractLoader):
full_path = self._resolve_module_from_path(".") full_path = self._resolve_module_from_path(".")
# TODO: remove duplication
if full_path.name == "__init__.py": if full_path.name == "__init__.py":
module_name = full_path.parent.name module_name = full_path.parent.name
path = full_path.parent.parent.absolute() path = full_path.parent.parent.absolute()
@ -46,16 +47,12 @@ class UnsafeFSLoader(AbstractLoader):
module_name = full_path.stem module_name = full_path.stem
path = full_path.parent.absolute() path = full_path.parent.absolute()
# Добавляем директорию модуля в sys.path
sys.path.insert(0, str(path)) sys.path.insert(0, str(path))
# Загружаем спецификацию модуля
spec = importlib.util.spec_from_file_location(module_name, full_path) spec = importlib.util.spec_from_file_location(module_name, full_path)
# Создаем модуль
module = importlib.util.module_from_spec(spec) module = importlib.util.module_from_spec(spec)
# Выполняем модуль
spec.loader.exec_module(module) spec.loader.exec_module(module)
return module return module

View File

@ -93,7 +93,7 @@ class ModulesManager:
async def load(self, loader: AbstractLoader): async def load(self, loader: AbstractLoader):
info = loader.info() info = loader.info()
# Check if the module is already loaded # Is the module loaded
if any(mod["info"].id == info.id for mod in self.modules): if any(mod["info"].id == info.id for mod in self.modules):
return return

View File

@ -48,13 +48,10 @@ class UnsafeFSLoader:
sys.path.insert(0, str(path)) sys.path.insert(0, str(path))
# Загружаем спецификацию модуля
spec = importlib.util.spec_from_file_location(module_name, full_path) spec = importlib.util.spec_from_file_location(module_name, full_path)
# Создаем модуль
module = importlib.util.module_from_spec(spec) module = importlib.util.module_from_spec(spec)
# Выполняем модуль
spec.loader.exec_module(module) spec.loader.exec_module(module)
return module return module