Skip to content

Commit 27292a0

Browse files
authored
Merge pull request #26 from gnatykdm/Settings-Configuration
Settings configuration
2 parents 82163fa + b80ad51 commit 27292a0

File tree

10 files changed

+327
-120
lines changed

10 files changed

+327
-120
lines changed

sql/schema.sql

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,6 @@ CREATE TABLE routines (
2121
routine_name VARCHAR(255) NOT NULL
2222
);
2323

24-
CREATE TABLE routine_steps (
25-
id SERIAL PRIMARY KEY,
26-
routine_id INT NOT NULL REFERENCES routines(id) ON DELETE CASCADE,
27-
step_order INT NOT NULL,
28-
step_description TEXT NOT NULL,
29-
UNIQUE(routine_id, step_order)
30-
);
31-
3224
-- TABLE tasks
3325
CREATE TABLE tasks (
3426
id SERIAL PRIMARY KEY,

telegram_bot_project/bot/buttons.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,43 @@ def routine_menu_keyboard() -> InlineKeyboardMarkup:
113113

114114
routine_markup.inline_keyboard.append([morning_routine_btn, evening_routine_btn])
115115

116-
return routine_markup
116+
return routine_markup
117+
118+
def morning_routine_keyboard() -> ReplyKeyboardMarkup:
119+
add_btn = KeyboardButton(text=MORNINGG_ROUTINE_ADD_BTN)
120+
edit_btn = KeyboardButton(text=MORNING_ROUTINE_EDIT_BTN)
121+
drop_btn = KeyboardButton(text=MORNING_ROUTINE_DELETE_BTN)
122+
all_btn = KeyboardButton(text=MY_MORNING_ROUTINE_BTN)
123+
settings_btn = KeyboardButton(text=BUTTON_SETTINGS)
124+
125+
keyboard = [
126+
[add_btn, edit_btn],
127+
[drop_btn, all_btn],
128+
[settings_btn]
129+
]
130+
131+
return ReplyKeyboardMarkup(
132+
keyboard=keyboard,
133+
resize_keyboard=True,
134+
row_width=2
135+
)
136+
137+
138+
def evening_routine_keyboard() -> ReplyKeyboardMarkup:
139+
add_btn = KeyboardButton(text=EVENING_ROUTINE_ADD_BTN)
140+
edit_btn = KeyboardButton(text=EVENING_ROUTINE_EDIT_BTN)
141+
drop_btn = KeyboardButton(text=EVENING_ROUTINE_DELETE_BTN)
142+
all_btn = KeyboardButton(text=MY_EVENING_ROUTINE_BTN)
143+
settings_btn = KeyboardButton(text=BUTTON_SETTINGS)
144+
145+
keyboard = [
146+
[add_btn, edit_btn],
147+
[drop_btn, all_btn],
148+
[settings_btn]
149+
]
150+
151+
return ReplyKeyboardMarkup(
152+
keyboard=keyboard,
153+
resize_keyboard=True,
154+
row_width=2
155+
)

telegram_bot_project/bot/callbacks.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
from aiogram import types
33
from aiogram.fsm.context import FSMContext
44

5-
from bot.buttons import menu_reply_keyboard, idea_reply_keyboard, task_menu_keyboard
5+
from bot.buttons import *
66
from messages import MESSAGES
77
from service.idea import IdeaService
88
from service.task import TaskService
99
from service.user import UserService
1010
from states import DialogStates
1111

12-
1312
async def start_callback_language(callback_query: types.CallbackQuery) -> None:
1413
await callback_query.answer()
1514

@@ -106,4 +105,24 @@ async def callback_task_deadline(callback_query: types.CallbackQuery, state: FSM
106105
await state.clear()
107106
case _:
108107
print(f"--[INFO] - User {user_id} ({user_name}) sent invalid callback: {callback_query.data}")
109-
await callback_query.message.answer(MESSAGES[language]["TASK_DEADLINE_INVALID"])
108+
await callback_query.message.answer(MESSAGES[language]["TASK_DEADLINE_INVALID"])
109+
110+
async def callback_routines(callback_query: types.CallbackQuery) -> None:
111+
await callback_query.answer()
112+
113+
user_id: int = callback_query.from_user.id
114+
user_find: Optional[dict] = await UserService.get_user_by_id(user_id)
115+
language: str = await UserService.get_user_language(user_id)
116+
if not language:
117+
language = 'ENGLISH'
118+
if not user_find:
119+
await callback_query.message.answer(MESSAGES['ENGLISH']["AUTHORIZATION_PROBLEM"])
120+
return
121+
122+
match callback_query.data:
123+
case "morning_view":
124+
await callback_query.message.answer(MESSAGES[language]['MORNING_ROUTINE'], reply_markup=morning_routine_keyboard())
125+
case "evening_view":
126+
await callback_query.message.answer(MESSAGES[language]['EVENING_ROUTINE'], reply_markup=evening_routine_keyboard())
127+
case _:
128+
await callback_query.message.answer(MESSAGES[language]["ROUTINES_INVALID"])

telegram_bot_project/bot/commands.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from bot.utills import format_date, calculate_awake_hours
77
from messages import MESSAGES
88
from service.idea import IdeaService
9+
from service.routine import RoutineService
910
from service.task import TaskService
1011
from service.user import UserService
1112
from bot.buttons import *
@@ -290,4 +291,84 @@ async def routine_menu_command(message: types.Message):
290291
if not user_find:
291292
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
292293
else:
293-
await message.answer(MESSAGES[language]['ROUTINE_MENU_DAY'], reply_markup=routine_menu_keyboard())
294+
await message.answer(MESSAGES[language]['ROUTINE_MENU_DAY'], reply_markup=routine_menu_keyboard())
295+
296+
# Set Morning Routine Command Handler
297+
async def set_morning_routine(message: types.Message, state: FSMContext):
298+
user_id: int = message.from_user.id
299+
user_find: Any = await UserService.get_user_by_id(user_id)
300+
language: str = await UserService.get_user_language(user_id) or "ENGLISH"
301+
302+
if not user_find:
303+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
304+
else:
305+
await message.answer(MESSAGES[language]['ADD_MORNING_ROUTINE'])
306+
await state.set_state(DialogStates.add_morning_routine)
307+
308+
async def show_morning_routines(message: types.Message):
309+
user_id: int = message.from_user.id
310+
user_find: Any = await UserService.get_user_by_id(user_id)
311+
language: str = await UserService.get_user_language(user_id) or "ENGLISH"
312+
313+
if not user_find:
314+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
315+
return
316+
317+
print(f"--[INFO] - User with id: {user_id} - opened /morning_routines.")
318+
morning_routine = await RoutineService.get_user_routines(user_id, routine_type="morning")
319+
if not morning_routine:
320+
await message.answer(MESSAGES[language]['NO_MORNING_ROUTINE'])
321+
return
322+
323+
dividers: str = "\n" + ("-" * int(len(MESSAGES[language]['MORNING_ROUTINE_SHOW']) * 1.65))
324+
325+
formatted_routine_items = "\n".join(
326+
f"# {idx}. {routine['routine_name']}"
327+
for idx, routine in enumerate(morning_routine, start=1)
328+
)
329+
330+
formatted_morning_routine = (
331+
MESSAGES[language]['MORNING_ROUTINE_SHOW'] +
332+
dividers +
333+
"\n" +
334+
formatted_routine_items
335+
)
336+
337+
await message.answer(formatted_morning_routine, reply_markup=morning_routine_keyboard())
338+
339+
# Delete Morning Routine Command Handler
340+
async def delete_morning_routine(message: types.Message, state: FSMContext):
341+
user_id: int = message.from_user.id
342+
user_find: Any = await UserService.get_user_by_id(user_id)
343+
language: str = await UserService.get_user_language(user_id) or "ENGLISH"
344+
345+
if not user_find:
346+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
347+
else:
348+
349+
morning_routine = await RoutineService.get_user_routines(user_id, routine_type="morning")
350+
if not morning_routine:
351+
await message.answer(MESSAGES[language]['NO_MORNING_ROUTINE'])
352+
return
353+
354+
await message.answer(MESSAGES[language]['PROVIDE_ROUTINE_ID'])
355+
await state.update_data(morning_routine=morning_routine)
356+
await state.set_state(DialogStates.delete_morning_routine)
357+
358+
# Update Morning Routine Command Handler
359+
async def update_morning_routine(message: types.Message, state: FSMContext):
360+
user_id: int = message.from_user.id
361+
user_find: Any = await UserService.get_user_by_id(user_id)
362+
language: str = await UserService.get_user_language(user_id) or "ENGLISH"
363+
364+
if not user_find:
365+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
366+
else:
367+
morning_routine = await RoutineService.get_user_routines(user_id, routine_type="morning")
368+
if not morning_routine:
369+
await message.answer(MESSAGES[language]['NO_MORNING_ROUTINE'])
370+
return
371+
else:
372+
await message.answer(MESSAGES[language]['NEW_ROUTINE_NAME'])
373+
await state.update_data(morning_routine=morning_routine)
374+
await state.set_state(DialogStates.update_morning_routine_id)

telegram_bot_project/bot/handlers.py

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from aiogram.fsm.context import FSMContext
2-
from aiogram.types import Message
2+
from aiogram.types import Message, message
33

44
from bot.buttons import *
55
from messages import MESSAGES
66
from service.idea import IdeaService
77
from service.task import TaskService
88
from service.user import UserService
99
from states import DialogStates
10-
from bot.utills import check_valid_time
10+
from service.routine import RoutineService
11+
from bot.utills import check_valid_time, validate_text
1112

1213
async def process_idea_save(message: Message, state: FSMContext) -> None:
1314
user_id = message.from_user.id
@@ -367,4 +368,102 @@ async def process_set_sleep_time(message: Message, state: FSMContext):
367368
MESSAGES[language]['SLEEP_TIME_SET'].format(new_sleep_time),
368369
reply_markup=routine_time_keyboard()
369370
)
370-
await state.clear()
371+
await state.clear()
372+
373+
async def process_set_routine_time(message: Message, state: FSMContext):
374+
user_id = message.from_user.id
375+
user_find = await UserService.get_user_by_id(user_id)
376+
language = await UserService.get_user_language(user_id) or "ENGLISH"
377+
378+
if not user_find:
379+
await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM'])
380+
return
381+
382+
routine_title: str = message.text.strip()
383+
if not validate_text(routine_title):
384+
await message.answer(MESSAGES[language]['INVALID_MORNING_ROUTINE'], reply_markup=morning_routine_keyboard())
385+
return
386+
387+
try:
388+
await RoutineService.create_routine(user_id, routine_type="morning", routine_name=routine_title)
389+
390+
print(f"User with id: {user_id} set routine title: {routine_title}")
391+
await message.answer(MESSAGES[language]['ROUTINE_SAVED'].format(routine_title), reply_markup=morning_routine_keyboard())
392+
await state.clear()
393+
except:
394+
await message.answer(MESSAGES[language]['ROUTINE_EXISTS'], reply_markup=morning_routine_keyboard())
395+
396+
async def process_delete_morning_routine(message: Message, state: FSMContext):
397+
user_id = message.from_user.id
398+
user_find = await UserService.get_user_by_id(user_id)
399+
language = await UserService.get_user_language(user_id) or "ENGLISH"
400+
401+
if not user_find:
402+
await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM'])
403+
return
404+
405+
routine_num: int = int(message.text.strip())
406+
if (routine_num < 1):
407+
await message.answer(MESSAGES[language]['COMPLETE_TASK_INVALID'], reply_markup=morning_routine_keyboard())
408+
return
409+
else:
410+
data = await state.get_data()
411+
routines = data.get("morning_routine")
412+
413+
routine_to_delete = routines[routine_num - 1]
414+
real_id = routine_to_delete["id"]
415+
416+
await RoutineService.delete_routine(real_id)
417+
print(f"User with id: {user_id} deleted routine with id: {real_id}")
418+
419+
await message.answer(MESSAGES[language]['ROUTINE_DELETED'].format(routine_num, routine_to_delete['routine_name']), reply_markup=morning_routine_keyboard())
420+
await state.clear()
421+
422+
async def process_update_morning_routine(message: Message, state: FSMContext):
423+
user_id = message.from_user.id
424+
user_find = await UserService.get_user_by_id(user_id)
425+
language = await UserService.get_user_language(user_id) or "ENGLISH"
426+
427+
if not user_find:
428+
await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM'])
429+
return
430+
431+
routine_num: int = int(message.text.strip())
432+
if (routine_num < 1):
433+
await message.answer(MESSAGES[language]['COMPLETE_TASK_INVALID'], reply_markup=morning_routine_keyboard())
434+
return
435+
else:
436+
data = await state.get_data()
437+
routines = data.get("morning_routine")
438+
439+
routine_to_update = routines[routine_num - 1]
440+
real_id = routine_to_update["id"]
441+
442+
await message.answer(MESSAGES[language]['NEW_ROUTINE_NAME'])
443+
await state.update_data(routine_id=real_id)
444+
await state.set_state(DialogStates.update_morning_routine)
445+
446+
async def process_save_updated_morning_routine(message: Message, state: FSMContext):
447+
user_id = message.from_user.id
448+
user_find = await UserService.get_user_by_id(user_id)
449+
language = await UserService.get_user_language(user_id) or "ENGLISH"
450+
451+
if not user_find:
452+
await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM'])
453+
return
454+
455+
routine_title: str = message.text.strip()
456+
if not validate_text(routine_title):
457+
await message.answer(MESSAGES[language]['INVALID_MORNING_ROUTINE'], reply_markup=morning_routine_keyboard())
458+
return
459+
460+
data = await state.get_data()
461+
routine_id = data.get("routine_id")
462+
463+
try:
464+
await RoutineService.update_routine(routine_id, routine_title)
465+
print(f"User with id: {user_id} updated routine title: {routine_title}")
466+
await message.answer(MESSAGES[language]['ROUTINE_NAME_SET'].format(routine_title), reply_markup=morning_routine_keyboard())
467+
await state.clear()
468+
except:
469+
await message.answer(MESSAGES[language]['ROUTINE_EXISTS'], reply_markup=morning_routine_keyboard())

telegram_bot_project/bot/utills.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,7 @@ def calculate_awake_hours(wake_time, sleep_time) -> str:
3030
total_hours = awake_duration.seconds // 3600
3131
total_minutes = (awake_duration.seconds % 3600) // 60
3232

33-
return f"{total_hours}h {total_minutes}m"
33+
return f"{total_hours}h {total_minutes}m"
34+
35+
def validate_text(text: str) -> bool:
36+
return text and len(text) <= 100

telegram_bot_project/main.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77
from sqlalchemy import lambda_stmt
88
from sqlalchemy.util import await_fallback
99

10-
from bot.callbacks import (
11-
start_callback_language,
12-
callback_idea_process,
13-
callback_task_deadline
14-
)
10+
from bot.callbacks import *
1511
from bot.commands import *
1612
from bot.handlers import *
1713
from config import TOKEN
@@ -153,6 +149,30 @@ async def routine(message: Message):
153149
async def routine(message: Message):
154150
await routine_menu_command(message)
155151

152+
@dp.message(lambda m: m.text == MORNINGG_ROUTINE_ADD_BTN)
153+
async def morning_add(message: Message, state: FSMContext):
154+
await set_morning_routine(message, state)
155+
156+
@dp.message(Command("morning_routines"))
157+
async def morning_routines(message: Message):
158+
await show_morning_routines(message)
159+
160+
@dp.message(lambda m: m.text == MY_MORNING_ROUTINE_BTN)
161+
async def morning_routines_show(message: types.Message):
162+
await show_morning_routines(message)
163+
164+
@dp.message(lambda m: m.text == MORNING_ROUTINE_DELETE_BTN)
165+
async def morning_routines_delete(message: types.Message, state: FSMContext):
166+
await delete_morning_routine(message, state)
167+
168+
@dp.message(lambda m: m.text == MORNING_ROUTINE_EDIT_BTN)
169+
async def morning_routines_edit(message: types.Message, state: FSMContext):
170+
await update_morning_routine(message, state)
171+
172+
@dp.callback_query(F.data.in_({"morning_view", "evening_view"}))
173+
async def callback_routine(callback_query: CallbackQuery):
174+
await callback_routines(callback_query)
175+
156176
@dp.callback_query(F.data.in_({"lang_ua", "lang_en"}))
157177
async def callback_language(callback_query: CallbackQuery):
158178
await start_callback_language(callback_query)
@@ -193,6 +213,14 @@ async def process_fallback(message: Message, state: FSMContext):
193213
await process_set_wake_time(message, state)
194214
elif current_state == DialogStates.set_sleep_time:
195215
await process_set_sleep_time(message, state)
216+
elif current_state == DialogStates.add_morning_routine:
217+
await process_set_routine_time(message, state)
218+
elif current_state == DialogStates.delete_morning_routine:
219+
await process_delete_morning_routine(message, state)
220+
elif current_state == DialogStates.update_morning_routine:
221+
await process_save_updated_morning_routine(message, state)
222+
elif current_state == DialogStates.update_morning_routine_id:
223+
await process_update_morning_routine(message, state)
196224

197225
# Main Function
198226
async def main():

0 commit comments

Comments
 (0)