Skip to content

Commit 10ed9e1

Browse files
authored
Merge pull request #9 from gnatykdm/Idea-Configuration
Idea-Configuration[Idea-Saving-Implementation] C:2
2 parents 8101b3f + 34f6717 commit 10ed9e1

File tree

9 files changed

+152
-38
lines changed

9 files changed

+152
-38
lines changed

telegram_bot_project/bot/commands.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
from typing import Any
22
from aiogram import types
3+
from aiogram.fsm.context import FSMContext
4+
35
from messages import MESSAGES
46
from service.user import UserService
57
from bot.buttons import get_language_keyboard, menu_reply_keyboard
8+
from states import DialogStates
9+
610

711
# Start Command Handler
812
async def start_command(message: types.Message):
@@ -36,7 +40,7 @@ async def language_command(message: types.Message):
3640
user_find = await UserService.get_user_by_id(user_id)
3741
language: str = await UserService.get_user_language(user_id)
3842
if not user_find:
39-
await message.answer(MESSAGES[language]['AUTHORIZATION_PROBLEM'])
43+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
4044
else:
4145
keyboard = get_language_keyboard()
4246
await message.answer(MESSAGES[language]['LANGUAGE_ASK'], reply_markup=keyboard)
@@ -47,10 +51,20 @@ async def menu_command(message: types.Message):
4751
user_find: Any = await UserService.get_user_by_id(user_id)
4852
language: str = await UserService.get_user_language(user_id)
4953
if not user_find:
50-
await message.answer(MESSAGES[language]['AUTHORIZATION_PROBLEM'])
54+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
5155
else:
5256
await message.answer(MESSAGES[language]['MENU_MSG'], reply_markup=menu_reply_keyboard())
5357

5458
# Idea Command Handler
55-
async def idea_command(message: types.Message):
56-
pass
59+
async def idea_command(message: types.Message, state: FSMContext):
60+
user_id: int = message.from_user.id
61+
user_find: Any = await UserService.get_user_by_id(user_id)
62+
language: str = await UserService.get_user_language(user_id)
63+
64+
print(f"--[INFO] - User with id: {user_id} - opened /idea.")
65+
if not user_find:
66+
await message.answer(MESSAGES['ENGLISH']['AUTHORIZATION_PROBLEM'])
67+
else:
68+
await message.answer(MESSAGES[language]['IDEA_RESPONSE'])
69+
await state.set_state(DialogStates.waiting_for_idea)
70+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from aiogram.fsm.context import FSMContext
2+
from aiogram.types import Message
3+
4+
from bot.buttons import menu_reply_keyboard
5+
from messages import MESSAGES
6+
from service.idea import IdeaService
7+
from service.user import UserService
8+
9+
async def process_idea_save(message: Message, state: FSMContext) -> None:
10+
user_id = message.from_user.id
11+
user_name = message.from_user.username or "unknown"
12+
13+
user_find = await UserService.get_user_by_id(user_id)
14+
if not user_find or not user_find.get("id"):
15+
await message.answer(MESSAGES["ENGLISH"]['AUTHORIZATION_PROBLEM'])
16+
return
17+
18+
language = await UserService.get_user_language(user_id)
19+
idea = message.text
20+
21+
print(f"--[INFO] User with id: {user_id} - provide idea.")
22+
try:
23+
await IdeaService.create_user_idea(user_id, idea)
24+
print(f"--[INFO] - User {user_id} ({user_name}) saved idea: {idea}")
25+
await message.answer(MESSAGES[language]['IDEA_SAVED'], reply_markup=menu_reply_keyboard())
26+
await state.clear()
27+
except Exception as e:
28+
print(f"[ERROR] Saving idea failed: {e}")
29+
await message.answer(MESSAGES[language].get('ERROR_SAVING_IDEA', 'Ошибка при сохранении идеи. Попробуйте позже.'))

