diff --git a/telegram_bot_project/bot/buttons.py b/telegram_bot_project/bot/buttons.py index 09756b4..5fe7e8f 100644 --- a/telegram_bot_project/bot/buttons.py +++ b/telegram_bot_project/bot/buttons.py @@ -50,4 +50,13 @@ def idea_reply_keyboard() -> ReplyKeyboardMarkup: idea_reply_keyboard.keyboard.append([button_update, button_all_ideas]) idea_reply_keyboard.keyboard.append([button_menu]) - return idea_reply_keyboard \ No newline at end of file + return idea_reply_keyboard + +def task_reply_keyboard() -> InlineKeyboardMarkup: + inline_markup = InlineKeyboardMarkup(inline_keyboard=[], row_width=2) + + button_yes: InlineKeyboardButton = InlineKeyboardButton(text=BUTTON_YES, callback_data="yes_task") + button_no: InlineKeyboardButton = InlineKeyboardButton(text=BUTTON_NO, callback_data="no_task") + + inline_markup.inline_keyboard.append([button_yes, button_no]) + return inline_markup \ No newline at end of file diff --git a/telegram_bot_project/bot/callbacks.py b/telegram_bot_project/bot/callbacks.py index 64de294..dbd8af4 100644 --- a/telegram_bot_project/bot/callbacks.py +++ b/telegram_bot_project/bot/callbacks.py @@ -5,7 +5,10 @@ from bot.buttons import menu_reply_keyboard, idea_reply_keyboard from messages import MESSAGES from service.idea import IdeaService +from service.task import TaskService from service.user import UserService +from states import DialogStates + async def start_callback_language(callback_query: types.CallbackQuery) -> None: await callback_query.answer() @@ -75,3 +78,32 @@ async def callback_idea_process(callback_query: types.CallbackQuery, state: FSMC case _: print(f"--[INFO] - User {user_id} ({user_name}) sent invalid callback: {callback_query.data}") await callback_query.message.answer(MESSAGES[language]["IDEA_PROBLEM"], reply_markup=idea_reply_keyboard()) + +async def callback_task_deadline(callback_query: types.CallbackQuery, state: FSMContext) -> None: + await callback_query.answer() + + user_id: int = callback_query.from_user.id + user_name: str = callback_query.from_user.username or "unknown" + user_find: Optional[dict] = await UserService.get_user_by_id(user_id) + language: str = await UserService.get_user_language(user_id) + if not language: + language = 'ENGLISH' + if not user_find: + await callback_query.message.answer(MESSAGES['ENGLISH']["AUTHORIZATION_PROBLEM"]) + return + + match callback_query.data: + case "yes_task": + await state.set_state(DialogStates.task_deadline) + await callback_query.message.answer(MESSAGES[language]["TASK_DEADLINE_YES"]) + case "no_task": + data = await state.get_data() + saved_task = data.get("task") + print(f"--[INFO] - User {user_id} ({user_name}) saved task: {saved_task}") + + await TaskService.create_task(user_id, saved_task, False) + await callback_query.message.answer(MESSAGES[language]["TASK_DEADLINE_NO"], reply_markup=menu_reply_keyboard()) + await state.clear() + case _: + print(f"--[INFO] - User {user_id} ({user_name}) sent invalid callback: {callback_query.data}") + await callback_query.message.answer(MESSAGES[language]["TASK_DEADLINE_INVALID"]) \ No newline at end of file diff --git a/telegram_bot_project/bot/commands.py b/telegram_bot_project/bot/commands.py index 71a33b7..3d0b975 100644 --- a/telegram_bot_project/bot/commands.py +++ b/telegram_bot_project/bot/commands.py @@ -118,3 +118,16 @@ async def update_idea_command(message: types.Message, state: FSMContext): await message.answer(MESSAGES[language]['UPDATE_IDEA']) await state.set_state(DialogStates.update_idea) +# Create Task Handler +async def task_command(message: types.Message, state: FSMContext): + user_id: int = message.from_user.id + user_find: Any = await UserService.get_user_by_id(user_id) + language: str = await UserService.get_user_language(user_id) + + if not user_find: + await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM']) + else: + print(f"--[INFO] - User with id: {user_id} - opened /task.") + + await message.answer(MESSAGES[language]['TASK_ADD']) + await state.set_state(DialogStates.confirm_task) \ No newline at end of file diff --git a/telegram_bot_project/bot/handlers.py b/telegram_bot_project/bot/handlers.py index a8529e3..266d279 100644 --- a/telegram_bot_project/bot/handlers.py +++ b/telegram_bot_project/bot/handlers.py @@ -1,9 +1,10 @@ from aiogram.fsm.context import FSMContext from aiogram.types import Message -from bot.buttons import get_idea_conf_keyboard, menu_reply_keyboard, idea_reply_keyboard +from bot.buttons import get_idea_conf_keyboard, menu_reply_keyboard, idea_reply_keyboard, task_reply_keyboard from messages import MESSAGES from service.idea import IdeaService +from service.task import TaskService from service.user import UserService from states import DialogStates @@ -146,3 +147,46 @@ async def process_save_updated_idea_text(message: Message, state: FSMContext): ) await state.clear() + +async def process_task_save(message: Message, state: FSMContext): + user_id = message.from_user.id + user_find = await UserService.get_user_by_id(user_id) + language = await UserService.get_user_language(user_id) or "ENGLISH" + if not user_find: + await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM']) + return + else: + task = message.text.strip() + print(f"--[INFO] User with id: {user_id} provided task: {task}") + + await message.answer(MESSAGES[language]['TASK_DEADLINE_ASK'], reply_markup=task_reply_keyboard()) + await state.update_data(task=task) + +from datetime import datetime + +async def process_task_deadline(message: Message, state: FSMContext): + user_id = message.from_user.id + user_find = await UserService.get_user_by_id(user_id) + language = await UserService.get_user_language(user_id) or "ENGLISH" + + if not user_find: + await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM']) + return + + data = await state.get_data() + task = data.get("task") + + deadline_str = message.text.strip() + + try: + time_obj = datetime.strptime(deadline_str, "%H:%M").time() + deadline_dt = datetime.combine(datetime.now().date(), time_obj) + + print(f"--[INFO] User with id: {user_id} provided deadline: {deadline_dt}") + + await TaskService.create_task(user_id, task, False, deadline_dt) + await message.answer(MESSAGES[language]['TASK_SAVED'], reply_markup=menu_reply_keyboard()) + await state.clear() + + except ValueError: + await message.answer(MESSAGES[language]['TASK_DEADLINE_INVALID']) diff --git a/telegram_bot_project/main.py b/telegram_bot_project/main.py index 270a415..537c829 100644 --- a/telegram_bot_project/main.py +++ b/telegram_bot_project/main.py @@ -6,7 +6,7 @@ from config import TOKEN from bot.commands import * from bot.handlers import * -from bot.callbacks import start_callback_language, callback_idea_process +from bot.callbacks import start_callback_language, callback_idea_process, callback_task_deadline from messages import * from states import DialogStates @@ -50,8 +50,8 @@ async def update_idea(message: Message, state: FSMContext): await update_idea_command(message, state) @dp.message(Command("task")) -async def task(message: Message): - pass +async def task(message: Message, state: FSMContext): + await task_command(message, state) @dp.callback_query(F.data.in_({"lang_ua", "lang_en"})) async def callback_language(callback_query: CallbackQuery): @@ -61,6 +61,10 @@ async def callback_language(callback_query: CallbackQuery): async def callback_idea(callback_query: CallbackQuery, state: FSMContext): await callback_idea_process(callback_query, state) +@dp.callback_query(F.data.in_({"yes_task", "no_task"})) +async def callback_idea(callback_query: CallbackQuery, state: FSMContext): + await callback_task_deadline(callback_query, state) + @dp.message() async def process_fallback(message: Message, state: FSMContext): current_state = await state.get_state() @@ -73,6 +77,10 @@ async def process_fallback(message: Message, state: FSMContext): await process_idea_update(message, state) elif current_state == DialogStates.waiting_for_update_text: await process_save_updated_idea_text(message, state) + elif current_state == DialogStates.confirm_task: + await process_task_save(message, state) + elif current_state == DialogStates.task_deadline: + await process_task_deadline(message, state) # Main Function async def main(): diff --git a/telegram_bot_project/messages.py b/telegram_bot_project/messages.py index 7076fb9..ba3f524 100644 --- a/telegram_bot_project/messages.py +++ b/telegram_bot_project/messages.py @@ -28,6 +28,12 @@ "IDEA_DELETED": "🗑️ Ідею №{} '{}' було видалено.", "ASK_NEW_IDEA_TEXT": "✏️ Введіть новий текст для ідеї №{} '{}'.", "IDEA_UPDATED": "✅ Ідею №{} успішно оновлено.", + "TASK_ADD": "Вкажіть назву завдання та натисніть кнопку нижче, щоб продовжити", + "TASK_DEADLINE_ASK": "Це завдання має крайній термін?", + "TASK_DEADLINE_YES": "Будьласка введіть годину (дедлайн) для задачі.\nПриклад: 13:10", + "TASK_DEADLINE_NO": "Гаразд, без крайнього терміну. Ваше завдання збережено.", + "TASK_DEADLINE_INVALID": "Недійсний термін. Будь ласка, спробуйте ще раз.", + "TASK_SAVED": "Задачу збережено.", "LANGUAGE_ASK": ( "🌐 **Оберіть мову інтерфейсу:**\n" "Натисніть кнопку нижче, щоб продовжити:" @@ -68,6 +74,12 @@ "IDEA_DELETED": "🗑️ Idea #{} '{}' has been deleted.", "ASK_NEW_IDEA_TEXT": "✏️ Please enter the new text for idea #{} '{}'.", "IDEA_UPDATED": "✅ Idea №{} updated successfully.", + "TASK_ADD": "Provide a task name and press the button below to continue", + "TASK_DEADLINE_ASK": "This task have a deadline?", + "TASK_DEADLINE_YES": "Please enter the time (deadline) for the task.\nExample: 13:10", + "TASK_DEADLINE_NO": "Ok, no deadline. Your task saved.", + "TASK_DEADLINE_INVALID": "Invalid deadline. Please try again.", + "TASK_SAVED": "Task saved successfully.", "LANGUAGE_ASK": ( "🌐 **Please choose your interface language:**\n" "Tap a button below to continue:" @@ -96,3 +108,5 @@ MENU_BUTTON: str = "📂 Main Menu" UPDATE_IDEA_BUTTON: str = "✏️ Update Idea" ALL_IDEAS: str = "📋 View All Ideas" +BUTTON_YES: str = "Yes" +BUTTON_NO: str = "No" diff --git a/telegram_bot_project/states.py b/telegram_bot_project/states.py index 8839600..c93c925 100644 --- a/telegram_bot_project/states.py +++ b/telegram_bot_project/states.py @@ -5,4 +5,6 @@ class DialogStates(StatesGroup): confirm_idea = State() delete_idea = State() update_idea = State() - waiting_for_update_text = State() \ No newline at end of file + waiting_for_update_text = State() + confirm_task = State() + task_deadline = State() \ No newline at end of file