diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/app/config.py b/app/config.py old mode 100644 new mode 100755 index 149b5ca..fbeaae9 --- a/app/config.py +++ b/app/config.py @@ -12,7 +12,7 @@ class config: "%Y-%m-%d-%H:%M", ) API_TOKEN = os.environ.get("API_TOKEN") - ADMIN_ID = os.environ.get("ADMIN_ID") + ADMIN_ID = int(os.environ.get("ADMIN_ID")) ENV = os.getenv("ENV", "PROD") DB_PORT = int(os.getenv("DB_PORT", 27017)) @@ -37,6 +37,7 @@ class Messages: "Доступные команды:" "\n/start - начать регистрацию", "\n/help - помощь", "\n/source - исходный код бота на Github", + "\n@more_logical - для всех вопросов по мероприятию", "\n\nCreated by АйТи блок ВМК with love ❤️", # "Начало мероприятия: {} \nЭто через целых {} минут!", ] diff --git a/app/db.py b/app/db.py old mode 100644 new mode 100755 index 9ef5c3e..7903f94 --- a/app/db.py +++ b/app/db.py @@ -3,17 +3,19 @@ from config import config class DB: - client = pymongo.MongoClient(f"mongodb://localhost:{config.DB_PORT}/") + client = pymongo.MongoClient(f"mongodb://mongo:{config.DB_PORT}/") db = client["rc_coffee"] def __init__(self, collection): + if collection not in self.db.list_collection_names(): + self.db.create_collection(collection) self.collection = self.db[collection] def insert(self, data): self.collection.insert_one(data) def find(self, query): - return self.collection.find(query) + return list(self.collection.find(query)) def find_one(self, query): return self.collection.find_one(query) diff --git a/app/main.py b/app/main.py old mode 100644 new mode 100755 index 4ac22b6..1830418 --- a/app/main.py +++ b/app/main.py @@ -42,7 +42,7 @@ def start_message(message: types.Message): Messages.REGISTRATION_CONFIRM.format( user.name, user.age, - user.gender, + "Парень" if user.gender == "man" else "Девушка", user.faculty, user.group, ), @@ -82,9 +82,28 @@ def source(message: types.Message): return +@bot.message_handler(func=lambda message: True) +def handle_all_messages(message: types.Message): + help_message(message) + + if __name__ == "__main__": print("/t--- Bot started ---") + admins = Admin.get_all_admins() + for admin in admins: + bot.send_message( + admin["user_id"], + "Служебное сообщение: бот был перезапущен.", + ) + + # Test connection to the database + try: + User.get_all() + print("Database connection successful.") + except Exception as e: + print(f"Database connection failed: {e}") + time_for_notif = config.DATE_START while True: @@ -103,5 +122,3 @@ if __name__ == "__main__": "Отправлено напоминание о скором начале мероприятия.", ) time.sleep(10) - - exit() diff --git a/app/plugin/admin.py b/app/plugin/admin.py old mode 100644 new mode 100755 index 0b67754..125a90a --- a/app/plugin/admin.py +++ b/app/plugin/admin.py @@ -1,5 +1,5 @@ from db import DB -import config +from config import config import os import threading import time @@ -34,17 +34,21 @@ class Admin: @staticmethod def get_all_admins(): - return Admin._db.find({}) + return [ + Admin(data["user_id"]) for data in Admin._db.find({}) if "user_id" in data + ] @staticmethod def is_admin(user_id): - return Admin._db.find({"user_id": user_id}) is not None + return (Admin._db.find_one({"user_id": user_id}) is not None) or ( + user_id == config.ADMIN_ID + ) @staticmethod def add_admin(new_user_id, name, unique_key) -> int: key_data = Admin._db.find_one({"unique_key": unique_key}) - if new_user_id == config.ADMIN_ID and not Admin.is_admin(new_user_id): + if new_user_id == config.ADMIN_ID: Admin._db.insert({"user_id": new_user_id, "name": name}) return new_user_id @@ -341,16 +345,25 @@ class Admin: return + @bot.message_handler(commands=["r", "restart"]) + @admin_only + def restart_command(message): + # os.system("python3 main.py") + os._exit(0) + + return + class AdminMessages: ADMIN_HELP = ( "Вы администратор! Вот что вы можете сделать:\n" "/remove_admin - удалить админа\n" - "/generate_key - сгенерировать уникальный ключ (admin_red - чтобы админ добавился)\n" + "/generate_key - сгенерировать уникальный ключ (admin_reg - чтобы админ добавился)\n" "/delete_user - удалить пользователя\n" "/stats - статистика\n" "/send_message - отправить всем сообщение\n" "/random - зарандомить людей для 1 тура\n" "/random_again - зарандомить людей без повторной регистрации\n" "clear_all - удаляет ВСЕХ пользователей для их повторной регистрации\n" + "/restart - перезапуск бота" ) diff --git a/app/plugin/bot_instance.py b/app/plugin/bot_instance.py old mode 100644 new mode 100755 diff --git a/app/plugin/register.py b/app/plugin/register.py old mode 100644 new mode 100755 index ff8f1dd..2d5a1e7 --- a/app/plugin/register.py +++ b/app/plugin/register.py @@ -9,15 +9,26 @@ import re def start_reg_name(message: types.Message): - user = User(message.chat.id, message.text) + user = User(message.chat.id) + user.name = message.text bot.send_message(message.chat.id, Messages.ENTER_AGE) bot.register_next_step_handler(message, start_reg_age) + return + def start_reg_age(message: types.Message): user = User(message.chat.id) + + if not message.text.isdigit(): + bot.send_message(message.chat.id, "Введите число") + + bot.register_next_step_handler(message, start_reg_age) + + return + user.age = int(message.text) markup = types.InlineKeyboardMarkup() @@ -25,9 +36,9 @@ def start_reg_age(message: types.Message): types.InlineKeyboardButton(Messages.GENDER_WOMAN, callback_data="gender_woman"), types.InlineKeyboardButton(Messages.GENDER_MAN, callback_data="gender_man"), ) - bot.send_message(message.chat.id, Messages.ENTER_GENDER) + bot.send_message(message.chat.id, Messages.ENTER_GENDER, reply_markup=markup) - bot.register_next_step_handler(message, start_reg_gender) + return @bot.callback_query_handler(func=lambda call: "gender" in call.data) @@ -70,7 +81,7 @@ def start_reg_group(message: types.Message): Messages.REGISTRATION_CONFIRM.format( user.name, user.age, - user.gender, + "Парень" if user.gender == "man" else "Девушка", user.faculty, user.group, ), @@ -128,12 +139,10 @@ def test_question(call: types.CallbackQuery): call.message.chat.id, call.message.message_id, reply_markup=None ) - if len(user.type) == 4: - show_result(call.message) - return - if call.data != "test_yes": - user.type += call.data.split("_")[-1] + user.type += TestMessages.TEST_QUESTIONS[len(user.type)]["answers"][ + int(call.data[-1]) + ][1] bot.edit_message_text( call.message.text @@ -145,12 +154,21 @@ def test_question(call: types.CallbackQuery): call.message.message_id, ) # упростить + if len(user.type) == 4: + show_result(call.message) + return + question = TestMessages.TEST_QUESTIONS[len(user.type)] + text = question["question"] markup = types.InlineKeyboardMarkup() - for answer in question["answers"]: - markup.add( - types.InlineKeyboardButton(answer[0], callback_data=f"test_{answer[1]}") - ) + markup.add( + types.InlineKeyboardButton("Первый вариант", callback_data=f"test_0"), + types.InlineKeyboardButton("Второй вариант", callback_data=f"test_1"), + ) + + text += f"\n\n1. {question['answers'][0][0]} \n\n2. {question['answers'][1][0]}" + + bot.send_message(call.message.chat.id, text, reply_markup=markup) return diff --git a/app/plugin/shuffle.py b/app/plugin/shuffle.py old mode 100644 new mode 100755 diff --git a/app/plugin/test.py b/app/plugin/test.py old mode 100644 new mode 100755 diff --git a/app/plugin/user.py b/app/plugin/user.py old mode 100644 new mode 100755 index e126433..91cb50a --- a/app/plugin/user.py +++ b/app/plugin/user.py @@ -10,7 +10,7 @@ users_reg: List["User"] = [] class User: _db = DB("Users") - def __init__(self, user_id, name): + def __init__(self, user_id, name=None): self.user_id: int = user_id self._name: str = name self._age: int = None @@ -19,10 +19,6 @@ class User: self._group: str = None self._type: str = None - self._save() - - def __init__(self, user_id): - self.user_id: int = user_id self._load() @property @@ -121,7 +117,8 @@ class User: def _load(self): if not self._db.exist({"_id": self.user_id}): - raise ValueError("User not found") + self._save() + # raise ValueError("User not found") data = self._db.find_one({"_id": self.user_id}) self._name = data["name"] @@ -145,19 +142,20 @@ class User: for user in users: bot.send_message(user.user_id, Messages.MATCHING_START, reply_markup=markup) - @bot.callback_query_handler(func=lambda call: call.data == "shuffle_agree") - def add_user_to_reg(call: types.CallbackQuery): - user = User(call.message.chat.id) - users_reg.append(user) + return - bot.edit_message_text( - call.message.chat.id, - call.message.message_id, - "Вы добавлены в список участников! Пожалуйста, подождите, пока все зарегистрируются", - reply_markup=None, - ) + @staticmethod + @bot.callback_query_handler(func=lambda call: call.data == "shuffle_agree") + def add_user_to_reg(call: types.CallbackQuery): + user = User(call.message.chat.id) + users_reg.append(user) - return + bot.edit_message_text( + call.message.chat.id, + call.message.message_id, + "Вы добавлены в список участников! Пожалуйста, подождите, пока все зарегистрируются", + reply_markup=None, + ) return diff --git a/app/requirements.txt b/app/requirements.txt old mode 100644 new mode 100755 diff --git a/docker-compose.yaml b/docker-compose.yaml old mode 100644 new mode 100755 index 6afeefa..946254d --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -1,32 +1,25 @@ -version: '3.8' services: bot: image: python:3.9 container_name: python_bot working_dir: /usr/src/app + links: + - "mongodb:mongo" volumes: - ./app:/usr/src/app - networks: - - rc_network depends_on: - mongodb command: sh -c "pip install -r requirements.txt && python main.py" + restart: unless-stopped mongodb: - image: mongo:latest - # image: mongo:8.0-rc - container_name: mongodb - networks: - - rc_network + image: 'mongo:4.4.6' + ports: + - '27017:27017' volumes: - - mongo-data:/data/db -networks: - rc_network: - driver: bridge - ipam: - config: - - subnet: 172.25.0.0/16 + - 'mongo-data:/data/db' + restart: unless-stopped volumes: mongo-data: @@ -34,4 +27,4 @@ volumes: driver_opts: type: none o: bind - device: ./.data \ No newline at end of file + device: ./.data diff --git a/readme.md b/readme.md old mode 100644 new mode 100755 index bda1016..4852f31 --- a/readme.md +++ b/readme.md @@ -46,6 +46,7 @@ - `/random_again` - сгенерировать повторную рассадку для людей первого тура (без повторной регистрации) - `/clear_all` - удалить всех людей из базы данных - `/remove_admin` - удалить админа по id +- `/restart` - перезапуск бота (только для Docker запуска) ## Настройка конфигурации