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

143
bot.py
View File

@@ -3,26 +3,29 @@ import logging
import sys
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.enums import ParseMode
from aiogram.filters import CommandStart
from aiogram.types import Message, InlineKeyboardMarkup, InlineKeyboardButton
from dotenv import load_dotenv
from aiogram import F
from aiogram.filters import CommandStart, Command
from aiogram.types import Message, InlineKeyboardButton, CallbackQuery
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
load_dotenv()
TOKEN = getenv("BOT_TOKEN")
dp = Dispatcher()
db = Database("users.db")
async def on_startup():
await db.create_tables()
print("db 200")
# Добавили состояние для ручного ввода сферы
class Registration(StatesGroup):
waiting_for_sphere = State()
waiting_for_custom_sphere = State() # <-- Новое состояние
waiting_for_language = State()
waiting_for_preferences = State()
@dp.message(CommandStart())
async def command_start_handler(message: Message) -> None:
@@ -32,40 +35,124 @@ async def command_start_handler(message: Message) -> None:
text = (
"<b>👋 Привет! Я твой персональный агент по Kwork.</b>\n\n"
"💻 ⚠️ <b>ВАЖНО:</b> Этот бот предназначен <b>исключительно для IT-специалистов</b>.\n\n"
"🔍 Я мониторю биржу 24/7 и мгновенно присылаю тебе свежие заказы.\n\n"
"⚠️ Нажимая кнопку «Подписаться», вы принимаете условия "
"Нажимая кнопку «Подписаться», вы принимаете условия "
"<a href='https://telegra.ph/Polzovatelskoe-soglashenie-i-Oferta-qwork-parse-bot-03-28'>публичной оферты</a>."
)
await message.answer(
text,
reply_markup=builder.as_markup(),
parse_mode="HTML",
disable_web_page_preview=True
await message.answer(text, reply_markup=builder.as_markup(), disable_web_page_preview=True)
@dp.message(Command("profile"))
async def show_profile(message: Message):
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")
async def subscribe_handler(callback: CallbackQuery):
user_id = callback.from_user.id
print("User ID:", user_id)
await db.add_user(user_id)
users = await db.get_all()
print("All users in DB:", users)
async def subscribe_handler(callback: CallbackQuery, state: FSMContext):
await db.add_user(callback.from_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}"))
# Добавляем кнопку своего варианта
builder.row(InlineKeyboardButton(text="⌨️ Свой вариант", callback_data="sphere_other"))
builder.adjust(2)
await callback.message.edit_text(
"✅ <b>Вы успешно подписались на уведомления!</b>",
parse_mode="HTML"
"Отлично! Давай настроим профиль.\n<b>В какой сфере IT ты работаешь?</b>",
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:
bot = Bot(token=TOKEN, default=DefaultBotProperties(parse_mode=ParseMode.HTML))
dp.startup.register(on_startup)
await dp.start_polling(bot)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
asyncio.run(main())

View File

@@ -9,7 +9,10 @@ class Database:
await db.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
user_id INTEGER UNIQUE
user_id INTEGER UNIQUE,
sphere TEXT,
language TEXT,
preferences TEXT
)
""")
await db.commit()
@@ -22,8 +25,22 @@ class Database:
)
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 with aiosqlite.connect(self.db_path) as db:
async with db.execute("SELECT * FROM users") as cursor:
rows = await cursor.fetchall()
return rows
return await cursor.fetchall()
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()