feat: add create and change profile
This commit is contained in:
139
bot.py
139
bot.py
@@ -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())
|
||||||
|
|||||||
23
database.py
23
database.py
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user