telegram_bot_project/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from dotenv import load_dotenv
33
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
44
from sqlalchemy.orm import sessionmaker
5+
from contextlib import asynccontextmanager
56

67
load_dotenv()
78

@@ -19,6 +20,7 @@
1920
def get_token() -> str:
2021
return TOKEN
2122

23+
@asynccontextmanager
2224
async def get_session() -> AsyncSession:
2325
async with async_session() as session:
2426
yield session

telegram_bot_project/main.py

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import asyncio
2-
from aiogram import Dispatcher, Bot
2+
from aiogram import Dispatcher, Bot, F
33
from aiogram.filters import Command
4+
from aiogram.fsm.context import FSMContext
45
from aiogram.fsm.storage.memory import MemoryStorage
56
from aiogram.types import Message, CallbackQuery
67
from config import TOKEN
7-
from bot.commands import start_command, help_command, menu_command, language_command
8+
from bot.commands import start_command, help_command, menu_command, language_command, idea_command
9+
from bot.handlers import process_idea_save
810
from bot.callbacks import start_callback_language
11+
from states import DialogStates
912

10-
dp = Dispatcher(storage=MemoryStorage())
13+
storage: MemoryStorage = MemoryStorage()
14+
dp = Dispatcher(storage=storage)
1115

1216
# Command Handlers
1317
@dp.message(Command("start"))
@@ -26,10 +30,21 @@ async def menu(message: Message):
2630
async def language(message: Message):
2731
await language_command(message)
2832

29-
@dp.callback_query(lambda c: c.data in ["lang_ua", "lang_en"])
33+
@dp.message(Command("idea"))
34+
async def idea(message: Message, state: FSMContext):
35+
await idea_command(message, state)
36+
37+
@dp.callback_query(F.data.in_({"lang_ua", "lang_en"}))
3038
async def callback_language(callback_query: CallbackQuery):
3139
await start_callback_language(callback_query)
3240

41+
@dp.message()
42+
async def process_idea_fallback(message: Message, state: FSMContext):
43+
current_state = await state.get_state()
44+
print(f"[DEBUG] Current state: {current_state}")
45+
if current_state == DialogStates.waiting_for_idea.state:
46+
await process_idea_save(message, state)
47+
3348
# Main Function
3449
async def main():
3550
bot = Bot(token=TOKEN)

