commit 1ef9dc18bb578a3b236f9c488c8a33fba54cc0ea Author: Evgeniy L. Date: Sat Mar 15 10:10:55 2025 +0500 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5fe22d1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +.env +.venv/ +.idea/ +.vscode/ diff --git a/Modules/getAnecdote.py b/Modules/getAnecdote.py new file mode 100644 index 0000000..1707ac7 --- /dev/null +++ b/Modules/getAnecdote.py @@ -0,0 +1,57 @@ +import asyncio +import aiohttp +from bs4 import BeautifulSoup + +import random +import logging + +URL = 'https://nekdo.ru/random/' +HEADERS = { + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36" +} + +JOKES_list = [ + '''— Доктор, у меня проблема: я всё время забываю, что хотел сказать. +— Сколько это уже продолжается? +— Что «это»?''', + + '''— Почему вы опоздали на работу? +— Проспал. +— И что, до 16:00 спали? +— Нет, до 15:55.''', + + '''— Папа, а кто такой пессимист? +— Это человек, который, когда ему дают выбор между двумя злами, выбирает оба.''', +] + +def findInSoup(soup: BeautifulSoup): + element = soup.find('div', id=True, class_=True) + return element + +async def getAnecdote() -> str: + logging.info("Запрашиваю анекдот с сайта.") + async with aiohttp.ClientSession(headers=HEADERS) as session: + try: + async with session.get(URL) as response: + if response.status == 200: + logging.info("Успешно получен ответ от сервера.") + html = await response.text() + soup = BeautifulSoup(html, 'html.parser') + + element = findInSoup(soup) + if element: + logging.info("Анекдот успешно найден на странице.") + return element.text.strip() + + logging.warning(f"Получен неудачный статус ответа: {response.status}. Использую локальный анекдот.") + return random.choice(JOKES_list) + except Exception as e: + logging.error(f"Ошибка при запросе: {e}. Использую локальный анекдот.") + return random.choice(JOKES_list) + +if __name__ == "__main__": + async def main(): + text = await getAnecdote() + print(text) + + asyncio.run(main()) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..adb3dd1 --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# Telegram Бот для Проекта SRSP + +Телеграм-бот для предоставления информации о команде разработчиков, документации и презентации проекта. + +## Описание + +Этот бот предоставляет удобный интерфейс для доступа к информации о команде разработчиков, технической документации и презентации проекта. Бот разработан с использованием библиотеки aiogram 3.x. + +## Функциональность + +- `/start` - Начать работу с ботом и отобразить основную клавиатуру. +- В ответном сообщение отправляется случайный анекдот с сайта nekdo.ru +- `/team_members` - Показать информацию о членах команды разработчиков +- `/documentation` - Скачать техническую документацию проекта +- `/presentation` - Скачать презентацию проекта +- `/help` - Показать список доступных команд + +## Установка и запуск + +### Предварительные требования + +- Python 3.8 или выше +- pip (менеджер пакетов Python) + +### Шаги по установке + +1. Клонировать репозиторий: +```bash +git clone https://github.com/ArtzSU/SRSP-bot +cd tgbotsrsp +``` + +2. Создать и активировать виртуальное окружение: +```bash +python -m venv .venv +# Для Windows +.venv\Scripts\activate +# Для macOS/Linux +source .venv/bin/activate +``` + +3. Установить зависимости: +```bash +pip install -r requirements.txt +``` + +4. Создать файл `.env` в корневой директории проекта и добавить токен бота: +``` +BOT_TOKEN=ваш_токен_бота +``` + +### Запуск бота + +```bash +python main.py +``` + +## Структура проекта + +- `main.py` - Основной файл с логикой бота +- `config.py` - Конфигурационный файл с константами и настройками +- `keyboard.py` - Файл с определениями клавиатур для бота +- `assets/` - Директория с ресурсами (документация, презентация) +- `Modules/` - Директория с модулями +- `Modules/getAnecdote.py` - Модуль запроса случайного анекдота +- `requirements.txt` - Список зависимостей проекта + +## Команда разработчиков + +- Лукьянов Е. - @artzsu +- Серик Т. - @tam_serik +- Скрипченко В. - @Sunny_Vls +- Исламберди А. - @Y191900 diff --git a/assets/pressetation.pptx b/assets/pressetation.pptx new file mode 100644 index 0000000..85761c3 Binary files /dev/null and b/assets/pressetation.pptx differ diff --git a/assets/tech_doc.docx b/assets/tech_doc.docx new file mode 100644 index 0000000..9bfc088 Binary files /dev/null and b/assets/tech_doc.docx differ diff --git a/config.py b/config.py new file mode 100644 index 0000000..d67787f --- /dev/null +++ b/config.py @@ -0,0 +1,19 @@ +import os +from dotenv import load_dotenv + +if not load_dotenv(): + raise FileNotFoundError('.env file does not exist') + +TOKEN = os.environ.get('BOT_TOKEN') +if not TOKEN: + raise ValueError("BOT_TOKEN is not set in the environment variables") + +DEBUG = os.environ.get('DEBUG', 'False').lower() in ('true', '1', 'yes', 'on') + +TEAM_MEMBERS_STR = """ +Team: +- Lukyanov E. - @queue_qq +- Serik T. - @tam_serik +- Skripchenko V. - @Sunny_Vls +- Islamberdi A. - @Y191900 +""" diff --git a/keyboard.py b/keyboard.py new file mode 100644 index 0000000..5356dde --- /dev/null +++ b/keyboard.py @@ -0,0 +1,22 @@ +from aiogram.types import ( + KeyboardButton, + ReplyKeyboardMarkup, +) + +# REPLY_KEYBOARDS +main_kb = ReplyKeyboardMarkup( + keyboard = [ + [ + KeyboardButton(text="/team_members") + ], + [ + KeyboardButton(text="/documentation"), + KeyboardButton(text="/presentation"), + ], + [ + KeyboardButton(text="/help") + ] + ], + resize_keyboard=True, + input_field_placeholder="Choose one option", +) diff --git a/main.py b/main.py new file mode 100644 index 0000000..fae81d7 --- /dev/null +++ b/main.py @@ -0,0 +1,133 @@ +import asyncio +import logging + +from aiogram.filters import Command +from aiogram.enums import ParseMode, ChatType +from aiogram.client.default import DefaultBotProperties +from aiogram import ( + F, + Bot, + html, + Dispatcher, +) +from aiogram.types import ( + Message, + FSInputFile, + BotCommand, +) + +from Modules.getAnecdote import getAnecdote + +import config + +from keyboard import main_kb + + +logger = logging.getLogger(__name__) +logging.basicConfig( + level=logging.DEBUG if config.DEBUG else logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' +) + +dp = Dispatcher() +bot = Bot( + token=config.TOKEN, + default=DefaultBotProperties( + parse_mode=ParseMode.HTML + ) +) + + +async def set_commands(service: Bot): + """ + Регистрация команд бота в меню команд Telegram + """ + commands = [ + BotCommand(command="start", description="Start the bot"), + BotCommand(command="help", description="Help"), + BotCommand(command="team_members", description="Show members of development team"), + BotCommand(command="documentation", description="Show documentation"), + BotCommand(command="presentation", description="Show presentation"), + ] + + await service.set_my_commands(commands) + logger.info("Команды бота успешно зарегистрированы") + + + +@dp.message(Command("start")) +async def command_start_handler(message: Message) -> None: + """ + Handler for the `/start` command + """ + + await message.reply( + text=f"Hello, {html.bold(message.from_user.full_name)}! {await getAnecdote()}", + reply_markup=main_kb + ) + + +@dp.message(Command("team_members")) +async def command_of_devers(message: Message): + """ + Handler for the `/team_members` command + """ + + await message.reply(text=config.TEAM_MEMBERS_STR) + + +@dp.message(Command("help")) +async def cmd_help(message: Message): + """ + Handler for the `/help` command + """ + + await message.reply( + text = """Вот список команд: +/start - начать работу +/help - вывести это сообщение +/documentation - отправляет отчет проделанной работы +/presentation - отправляет презентацию о боте""" + + ) + + +@dp.message(Command("documentation")) +async def cmd_doc(message: Message): + """ + Handler for the `/documentation` command + """ + + await message.reply_document( + document=FSInputFile(path="assets/tech_doc.docx", filename="техническая документация.docx") + ) + + +@dp.message(Command("presentation")) +async def cmd_presentation(message: Message): + """ + Handler for the `/presentation` command + """ + + await message.reply_document( + document=FSInputFile(path="assets/pressetation.pptx", filename="презентация.pptx") + ) + + +async def main() -> None: + """ + Main function to start the bot + """ + + logging.info("Starting bot") + + dp.message.filter(F.chat.type == ChatType.PRIVATE) + dp.callback_query.filter(F.message.chat.type == ChatType.PRIVATE) + + await set_commands(bot) + await bot.delete_webhook(drop_pending_updates=True) + await dp.start_polling(bot) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..3ee397a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +aiogram~=3.18.0 +python-dotenv~=1.0.1 +beautifulsoup4~=4.13.3 +requests~=2.32.3