0.6.1 Официальный шаблон, который позволяет управлять всем, что необходимо
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -30,3 +30,6 @@ BotFiles/
|
|||||||
# Игнорирование базы данных пользователя
|
# Игнорирование базы данных пользователя
|
||||||
MySQL/user_data.db
|
MySQL/user_data.db
|
||||||
MySQL/user_data.json
|
MySQL/user_data.json
|
||||||
|
|
||||||
|
# Файл подсчета строк
|
||||||
|
project_count_line.py
|
||||||
|
|||||||
1
.idea/PRIMOWORLD.iml
generated
1
.idea/PRIMOWORLD.iml
generated
@@ -13,6 +13,7 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/BotLibrary/timer" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/BotLibrary/timer" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/BotLibrary/validators" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/BotLibrary/validators" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/SQLite3" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/SQLite3" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/Test" isTestSource="true" />
|
||||||
<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" />
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class CommandHandler:
|
|||||||
async def handler(self, message: types.Message):
|
async def handler(self, message: types.Message):
|
||||||
"""Основной хэндлер команды."""
|
"""Основной хэндлер команды."""
|
||||||
try:
|
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(
|
await message.reply(
|
||||||
text=self.text_msg,
|
text=self.text_msg,
|
||||||
reply_markup=self.keyboard() if self.keyboard else None,
|
reply_markup=self.keyboard() if self.keyboard else None,
|
||||||
@@ -51,4 +51,4 @@ class CommandHandler:
|
|||||||
|
|
||||||
# Проверка на ошибку
|
# Проверка на ошибку
|
||||||
except Exception as e:
|
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}")
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class Logs:
|
|||||||
"""Класс для логирования с разными уровнями через loguru."""
|
"""Класс для логирования с разными уровнями через loguru."""
|
||||||
|
|
||||||
@staticmethod
|
@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.
|
Логирует сообщение на уровне DEBUG.
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class Logs:
|
|||||||
logger.bind(log_type=log_type, user=user).debug(text)
|
logger.bind(log_type=log_type, user=user).debug(text)
|
||||||
|
|
||||||
@staticmethod
|
@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.
|
Логирует сообщение на уровне INFO.
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ class Logs:
|
|||||||
logger.bind(log_type=log_type, user=user).info(text)
|
logger.bind(log_type=log_type, user=user).info(text)
|
||||||
|
|
||||||
@staticmethod
|
@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.
|
Логирует сообщение на уровне WARNING.
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ class Logs:
|
|||||||
logger.bind(log_type=log_type, user=user).warning(text)
|
logger.bind(log_type=log_type, user=user).warning(text)
|
||||||
|
|
||||||
@staticmethod
|
@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.
|
Логирует сообщение на уровне ERROR.
|
||||||
|
|
||||||
|
|||||||
51
Documentation/FIX_LIST.md
Normal file
51
Documentation/FIX_LIST.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
## Что нужно исправить: <i>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
- [X] Сделать НОВОЕ логгирование
|
||||||
|
|
||||||
|
~~- [ ] Создать новые классы логгеров~~
|
||||||
|
- [X] Переделать везде на новые логгеры
|
||||||
|
- [X] Создать логгеры на ошибки
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Определение типа сообщения
|
||||||
|
- [X] Закреп
|
||||||
|
- [ ] Добавление\Уход участника
|
||||||
|
- [ ] Прочие системные уведомления
|
||||||
|
|
||||||
|
|
||||||
|
- [X] Починить скачивание документов и файлов <b>[Возможно-частично!]</b>
|
||||||
|
- [ ] Улучшить качество изображений аватарок чата
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] ~~Сделать красивый GUI работы~~
|
||||||
|
<b>[Боту нужнее новое логирование, пока отменить GUI]</b>
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Определение юзернейма по id (Для работы команд администрации)
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Доделать команды администрирования (бан, кик, мут, админ+, админ-)
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Починить батники для работы с обновами (Авто-обновления проекта)
|
||||||
|
|
||||||
|
|
||||||
|
- [ ] Исправить остальные проблемы
|
||||||
|
- [X] Прокомментировать каждый файл
|
||||||
|
- [ ] Сделать нормальную инструкцию
|
||||||
|
- [ ] Проверить все файлы и улучшить их
|
||||||
|
- [ ] Иное.
|
||||||
|
---
|
||||||
|
|
||||||
|
- [ ] Сделать проверку на ошибки в edit_bot? (Там также добавлена команда set_commands)
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
07.02.2025
|
||||||
|
- [ ] Сделать проверку на личные сообщения
|
||||||
|
- [ ] Починить start_time и отображение времени
|
||||||
|
- [ ] Модуль день рождение
|
||||||
|
- [ ] FSM
|
||||||
74
Documentation/README.md
Normal file
74
Documentation/README.md
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
## PRIMO_aiogram_bot
|
||||||
|
|
||||||
|
---
|
||||||
|
## Приветствие
|
||||||
|
|
||||||
|
Здравствуй, <u>**дорогой пользователь**</u>!
|
||||||
|
Меня зовут *Лейн*, я думаю, мы вряд ли с Вами знакомы,
|
||||||
|
но это и неважно.
|
||||||
|
|
||||||
|
Этот проект нужен для того, чтобы каждый мог
|
||||||
|
создать своего *бота* на основе **Aiogram**.
|
||||||
|
Этот **шаблон** позволит Вам получить все возможные функции: от создания *клавиатур*,
|
||||||
|
до *логгеров* или *машины состояний*.
|
||||||
|
|
||||||
|
---
|
||||||
|
## Навигация:
|
||||||
|
|
||||||
|
- ### [Приветствие](#Приветствие)
|
||||||
|
- ### [Первый запуск бота](#Запуск)
|
||||||
|
- ### [Его возможности](#Возможности)
|
||||||
|
- ### [Прочее](#Прочее)
|
||||||
|
- ### [Задачи:](#Задачи)
|
||||||
|
- ### [Прощание](#Прощание)
|
||||||
|
|
||||||
|
---
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
Так что, давайте поговорим немного о самом проекте.
|
||||||
|
Для начала, проект, что Вы получили с **GitHub**, имеет небольшую особенность
|
||||||
|
для Windows-пользователей, а именно файл **project.bat**.
|
||||||
|
Активировав этот файл через *консоль* с помощью команды:
|
||||||
|
**start project**.
|
||||||
|
Вы сможете установить локальное окружение, обновить библиотеки и запустить бота. Вам
|
||||||
|
не понадобиться думать и настраивать бота. Все, что Вам необходимо - это иметь
|
||||||
|
установленным **Python 3.13** и **GIT**. После этого он автоматически:
|
||||||
|
|
||||||
|
- создаст локальное окружение
|
||||||
|
- установит все необходимые библиотеки
|
||||||
|
- создаст локальный **GIT** репозиторий
|
||||||
|
- запустит сам **main.py** (*основной файл бота*)
|
||||||
|
|
||||||
|
---
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
Поэтому, Вы уже получите возможность пользоваться системой **GIT**. Также из плюсов можно
|
||||||
|
выделить многое другое, например:
|
||||||
|
- Работа с репозиториями и системой GIT
|
||||||
|
- Удобное логирование с помощью loguru
|
||||||
|
- Проверка на ошибки и удобный вывод их в окно консоли
|
||||||
|
- Работа с базами данных (в разработке)
|
||||||
|
- И т.д...
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
## Задачи:
|
||||||
|
|
||||||
|
- Сделать адекватную базу данных
|
||||||
|
- Сделать проверки на ошибки, и не правильный тип данных,
|
||||||
|
а главное, чтобы это логгировалось консолью
|
||||||
|
- Сделать отдельный логгер под ошибки в файл
|
||||||
|
- Скачивание аватарок каналов + доделать для чатов
|
||||||
|
- Доделать команды /ban, /kik, /mute
|
||||||
|
- И т.д.
|
||||||
|
|
||||||
|
---
|
||||||
|
## Прощание
|
||||||
|
|
||||||
|
Я очень рад, что Вы пользуетесь этим проектом, надеюсь,
|
||||||
|
что в дальнейшем буду улучшать его все дальше и дальше.
|
||||||
|
Удачи Вам, и ,конечно же...
|
||||||
|
|
||||||
|
***Вперед за Истиной, Дорогой Друг!***
|
||||||
|
|
||||||
|
- **Verum.**
|
||||||
35
SQLite3/list_ids.json
Normal file
35
SQLite3/list_ids.json
Normal file
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
4
Test/GUI/__init__.py
Normal file
4
Test/GUI/__init__.py
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# GUI/__init__.py
|
||||||
|
# Инициализация пакета GUI, для работы с графическим интерфейсом
|
||||||
|
|
||||||
|
from .console import *
|
||||||
167
Test/GUI/console.py
Normal file
167
Test/GUI/console.py
Normal file
@@ -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()
|
||||||
74
Test/GUI/console_0.py
Normal file
74
Test/GUI/console_0.py
Normal file
@@ -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()
|
||||||
12
Test/__init__.py
Normal file
12
Test/__init__.py
Normal file
@@ -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")
|
||||||
63
Test/commands/ban_cmd.py
Normal file
63
Test/commands/ban_cmd.py
Normal file
@@ -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
|
||||||
63
Test/commands/download_channel_avatar.py
Normal file
63
Test/commands/download_channel_avatar.py
Normal file
@@ -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
|
||||||
25
Test/commands/find_username.py
Normal file
25
Test/commands/find_username.py
Normal file
@@ -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
|
||||||
65
Test/commands/send_to_user.py
Normal file
65
Test/commands/send_to_user.py
Normal file
@@ -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 <user_id> <текст>"
|
||||||
|
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
|
||||||
22
Test/old_files/__init__.py
Normal file
22
Test/old_files/__init__.py
Normal file
@@ -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()
|
||||||
55
Test/old_files/media_func.py
Normal file
55
Test/old_files/media_func.py
Normal file
@@ -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
|
||||||
29
Test/old_files/regular_handlers.py
Normal file
29
Test/old_files/regular_handlers.py
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user