telegram_bot_project/messages.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"SETTINGS_RESPONSE": "🔧 Відкриваю налаштування...",
1313
"MYDAY_RESPONSE": "📅 Ось ваш план на сьогодні...",
1414
"IDEA_RESPONSE": "💡 Поділіться своєю ідеєю, я все запишу!",
15+
"IDEA_SAVED": "💡 Ідея успішно збережена.",
1516
"ADD_TASK_RESPONSE": "📝 Створюємо нову задачу...",
1617
"LANGUAGE_ASK": (
1718
"🌐 **Оберіть мову інтерфейсу:**\n"
@@ -37,6 +38,7 @@
3738
"SETTINGS_RESPONSE": "🔧 Opening your settings...",
3839
"MYDAY_RESPONSE": "📅 Here’s your plan for today...",
3940
"IDEA_RESPONSE": "💡 Tell me your idea, I’ll save it for you!",
41+
"IDEA_SAVED": "💡 Idea saved successfully.",
4042
"ADD_TASK_RESPONSE": "📝 Creating a new task...",
4143
"LANGUAGE_ASK": (
4244
"🌐 **Choose your language:**\n"
Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,63 @@
11
from sqlalchemy import text
22
from config import get_session
33

4-
# Must implement later :)
54
class IdeaService:
6-
pass
5+
@staticmethod
6+
async def create_user_idea(user_id: int, idea_name: str) -> int:
7+
async with get_session() as session:
8+
query = text("""
9+
INSERT INTO ideas (user_id, idea_name)
10+
VALUES (:user_id, :idea_name)
11+
RETURNING id
12+
""")
13+
result = await session.execute(query, {
14+
"user_id": user_id,
15+
"idea_name": idea_name
16+
})
17+
await session.commit()
18+
return result.scalar()
19+
20+
@staticmethod
21+
async def update_user_idea(idea_id: int, new_name: str) -> None:
22+
async with get_session() as session:
23+
query = text("""
24+
UPDATE ideas
25+
SET idea_name = :new_name
26+
WHERE id = :idea_id
27+
""")
28+
await session.execute(query, {
29+
"idea_id": idea_id,
30+
"new_name": new_name
31+
})
32+
await session.commit()
33+
34+
@staticmethod
35+
async def delete_user_idea(idea_id: int) -> None:
36+
async with get_session() as session:
37+
query = text("""
38+
DELETE FROM ideas
39+
WHERE id = :idea_id
40+
""")
41+
await session.execute(query, {"idea_id": idea_id})
42+
await session.commit()
43+
44+
@staticmethod
45+
async def get_all_ideas_by_user_id(user_id: int) -> list[dict]:
46+
async with get_session() as session:
47+
query = text("""
48+
SELECT id, idea_name, creation_date
49+
FROM ideas
50+
WHERE user_id = :user_id
51+
ORDER BY creation_date DESC
52+
""")
53+
result = await session.execute(query, {"user_id": user_id})
54+
rows = result.fetchall()
55+
ideas = [
56+
{
57+
"id": row.id,
58+
"idea_name": row.idea_name,
59+
"creation_date": row.creation_date
60+
}
61+
for row in rows
62+
]
63+
return ideas

telegram_bot_project/service/task.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
class TaskService:
77
@staticmethod
88
async def create_task(user_id: int, task_name: str, task_status: bool = False, start_time: Optional[datetime] = None) -> int:
9-
async for session in get_session():
9+
async with get_session() as session:
1010
result: Any = await session.execute(
1111
text(
1212
"""
@@ -25,11 +25,10 @@ async def create_task(user_id: int, task_name: str, task_status: bool = False, s
2525
task_id: int = result.scalar_one()
2626
await session.commit()
2727
return task_id
28-
return None
2928

3029
@staticmethod
3130
async def get_task_by_id(task_id: int) -> Optional[dict]:
32-
async for session in get_session():
31+
async with get_session() as session:
3332
result: Any = await session.execute(
3433
text(
3534
"""
@@ -40,7 +39,7 @@ async def get_task_by_id(task_id: int) -> Optional[dict]:
4039
),
4140
{"task_id": task_id}
4241
)
43-
task: int = result.fetchone()
42+
task = result.fetchone()
4443
if task:
4544
return {
4645
"id": task.id,
@@ -51,11 +50,10 @@ async def get_task_by_id(task_id: int) -> Optional[dict]:
5150
"creation_date": task.creation_date
5251
}
5352
return None
54-
return None
5553

5654
@staticmethod
5755
async def get_user_tasks(user_id: int) -> List[dict]:
58-
async for session in get_session():
56+
async with get_session() as session:
5957
result: Any = await session.execute(
6058
text(
6159
"""
@@ -67,6 +65,7 @@ async def get_user_tasks(user_id: int) -> List[dict]:
6765
),
6866
{"user_id": user_id}
6967
)
68+
tasks = result.fetchall()
7069
return [
7170
{
7271
"id": task.id,
@@ -76,23 +75,22 @@ async def get_user_tasks(user_id: int) -> List[dict]:
7675
"start_time": task.start_time,
7776
"creation_date": task.creation_date
7877
}
79-
for task in result.fetchall()
78+
for task in tasks
8079
]
81-
return None
8280

8381
@staticmethod
8482
async def update_task(task_id: int, task_name: Optional[str] = None,
85-
status: Optional[bool] = None,
86-
start_time: Optional[datetime] = None) -> bool:
87-
async for session in get_session():
83+
status: Optional[bool] = None,
84+
start_time: Optional[datetime] = None) -> bool:
85+
async with get_session() as session:
8886
exists: Any = await session.execute(
8987
text("SELECT 1 FROM tasks WHERE id = :task_id"),
9088
{"task_id": task_id}
9189
)
9290
if not exists.scalar():
9391
return False
9492

95-
update_fields: Any = {}
93+
update_fields: dict = {}
9694
if task_name is not None:
9795
update_fields["task_name"] = task_name
9896
if status is not None:
@@ -101,7 +99,7 @@ async def update_task(task_id: int, task_name: Optional[str] = None,
10199
update_fields["start_time"] = start_time
102100

103101
if update_fields:
104-
query: Any = text(
102+
query = text(
105103
f"""
106104
UPDATE tasks
107105
SET {', '.join(f'{k} = :{k}' for k in update_fields.keys())}
@@ -112,11 +110,10 @@ async def update_task(task_id: int, task_name: Optional[str] = None,
112110
await session.execute(query, update_fields)
113111
await session.commit()
114112
return True
115-
return None
116113

117114
@staticmethod
118115
async def delete_task(task_id: int) -> bool:
119-
async for session in get_session():
116+
async with get_session() as session:
120117
result: Any = await session.execute(
121118
text(
122119
"""
@@ -127,14 +124,13 @@ async def delete_task(task_id: int) -> bool:
127124
),
128125
{"task_id": task_id}
129126
)
130-
deleted: Any = result.scalar_one_or_none()
127+
deleted = result.scalar_one_or_none()
131128
await session.commit()
132129
return deleted is not None
133-
return None
134130

135131
@staticmethod
136132
async def toggle_task_status(task_id: int) -> bool:
137-
async for session in get_session():
133+
async with get_session() as session:
138134
result: Any = await session.execute(
139135
text(
140136
"""
@@ -146,7 +142,6 @@ async def toggle_task_status(task_id: int) -> bool:
146142
),
147143
{"task_id": task_id}
148144
)
149-
updated: Any = result.scalar_one_or_none()
145+
updated = result.scalar_one_or_none()
150146
await session.commit()
151147
return updated is not None
152-
return None

telegram_bot_project/service/user.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
class UserService:
55
@staticmethod
66
async def create_user(user_id: int, user_name: str, language: str = "ENGLISH") -> int:
7-
async for session in get_session():
7+
async with get_session() as session:
88
result = await session.execute(
99
text("""
1010
INSERT INTO users (id, user_name, language)
@@ -16,22 +16,20 @@ async def create_user(user_id: int, user_name: str, language: str = "ENGLISH") -
1616
await session.commit()
1717
inserted_id = result.scalar_one()
1818
return inserted_id
19-
return None
2019

2120
@staticmethod
2221
async def get_user_by_id(user_id: int):
23-
async for session in get_session():
22+
async with get_session() as session:
2423
result = await session.execute(
2524
text("SELECT * FROM users WHERE id = :id"),
2625
{"id": user_id}
2726
)
2827
row = result.first()
2928
return dict(row._mapping) if row else None
30-
return None
3129

3230
@staticmethod
3331
async def update_user_language(user_id: int, new_language: str) -> bool:
34-
async for session in get_session():
32+
async with get_session() as session:
3533
result = await session.execute(
3634
text("""
3735
UPDATE users
@@ -42,14 +40,12 @@ async def update_user_language(user_id: int, new_language: str) -> bool:
4240
)
4341
await session.commit()
4442
return result.rowcount == 1
45-
return None
4643

4744
@staticmethod
4845
async def get_user_language(user_id: int) -> str:
49-
async for session in get_session():
46+
async with get_session() as session:
5047
result = await session.execute(
5148
text("SELECT language FROM users WHERE id = :id"),
5249
{"id": user_id}
5350
)
5451
return result.scalar_one_or_none()
55-
return None

0 commit comments

Comments
 (0)