From 899ff5aaace6d0eebb4348a5d83958e54d8068aa Mon Sep 17 00:00:00 2001 From: Verum Date: Mon, 24 Feb 2025 05:57:04 +0700 Subject: [PATCH] =?UTF-8?q?0.7.2=20=D1=82=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20?= =?UTF-8?q?=D1=81=D0=B1=D0=BE=D1=80=D1=89=D0=B8=D0=BA=20=D0=BA=D0=BE=D0=BC?= =?UTF-8?q?=D0=B0=D0=BD=D0=B4=20=D0=B8=D0=BC=D0=B5=D0=B5=D1=82=20=D0=B2?= =?UTF-8?q?=D1=81=D0=B5=20=D1=82=D0=B8=D0=BF=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BotCode/routers/commands/user_cmd/help_cmd.py | 4 + .../routers/commands/user_cmd/start_cmd.py | 1 + BotLibrary/samples/user_cmd_class.py | 92 ++++++++++++++++-- BotLibrary/validators/__init__.py | 1 + BotLibrary/validators/url_valid.py | 24 +++++ ProjectsFiles/configs/.env | 6 +- ProjectsFiles/media/Avatar/bot_avatar.png | Bin 0 -> 6577 bytes ProjectsFiles/media/Avatar/console_avatar.png | Bin 0 -> 6577 bytes 8 files changed, 115 insertions(+), 13 deletions(-) create mode 100644 BotLibrary/validators/url_valid.py create mode 100644 ProjectsFiles/media/Avatar/bot_avatar.png create mode 100644 ProjectsFiles/media/Avatar/console_avatar.png diff --git a/BotCode/routers/commands/user_cmd/help_cmd.py b/BotCode/routers/commands/user_cmd/help_cmd.py index a9306b0..5156676 100644 --- a/BotCode/routers/commands/user_cmd/help_cmd.py +++ b/BotCode/routers/commands/user_cmd/help_cmd.py @@ -2,6 +2,8 @@ # Работа с командой /help, для вывода помощи пользователю from BotLibrary import CommandHandler +from BotCode.keyboards import get_start_kb + # Создание команды /help с нужными параметрами help_cmd = CommandHandler( @@ -9,5 +11,7 @@ help_cmd = CommandHandler( description="Получить помощь", keywords=["help", "info", "помощь", "инфо", "информация", "рудз", "штащ", "byaj", "gjvjom", "byajhvfwbz"], callbackdata="keywords", + keyboard=get_start_kb, text_msg="Привет! Это команда помощи. Тут ты можешь узнать, как пользоваться ботом.", + media="gif", path_to_media="https://t.me/c/2442589033/74653" ) diff --git a/BotCode/routers/commands/user_cmd/start_cmd.py b/BotCode/routers/commands/user_cmd/start_cmd.py index 0172a52..e9b2670 100644 --- a/BotCode/routers/commands/user_cmd/start_cmd.py +++ b/BotCode/routers/commands/user_cmd/start_cmd.py @@ -13,4 +13,5 @@ start_cmd = CommandHandler( callbackdata="keywords", text_msg="Старт!", keyboard=get_start_kb, + media="file", path_to_media="https://gdb.voanews.com/455403fe-91ea-4abe-8d29-3862282ec56b_cx0_cy9_cw0_w408_r1_s.jpg", ) diff --git a/BotLibrary/samples/user_cmd_class.py b/BotLibrary/samples/user_cmd_class.py index 9561222..6fa2bd9 100644 --- a/BotLibrary/samples/user_cmd_class.py +++ b/BotLibrary/samples/user_cmd_class.py @@ -5,6 +5,7 @@ from aiogram import Router, types, F from aiogram.enums import ChatAction from aiogram.filters import Command +from BotLibrary import valid_url from ProjectsFiles import BotVar from BotLibrary.validators import username from BotLibrary.loggers import Logs @@ -55,6 +56,8 @@ class CommandHandler: async def handler(self, message: types.Message): """Основной хэндлер команды.""" try: + url : bool = valid_url(self.path_to_media) + Logs.info(log_type=self.log_type, user=username(message), text=f"использовал(а) команду /{self.name}") if self.media == "message": await message.reply( @@ -70,46 +73,115 @@ class CommandHandler: ) else: if self.media == "photo": - await message.reply_photo( - photo="https://vos-mo.ru/upload/iblock/329/g0s939ge8o1n8xp7rcqnw9kkz9mcfrg2/risunok.jpg", - caption=self.text_msg) + if url: + await message.reply_photo(photo=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_photo(photo=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, action=ChatAction.UPLOAD_PHOTO, ) - if self.media == "gif": - await message.reply_animation( - animation="https://vos-mo.ru/upload/iblock/329/g0s939ge8o1n8xp7rcqnw9kkz9mcfrg2/risunok.jpg") + elif self.media == "gif": + if url: + await message.reply_animation(animation=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_animation(animation=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, action=ChatAction.UPLOAD_VIDEO, ) - if self.media == "video": + + elif self.media == "video": + if url: + await message.reply_video(video=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_video(video=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, action=ChatAction.UPLOAD_VIDEO, ) - if self.media == "videonote": + elif self.media == "videonote": + if url: + await message.reply_video_note(video_note=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_video_note(video_note=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, action=ChatAction.UPLOAD_VIDEO_NOTE, ) - if self.media == "audio": + elif self.media == "audio": + if url: + await message.reply_audio(audio=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_audio(audio=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, action=ChatAction.UPLOAD_VOICE, ) - if self.media == "file": + elif self.media == "file": + if url: + await message.reply_document(document=self.path_to_media, + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) + else: + await message.reply_document(document=types.FSInputFile(path=self.path_to_media), + caption=self.text_msg, + reply_markup=self.keyboard() if self.keyboard else None, + parse_mode=self.parse_mode, + disable_notification=self.disable_notification) if self.chat_action: await message.bot.send_chat_action( chat_id=message.chat.id, diff --git a/BotLibrary/validators/__init__.py b/BotLibrary/validators/__init__.py index 6707043..a45718c 100644 --- a/BotLibrary/validators/__init__.py +++ b/BotLibrary/validators/__init__.py @@ -4,3 +4,4 @@ # Экспортирование модулей во внешние слои проекта from .email_valid import * from .username import * +from .url_valid import * diff --git a/BotLibrary/validators/url_valid.py b/BotLibrary/validators/url_valid.py new file mode 100644 index 0000000..9729dcb --- /dev/null +++ b/BotLibrary/validators/url_valid.py @@ -0,0 +1,24 @@ +# BotLibrary/validators/url_valid.py +# Валидатор ссылок на регулярных выражениях + +import re + +# Настройка экспорта из этого модуля +__all__ = ("valid_url",) + + +# Функция определения является ли строка ссылкой +def valid_url(url: str) -> bool: + """ + Проверяет, является ли строка валидной ссылкой (URL). + + :param url: Строка для проверки. + :return: True, если строка является валидным URL, иначе False. + """ + url_pattern = re.compile( + r'^(https?://)?' # Протокол (http или https, необязателен) + r'([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}' # Домен + r'(:\d+)?' # Порт (необязателен) + r'(/[-a-zA-Z0-9@:%_+.~#?&//=]*)?$' # Путь, параметры и фрагменты + ) + return bool(url_pattern.match(url)) diff --git a/ProjectsFiles/configs/.env b/ProjectsFiles/configs/.env index ff89f56..c4a15e3 100644 --- a/ProjectsFiles/configs/.env +++ b/ProjectsFiles/configs/.env @@ -2,9 +2,9 @@ # Файл-хранилище всех секретных токенов и ключей # Токены от ботов телеграмма -BOT_TOKEN=8076305634:AAGNoo4N-WVP9mbeD76G7SLClSsySw23nGw -BOT1_TOKEN=ТОКЕН_БОТА1 -BOT2_TOKEN=ТОКЕН_БОТА2 +BOT_TOKEN=7193685715:AAHFEnFreZGLQcHj8_wdWYJ2FLPrB-A-hzY +BOT1_TOKEN=8076305634:AAGNoo4N-WVP9mbeD76G7SLClSsySw23nGw +BOT2_TOKEN= # Ключи от API API_KEY=КЛЮЧ_ОТ_СТОРОННЕГО_API diff --git a/ProjectsFiles/media/Avatar/bot_avatar.png b/ProjectsFiles/media/Avatar/bot_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..c8ba74c5949d31141892857be3978c0d978df536 GIT binary patch literal 6577 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 CgyLTS literal 0 HcmV?d00001 diff --git a/ProjectsFiles/media/Avatar/console_avatar.png b/ProjectsFiles/media/Avatar/console_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..c8ba74c5949d31141892857be3978c0d978df536 GIT binary patch literal 6577 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 CgyLTS literal 0 HcmV?d00001