diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/README.md b/src/karkas_blocks/karkas_blocks/standard/admin/README.md deleted file mode 100644 index bb00f2a..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Модуль Admin - -Модуль `admin` предоставляет администраторам и модераторам чата инструменты для управления: - -## Функциональность - -- Удаление сообщений. -- Получение ID чата. - -## Команды - -- `/rm` - удалить сообщение, на которое отвечает команда. -- `/chatID` - получить ID текущего чата. - -## Использование - -1. Ответьте на сообщение, которое нужно удалить. -2. Отправьте команду `/rm`. - -Чтобы получить ID чата, отправьте команду `/chatID`. diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/__init__.py b/src/karkas_blocks/karkas_blocks/standard/admin/__init__.py deleted file mode 100644 index c8fccb0..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .main import module_init diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/handlers.py b/src/karkas_blocks/karkas_blocks/standard/admin/handlers.py deleted file mode 100644 index 368cb2b..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/handlers.py +++ /dev/null @@ -1,65 +0,0 @@ -# flake8: noqa -from typing import TYPE_CHECKING - -from aiogram import Bot -from aiogram.types import Message - -from karkas_core.modules_system.public_api import get_module - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - -config: "IConfig" = get_module("standard.config", "config") - - -def get_default_chat_tag(): - return config.get("filters::default_chat_tag") - - -async def delete_message(message: Message, bot: Bot): - reply_message_id = message.reply_to_message.message_id - await bot.delete_message(message.chat.id, reply_message_id) - - -async def error_access(message: Message, bot: Bot): - await message.reply("Вы не админ/модератор") - - -async def get_chat_id(message: Message, bot: Bot): - await message.reply( - f"ID данного чата: `{message.chat.id}`", parse_mode="MarkdownV2" - ) - - -async def chat_not_in_approve_list(message: Message, bot: Bot): - await message.reply( - f"Бот недоступен в данном чате, пожалуйста," - f" обратитесь к администратору для добавления чата в список доступных или перейдите в чат " - f"{get_default_chat_tag()}" - ) - await get_chat_id(message, 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) - - mutePermissions = { - "can_send_messages": False, - "can_send_audios": False, - "can_send_documents": False, - "can_send_photos": False, - "can_send_videos": False, - "can_send_video_notes": False, - "can_send_voice_notes": False, - "can_send_polls": False, - "can_send_other_messages": False, - "can_add_web_page_previews": False, - "can_change_info": False, - "can_invite_users": False, - "can_pin_messages": False, - "can_manage_topics": False, - } - end_time = time + int(time.time()) - await bot.restrict_chat_member( - chat_id, user_id, until_date=end_time, **mutePermissions - ) diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/info.json b/src/karkas_blocks/karkas_blocks/standard/admin/info.json deleted file mode 100644 index fd54142..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/info.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "standard.admin", - "name": "Admin", - "description": "Модуль для работы с админкой", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": false, - "dependencies": { - "required": { - "standard.filters": "^1.0.0", - "standard.roles": "^1.0.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/main.py b/src/karkas_blocks/karkas_blocks/standard/admin/main.py deleted file mode 100644 index 1f67729..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/main.py +++ /dev/null @@ -1,7 +0,0 @@ -from karkas_core.modules_system.public_api import register_router - -from .routers import router - - -async def module_init(): - register_router(router) diff --git a/src/karkas_blocks/karkas_blocks/standard/admin/routers.py b/src/karkas_blocks/karkas_blocks/standard/admin/routers.py deleted file mode 100644 index 326de75..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/admin/routers.py +++ /dev/null @@ -1,27 +0,0 @@ -# flake8: noqa -from aiogram import F, Router -from aiogram.filters import Command - -from karkas_core.modules_system.public_api import get_module, log - -from .handlers import ( - chat_not_in_approve_list, - delete_message, - error_access, - get_chat_id, -) - -(ChatModerOrAdminFilter, ChatNotInApproveFilter) = get_module( - "standard.filters", ["ChatModerOrAdminFilter", "ChatNotInApproveFilter"] -) - -router = Router() - -# Если сообщение содержит какой либо текст и выполняется фильтр ChatNotInApproveFilter, то вызывается функция chat_not_in_approve_list -router.message.register(chat_not_in_approve_list, ChatNotInApproveFilter(), F.text) - -router.message.register(get_chat_id, ChatModerOrAdminFilter(), Command("chatID")) - -router.message.register(delete_message, ChatModerOrAdminFilter(), Command("rm")) -router.message.register(error_access, Command("rm")) -router.message.register(error_access, Command("chatID")) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/README.md b/src/karkas_blocks/karkas_blocks/standard/database/README.md deleted file mode 100644 index 6553172..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/README.md +++ /dev/null @@ -1,48 +0,0 @@ -## Модуль DataBase - -Модуль DataBase предназначен для ведения и работы с базами данных Karkas. - -Модуль содержит в себе следующие таблицы: - -* `Chats` - таблица для хранения информации о чатах. -* `Users` - таблица для хранения информации о пользователях. -* `Messages` - таблица для хранения информации о сообщениях. -* `ChatStats` - таблица для хранения статистики чатов по дням. -* `UserStats` - таблица для хранения статистики пользователей по дням. - -Cтруктура таблицы `Chats`: -* `chat_id` - идентификатор чата. -* `chat_name` - название чата. -* `chat_type` - тип чата. (0 - Чат администраторов, 1 - Пользовательский чат, 3 - Чат разрешённых личных запросов к боту -10 - Не инициализированный чат) -* `chat_stats` - количество всех отправленных сообщений в чате. - -Cтруктура таблицы `Users`: -* `user_id` - идентификатор пользователя telegram. -* `user_tag` - тег пользователя telegram. -* `user_name` - имя пользователя telegram. -* `user_role` - роль пользователя в чате. (0 - Администратор, 1 - Модератор, 2 - Пользователь) -* `user_stats` - количество всех отправленных сообщений пользователем. -* `user_rep` - репутация пользователя. - -Cтруктура таблицы `Messages`: -* `message_chat_id` - идентификатор чата в котором отправлено сообщение. -* `message_id` - идентификатор сообщения. -* `messag_sender_id` - идентификатор пользователя отправившего сообщение. Если сообщение отправил бот, то -`messag_sender_id` = 0. -* `answer_to_message_id` - идентификатор сообщения на которое дан ответ. Если ответа нет или ответ на служебное -сообщение о создании топика в чатах с форумным типом, то `answer_to_message_id` = 0. -* `message_ai_model` - идентификатор модели нейросети, которая использовалась для генерации ответа. Если ответ' -сгенерирован не был, то `message_ai_model` = null. -* `message_text` - текст сообщения. - -Cтруктура таблицы `ChatStats`: -* `chat_id` - идентификатор чата для которого собрана статистика. -* `date` - дата на которую собрана статистика. -* `messages_count` - количество сообщений отправленных в чат за день. - -Cтруктура таблицы `UserStats`: -* `chat_id` - идентификатор чата для которого собрана статистика. -* `user_id` - идентификатор пользователя для которого собрана статистика. -* `date` - дата на которую собрана статистика. -* `messages_count` - количество сообщений отправленных пользователем в чат за день. diff --git a/src/karkas_blocks/karkas_blocks/standard/database/__init__.py b/src/karkas_blocks/karkas_blocks/standard/database/__init__.py deleted file mode 100644 index b282cf9..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from . import db_api, models, repositories - - -async def module_init(): - db_api.connect_database() diff --git a/src/karkas_blocks/karkas_blocks/standard/database/db_api.py b/src/karkas_blocks/karkas_blocks/standard/database/db_api.py deleted file mode 100644 index fca29b3..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/db_api.py +++ /dev/null @@ -1,301 +0,0 @@ -import peewee as pw -from aiogram.types import Message - -from .exceptions import NotExpectedModuleName -from .models.chat_stats import ChatStats -from .models.chats import Chats -from .models.db import database_proxy -from .models.fsm_data import FSMData -from .models.messages import Messages -from .models.user_stats import UserStats -from .models.users import Users - - -def connect_database(is_test: bool = False, module: str | None = None): - if module: - raise NotExpectedModuleName() - db_path = "database" - - database = pw.SqliteDatabase(f"{db_path}/Karkas.db") - database_proxy.initialize(database) - database.connect() - create_tables(database) - - return database, f"{db_path}/Karkas.db" - - -def create_tables(db: pw.SqliteDatabase): - """Создание таблиц""" - for table in Chats, Messages, Users, UserStats, ChatStats, FSMData: - if not table.table_exists(): - db.create_tables([table]) - - -def add_chat(chat_id, chat_name, chat_type=10, chat_stats=0): - chat, created = Chats.get_or_create( - id=chat_id, - defaults={ - "chat_name": chat_name, - "chat_type": chat_type, - "chat_all_stat": chat_stats, - }, - ) - if not created: - # Обновить существующий чат, если он уже существует - chat.chat_name = chat_name - chat.chat_type = chat_type - chat.chat_stats = chat_stats - chat.save() - - -def add_user( - user_id, - user_first_name, - user_last_name=None, - user_tag=None, - user_role=0, - user_stats=0, - user_rep=0, -): - if user_last_name is None: - user_name = user_first_name - else: - user_name = user_first_name + " " + user_last_name - - user, created = Users.get_or_create( - id=user_id, - defaults={ - "user_tag": user_tag, - "user_name": user_name, - "user_role": user_role, - "user_stats": user_stats, - "user_rep": user_rep, - }, - ) - if not created: - # Обновить существующего пользователя, если он уже существует - user.user_tag = user_tag - user.user_name = user_name - user.user_role = user_role - user.user_stats = user_stats - user.user_rep = user_rep - user.save() - - -def add_message(message: Message, message_ai_model=None): - if message.reply_to_message: - answer_to_message_id = message.reply_to_message.message_id - else: - answer_to_message_id = None - Messages.create( - message_chat_id=message.chat.id, - message_id=message.message_id, - message_sender_id=message.from_user.id, - answer_to_message_id=answer_to_message_id, - message_ai_model=message_ai_model, - message_text=message.text, - ) - - -def add_chat_stats(chat_id, date, messages_count): - ChatStats.create(chat_id=chat_id, date=date, messages_count=messages_count) - - -def add_user_stats(chat_id, user_id, date, messages_count): - UserStats.create( - chat_id=chat_id, user_id=user_id, date=date, messages_count=messages_count - ) - - -# Работа с таблицей чатов - - -def get_chat(chat_id): - return Chats.get_or_none(Chats.id == chat_id) - - -def change_chat_name(chat_id, new_chat_name): - query = Chats.update(chat_name=new_chat_name).where(Chats.id == chat_id) - query.execute() - - -def change_chat_type(chat_id, new_chat_type): - query = Chats.update(chat_type=new_chat_type).where(Chats.id == chat_id) - query.execute() - - -def get_chat_all_stat(chat_id): - chat = Chats.get_or_none(Chats.id == chat_id) - return chat.chat_all_stat if chat else None - - -# Работа с таблицей пользователей - - -def get_user(user_id) -> Users | None: - return Users.get_or_none(Users.id == user_id) - - -def get_user_tag(user_id): - user = Users.get_or_none(Users.id == user_id) - return user.user_tag if user else None - - -def get_user_id(user_tag): - user = Users.get_or_none(Users.user_tag == user_tag) - return user.id if user else None - - -def get_user_name(user_id): - user = Users.get_or_none(Users.id == user_id) - return user.user_name if user else None - - -def get_user_role(user_id: str): - user = Users.get_or_none(Users.id == user_id) - return user.user_role if user else None - - -def get_user_all_stats(user_id): - user = Users.get_or_none(Users.id == user_id) - return user.user_stats if user else None - - -def get_user_rep(user_id): - user = Users.get_or_none(Users.id == user_id) - return user.user_rep if user else None - - -def change_user_name(user_id, user_first_name, user_last_name=None): - if user_last_name is None: - new_user_name = user_first_name - else: - new_user_name = user_first_name + " " + user_last_name - query = Users.update(user_name=new_user_name).where(Users.id == user_id) - query.execute() - - -def change_user_tag(user_id, new_user_tag): - query = Users.update(user_tag=new_user_tag).where(Users.id == user_id) - query.execute() - - -def change_user_role(user_id, new_user_role): - query = Users.update(user_role=new_user_role).where(Users.id == user_id) - query.execute() - - -# Работа с таблицей сообщений - - -def get_message(message_chat_id, message_id): - return Messages.get_or_none( - Messages.message_chat_id == message_chat_id, - Messages.message_id == message_id, - ) - - -def get_message_sender_id(message_chat_id, message_id): - message = Messages.get_or_none( - Messages.message_chat_id == message_chat_id, Messages.message_id == message_id - ) - return message.message_sender_id if message else None - - -def get_message_text(message_chat_id, message_id): - message = Messages.get_or_none( - Messages.message_chat_id == message_chat_id, Messages.message_id == message_id - ) - return message.message_text if message else None - - -def get_message_ai_model(message_chat_id, message_id): - message = Messages.get_or_none( - Messages.message_chat_id == message_chat_id, Messages.message_id == message_id - ) - return message.message_ai_model if message else None - - -def get_answer_to_message_id(message_chat_id, message_id): - message = Messages.get_or_none( - Messages.message_chat_id == message_chat_id, Messages.message_id == message_id - ) - return message.answer_to_message_id if message else None - - -# Работа с таблицей статистики чатов - - -def get_chat_stats(chat_id): - chat_stats = {} - for chat_stat in ChatStats.select().where(ChatStats.chat_id == chat_id): - chat_stats[chat_stat.date] = chat_stat.messages_count - return chat_stats - - -# Работа с таблицей статистики пользователей - - -def get_user_stats(user_id): - user_stats = {} - for user_stat in UserStats.select().where(UserStats.user_id == user_id): - user_stats[user_stat.date] = user_stat.messages_count - return user_stats - - -# Функции обновления - - -def update_chat_all_stat(chat_id): - query = Chats.update(chat_all_stat=Chats.chat_all_stat + 1).where( - Chats.id == chat_id - ) - query.execute() - - -def update_chat_stats(chat_id, date): - chat_stats = ChatStats.get_or_none( - ChatStats.chat_id == chat_id, ChatStats.date == date - ) - if chat_stats: - query = ChatStats.update(messages_count=ChatStats.messages_count + 1).where( - ChatStats.chat_id == chat_id, ChatStats.date == date - ) - query.execute() - else: - ChatStats.create(chat_id=chat_id, date=date, messages_count=1) - - -def update_user_all_stat(user_id): - user = Users.get_or_none(Users.id == user_id) - if user: - query = Users.update(user_stats=Users.user_stats + 1).where(Users.id == user_id) - query.execute() - else: - Users.create(id=user_id, user_stats=1) - - -def update_user_rep(user_id): - user = Users.get_or_none(Users.id == user_id) - if user: - query = Users.update(user_rep=Users.user_rep + 1).where(Users.id == user_id) - query.execute() - else: - Users.create(id=user_id, user_rep=1) - - -def update_user_stats(chat_id, user_id, date): - user_stats = UserStats.get_or_none( - UserStats.chat_id == chat_id, - UserStats.user_id == user_id, - UserStats.date == date, - ) - if user_stats: - query = UserStats.update(messages_count=UserStats.messages_count + 1).where( - UserStats.chat_id == chat_id, - UserStats.user_id == user_id, - UserStats.date == date, - ) - query.execute() - else: - UserStats.create(chat_id=chat_id, user_id=user_id, date=date, messages_count=1) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/exceptions.py b/src/karkas_blocks/karkas_blocks/standard/database/exceptions.py deleted file mode 100644 index d315424..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/exceptions.py +++ /dev/null @@ -1,12 +0,0 @@ -class MissingModuleName(BaseException): - def __init__(self): - self.message = "Пропущено название директории модуля" - - super().__init__(self.message) - - -class NotExpectedModuleName(BaseException): - def __init__(self): - self.message = "Не ожидалось название директории модуля" - - super().__init__(self.message) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/info.json b/src/karkas_blocks/karkas_blocks/standard/database/info.json deleted file mode 100644 index 3534496..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/info.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "id": "standard.database", - "name": "Database", - "description": "Модуль для работы с БД", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": true, - "dependencies": {} -} diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/__init__.py b/src/karkas_blocks/karkas_blocks/standard/database/models/__init__.py deleted file mode 100644 index 19118f4..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .fsm_data import FSMData diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/chat_stats.py b/src/karkas_blocks/karkas_blocks/standard/database/models/chat_stats.py deleted file mode 100644 index b681407..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/chat_stats.py +++ /dev/null @@ -1,12 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class ChatStats(pw.Model): - class Meta: - database = database_proxy - - chat_id = pw.IntegerField(null=False) - date = pw.DateField(null=False) - messages_count = pw.IntegerField(null=False, default=0) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/chats.py b/src/karkas_blocks/karkas_blocks/standard/database/models/chats.py deleted file mode 100644 index f47cd8b..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/chats.py +++ /dev/null @@ -1,12 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class Chats(pw.Model): - class Meta: - database = database_proxy - - chat_name = pw.CharField(null=False) - chat_type = pw.IntegerField(null=False, default=10) - chat_all_stat = pw.IntegerField(null=False) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/db.py b/src/karkas_blocks/karkas_blocks/standard/database/models/db.py deleted file mode 100644 index cc1f8f7..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/db.py +++ /dev/null @@ -1,3 +0,0 @@ -from peewee import DatabaseProxy - -database_proxy = DatabaseProxy() diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/fsm_data.py b/src/karkas_blocks/karkas_blocks/standard/database/models/fsm_data.py deleted file mode 100644 index 1cbff67..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/fsm_data.py +++ /dev/null @@ -1,12 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class FSMData(pw.Model): - class Meta: - database = database_proxy - - key = pw.CharField(primary_key=True) - state = pw.CharField(null=True) - data = pw.CharField(null=True) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/messages.py b/src/karkas_blocks/karkas_blocks/standard/database/models/messages.py deleted file mode 100644 index c532b0d..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/messages.py +++ /dev/null @@ -1,15 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class Messages(pw.Model): - class Meta: - database = database_proxy - - message_chat_id = pw.IntegerField(null=False) - message_id = pw.IntegerField(null=False) - message_sender_id = pw.IntegerField(null=False) - answer_to_message_id = pw.IntegerField(null=True) - message_ai_model = pw.TextField(null=True) - message_text = pw.TextField(null=False) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/user_stats.py b/src/karkas_blocks/karkas_blocks/standard/database/models/user_stats.py deleted file mode 100644 index e0e96f2..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/user_stats.py +++ /dev/null @@ -1,13 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class UserStats(pw.Model): - class Meta: - database = database_proxy - - chat_id = pw.IntegerField(null=False) - user_id = pw.IntegerField(null=False) - date = pw.DateField(null=False) - messages_count = pw.IntegerField(null=False, default=0) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/models/users.py b/src/karkas_blocks/karkas_blocks/standard/database/models/users.py deleted file mode 100644 index 2dfd407..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/models/users.py +++ /dev/null @@ -1,14 +0,0 @@ -import peewee as pw - -from .db import database_proxy - - -class Users(pw.Model): - class Meta: - database = database_proxy - - user_tag = pw.CharField(null=True) - user_name = pw.CharField(null=False) # до 255 символов - user_role = pw.IntegerField(null=True, default=3) - user_stats = pw.IntegerField(null=True, default=0) - user_rep = pw.IntegerField(null=True, default=0) diff --git a/src/karkas_blocks/karkas_blocks/standard/database/repositories/__init__.py b/src/karkas_blocks/karkas_blocks/standard/database/repositories/__init__.py deleted file mode 100644 index 5d225ba..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/repositories/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .fsm_data import FSMDataRepository diff --git a/src/karkas_blocks/karkas_blocks/standard/database/repositories/fsm_data.py b/src/karkas_blocks/karkas_blocks/standard/database/repositories/fsm_data.py deleted file mode 100644 index f8526bc..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/repositories/fsm_data.py +++ /dev/null @@ -1,32 +0,0 @@ -from peewee import fn - -from ..models import FSMData - - -class FSMDataRepository: - def get(self, key: str): - return FSMData.get_or_none(key=key) - - def set_state(self, key: str, state: str): - FSMData.insert( - key=key, - state=state, - data=fn.COALESCE( - FSMData.select(FSMData.data).where(FSMData.key == key), None - ), - ).on_conflict( - conflict_target=[FSMData.key], - update={FSMData.state: state}, - ).execute() - - def set_data(self, key: str, data: str): - FSMData.insert( - key=key, - data=data, - state=fn.COALESCE( - FSMData.select(FSMData.state).where(FSMData.key == key), None - ), - ).on_conflict( - conflict_target=[FSMData.key], - update={FSMData.data: data}, - ).execute() diff --git a/src/karkas_blocks/karkas_blocks/standard/database/tests/__init__.py b/src/karkas_blocks/karkas_blocks/standard/database/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/karkas_blocks/karkas_blocks/standard/database/tests/database/file b/src/karkas_blocks/karkas_blocks/standard/database/tests/database/file deleted file mode 100644 index e29d9d5..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/tests/database/file +++ /dev/null @@ -1 +0,0 @@ -Эта директория для тестовой БД diff --git a/src/karkas_blocks/karkas_blocks/standard/database/tests/test_db.py b/src/karkas_blocks/karkas_blocks/standard/database/tests/test_db.py deleted file mode 100644 index 0052a7e..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/database/tests/test_db.py +++ /dev/null @@ -1,142 +0,0 @@ -# flake8: noqa - -import os -import unittest - -from ...exceptions.module_exceptions import MissingModuleName, NotExpectedModuleName -from ..db_api import * - - -class TestDatabaseAPI(unittest.TestCase): - database = None - path = None - - @classmethod - def setUpClass(cls): - cls.database, cls.path = connect_database(is_test=True, module="database") - create_tables(cls.database) - - def test_fail_connect(cls): - with cls.assertRaises(MissingModuleName): - cls.database, cls.path = connect_database(is_test=True) - - with cls.assertRaises(NotExpectedModuleName): - cls.database, cls.path = connect_database(module="database") - - def test_add_and_get_chat(self): - add_chat(chat_id=21, chat_role=0, chat_stats=0, chat_federation=0) - add_chat(chat_id=22, chat_role=1, chat_stats=100, chat_federation=1) - - chat1 = get_chat(21) - self.assertIsNotNone(chat1) - self.assertEqual(chat1.id, 21) - self.assertEqual(chat1.chat_role, 0) - - chat2 = get_chat(22) - self.assertIsNotNone(chat2) - self.assertEqual(chat2.id, 22) - self.assertEqual(chat2.chat_role, 1) - - def test_add_and_get_message(self): - add_message( - message_id=1, message_text="Test Message 1", message_sender=1, answer_id=2 - ) - add_message( - message_id=2, message_text="Test Message 2", message_sender=2, answer_id=1 - ) - - message1 = get_message(1) - self.assertIsNotNone(message1) - self.assertEqual(message1.id, 1) - self.assertEqual(message1.message_text, "Test Message 1") - - message2 = get_message(2) - self.assertIsNotNone(message2) - self.assertEqual(message2.id, 2) - self.assertEqual(message2.message_text, "Test Message 2") - - def test_add_and_get_user(self): - add_user( - user_id=100, - user_name="TestUser1", - user_tag="TestTag1", - user_role=0, - user_stats=10, - user_rep=5, - ) - add_user( - user_id=101, - user_name="TestUser2", - user_tag="TestTag2", - user_role=1, - user_stats=20, - user_rep=10, - ) - - user1 = get_user(100) - self.assertIsNotNone(user1) - self.assertEqual(user1.id, 100) - self.assertEqual(user1.user_name, "TestUser1") - - user2 = get_user(101) - self.assertIsNotNone(user2) - self.assertEqual(user2.id, 101) - self.assertEqual(user2.user_name, "TestUser2") - - def test_get_user_role(self): - add_user( - user_id=102, - user_name="TestUser3", - user_tag="TestTag3", - user_role=0, - user_stats=30, - user_rep=15, - ) - add_user( - user_id=103, - user_name="TestUser4", - user_tag="TestTag4", - user_role=1, - user_stats=40, - user_rep=20, - ) - - user_role1 = get_user_role(102) - self.assertEqual(user_role1, 0) - - user_role2 = get_user_role(103) - self.assertEqual(user_role2, 1) - - def test_change_user_name(self): - add_user( - user_id=104, - user_name="OldName1", - user_tag="TestTag5", - user_role=0, - user_stats=50, - user_rep=25, - ) - change_user_name(104, "NewName1") - updated_user1 = get_user(104) - self.assertEqual(updated_user1.user_name, "NewName1") - - add_user( - user_id=105, - user_name="OldName2", - user_tag="TestTag6", - user_role=1, - user_stats=60, - user_rep=30, - ) - change_user_name(105, "NewName2") - updated_user2 = get_user(105) - self.assertEqual(updated_user2.user_name, "NewName2") - - @classmethod - def tearDownClass(cls): - cls.database.close() - os.system(f"rm {cls.path}") # nosec - - -if __name__ == "__main__": - unittest.main() diff --git a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/README.md b/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/README.md deleted file mode 100644 index 9a39102..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Модуль FSM Database Storage - -Модуль `fsm_database_storage` реализует хранение состояний FSM (Finite State Machine) в базе данных. - -## Функциональность - -- Сохранение состояния FSM в базу данных. -- Получение состояния FSM из базы данных. -- Обновление данных состояния FSM. - -## Использование - -Модуль автоматически регистрирует хранилище состояний FSM при инициализации. diff --git a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/__init__.py b/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/__init__.py deleted file mode 100644 index 87a9ce8..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .fsm import module_init diff --git a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/fsm.py b/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/fsm.py deleted file mode 100644 index 1716158..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/fsm.py +++ /dev/null @@ -1,129 +0,0 @@ -import json -from typing import TYPE_CHECKING, Any, Dict, Optional - -from aiogram.fsm.state import State -from aiogram.fsm.storage.base import BaseStorage, StorageKey - -from karkas_core.modules_system.public_api import get_module, log -from karkas_core.modules_system.public_api.public_api import set_fsm - -if TYPE_CHECKING: - from karkas_blocks.standard.database.repositories import ( - FSMDataRepository as IFSMDataRepository, - ) - -FSMDataRepository: "type[IFSMDataRepository]" = get_module( - "standard.database", "repositories.FSMDataRepository" -) - - -def serialize_key(key: StorageKey) -> str: - return f"{key.bot_id}:{key.chat_id}:{key.user_id}" - - -def serialize_object(obj: object) -> str | None: - try: - return json.dumps(obj) - except Exception as e: - log(f"Serializing error! {e}") - return None - - -def deserialize_object(obj): - try: - return json.loads(obj) - except Exception as e: - log(f"Deserializing error! {e}") - return None - - -class SQLStorage(BaseStorage): - def __init__(self): - super().__init__() - self.repo = FSMDataRepository() - - async def set_state(self, key: StorageKey, state: State | None = None) -> None: - """ - Set state for specified key - - :param key: storage key - :param state: new state - """ - s_key = serialize_key(key) - s_state = state.state if isinstance(state, State) else state - - try: - self.repo.set_state(s_key, s_state) - except Exception as e: - log(f"FSM Storage database error: {e}") - - async def get_state(self, key: StorageKey) -> Optional[str]: - """ - Get key state - - :param key: storage key - :return: current state - """ - s_key = serialize_key(key) - - try: - s_state = self.repo.get(s_key) - return s_state.state if s_state else None - except Exception as e: - log(f"FSM Storage database error: {e}") - return None - - async def set_data(self, key: StorageKey, data: Dict[str, Any]) -> None: - """ - Write data (replace) - - :param key: storage key - :param data: new data - """ - s_key = serialize_key(key) - s_data = serialize_object(data) - - try: - self.repo.set_data(s_key, s_data) - except Exception as e: - log(f"FSM Storage database error: {e}") - - async def get_data(self, key: StorageKey) -> Optional[Dict[str, Any]]: - """ - Get current data for key - - :param key: storage key - :return: current data - """ - s_key = serialize_key(key) - - try: - s_data = self.repo.get(s_key) - return deserialize_object(s_data.data) if s_data else None - except Exception as e: - log(f"FSM Storage database error: {e}") - return None - - async def update_data( - self, key: StorageKey, data: Dict[str, Any] - ) -> Dict[str, Any]: - """ - Update data in the storage for key (like dict.update) - - :param key: storage key - :param data: partial data - :return: new data - """ - current_data = await self.get_data(key=key) - if not current_data: - current_data = {} - current_data.update(data) - await self.set_data(key=key, data=current_data) - return current_data.copy() - - async def close(self) -> None: # pragma: no cover - pass - - -async def module_init(): - set_fsm(SQLStorage()) diff --git a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/info.json b/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/info.json deleted file mode 100644 index 1302a34..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/fsm_database_storage/info.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "standard.fsm_database_storage", - "name": "FSM Database Storage", - "description": "Очень полезный модуль", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": false, - "dependencies": { - "required": { - "standard.database": "^1.0.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/info/README.md b/src/karkas_blocks/karkas_blocks/standard/info/README.md deleted file mode 100644 index 3f0597a..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/info/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Модуль Info - -Модуль `info` предоставляет информацию о пользователях и чатах. - -## Команды - -- `/info` - получить информацию о пользователе. -- `/chatinfo` - получить информацию о чате. - -## Использование - -Чтобы получить информацию о пользователе, отправьте команду `/info`, -ответив на сообщение пользователя или указав его тег. - -Чтобы получить информацию о чате, отправьте команду `/chatinfo`. diff --git a/src/karkas_blocks/karkas_blocks/standard/info/__init__.py b/src/karkas_blocks/karkas_blocks/standard/info/__init__.py deleted file mode 100644 index 96b1e7e..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/info/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .handlers import get_chat_info, get_user_info -from .main import module_init diff --git a/src/karkas_blocks/karkas_blocks/standard/info/handlers.py b/src/karkas_blocks/karkas_blocks/standard/info/handlers.py deleted file mode 100644 index 8c18816..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/info/handlers.py +++ /dev/null @@ -1,86 +0,0 @@ -# flake8: noqa - -from typing import TYPE_CHECKING - -from aiogram import Bot -from aiogram.types import Message - -from karkas_core.modules_system.public_api import get_module, log - -if TYPE_CHECKING: - from karkas_blocks.standard.database import db_api as IDbApi - from karkas_blocks.standard.roles import Roles as IRoles - -db_api: "IDbApi" = get_module( - "standard.database", - "db_api", -) - -Roles: "type[IRoles]" = get_module("standard.roles", "Roles") - - -async def get_info_answer_by_id(message: Message, bot: Bot, user_id: int): - ai_model = db_api.get_message_ai_model(message.chat.id, message.message_id) - if ai_model is not None: - await message.reply( - "Это сообщение было сгенерировано ботом используя модель: " + ai_model - ) - return - - if user_id == bot.id: - await message.reply("Это сообщение было отправлено ботом") - return - - user = db_api.get_user(user_id) - - if user is None: - await message.reply("Пользователь не найден") - log(f"Пользователь не найден: {user_id}, {user}") - return - - roles = Roles() - answer = ( - f"Пользователь: {user.user_name}\n" - f"Роль: {await roles.get_role_name(role_id=user.user_role)}\n" - f"Тег: @{user.user_tag}\n" - f"Кол-во сообщений: {user.user_stats}\n" - f"Репутация: {user.user_rep}" - ) - await message.reply(answer) - - -async def get_user_info(message: Message, bot: Bot): - # Проверяем содержимое сообщения, если содержит вторым элементом тег пользователя, то выводим информацию о нем - # Если сообщение отвечает на другое сообщение, то выводим информацию о пользователе, на чье сообщение был ответ - # Если это бот то выводим информацию, что это бот и какая модель yandexgpt используется - try: - if len(message.text.split()) > 1 and message.text.split()[1].startswith("@"): - user_tag = message.text.split()[1][1:] - user_id = db_api.get_user_id(user_tag) - if user_id: - await get_info_answer_by_id(message, bot, user_id) - else: - await message.reply(f"Пользователь с тегом @{user_tag} не найден") - elif message.reply_to_message: - user_id = message.reply_to_message.from_user.id - await get_info_answer_by_id(message, bot, user_id) - else: - await get_info_answer_by_id(message, bot, message.from_user.id) - except Exception as e: - await message.reply( - "В вашем запросе что-то пошло не так," - " попробуйте запросить информацию о пользователе по его тегу или ответив на его сообщение" - ) - # print(e) - log(e) - - -async def get_chat_info(message: Message, bot: Bot): - answer = ( - f"*Название чата:* {message.chat.title}\n" - f"*ID чата:* `{message.chat.id}`\n \n" - f"*Суммарное количество сообщений в чате:* {db_api.get_chat_all_stat(message.chat.id)}\n" - f"*Количество пользователей в чате:* {await bot.get_chat_member_count(message.chat.id)}\n" - f"*Количество администраторов в чате:* {len(await bot.get_chat_administrators(message.chat.id))}" - ) - await message.reply(answer, parse_mode="MarkdownV2") diff --git a/src/karkas_blocks/karkas_blocks/standard/info/info.json b/src/karkas_blocks/karkas_blocks/standard/info/info.json deleted file mode 100644 index 454f1c7..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/info/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "standard.info", - "name": "Info", - "description": "Модуль с информацией", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": false, - "dependencies": { - "required": { - "standard.roles": "^1.0.0", - "standard.database": "^1.0.0", - "standard.command_helper": "^1.0.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/info/main.py b/src/karkas_blocks/karkas_blocks/standard/info/main.py deleted file mode 100644 index 4756851..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/info/main.py +++ /dev/null @@ -1,20 +0,0 @@ -from aiogram import Router -from aiogram.filters import Command - -from karkas_core.modules_system.public_api import get_module, register_router - -from .handlers import get_chat_info, get_user_info - -register_command = get_module("standard.command_helper", "register_command") - - -async def module_init(): - router = Router() - - router.message.register(get_user_info, Command("info")) - router.message.register(get_chat_info, Command("chatinfo")) - - register_router(router) - - register_command("info", "Информация о пользователе") - register_command("chatinfo", "Информация о чате") diff --git a/src/karkas_blocks/karkas_blocks/standard/message_processing/README.md b/src/karkas_blocks/karkas_blocks/standard/message_processing/README.md deleted file mode 100644 index 86f6f15..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/message_processing/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Модуль Message Processing - -Модуль `message_processing` обрабатывает все входящие сообщения. - -## Функциональность - -- Проверка чата и пользователя на наличие в базе данных. -- Обновление информации о чате и пользователе. -- Добавление статистики сообщений. -- Передача сообщения модулю `yandexgpt`, если оно соответствует условиям. - -## Использование - -Модуль автоматически обрабатывает все входящие сообщения. diff --git a/src/karkas_blocks/karkas_blocks/standard/message_processing/__init__.py b/src/karkas_blocks/karkas_blocks/standard/message_processing/__init__.py deleted file mode 100644 index 90d8eda..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/message_processing/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .message_api import module_init diff --git a/src/karkas_blocks/karkas_blocks/standard/message_processing/info.json b/src/karkas_blocks/karkas_blocks/standard/message_processing/info.json deleted file mode 100644 index 6c72bed..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/message_processing/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "id": "standard.message_processing", - "name": "Info", - "description": "Модуль с информацией", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": false, - "dependencies": { - "required": { - "standard.roles": "^1.0.0", - "standard.database": "^1.0.0", - "standard.command_helper": "^1.0.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/message_processing/message_api.py b/src/karkas_blocks/karkas_blocks/standard/message_processing/message_api.py deleted file mode 100644 index 496f454..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/message_processing/message_api.py +++ /dev/null @@ -1,155 +0,0 @@ -# flake8: noqa - -from typing import TYPE_CHECKING - -from aiogram import Bot, F, Router, types - -from karkas_core.modules_system.public_api import get_module, log, register_router - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - -config: "IConfig" = get_module("standard.config", "config") - - -def get_yandexgpt_start_words(): - return config.get("yandexgpt::startword").split(" | ") - - -def get_yandexgpt_in_words(): - return config.get("yandexgpt::inword").split(" | ") - - -chat_not_in_approve = get_module("standard.filters", ["chat_not_in_approve"]) - -answer_to_message = get_module("external.yandexgpt", "answer_to_message") - -( - get_chat, - add_chat, - get_user, - add_user, - get_user_name, - change_user_name, - get_user_tag, - change_user_tag, - update_chat_all_stat, - update_user_all_stat, - add_message, -) = get_module( - "standard.database", - [ - "db_api.get_chat", - "db_api.add_chat", - "db_api.get_user", - "db_api.add_user", - "db_api.get_user_name", - "db_api.change_user_name", - "db_api.get_user_tag", - "db_api.change_user_tag", - "db_api.update_chat_all_stat", - "db_api.update_user_all_stat", - "db_api.add_message", - ], -) - - -async def chat_check(message: types.Message): - # Проверка наличия id чата в базе данных чатов - # Если чата нет в базе данных, то проверяем его в наличии в конфиге и если он там есть то добавляем его в БД - # Если чат есть в базе данных, то pass - if get_chat(message.chat.id) is None: - if not chat_not_in_approve(message): - # print(f"Chat in approve list: {message.chat.id} {message.chat.title}") - log(f"Chat in approve list: {message.chat.id} {message.chat.title}") - add_chat(message.chat.id, message.chat.title) - # print(f"Chat added: {message.chat.id} {message.chat.title}") - log(f"Chat added: {message.chat.id} {message.chat.title}") - else: - # print(f"Chat not in approve list: {message.chat.id} {message.chat.title}") - log(f"Chat not in approve list: {message.chat.id} {message.chat.title}") - pass - else: - # Проверяем обновление названия чата - chat = get_chat(message.chat.id) - if chat.chat_name != message.chat.title: - chat.chat_name = message.chat.title - chat.save() - # print(f"Chat updated: {message.chat.id} {message.chat.title}") - log(f"Chat updated: {message.chat.id} {message.chat.title}") - else: - # print(f"Chat already exists: {message.chat.id} {message.chat.title}") - log(f"Chat already exists: {message.chat.id} {message.chat.title}") - pass - - -async def user_check(message: types.Message): - # Проверка наличия id пользователя в базе данных пользователей - # Если пользователя нет в базе данных, то добавляем его - # Если пользователь есть в базе данных, то pass - current_user_name = "" - if message.from_user.last_name is None: - current_user_name = message.from_user.first_name - else: - current_user_name = ( - message.from_user.first_name + " " + message.from_user.last_name - ) - - if get_user(message.from_user.id) is None: - add_user( - message.from_user.id, - message.from_user.first_name, - message.from_user.last_name, - message.from_user.username, - ) - log(f"User added: {message.from_user.id} {current_user_name}") - else: - log( - f"User already exists: {message.from_user.id} {current_user_name} {message.from_user.username}" - ) - # Проверяем обновление имени пользователя - if get_user_name(message.from_user.id) != current_user_name: - change_user_name(message.from_user.id, current_user_name) - log(f"User name updated: {message.from_user.id} {current_user_name}") - # Проверяем обновление username пользователя - if get_user_tag(message.from_user.id) != message.from_user.username: - change_user_tag(message.from_user.id, message.from_user.username) - log( - f"User tag updated: {message.from_user.id} {message.from_user.username}" - ) - pass - - -async def add_stats(message: types.Message): - # Добавляем пользователю и чату статистику - update_chat_all_stat(message.chat.id) - update_user_all_stat(message.from_user.id) - - -async def message_processing(message: types.Message, bot: Bot): - await chat_check(message) - await user_check(message) - await add_stats(message) - - add_message(message) - # Если сообщение в начале содержит слово из списка или внутри сообщения содержится слово из списка или сообщение отвечает на сообщение бота - - if (message.text.split(" ")[0] in get_yandexgpt_start_words()) or ( - any(word in message.text for word in get_yandexgpt_in_words()) - ): - log("message_processing") - await answer_to_message(message, bot) - - elif message.reply_to_message is not None: - if message.reply_to_message.from_user.is_bot: - log("message_processing") - await answer_to_message(message, bot) - - -router = Router() -# Если сообщение содержит текст то вызывается функция message_processing -router.message.register(message_processing, F.text) - - -async def module_init(): - register_router(router) diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/README.md b/src/karkas_blocks/karkas_blocks/standard/miniapp/README.md deleted file mode 100644 index 0fd1008..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Модуль Miniapp - -Модуль `miniapp` реализует веб-интерфейс для бота, доступный через Telegram Mini Apps. - -## Функциональность - -- Регистрация страниц веб-интерфейса. -- Авторизация пользователей через Telegram. - -## Использование - -1. Импортируйте функцию `register_page`. -2. Вызовите функцию `register_page`, передав ей название страницы, ее путь, blueprint Dash и префикс. - -## Пример - -```python -from karkas_core.modules_system.public_api import get_module - -register_page = get_module("standard.miniapp", "register_page") - -register_page("Моя страница", "/my_page", my_blueprint, prefix="my_page") -``` diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/__init__.py b/src/karkas_blocks/karkas_blocks/standard/miniapp/__init__.py deleted file mode 100644 index 19b7130..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .lib import register_page -from .main import module_init, module_late_init diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/dash_telegram_auth.py b/src/karkas_blocks/karkas_blocks/standard/miniapp/dash_telegram_auth.py deleted file mode 100644 index 2d5a928..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/dash_telegram_auth.py +++ /dev/null @@ -1,146 +0,0 @@ -import flask -from aiogram.utils.web_app import safe_parse_webapp_init_data -from dash import Dash -from dash_extensions.enrich import Input, Output -from flask import request - -# TODO: добавить прокидывание BASE_PATH, т.к. это параметр из настроек - -WEBAPP_LOADER_TEMPLATE = """ - - - - - - Karkas - - - - - -
Loading...
- - - - -""" - - -def get_auth_server(bot_token: str): - server = flask.Flask(__name__) - - @server.route("/") - @server.route("/") - def webapp_loader(rest=None): - return flask.Response(WEBAPP_LOADER_TEMPLATE, mimetype="text/html") - - @server.before_request - def add_auth_data(): - init_data = request.cookies.get("tg_init_data") - if init_data: - try: - data = safe_parse_webapp_init_data(token=bot_token, init_data=init_data) - flask.g.user = data.user.model_dump() - except ValueError: - pass - - return server - - -def setup_auth_clientcallbacks(app: Dash): - app.clientside_callback( - """ - function(n_intervals) { - if (window.webAppData) { - return window.webAppData; - } - - function receiveMessage(event) { - if (event.data.type === 'webAppData') { - window.webAppData = event.data.webApp; - window.removeEventListener('message', receiveMessage); - } - } - - window.addEventListener('message', receiveMessage, false); - - return window.dash_clientside.no_update; - } - """, - Output("hidden-div", "children"), - Input("interval-component", "n_intervals"), - ) - - app.clientside_callback( - """ - function(pathname) { - window.parent.postMessage({ type: 'iframe-url-changed', pathname }, '*'); - } - """, - Input("url", "pathname"), - ) diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/info.json b/src/karkas_blocks/karkas_blocks/standard/miniapp/info.json deleted file mode 100644 index c961535..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/info.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "id": "standard.miniapp", - "name": "Miniapp", - "description": "Очень полезный модуль", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": false, - "dependencies": { - "required": { - "standard.config": { - "version": "^1.0.0", - "uses": [] - } - } - }, - "pythonDependencies": { - "required": { - "dash": "^2.17.1", - "dash_extensions": "^1.0.18", - "dash_bootstrap_components": "^1.6.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/lib.py b/src/karkas_blocks/karkas_blocks/standard/miniapp/lib.py deleted file mode 100644 index b14d14d..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/lib.py +++ /dev/null @@ -1,191 +0,0 @@ -import asyncio -from collections import OrderedDict -from typing import TYPE_CHECKING - -import dash -import dash_bootstrap_components as dbc -import flask -from dash_extensions.enrich import DashBlueprint, DashProxy, Input, Output, dcc, html -from dash_extensions.pages import setup_page_components - -from karkas_core.modules_system.public_api import get_module, log - -from .dash_telegram_auth import get_auth_server, setup_auth_clientcallbacks - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - from karkas_blocks.standard.roles import Roles as IRoles - -pages = OrderedDict() - - -def register_page(name, path, blueprint, prefix="", role="USER"): - pages[path] = { - "name": name, - "blueprint": blueprint, - "prefix": prefix, - "role": role, - } - - -def register_home_page(): - page = DashBlueprint() - page.layout = html.Div([html.H1("Главная")]) - register_page("Главная", path="/", blueprint=page) - - -register_home_page() - -config: "IConfig" = get_module("standard.config", "config") -Roles: "type[IRoles]" = get_module("standard.roles", "Roles") - - -def create_dash_app(requests_pathname_prefix: str = None) -> dash.Dash: - log(requests_pathname_prefix) - - real_prefix = f"{requests_pathname_prefix}_internal/" - - server = get_auth_server(config.get("core::token")) - - app = DashProxy( - pages_folder="", - use_pages=True, - suppress_callback_exceptions=True, - external_stylesheets=[ - dbc.themes.BOOTSTRAP, - dbc.icons.BOOTSTRAP, - ], - external_scripts=[ - # - "https://telegram.org/js/telegram-web-app.js" - ], - server=server, - requests_pathname_prefix=real_prefix, - routes_pathname_prefix="/_internal/", - # requests_pathname_prefix=requests_pathname_prefix, - meta_tags=[ - {"name": "viewport", "content": "width=device-width, initial-scale=1"}, - ], - ) - - # app.enable_dev_tools( - # dev_tools_ui=True, - # dev_tools_serve_dev_bundles=True, - # ) - - # Register pages - for path, page in pages.items(): - page["blueprint"].register(app, path, prefix=page["prefix"]) - - # Create navbar - navbar = dbc.Navbar( - dbc.Container( - [ - dbc.Button( - html.I(className="bi bi-list"), - id="open-offcanvas", - color="light", - className="me-2", - ), - dbc.NavbarBrand("Karkas"), - ] - ), - color="primary", - dark=True, - ) - - roles = Roles() - - def create_layout(): - user = getattr(flask.g, "user", None) - - if not user: - return html.Div() - - user_id = user["id"] - user_permission = asyncio.run(roles.get_user_permission(user_id)) or "USER" - - available_pages = { - path: page - for path, page in pages.items() - if (isinstance(page["role"], list) and user_permission in page["role"]) - or page["role"] == user_permission - or page["role"] == "USER" - } - - # Create sidebar - sidebar = dbc.Offcanvas( - id="offcanvas", - title="Меню", - is_open=False, - children=[ - dbc.Nav( - [ - dbc.NavLink( - page["name"], - href=f"{real_prefix}/{path.lstrip('/')}", - id={"type": "nav-link", "index": path}, - ) - for path, page in available_pages.items() - ], - vertical=True, - pills=True, - ), - ], - ) - - layout = html.Div( - [ - dcc.Location(id="url", refresh=False), - dcc.Interval( - id="init-telegram-interval", - interval=100, - n_intervals=0, - max_intervals=1, - ), - navbar, - sidebar, - dash.page_container, - setup_page_components(), - ] - ) - - return layout - - app.layout = create_layout - - setup_auth_clientcallbacks(app) - - # Открытие на кнопку меню - app.clientside_callback( - """ - function(n_clicks) { - if (n_clicks == null) { - return false; - } - return true; - } - """, - Output( - "offcanvas", - "is_open", - ), - Input("open-offcanvas", "n_clicks"), - ) - - # Закрываем offcanvas при клике на ссылку в меню - app.clientside_callback( - """ - function(n_clicks) { - if (n_clicks == null) { - return true; - } - return false; - } - """, - Output("offcanvas", "is_open", allow_duplicate=True), - Input({"type": "nav-link", "index": dash.dependencies.ALL}, "n_clicks"), - prevent_initial_call="initial_duplicate", - ) - - return app diff --git a/src/karkas_blocks/karkas_blocks/standard/miniapp/main.py b/src/karkas_blocks/karkas_blocks/standard/miniapp/main.py deleted file mode 100644 index 404e3fb..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/miniapp/main.py +++ /dev/null @@ -1,54 +0,0 @@ -from typing import TYPE_CHECKING - -from aiogram import types -from fastapi.middleware.wsgi import WSGIMiddleware - -from karkas_core.modules_system.public_api import ( - Storage, - get_module, - set_chat_menu_button, -) - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - -config: "IConfig" = get_module("standard.config", "config") - - -def get_link(): - pass - - -def module_init(): - - config.register( - "miniapp::prefix", - "string", - default_value="/webapp/", - visible=False, - ) - - config.register( - "miniapp::public_url", - "string", - visible=False, - ) - - pass - - -def register_page(): - pass - - -async def module_late_init(): - from .lib import create_dash_app - - dash_app = create_dash_app(requests_pathname_prefix=config.get("miniapp::prefix")) - - Storage.set("webapp", WSGIMiddleware(dash_app.server)) - - web_app_info = types.WebAppInfo(url=config.get("miniapp::public_url")) - menu_button = types.MenuButtonWebApp(text="Меню", web_app=web_app_info) - - await set_chat_menu_button(menu_button) diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/README.md b/src/karkas_blocks/karkas_blocks/standard/roles/README.md deleted file mode 100644 index 3311af7..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Модуль Roles - -Модуль `roles` управляет ролями пользователей. - -## Роли - -- `USER` - обычный пользователь. -- `MODERATOR` - модератор. -- `ADMIN` - администратор. -- `BOT` - бот. - -## Функциональность - -- Проверка роли пользователя. -- Получение имени роли по ID. -- Получение ID роли по имени. - -## Использование - -1. Импортируйте класс `Roles`. -2. Создайте экземпляр класса. -3. Вызовите методы класса для проверки роли пользователя или получения имени роли. - -## Пример - -```python -from karkas_core.modules_system.public_api import get_module - -Roles = get_module("standard.roles", "Roles") - -roles = Roles() - -is_admin = await roles.check_admin_permission(user_id) - -role_name = await roles.get_role_name(role_id) -``` diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/__init__.py b/src/karkas_blocks/karkas_blocks/standard/roles/__init__.py deleted file mode 100644 index 714df8c..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from .main import module_init -from .roles import Roles diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/info.json b/src/karkas_blocks/karkas_blocks/standard/roles/info.json deleted file mode 100644 index 3f6b80d..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/info.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "id": "standard.roles", - "name": "Roles", - "description": "Модуль для работы с ролями", - "author": "Karkas Team", - "version": "1.0.0", - "privileged": true, - "dependencies": { - "required": { - "standard.config": "^1.0.0", - "standard.database": "^1.0.0" - } - } -} diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/main.py b/src/karkas_blocks/karkas_blocks/standard/roles/main.py deleted file mode 100644 index 4c51ea6..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/main.py +++ /dev/null @@ -1,37 +0,0 @@ -from typing import TYPE_CHECKING - -from karkas_core.modules_system.public_api import get_module - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - - -def module_init(): - config: "IConfig" = get_module("standard.config", "config") - - config.register( - "roles::admin", - "number", - default_value=2, - visible=False, - ) - config.register( - "roles::moderator", - "number", - default_value=1, - visible=False, - ) - config.register( - "roles::user", - "number", - default_value=0, - visible=False, - ) - config.register( - "roles::bot", - "number", - default_value=3, - visible=False, - ) - - pass diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/roles.py b/src/karkas_blocks/karkas_blocks/standard/roles/roles.py deleted file mode 100644 index 39b6bac..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/roles.py +++ /dev/null @@ -1,72 +0,0 @@ -from typing import TYPE_CHECKING - -from karkas_core.modules_system.public_api import get_module - -if TYPE_CHECKING: - from karkas_blocks.standard.config import IConfig - from karkas_blocks.standard.database.db_api import get_user_role as IGetUserRoleType - -get_user_role: "IGetUserRoleType" = get_module( - "standard.database", "db_api.get_user_role" -) -config: "IConfig" = get_module("standard.config", "config") - - -class Roles: - user = "USER" - moderator = "MODERATOR" - admin = "ADMIN" - bot = "BOT" - - def __init__(self): - pass - - def update_roles(self): - self.user_role_id = config.get("roles::user") - self.moderator_role_id = config.get("roles::moderator") - self.admin_role_id = config.get("roles::admin") - self.bot_role_id = config.get("roles::bot") - - async def check_admin_permission(self, user_id): - self.update_roles() - match get_user_role(user_id): - case self.admin_role_id: - return True - case _: - return False - - async def check_moderator_permission(self, user_id): - self.update_roles() - match get_user_role(user_id): - case self.moderator_role_id: - return True - case _: - return False - - async def get_role_name(self, role_id): - self.update_roles() - match role_id: - case self.admin_role_id: - return self.admin - case self.moderator_role_id: - return self.moderator - case self.user_role_id: - return self.user - case self.bot_role_id: - return self.bot - case _: - raise ValueError(f"Нет роли с id={role_id}") - - async def get_user_permission(self, user_id): - self.update_roles() - match get_user_role(user_id): - case self.admin_role_id: - return self.admin - case self.moderator_role_id: - return self.moderator - case self.user_role_id: - return self.user - case self.bot_role_id: - return self.bot - case _: - return None diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/tests/__init__.py b/src/karkas_blocks/karkas_blocks/standard/roles/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/karkas_blocks/karkas_blocks/standard/roles/tests/test_roles.py b/src/karkas_blocks/karkas_blocks/standard/roles/tests/test_roles.py deleted file mode 100644 index 4828306..0000000 --- a/src/karkas_blocks/karkas_blocks/standard/roles/tests/test_roles.py +++ /dev/null @@ -1,80 +0,0 @@ -import os -import unittest - -from ...database.db_api import add_user, connect_database, create_tables -from ..roles import Roles - - -class TestRoles(unittest.IsolatedAsyncioTestCase): - database = None - path = None - - @classmethod - def setUpClass(cls): - cls.roles = Roles() - cls.database, cls.path = connect_database(is_test=True, module="roles") - create_tables(cls.database) - - add_user( - user_id=1, - user_name="TestUser1", - user_tag="TestTag1", - user_role=0, - user_stats=30, - user_rep=15, - ) - add_user( - user_id=2, - user_name="TestUser3", - user_tag="TestTag3", - user_role=1, - user_stats=30, - user_rep=15, - ) - add_user( - user_id=3, - user_name="TestUser4", - user_tag="TestTag4", - user_role=2, - user_stats=30, - user_rep=15, - ) - add_user( - user_id=4, - user_name="TestUser2", - user_tag="TestTag2", - user_role=3, - user_stats=30, - user_rep=15, - ) - - async def test_check_admin_permission(cls): - cls.assertTrue(await cls.roles.check_admin_permission(1)) - cls.assertFalse(await cls.roles.check_admin_permission(2)) - cls.assertFalse(await cls.roles.check_admin_permission(3)) - cls.assertFalse(await cls.roles.check_admin_permission(4)) - - async def test_check_moderator_permission(cls): - cls.assertTrue(await cls.roles.check_moderator_permission(2)) - cls.assertFalse(await cls.roles.check_moderator_permission(0)) - cls.assertFalse(await cls.roles.check_moderator_permission(1)) - cls.assertFalse(await cls.roles.check_moderator_permission(3)) - - async def test_get_role_name(cls): - cls.assertEqual(await cls.roles.get_role_name(cls.roles.admin_role_id), "ADMIN") - cls.assertEqual( - await cls.roles.get_role_name(cls.roles.moderator_role_id), "MODERATOR" - ) - 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") - with cls.assertRaises(ValueError): - await cls.roles.get_role_name(999) # Несуществующий ID роли - - @classmethod - def tearDownClass(cls): - cls.database.close() - os.system(f"rm {cls.path}") # nosec - - -if __name__ == "__main__": - unittest.main() diff --git a/src/karkas_blocks/pyproject.toml b/src/karkas_blocks/pyproject.toml index 375774b..3fefa6a 100644 --- a/src/karkas_blocks/pyproject.toml +++ b/src/karkas_blocks/pyproject.toml @@ -9,13 +9,13 @@ readme = "README.md" python = "~3.12" karkas-core = { path = "../karkas_core", develop = true } -peewee = "^3.17.6" +# peewee = "^3.17.6" pyyaml = "^6.0.1" -dash = "^2.17.1" -dash-extensions = "^1.0.18" -dash-bootstrap-components = "^1.6.0" +# dash = "^2.17.1" +# dash-extensions = "^1.0.18" +# dash-bootstrap-components = "^1.6.0" [tool.poetry-monorepo.deps] enabled = true