base logic

This commit is contained in:
2025-02-22 22:36:39 +03:00
parent 1616181430
commit 8c191ca139
11 changed files with 581 additions and 3 deletions
+52
View File
@@ -0,0 +1,52 @@
import os
from sshtunnel import SSHTunnelForwarder
from dotenv import load_dotenv
load_dotenv()
class config:
BOT_TOKEN = os.environ.get("TOKEN")
API_KEY = os.environ.get("API_KEY")
ADMIN_ID = os.environ.get("ADMIN_ID")
ENV = os.getenv("ENV", "PROD")
DB_PORT = int(os.getenv("DB_PORT", 27017))
if ENV == "DEV":
server = SSHTunnelForwarder(
(os.environ.get("SSH_HOST"), 22),
ssh_private_key=os.getenv("SSH_KEY", None),
ssh_username=os.environ.get("SSH_USER"),
ssh_password=os.getenv("SSH_PASSWORD", None),
remote_bind_address=("localhost", DB_PORT),
)
server.start()
DB_PORT = server.local_bind_port
class BotCommands:
Start = ["start", "s"]
Help = ["help", "h"]
class Messages:
WELCOME_LIST = [
"Привет! Это бот Quick dates (Random Coffee). Чтобы зарегистрироваться, пожалуйста, ответь на следующие вопросы." # несколько сообщений подряд
]
ERROR = "An error occurred"
ENTER_NAME = "Как тебя зовут?"
ENTER_AGE = "Сколько тебе лет?"
ENTER_GENDER = "Выбери пол (женский, мужской)"
GENDER_WOMAN = "Я девушка" # кнопки выбора
GENDER_MAN = "Я парень" # кнопки выбора
ENTER_FACULTY = "С какого ты факультета?"
ENTER_GROUP = "Напиши номер своей группы"
REGISTRATION_CONFIRM = "Ты ввел следующие данные:\
\n\nИмя: {}\
\nВозраст: {}\
\nПол: {}\
\nФакультет: {}\
\nГруппа: {}\
\n\nВсё верно?"
ALREADY_REGISTERED = "Ты уже зарегистрирован. Хочешь изменить данные?"
+22
View File
@@ -0,0 +1,22 @@
import pymongo
from config import config
class DB:
client = pymongo.MongoClient(f"mongodb://localhost:{config.DB_PORT}/")
db = client["rc_coffee"]
def __init__(self, collection):
self.collection = self.db[collection]
def insert(self, data):
self.collection.insert_one(data)
def find(self, query):
return self.collection.find(query)
def update(self, query, data):
self.collection.update_one(query, {"$set": data})
def exist(self, query):
return self.collection.find_one(query) is not None
+63
View File
@@ -0,0 +1,63 @@
import os
import sys
import telebot
import threading
from config import config, BotCommands, Messages
from telebot import types
from plugin.user import User
from plugin.admin import Admin
from plugin.bot_instance import bot
from plugin.register import start_reg_name
import time
admin_id = config.ADMIN_ID
@bot.message_handler(commands=["start"])
def start_message(message: types.Message):
if User(message.chat.id).name is not None:
user = User(message.chat.id)
markup = types.InlineKeyboardMarkup()
markup.add(
types.InlineKeyboardButton(
"Оставьте как есть!", callback_data="registration_skip"
)
)
markup.add(
types.InlineKeyboardButton(
"Зарегестрироваться заново", callback_data="registration_change"
)
)
bot.send_message(message.chat.id, Messages.ALREADY_REGISTERED)
bot.send_message(
message.chat.id,
Messages.REGISTRATION_CONFIRM.format(
user.name,
user.age,
user.gender,
user.faculty,
user.group,
),
reply_markup=markup,
)
return
for msg in Messages.WELCOME_LIST:
bot.send_message(message.chat.id, msg)
bot.send_message(message.chat.id, Messages.ENTER_NAME)
bot.register_next_step_handler(message, start_reg_name)
return
if __name__ == "__main__":
print("/t--- Bot started ---")
while True:
time.sleep(10)
exit()
+21
View File
@@ -0,0 +1,21 @@
from db import DB
class Admin:
_db = DB("admins")
def __init__(self, user_id, name):
self.user_id = user_id
self.name = name
self._save()
def __init__(self, user_id):
self.user_id = user_id
self._load()
def _save(self):
self._db.insert({"user_id": self.user_id, "name": self.name})
def _load(self):
data = self._db.find_one({"user_id": self.user_id})
self.name = data["name"]
+14
View File
@@ -0,0 +1,14 @@
import telebot
import config
import threading
bot = telebot.TeleBot(
config.BOT_TOKEN,
colorful_logs=True,
)
threading.Thread(
target=bot.infinity_polling,
name="bot_infinity_polling",
daemon=True,
).start()
+109
View File
@@ -0,0 +1,109 @@
import telebot
from telebot import types
from plugin.user import User
from config import Messages
from plugin.test import TestMessages
from plugin.bot_instance import bot
def start_reg_name(message: types.Message):
user = User(message.chat.id, message.text)
bot.send_message(message.chat.id, Messages.ENTER_AGE)
bot.register_next_step_handler(message, start_reg_age)
def start_reg_age(message: types.Message):
user = User(message.chat.id)
user.age = int(message.text)
markup = types.InlineKeyboardMarkup(resize_keyboard=True)
markup.add(
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.register_next_step_handler(message, start_reg_gender)
@bot.callback_query_handler(func=lambda call: "gender" in call.data)
def start_reg_gender(call: types.CallbackQuery):
user = User(call.message.chat.id)
user.gender = call.data.split("_")[-1]
bot.edit_message_text(
Messages.GENDER_WOMAN if user.gender == "woman" else Messages.GENDER_MAN,
call.message.chat.id,
call.message.message_id,
reply_markup=None,
)
bot.send_message(call.message.chat.id, Messages.ENTER_FACULTY)
bot.register_next_step_handler(call.message, start_reg_faculty)
def start_reg_faculty(message: types.Message):
user = User(message.chat.id)
user.faculty = message.text
bot.send_message(message.chat.id, Messages.ENTER_GROUP)
bot.register_next_step_handler(message, start_reg_group)
def start_reg_group(message: types.Message):
user = User(message.chat.id)
user.group = message.text
markup = types.InlineKeyboardMarkup(resize_keyboard=True)
markup.add(
types.InlineKeyboardButton("Всё верно!", callback_data="registration_confirm"),
types.InlineKeyboardButton("Изменить", callback_data="registration_change"),
)
bot.send_message(
message.chat.id,
Messages.REGISTRATION_CONFIRM.format(
user.name,
user.age,
user.gender,
user.faculty,
user.group,
),
reply_markup=markup,
)
@bot.callback_query_handler(func=lambda call: call.data == "registration_skip")
def start_skip_reg(call: types.CallbackQuery):
bot.edit_message_reply_markup(
call.message.chat.id, call.message.message_id, reply_markup=None
)
return
@bot.callback_query_handler(func=lambda call: call.data == "registration_change")
def start_reg_again(call: types.CallbackQuery):
bot.edit_message_reply_markup(
call.message.chat.id, call.message.message_id, reply_markup=None
)
bot.send_message(call.message.chat.id, Messages.ENTER_NAME)
bot.register_next_step_handler(call.message, start_reg_name)
@bot.callback_query_handler(func=lambda call: call.data == "registration_confirm")
def start_test(call: types.CallbackQuery):
user = User(call.message.chat.id)
bot.edit_message_reply_markup(
call.message.chat.id, call.message.message_id, reply_markup=None
)
bot.send_message(call.message.chat.id, TestMessages.TEST_WELCOME)
pass
+122
View File
@@ -0,0 +1,122 @@
class TestMessages:
TEST_WELCOME = "Пройди следующий короткий тест, чтобы было легче подобрать тебе пару. А еще ты узнаешь, кто ты из героев советских мультфильмов."
TEST_QUESTIONS = [
{
"question": "Когда вы оказываетесь в новой компании людей, вы, как правило:",
"answers": [
(
"Легко заводите разговоры с разными людьми.",
"E",
),
(
"Предпочитаете сначала понаблюдать и только потом начать общаться с теми, кто вам интересен.",
"I",
),
],
},
{
"question": "Вы пишете книгу или создаете проект. Какой подход вам ближе?",
"answers": [
(
"Тщательно исследую тему, соберу всю доступную информацию и буду двигаться шаг за шагом, основываясь на фактах.",
"S",
),
(
"Сначала придумаю общую концепцию, представлю мир и героев (или цели проекта), и буду импровизировать, раскрывая детали по ходу дела.",
"N",
),
],
},
{
"question": "Ваш друг совершил ошибку, которая имеет серьезные последствия. Как вы отреагируете?",
"answers": [
(
"Объективно проанализирую ситуацию, укажу на ошибки и предложу логичное решение проблемы.",
"T",
),
(
"Постараюсь понять его мотивы, проявить сочувствие и оказать эмоциональную поддержку, чтобы он справился с ситуацией.",
"F",
),
],
},
{
"question": "Представьте, что у вас есть свободный день. Что вы выберете?",
"answers": [
(
"Заранее составлю план, чтобы максимально эффективно использовать время: посетить музей, заняться спортом, встретиться с друзьями.",
"J",
),
(
"Отложу все планы и позволю дню разворачиваться спонтанно: почитаю книгу, прогуляюсь по парку или просто буду наслаждаться моментом.",
"P",
),
],
},
]
TEST_RESULTS = {
"INTJ": (
"Профессор Селезнёв",
"Ты умеешь воспринимать ситуацию глобально, а твои действия точны и эффективны. Ты, как и профессор Селезнев, привык к системному подходу и логическому анализу, эксперт в своей области",
),
"INTP": (
"Знайка",
"Знаешь всё про всё и даже больше. Предпочитаешь полагаться на свою голову. Любишь “покопаться” в каком-нибудь вопросе и не боишься выдвигать даже самые неожиданные гипотезы",
),
"INFJ": (
"Ёжик в тумане",
"Ты, как и Ежик, типичный интроверт, погруженный в свой внутренний мир. Ты глубоко чувствуешь окружающий мир и обладаешь богатым воображением. Хоть и бываешь застенчив и раним, но при этом ты отзывчив и добр.",
),
"INFP": (
"Кот Леопольд",
"«Ребята, давайте жить дружно!». Ты стремишься к гармонии во всех сферах жизни. Ты творческая личность, которая в принятии решений руководствуется своими ценностями и убеждениями",
),
"ISTJ": (
"Кролик из Винни Пуха",
"“-И это всё потому, что у кого-то очень узкие двери! -Нет! Это всё потому, что кто-то слишком много ест!” Ты, как и кролик, всегда логичен и прагматичен. Не тратишь слов попусту, но в ответ на критику за словом в карман не полезешь))",
),
"ISTP": (
"Буратино",
"Ты стремишься узнать мир и найти свое место в жизни. Ты, как и Буратино, полон энергии и любопытства. Ты всегда готов исследовать новое и пробовать разные вещи",
),
"ISFJ": (
"Пятачок",
"Ты добрый и заботливый (поросенок), всегда готов поддержать своих друзей. Любишь проявлять преданность и стремление заботиться о других, стараясь сделать их счастливыми. Как и Пятачок ты всегда готов прийти на помощь, даже если это требует смелости.",
),
"ISFP": (
"Кот Матроскин",
"Ты гибкий, очаровательный артист, всегда готовый исследовать и испытать что-то новое. Ты творческая личность, тонкая, эмоциональные и чувствительные натура",
),
"ENTJ": (
"Сыщик из бременских музыкантов",
"Оу ес! Ты решителен и успешен в любом деле. Можешь легко подстроиться под обстоятельства и наперёд просчитать свои действия, прямо как гениальный сыщик!",
),
"ENTP": (
"Карлсон",
"“В самом расцвете сил!” Ты экстравертен, обаятелен, остроумен, любишь привлекать внимание и постоянно придумывать новые затеи!",
),
"ENFJ": (
"Почтальон Печкин",
"Своей яркой харизмой ты без усилий убеждаешь и увлекаешь других, наполняя пространство теплом и создавая отличную атмосферу для продуктивной работы.",
),
"ENFP": (
"Трубадур из бременских музыкантов",
"Ты энергичный, харизматичный и независимый человек. Ты не боишься перемен и всегда открыт к чему-то новому, легко находишь общий язык с людьми, а твое творческое мышление помогает находить нестандартные решения",
),
"ESTJ": (
"Римма Трофимовна. Мама дядя Федора",
"Ты являешься практичным и инициативным человеком, способным организовывать своё время и задачи. Высокие стандарты, которые ты установил для себя, делают тебя надежным и вдохновляющим примером для окружающих.",
),
"ESTP": (
"Волк из “Ну, погоди!”",
"Ты энергичный, авантюрный и предприимчивый. Как Волк всегда стремишься достичь своей цели и, не останавливаясь, ищешь новых приключений!",
),
"ESFJ": (
"Дядя Федор",
"Как и Дядя Федор, ты надежный и ответственный, на тебя всегда можно положиться. Ты внимателен к потребностям и чувствам других людей и всегда готов прийти на помощь.",
),
"ESFP": (
"Мышонок (“Какой чудесный день, какой чудесный пень…”)",
"Заводила, запевала. Всегда в центре событий. Умеешь заставить улыбнуться людей",
),
}
+124
View File
@@ -0,0 +1,124 @@
from db import DB
class User:
_db = DB("Users")
def __init__(self, user_id, name):
self.user_id: int = user_id
self._name: str = name
self._age: int = None
self._gender: str = None
self._faculty: str = None
self._group: str = None
self._type: str = None
self._save()
def __init__(self, user_id):
self.user_id: int = user_id
self._load()
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
self.update_data()
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, value):
self._age = value
self.update_data()
return self._age
@property
def gender(self):
return self._gender
@gender.setter
def gender(self, value):
self._gender = value
self.update_data()
return self._gender
@property
def faculty(self):
return self._faculty
@faculty.setter
def faculty(self, value):
self._faculty = value
self.update_data()
return self._faculty
@property
def group(self):
return self._group
@group.setter
def group(self, value):
self._group = value
self.update_data()
return self._group
@property
def type(self):
return self._type
@type.setter
def type(self, value):
self._type = value
self.update_data()
return self._type
def _into_json(self):
return {
"_id": self.user_id,
"name": self._name,
"age": self._age,
"gender": self._gender,
"faculty": self._faculty,
"group": self._group,
"type": self._type,
}
def update_data(self):
self._db.update({"_id": self.user_id}, self._into_json())
def _save(self):
if not self._db.exist({"_id": self.user_id}):
self._db.insert(self._into_json())
else:
self.update_data()
def _load(self):
if not self._db.exist({"_id": self.user_id}):
return
data = self._db.find_one({"_id": self.user_id})
self._name = data["name"]
self._age = data["age"]
self._gender = data["gender"]
self._faculty = data["faculty"]
self._group = data["group"]
self._type = data["type"]
def __str__(self):
text = [f"{var}: {vars(self)[var]}" for var in vars(self) if var]
text = "\n".join(text)
return text