From f48d439a7b94632c261b649c93a5883fe48d134a Mon Sep 17 00:00:00 2001 From: Verum Date: Mon, 24 Feb 2025 01:21:26 +0700 Subject: [PATCH] =?UTF-8?q?0.6.1=20=D0=9E=D1=84=D0=B8=D1=86=D0=B8=D0=B0?= =?UTF-8?q?=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D1=88=D0=B0=D0=B1=D0=BB=D0=BE?= =?UTF-8?q?=D0=BD,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B9=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B7=D0=B2=D0=BE=D0=BB=D1=8F=D0=B5=D1=82=20=D1=83=D0=BF?= =?UTF-8?q?=D1=80=D0=B0=D0=B2=D0=BB=D1=8F=D1=82=D1=8C=20=D0=B2=D1=81=D0=B5?= =?UTF-8?q?=D0=BC,=20=D1=87=D1=82=D0=BE=20=D0=BD=D0=B5=D0=BE=D0=B1=D1=85?= =?UTF-8?q?=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + .idea/PRIMOWORLD.iml | 1 + .../commands/cmd_class/user_cmd_class.py | 4 +- BotLibrary/loggers/custom_loggers.py | 8 +- Documentation/FIX_LIST.md | 51 ++++++ Documentation/README.md | 74 ++++++++ SQLite3/list_ids.json | 35 ++++ Test/GUI/__init__.py | 4 + Test/GUI/console.py | 167 ++++++++++++++++++ Test/GUI/console_0.py | 74 ++++++++ Test/__init__.py | 12 ++ .../ReadMe.md => Test/commands/__init__.py | 0 Test/commands/ban_cmd.py | 63 +++++++ Test/commands/download_channel_avatar.py | 63 +++++++ Test/commands/find_username.py | 25 +++ Test/commands/send_to_user.py | 65 +++++++ Test/old_files/__init__.py | 22 +++ Test/old_files/media_func.py | 55 ++++++ Test/old_files/regular_handlers.py | 29 +++ 19 files changed, 749 insertions(+), 6 deletions(-) create mode 100644 Documentation/FIX_LIST.md create mode 100644 Documentation/README.md create mode 100644 SQLite3/list_ids.json create mode 100644 Test/GUI/__init__.py create mode 100644 Test/GUI/console.py create mode 100644 Test/GUI/console_0.py create mode 100644 Test/__init__.py rename Documentation/ReadMe.md => Test/commands/__init__.py (100%) create mode 100644 Test/commands/ban_cmd.py create mode 100644 Test/commands/download_channel_avatar.py create mode 100644 Test/commands/find_username.py create mode 100644 Test/commands/send_to_user.py create mode 100644 Test/old_files/__init__.py create mode 100644 Test/old_files/media_func.py create mode 100644 Test/old_files/regular_handlers.py diff --git a/.gitignore b/.gitignore index 98e7c69..64038af 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,6 @@ BotFiles/ # Игнорирование базы данных пользователя MySQL/user_data.db MySQL/user_data.json + +# Файл подсчета строк +project_count_line.py diff --git a/.idea/PRIMOWORLD.iml b/.idea/PRIMOWORLD.iml index 66cc0a4..bd5aef4 100644 --- a/.idea/PRIMOWORLD.iml +++ b/.idea/PRIMOWORLD.iml @@ -13,6 +13,7 @@ + diff --git a/BotCode/routers/commands/cmd_class/user_cmd_class.py b/BotCode/routers/commands/cmd_class/user_cmd_class.py index eecbbd1..70efdd9 100644 --- a/BotCode/routers/commands/cmd_class/user_cmd_class.py +++ b/BotCode/routers/commands/cmd_class/user_cmd_class.py @@ -43,7 +43,7 @@ class CommandHandler: async def handler(self, message: types.Message): """Основной хэндлер команды.""" try: - Logs.info(log_type=self.name.capitalize(), text=f"использовал(а) команду /{self.name}") + Logs.info(log_type=self.name.capitalize(), user=username(message), text=f"использовал(а) команду /{self.name}") await message.reply( text=self.text_msg, reply_markup=self.keyboard() if self.keyboard else None, @@ -51,4 +51,4 @@ class CommandHandler: # Проверка на ошибку except Exception as e: - Logs.error(log_type=self.name.capitalize(), user=message.from_user.username, text=f"Ошибка команды: {e}") + Logs.error(log_type=self.name.capitalize(), user=username(message), text=f"Ошибка команды: {e}") diff --git a/BotLibrary/loggers/custom_loggers.py b/BotLibrary/loggers/custom_loggers.py index 232a690..7c95b96 100644 --- a/BotLibrary/loggers/custom_loggers.py +++ b/BotLibrary/loggers/custom_loggers.py @@ -13,7 +13,7 @@ class Logs: """Класс для логирования с разными уровнями через loguru.""" @staticmethod - def debug(text: str = "Логирование!", log_type: str = "Logs", user: str = "Console", message: Message = None) -> None: + def debug(text: str = "Логирование!", log_type: str = "Logs", user: str = "@Console", message: Message = None) -> None: """ Логирует сообщение на уровне DEBUG. @@ -27,7 +27,7 @@ class Logs: logger.bind(log_type=log_type, user=user).debug(text) @staticmethod - def info(text: str = "Логирование!", log_type: str = "Logs", user: str = "Console", message: Message = None) -> None: + def info(text: str = "Логирование!", log_type: str = "Logs", user: str = "@Console", message: Message = None) -> None: """ Логирует сообщение на уровне INFO. @@ -41,7 +41,7 @@ class Logs: logger.bind(log_type=log_type, user=user).info(text) @staticmethod - def warning(text: str = "Логирование!", log_type: str = "Logs", user: str = "Console", message: Message = None) -> None: + def warning(text: str = "Логирование!", log_type: str = "Logs", user: str = "@Console", message: Message = None) -> None: """ Логирует сообщение на уровне WARNING. @@ -55,7 +55,7 @@ class Logs: logger.bind(log_type=log_type, user=user).warning(text) @staticmethod - def error(text: str = "Логирование!", log_type: str = "Logs", user: str = "Console", message: Message = None) -> None: + def error(text: str = "Логирование!", log_type: str = "Logs", user: str = "@Console", message: Message = None) -> None: """ Логирует сообщение на уровне ERROR. diff --git a/Documentation/FIX_LIST.md b/Documentation/FIX_LIST.md new file mode 100644 index 0000000..0c1b216 --- /dev/null +++ b/Documentation/FIX_LIST.md @@ -0,0 +1,51 @@ +## Что нужно исправить: + +--- + +- [X] Сделать НОВОЕ логгирование + + ~~- [ ] Создать новые классы логгеров~~ + - [X] Переделать везде на новые логгеры + - [X] Создать логгеры на ошибки + + +- [ ] Определение типа сообщения + - [X] Закреп + - [ ] Добавление\Уход участника + - [ ] Прочие системные уведомления + + +- [X] Починить скачивание документов и файлов [Возможно-частично!] + - [ ] Улучшить качество изображений аватарок чата + + +- [ ] ~~Сделать красивый GUI работы~~ + [Боту нужнее новое логирование, пока отменить GUI] + + +- [ ] Определение юзернейма по id (Для работы команд администрации) + + +- [ ] Доделать команды администрирования (бан, кик, мут, админ+, админ-) + + +- [ ] Починить батники для работы с обновами (Авто-обновления проекта) + + +- [ ] Исправить остальные проблемы + - [X] Прокомментировать каждый файл + - [ ] Сделать нормальную инструкцию + - [ ] Проверить все файлы и улучшить их + - [ ] Иное. +--- + +- [ ] Сделать проверку на ошибки в edit_bot? (Там также добавлена команда set_commands) + + +--- + +07.02.2025 +- [ ] Сделать проверку на личные сообщения +- [ ] Починить start_time и отображение времени +- [ ] Модуль день рождение +- [ ] FSM \ No newline at end of file diff --git a/Documentation/README.md b/Documentation/README.md new file mode 100644 index 0000000..62927ab --- /dev/null +++ b/Documentation/README.md @@ -0,0 +1,74 @@ +## PRIMO_aiogram_bot + +--- +## Приветствие + +Здравствуй, **дорогой пользователь**! +Меня зовут *Лейн*, я думаю, мы вряд ли с Вами знакомы, +но это и неважно. + +Этот проект нужен для того, чтобы каждый мог +создать своего *бота* на основе **Aiogram**. +Этот **шаблон** позволит Вам получить все возможные функции: от создания *клавиатур*, +до *логгеров* или *машины состояний*. + +--- +## Навигация: + +- ### [Приветствие](#Приветствие) +- ### [Первый запуск бота](#Запуск) +- ### [Его возможности](#Возможности) +- ### [Прочее](#Прочее) +- ### [Задачи:](#Задачи) +- ### [Прощание](#Прощание) + +--- +## Запуск + +Так что, давайте поговорим немного о самом проекте. +Для начала, проект, что Вы получили с **GitHub**, имеет небольшую особенность +для Windows-пользователей, а именно файл **project.bat**. +Активировав этот файл через *консоль* с помощью команды: +**start project**. +Вы сможете установить локальное окружение, обновить библиотеки и запустить бота. Вам +не понадобиться думать и настраивать бота. Все, что Вам необходимо - это иметь +установленным **Python 3.13** и **GIT**. После этого он автоматически: + +- создаст локальное окружение +- установит все необходимые библиотеки +- создаст локальный **GIT** репозиторий +- запустит сам **main.py** (*основной файл бота*) + +--- +## Возможности + +Поэтому, Вы уже получите возможность пользоваться системой **GIT**. Также из плюсов можно +выделить многое другое, например: +- Работа с репозиториями и системой GIT +- Удобное логирование с помощью loguru +- Проверка на ошибки и удобный вывод их в окно консоли +- Работа с базами данных (в разработке) +- И т.д... + + +--- +## Задачи: + +- Сделать адекватную базу данных +- Сделать проверки на ошибки, и не правильный тип данных, +а главное, чтобы это логгировалось консолью +- Сделать отдельный логгер под ошибки в файл +- Скачивание аватарок каналов + доделать для чатов +- Доделать команды /ban, /kik, /mute +- И т.д. + +--- +## Прощание + +Я очень рад, что Вы пользуетесь этим проектом, надеюсь, +что в дальнейшем буду улучшать его все дальше и дальше. +Удачи Вам, и ,конечно же... + +***Вперед за Истиной, Дорогой Друг!*** + +- **Verum.** diff --git a/SQLite3/list_ids.json b/SQLite3/list_ids.json new file mode 100644 index 0000000..67a513a --- /dev/null +++ b/SQLite3/list_ids.json @@ -0,0 +1,35 @@ +{ + "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" + } +} diff --git a/Test/GUI/__init__.py b/Test/GUI/__init__.py new file mode 100644 index 0000000..732d5ec --- /dev/null +++ b/Test/GUI/__init__.py @@ -0,0 +1,4 @@ +# GUI/__init__.py +# Инициализация пакета GUI, для работы с графическим интерфейсом + +from .console import * diff --git a/Test/GUI/console.py b/Test/GUI/console.py new file mode 100644 index 0000000..f06444b --- /dev/null +++ b/Test/GUI/console.py @@ -0,0 +1,167 @@ +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() diff --git a/Test/GUI/console_0.py b/Test/GUI/console_0.py new file mode 100644 index 0000000..ce73298 --- /dev/null +++ b/Test/GUI/console_0.py @@ -0,0 +1,74 @@ +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() diff --git a/Test/__init__.py b/Test/__init__.py new file mode 100644 index 0000000..b37c6a3 --- /dev/null +++ b/Test/__init__.py @@ -0,0 +1,12 @@ +# Test/__init__.py +# Инициализация пакета Test, для работы с тестированием (в разработке) + +# Импортируем библиотеки для экспорта +from aiogram import Router +from .commands import * +from .GUI import * +from .old_files import * + + +# Создание роутера "test_router" +router = Router(name="test_router") diff --git a/Documentation/ReadMe.md b/Test/commands/__init__.py similarity index 100% rename from Documentation/ReadMe.md rename to Test/commands/__init__.py diff --git a/Test/commands/ban_cmd.py b/Test/commands/ban_cmd.py new file mode 100644 index 0000000..c022f72 --- /dev/null +++ b/Test/commands/ban_cmd.py @@ -0,0 +1,63 @@ +# 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 diff --git a/Test/commands/download_channel_avatar.py b/Test/commands/download_channel_avatar.py new file mode 100644 index 0000000..d64d9ab --- /dev/null +++ b/Test/commands/download_channel_avatar.py @@ -0,0 +1,63 @@ +# BotCode/routers/downloads/download_channel_avatar.py +# Закачка аватарок канала (в разработке + сделать логирование!!!) + +import requests +from aiogram import Router +from aiogram.types import Message +from BotLibrary import * + +# Создание роутера и настройка экспорта +__all__ = ("router", "download_channel_avatar",) +router = Router(name="avatar_channel_router") +type_messages = "AvatarChannel" + + +# Функция для скачивания аватарки канала +@router.message(lambda message: message.chat.type == 'channel') +async def download_channel_avatar(message: Message): + try: + # Логирование для получения сообщения из канала + logger.bind(custom_variable=type_messages, user_var=f"{message.chat.id}").info(f"Получено сообщение из канала ID {message.chat.id}: {message.text}") + + # Получаем информацию о чате канала + chat_info = await bot.get_chat(message.chat.id) # message.chat.id для получения ID канала + + # Логирование полученной информации + logger.bind(custom_variable=type_messages, user_var=f"{chat_info.id}").info(f"Информация о канале: {chat_info.title}") + + # Проверка наличия аватара + if not chat_info.photo: + text_error = f"Канал с ID {message.chat.id} не имеет аватара." + logger.error(text_error) + return text_error + + # Получаем file_id для фото (используем big_file_id для лучшего качества) + file_info = await bot.get_file(chat_info.photo.big_file_id) + + # Строим URL для скачивания файла + file_url = f"https://api.telegram.org/file/bot{bot.token}/{file_info.file_path}" + + # Формируем имя и путь для сохранения фото + save_dir = f"{ImportantPath.channel_avatar}/{message.chat.id}" + os.makedirs(save_dir, exist_ok=True) + file_name = file_info.file_path.split("/")[-1] # Имя файла (например, "abc.jpg") + save_path = os.path.join(save_dir, file_name) + + # Скачиваем аватар + response = requests.get(file_url) + if response.status_code == 200: + with open(save_path, "wb") as file: + file.write(response.content) + text = f"Фото аватара канала с ID {message.chat.id} успешно скачано и сохранено как {save_path}" + logger.info(text) + return text + + else: + text_error = f"Не удалось скачать аватар канала с ID {message.chat.id}. Статус: {response.status_code}" + logger.bind(custom_variable=type_messages, user_var=f"{message.chat.id}").error(text_error) + return text_error + + except Exception as e: + text_error = f"Ошибка при скачивании фото аватара канала с ID {message.chat.id}: {e}" + logger.bind(custom_variable=type_messages, user_var=f"{message.chat.id}").error(text_error) + return text_error diff --git a/Test/commands/find_username.py b/Test/commands/find_username.py new file mode 100644 index 0000000..7733ca5 --- /dev/null +++ b/Test/commands/find_username.py @@ -0,0 +1,25 @@ +# 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 diff --git a/Test/commands/send_to_user.py b/Test/commands/send_to_user.py new file mode 100644 index 0000000..9eb0b2f --- /dev/null +++ b/Test/commands/send_to_user.py @@ -0,0 +1,65 @@ +# BotCode/routers/commands/admin_cmd/send_to_user.py +# Работа с админ-командой /send, для отправки конкретного сообщения пользователю (в разработке) + +from aiogram import Router, types, F +from aiogram.filters import Command +from BotLibrary import * + +# Создание роутера и настройка экспорта +__all__ = ("router", "send_message",) +router = Router(name="send_router") +command_text = "Send" + + +# Обработчик команды /send для отправки сообщения определенному пользователю (в разработке) +@router.message(F.from_user.id.in_(ListId.important), + Command("send", "отправить", "отправ", "s", "ыутв", "jnghfdbnm", "jnghfd", + prefix=BotEdit.prefixs, ignore_case=True)) +async def send_message(message: types_msg.Message): + try: + if message.chat.id in ListId.adm_list_id: + text = f"использовал(а) команду /{command_text.lower()}" + + # Разбиваем сообщение на аргументы + args = message.text.split() + + # Проверка на правильность команды /send + if len(args) < 3: + texts = "Некорректный формат команды. Используйте: /send <текст>" + await message.reply(texts) + return texts + + # Получаем user_id и текст сообщения + user_id = int(args[1]) + text_send = ' '.join(args[2:]) + + # Отправляем сообщение пользователю + await bot.send_message(chat_id=user_id, text=text_send) + + # Логирование + user_id = find_imp_id(user_id) + await cmd_logginger(message, command_text, text) + + # Логирование и отчет об отправке + await message.reply(f"Сообщение успешно отправлено пользователю с ID {user_id}") + return text + + # Проверка на ошибку и ее логирование + except Exception as e: + text_error = await error_cmd_logginger(message, command_text, e) + return text_error + + # Проверка заблокирован ли бот для пользователя + # except exceptions.BotBlocked: + # await message.answer("Пользователь заблокировал бота") + # except aiogram.utils.exceptions.ChatNotFound: + # await message.answer("Чат с пользователем не найден") + # except exceptions.RetryAfter as e: + # await asyncio.sleep(e.timeout) + # return await send_message(message) + # except exceptions.UserDeactivated: + # await message.answer("Пользователь деактивирован") + # except exceptions.TelegramAPIError: + # await message.answer("Произошла ошибка при отправке сообщения") + # except: + # return diff --git a/Test/old_files/__init__.py b/Test/old_files/__init__.py new file mode 100644 index 0000000..492dcdc --- /dev/null +++ b/Test/old_files/__init__.py @@ -0,0 +1,22 @@ +# 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() diff --git a/Test/old_files/media_func.py b/Test/old_files/media_func.py new file mode 100644 index 0000000..ac76469 --- /dev/null +++ b/Test/old_files/media_func.py @@ -0,0 +1,55 @@ +# 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 diff --git a/Test/old_files/regular_handlers.py b/Test/old_files/regular_handlers.py new file mode 100644 index 0000000..f51394e --- /dev/null +++ b/Test/old_files/regular_handlers.py @@ -0,0 +1,29 @@ +# BotCode/routers/old_files/regular_handlers.py +# Регулярная функция, выдает тебе сообщение на код при сообщении с числами + +from aiogram import F, types, Router +from magic_filter import RegexpMode +from re import Match + +from BotLibrary import logginger +import configs + +# Настройка экспорта модулей и роутера +__all__ = ("router",) +router = Router(name="regular_handlers") + + +# Хэндлер на циферный код (регулярная функция) +@router.message( + F.from_user.id.in_(configs.ListId.adm_list_id), + F.text.regexp(r"(\d+)", mode=RegexpMode.MATCH).as_("code"), +) +async def handle_code(message: types.Message, code: Match[str]): + # Вывод сообщения + text = f"Ваш код: {code.group()}" + await message.reply(text) + + # Включение логирования в файл + await logginger(message) + + return text