feat: add create and change profile

This commit is contained in:
Faynot
2026-03-28 21:39:27 +03:00
parent 6d2b4b6346
commit 1db524f757
2 changed files with 135 additions and 31 deletions

139
bot.py
View File

@@ -3,26 +3,29 @@ import logging
import sys import sys
from os import getenv from os import getenv
from aiogram import Bot, Dispatcher, html from aiogram import Bot, Dispatcher, html, F
from aiogram.client.default import DefaultBotProperties from aiogram.client.default import DefaultBotProperties
from aiogram.enums import ParseMode from aiogram.enums import ParseMode
from aiogram.filters import CommandStart from aiogram.filters import CommandStart, Command
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton from aiogram.types import Message, InlineKeyboardButton, CallbackQuery
from dotenv import load_dotenv
from aiogram import F
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
from aiogram.utils.keyboard import InlineKeyboardBuilder, ReplyKeyboardBuilder from aiogram.fsm.state import State, StatesGroup
from aiogram.utils.keyboard import InlineKeyboardBuilder
from dotenv import load_dotenv
from database import Database from database import Database
load_dotenv() load_dotenv()
TOKEN = getenv("BOT_TOKEN") TOKEN = getenv("BOT_TOKEN")
dp = Dispatcher() dp = Dispatcher()
db = Database("users.db") db = Database("users.db")
async def on_startup(): # Добавили состояние для ручного ввода сферы
await db.create_tables() class Registration(StatesGroup):
print("db 200") waiting_for_sphere = State()
waiting_for_custom_sphere = State() # <-- Новое состояние
waiting_for_language = State()
waiting_for_preferences = State()
@dp.message(CommandStart()) @dp.message(CommandStart())
async def command_start_handler(message: Message) -> None: async def command_start_handler(message: Message) -> None:
@@ -32,40 +35,124 @@ async def command_start_handler(message: Message) -> None:
text = ( text = (
"<b>👋 Привет! Я твой персональный агент по Kwork.</b>\n\n" "<b>👋 Привет! Я твой персональный агент по Kwork.</b>\n\n"
"💻 ⚠️ <b>ВАЖНО:</b> Этот бот предназначен <b>исключительно для IT-специалистов</b>.\n\n"
"🔍 Я мониторю биржу 24/7 и мгновенно присылаю тебе свежие заказы.\n\n" "🔍 Я мониторю биржу 24/7 и мгновенно присылаю тебе свежие заказы.\n\n"
"⚠️ Нажимая кнопку «Подписаться», вы принимаете условия " "Нажимая кнопку «Подписаться», вы принимаете условия "
"<a href='https://telegra.ph/Polzovatelskoe-soglashenie-i-Oferta-qwork-parse-bot-03-28'>публичной оферты</a>." "<a href='https://telegra.ph/Polzovatelskoe-soglashenie-i-Oferta-qwork-parse-bot-03-28'>публичной оферты</a>."
) )
await message.answer( await message.answer(text, reply_markup=builder.as_markup(), disable_web_page_preview=True)
text,
reply_markup=builder.as_markup(), @dp.message(Command("profile"))
parse_mode="HTML", async def show_profile(message: Message):
disable_web_page_preview=True user_data = await db.get_user(message.from_user.id)
if not user_data or user_data[0] is None:
await message.answer("⚠️ Твой профиль еще не настроен. Нажми /start, чтобы начать.")
return
sphere, lang, prefs = user_data
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="📝 Редактировать профиль", callback_data="subscribe")) # Используем тот же callback
text = (
"<b>👤 Твой профиль IT-специалиста:</b>\n\n"
f"<b>🌐 Сфера:</b> {sphere}\n"
f"<b>🛠 Стек:</b> {lang}\n"
f"<b>⚙️ Предпочтения:</b> {prefs}\n\n"
"Хочешь что-то изменить? Нажми кнопку ниже."
) )
await message.answer(text, reply_markup=builder.as_markup())
@dp.callback_query(F.data == "subscribe") @dp.callback_query(F.data == "subscribe")
async def subscribe_handler(callback: CallbackQuery): async def subscribe_handler(callback: CallbackQuery, state: FSMContext):
user_id = callback.from_user.id await db.add_user(callback.from_user.id)
print("User ID:", user_id)
await db.add_user(user_id) builder = InlineKeyboardBuilder()
spheres = ["Backend", "Frontend", "Mobile", "DevOps", "Design", "QA"]
for sphere in spheres:
builder.add(InlineKeyboardButton(text=sphere, callback_data=f"sphere_{sphere}"))
users = await db.get_all() # Добавляем кнопку своего варианта
print("All users in DB:", users) builder.row(InlineKeyboardButton(text="⌨️ Свой вариант", callback_data="sphere_other"))
builder.adjust(2)
await callback.message.edit_text( await callback.message.edit_text(
"✅ <b>Вы успешно подписались на уведомления!</b>", "Отлично! Давай настроим профиль.\n<b>В какой сфере IT ты работаешь?</b>",
parse_mode="HTML" reply_markup=builder.as_markup()
) )
await callback.answer("Подписка активирована!") await state.set_state(Registration.waiting_for_sphere)
await callback.answer()
@dp.callback_query(Registration.waiting_for_sphere)
async def sphere_chosen(callback: CallbackQuery, state: FSMContext):
sphere = callback.data.split("_")[1]
if sphere == "other":
await callback.message.edit_text("Напиши свою сферу деятельности (например: <i>Data Science</i> или <i>GameDev</i>):")
await state.set_state(Registration.waiting_for_custom_sphere)
else:
await state.update_data(sphere=sphere)
await callback.message.edit_text(
f"Выбрано: <b>{sphere}</b>\n\nКакой основной <b>язык программирования</b> или стек технологий используешь?"
)
await state.set_state(Registration.waiting_for_language)
await callback.answer()
# Обработчик для текстового ввода своей сферы
@dp.message(Registration.waiting_for_custom_sphere)
async def custom_sphere_input(message: Message, state: FSMContext):
sphere = message.text
await state.update_data(sphere=sphere)
await message.answer(
f"Принято: <b>{sphere}</b>\n\nКакой основной <b>язык программирования</b> или стек технологий используешь?"
)
await state.set_state(Registration.waiting_for_language)
@dp.message(Registration.waiting_for_language)
async def language_chosen(message: Message, state: FSMContext):
await state.update_data(language=message.text)
# Создаем кнопку для пропуска
builder = InlineKeyboardBuilder()
builder.row(InlineKeyboardButton(text="⏩ Пропустить", callback_data="skip_preferences"))
await message.answer(
"Принято! И последнее: напиши свои <b>предпочтения по заказам</b> (фильтры).\n"
"Например: 'чек от 5000р' или 'без правок'.\n\n"
"<i>Если не хочешь заполнять сейчас, нажми кнопку ниже.</i>",
reply_markup=builder.as_markup()
)
await state.set_state(Registration.waiting_for_preferences)
@dp.callback_query(Registration.waiting_for_preferences, F.data == "skip_preferences")
async def skip_preferences(callback: CallbackQuery, state: FSMContext):
await state.update_data(preferences="Не указано") # Устанавливаем значение по умолчанию
user_data = await state.get_data()
await db.update_user_data(callback.from_user.id, user_data)
await callback.message.edit_text(
"✅ <b>Профиль успешно настроен!</b> (Фильтры пропущены)\n\n"
f"Сфера: {user_data['sphere']}\n"
f"Стек: {user_data['language']}\n"
f"Фильтры: {user_data['preferences']}"
)
await state.clear()
await callback.answer()
async def on_startup():
await db.create_tables()
print("Database ready")
async def main() -> None: async def main() -> None:
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML)) bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp.startup.register(on_startup) dp.startup.register(on_startup)
await dp.start_polling(bot) await dp.start_polling(bot)
if __name__ == "__main__": if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout) logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main()) asyncio.run(main())

