3.0 Выпуск в PrimoRU
This commit is contained in:
1
.idea/PRIMOWORLD.iml
generated
1
.idea/PRIMOWORLD.iml
generated
@@ -23,6 +23,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/BotCode/routers/commands" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/BotCode/routers/commands" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/BotCode/routers/common" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/BotCode/routers/common" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/BotCode/utils" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/BotCode/utils" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/BotLibrary/sql" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.13 (PRIMOWORLD)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.13 (PRIMOWORLD)" jdkType="Python SDK" />
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# BotCode/inline/reklama.py
|
# BotCode/inline/reklama.py
|
||||||
# Работа с инлайн запросами на рекламу
|
# Работа с инлайн запросами на рекламу
|
||||||
|
|
||||||
from aiogram import Router, types
|
from aiogram import Router
|
||||||
from aiogram.types import InlineQueryResultPhoto
|
from aiogram.types import (InlineQueryResultPhoto, InlineQuery, CallbackQuery,
|
||||||
|
InlineKeyboardMarkup, InlineKeyboardButton)
|
||||||
from BotLibrary import bot
|
from BotLibrary import bot
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
# Настройка экспорта в модули
|
||||||
@@ -14,13 +15,13 @@ f"""Это сообщение с изображением и инлайн кно
|
|||||||
|
|
||||||
|
|
||||||
@router.callback_query(lambda c: c.data == 'button_1')
|
@router.callback_query(lambda c: c.data == 'button_1')
|
||||||
async def process_callback_button(callback_query: types.CallbackQuery) -> None:
|
async def process_callback_button(callback_query: CallbackQuery) -> None:
|
||||||
await bot.answer_callback_query(callback_query.id, text="Вы нажали первую кнопку!")
|
await bot.answer_callback_query(callback_query.id, text="Вы нажали первую кнопку!")
|
||||||
await bot.send_message(callback_query.from_user.id, "Ответ на вашу кнопку.")
|
await bot.send_message(callback_query.from_user.id, "Ответ на вашу кнопку.")
|
||||||
|
|
||||||
|
|
||||||
@router.inline_query()
|
@router.inline_query()
|
||||||
async def inline_echo(inline_query: types.InlineQuery) -> None:
|
async def inline_echo(inline_query: InlineQuery) -> None:
|
||||||
# Содержимое запроса
|
# Содержимое запроса
|
||||||
query = inline_query.query
|
query = inline_query.query
|
||||||
|
|
||||||
@@ -36,10 +37,10 @@ async def inline_echo(inline_query: types.InlineQuery) -> None:
|
|||||||
photo_url=image_url, # URL изображения
|
photo_url=image_url, # URL изображения
|
||||||
thumbnail_url=image_url, # Миниатюра изображения
|
thumbnail_url=image_url, # Миниатюра изображения
|
||||||
caption=text_msg, # Текст, который будет показываться под изображением
|
caption=text_msg, # Текст, который будет показываться под изображением
|
||||||
reply_markup=types.InlineKeyboardMarkup(
|
reply_markup=InlineKeyboardMarkup(
|
||||||
inline_keyboard=[
|
inline_keyboard=[
|
||||||
[types.InlineKeyboardButton(text="Посмотреть инфо-канал", url="https://t.me/adeptusfiziks")],
|
[InlineKeyboardButton(text="Посмотреть инфо-канал", url="https://t.me/adeptusfiziks")],
|
||||||
[types.InlineKeyboardButton(text="Вторая кнопка", callback_data="button_1")],
|
[InlineKeyboardButton(text="Вторая кнопка", callback_data="button_1")],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,15 +2,14 @@
|
|||||||
# Работа с командой /stats, для получения информации о себе
|
# Работа с командой /stats, для получения информации о себе
|
||||||
|
|
||||||
from aiogram import types
|
from aiogram import types
|
||||||
from BotLibrary import CommandHandler, bot
|
from BotLibrary import CommandHandler, bot, db
|
||||||
from SQLite3 import status_user
|
|
||||||
|
|
||||||
# Настройки экспорта в модули
|
# Настройки экспорта в модули
|
||||||
__all__ = ("ban_cmd",)
|
__all__ = ("ban_cmd",)
|
||||||
|
|
||||||
# Функция блокировки пользователя
|
# Функция блокировки пользователя
|
||||||
async def ban_user(message: types.Message, *args, **kwargs) -> None:
|
async def ban_user(message: types.Message, *args, **kwargs) -> None:
|
||||||
status = await status_user(message)
|
status = db.get_user_status(message)
|
||||||
if status not in ('Пользователь', 'Забаннен'):
|
if status not in ('Пользователь', 'Забаннен'):
|
||||||
# Проверка, что команда вызвана с упоминанием пользователя
|
# Проверка, что команда вызвана с упоминанием пользователя
|
||||||
args = message.text.split()
|
args = message.text.split()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# BotCode/routers/commands/user_cmd/start_time_cmd.py
|
# BotCode/routers/commands/user_cmd/start_time_cmd.py
|
||||||
#
|
# Команда на выдачу погоды определенного города
|
||||||
|
|
||||||
from BotLibrary import CommandHandler
|
from BotLibrary import CommandHandler
|
||||||
from BotCode.utils import get_weather
|
from BotCode.utils import get_weather
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
from aiogram import Router, types
|
from aiogram import Router, types
|
||||||
from BotLibrary import *
|
from BotLibrary import *
|
||||||
from SQLite3 import base_sql, status_user
|
|
||||||
|
|
||||||
# Настройка экспорта модулей и роутера
|
# Настройка экспорта модулей и роутера
|
||||||
__all__ = ("router",)
|
__all__ = ("router",)
|
||||||
@@ -12,6 +11,6 @@ router = Router(name="common_msg_router")
|
|||||||
# Обработчик всех сообщений
|
# Обработчик всех сообщений
|
||||||
@router.message()
|
@router.message()
|
||||||
async def all_messages(message: types.Message) -> None:
|
async def all_messages(message: types.Message) -> None:
|
||||||
await base_sql(message)
|
db.update_user(message)
|
||||||
await status_user(message)
|
db.update_user_messages(message)
|
||||||
Logs.msg(message)
|
Logs.msg(message)
|
||||||
|
|||||||
@@ -1,22 +1,34 @@
|
|||||||
# BotCode/utils/admin_lists.py
|
# BotCode/utils/admin_lists.py
|
||||||
# Составления листа администраторов
|
# Составления листа администраторов
|
||||||
|
|
||||||
|
from aiogram.types import Message
|
||||||
from BotLibrary import bot
|
from BotLibrary import bot
|
||||||
|
from ProjectsFiles import BotVar
|
||||||
|
|
||||||
# Настройки экспорта в модули
|
# Настройки экспорта в модули
|
||||||
__all__ = ("admin_lists",)
|
__all__ = ("admin_lists",)
|
||||||
|
|
||||||
|
async def admin_lists(chat_id: int = None, message: Message = None) -> str:
|
||||||
|
"""
|
||||||
|
Функция составления словаря администраторов.
|
||||||
|
|
||||||
# Функция составления словаря администраторов
|
:param message: Объект сообщения от пользователя.
|
||||||
async def admin_lists(chat_id: int) -> str:
|
:param chat_id: ID-чата в котором будет проводиться работа.
|
||||||
|
:return: Строка с юзерами администрации.
|
||||||
|
"""
|
||||||
|
chat_id = chat_id if isinstance(chat_id, int) else message.chat.id
|
||||||
admins = await bot.get_chat_administrators(chat_id)
|
admins = await bot.get_chat_administrators(chat_id)
|
||||||
|
|
||||||
# Формируем список упоминаний администраторов
|
# Формируем список упоминаний администраторов
|
||||||
admin_mentions = []
|
admin_mentions = []
|
||||||
for admin in admins:
|
for admin in admins:
|
||||||
if admin.user.is_bot:
|
if admin.user.is_bot:
|
||||||
continue
|
continue
|
||||||
|
if BotVar.parse_mode == "HTML":
|
||||||
admin_mentions.append(
|
admin_mentions.append(
|
||||||
f"@{admin.user.username}" if admin.user.username else f"<a href=\"tg://user?id={admin.user.id}\">{admin.user.full_name}</a>")
|
f"@{admin.user.username}" if admin.user.username else f"<a href=\"tg://user?id={admin.user.id}\">{admin.user.full_name}</a>")
|
||||||
|
elif BotVar.parse_mode == "MarkdownV2":
|
||||||
|
admin_mentions.append(
|
||||||
|
f"@{admin.user.username}" if admin.user.username else f"[{admin.user.full_name}](tg://user?id={admin.user.id})")
|
||||||
admins_text = ", ".join(admin_mentions) if admin_mentions else "Нет администраторов"
|
admins_text = ", ".join(admin_mentions) if admin_mentions else "Нет администраторов"
|
||||||
return admins_text
|
return admins_text
|
||||||
|
|||||||
@@ -8,18 +8,28 @@ from BotLibrary import bot
|
|||||||
# Настройки экспорта в модули
|
# Настройки экспорта в модули
|
||||||
__all__ = ("hidden_admins_message",)
|
__all__ = ("hidden_admins_message",)
|
||||||
|
|
||||||
|
|
||||||
# Функция составления словаря администраторов
|
|
||||||
async def hidden_admins_message(message: types.Message = None,
|
async def hidden_admins_message(message: types.Message = None,
|
||||||
chat_id: int = None,
|
chat_id: int = None,
|
||||||
text: str = "",
|
text: str = "",
|
||||||
msg: bool = True, *args) -> str | None:
|
msg: bool = True, *args) -> str | None:
|
||||||
|
"""
|
||||||
|
Формирует скрытые ссылки на администраторов чата в Markdown-разметке.
|
||||||
|
|
||||||
|
:param message: Объект сообщения от пользователя (если chat_id не указан, ID чата берется из него).
|
||||||
|
:param chat_id: ID чата, в котором нужно получить список администраторов (если не указан, берется из message).
|
||||||
|
:param text: Дополнительный текст, который будет добавлен к результату.
|
||||||
|
:param msg: Определяет, возвращать ли результат (True) или отправлять его в чат (False).
|
||||||
|
:param args: Дополнительные аргументы (не используются, оставлены для совместимости с шаблоном).
|
||||||
|
:return: Строка со скрытыми ссылками на администраторов и добавленным текстом (если msg=True), иначе None.
|
||||||
|
"""
|
||||||
chat_id = chat_id if isinstance(chat_id, int) else message.chat.id
|
chat_id = chat_id if isinstance(chat_id, int) else message.chat.id
|
||||||
admins = await bot.get_chat_administrators(chat_id)
|
admins = await bot.get_chat_administrators(chat_id)
|
||||||
|
|
||||||
hidden_links = "".join(
|
hidden_links = "".join(
|
||||||
markdown.hide_link(f"tg://user?id={admin.user.id}")
|
markdown.hide_link(f"tg://user?id={admin.user.id}")
|
||||||
for admin in admins if not admin.user.is_bot
|
for admin in admins if not admin.user.is_bot
|
||||||
)
|
)
|
||||||
|
|
||||||
result = f"{hidden_links}{text}"
|
result = f"{hidden_links}{text}"
|
||||||
if msg:
|
if msg:
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -1,10 +1,17 @@
|
|||||||
import aiohttp
|
import aiohttp
|
||||||
|
from aiogram.types import Message
|
||||||
from ProjectsFiles import weather_api_key
|
from ProjectsFiles import weather_api_key
|
||||||
|
|
||||||
# Настройки экспорта в модули
|
# Настройки экспорта в модули
|
||||||
__all__ = ("get_weather",)
|
__all__ = ("get_weather",)
|
||||||
|
|
||||||
async def get_weather(message, *args) -> str:
|
async def get_weather(message: Message, *args) -> str:
|
||||||
|
"""
|
||||||
|
Обрабатывает запрос о погоде для указанного города и возвращает информацию о текущей погоде.
|
||||||
|
|
||||||
|
:param message: Объект сообщения от пользователя.
|
||||||
|
:return: Возвращает ответ о погоде в указанном городе.
|
||||||
|
"""
|
||||||
# Извлекаем город из сообщения
|
# Извлекаем город из сообщения
|
||||||
command_parts = message.text.split(maxsplit=1)
|
command_parts = message.text.split(maxsplit=1)
|
||||||
print(command_parts[1])
|
print(command_parts[1])
|
||||||
|
|||||||
@@ -5,37 +5,7 @@
|
|||||||
from .analytics import *
|
from .analytics import *
|
||||||
from .loggers import *
|
from .loggers import *
|
||||||
from .samples import *
|
from .samples import *
|
||||||
|
from .sql import *
|
||||||
from .system import *
|
from .system import *
|
||||||
from .timer import *
|
from .timer import *
|
||||||
from .validators import *
|
from .validators import *
|
||||||
|
|
||||||
from SQLite3 import create_user_db
|
|
||||||
from ProjectsFiles import Permissions
|
|
||||||
|
|
||||||
|
|
||||||
# Функция установки
|
|
||||||
async def setup():
|
|
||||||
# Запуск логеров
|
|
||||||
await setup_logger()
|
|
||||||
|
|
||||||
# Получение информации о боте
|
|
||||||
await bot_get_info()
|
|
||||||
|
|
||||||
# Вывод сообщение о запуске
|
|
||||||
Logs.start(text=f"Начало запуска бота @{BotInfo.username}...")
|
|
||||||
Logs.console()
|
|
||||||
|
|
||||||
# Автоматическое создание базы данных при отсутствии
|
|
||||||
await create_user_db()
|
|
||||||
|
|
||||||
# Создание пустых директорий
|
|
||||||
await setup_directories()
|
|
||||||
|
|
||||||
# Нужно ли удалить веб-хук
|
|
||||||
if Permissions.delete_webhook:
|
|
||||||
await bot.delete_webhook()
|
|
||||||
|
|
||||||
await set_adm_rights()
|
|
||||||
await set_bot_name()
|
|
||||||
await set_bot_description()
|
|
||||||
await set_bot_short_description()
|
|
||||||
|
|||||||
@@ -1,25 +1,23 @@
|
|||||||
# BotLibrary/analytics/type_chat.py
|
# BotLibrary/analytics/type_chat.py
|
||||||
# Определение типа чата
|
# Определение типа чата
|
||||||
|
|
||||||
from aiogram import types
|
from aiogram.types import Message
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
# Настройка экспорта в модули
|
||||||
__all__ = ("type_chat",)
|
__all__ = ("type_chat",)
|
||||||
|
|
||||||
# Проверка на тип чата
|
async def type_chat(message: Message) -> str:
|
||||||
async def type_chat(message: types.Message) -> str:
|
|
||||||
"""
|
"""
|
||||||
Преобразует информацию о чате в понятные значения.
|
Преобразует информацию о чате в его тип на русском языке.
|
||||||
|
|
||||||
:param message: Объект сообщения из aiogram.
|
:param message: Объект сообщения из aiogram, содержащий информацию о чате.
|
||||||
:return: Тип чата строкой.
|
:return: Тип чата строкой.
|
||||||
"""
|
"""
|
||||||
chat_type: str = message.chat.type
|
chat_types: dict[str, str] = {
|
||||||
if chat_type == "private":
|
"private": "Личный",
|
||||||
return "Личный"
|
"group": "Группа",
|
||||||
elif chat_type == "group" or chat_type == "supergroup":
|
"supergroup": "Группа",
|
||||||
return "Группа"
|
"channel": "Канал",
|
||||||
elif chat_type == "channel":
|
}
|
||||||
return "Канал"
|
|
||||||
else:
|
return chat_types.get(message.chat.type, "Неизвестный тип чата")
|
||||||
return "Неизвестный тип чата."
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ from aiogram.types import ContentType, Message
|
|||||||
# Настройка экспорта из модуля
|
# Настройка экспорта из модуля
|
||||||
__all__ = ("type_msg",)
|
__all__ = ("type_msg",)
|
||||||
|
|
||||||
# Функция определения типа сообщения
|
|
||||||
def type_msg(message: Message) -> str:
|
def type_msg(message: Message) -> str:
|
||||||
"""
|
"""
|
||||||
Функция для определения типа сообщения на основе его содержимого.
|
Функция для определения типа сообщения на основе его содержимого.
|
||||||
@@ -50,7 +49,7 @@ def type_msg(message: Message) -> str:
|
|||||||
ContentType.INVOICE: "Счет",
|
ContentType.INVOICE: "Счет",
|
||||||
ContentType.SUCCESSFUL_PAYMENT: "Успешный платеж",
|
ContentType.SUCCESSFUL_PAYMENT: "Успешный платеж",
|
||||||
ContentType.REFUNDED_PAYMENT: "Возврат платежа",
|
ContentType.REFUNDED_PAYMENT: "Возврат платежа",
|
||||||
ContentType.USERS_SHARED: "Пользователи поделились",
|
ContentType.USERS_SHARED: "Пользователь поделился",
|
||||||
ContentType.CHAT_SHARED: "Чат был передан",
|
ContentType.CHAT_SHARED: "Чат был передан",
|
||||||
ContentType.CONNECTED_WEBSITE: "Подключенный веб-сайт",
|
ContentType.CONNECTED_WEBSITE: "Подключенный веб-сайт",
|
||||||
ContentType.WRITE_ACCESS_ALLOWED: "Разрешение на запись",
|
ContentType.WRITE_ACCESS_ALLOWED: "Разрешение на запись",
|
||||||
@@ -77,9 +76,20 @@ def type_msg(message: Message) -> str:
|
|||||||
# Получение типа сообщения
|
# Получение типа сообщения
|
||||||
message_type: str = message.content_type
|
message_type: str = message.content_type
|
||||||
|
|
||||||
|
|
||||||
# Если это контакт, добавляем номер телефона
|
# Если это контакт, добавляем номер телефона
|
||||||
if message_type == ContentType.CONTACT and message.contact:
|
if message_type == ContentType.CONTACT and message.contact:
|
||||||
return f"{content_types.get(message_type, 'Контакт')}: {message.contact.phone_number}"
|
return f"{content_types.get(message_type, 'Контакт')}: {message.contact.phone_number}"
|
||||||
|
|
||||||
|
# Если это пользователи, добавляем их ID
|
||||||
|
if message_type == ContentType.USERS_SHARED and message.users_shared:
|
||||||
|
user_ids = ", ".join(map(str, message.users_shared.user_ids))
|
||||||
|
return f"{content_types.get(message_type, 'Пользователь поделился')}: {user_ids}"
|
||||||
|
|
||||||
|
# Если это переданный чат, добавляем его ID
|
||||||
|
if message_type == ContentType.CHAT_SHARED and message.chat_shared:
|
||||||
|
return f"{content_types.get(message_type, 'Чат был передан')}: {message.chat_shared.chat_id}"
|
||||||
|
|
||||||
|
|
||||||
# Возвращаем описание типа сообщения, если оно есть в словаре, иначе "Неизвестный тип"
|
# Возвращаем описание типа сообщения, если оно есть в словаре, иначе "Неизвестный тип"
|
||||||
return content_types.get(message_type, "Неизвестный тип")
|
return content_types.get(message_type, "Неизвестный тип")
|
||||||
|
|||||||
@@ -3,4 +3,3 @@
|
|||||||
|
|
||||||
# Экспортирование модулей во внешние слои проекта
|
# Экспортирование модулей во внешние слои проекта
|
||||||
from .logs import *
|
from .logs import *
|
||||||
from .custom_loggers import *
|
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
# BotLibrary/loggers/custom_loggers.py
|
|
||||||
# Кастомные логгеры для проекта, с более стандартизированным использованием
|
|
||||||
|
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
from aiogram import types
|
|
||||||
from colorama import Fore
|
|
||||||
from loguru import logger
|
|
||||||
from aiogram.types import Message
|
|
||||||
|
|
||||||
from BotLibrary.system.bots import BotInfo
|
|
||||||
from BotLibrary.validators.username import username
|
|
||||||
from BotLibrary.analytics.type_msg import type_msg
|
|
||||||
|
|
||||||
from ProjectsFiles import BotLogs, Permissions, ProjectPath, BotVar, bot_owner
|
|
||||||
|
|
||||||
# Настройка экспорта из модуля
|
|
||||||
__all__ = ("Logs",)
|
|
||||||
|
|
||||||
|
|
||||||
class Logs:
|
|
||||||
"""Класс для логирования с разными уровнями через loguru."""
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def start(text: str = "Логирование!",
|
|
||||||
system: str = "PRIMO",
|
|
||||||
log_type: str = "AEP",
|
|
||||||
user: str = "@Console") -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение на уровне START.
|
|
||||||
|
|
||||||
:param text: Сообщение для логирования.
|
|
||||||
:param system: Тип системы логирования.
|
|
||||||
:param log_type: Тип лога (например, "Help").
|
|
||||||
:param user: Имя пользователя или источник вызова лога.
|
|
||||||
|
|
||||||
:return: Вывод сообщения об старте бота
|
|
||||||
"""
|
|
||||||
logger.bind(system=system, user=user, log_type=log_type).log("START", text)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def debug(text: str = "Логирование!",
|
|
||||||
system: str = "DEBUG",
|
|
||||||
log_type: str = "Logs",
|
|
||||||
user: str = "@Console",
|
|
||||||
message: Message = None) -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение на уровне DEBUG.
|
|
||||||
|
|
||||||
:param text: Сообщение для логирования.
|
|
||||||
:param system: Тип системы логирования.
|
|
||||||
:param log_type: Тип лога (например, "Help").
|
|
||||||
:param user: Имя пользователя или источник вызова лога.
|
|
||||||
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
|
||||||
|
|
||||||
:return: Вывод сообщения об дебаг-информации
|
|
||||||
"""
|
|
||||||
if message:
|
|
||||||
user = username(message)
|
|
||||||
logger.bind(system=system, log_type=log_type, user=user).debug(text)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def info(text: str = "Логирование!",
|
|
||||||
system: str = "PRIMO",
|
|
||||||
log_type: str = "Logs",
|
|
||||||
user: str = "@Console",
|
|
||||||
message: Message = None) -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение на уровне INFO.
|
|
||||||
|
|
||||||
:param text: Сообщение для логирования.
|
|
||||||
:param system: Тип системы логирования.
|
|
||||||
:param log_type: Тип лога (например, "Logs").
|
|
||||||
:param user: Имя пользователя или источник вызова лога.
|
|
||||||
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
|
||||||
|
|
||||||
:return: Вывод сообщения об некой информации
|
|
||||||
"""
|
|
||||||
if message:
|
|
||||||
user = username(message)
|
|
||||||
logger.bind(system=system, log_type=log_type, user=user).info(text)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def warning(text: str = "Логирование!",
|
|
||||||
system: str = "WARNING",
|
|
||||||
log_type: str = "Logs",
|
|
||||||
user: str = "@Console",
|
|
||||||
message: Message = None) -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение на уровне WARNING.
|
|
||||||
|
|
||||||
:param text: Сообщение для логирования.
|
|
||||||
:param system: Тип системы логирования.
|
|
||||||
:param log_type: Тип лога (например, "Logs").
|
|
||||||
:param user: Имя пользователя или источник вызова лога.
|
|
||||||
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
|
||||||
|
|
||||||
:return: Вывод сообщения об предупреждении
|
|
||||||
"""
|
|
||||||
if message:
|
|
||||||
user = username(message)
|
|
||||||
logger.bind(system=system, log_type=log_type, user=user).warning(text)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def error(text: str = "Логирование!",
|
|
||||||
system: str = "ERROR",
|
|
||||||
log_type: str = "Logs",
|
|
||||||
user: str = "@Console",
|
|
||||||
message: Message = None) -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение на уровне ERROR.
|
|
||||||
|
|
||||||
:param text: Сообщение для логирования.
|
|
||||||
:param system: Тип системы логирования.
|
|
||||||
:param log_type: Тип лога (например, "Logs").
|
|
||||||
:param user: Имя пользователя или источник вызова лога.
|
|
||||||
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
|
||||||
|
|
||||||
:return: Вывод сообщения об ошибке
|
|
||||||
"""
|
|
||||||
if message:
|
|
||||||
user = username(message)
|
|
||||||
logger.bind(system=system, log_type=log_type, user=user).error(text)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def msg(message: types.Message,
|
|
||||||
log_type: str = "Message",
|
|
||||||
user: str = None,
|
|
||||||
msg_type: str = None,
|
|
||||||
permission: bool = BotLogs.permission) -> None:
|
|
||||||
"""
|
|
||||||
Логирует сообщение, если оно не обработано.
|
|
||||||
|
|
||||||
:param message: Сообщение от пользователя.
|
|
||||||
:param log_type: Тип лога (по умолчанию "Message").
|
|
||||||
:param permission: Разрешение на логирование (config).
|
|
||||||
:param user: Получение пользователя (автоматически).
|
|
||||||
:param msg_type: Получение типа сообщения (автоматически).
|
|
||||||
.
|
|
||||||
:return: Вывод сообщения об обычном сообщении пользователя.
|
|
||||||
"""
|
|
||||||
# Получаем айди чата
|
|
||||||
chat_id = message.chat.id
|
|
||||||
|
|
||||||
# Получаем username или id пользователя
|
|
||||||
if user is None:
|
|
||||||
user: str = f"@{message.from_user.username or message.from_user.id}"
|
|
||||||
if msg_type is None:
|
|
||||||
msg_type: str = type_msg(message)
|
|
||||||
|
|
||||||
# Логирование только если разрешено
|
|
||||||
if permission:
|
|
||||||
# Проверка на наличие текста и его типа
|
|
||||||
if message.text is None and msg_type not in ("Новые участники чата", "Ушедший участник чата"):
|
|
||||||
Logs.info(log_type=log_type, user=user, text=f"Получено сообщение из ({chat_id}) : {msg_type}")
|
|
||||||
elif message.text is not None:
|
|
||||||
Logs.info(log_type=log_type, user=user,
|
|
||||||
text=f"Получено сообщение из ({chat_id}) : {message.text}")
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def console(stop_time: int = 1,
|
|
||||||
console: bool = Permissions.start_info_console,
|
|
||||||
file: bool = Permissions.start_info_to_file,
|
|
||||||
path: str = ProjectPath.bot_info_log_file) -> None:
|
|
||||||
"""
|
|
||||||
Собирает информацию о боте и выводит её в консоль, а также возвращает как строку.
|
|
||||||
|
|
||||||
:param stop_time: Количество времени в секундах, после которых выведется информация (1 сек)
|
|
||||||
:param console: Разрешение на внесение информации в консоль (config)
|
|
||||||
:param file: Разрешение на внесение информации в файл (config)
|
|
||||||
:param path: Путь до файла для сохранения информации о боте (config)
|
|
||||||
|
|
||||||
:return: Информация о боте в виде строки.
|
|
||||||
"""
|
|
||||||
# Собираем данные о боте
|
|
||||||
bot_name: str = f"Основное имя: {BotInfo.first_name}\n"
|
|
||||||
bot_post_name: str = f"Владельцы бота: {bot_owner}\n"
|
|
||||||
bot_username: str = f"Юзернейм: @{BotInfo.username}\n"
|
|
||||||
bot_id: str = f"ID: {BotInfo.id}\n"
|
|
||||||
bot_can_join_groups: str = f"Может ли вступать в группы: {BotInfo.can_join_groups}\n"
|
|
||||||
bot_can_read_all_group_messages: str = f"Чтение всех сообщений: {BotInfo.can_read_all_group_messages}\n"
|
|
||||||
bot_supports_inline_queries: str = f"Поддерживает инлайн-запросы: {BotInfo.supports_inline_queries}\n"
|
|
||||||
bot_can_connect_to_business: str = f"Подключение к бизнес-аккаунтам: {BotInfo.can_connect_to_business}\n"
|
|
||||||
bot_has_main_web_app: str = f"Основное веб-приложение: {BotInfo.has_main_web_app}\n"
|
|
||||||
|
|
||||||
# Формируем полный текст с выводом информации о боте
|
|
||||||
bot_all_info: str = (f"{bot_name} {bot_post_name} {bot_username} {bot_id} "
|
|
||||||
f"{bot_can_join_groups} {bot_can_read_all_group_messages} "
|
|
||||||
f"{bot_supports_inline_queries} {bot_can_connect_to_business} "
|
|
||||||
f"{bot_has_main_web_app}")
|
|
||||||
|
|
||||||
# Печатаем всю информацию в консоль с задержкой
|
|
||||||
if console:
|
|
||||||
sleep(stop_time)
|
|
||||||
print(Fore.CYAN + bot_all_info)
|
|
||||||
|
|
||||||
# Печатаем всю информацию в файл
|
|
||||||
if file:
|
|
||||||
# Преобразуем словарь bot_all_info в строку и записываем в файл
|
|
||||||
with open(path, 'w', encoding=BotVar.encod) as file:
|
|
||||||
file.write(str(bot_all_info))
|
|
||||||
@@ -1,15 +1,23 @@
|
|||||||
# BotLibrary/loggers/logs.py
|
# BotLibrary/loggers/logs.py
|
||||||
# Создание логгеров и их шаблон для проекта
|
# Кастомные логгеры для проекта, с более стандартизированным использованием
|
||||||
|
|
||||||
import sys
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from ProjectsFiles import BotLogs, ProjectPath
|
from aiogram.types import Message
|
||||||
|
|
||||||
|
from BotLibrary.system.bots import BotInfo
|
||||||
|
from BotLibrary.validators.username import username
|
||||||
|
from BotLibrary.analytics.type_msg import type_msg
|
||||||
|
|
||||||
|
from ProjectsFiles import BotLogs, Permissions, ProjectPath, BotVar, bot_owner
|
||||||
|
|
||||||
# Настройка экспорта из модуля
|
# Настройка экспорта из модуля
|
||||||
__all__ = ("setup_logger",)
|
__all__ = ("Logs",)
|
||||||
|
|
||||||
# Создание обычного логгера + логгер в файл
|
|
||||||
async def setup_logger(logging: bool = BotLogs.permission,
|
class Logs:
|
||||||
|
"""Класс для логирования с разными уровнями через loguru."""
|
||||||
|
@staticmethod
|
||||||
|
def setup(logging: bool = BotLogs.permission,
|
||||||
to_file: bool = BotLogs.permission_to_file) -> None:
|
to_file: bool = BotLogs.permission_to_file) -> None:
|
||||||
"""
|
"""
|
||||||
Настройка логгеров для проекта, выводящих логи в консоль и файлы.
|
Настройка логгеров для проекта, выводящих логи в консоль и файлы.
|
||||||
@@ -20,12 +28,10 @@ async def setup_logger(logging: bool = BotLogs.permission,
|
|||||||
|
|
||||||
:param logging: Разрешение на логирование в консоль (config)
|
:param logging: Разрешение на логирование в консоль (config)
|
||||||
:param to_file: Разрешение на логирование в файл (config)
|
:param to_file: Разрешение на логирование в файл (config)
|
||||||
|
|
||||||
:return: Создание логеров под различные уровни
|
:return: Создание логеров под различные уровни
|
||||||
"""
|
"""
|
||||||
logger.remove() # Удаляем все стандартные логгеры
|
logger.remove() # Удаляем все стандартные логгеры
|
||||||
|
|
||||||
|
|
||||||
# Если есть разрешение, то он создает новые уровни
|
# Если есть разрешение, то он создает новые уровни
|
||||||
if logging and BotLogs.permission_to_file:
|
if logging and BotLogs.permission_to_file:
|
||||||
# Добавляем новый уровень START
|
# Добавляем новый уровень START
|
||||||
@@ -37,37 +43,36 @@ async def setup_logger(logging: bool = BotLogs.permission,
|
|||||||
# Добавляем новый уровень LEAVE_USER
|
# Добавляем новый уровень LEAVE_USER
|
||||||
logger.level("LEAVE_USER", no=3, color="white", icon="🫰")
|
logger.level("LEAVE_USER", no=3, color="white", icon="🫰")
|
||||||
|
|
||||||
|
|
||||||
# Настройка логирования в консоль для каждого уровня
|
# Настройка логирования в консоль для каждого уровня
|
||||||
if logging:
|
if logging:
|
||||||
logger.add(sys.stderr,
|
from sys import stderr
|
||||||
|
logger.add(stderr,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format=BotLogs.start_text,
|
format=BotLogs.start_text,
|
||||||
level="START",
|
level="START",
|
||||||
filter=lambda record: record["level"].name == "START"
|
filter=lambda record: record["level"].name == "START"
|
||||||
)
|
)
|
||||||
logger.add(sys.stderr,
|
logger.add(stderr,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format=BotLogs.debug_text,
|
format=BotLogs.debug_text,
|
||||||
level="DEBUG",
|
level="DEBUG",
|
||||||
filter=lambda record: record["level"].name == "DEBUG")
|
filter=lambda record: record["level"].name == "DEBUG")
|
||||||
logger.add(sys.stderr,
|
logger.add(stderr,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format=BotLogs.info_text,
|
format=BotLogs.info_text,
|
||||||
level="INFO",
|
level="INFO",
|
||||||
filter=lambda record: record["level"].name == "INFO")
|
filter=lambda record: record["level"].name == "INFO")
|
||||||
logger.add(sys.stderr,
|
logger.add(stderr,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format=BotLogs.warning_text,
|
format=BotLogs.warning_text,
|
||||||
level="WARNING",
|
level="WARNING",
|
||||||
filter=lambda record: record["level"].name == "WARNING")
|
filter=lambda record: record["level"].name == "WARNING")
|
||||||
logger.add(sys.stderr,
|
logger.add(stderr,
|
||||||
colorize=True,
|
colorize=True,
|
||||||
format=BotLogs.error_text,
|
format=BotLogs.error_text,
|
||||||
level="ERROR",
|
level="ERROR",
|
||||||
filter=lambda record: record["level"].name == "ERROR")
|
filter=lambda record: record["level"].name == "ERROR")
|
||||||
|
|
||||||
|
|
||||||
# Добавление логгера для записи в файл
|
# Добавление логгера для записи в файл
|
||||||
if to_file:
|
if to_file:
|
||||||
logger.add(ProjectPath.start_log_file,
|
logger.add(ProjectPath.start_log_file,
|
||||||
@@ -105,3 +110,186 @@ async def setup_logger(logging: bool = BotLogs.permission,
|
|||||||
diagnose=True,
|
diagnose=True,
|
||||||
level="ERROR",
|
level="ERROR",
|
||||||
filter=lambda record: record["level"].name == "ERROR")
|
filter=lambda record: record["level"].name == "ERROR")
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def start(text: str = "Логирование!",
|
||||||
|
system: str = "PRIMO",
|
||||||
|
log_type: str = "AEP",
|
||||||
|
user: str = "@Console") -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение на уровне START.
|
||||||
|
|
||||||
|
:param text: Сообщение для логирования.
|
||||||
|
:param system: Тип системы логирования.
|
||||||
|
:param log_type: Тип лога (например, "Help").
|
||||||
|
:param user: Имя пользователя или источник вызова лога.
|
||||||
|
|
||||||
|
:return: Вывод сообщения об старте бота
|
||||||
|
"""
|
||||||
|
logger.bind(system=system, user=user, log_type=log_type).log("START", text)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def debug(text: str = "Логирование!",
|
||||||
|
system: str = "DEBUG",
|
||||||
|
log_type: str = "Logs",
|
||||||
|
user: str = "@Console",
|
||||||
|
message: Message = None) -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение на уровне DEBUG.
|
||||||
|
|
||||||
|
:param text: Сообщение для логирования.
|
||||||
|
:param system: Тип системы логирования.
|
||||||
|
:param log_type: Тип лога (например, "Help").
|
||||||
|
:param user: Имя пользователя или источник вызова лога.
|
||||||
|
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
||||||
|
|
||||||
|
:return: Вывод сообщения об дебаг-информации
|
||||||
|
"""
|
||||||
|
if message:
|
||||||
|
user = username(message)
|
||||||
|
logger.bind(system=system, log_type=log_type, user=user).debug(text)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def info(text: str = "Логирование!",
|
||||||
|
system: str = "PRIMO",
|
||||||
|
log_type: str = "Logs",
|
||||||
|
user: str = "@Console",
|
||||||
|
message: Message = None) -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение на уровне INFO.
|
||||||
|
|
||||||
|
:param text: Сообщение для логирования.
|
||||||
|
:param system: Тип системы логирования.
|
||||||
|
:param log_type: Тип лога (например, "Logs").
|
||||||
|
:param user: Имя пользователя или источник вызова лога.
|
||||||
|
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
||||||
|
|
||||||
|
:return: Вывод сообщения об некой информации
|
||||||
|
"""
|
||||||
|
if message:
|
||||||
|
user = username(message)
|
||||||
|
logger.bind(system=system, log_type=log_type, user=user).info(text)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def warning(text: str = "Логирование!",
|
||||||
|
system: str = "WARNING",
|
||||||
|
log_type: str = "Logs",
|
||||||
|
user: str = "@Console",
|
||||||
|
message: Message = None) -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение на уровне WARNING.
|
||||||
|
|
||||||
|
:param text: Сообщение для логирования.
|
||||||
|
:param system: Тип системы логирования.
|
||||||
|
:param log_type: Тип лога (например, "Logs").
|
||||||
|
:param user: Имя пользователя или источник вызова лога.
|
||||||
|
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
||||||
|
|
||||||
|
:return: Вывод сообщения об предупреждении
|
||||||
|
"""
|
||||||
|
if message:
|
||||||
|
user = username(message)
|
||||||
|
logger.bind(system=system, log_type=log_type, user=user).warning(text)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def error(text: str = "Логирование!",
|
||||||
|
system: str = "ERROR",
|
||||||
|
log_type: str = "Logs",
|
||||||
|
user: str = "@Console",
|
||||||
|
message: Message = None) -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение на уровне ERROR.
|
||||||
|
|
||||||
|
:param text: Сообщение для логирования.
|
||||||
|
:param system: Тип системы логирования.
|
||||||
|
:param log_type: Тип лога (например, "Logs").
|
||||||
|
:param user: Имя пользователя или источник вызова лога.
|
||||||
|
:param message: Сообщение от пользователя, если необходимо извлечь имя.
|
||||||
|
|
||||||
|
:return: Вывод сообщения об ошибке
|
||||||
|
"""
|
||||||
|
if message:
|
||||||
|
user = username(message)
|
||||||
|
logger.bind(system=system, log_type=log_type, user=user).error(text)
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def msg(message: Message,
|
||||||
|
log_type: str = "Message",
|
||||||
|
user: str = None,
|
||||||
|
msg_type: str = None,
|
||||||
|
permission: bool = BotLogs.permission) -> None:
|
||||||
|
"""
|
||||||
|
Логирует сообщение, если оно не обработано.
|
||||||
|
|
||||||
|
:param message: Сообщение от пользователя.
|
||||||
|
:param log_type: Тип лога (по умолчанию "Message").
|
||||||
|
:param permission: Разрешение на логирование (config).
|
||||||
|
:param user: Получение пользователя (автоматически).
|
||||||
|
:param msg_type: Получение типа сообщения (автоматически).
|
||||||
|
.
|
||||||
|
:return: Вывод сообщения об обычном сообщении пользователя.
|
||||||
|
"""
|
||||||
|
# Получаем айди чата
|
||||||
|
chat_id = message.chat.id
|
||||||
|
|
||||||
|
# Получаем username или id пользователя
|
||||||
|
if user is None:
|
||||||
|
user: str = f"@{message.from_user.username or message.from_user.id}"
|
||||||
|
if msg_type is None:
|
||||||
|
msg_type: str = type_msg(message)
|
||||||
|
|
||||||
|
# Логирование только если разрешено
|
||||||
|
if permission:
|
||||||
|
# Проверка на наличие текста и его типа
|
||||||
|
if message.text is None and msg_type not in ("Новые участники чата", "Ушедший участник чата"):
|
||||||
|
Logs.info(log_type=log_type, user=user, text=f"Получено сообщение из ({chat_id}) : {msg_type}")
|
||||||
|
elif message.text is not None:
|
||||||
|
Logs.info(log_type=log_type, user=user,
|
||||||
|
text=f"Получено сообщение из ({chat_id}) : {message.text}")
|
||||||
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def console(console: bool = Permissions.start_info_console,
|
||||||
|
file: bool = Permissions.start_info_to_file,
|
||||||
|
path: str = ProjectPath.bot_info_log_file) -> None:
|
||||||
|
"""
|
||||||
|
Собирает информацию о боте и выводит её в консоль, а также возвращает как строку.
|
||||||
|
|
||||||
|
:param console: Разрешение на внесение информации в консоль (config)
|
||||||
|
:param file: Разрешение на внесение информации в файл (config)
|
||||||
|
:param path: Путь до файла для сохранения информации о боте (config)
|
||||||
|
:return: Информация о боте в виде строки.
|
||||||
|
"""
|
||||||
|
# Собираем данные о боте
|
||||||
|
bot_name: str = f"Основное имя: {BotInfo.first_name}\n"
|
||||||
|
bot_post_name: str = f"Владельцы бота: {bot_owner}\n"
|
||||||
|
bot_username: str = f"Юзернейм: @{BotInfo.username}\n"
|
||||||
|
bot_id: str = f"ID: {BotInfo.id}\n"
|
||||||
|
bot_can_join_groups: str = f"Может ли вступать в группы: {BotInfo.can_join_groups}\n"
|
||||||
|
bot_can_read_all_group_messages: str = f"Чтение всех сообщений: {BotInfo.can_read_all_group_messages}\n"
|
||||||
|
bot_supports_inline_queries: str = f"Поддерживает инлайн-запросы: {BotInfo.supports_inline_queries}\n"
|
||||||
|
bot_can_connect_to_business: str = f"Подключение к бизнес-аккаунтам: {BotInfo.can_connect_to_business}\n"
|
||||||
|
bot_has_main_web_app: str = f"Основное веб-приложение: {BotInfo.has_main_web_app}\n"
|
||||||
|
|
||||||
|
# Формируем полный текст с выводом информации о боте
|
||||||
|
bot_all_info: str = (f"{bot_name} {bot_post_name} {bot_username} {bot_id} "
|
||||||
|
f"{bot_can_join_groups} {bot_can_read_all_group_messages} "
|
||||||
|
f"{bot_supports_inline_queries} {bot_can_connect_to_business} "
|
||||||
|
f"{bot_has_main_web_app}")
|
||||||
|
|
||||||
|
# Печатаем всю информацию в консоль с задержкой
|
||||||
|
if console:
|
||||||
|
from colorama import Fore
|
||||||
|
print(Fore.CYAN + bot_all_info)
|
||||||
|
|
||||||
|
# Печатаем всю информацию в файл
|
||||||
|
if file:
|
||||||
|
# Преобразуем словарь bot_all_info в строку и записываем в файл
|
||||||
|
with open(path, 'w', encoding=BotVar.encod) as file:
|
||||||
|
file.write(str(bot_all_info))
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
# BotLibrary/samples/inline_kb_sample.py
|
# BotLibrary/samples/inline_kb_sample.py
|
||||||
# Шаблон для создания инлайн клавиатур
|
# Шаблон для создания инлайн клавиатур
|
||||||
|
|
||||||
from aiogram.types import InlineKeyboardMarkup, ReplyKeyboardRemove
|
from aiogram.types import InlineKeyboardMarkup
|
||||||
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
from aiogram.utils.keyboard import InlineKeyboardBuilder
|
||||||
from typing import List, Tuple, Optional
|
from typing import List, Tuple, Optional
|
||||||
|
|
||||||
|
# Настройка экспорта в модули
|
||||||
|
__all__ = ("BaseInlineKeyboard",)
|
||||||
|
|
||||||
class BaseInlineKeyboard:
|
class BaseInlineKeyboard:
|
||||||
def __init__(self, buttons: List[Tuple[str, Optional[str], Optional[str]]], row_width: int = 1):
|
def __init__(self, buttons: List[Tuple[str, Optional[str], Optional[str]]], row_width: int = 1):
|
||||||
"""
|
"""
|
||||||
@@ -17,7 +20,7 @@ class BaseInlineKeyboard:
|
|||||||
def get_keyboard(self) -> InlineKeyboardMarkup:
|
def get_keyboard(self) -> InlineKeyboardMarkup:
|
||||||
"""
|
"""
|
||||||
Создаёт инлайн-клавиатуру и возвращает её вместе с объектом для удаления reply-клавиатуры.
|
Создаёт инлайн-клавиатуру и возвращает её вместе с объектом для удаления reply-клавиатуры.
|
||||||
:return: кортеж (InlineKeyboardMarkup, ReplyKeyboardRemove)
|
:return: кортеж InlineKeyboardMarkup
|
||||||
"""
|
"""
|
||||||
ikb = InlineKeyboardBuilder()
|
ikb = InlineKeyboardBuilder()
|
||||||
for text, url, callback_data in self.buttons:
|
for text, url, callback_data in self.buttons:
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ from aiogram.types import ReplyKeyboardMarkup, KeyboardButton, KeyboardButtonPol
|
|||||||
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
from aiogram.utils.keyboard import ReplyKeyboardBuilder
|
||||||
from typing import List, Union, Tuple, Optional, Dict, Any
|
from typing import List, Union, Tuple, Optional, Dict, Any
|
||||||
|
|
||||||
|
# Настройка экспорта в модули
|
||||||
|
__all__ = ("BaseReplyKeyboard",)
|
||||||
|
|
||||||
class BaseReplyKeyboard:
|
class BaseReplyKeyboard:
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -11,16 +11,47 @@ from typing import Optional, Callable
|
|||||||
from ..loggers import Logs
|
from ..loggers import Logs
|
||||||
from ..validators import username, valid_url
|
from ..validators import username, valid_url
|
||||||
from ProjectsFiles import BotVar
|
from ProjectsFiles import BotVar
|
||||||
from SQLite3 import base_sql
|
from ..sql import db
|
||||||
|
|
||||||
# Настройки экспорта в модули
|
# Настройки экспорта в модули
|
||||||
__all__ = ("CommandHandler",)
|
__all__ = ("CommandHandler",)
|
||||||
|
|
||||||
class CommandHandler:
|
class CommandHandler:
|
||||||
|
"""
|
||||||
|
Класс для создания и управления командами Telegram-бота.
|
||||||
|
|
||||||
|
Этот класс позволяет создавать команды с различными настройками, включая
|
||||||
|
текстовые сообщения, медиафайлы, клавиатуры, выполнение функций и обработку
|
||||||
|
callback-запросов.
|
||||||
|
|
||||||
|
:param name: Название команды.
|
||||||
|
:param keywords: Список ключевых слов, вызывающих команду.
|
||||||
|
:param func: Список функций, которые выполняются при вызове команды.
|
||||||
|
:param text_msg: Текстовое сообщение, которое отправляется в ответ на команду.
|
||||||
|
:param chat_action: Флаг отправки анимации набора текста перед ответом.
|
||||||
|
:param description: Описание команды.
|
||||||
|
:param tg_links: Флаг обработки ссылок на пользователей в тексте.
|
||||||
|
:param keyboard: Клавиатура, привязанная к команде.
|
||||||
|
:param prefix: Префикс команды (по умолчанию `BotVar.prefix`).
|
||||||
|
:param callbackdata: Список callback-данных, связанных с командой.
|
||||||
|
:param only_admin: Флаг, разрешающий использование команды только администраторам.
|
||||||
|
:param ignore_case: Флаг игнорирования регистра в ключевых словах.
|
||||||
|
:param activate_keywords: Флаг активации команды по ключевым словам.
|
||||||
|
:param delete_msg: Флаг удаления исходного сообщения после обработки команды.
|
||||||
|
:param activate_commands: Флаг активации команды через стандартный обработчик команд.
|
||||||
|
:param activate_callback: Флаг активации обработки callback-запросов.
|
||||||
|
:param media: Тип медиафайла, который отправляется (`"message"`, `"photo"`, `"video"`, и т. д.).
|
||||||
|
:param path_to_media: Путь к медиафайлу (или список путей).
|
||||||
|
:param parse_mode: Форматирование текста (`Markdown`, `HTML` и т. д.).
|
||||||
|
:param disable_notification: Флаг отключения уведомлений при отправке сообщений.
|
||||||
|
:param protect: Флаг защиты контента сообщений.
|
||||||
|
|
||||||
|
:return: Готовый шаблон для команды.
|
||||||
|
"""
|
||||||
def __init__(self, name: str,
|
def __init__(self, name: str,
|
||||||
keywords: list,
|
keywords: list,
|
||||||
func: Optional[list[Callable]] = None,
|
func: Optional[list[Callable]] = None,
|
||||||
text_msg=None,
|
text_msg = None,
|
||||||
chat_action: bool = False,
|
chat_action: bool = False,
|
||||||
description: str = "Описание команды",
|
description: str = "Описание команды",
|
||||||
tg_links: bool = False,
|
tg_links: bool = False,
|
||||||
@@ -34,15 +65,16 @@ class CommandHandler:
|
|||||||
activate_commands: bool = True,
|
activate_commands: bool = True,
|
||||||
activate_callback: bool = True,
|
activate_callback: bool = True,
|
||||||
media: str = "message",
|
media: str = "message",
|
||||||
path_to_media=None,
|
path_to_media = None,
|
||||||
parse_mode: str = BotVar.parse_mode,
|
parse_mode: str = BotVar.parse_mode,
|
||||||
disable_notification: bool = BotVar.disable_notification,
|
disable_notification: bool = BotVar.disable_notification,
|
||||||
protect: bool = BotVar.protect_content):
|
protect: bool = BotVar.protect_content):
|
||||||
|
|
||||||
self.router = Router(name=f"{name}_router")
|
self.router = Router(name=f"{name}_router")
|
||||||
self.name = name
|
self.name = name
|
||||||
self.log_type = name.capitalize()
|
self.log_type = name.capitalize()
|
||||||
self.description = description
|
self.description = description
|
||||||
self.last_bot_message = {} # {chat_id: message_id}
|
self.last_bot_message = {}
|
||||||
|
|
||||||
self.keywords = keywords
|
self.keywords = keywords
|
||||||
self.text_msg = text_msg
|
self.text_msg = text_msg
|
||||||
@@ -125,7 +157,10 @@ class CommandHandler:
|
|||||||
text = text.replace("<users>", str(message.from_user.id))
|
text = text.replace("<users>", str(message.from_user.id))
|
||||||
|
|
||||||
Logs.info(log_type=self.log_type, user=username(message), text=f"использовал(а) команду /{self.name}")
|
Logs.info(log_type=self.log_type, user=username(message), text=f"использовал(а) команду /{self.name}")
|
||||||
await base_sql(message)
|
|
||||||
|
# Работа с базами данных
|
||||||
|
db.update_user(message)
|
||||||
|
db.update_user_messages(message)
|
||||||
|
|
||||||
# Обрабатываем текстовое сообщение
|
# Обрабатываем текстовое сообщение
|
||||||
if callable(self.text_msg):
|
if callable(self.text_msg):
|
||||||
|
|||||||
12
BotLibrary/sql/__init__.py
Normal file
12
BotLibrary/sql/__init__.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# BotLibrary/system/__init__.py
|
||||||
|
# Инициализация пакета system, для библиотек запуска
|
||||||
|
|
||||||
|
# Экспортирование модулей во внешние слои проекта
|
||||||
|
from .db_class import *
|
||||||
|
from ProjectsFiles import BotVar
|
||||||
|
|
||||||
|
# Создание экземпляра класса
|
||||||
|
db = Database(BotVar.bd_names)
|
||||||
|
|
||||||
|
# Создание базы данных
|
||||||
|
db.create_db()
|
||||||
563
BotLibrary/sql/db_class.py
Normal file
563
BotLibrary/sql/db_class.py
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
# BotLibrary/system/db_class.py
|
||||||
|
# Создание базы данных
|
||||||
|
import os
|
||||||
|
import sqlite3
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
|
from aiogram import types
|
||||||
|
from typing import Optional, List, Tuple
|
||||||
|
from ProjectsFiles import BotVar
|
||||||
|
|
||||||
|
# Настройка экспорта в модули
|
||||||
|
__all__ = ("Database",)
|
||||||
|
|
||||||
|
class Database:
|
||||||
|
"""Класс для управления базой данных пользователей чата с использованием SQLite3."""
|
||||||
|
|
||||||
|
def __init__(self, db_name: str = BotVar.bd_path) -> None:
|
||||||
|
"""Инициализация класса с именем базы данных."""
|
||||||
|
self.db_name = db_name
|
||||||
|
|
||||||
|
# --- Основные методы из предоставленных функций ---
|
||||||
|
|
||||||
|
def create_db(self) -> None:
|
||||||
|
"""Создание базы данных и таблиц с начальными данными."""
|
||||||
|
# Создание директории, если её нет
|
||||||
|
db_directory = os.path.dirname(self.db_name)
|
||||||
|
if db_directory and not os.path.exists(db_directory):
|
||||||
|
os.makedirs(db_directory)
|
||||||
|
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
|
||||||
|
# Таблица пользователей
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
user_id INTEGER PRIMARY KEY,
|
||||||
|
tg_id INTEGER NOT NULL UNIQUE,
|
||||||
|
username TEXT,
|
||||||
|
first_name TEXT,
|
||||||
|
last_name TEXT,
|
||||||
|
role TEXT DEFAULT NULL,
|
||||||
|
status TEXT DEFAULT 'active',
|
||||||
|
user TEXT DEFAULT 'user'
|
||||||
|
);''')
|
||||||
|
|
||||||
|
# Таблица сообщений пользователей
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS user_messages (
|
||||||
|
user_id INTEGER PRIMARY KEY,
|
||||||
|
last_message TEXT,
|
||||||
|
last_message_id INTEGER,
|
||||||
|
last_message_time TEXT,
|
||||||
|
messages_per_day INTEGER DEFAULT 0,
|
||||||
|
messages_per_week INTEGER DEFAULT 0,
|
||||||
|
messages_per_month INTEGER DEFAULT 0,
|
||||||
|
total_messages INTEGER DEFAULT 0,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE
|
||||||
|
);''')
|
||||||
|
|
||||||
|
# Таблица персонажей Genshin Impact
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS characters (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
region TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
status TEXT DEFAULT 'Свободно',
|
||||||
|
user_id INTEGER DEFAULT NULL,
|
||||||
|
comment TEXT DEFAULT '',
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE SET NULL
|
||||||
|
);''')
|
||||||
|
|
||||||
|
# Таблица персонажей Honkai: Star Rail
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS characters_hsr (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
region TEXT NOT NULL,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
status TEXT DEFAULT 'Свободно',
|
||||||
|
user_id INTEGER DEFAULT NULL,
|
||||||
|
comment TEXT DEFAULT '',
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE SET NULL
|
||||||
|
);''')
|
||||||
|
|
||||||
|
# Начальные данные для characters (Genshin Impact)
|
||||||
|
characters_genshin: list[tuple[str, str, str, str]] = [
|
||||||
|
# Мондштадт
|
||||||
|
("Мондштадт", "Венти", "Свободно", ""),
|
||||||
|
("Мондштадт", "Кэйа", "Свободно", ""),
|
||||||
|
("Мондштадт", "Альбедо", "Свободно", ""),
|
||||||
|
("Мондштадт", "Дилюк", "Свободно", ""),
|
||||||
|
("Мондштадт", "Мика", "Свободно", ""),
|
||||||
|
("Мондштадт", "Беннет", "Свободно", ""),
|
||||||
|
("Мондштадт", "Рэйзор", "Свободно", ""),
|
||||||
|
("Мондштадт", "Эола", "Свободно", ""),
|
||||||
|
("Мондштадт", "Мона", "Свободно", ""),
|
||||||
|
("Мондштадт", "Джинн", "Свободно", ""),
|
||||||
|
("Мондштадт", "Диона", "Свободно", ""),
|
||||||
|
("Мондштадт", "Лиза", "Свободно", ""),
|
||||||
|
("Мондштадт", "Ноэлль", "Свободно", ""),
|
||||||
|
("Мондштадт", "Сахароза", "Свободно", ""),
|
||||||
|
("Мондштадт", "Розария", "Свободно", ""),
|
||||||
|
("Мондштадт", "Эмбер", "Свободно", ""),
|
||||||
|
("Мондштадт", "Фишль", "Свободно", ""),
|
||||||
|
("Мондштадт", "Барбара", "Свободно", ""),
|
||||||
|
|
||||||
|
# Ли Юэ
|
||||||
|
("Ли Юэ", "Чжун Ли", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Сяо", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Син Цю", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Чун Юнь", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Бай Чжу", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Е Лань", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Шень Хэ", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Гань Юй", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Ци Ци", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Кэ Цин", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Янь Фэй", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Нин Гуан", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Бэй Доу", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Яо Яо", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Ка Мин", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Сянь Юнь", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Юнь Цзинь", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Ху Тао", "Свободно", ""),
|
||||||
|
("Ли Юэ", "Лань Янь", "Свободно", ""),
|
||||||
|
|
||||||
|
# Инадзума
|
||||||
|
("Инадзума", "Итто", "Свободно", ""),
|
||||||
|
("Инадзума", "Горо", "Свободно", ""),
|
||||||
|
("Инадзума", "Аято", "Свободно", ""),
|
||||||
|
("Инадзума", "Хэйдзо", "Свободно", ""),
|
||||||
|
("Инадзума", "Тома", "Свободно", ""),
|
||||||
|
("Инадзума", "Кадзуха", "Свободно", ""),
|
||||||
|
("Инадзума", "Кирара", "Свободно", ""),
|
||||||
|
("Инадзума", "Кудзё Сара", "Свободно", ""),
|
||||||
|
("Инадзума", "Ёимия", "Свободно", ""),
|
||||||
|
("Инадзума", "Аяка", "Свободно", ""),
|
||||||
|
("Инадзума", "Сангономия Кокоми", "Свободно", ""),
|
||||||
|
("Инадзума", "Яэ Мико", "Свободно", ""),
|
||||||
|
("Инадзума", "Райдэн Эи", "Свободно", ""),
|
||||||
|
("Инадзума", "Саю", "Свободно", ""),
|
||||||
|
("Инадзума", "Куки Синобу", "Свободно", ""),
|
||||||
|
("Инадзума", "Мидзуки", "Свободно", ""),
|
||||||
|
|
||||||
|
# Сумеру
|
||||||
|
("Сумеру", "Аль-Хайтам", "Свободно", ""),
|
||||||
|
("Сумеру", "Кавех", "Свободно", ""),
|
||||||
|
("Сумеру", "Сайно", "Свободно", ""),
|
||||||
|
("Сумеру", "Тигнари", "Свободно", ""),
|
||||||
|
("Сумеру", "Сетос", "Свободно", ""),
|
||||||
|
("Сумеру", "Нилу", "Свободно", ""),
|
||||||
|
("Сумеру", "Нахида", "Свободно", ""),
|
||||||
|
("Сумеру", "Лайла", "Свободно", ""),
|
||||||
|
("Сумеру", "Кандакия", "Свободно", ""),
|
||||||
|
("Сумеру", "Дори", "Свободно", ""),
|
||||||
|
("Сумеру", "Дэхья", "Свободно", ""),
|
||||||
|
("Сумеру", "Коллеи", "Свободно", ""),
|
||||||
|
("Сумеру", "Фарузан", "Свободно", ""),
|
||||||
|
|
||||||
|
# Фонтейн
|
||||||
|
("Фонтейн", "Лини", "Свободно", ""),
|
||||||
|
("Фонтейн", "Ризли", "Свободно", ""),
|
||||||
|
("Фонтейн", "Невиллет", "Свободно", ""),
|
||||||
|
("Фонтейн", "Фремине", "Свободно", ""),
|
||||||
|
("Фонтейн", "Линетт", "Свободно", ""),
|
||||||
|
("Фонтейн", "Эмилия", "Свободно", ""),
|
||||||
|
("Фонтейн", "Клоринда", "Свободно", ""),
|
||||||
|
("Фонтейн", "Навия", "Свободно", ""),
|
||||||
|
("Фонтейн", "Шарлотта", "Свободно", ""),
|
||||||
|
("Фонтейн", "Фурина", "Свободно", ""),
|
||||||
|
("Фонтейн", "Тиори", "Свободно", ""),
|
||||||
|
("Фонтейн", "Сиджвин", "Свободно", ""),
|
||||||
|
|
||||||
|
# Натлан
|
||||||
|
("Натлан", "Кинич", "Свободно", ""),
|
||||||
|
("Натлан", "Оророн", "Свободно", ""),
|
||||||
|
("Натлан", "Муалани", "Свободно", ""),
|
||||||
|
("Натлан", "Ситлали", "Свободно", ""),
|
||||||
|
("Натлан", "Шилонен", "Свободно", ""),
|
||||||
|
("Натлан", "Иансан", "Свободно", ""),
|
||||||
|
("Натлан", "Мавуика", "Свободно", ""),
|
||||||
|
("Натлан", "Часка", "Свободно", ""),
|
||||||
|
|
||||||
|
# Фатуи
|
||||||
|
("Фатуи", "Тарталья", "Свободно", ""),
|
||||||
|
("Фатуи", "Панталоне", "Свободно", ""),
|
||||||
|
("Фатуи", "Дотторе", "Свободно", ""),
|
||||||
|
("Фатуи", "Капитано", "Свободно", ""),
|
||||||
|
("Фатуи", "Пьеро", "Свободно", ""),
|
||||||
|
("Фатуи", "Пульничелла", "Свободно", ""),
|
||||||
|
("Фатуи", "Синьора", "Свободно", ""),
|
||||||
|
("Фатуи", "Арлекино", "Свободно", ""),
|
||||||
|
("Фатуи", "Коломбина", "Свободно", ""),
|
||||||
|
("Фатуи", "Царица", "Свободно", ""),
|
||||||
|
("Фатуи", "Странник", "Свободно", ""),
|
||||||
|
|
||||||
|
# Иные персонажи
|
||||||
|
("Иные персонажи", "Итэр", "Свободно", ""),
|
||||||
|
("Иные персонажи", "Люмин", "Свободно", ""),
|
||||||
|
("Иные персонажи", "Элой", "Свободно", ""),
|
||||||
|
("Иные персонажи", "Паймон", "Свободно", ""),
|
||||||
|
("Иные персонажи", "Дайнслейф", "Свободно", ""),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Начальные данные для characters_hsr (Honkai: Star Rail)
|
||||||
|
characters_hsr: list[tuple[str, str, str, str]] = [
|
||||||
|
# Ярило-6
|
||||||
|
("Ярило-6", "Броня", "Свободно", ""),
|
||||||
|
("Ярило-6", "Гепард", "Свободно", ""),
|
||||||
|
("Ярило-6", "Зеле", "Свободно", ""),
|
||||||
|
("Ярило-6", "Клара", "Свободно", ""),
|
||||||
|
("Ярило-6", "Лука", "Свободно", ""),
|
||||||
|
("Ярило-6", "Наташа", "Свободно", ""),
|
||||||
|
("Ярило-6", "Пела", "Свободно", ""),
|
||||||
|
("Ярило-6", "Рысь", "Свободно", ""),
|
||||||
|
("Ярило-6", "Сампо", "Свободно", ""),
|
||||||
|
("Ярило-6", "Сервал", "Свободно", ""),
|
||||||
|
("Ярило-6", "Хук", "Свободно", ""),
|
||||||
|
|
||||||
|
# Станция «Герта»
|
||||||
|
("Станция «Герта»", "Арлан", "Свободно", ""),
|
||||||
|
("Станция «Герта»", "Аста", "Свободно", ""),
|
||||||
|
("Станция «Герта»", "Великая Герта", "Свободно", ""),
|
||||||
|
("Станция «Герта»", "Кукла «Герта»", "Свободно", ""),
|
||||||
|
("Станция «Герта»", "Жуань Мэй", "Свободно", ""),
|
||||||
|
|
||||||
|
# Пенакония
|
||||||
|
("Пенакония", "Авантюрин", "Свободно", ""),
|
||||||
|
("Пенакония", "Ахерон", "Свободно", ""),
|
||||||
|
("Пенакония", "Галлахер", "Свободно", ""),
|
||||||
|
("Пенакония", "Зарянка", "Свободно", ""),
|
||||||
|
("Пенакония", "Миша", "Свободно", ""),
|
||||||
|
("Пенакония", "Мистер Река", "Свободно", ""),
|
||||||
|
("Пенакония", "Раппа", "Свободно", ""),
|
||||||
|
("Пенакония", "Чёрный Лебедь", "Свободно", ""),
|
||||||
|
("Пенакония", "Яшма", "Свободно", ""),
|
||||||
|
("Пенакония", "Воскресенье", "Свободно", ""),
|
||||||
|
|
||||||
|
# Звёздный Экспресс
|
||||||
|
("Звёздный Экспресс", "Вельт", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Келус", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Стелла", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Дань Хэн", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Март 7", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Химеко", "Свободно", ""),
|
||||||
|
("Звёздный Экспресс", "Пом Пом", "Свободно", ""),
|
||||||
|
|
||||||
|
# Галактика
|
||||||
|
("Галактика", "Аргенти", "Свободно", ""),
|
||||||
|
("Галактика", "Блэйд", "Свободно", ""),
|
||||||
|
("Галактика", "Бутхилл", "Свободно", ""),
|
||||||
|
("Галактика", "Доктор Рацио", "Свободно", ""),
|
||||||
|
("Галактика", "Кафка", "Свободно", ""),
|
||||||
|
("Галактика", "Светлячок", "Свободно", ""),
|
||||||
|
("Галактика", "Искорка", "Свободно", ""),
|
||||||
|
("Галактика", "Серебряный Волк", "Свободно", ""),
|
||||||
|
("Галактика", "Топаз", "Свободно", ""),
|
||||||
|
|
||||||
|
# Амфореус
|
||||||
|
("Амфореус", "Аглая", "Свободно", ""),
|
||||||
|
("Амфореус", "Мидей", "Свободно", ""),
|
||||||
|
("Амфореус", "Трибби", "Свободно", ""),
|
||||||
|
|
||||||
|
# Альянс Сяньчжоу
|
||||||
|
("Альянс Сяньчжоу", "Байлу", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Гуйнайфей", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Линша", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Лоча", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Моцзэ", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Пожиратель Луны", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Сушан", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Сюзи", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Фуга", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Фэйсяо", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Ханья", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Хохо", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Цзин Юань", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Цзиннлю", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Цзяоцю", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Цинцюэ", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Юйкун", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Юньли", "Свободно", ""),
|
||||||
|
("Альянс Сяньчжоу", "Яньцин", "Свободно", ""),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Заполнение таблиц начальными данными, если они пусты
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM characters")
|
||||||
|
if cursor.fetchone()[0] == 0:
|
||||||
|
cursor.executemany('INSERT INTO characters (region, name, status, comment) VALUES (?, ?, ?, ?)',
|
||||||
|
characters_genshin)
|
||||||
|
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM characters_hsr")
|
||||||
|
if cursor.fetchone()[0] == 0:
|
||||||
|
cursor.executemany('INSERT INTO characters_hsr (region, name, status, comment) VALUES (?, ?, ?, ?)',
|
||||||
|
characters_hsr)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def add_user(self, tg_id: int, username: str, first_name: str, last_name: str, role: str, status: str,
|
||||||
|
user: str) -> None:
|
||||||
|
"""Добавление нового пользователя в базу данных."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
|
||||||
|
# Проверка на существование пользователя
|
||||||
|
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
if cursor.fetchone():
|
||||||
|
return # Пользователь уже существует
|
||||||
|
|
||||||
|
# Определение нового user_id
|
||||||
|
cursor.execute("SELECT MAX(user_id) FROM users")
|
||||||
|
max_id = cursor.fetchone()[0]
|
||||||
|
new_user_id = 1 if max_id is None else max_id + 1
|
||||||
|
|
||||||
|
# Вставка пользователя
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO users (user_id, tg_id, username, first_name, last_name, role, status, user)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
''', (new_user_id, tg_id, username, first_name, last_name, role, status, user))
|
||||||
|
|
||||||
|
# Создание записи в user_messages
|
||||||
|
cursor.execute('INSERT INTO user_messages (user_id) VALUES (?)', (new_user_id,))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def get_user(self, tg_id: int) -> Optional[Tuple]:
|
||||||
|
"""Получение информации о пользователе по tg_id."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT * FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
return cursor.fetchone()
|
||||||
|
|
||||||
|
def update_user(self, tg_id: int, username: Optional[str] = None, first_name: Optional[str] = None,
|
||||||
|
last_name: Optional[str] = None, role: Optional[str] = None, user: Optional[str] = None) -> None:
|
||||||
|
"""Обновление данных о пользователе."""
|
||||||
|
updates = []
|
||||||
|
params = []
|
||||||
|
|
||||||
|
if username:
|
||||||
|
updates.append("username = ?")
|
||||||
|
params.append(username)
|
||||||
|
if first_name:
|
||||||
|
updates.append("first_name = ?")
|
||||||
|
params.append(first_name)
|
||||||
|
if last_name:
|
||||||
|
updates.append("last_name = ?")
|
||||||
|
params.append(last_name)
|
||||||
|
if role:
|
||||||
|
updates.append("role = ?")
|
||||||
|
params.append(role)
|
||||||
|
if user:
|
||||||
|
updates.append("user = ?")
|
||||||
|
params.append(user)
|
||||||
|
|
||||||
|
if updates:
|
||||||
|
query = f"UPDATE users SET {', '.join(updates)} WHERE tg_id = ?"
|
||||||
|
params.append(tg_id)
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute(query, params)
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def update_user_messages(self, message: types.Message) -> None:
|
||||||
|
"""Обновление статистики сообщений пользователя."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
tg_id = message.from_user.id
|
||||||
|
|
||||||
|
# Получение user_id
|
||||||
|
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if not result:
|
||||||
|
return # Пользователь не найден
|
||||||
|
user_id = result[0]
|
||||||
|
|
||||||
|
# Проверка существующей записи в user_messages
|
||||||
|
cursor.execute(
|
||||||
|
"SELECT last_message_time, messages_per_day, messages_per_week, messages_per_month, total_messages "
|
||||||
|
"FROM user_messages WHERE user_id = ?", (user_id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
|
||||||
|
# Время сообщения в московском часовом поясе
|
||||||
|
now = message.date.astimezone(timezone(timedelta(hours=3)))
|
||||||
|
today = now.date()
|
||||||
|
start_of_week = today - timedelta(days=today.weekday())
|
||||||
|
current_month = now.month
|
||||||
|
current_year = now.year
|
||||||
|
|
||||||
|
last_message = message.text or "Н/Д" # Замените на type_msg(message) при необходимости
|
||||||
|
last_message_id = message.message_id
|
||||||
|
|
||||||
|
if result:
|
||||||
|
last_message_time, messages_per_day, messages_per_week, messages_per_month, total_messages = result
|
||||||
|
if last_message_time:
|
||||||
|
last_message_time = datetime.fromisoformat(last_message_time).astimezone(
|
||||||
|
timezone(timedelta(hours=3)))
|
||||||
|
last_date = last_message_time.date()
|
||||||
|
last_week = last_date - timedelta(days=last_date.weekday())
|
||||||
|
last_month = last_message_time.month
|
||||||
|
last_year = last_message_time.year
|
||||||
|
|
||||||
|
# Обнуление счетчиков при смене периода
|
||||||
|
if last_date != today:
|
||||||
|
messages_per_day = 0
|
||||||
|
if last_week != start_of_week:
|
||||||
|
messages_per_week = 0
|
||||||
|
if last_month != current_month or last_year != current_year:
|
||||||
|
messages_per_month = 0
|
||||||
|
else:
|
||||||
|
messages_per_day, messages_per_week, messages_per_month = 0, 0, 0
|
||||||
|
|
||||||
|
# Увеличение счетчиков
|
||||||
|
messages_per_day += 1
|
||||||
|
messages_per_week += 1
|
||||||
|
messages_per_month += 1
|
||||||
|
total_messages += 1
|
||||||
|
else:
|
||||||
|
messages_per_day, messages_per_week, messages_per_month, total_messages = 1, 1, 1, 1
|
||||||
|
cursor.execute('''
|
||||||
|
INSERT INTO user_messages (user_id, last_message, last_message_id, last_message_time,
|
||||||
|
messages_per_day, messages_per_week, messages_per_month, total_messages)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
''', (user_id, last_message, last_message_id, now.isoformat(), messages_per_day,
|
||||||
|
messages_per_week, messages_per_month, total_messages))
|
||||||
|
db.commit()
|
||||||
|
return
|
||||||
|
|
||||||
|
# Обновление записи
|
||||||
|
cursor.execute('''
|
||||||
|
UPDATE user_messages
|
||||||
|
SET last_message = ?, last_message_id = ?, last_message_time = ?,
|
||||||
|
messages_per_day = ?, messages_per_week = ?, messages_per_month = ?,
|
||||||
|
total_messages = ?
|
||||||
|
WHERE user_id = ?
|
||||||
|
''', (last_message, last_message_id, now.isoformat(), messages_per_day,
|
||||||
|
messages_per_week, messages_per_month, total_messages, user_id))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def get_user_status(self, message: types.Message) -> str:
|
||||||
|
"""Получение статуса пользователя."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT user FROM users WHERE tg_id = ?", (message.from_user.id,))
|
||||||
|
row = cursor.fetchone()
|
||||||
|
status_map = {
|
||||||
|
"ban": "Забанен",
|
||||||
|
"user": "Пользователь",
|
||||||
|
"moderator": "Модератор",
|
||||||
|
"admin": "Администратор",
|
||||||
|
"so-owner": "Совладелец",
|
||||||
|
"owner": "Владелец",
|
||||||
|
}
|
||||||
|
return status_map.get(row[0], "Ошибка!") if row else "Пользователь не найден"
|
||||||
|
|
||||||
|
# --- Новые и улучшенные методы ---
|
||||||
|
|
||||||
|
def delete_user(self, tg_id: int) -> None:
|
||||||
|
"""Удаление пользователя из базы данных."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("DELETE FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def get_all_users(self) -> List[Tuple]:
|
||||||
|
"""Получение списка всех пользователей."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT * FROM users")
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def get_user_messages(self, tg_id: int) -> Optional[Tuple]:
|
||||||
|
"""Получение статистики сообщений пользователя."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if not result:
|
||||||
|
return None
|
||||||
|
user_id = result[0]
|
||||||
|
cursor.execute("SELECT * FROM user_messages WHERE user_id = ?", (user_id,))
|
||||||
|
return cursor.fetchone()
|
||||||
|
|
||||||
|
def ban_user(self, tg_id: int) -> None:
|
||||||
|
"""Блокировка пользователя."""
|
||||||
|
self.update_user(tg_id, user="ban")
|
||||||
|
|
||||||
|
def unban_user(self, tg_id: int) -> None:
|
||||||
|
"""Разблокировка пользователя."""
|
||||||
|
self.update_user(tg_id, user="user")
|
||||||
|
|
||||||
|
def promote_user(self, tg_id: int, new_role: str) -> None:
|
||||||
|
"""Изменение роли пользователя."""
|
||||||
|
valid_roles = ["user", "moderator", "admin", "so-owner", "owner"]
|
||||||
|
if new_role in valid_roles:
|
||||||
|
self.update_user(tg_id, user=new_role)
|
||||||
|
|
||||||
|
def get_top_active_users(self, limit: int = 10) -> List[Tuple]:
|
||||||
|
"""Получение самых активных пользователей по количеству сообщений."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT u.tg_id, u.username, um.total_messages
|
||||||
|
FROM users u
|
||||||
|
JOIN user_messages um ON u.user_id = um.user_id
|
||||||
|
ORDER BY um.total_messages DESC
|
||||||
|
LIMIT ?
|
||||||
|
''', (limit,))
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def assign_character(self, tg_id: int, character_id: int, game: str = "genshin") -> bool:
|
||||||
|
"""Назначение персонажа пользователю."""
|
||||||
|
table = "characters" if game == "genshin" else "characters_hsr"
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute(f"SELECT user_id FROM {table} WHERE id = ?", (character_id,))
|
||||||
|
result = cursor.fetchone()
|
||||||
|
if result and result[0] is not None:
|
||||||
|
return False # Персонаж уже занят
|
||||||
|
|
||||||
|
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
user_id = cursor.fetchone()
|
||||||
|
if not user_id:
|
||||||
|
return False # Пользователь не найден
|
||||||
|
|
||||||
|
cursor.execute(f"UPDATE {table} SET user_id = ?, status = 'Занят' WHERE id = ?", (user_id[0], character_id))
|
||||||
|
db.commit()
|
||||||
|
return True
|
||||||
|
|
||||||
|
def free_character(self, character_id: int, game: str = "genshin") -> None:
|
||||||
|
"""Освобождение персонажа."""
|
||||||
|
table = "characters" if game == "genshin" else "characters_hsr"
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute(f"UPDATE {table} SET user_id = NULL, status = 'Свободно' WHERE id = ?", (character_id,))
|
||||||
|
db.commit()
|
||||||
|
|
||||||
|
def get_user_characters(self, tg_id: int, game: str = "genshin") -> List[Tuple]:
|
||||||
|
"""Получение списка персонажей пользователя."""
|
||||||
|
table = "characters" if game == "genshin" else "characters_hsr"
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
||||||
|
user_id = cursor.fetchone()
|
||||||
|
if not user_id:
|
||||||
|
return []
|
||||||
|
cursor.execute(f"SELECT * FROM {table} WHERE user_id = ?", (user_id[0],))
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def search_users(self, query: str) -> List[Tuple]:
|
||||||
|
"""Поиск пользователей по имени или юзернейму."""
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute("""
|
||||||
|
SELECT * FROM users
|
||||||
|
WHERE username LIKE ? OR first_name LIKE ? OR last_name LIKE ?
|
||||||
|
""", (f"%{query}%", f"%{query}%", f"%{query}%"))
|
||||||
|
return cursor.fetchall()
|
||||||
|
|
||||||
|
def get_character_by_name(self, name: str, game: str = "genshin") -> Optional[Tuple]:
|
||||||
|
"""Поиск персонажа по имени."""
|
||||||
|
table = "characters" if game == "genshin" else "characters_hsr"
|
||||||
|
with sqlite3.connect(self.db_name) as db:
|
||||||
|
cursor = db.cursor()
|
||||||
|
cursor.execute(f"SELECT * FROM {table} WHERE name = ?", (name,))
|
||||||
|
return cursor.fetchone()
|
||||||
@@ -1,153 +1,115 @@
|
|||||||
# BotLibrary/system/bot_edit.py
|
# BotLibrary/system/bot_edit.py
|
||||||
# Под-пакет установки настроек бота
|
# Под-пакет установки настроек бота
|
||||||
|
|
||||||
from aiogram.types import ChatAdministratorRights
|
from aiogram import Bot
|
||||||
from ProjectsFiles import BotEdit
|
from ProjectsFiles import BotEdit
|
||||||
from .bots import bot
|
|
||||||
|
|
||||||
# Настройка логирования
|
|
||||||
log_type = "Edit"
|
|
||||||
|
|
||||||
# Настройка экспорта из модуля
|
# Настройка экспорта из модуля
|
||||||
__all__ = ("set_adm_rights", "set_bot_name", "set_bot_description", "set_bot_short_description")
|
__all__ = ("BotRights",)
|
||||||
|
|
||||||
# Функция установки прав администратора
|
class BotRights:
|
||||||
async def set_adm_rights(anonym: bool = BotEdit.is_anonymous,
|
|
||||||
manage_chat: bool = BotEdit.manage_chat,
|
|
||||||
delete_msg: bool = BotEdit.delete_messages,
|
|
||||||
manage_video_chats: bool = BotEdit.manage_video_chats,
|
|
||||||
restrict_members: bool = BotEdit.restrict_members,
|
|
||||||
promote_members: bool = BotEdit.promote_members,
|
|
||||||
change_info: bool = BotEdit.change_info,
|
|
||||||
invite_users: bool = BotEdit.invite_users,
|
|
||||||
post_stories: bool = BotEdit.post_stories,
|
|
||||||
edit_stories: bool = BotEdit.edit_stories,
|
|
||||||
delete_stories: bool = BotEdit.delete_stories,
|
|
||||||
post_messages: bool = BotEdit.post_messages,
|
|
||||||
edit_messages: bool = BotEdit.edit_messages,
|
|
||||||
pin_messages: bool = BotEdit.pin_messages,
|
|
||||||
manage_topics: bool = BotEdit.manage_topics,) -> None:
|
|
||||||
"""
|
"""
|
||||||
Устанавливает права администратора для бота, если они отличаются от текущих.
|
Класс для установки прав администратора и метаинформации бота (имя, описания).
|
||||||
Все через конфиги!!!
|
|
||||||
|
|
||||||
:param anonym: Позволяет ли боту быть анонимным.
|
|
||||||
:param manage_chat: Разрешение на управление чатом.
|
|
||||||
:param delete_msg: Разрешение на удаление сообщений.
|
|
||||||
:param manage_video_chats: Разрешение на управление видеочатами.
|
|
||||||
:param restrict_members: Разрешение на ограничение участников (мут, бан).
|
|
||||||
:param promote_members: Разрешение на назначение администраторов.
|
|
||||||
:param change_info: Разрешение на изменение информации о группе/канале.
|
|
||||||
:param invite_users: Разрешение на приглашение новых участников.
|
|
||||||
:param post_stories: Разрешение на публикацию историй.
|
|
||||||
:param edit_stories: Разрешение на редактирование историй.
|
|
||||||
:param delete_stories: Разрешение на удаление историй.
|
|
||||||
:param post_messages: Разрешение на публикацию сообщений (только для каналов).
|
|
||||||
:param edit_messages: Разрешение на редактирование сообщений (только для каналов).
|
|
||||||
:param pin_messages: Разрешение на закрепление сообщений.
|
|
||||||
:param manage_topics: Разрешение на управление темами (в супергруппах).
|
|
||||||
|
|
||||||
:return: Изменение прав администратора
|
|
||||||
"""
|
"""
|
||||||
rights = ChatAdministratorRights(
|
@staticmethod
|
||||||
is_anonymous=anonym,
|
async def set_administrator_rights(bot: Bot) -> None:
|
||||||
can_manage_chat=manage_chat,
|
"""
|
||||||
can_delete_messages=delete_msg,
|
Установка прав администратора в чатах.
|
||||||
can_manage_video_chats=manage_video_chats,
|
|
||||||
can_restrict_members=restrict_members,
|
:param bot: Базовый объект бота.
|
||||||
can_promote_members=promote_members,
|
:return: Измененные права по конфигу.
|
||||||
can_change_info=change_info,
|
"""
|
||||||
can_invite_users=invite_users,
|
from aiogram.types import ChatAdministratorRights
|
||||||
can_post_stories=post_stories,
|
rights: ChatAdministratorRights = ChatAdministratorRights(
|
||||||
can_edit_stories=edit_stories,
|
is_anonymous=BotEdit.is_anonymous,
|
||||||
can_delete_stories=delete_stories,
|
can_manage_chat=BotEdit.manage_chat,
|
||||||
can_post_messages=post_messages,
|
can_delete_messages=BotEdit.delete_messages,
|
||||||
can_edit_messages=edit_messages,
|
can_manage_video_chats=BotEdit.manage_video_chats,
|
||||||
can_pin_messages=pin_messages,
|
can_restrict_members=BotEdit.restrict_members,
|
||||||
can_manage_topics=manage_topics,
|
can_promote_members=BotEdit.promote_members,
|
||||||
|
can_change_info=BotEdit.change_info,
|
||||||
|
can_invite_users=BotEdit.invite_users,
|
||||||
|
can_post_stories=BotEdit.post_stories,
|
||||||
|
can_edit_stories=BotEdit.edit_stories,
|
||||||
|
can_delete_stories=BotEdit.delete_stories,
|
||||||
|
can_post_messages=BotEdit.post_messages,
|
||||||
|
can_edit_messages=BotEdit.edit_messages,
|
||||||
|
can_pin_messages=BotEdit.pin_messages,
|
||||||
|
can_manage_topics=BotEdit.manage_topics,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Применяем права только в случае изменения
|
current_rights: ChatAdministratorRights = await bot.get_my_default_administrator_rights()
|
||||||
current_rights = await bot.get_my_default_administrator_rights()
|
|
||||||
if current_rights != rights:
|
if current_rights != rights:
|
||||||
await bot.set_my_default_administrator_rights(rights)
|
await bot.set_my_default_administrator_rights(rights)
|
||||||
else:
|
|
||||||
|
@staticmethod
|
||||||
|
async def set_name(bot: Bot) -> None:
|
||||||
|
"""
|
||||||
|
Установка имени бота.
|
||||||
|
|
||||||
|
:param bot: Базовый объект бота.
|
||||||
|
:return: Измененное имя бота.
|
||||||
|
"""
|
||||||
|
current_name: str = (await bot.get_me()).first_name
|
||||||
|
new_name: str = str(BotEdit.name)
|
||||||
|
|
||||||
|
if not (1 <= len(new_name) <= 32):
|
||||||
|
from ..loggers import Logs
|
||||||
|
Logs.error(log_type="SET_NAME", user="BOT", text="Имя бота должно быть от 1 до 32 символов.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Функция установки имени бота с проверкой на ограничения
|
|
||||||
async def set_bot_name(new_name: str = BotEdit.name) -> None:
|
|
||||||
"""
|
|
||||||
Устанавливает имя бота, если оно отличается от текущего и соответствует ограничениям.
|
|
||||||
|
|
||||||
:param new_name: Новое имя бота (config)
|
|
||||||
:return: Имя бота
|
|
||||||
"""
|
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
|
||||||
from ..loggers.custom_loggers import Logs
|
|
||||||
|
|
||||||
# Получаем текущее имя бота
|
|
||||||
current_name = (await bot.get_me()).first_name
|
|
||||||
|
|
||||||
# Проверка длины имени
|
|
||||||
if len(new_name) < 1 or len(new_name) > 32:
|
|
||||||
Logs.error(log_type=log_type, user="NAME_BOT", text="Имя бота должно быть от 1 до 32 символов.")
|
|
||||||
return # Выходим из функции, если имя некорректно
|
|
||||||
|
|
||||||
# Проверяем, совпадает ли текущее имя с тем, которое мы хотим установить
|
|
||||||
if current_name != new_name:
|
if current_name != new_name:
|
||||||
await bot.set_my_name(new_name)
|
await bot.set_my_name(new_name)
|
||||||
else:
|
|
||||||
|
@staticmethod
|
||||||
|
async def set_description(bot: Bot) -> None:
|
||||||
|
"""
|
||||||
|
Установка описания бота.
|
||||||
|
|
||||||
|
:param bot: Базовый объект бота.
|
||||||
|
:return: Измененное описание бота.
|
||||||
|
"""
|
||||||
|
from aiogram.types import BotDescription
|
||||||
|
current_description: BotDescription = await bot.get_my_description()
|
||||||
|
new_description: str = str(BotEdit.description)
|
||||||
|
|
||||||
|
if not (0 < len(new_description) <= 255):
|
||||||
|
from ..loggers import Logs
|
||||||
|
Logs.error(log_type="SET_DESCRIPTION", user="BOT", text="Описание должно быть от 1 до 255 символов.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Функция установки описания бота с проверкой на ограничения
|
|
||||||
async def set_bot_description(new_description: str = BotEdit.description) -> None:
|
|
||||||
"""
|
|
||||||
Устанавливает описание бота, если оно отличается от текущего и соответствует ограничениям.
|
|
||||||
|
|
||||||
:param new_description: Новое описание для бота (config)
|
|
||||||
:return: Описание бота
|
|
||||||
"""
|
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
|
||||||
from ..loggers.custom_loggers import Logs
|
|
||||||
|
|
||||||
# Получаем текущее описание бота
|
|
||||||
current_description = await bot.get_my_description()
|
|
||||||
|
|
||||||
# Проверка длины описания
|
|
||||||
if len(new_description) > 255 or len(new_description)==0:
|
|
||||||
Logs.error(log_type=log_type, user="DISCRIPT", text="Короткое описание бота не может превышать 255 символов или быть равно 0.")
|
|
||||||
return # Выходим из функции, если описание некорректно
|
|
||||||
|
|
||||||
# Проверяем, совпадает ли текущее описание с тем, которое мы хотим установить
|
|
||||||
if current_description != new_description:
|
if current_description != new_description:
|
||||||
await bot.set_my_description(description=new_description)
|
await bot.set_my_description(description=new_description)
|
||||||
else:
|
|
||||||
|
@staticmethod
|
||||||
|
async def set_short_description(bot: Bot) -> None:
|
||||||
|
"""
|
||||||
|
Установка описания виджета.
|
||||||
|
|
||||||
|
:param bot: Базовый объект бота.
|
||||||
|
:return: Измененное описание виджета бота.
|
||||||
|
"""
|
||||||
|
from aiogram.types import BotShortDescription
|
||||||
|
current_short_description: BotShortDescription = await bot.get_my_short_description()
|
||||||
|
new_short_description: str = str(BotEdit.short_description)
|
||||||
|
|
||||||
|
if not (0 < len(new_short_description) <= 512):
|
||||||
|
from ..loggers import Logs
|
||||||
|
Logs.error(log_type="SET_SHORT_DESCRIPTION", user="BOT", text="Короткое описание должно быть от 1 до 512 символов.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# Функция установки короткого описания бота с проверкой на ограничения
|
|
||||||
async def set_bot_short_description(new_short_description: str = BotEdit.short_description) -> None:
|
|
||||||
"""
|
|
||||||
Устанавливает короткое описание бота, если оно отличается от текущего и соответствует ограничениям.
|
|
||||||
|
|
||||||
:param new_short_description: Новое описание виджета для бота (config)
|
|
||||||
:return: Короткое описание бота
|
|
||||||
"""
|
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
|
||||||
from ..loggers.custom_loggers import Logs
|
|
||||||
|
|
||||||
# Получаем текущее короткое описание бота
|
|
||||||
current_short_description = await bot.get_my_short_description()
|
|
||||||
|
|
||||||
# Проверка длины короткого описания
|
|
||||||
if len(new_short_description) > 512 or len(new_short_description) == 0:
|
|
||||||
Logs.error(log_type=log_type, user="SHORT_DISCRIPT", text="Описание виджета не может превышать 512 символов или быть равно 0.")
|
|
||||||
return # Выходим из функции, если короткое описание некорректно
|
|
||||||
|
|
||||||
# Проверяем, совпадает ли текущее короткое описание с тем, которое мы хотим установить
|
|
||||||
if current_short_description != new_short_description:
|
if current_short_description != new_short_description:
|
||||||
await bot.set_my_short_description(short_description=new_short_description)
|
await bot.set_my_short_description(short_description=new_short_description)
|
||||||
else:
|
|
||||||
return
|
@staticmethod
|
||||||
|
async def all(bot: Bot) -> None:
|
||||||
|
"""
|
||||||
|
Применяет все настройки: права, имя, описание и короткое описание.
|
||||||
|
|
||||||
|
:param bot: Базовый объект бота.
|
||||||
|
:return: Изменение всех основных параметров бота.
|
||||||
|
"""
|
||||||
|
await BotRights.set_administrator_rights(bot)
|
||||||
|
await BotRights.set_name(bot)
|
||||||
|
await BotRights.set_description(bot)
|
||||||
|
await BotRights.set_short_description(bot)
|
||||||
|
|||||||
@@ -17,23 +17,14 @@ dp = Dispatcher()
|
|||||||
dp["started_at"] = get_host_time()
|
dp["started_at"] = get_host_time()
|
||||||
dp["started_at_city"] = get_city_time()
|
dp["started_at_city"] = get_city_time()
|
||||||
dp["is_active"] = True # Флаг активности бота
|
dp["is_active"] = True # Флаг активности бота
|
||||||
dp["logs"] = []
|
|
||||||
dp["users"] = {}
|
|
||||||
dp["admins"] = {}
|
|
||||||
dp["sessions"] = {}
|
|
||||||
dp["task_queue"] = []
|
|
||||||
dp["configs"] = {"max_connections": 100, "retry_interval": 5, "time_format": BotVar.time_format}
|
dp["configs"] = {"max_connections": 100, "retry_interval": 5, "time_format": BotVar.time_format}
|
||||||
dp["metrics"] = {"messages_received": 0, "messages_sent": 0, "errors": 0}
|
dp["metrics"] = {"messages_received": 0, "messages_sent": 0, "errors": 0}
|
||||||
dp["modules"] = {}
|
|
||||||
dp["state"] = {}
|
|
||||||
dp["scheduler"] = []
|
|
||||||
dp["handlers"] = {"on_message": [], "on_error": []}
|
dp["handlers"] = {"on_message": [], "on_error": []}
|
||||||
dp["storage"] = {}
|
|
||||||
dp["database"] = "SQLite3"
|
dp["database"] = "SQLite3"
|
||||||
|
|
||||||
|
|
||||||
# Создание экземпляра бота и его настройка
|
# Создание экземпляра бота и его настройка
|
||||||
bot = Bot(token=bot_token, default=DefaultBotProperties(
|
bot: Bot = Bot(token=bot_token, default=DefaultBotProperties(
|
||||||
parse_mode=BotVar.parse_mode,
|
parse_mode=BotVar.parse_mode,
|
||||||
disable_notification=BotVar.disable_notification,
|
disable_notification=BotVar.disable_notification,
|
||||||
protect_content=BotVar.protect_content,
|
protect_content=BotVar.protect_content,
|
||||||
@@ -57,27 +48,31 @@ class BotInfo:
|
|||||||
"""
|
"""
|
||||||
id: int = None
|
id: int = None
|
||||||
first_name: str = None
|
first_name: str = None
|
||||||
bot_owner: str = BotVar
|
|
||||||
last_name: str = None
|
last_name: str = None
|
||||||
username: str = None
|
username: str = None
|
||||||
description: str = None
|
description: str = ''
|
||||||
short_description: str = None
|
short_description: str = ''
|
||||||
can_join_groups: bool = False
|
|
||||||
can_read_all_group_messages: bool = False
|
|
||||||
language_code: str = BotVar.language
|
language_code: str = BotVar.language
|
||||||
prefix: str = BotVar.prefix
|
prefix: str = BotVar.prefix
|
||||||
|
bot_owner: str = BotVar
|
||||||
is_premium: bool = False
|
is_premium: bool = False
|
||||||
added_to_attachment_menu: bool = False
|
added_to_attachment_menu: bool = False
|
||||||
supports_inline_queries: bool = False
|
supports_inline_queries: bool = False
|
||||||
can_connect_to_business: bool = False
|
can_connect_to_business: bool = False
|
||||||
has_main_web_app: bool = False
|
has_main_web_app: bool = False
|
||||||
|
can_join_groups: bool = False
|
||||||
|
can_read_all_group_messages: bool = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update(cls, bot_info) -> None:
|
async def info(cls, bots: Bot = bot) -> dict:
|
||||||
"""
|
"""
|
||||||
Обновляет данные о боте.
|
Получает информацию о боте через API и обновляет данные в классе.
|
||||||
:param bot_info: Объект с данными о боте, полученные через API Telegram.
|
|
||||||
|
:param bots: Объект бота
|
||||||
|
:return: Словарь с данными о боте
|
||||||
"""
|
"""
|
||||||
|
bot_info = await bots.get_me()
|
||||||
|
|
||||||
cls.id = bot_info.id
|
cls.id = bot_info.id
|
||||||
cls.first_name = bot_info.first_name
|
cls.first_name = bot_info.first_name
|
||||||
cls.last_name = bot_info.last_name
|
cls.last_name = bot_info.last_name
|
||||||
@@ -93,31 +88,28 @@ class BotInfo:
|
|||||||
cls.can_join_groups = getattr(bot_info, 'can_join_groups', False)
|
cls.can_join_groups = getattr(bot_info, 'can_join_groups', False)
|
||||||
cls.can_read_all_group_messages = getattr(bot_info, 'can_read_all_group_messages', False)
|
cls.can_read_all_group_messages = getattr(bot_info, 'can_read_all_group_messages', False)
|
||||||
|
|
||||||
|
return cls.to_dict()
|
||||||
|
|
||||||
# Функция получения информации о боте
|
@classmethod
|
||||||
async def bot_get_info(bots: Bot = bot) -> dict:
|
def to_dict(cls) -> dict:
|
||||||
"""
|
"""
|
||||||
Получает информацию о боте и обновляет данные в классе BotInfo.
|
Возвращает текущие данные в виде словаря.
|
||||||
:param bots: Получение объекта бота в функцию.
|
|
||||||
:return: Словарь с данными о боте.
|
|
||||||
"""
|
"""
|
||||||
bot_info_data = await bots.get_me()
|
|
||||||
BotInfo.update(bot_info_data)
|
|
||||||
return {
|
return {
|
||||||
'bot_info': bot_info_data,
|
'id': cls.id,
|
||||||
'id': bot_info_data.id,
|
'first_name': cls.first_name,
|
||||||
'first_name': bot_info_data.first_name,
|
'last_name': cls.last_name,
|
||||||
'last_name': bot_info_data.last_name,
|
'username': cls.username,
|
||||||
'username': bot_info_data.username,
|
'description': cls.description,
|
||||||
'description': getattr(bot_info_data, 'description', ''),
|
'short_description': cls.short_description,
|
||||||
'short_description': getattr(bot_info_data, 'short_description', ''),
|
'language_code': cls.language_code,
|
||||||
'language_code': bot_info_data.language_code,
|
'prefix': cls.prefix,
|
||||||
'prefix': BotVar.prefix,
|
'bot_owner': cls.bot_owner,
|
||||||
'is_premium': bot_info_data.is_premium,
|
'is_premium': cls.is_premium,
|
||||||
'added_to_attachment_menu': bot_info_data.added_to_attachment_menu,
|
'added_to_attachment_menu': cls.added_to_attachment_menu,
|
||||||
'supports_inline_queries': bot_info_data.supports_inline_queries,
|
'supports_inline_queries': cls.supports_inline_queries,
|
||||||
'can_connect_to_business': bot_info_data.can_connect_to_business,
|
'can_connect_to_business': cls.can_connect_to_business,
|
||||||
'has_main_web_app': bot_info_data.has_main_web_app,
|
'has_main_web_app': cls.has_main_web_app,
|
||||||
'can_join_groups': getattr(bot_info_data, 'can_join_groups', False),
|
'can_join_groups': cls.can_join_groups,
|
||||||
'can_read_all_group_messages': getattr(bot_info_data, 'can_read_all_group_messages', False),
|
'can_read_all_group_messages': cls.can_read_all_group_messages,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,26 +2,25 @@
|
|||||||
# Создание пустых директорий при первом запуске
|
# Создание пустых директорий при первом запуске
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from ProjectsFiles import ProjectPath, TypeDirectory
|
|
||||||
from typing import List
|
from typing import List
|
||||||
|
from ProjectsFiles import ProjectPath, TypeDirectory
|
||||||
|
|
||||||
# Настройка экспорта из модуля
|
# Настройка экспорта из модуля
|
||||||
__all__ = ("create_directories", "setup_directories", "create_directory")
|
__all__ = ("Directory",)
|
||||||
|
|
||||||
|
class Directory:
|
||||||
# Функция создания директории
|
@staticmethod
|
||||||
async def create_directory(directory : str) -> None:
|
async def create_directory(directory: str) -> None:
|
||||||
"""
|
"""
|
||||||
Создает директории, если они еще не существуют.
|
Создает директории, если они еще не существуют.
|
||||||
|
|
||||||
:param directory: Путь к базовой директории.
|
:param directory: Путь к базовой директории.
|
||||||
:return: Создание директорий по определенному пути.
|
:return: Создание директорий по определенному пути.
|
||||||
"""
|
"""
|
||||||
os.makedirs(directory)
|
os.makedirs(directory, exist_ok=True)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
# Функция создания поддиректорий
|
async def create_directories(base_directory: str, subdirectories: List[str]) -> None:
|
||||||
async def create_directories(base_directory: str, subdirectories: List[str]) -> None:
|
|
||||||
"""
|
"""
|
||||||
Создает указанные поддиректории в указанной базовой директории.
|
Создает указанные поддиректории в указанной базовой директории.
|
||||||
|
|
||||||
@@ -34,19 +33,16 @@ async def create_directories(base_directory: str, subdirectories: List[str]) ->
|
|||||||
directory_path = os.path.join(base_directory, subdirectory)
|
directory_path = os.path.join(base_directory, subdirectory)
|
||||||
|
|
||||||
# Проверка, существует ли директория, если нет - создаём
|
# Проверка, существует ли директория, если нет - создаём
|
||||||
if not os.path.exists(directory_path):
|
os.makedirs(directory_path, exist_ok=True)
|
||||||
os.makedirs(directory_path)
|
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
# Функция установки начальных директорий
|
async def setup() -> None:
|
||||||
async def setup_directories() -> None:
|
|
||||||
"""
|
"""
|
||||||
Настройка начальных пустых директорий для проекта.
|
Настройка начальных пустых директорий для проекта.
|
||||||
|
|
||||||
:return: Создание системы директорий по определенному пути.
|
:return: Создание системы директорий по определенному пути.
|
||||||
"""
|
"""
|
||||||
# Создание директорий для медиа файлов
|
# Создание директорий для медиа файлов
|
||||||
await create_directories(ProjectPath.personal_media, TypeDirectory.media_directories)
|
await Directory.create_directories(ProjectPath.personal_media, TypeDirectory.media_directories)
|
||||||
await create_directories(ProjectPath.received_media, TypeDirectory.media_directories)
|
await Directory.create_directories(ProjectPath.received_media, TypeDirectory.media_directories)
|
||||||
await create_directories(ProjectPath.received_avatars, TypeDirectory.avatar_directories)
|
await Directory.create_directories(ProjectPath.received_avatars, TypeDirectory.avatar_directories)
|
||||||
# await create_directories(ProjectPath.msg, TypeDirectory.msg_directories)
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# BotLibrary/timer/start_time.py
|
# BotLibrary/timer/start_time.py
|
||||||
# Получение времени по разным часовым поясам
|
# Получение времени по разным часовым поясам
|
||||||
|
|
||||||
import pytz
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from tzlocal import get_localzone
|
from tzlocal import get_localzone
|
||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
@@ -14,7 +13,6 @@ __all__ = ("scheduler", "get_city_time", "get_host_time")
|
|||||||
scheduler = AsyncIOScheduler(timezone=get_localzone().key)
|
scheduler = AsyncIOScheduler(timezone=get_localzone().key)
|
||||||
|
|
||||||
|
|
||||||
# Функция получение иного времени
|
|
||||||
def get_city_time(city: str = 'Europe/Moscow',
|
def get_city_time(city: str = 'Europe/Moscow',
|
||||||
time_format: str = BotVar.time_format) -> str:
|
time_format: str = BotVar.time_format) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -24,13 +22,13 @@ def get_city_time(city: str = 'Europe/Moscow',
|
|||||||
:param time_format: Шаблон форматирования времени (конфиг).
|
:param time_format: Шаблон форматирования времени (конфиг).
|
||||||
:return: Строка, представляющая время в формате, заданном в BotVar.time_format.
|
:return: Строка, представляющая время в формате, заданном в BotVar.time_format.
|
||||||
"""
|
"""
|
||||||
|
from pytz import timezone
|
||||||
# Устанавливаем временную зону для Москвы
|
# Устанавливаем временную зону для Москвы
|
||||||
city_tz = pytz.timezone(city)
|
city_tz = timezone(city)
|
||||||
# Возвращаем строку с форматом времени
|
# Возвращаем строку с форматом времени
|
||||||
return datetime.now(city_tz).strftime(time_format)
|
return datetime.now(city_tz).strftime(time_format)
|
||||||
|
|
||||||
|
|
||||||
# Функция получение времени хоста
|
|
||||||
def get_host_time(time_format: str = BotVar.time_format) -> str:
|
def get_host_time(time_format: str = BotVar.time_format) -> str:
|
||||||
"""
|
"""
|
||||||
Получение текущего времени хоста (локального времени).
|
Получение текущего времени хоста (локального времени).
|
||||||
|
|||||||
@@ -2,13 +2,10 @@
|
|||||||
# Создание валидации почты для проекта
|
# Создание валидации почты для проекта
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from email_validator import validate_email, EmailNotValidError
|
|
||||||
|
|
||||||
# Настройка экспорта из этого модуля
|
# Настройка экспорта из этого модуля
|
||||||
__all__ = ("valid_email",)
|
__all__ = ("valid_email",)
|
||||||
|
|
||||||
|
|
||||||
# Функция проверки почты на корректность
|
|
||||||
def valid_email(email: str) -> Optional[str]:
|
def valid_email(email: str) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
Делает почтовый адрес корректным.
|
Делает почтовый адрес корректным.
|
||||||
@@ -16,10 +13,12 @@ def valid_email(email: str) -> Optional[str]:
|
|||||||
:param email: Почтовый адрес в виде строки.
|
:param email: Почтовый адрес в виде строки.
|
||||||
:return: Нормализованный почтовый адрес, если он валиден, иначе None.
|
:return: Нормализованный почтовый адрес, если он валиден, иначе None.
|
||||||
"""
|
"""
|
||||||
|
from email_validator import validate_email, EmailNotValidError
|
||||||
try:
|
try:
|
||||||
return validate_email(email).normalized
|
return validate_email(email).normalized
|
||||||
|
|
||||||
except EmailNotValidError as e:
|
except EmailNotValidError as e:
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
||||||
from ..loggers.custom_loggers import Logs
|
from ..loggers.logs import Logs
|
||||||
Logs.error(text=f"Ошибка в нормализировании почты: {e}", log_type="NormalEmail")
|
Logs.error(text=f"Ошибка в нормализировании почты: {e}", log_type="NormalEmail")
|
||||||
return None
|
return None
|
||||||
@@ -13,8 +13,9 @@ async def normal_words(word: str) -> str:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return word.lower().capitalize()
|
return word.lower().capitalize()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
||||||
from ..loggers.custom_loggers import Logs
|
from ..loggers.logs import Logs
|
||||||
Logs.error(text=f"Ошибка в нормализировании слова: {e}", log_type="NormalWord")
|
Logs.error(text=f"Ошибка в нормализировании слова: {e}", log_type="NormalWord")
|
||||||
return word
|
return word
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
# BotLibrary/validators/url_valid.py
|
# BotLibrary/validators/url_valid.py
|
||||||
# Валидатор ссылок на регулярных выражениях
|
# Валидатор ссылок на регулярных выражениях
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
# Настройка экспорта из этого модуля
|
# Настройка экспорта из этого модуля
|
||||||
__all__ = ("valid_url", "url_to_text")
|
__all__ = ("valid_url", "url_to_text")
|
||||||
|
|
||||||
|
|
||||||
# Функция определения является ли строка ссылкой
|
|
||||||
def valid_url(url: str) -> bool:
|
def valid_url(url: str) -> bool:
|
||||||
"""
|
"""
|
||||||
Проверяет, является ли строка валидной ссылкой (URL).
|
Проверяет, является ли строка валидной ссылкой (URL).
|
||||||
@@ -15,7 +11,8 @@ def valid_url(url: str) -> bool:
|
|||||||
:param url: Строка для проверки.
|
:param url: Строка для проверки.
|
||||||
:return: True, если строка является валидным URL, иначе False.
|
:return: True, если строка является валидным URL, иначе False.
|
||||||
"""
|
"""
|
||||||
url_pattern = re.compile(
|
from re import compile
|
||||||
|
url_pattern = compile(
|
||||||
r'^(https?://)?' # Протокол (http или https, необязателен)
|
r'^(https?://)?' # Протокол (http или https, необязателен)
|
||||||
r'([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}' # Домен
|
r'([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}' # Домен
|
||||||
r'(:\d+)?' # Порт (необязателен)
|
r'(:\d+)?' # Порт (необязателен)
|
||||||
@@ -24,7 +21,6 @@ def valid_url(url: str) -> bool:
|
|||||||
return bool(url_pattern.match(url))
|
return bool(url_pattern.match(url))
|
||||||
|
|
||||||
|
|
||||||
# Функция, что дает тексту ссылку на HTML
|
|
||||||
def url_to_text(text: str, url: str) -> str:
|
def url_to_text(text: str, url: str) -> str:
|
||||||
"""
|
"""
|
||||||
Преобразует текст в HTML ссылку с указанным URL.
|
Преобразует текст в HTML ссылку с указанным URL.
|
||||||
@@ -45,7 +41,7 @@ def url_to_text(text: str, url: str) -> str:
|
|||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
# Импортируем Logs внутри функции, чтобы избежать циклического импорта
|
||||||
from ..loggers.custom_loggers import Logs
|
from ..loggers.logs import Logs
|
||||||
# Логируем ошибку с использованием Logs.error, как указано
|
# Логируем ошибку с использованием Logs.error, как указано
|
||||||
Logs.error(text=f"Ошибка при создании ссылки: {e}", log_type="InvalidURL")
|
Logs.error(text=f"Ошибка при создании ссылки: {e}", log_type="InvalidURL")
|
||||||
raise e # Перебрасываем ошибку выше для дальнейшей обработки или уведомления
|
raise e # Перебрасываем ошибку выше для дальнейшей обработки или уведомления
|
||||||
@@ -7,7 +7,6 @@ from aiogram.types import Message
|
|||||||
__all__ = ("username", "username_to_text")
|
__all__ = ("username", "username_to_text")
|
||||||
|
|
||||||
|
|
||||||
# Функция получения юзера или ID пользователя
|
|
||||||
def username(message: Message) -> str:
|
def username(message: Message) -> str:
|
||||||
"""
|
"""
|
||||||
Возвращает юзернейм пользователя из сообщения, или ID, если юзернейм не указан.
|
Возвращает юзернейм пользователя из сообщения, или ID, если юзернейм не указан.
|
||||||
@@ -26,7 +25,6 @@ def username(message: Message) -> str:
|
|||||||
raise e # Перебрасываем ошибку выше для дальнейшей обработки
|
raise e # Перебрасываем ошибку выше для дальнейшей обработки
|
||||||
|
|
||||||
|
|
||||||
# Функция получение имени пользователя + ссылка на него
|
|
||||||
def username_to_text(message: Message) -> str:
|
def username_to_text(message: Message) -> str:
|
||||||
"""
|
"""
|
||||||
Преобразует информацию о пользователе в строку с HTML-ссылкой.
|
Преобразует информацию о пользователе в строку с HTML-ссылкой.
|
||||||
|
|||||||
@@ -14,15 +14,6 @@
|
|||||||
-...
|
-...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Второй модуль loggers:
|
Второй модуль loggers:
|
||||||
logs.py - создает логгеры, три кастомных уровня и 4 обычных. Он может создавать
|
logs.py - создает логгеры, три кастомных уровня и 4 обычных. Он может создавать
|
||||||
-NEW_USER
|
-NEW_USER
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
# GUI/__init__.py
|
|
||||||
# Инициализация пакета GUI, для работы с графическим интерфейсом
|
|
||||||
|
|
||||||
from .console import *
|
|
||||||
167
GUI/console.py
167
GUI/console.py
@@ -1,167 +0,0 @@
|
|||||||
from tkinter import PhotoImage
|
|
||||||
import customtkinter as ctk # модуль для создания стилизованных интерфейсов
|
|
||||||
from PIL import Image, ImageTk
|
|
||||||
from BotLibrary import * # импорт настроек бота (например, имени, фамилии, и имени пользователя)
|
|
||||||
|
|
||||||
# Создание роутера и настройка экспорта
|
|
||||||
__all__ = ("App", )
|
|
||||||
command_text = "GUI"
|
|
||||||
|
|
||||||
|
|
||||||
# Настройка внешнего вида интерфейса
|
|
||||||
ctk.set_appearance_mode("System") # Установка режима внешнего вида: "System", "Dark" или "Light"
|
|
||||||
ctk.set_default_color_theme("blue") # Установка цветовой темы: "blue", "green", "dark-blue"
|
|
||||||
|
|
||||||
|
|
||||||
# Класс приложения, наследующий от customtkinter.CTk
|
|
||||||
class App(ctk.CTk):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__() # Инициализация базового класса
|
|
||||||
|
|
||||||
# Настройка главного окна
|
|
||||||
self.title(f"{BotInfo.first_name} {BotInfo.last_name} - @{BotInfo.username}") # Заголовок окна
|
|
||||||
self.geometry(f"{700}x{580}") # Размер окна (ширина x высота)
|
|
||||||
|
|
||||||
# Настройка сетки (разметка окна на ячейки)
|
|
||||||
self.grid_columnconfigure(0, weight=1) # Установка растяжения для 1-го столбца (боковая панель)
|
|
||||||
self.grid_columnconfigure(1, weight=9) # Установка растяжения для 2-го столбца (содержимое вкладок)
|
|
||||||
self.grid_rowconfigure((0, 1), weight=1) # Установка растяжения для первых трех строк
|
|
||||||
|
|
||||||
# Создание боковой панели
|
|
||||||
self.sidebar_frame = ctk.CTkFrame(self, width=100, corner_radius=0) # Рамка боковой панели с уменьшенной шириной
|
|
||||||
self.sidebar_frame.grid(row=0, column=0, rowspan=4, sticky="nsew") # Расположение в сетке
|
|
||||||
self.sidebar_frame.grid_rowconfigure(4, weight=1) # Установка растяжения для 4-й строки
|
|
||||||
|
|
||||||
# Логотип на боковой панели
|
|
||||||
self.logo_label = ctk.CTkLabel(self.sidebar_frame, text=BotInfo.username,
|
|
||||||
font=ctk.CTkFont(size=16, weight="bold")) # Метка с текстом
|
|
||||||
self.logo_label.grid(row=0, column=0, padx=10, pady=(20, 10)) # Расположение метки в сетке
|
|
||||||
|
|
||||||
# Кнопки на боковой панели
|
|
||||||
self.sidebar_button_1 = ctk.CTkButton(self.sidebar_frame, text="Консоль",
|
|
||||||
command=self.switch_tab_console,
|
|
||||||
font=ctk.CTkFont(size=14))
|
|
||||||
self.sidebar_button_1.grid(row=1, column=0, padx=10, pady=10) # Первая кнопка
|
|
||||||
self.sidebar_button_2 = ctk.CTkButton(self.sidebar_frame, text="База данных",
|
|
||||||
command=self.switch_tab_database,
|
|
||||||
font=ctk.CTkFont(size=14))
|
|
||||||
self.sidebar_button_2.grid(row=2, column=0, padx=10, pady=10) # Вторая кнопка
|
|
||||||
self.sidebar_button_3 = ctk.CTkButton(self.sidebar_frame, text="Иное",
|
|
||||||
command=self.switch_tab_other,
|
|
||||||
font=ctk.CTkFont(size=14))
|
|
||||||
self.sidebar_button_3.grid(row=3, column=0, padx=10, pady=10) # Третья кнопка
|
|
||||||
|
|
||||||
# Новые кнопки "Запуск" и "Выключение"
|
|
||||||
self.start_button = ctk.CTkButton(self.sidebar_frame, text="Запуск", command=self.start_button_click,
|
|
||||||
font=ctk.CTkFont(size=14))
|
|
||||||
self.start_button.grid(row=5, column=0, padx=10, pady=10) # Кнопка "Запуск"
|
|
||||||
|
|
||||||
self.stop_button = ctk.CTkButton(self.sidebar_frame, text="Выключение",
|
|
||||||
command=self.stop_button_click,
|
|
||||||
font=ctk.CTkFont(size=14))
|
|
||||||
self.stop_button.grid(row=6, column=0, padx=10, pady=10) # Кнопка "Выключение"
|
|
||||||
|
|
||||||
# Элементы управления режимами и масштабированием интерфейса
|
|
||||||
self.appearance_mode_label = ctk.CTkLabel(self.sidebar_frame, text="Тема UI", anchor="w",
|
|
||||||
font=ctk.CTkFont(size=12))
|
|
||||||
self.appearance_mode_label.grid(row=7, column=0, padx=10, pady=(10, 0)) # Метка для выбора темы
|
|
||||||
self.appearance_mode_optionemenu = ctk.CTkOptionMenu(
|
|
||||||
self.sidebar_frame, values=["Светлая", "Темная", "Система"], command=self.change_appearance_mode_event
|
|
||||||
) # Меню выбора темы
|
|
||||||
self.appearance_mode_optionemenu.grid(row=8, column=0, padx=10, pady=(10, 10)) # Расположение меню
|
|
||||||
|
|
||||||
self.scaling_label = ctk.CTkLabel(self.sidebar_frame, text="Масштабирование",
|
|
||||||
anchor="w", font=ctk.CTkFont(size=12)) # Метка для масштабирования
|
|
||||||
self.scaling_label.grid(row=9, column=0, padx=10, pady=(10, 0)) # Расположение метки
|
|
||||||
self.scaling_optionemenu = ctk.CTkOptionMenu(
|
|
||||||
self.sidebar_frame, values=["80%", "90%", "100%", "110%", "120%"], command=self.change_scaling_event
|
|
||||||
) # Меню выбора масштаба
|
|
||||||
self.scaling_optionemenu.grid(row=10, column=0, padx=10, pady=(10, 20)) # Расположение меню
|
|
||||||
|
|
||||||
# Создание вкладок
|
|
||||||
self.tabview = ctk.CTkTabview(self, width=250) # Виджет вкладок
|
|
||||||
self.tabview.grid(row=0, column=1, rowspan=3, columnspan=2, padx=(20, 0), pady=(20, 0),
|
|
||||||
sticky="nsew") # Растягиваем на все пустое пространство
|
|
||||||
self.tabview.add("Консоль") # Первая вкладка
|
|
||||||
self.tabview.add("База данных") # Вторая вкладка
|
|
||||||
self.tabview.add("Иное") # Третья вкладка
|
|
||||||
|
|
||||||
# Вкладка "Консоль" с текстовым полем
|
|
||||||
self.textbox_tab_1 = ctk.CTkTextbox(self.tabview.tab("Консоль"))
|
|
||||||
self.textbox_tab_1.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
|
||||||
self.textbox_tab_1.insert("0.0", "Текст в Textbox на вкладке Консоль\n\n")
|
|
||||||
|
|
||||||
# Вкладка "База данных" с текстовым полем
|
|
||||||
self.textbox_tab_2 = ctk.CTkTextbox(self.tabview.tab("База данных"))
|
|
||||||
self.textbox_tab_2.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
|
||||||
self.textbox_tab_2.insert("0.0", "Текст в Textbox на вкладке База данных\n\n")
|
|
||||||
|
|
||||||
# Вкладка "Иное" с текстовым полем
|
|
||||||
self.textbox_tab_3 = ctk.CTkTextbox(self.tabview.tab("Иное"))
|
|
||||||
self.textbox_tab_3.grid(row=0, column=0, padx=0, pady=0, sticky="nsew")
|
|
||||||
self.textbox_tab_3.insert("0.0", "Текст в Textbox на вкладке Иное\n\n")
|
|
||||||
|
|
||||||
# Растягиваем строки и столбцы вкладок
|
|
||||||
self.tabview.grid_rowconfigure(0, weight=1) # Растягиваем строку, где находится текстовое поле
|
|
||||||
self.tabview.grid_columnconfigure(0, weight=1) # Растягиваем столбец, где находится текстовое поле
|
|
||||||
|
|
||||||
# Убедитесь, что в каждой из вкладок разрешено растяжение:
|
|
||||||
self.tabview.tab("Консоль").grid_rowconfigure(0, weight=1)
|
|
||||||
self.tabview.tab("База данных").grid_rowconfigure(0, weight=1)
|
|
||||||
self.tabview.tab("Иное").grid_rowconfigure(0, weight=1)
|
|
||||||
|
|
||||||
self.tabview.tab("Консоль").grid_columnconfigure(0, weight=1)
|
|
||||||
self.tabview.tab("База данных").grid_columnconfigure(0, weight=1)
|
|
||||||
self.tabview.tab("Иное").grid_columnconfigure(0, weight=1)
|
|
||||||
|
|
||||||
# Настройка элементов
|
|
||||||
self.appearance_mode_optionemenu.set("Темная") # Режим отображения установлен на "Dark"
|
|
||||||
self.scaling_optionemenu.set("100%") # Масштаб интерфейса установлен на 100%
|
|
||||||
|
|
||||||
self.update() # Принудительное обновление окна после создания
|
|
||||||
|
|
||||||
def change_appearance_mode_event(self, new_appearance_mode: str):
|
|
||||||
# Метод для изменения режима отображения интерфейса
|
|
||||||
if new_appearance_mode == "Светлая":
|
|
||||||
ctk.set_appearance_mode("Light")
|
|
||||||
elif new_appearance_mode == "Темная":
|
|
||||||
ctk.set_appearance_mode("Dark")
|
|
||||||
elif new_appearance_mode == "Система":
|
|
||||||
ctk.set_appearance_mode("System")
|
|
||||||
|
|
||||||
def change_scaling_event(self, new_scaling: str):
|
|
||||||
# Метод для изменения масштаба интерфейса
|
|
||||||
new_scaling_float = int(new_scaling.replace("%", "")) / 100
|
|
||||||
# Преобразование процента масштаба в дробное число
|
|
||||||
ctk.set_widget_scaling(new_scaling_float)
|
|
||||||
# Применение нового масштаба ко всем виджетам
|
|
||||||
|
|
||||||
def switch_tab_console(self):
|
|
||||||
# Переключение на вкладку "Консоль"
|
|
||||||
self.tabview.grid(row=0, column=1, rowspan=3, columnspan=2, padx=(20, 0), pady=(20, 0), sticky="nsew")
|
|
||||||
self.tabview.set("Консоль")
|
|
||||||
|
|
||||||
def switch_tab_database(self):
|
|
||||||
# Переключение на вкладку "База данных"
|
|
||||||
# Для возвращения вкладок
|
|
||||||
self.tabview.grid(row=0, column=1, rowspan=3, columnspan=2, padx=(20, 0), pady=(20, 0), sticky="nsew")
|
|
||||||
self.tabview.set("База данных")
|
|
||||||
|
|
||||||
def switch_tab_other(self):
|
|
||||||
# Переключение на вкладку "Иное"
|
|
||||||
self.tabview.grid(row=0, column=1, rowspan=3, columnspan=2, padx=(20, 0), pady=(20, 0), sticky="nsew")
|
|
||||||
self.tabview.set("Иное")
|
|
||||||
|
|
||||||
def start_button_click(self):
|
|
||||||
# Обработчик для кнопки "Запуск"
|
|
||||||
print("Запуск")
|
|
||||||
|
|
||||||
def stop_button_click(self):
|
|
||||||
# Обработчик для кнопки "Выключение"
|
|
||||||
print("Выключение")
|
|
||||||
|
|
||||||
|
|
||||||
# Начало кода и запуск GUI
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = App()
|
|
||||||
app.mainloop()
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
import sys
|
|
||||||
import customtkinter as ctk
|
|
||||||
import asyncio
|
|
||||||
import threading
|
|
||||||
|
|
||||||
# Ваши настройки и модули
|
|
||||||
from BotLibrary import *
|
|
||||||
from BotCode.routers import router as main_router
|
|
||||||
from BotCode.routers import set_commands
|
|
||||||
|
|
||||||
|
|
||||||
# Класс для перенаправления стандартного вывода в текстовое поле
|
|
||||||
class Logger:
|
|
||||||
def __init__(self, text_widget):
|
|
||||||
self.text_widget = text_widget
|
|
||||||
|
|
||||||
def write(self, message):
|
|
||||||
self.text_widget.insert("end", message)
|
|
||||||
self.text_widget.see("end") # Прокрутка к последнему сообщению
|
|
||||||
|
|
||||||
def flush(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# Основная функция для запуска бота
|
|
||||||
async def main_bot():
|
|
||||||
just_fix_windows_console() # Подключение ANSI в Windows CMD
|
|
||||||
dp.include_router(main_router) # Подключение главного роутера
|
|
||||||
|
|
||||||
await set_all() # Установка настроек бота
|
|
||||||
await set_commands() # Установка команд бота
|
|
||||||
await bot_get_info() # Получение информации о боте
|
|
||||||
|
|
||||||
# Логирование в консоль и текстовое поле
|
|
||||||
logger.add(sys.stderr, colorize=True, format=logs_text, level="INFO")
|
|
||||||
logger.info(f"Начало запуска бота @{BotInfo.username}...")
|
|
||||||
|
|
||||||
bot_info_out() # Включение опроса бота
|
|
||||||
await dp.start_polling(bot) # Запуск бота
|
|
||||||
|
|
||||||
|
|
||||||
# Класс графического интерфейса
|
|
||||||
class BotConsoleWindow(ctk.CTk):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
# Настройка окна
|
|
||||||
self.title("Bot Console")
|
|
||||||
self.geometry("800x600")
|
|
||||||
|
|
||||||
# Создание текстового поля для логов
|
|
||||||
self.log_text = ctk.CTkTextbox(self, wrap="word", width=780, height=500)
|
|
||||||
self.log_text.pack(padx=10, pady=10)
|
|
||||||
|
|
||||||
# Перенаправление вывода в текстовое поле
|
|
||||||
sys.stdout = Logger(self.log_text)
|
|
||||||
sys.stderr = Logger(self.log_text)
|
|
||||||
|
|
||||||
# Кнопка запуска бота
|
|
||||||
self.start_button = ctk.CTkButton(self, text="Запустить бота", command=self.start_bot)
|
|
||||||
self.start_button.pack(pady=10)
|
|
||||||
|
|
||||||
def start_bot(self):
|
|
||||||
self.start_button.configure(state="disabled") # Отключить кнопку
|
|
||||||
threading.Thread(target=self.run_bot, daemon=True).start()
|
|
||||||
|
|
||||||
def run_bot(self):
|
|
||||||
asyncio.run(main_bot())
|
|
||||||
self.start_button.configure(state="normal") # Включить кнопку после завершения
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app = BotConsoleWindow()
|
|
||||||
app.mainloop()
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# Файл-хранилище всех секретных токенов и ключей
|
# Файл-хранилище всех секретных токенов и ключей
|
||||||
|
|
||||||
# Токены от ботов телеграмма
|
# Токены от ботов телеграмма
|
||||||
BOT_TOKEN=7162745909:AAF9023WMRMm6uZYldtUcgqB_al4VmZpH1c
|
BOT_TOKEN=6393974380:AAFM0F3opRVzCvnhfmNaaNeW5-gJKXwSicU
|
||||||
BOT1_TOKEN=7193685715:AAHFEnFreZGLQcHj8_wdWYJ2FLPrB-A-hzY
|
BOT1_TOKEN=7193685715:AAHFEnFreZGLQcHj8_wdWYJ2FLPrB-A-hzY
|
||||||
BOT2_TOKEN=8076305634:AAGNoo4N-WVP9mbeD76G7SLClSsySw23nGw
|
BOT2_TOKEN=8076305634:AAGNoo4N-WVP9mbeD76G7SLClSsySw23nGw
|
||||||
|
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ class BotEdit:
|
|||||||
Класс для хранения данных о боте: имя, описание, разрешения и настройки.
|
Класс для хранения данных о боте: имя, описание, разрешения и настройки.
|
||||||
"""
|
"""
|
||||||
# Разрешение на ведение логов
|
# Разрешение на ведение логов
|
||||||
project_name: str = "Свалка Флуд"
|
project_name: str = "PRIMO"
|
||||||
permission: bool = Permissions.bot_edit
|
permission: bool = Permissions.bot_edit
|
||||||
name: str = "Стартовый бот"
|
name: str = "Первозданная Жемчужина"
|
||||||
description: str = "Описание бота"
|
description: str = "Ваш помощник в удивительные миры! Prod. by:『@verdise』"
|
||||||
short_description: str = "Описание виджета"
|
short_description: str = "Тех.поддержка: @verdise"
|
||||||
|
|
||||||
is_anonymous: bool = False
|
is_anonymous: bool = False
|
||||||
manage_chat: bool = True
|
manage_chat: bool = True
|
||||||
@@ -61,7 +61,8 @@ class BotVar:
|
|||||||
encod: str = "utf-8"
|
encod: str = "utf-8"
|
||||||
language: str = "Python3-Aiogram"
|
language: str = "Python3-Aiogram"
|
||||||
time_format: str = "%Y-%m-%d %H:%M:%S"
|
time_format: str = "%Y-%m-%d %H:%M:%S"
|
||||||
bd_names: str = 'SQLite3/bd.db'
|
bd_names: str = 'ProjectsFiles/database/users.db'
|
||||||
|
bd_path: str = 'ProjectsFiles/database'
|
||||||
prefix: Tuple[str, ...] = ('$', '!', '.', '%', '&', ':', '|', '+', '-', '/', '~', '?')
|
prefix: Tuple[str, ...] = ('$', '!', '.', '%', '&', ':', '|', '+', '-', '/', '~', '?')
|
||||||
|
|
||||||
parse_mode: str = "HTML" # Устанавливаем формат HTML для всех сообщений
|
parse_mode: str = "HTML" # Устанавливаем формат HTML для всех сообщений
|
||||||
|
|||||||
Binary file not shown.
@@ -1,5 +0,0 @@
|
|||||||
# SQLite3/__init__.py
|
|
||||||
# Инициализация пакета SQLite3, для базы данных проекта
|
|
||||||
|
|
||||||
# Экспортирование модулей во внешние слои проекта
|
|
||||||
from .bd_func import *
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# SQLite3/bd_func/__init__.py
|
|
||||||
# Инициализация модуля bd_func, для функция с БД
|
|
||||||
|
|
||||||
from aiogram import types
|
|
||||||
from BotLibrary.validators import username
|
|
||||||
from ProjectsFiles import Permissions
|
|
||||||
|
|
||||||
from .bd_add_user import *
|
|
||||||
from .bd_get_user import *
|
|
||||||
from .bd_update_user import *
|
|
||||||
from .bd_update_user_msg import *
|
|
||||||
from .bd_user_create import *
|
|
||||||
from .status_user import *
|
|
||||||
|
|
||||||
|
|
||||||
# Основная обработка SQL
|
|
||||||
async def base_sql(message: types.Message) -> None:
|
|
||||||
tg_id = message.from_user.id
|
|
||||||
usernames = username(message)
|
|
||||||
first_name = message.from_user.first_name
|
|
||||||
last_name = message.from_user.last_name
|
|
||||||
|
|
||||||
if Permissions.sql_user:
|
|
||||||
await add_user(tg_id, usernames, first_name, last_name, role="", status="active", user="user")
|
|
||||||
await update_user(tg_id=tg_id, first_name=first_name, last_name=last_name)
|
|
||||||
await update_user_messages(message=message)
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# SQLite3/bd_func/bd_add_user.py
|
|
||||||
# Добавление пользователя в базу данных bd|user
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
|
||||||
__all__ = ("add_user",)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция добавления пользователя с последовательным user_id
|
|
||||||
async def add_user(tg_id: int, username: str, first_name: str, last_name: str,
|
|
||||||
role: str, status: str, user: str, bd_name: str = BotVar.bd_names) -> None:
|
|
||||||
with sqlite3.connect(bd_name) as db:
|
|
||||||
cursor = db.cursor()
|
|
||||||
|
|
||||||
# Проверяем, существует ли пользователь с таким tg_id
|
|
||||||
cursor.execute("SELECT user_id FROM users WHERE tg_id = ?", (tg_id,))
|
|
||||||
if cursor.fetchone():
|
|
||||||
return # Пользователь уже существует, ничего не добавляем
|
|
||||||
|
|
||||||
# Находим максимальный user_id
|
|
||||||
cursor.execute("SELECT MAX(user_id) FROM users")
|
|
||||||
max_id = cursor.fetchone()[0]
|
|
||||||
new_user_id = 1 if max_id is None else max_id + 1
|
|
||||||
|
|
||||||
# Добавляем нового пользователя
|
|
||||||
cursor.execute('''
|
|
||||||
INSERT INTO users (user_id, tg_id, username, first_name, last_name, role, status, user)
|
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
||||||
''', (new_user_id, tg_id, username, first_name, last_name, role, status, user))
|
|
||||||
|
|
||||||
# Добавляем запись в user_messages
|
|
||||||
cursor.execute('''
|
|
||||||
INSERT INTO user_messages (user_id)
|
|
||||||
VALUES (?)
|
|
||||||
''', (new_user_id,))
|
|
||||||
|
|
||||||
db.commit()
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
# SQLite3/bd_func/bd_get_user.py
|
|
||||||
# Получение информации о пользователе из базы данных bd|user
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
|
||||||
__all__ = ("get_user",)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция для получения данных о пользователе
|
|
||||||
async def get_user(tg_id: int, bd_name: str = BotVar.bd_names) -> None:
|
|
||||||
with sqlite3.connect(bd_name) as db:
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute("SELECT * FROM users WHERE tg_id = ?", (tg_id,))
|
|
||||||
return cursor.fetchone()
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
# SQLite3/bd_func/bd_update_user.py
|
|
||||||
# Обновление данных о пользователях в базу данных bd|user
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
|
||||||
__all__ = ("update_user",)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция обновления пользователя
|
|
||||||
async def update_user(tg_id: int, username: str = None, first_name: str = None, last_name: str = None,
|
|
||||||
bd_name: str = BotVar.bd_names, role: str = None, user: str = None) -> None:
|
|
||||||
updates = []
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if username:
|
|
||||||
updates.append("username = ?")
|
|
||||||
params.append(username)
|
|
||||||
if first_name:
|
|
||||||
updates.append("first_name = ?")
|
|
||||||
params.append(first_name)
|
|
||||||
if last_name:
|
|
||||||
updates.append("last_name = ?")
|
|
||||||
params.append(last_name)
|
|
||||||
if role:
|
|
||||||
updates.append("role = ?")
|
|
||||||
params.append(role)
|
|
||||||
if user:
|
|
||||||
updates.append("user = ?")
|
|
||||||
params.append(user)
|
|
||||||
|
|
||||||
if updates:
|
|
||||||
query = f"UPDATE users SET {', '.join(updates)} WHERE tg_id = ?"
|
|
||||||
params.append(tg_id)
|
|
||||||
with sqlite3.connect(bd_name) as db:
|
|
||||||
cursor = db.cursor()
|
|
||||||
cursor.execute(query, params)
|
|
||||||
db.commit()
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
# SQLite3/bd_func/bd_update_user_msg.py
|
|
||||||
# Обновление данных о сообщениях пользователя в базу данных bd|message
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from aiogram import types
|
|
||||||
from datetime import timezone, datetime, timedelta
|
|
||||||
|
|
||||||
from BotLibrary import type_msg
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
|
||||||
__all__ = ("update_user_messages",)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция обновления статистики сообщений пользователя
|
|
||||||
async def update_user_messages(message: types.Message, bd_name: str = BotVar.bd_names) -> None:
|
|
||||||
with sqlite3.connect(bd_name) as db:
|
|
||||||
cursor = db.cursor()
|
|
||||||
user_id = message.from_user.id # Используем user_id напрямую
|
|
||||||
|
|
||||||
# Проверяем, существует ли запись в user_messages
|
|
||||||
cursor.execute(
|
|
||||||
"SELECT last_message_time, messages_per_day, messages_per_week, messages_per_month, total_messages FROM user_messages WHERE user_id = ?",
|
|
||||||
(user_id,))
|
|
||||||
result = cursor.fetchone()
|
|
||||||
|
|
||||||
# Время сообщения в московском времени
|
|
||||||
now = message.date.astimezone(timezone(timedelta(hours=3)))
|
|
||||||
today = now.date()
|
|
||||||
start_of_week = today - timedelta(days=today.weekday()) # Понедельник текущей недели
|
|
||||||
current_month = now.month
|
|
||||||
current_year = now.year
|
|
||||||
|
|
||||||
last_message = message.text or type_msg(message)
|
|
||||||
last_message_id = message.message_id
|
|
||||||
|
|
||||||
if result:
|
|
||||||
last_message_time, messages_per_day, messages_per_week, messages_per_month, total_messages = result
|
|
||||||
if last_message_time:
|
|
||||||
last_message_time = datetime.fromisoformat(last_message_time).astimezone(timezone(timedelta(hours=3)))
|
|
||||||
last_date = last_message_time.date()
|
|
||||||
last_week = last_date - timedelta(days=last_date.weekday())
|
|
||||||
last_month = last_message_time.month
|
|
||||||
last_year = last_message_time.year
|
|
||||||
|
|
||||||
# Обнуляем счетчики, если наступил новый день, неделя или месяц
|
|
||||||
if last_date != today:
|
|
||||||
messages_per_day = 0
|
|
||||||
if last_week != start_of_week:
|
|
||||||
messages_per_week = 0
|
|
||||||
if last_month != current_month or last_year != current_year:
|
|
||||||
messages_per_month = 0
|
|
||||||
else:
|
|
||||||
messages_per_day, messages_per_week, messages_per_month = 0, 0, 0
|
|
||||||
|
|
||||||
# Увеличиваем счетчики
|
|
||||||
messages_per_day += 1
|
|
||||||
messages_per_week += 1
|
|
||||||
messages_per_month += 1
|
|
||||||
total_messages += 1
|
|
||||||
else:
|
|
||||||
# Если записи нет, создаем новую
|
|
||||||
messages_per_day, messages_per_week, messages_per_month, total_messages = 1, 1, 1, 1
|
|
||||||
cursor.execute('INSERT INTO user_messages (user_id, last_message, last_message_id, last_message_time, messages_per_day, messages_per_week, messages_per_month, total_messages) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
|
|
||||||
(user_id, last_message, last_message_id, now.isoformat(), messages_per_day, messages_per_week, messages_per_month, total_messages))
|
|
||||||
db.commit()
|
|
||||||
return
|
|
||||||
|
|
||||||
# Обновляем существующую запись
|
|
||||||
cursor.execute('''
|
|
||||||
UPDATE user_messages
|
|
||||||
SET last_message = ?, last_message_id = ?, last_message_time = ?,
|
|
||||||
messages_per_day = ?, messages_per_week = ?, messages_per_month = ?,
|
|
||||||
total_messages = ?
|
|
||||||
WHERE user_id = ?
|
|
||||||
''', (last_message, last_message_id, now.isoformat(), messages_per_day,
|
|
||||||
messages_per_week, messages_per_month, total_messages, user_id))
|
|
||||||
db.commit()
|
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
# SQLite3/bd_func/bd_user_create.py
|
|
||||||
# Создание базы данных
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Настройка экспорта в модули
|
|
||||||
__all__ = ("create_user_db",)
|
|
||||||
|
|
||||||
|
|
||||||
# Функция создания базы данных
|
|
||||||
async def create_user_db(bd_name: str = BotVar.bd_names) -> None:
|
|
||||||
with sqlite3.connect(bd_name) as db:
|
|
||||||
cursor = db.cursor()
|
|
||||||
|
|
||||||
# Таблица пользователей
|
|
||||||
cursor.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
|
||||||
user_id INTEGER PRIMARY KEY,
|
|
||||||
tg_id INTEGER NOT NULL UNIQUE,
|
|
||||||
username TEXT,
|
|
||||||
first_name TEXT,
|
|
||||||
last_name TEXT,
|
|
||||||
role TEXT DEFAULT NULL,
|
|
||||||
status TEXT DEFAULT 'active',
|
|
||||||
user TEXT DEFAULT 'user'
|
|
||||||
);''')
|
|
||||||
|
|
||||||
# Таблица сообщений пользователей
|
|
||||||
cursor.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS user_messages (
|
|
||||||
user_id INTEGER PRIMARY KEY, -- Уникальный ключ
|
|
||||||
last_message TEXT,
|
|
||||||
last_message_id INTEGER,
|
|
||||||
last_message_time TEXT,
|
|
||||||
messages_per_day INTEGER DEFAULT 0,
|
|
||||||
messages_per_week INTEGER DEFAULT 0,
|
|
||||||
messages_per_month INTEGER DEFAULT 0,
|
|
||||||
total_messages INTEGER DEFAULT 0,
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE CASCADE
|
|
||||||
);''')
|
|
||||||
|
|
||||||
# Таблица персонажей
|
|
||||||
cursor.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS characters (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
region TEXT NOT NULL,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
status TEXT DEFAULT 'Свободно',
|
|
||||||
user_id INTEGER DEFAULT NULL,
|
|
||||||
comment TEXT DEFAULT '',
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE SET NULL
|
|
||||||
);''')
|
|
||||||
|
|
||||||
# Таблица персонажей Хонкай
|
|
||||||
cursor.execute('''
|
|
||||||
CREATE TABLE IF NOT EXISTS characters_hsr (
|
|
||||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
||||||
region TEXT NOT NULL,
|
|
||||||
name TEXT NOT NULL,
|
|
||||||
status TEXT DEFAULT 'Свободно',
|
|
||||||
user_id INTEGER DEFAULT NULL,
|
|
||||||
comment TEXT DEFAULT '',
|
|
||||||
FOREIGN KEY (user_id) REFERENCES users (user_id) ON DELETE SET NULL
|
|
||||||
);''')
|
|
||||||
|
|
||||||
characters_genshin = [
|
|
||||||
# Мондштадт
|
|
||||||
("Мондштадт", "Венти", "Свободно", ""),
|
|
||||||
("Мондштадт", "Кэйа", "Свободно", ""),
|
|
||||||
("Мондштадт", "Альбедо", "Свободно", ""),
|
|
||||||
("Мондштадт", "Дилюк", "Свободно", ""),
|
|
||||||
("Мондштадт", "Мика", "Свободно", ""),
|
|
||||||
("Мондштадт", "Беннет", "Свободно", ""),
|
|
||||||
("Мондштадт", "Рэйзор", "Свободно", ""),
|
|
||||||
("Мондштадт", "Эола", "Свободно", ""),
|
|
||||||
("Мондштадт", "Мона", "Свободно", ""),
|
|
||||||
("Мондштадт", "Джинн", "Свободно", ""),
|
|
||||||
("Мондштадт", "Диона", "Свободно", ""),
|
|
||||||
("Мондштадт", "Лиза", "Свободно", ""),
|
|
||||||
("Мондштадт", "Ноэлль", "Свободно", ""),
|
|
||||||
("Мондштадт", "Сахароза", "Свободно", ""),
|
|
||||||
("Мондштадт", "Розария", "Свободно", ""),
|
|
||||||
("Мондштадт", "Эмбер", "Свободно", ""),
|
|
||||||
("Мондштадт", "Фишль", "Свободно", ""),
|
|
||||||
("Мондштадт", "Барбара", "Свободно", ""),
|
|
||||||
|
|
||||||
# Ли Юэ
|
|
||||||
("Ли Юэ", "Чжун Ли", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Сяо", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Син Цю", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Чун Юнь", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Бай Чжу", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Е Лань", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Шень Хэ", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Гань Юй", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Ци Ци", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Кэ Цин", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Янь Фэй", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Нин Гуан", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Бэй Доу", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Яо Яо", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Ка Мин", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Сянь Юнь", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Юнь Цзинь", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Ху Тао", "Свободно", ""),
|
|
||||||
("Ли Юэ", "Лань Янь", "Свободно", ""),
|
|
||||||
|
|
||||||
# Инадзума
|
|
||||||
("Инадзума", "Итто", "Свободно", ""),
|
|
||||||
("Инадзума", "Горо", "Свободно", ""),
|
|
||||||
("Инадзума", "Аято", "Свободно", ""),
|
|
||||||
("Инадзума", "Хэйдзо", "Свободно", ""),
|
|
||||||
("Инадзума", "Тома", "Свободно", ""),
|
|
||||||
("Инадзума", "Кадзуха", "Свободно", ""),
|
|
||||||
("Инадзума", "Кирара", "Свободно", ""),
|
|
||||||
("Инадзума", "Кудзё Сара", "Свободно", ""),
|
|
||||||
("Инадзума", "Ёимия", "Свободно", ""),
|
|
||||||
("Инадзума", "Аяка", "Свободно", ""),
|
|
||||||
("Инадзума", "Сангономия Кокоми", "Свободно", ""),
|
|
||||||
("Инадзума", "Яэ Мико", "Свободно", ""),
|
|
||||||
("Инадзума", "Райдэн Эи", "Свободно", ""),
|
|
||||||
("Инадзума", "Саю", "Свободно", ""),
|
|
||||||
("Инадзума", "Куки Синобу", "Свободно", ""),
|
|
||||||
("Инадзума", "Мидзуки", "Свободно", ""),
|
|
||||||
|
|
||||||
# Сумеру
|
|
||||||
("Сумеру", "Аль-Хайтам", "Свободно", ""),
|
|
||||||
("Сумеру", "Кавех", "Свободно", ""),
|
|
||||||
("Сумеру", "Сайно", "Свободно", ""),
|
|
||||||
("Сумеру", "Тигнари", "Свободно", ""),
|
|
||||||
("Сумеру", "Сетос", "Свободно", ""),
|
|
||||||
("Сумеру", "Нилу", "Свободно", ""),
|
|
||||||
("Сумеру", "Нахида", "Свободно", ""),
|
|
||||||
("Сумеру", "Лайла", "Свободно", ""),
|
|
||||||
("Сумеру", "Кандакия", "Свободно", ""),
|
|
||||||
("Сумеру", "Дори", "Свободно", ""),
|
|
||||||
("Сумеру", "Дэхья", "Свободно", ""),
|
|
||||||
("Сумеру", "Коллеи", "Свободно", ""),
|
|
||||||
("Сумеру", "Фарузан", "Свободно", ""),
|
|
||||||
|
|
||||||
# Фонтейн
|
|
||||||
("Фонтейн", "Лини", "Свободно", ""),
|
|
||||||
("Фонтейн", "Ризли", "Свободно", ""),
|
|
||||||
("Фонтейн", "Невиллет", "Свободно", ""),
|
|
||||||
("Фонтейн", "Фремине", "Свободно", ""),
|
|
||||||
("Фонтейн", "Линетт", "Свободно", ""),
|
|
||||||
("Фонтейн", "Эмилия", "Свободно", ""),
|
|
||||||
("Фонтейн", "Клоринда", "Свободно", ""),
|
|
||||||
("Фонтейн", "Навия", "Свободно", ""),
|
|
||||||
("Фонтейн", "Шарлотта", "Свободно", ""),
|
|
||||||
("Фонтейн", "Фурина", "Свободно", ""),
|
|
||||||
("Фонтейн", "Тиори", "Свободно", ""),
|
|
||||||
("Фонтейн", "Сиджвин", "Свободно", ""),
|
|
||||||
|
|
||||||
# Натлан
|
|
||||||
("Натлан", "Кинич", "Свободно", ""),
|
|
||||||
("Натлан", "Оророн", "Свободно", ""),
|
|
||||||
("Натлан", "Муалани", "Свободно", ""),
|
|
||||||
("Натлан", "Ситлали", "Свободно", ""),
|
|
||||||
("Натлан", "Шилонен", "Свободно", ""),
|
|
||||||
("Натлан", "Иансан", "Свободно", ""),
|
|
||||||
("Натлан", "Мавуика", "Свободно", ""),
|
|
||||||
("Натлан", "Часка", "Свободно", ""),
|
|
||||||
|
|
||||||
# Фатуи
|
|
||||||
("Фатуи", "Тарталья", "Свободно", ""),
|
|
||||||
("Фатуи", "Панталоне", "Свободно", ""),
|
|
||||||
("Фатуи", "Дотторе", "Свободно", ""),
|
|
||||||
("Фатуи", "Капитано", "Свободно", ""),
|
|
||||||
("Фатуи", "Пьеро", "Свободно", ""),
|
|
||||||
("Фатуи", "Пульничелла", "Свободно", ""),
|
|
||||||
("Фатуи", "Синьора", "Свободно", ""),
|
|
||||||
("Фатуи", "Арлекино", "Свободно", ""),
|
|
||||||
("Фатуи", "Коломбина", "Свободно", ""),
|
|
||||||
("Фатуи", "Царица", "Свободно", ""),
|
|
||||||
("Фатуи", "Странник", "Свободно", ""),
|
|
||||||
|
|
||||||
# Иные персонажи
|
|
||||||
("Иные персонажи", "Итэр", "Свободно", ""),
|
|
||||||
("Иные персонажи", "Люмин", "Свободно", ""),
|
|
||||||
("Иные персонажи", "Элой", "Свободно", ""),
|
|
||||||
("Иные персонажи", "Паймон", "Свободно", ""),
|
|
||||||
("Иные персонажи", "Дайнслейф", "Свободно", ""),
|
|
||||||
]
|
|
||||||
|
|
||||||
characters_hsr = [
|
|
||||||
# Ярило-6
|
|
||||||
("Ярило-6", "Броня", "Свободно", ""),
|
|
||||||
("Ярило-6", "Гепард", "Свободно", ""),
|
|
||||||
("Ярило-6", "Зеле", "Свободно", ""),
|
|
||||||
("Ярило-6", "Клара", "Свободно", ""),
|
|
||||||
("Ярило-6", "Лука", "Свободно", ""),
|
|
||||||
("Ярило-6", "Наташа", "Свободно", ""),
|
|
||||||
("Ярило-6", "Пела", "Свободно", ""),
|
|
||||||
("Ярило-6", "Рысь", "Свободно", ""),
|
|
||||||
("Ярило-6", "Сампо", "Свободно", ""),
|
|
||||||
("Ярило-6", "Сервал", "Свободно", ""),
|
|
||||||
("Ярило-6", "Хук", "Свободно", ""),
|
|
||||||
|
|
||||||
# Станция «Герта»
|
|
||||||
("Станция «Герта»", "Арлан", "Свободно", ""),
|
|
||||||
("Станция «Герта»", "Аста", "Свободно", ""),
|
|
||||||
("Станция «Герта»", "Великая Герта", "Свободно", ""),
|
|
||||||
("Станция «Герта»", "Кукла «Герта»", "Свободно", ""),
|
|
||||||
("Станция «Герта»", "Жуань Мэй", "Свободно", ""),
|
|
||||||
|
|
||||||
# Пенакония
|
|
||||||
("Пенакония", "Авантюрин", "Свободно", ""),
|
|
||||||
("Пенакония", "Ахерон", "Свободно", ""),
|
|
||||||
("Пенакония", "Галлахер", "Свободно", ""),
|
|
||||||
("Пенакония", "Зарянка", "Свободно", ""),
|
|
||||||
("Пенакония", "Миша", "Свободно", ""),
|
|
||||||
("Пенакония", "Мистер Река", "Свободно", ""),
|
|
||||||
("Пенакония", "Раппа", "Свободно", ""),
|
|
||||||
("Пенакония", "Чёрный Лебедь", "Свободно", ""),
|
|
||||||
("Пенакония", "Яшма", "Свободно", ""),
|
|
||||||
("Пенакония", "Воскресенье", "Свободно", ""),
|
|
||||||
|
|
||||||
# Звёздный Экспресс
|
|
||||||
("Звёздный Экспресс", "Вельт", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Келус", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Стелла", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Дань Хэн", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Март 7", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Химеко", "Свободно", ""),
|
|
||||||
("Звёздный Экспресс", "Пом Пом", "Свободно", ""),
|
|
||||||
|
|
||||||
# Галактика
|
|
||||||
("Галактика", "Аргенти", "Свободно", ""),
|
|
||||||
("Галактика", "Блэйд", "Свободно", ""),
|
|
||||||
("Галактика", "Бутхилл", "Свободно", ""),
|
|
||||||
("Галактика", "Доктор Рацио", "Свободно", ""),
|
|
||||||
("Галактика", "Кафка", "Свободно", ""),
|
|
||||||
("Галактика", "Светлячок", "Свободно", ""),
|
|
||||||
("Галактика", "Искорка", "Свободно", ""),
|
|
||||||
("Галактика", "Серебряный Волк", "Свободно", ""),
|
|
||||||
("Галактика", "Топаз", "Свободно", ""),
|
|
||||||
|
|
||||||
# Амфореус
|
|
||||||
("Амфореус", "Аглая", "Свободно", ""),
|
|
||||||
("Амфореус", "Мидей", "Свободно", ""),
|
|
||||||
("Амфореус", "Трибби", "Свободно", ""),
|
|
||||||
|
|
||||||
# Альянс Сяньчжоу
|
|
||||||
("Альянс Сяньчжоу", "Байлу", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Гуйнайфей", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Линша", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Лоча", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Моцзэ", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Пожиратель Луны", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Сушан", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Сюзи", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Фуга", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Фэйсяо", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Ханья", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Хохо", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Цзин Юань", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Цзиннлю", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Цзяоцю", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Цинцюэ", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Юйкун", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Юньли", "Свободно", ""),
|
|
||||||
("Альянс Сяньчжоу", "Яньцин", "Свободно", ""),
|
|
||||||
]
|
|
||||||
|
|
||||||
# Проверяем, пуста ли таблица characters
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM characters;")
|
|
||||||
if cursor.fetchone()[0] == 0:
|
|
||||||
cursor.executemany('''
|
|
||||||
INSERT INTO characters (region, name, status, comment)
|
|
||||||
VALUES (?, ?, ?, ?);
|
|
||||||
''', characters_genshin)
|
|
||||||
|
|
||||||
# Проверяем, пуста ли таблица characters_hsr
|
|
||||||
cursor.execute("SELECT COUNT(*) FROM characters_hsr;")
|
|
||||||
if cursor.fetchone()[0] == 0:
|
|
||||||
cursor.executemany('''
|
|
||||||
INSERT INTO characters_hsr (region, name, status, comment)
|
|
||||||
VALUES (?, ?, ?, ?);
|
|
||||||
''', characters_hsr)
|
|
||||||
|
|
||||||
db.commit()
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
# SQLite3/bd_func/status_user.py
|
|
||||||
# Проверка статусов пользователя с БД
|
|
||||||
|
|
||||||
import sqlite3
|
|
||||||
from aiogram import types
|
|
||||||
from ProjectsFiles import BotVar
|
|
||||||
|
|
||||||
# Функция проверки статуса пользователя
|
|
||||||
async def status_user(message: types.Message, bd_path: str = BotVar.bd_names) -> str:
|
|
||||||
# Подключение к базе данных
|
|
||||||
bd = sqlite3.connect(bd_path)
|
|
||||||
tg_id = message.from_user.id
|
|
||||||
cursor = bd.cursor()
|
|
||||||
|
|
||||||
# Запрос к базе данных для получения значения из столбца 'user' для конкретного tg_id
|
|
||||||
cursor.execute("SELECT user FROM users WHERE tg_id = ?", (tg_id,))
|
|
||||||
|
|
||||||
# Получаем результат
|
|
||||||
row = cursor.fetchone()
|
|
||||||
|
|
||||||
# Словарь для сопоставления статусов
|
|
||||||
status_map = {
|
|
||||||
"ban": "Забаннен",
|
|
||||||
"user": "Пользователь",
|
|
||||||
"moderator": "Модератор",
|
|
||||||
"admin": "Администратор",
|
|
||||||
"so-owner": "Совладелец",
|
|
||||||
"owner": "Владелец",
|
|
||||||
}
|
|
||||||
|
|
||||||
if row:
|
|
||||||
user_type = row[0] # предполагаем, что в столбце 'user' находится только одно значение
|
|
||||||
status: str = status_map.get(user_type, "Ошибка!") # Получаем статус или "Ошибка!"
|
|
||||||
else:
|
|
||||||
status: str = "Пользователь не найден"
|
|
||||||
|
|
||||||
# Закрываем соединение с базой данных
|
|
||||||
bd.close()
|
|
||||||
|
|
||||||
# Выводим статус
|
|
||||||
return status
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# SQLite3/bd_func/username_to_id.py
|
|
||||||
#
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
{
|
|
||||||
"ban_list_ids": {
|
|
||||||
"6666666666666": "Забанненый"
|
|
||||||
},
|
|
||||||
"important_adm_ids": {
|
|
||||||
"6751720805": "Лейн",
|
|
||||||
"7051557370": "Рикси",
|
|
||||||
"1570652377": "Риша",
|
|
||||||
"1398573474": "Финаки",
|
|
||||||
"1851081467": "Финик",
|
|
||||||
"929782381": "Хиде",
|
|
||||||
"6714237814": "Слешик",
|
|
||||||
"1686743480": "Полина",
|
|
||||||
"1184519857": "Катаз"
|
|
||||||
},
|
|
||||||
"important_groups_ids": {
|
|
||||||
"1087968824": "GroupAnonymousBot",
|
|
||||||
"-1002442589033": "Любовники Сергея",
|
|
||||||
"-1002124483077": "Труба_Сквад",
|
|
||||||
"-1002123850090": "Тест_Чат",
|
|
||||||
"-1001552311087": "Все_Будет_Хорошо"
|
|
||||||
},
|
|
||||||
"important_users_list_ids": {
|
|
||||||
"7145369362": "Артур",
|
|
||||||
"1219440132": "Данил",
|
|
||||||
"1443833264": "Виктор",
|
|
||||||
"5424384921": "Олег",
|
|
||||||
"556943853": "Ваня",
|
|
||||||
"1295708467": "Степан"
|
|
||||||
},
|
|
||||||
"important_channel_ids": {
|
|
||||||
"10000000000000": "Канал1",
|
|
||||||
"20000000000000": "Канал2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
# BotCode/routers/commands/admin_cmd/ban_cmd.py
|
|
||||||
# Работа с админ-командой /ban, для блокировки пользователей (в разработке)
|
|
||||||
# Проверка на наличие блокировки пользователя в боте
|
|
||||||
|
|
||||||
|
|
||||||
from aiogram import Router, types
|
|
||||||
from aiogram.filters import Command
|
|
||||||
from BotLibrary import *
|
|
||||||
|
|
||||||
# Создание роутера и настройка экспорта
|
|
||||||
__all__ = ("router", "banned_user", "ban_user_by_username",)
|
|
||||||
router = Router(name="ban_router")
|
|
||||||
command_text = "BAN"
|
|
||||||
|
|
||||||
|
|
||||||
# Функция проверки блокировки пользователя в боте
|
|
||||||
@router.message(lambda message: message.from_user.id in ListId.ban_list_id)
|
|
||||||
async def banned_user(message: types_msg.Message):
|
|
||||||
try:
|
|
||||||
# Вывод сообщения пользователю
|
|
||||||
chat_id = await find_chat_id(message)
|
|
||||||
text = (f"{TextDecorator.RED}Получено сообщение от забанненго пользователя"
|
|
||||||
f" из ({chat_id}) : {message.text}{TextDecorator.RESET_DECORATOR}")
|
|
||||||
await message.answer(f"Вы были забаннены в боте @{BotInfo.username}!")
|
|
||||||
|
|
||||||
# Активация логгера
|
|
||||||
await cmd_logginger(message, command_text, text)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
# Проверка на ошибку и ее логирование
|
|
||||||
except Exception as e:
|
|
||||||
text_error = await error_cmd_logginger(message, command_text, e)
|
|
||||||
return text_error
|
|
||||||
|
|
||||||
|
|
||||||
# Обработчик команды /ban
|
|
||||||
@router.message(Command("ban", "ифт", "бан", ",fy", prefix=BotEdit.prefixs, ignore_case=True))
|
|
||||||
async def ban_user_by_username(message: types_msg.Message):
|
|
||||||
try:
|
|
||||||
text = f"использовал(а) команду /{command_text.lower()}"
|
|
||||||
|
|
||||||
# Получаем аргументы команды
|
|
||||||
args = message.get_args() # Вернет все, что идет после /ban
|
|
||||||
|
|
||||||
# Проверка на наличие аргумента
|
|
||||||
if not args:
|
|
||||||
text = f"Пожалуйста, укажите ID или имя пользователя для бана. Пример: /ban 123456"
|
|
||||||
await message.reply(text)
|
|
||||||
return text
|
|
||||||
|
|
||||||
# Вывод сообщения пользователю
|
|
||||||
await message.reply(text=f"Вы попытались забанить, обидно да?")
|
|
||||||
|
|
||||||
# Активация логгера
|
|
||||||
await cmd_logginger(message, command_text, text)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
# Проверка на ошибку и ее логирование
|
|
||||||
except Exception as e:
|
|
||||||
text_error = await error_cmd_logginger(message, command_text, e)
|
|
||||||
return text_error
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
# BotLibrary/analitics/find_username.py
|
|
||||||
# Нахождение юзернейма пользователя по id (в разработке)
|
|
||||||
|
|
||||||
from loguru import logger
|
|
||||||
from BotLibrary.library.bots import bot
|
|
||||||
|
|
||||||
# Настройка экспорта
|
|
||||||
__all__ = ("get_user_id_by_username",)
|
|
||||||
type_messages = "ID_USERNAME"
|
|
||||||
|
|
||||||
|
|
||||||
# Получение ID пользователя по юзернейму (в разработке)
|
|
||||||
async def get_user_id_by_username(chat_id, username):
|
|
||||||
try:
|
|
||||||
user = await bot.get_chat_member_by_username(chat_id, username)
|
|
||||||
if user:
|
|
||||||
return user.user.id
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Проверка на ошибку и ее логирование (в разработке)
|
|
||||||
except Exception as e:
|
|
||||||
text_error = f"Ошибка при получении ID пользователя: {e}"
|
|
||||||
logger.bind(custom_variable="IDS", user_var=type_messages).error(text_error)
|
|
||||||
return text_error
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
# BotCode/routers/old_files/__init__.py
|
|
||||||
# Инициализация старого пакета old_files, для хранения старых функций
|
|
||||||
|
|
||||||
from aiogram import Router
|
|
||||||
from .media_func import router as media_old_router
|
|
||||||
from .regular_handlers import router as regular_router
|
|
||||||
|
|
||||||
|
|
||||||
# Объявление роутера и настройка экспорта
|
|
||||||
__all__ = ("router",)
|
|
||||||
router = Router(name="old_files_router")
|
|
||||||
|
|
||||||
|
|
||||||
# Список подключаемых роутеров сверху-вниз
|
|
||||||
router.include_routers(
|
|
||||||
regular_router,
|
|
||||||
media_old_router,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Список подключаемых роутеров сверху-вниз
|
|
||||||
router.include_routers()
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
# BotCode/routers/old_files/media_func.py
|
|
||||||
# Некоторые функции для работы с медиа-сообщениями
|
|
||||||
|
|
||||||
from re import Match
|
|
||||||
from aiogram import Router, F, types
|
|
||||||
from magic_filter import RegexpMode
|
|
||||||
from BotLibrary import *
|
|
||||||
|
|
||||||
# Настройка экспорта модулей и роутера
|
|
||||||
__all__ = ("router",)
|
|
||||||
router = Router(name="media_func")
|
|
||||||
|
|
||||||
|
|
||||||
# @router.message(F.photo, ~F.caption)
|
|
||||||
async def handle_photo_wo_caption(message: types_msg.Message):
|
|
||||||
caption = f"Простите, я не могу это увидеть. Вы можете описать что это?"
|
|
||||||
await message.reply_photo(
|
|
||||||
photo=message.photo[-1].file_id,
|
|
||||||
caption=caption,
|
|
||||||
)
|
|
||||||
return caption
|
|
||||||
|
|
||||||
|
|
||||||
# @router.message(F.photo, F.caption.contains("please"))
|
|
||||||
async def handle_photo_with_please_caption(message: types_msg.Message):
|
|
||||||
text = f"Простите, я не могу это увидеть."
|
|
||||||
await message.reply(text)
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
# @router.message(any_media_filter, ~F.caption)
|
|
||||||
async def handle_any_media_wo_caption(message: types_msg.Message):
|
|
||||||
if message.document:
|
|
||||||
await message.reply_document(
|
|
||||||
document=message.document.file_id,
|
|
||||||
)
|
|
||||||
return f"Перессылка документа"
|
|
||||||
|
|
||||||
elif message.video:
|
|
||||||
await message.reply_video(
|
|
||||||
video=message.video.file_id,
|
|
||||||
)
|
|
||||||
return f"Перессылка видео"
|
|
||||||
|
|
||||||
else:
|
|
||||||
text = f"Я не могу это увидеть."
|
|
||||||
await message.reply(text)
|
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
# @router.message(any_media_filter, F.caption)
|
|
||||||
async def handle_any_media_w_caption(message: types_msg.Message):
|
|
||||||
text = f"Что-то на медиа. Твой текст: {message.caption!r}"
|
|
||||||
await message.reply(text)
|
|
||||||
return text
|
|
||||||
32
main.py
32
main.py
@@ -1,21 +1,39 @@
|
|||||||
# main.py
|
# main.py
|
||||||
# Основной код проекта, который и соединяет в себе все его возможности
|
# Основной код проекта, который и соединяет в себе все его возможности
|
||||||
|
|
||||||
import asyncio
|
|
||||||
from BotLibrary import *
|
from BotLibrary import *
|
||||||
from BotCode import router as main_router
|
from ProjectsFiles import Permissions
|
||||||
|
from BotCode import router as main_routers
|
||||||
|
|
||||||
# Запуск основного кода
|
# Запуск основного кода
|
||||||
async def main():
|
async def main() -> None:
|
||||||
# Функция установки
|
# Запуск логеров
|
||||||
await setup()
|
Logs.setup()
|
||||||
|
|
||||||
|
# Получение информации о боте
|
||||||
|
await BotInfo.info()
|
||||||
|
|
||||||
|
# Вывод сообщение о запуске
|
||||||
|
Logs.start(text=f"Начало запуска бота @{BotInfo.username}...")
|
||||||
|
|
||||||
|
# Создание пустых директорий
|
||||||
|
await Directory.setup()
|
||||||
|
|
||||||
|
# Нужно ли удалить веб-хук
|
||||||
|
if Permissions.delete_webhook:
|
||||||
|
await bot.delete_webhook()
|
||||||
|
|
||||||
|
# Установка необходимых прав
|
||||||
|
await BotRights.all(bot)
|
||||||
|
Logs.console()
|
||||||
|
|
||||||
# Подключение главного маршрутизатора
|
# Подключение главного маршрутизатора
|
||||||
dp.include_router(main_router)
|
dp.include_router(main_routers)
|
||||||
|
|
||||||
# Включение опроса бота
|
# Включение опроса бота
|
||||||
await dp.start_polling(bot)
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
# Вечная загрузка бота
|
# Вечная загрузка бота
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
asyncio.run(main())
|
from asyncio import run
|
||||||
|
run(main())
|
||||||
|
|||||||
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
Reference in New Issue
Block a user