View File

@@ -9,7 +9,10 @@ class Database:
await db.execute(""" await db.execute("""
CREATE TABLE IF NOT EXISTS users ( CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY, id INTEGER PRIMARY KEY,
user_id INTEGER UNIQUE user_id INTEGER UNIQUE,
sphere TEXT,
language TEXT,
preferences TEXT
) )
""") """)
await db.commit() await db.commit()
@@ -22,8 +25,22 @@ class Database:
) )
await db.commit() await db.commit()
async def update_user_data(self, user_id: int, data: dict):
async with aiosqlite.connect(self.db_path) as db:
await db.execute(
"UPDATE users SET sphere = ?, language = ?, preferences = ? WHERE user_id = ?",
(data.get('sphere'), data.get('language'), data.get('preferences'), user_id)
)
await db.commit()
async def get_all(self): async def get_all(self):
async with aiosqlite.connect(self.db_path) as db: async with aiosqlite.connect(self.db_path) as db:
async with db.execute("SELECT * FROM users") as cursor: async with db.execute("SELECT * FROM users") as cursor:
rows = await cursor.fetchall() return await cursor.fetchall()
return rows async def get_user(self, user_id: int):
async with aiosqlite.connect(self.db_path) as db:
async with db.execute(
"SELECT sphere, language, preferences FROM users WHERE user_id = ?",
(user_id,)
) as cursor:
return await cursor.fetchone()