Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions telegram_bot_project/.idea/dictionaries/project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion telegram_bot_project/bot/buttons.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# bot/buttons.py
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
from messages import *

Expand Down Expand Up @@ -152,4 +153,4 @@ def evening_routine_keyboard() -> ReplyKeyboardMarkup:
keyboard=keyboard,
resize_keyboard=True,
row_width=2
)
)
2 changes: 1 addition & 1 deletion telegram_bot_project/bot/callbacks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# bot/callbacks.py
from typing import Optional
from aiogram import types
from aiogram.fsm.context import FSMContext

from bot.buttons import *
Expand Down
4 changes: 1 addition & 3 deletions telegram_bot_project/bot/commands.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
# bot/commands.py
from typing import List
from aiogram import types
from aiogram.fsm.context import FSMContext

from bot.utills import format_date, calculate_awake_hours
from service.idea import IdeaService
from service.routine import RoutineService
from service.task import TaskService
from service.user import UserService
from bot.buttons import *
from states import DialogStates
from service.myday import MyDayService
Expand Down
3 changes: 1 addition & 2 deletions telegram_bot_project/bot/fallbacks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import aiogram.types as types

# bot/fallbacks.py
from bot.handlers import *
from states import DialogStates

Expand Down
6 changes: 5 additions & 1 deletion telegram_bot_project/bot/handlers.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# bot/handlers.py
from aiogram.fsm.context import FSMContext
from aiogram.types import Message
from datetime import datetime

from service.smtp import SmtpService
from bot.buttons import *
from messages import MESSAGES
from messages import *
from service.idea import IdeaService
from service.task import TaskService
from service.user import UserService
from states import DialogStates
from service.routine import RoutineService
from bot.utills import check_valid_time, validate_text
from service.myday import MyDayService
from bot.scheduler import update_user_job

async def process_idea_save(message: Message, state: FSMContext) -> None:
user_id = message.from_user.id
Expand Down Expand Up @@ -334,6 +336,7 @@ async def process_set_wake_time(message: Message, state: FSMContext):

print(f"[INFO] - User with id: {user_id} set wake time to: {new_wake_time}")
await UserService.update_wake_time(user_id, time_obj)
update_user_job(user_id, time_obj, message.bot, job_type="wake")
await message.answer(
MESSAGES[language]['TIMER_SET'].format(new_wake_time),
reply_markup=routine_time_keyboard()
Expand Down Expand Up @@ -369,6 +372,7 @@ async def process_set_sleep_time(message: Message, state: FSMContext):

print(f"[INFO] - User with id: {user_id} set sleep time to: {new_sleep_time}")
await UserService.update_sleep_time(user_id, time_obj)
update_user_job(user_id, time_obj, message.bot, job_type="sleep")
await message.answer(
MESSAGES[language]['TIMER_SET'].format(new_sleep_time),
reply_markup=routine_time_keyboard()
Expand Down
37 changes: 37 additions & 0 deletions telegram_bot_project/bot/scheduler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# bot/scheduler.py
from datetime import time
from aiogram import Bot
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from messages import send_morning_message, send_evening_message
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This import is redundant since line 6 already imports everything from messages with 'from messages import *'. Remove this duplicate import.

Suggested change
from messages import send_morning_message, send_evening_message

Copilot uses AI. Check for mistakes.

from service.user import UserService

scheduler: AsyncIOScheduler = AsyncIOScheduler()

def initialize_scheduler():
scheduler.start()
return scheduler

def update_user_job(user_id: int, when: time, bot: Bot, job_type: str):
job_id = f"{job_type}_message_{user_id}"

if scheduler.get_job(job_id):
scheduler.remove_job(job_id)

scheduler.add_job(
send_morning_message if job_type == "wake" else send_evening_message,
trigger=CronTrigger(hour=when.hour, minute=when.minute),
args=[bot, user_id],
id=job_id,
replace_existing=True
)

print(f"[INFO] - User with id: {user_id} updated job, {job_id}")

async def schedule_all_users_jobs(bot: Bot):
users = await UserService.get_all_users()
for user in users:
if user["wake_time"]:
update_user_job(user["id"], user["wake_time"], bot, job_type="wake")
if user["sleep_time"]:
update_user_job(user["id"], user["sleep_time"], bot, job_type="sleep")
1 change: 1 addition & 0 deletions telegram_bot_project/bot/utills.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# bot/utills.py
from datetime import datetime, timedelta

def format_date(dt: datetime) -> str:
Expand Down
14 changes: 13 additions & 1 deletion telegram_bot_project/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
from aiogram.filters import Command
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import CallbackQuery
from apscheduler.schedulers.asyncio import AsyncIOScheduler

from config import TOKEN

from bot.scheduler import initialize_scheduler, schedule_all_users_jobs
from bot.commands import *
from bot.callbacks import *
from bot.fallbacks import *
from messages import *

storage: MemoryStorage = MemoryStorage()
dp = Dispatcher(storage=storage)
Expand Down Expand Up @@ -184,6 +186,16 @@ async def process_fallback(message: Message, state: FSMContext):
# Main Function
async def main():
bot = Bot(token=TOKEN)

scheduler: AsyncIOScheduler = initialize_scheduler()
scheduler.add_job(
MyDayService.create_stats_for_all_users,
trigger='cron',
hour='0',
minute='0'
)

await schedule_all_users_jobs(bot)
await dp.start_polling(bot)

# Start point
Expand Down
45 changes: 43 additions & 2 deletions telegram_bot_project/messages.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from typing import Any
from aiogram import types, Bot
from service.user import UserService
from service.routine import RoutineService

MESSAGES: Any = {
"UKRANIAN": {
Expand Down Expand Up @@ -96,6 +99,8 @@
"ROUTINE_TIME": "⏰ Прокидаєшся о {}, лягаєш спати о {}, загальний час дня: {}. Чудовий план! 😊",
"TIMER_INVALID": "❌ Неправильний формат часу (потрібно 10:00). Спробуй ще раз! 😌",
"IDEA_EXIST": "⚠️ Ідея з такою назвою вже є. Придумай нову, ти ж креативний! 😊",
"SEND_MORNING_MSG": "Доброго ранку, {}",
"SEND_EVENING_MSG": "Доброго вечора, {}",
"LANGUAGE_ASK": (
"🌐 Яку мову обереш, друже? \n"
"Тисни кнопку нижче, і поїхали! 😄"
Expand Down Expand Up @@ -199,6 +204,8 @@
"TIMER_INVALID": "❌ Wrong time format (use 10:00). Try again! 😌",
"ROUTINE_TIME": "⏰ Wake up at {}, sleep at {}, total day time: {}. Great plan! 😊",
"IDEA_EXIST": "⚠️ An idea with that name already exists. Got another creative one? 😊",
"SEND_MORNING_MSG": "Good morning, {}!",
"SEND_EVENING_MSG": "Good evening, {}!",
"LANGUAGE_ASK": (
"🌐 What language would you like, friend? \n"
"Pick one below, and let’s roll! 😄"
Expand All @@ -209,10 +216,10 @@
}

# Buttons
BUTTON_SETTINGS = "⚙️ Settings"
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BUTTON_SETTINGS variable is being redefined. The original definition on line 222 is being moved, but this creates inconsistency in the code structure. Consider maintaining the original order or using a single definition.

Copilot uses AI. Check for mistakes.

BUTTON_ADD_TASK: str = "📝 Add a Task"
BUTTON_IDEA: str = "💾 Save an Idea"
BUTTON_MYDAY: str = "📅 My Day"
BUTTON_SETTINGS: str = "⚙️ Settings"
BUTTON_HELP: str = "❓ Help"
BUTTON_UA_LANG: str = "🇺🇦 Українська"
BUTTON_EN_LANG: str = "🇬🇧 English"
Expand Down Expand Up @@ -284,4 +291,38 @@ def generate_daily_stats_message(language: str, created_ideas: int, completed_ta
f"📝 *Tasks added*: {created_tasks}\n\n"
"🔄 Updates every day at 00:00.\n\n"
"You’re absolutely crushing it! Keep shining! 🌟"
)
)

async def send_morning_message(bot: Bot, user_id: int):
language = await UserService.get_user_language(user_id) or "ENGLISH"
morning_routine = await RoutineService.get_user_routines(user_id, routine_type="morning")

print(f"[INFO] - Sending morning routine to user with id, {user_id}")
if not morning_routine:
await bot.send_message(
user_id,
MESSAGES[language]['SEND_MORNING_MSG'].format("👤") + '\n' + MESSAGES[language]['NO_MORNING_ROUTINE']
Comment on lines +299 to +304
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded "👤" emoji should be replaced with a more meaningful placeholder or the actual username, as suggested by the message template parameter structure.

Suggested change
print(f"[INFO] - Sending morning routine to user with id, {user_id}")
if not morning_routine:
await bot.send_message(
user_id,
MESSAGES[language]['SEND_MORNING_MSG'].format("👤") + '\n' + MESSAGES[language]['NO_MORNING_ROUTINE']
username = await UserService.get_username(user_id) or "Friend"
print(f"[INFO] - Sending morning routine to user with id, {user_id}")
if not morning_routine:
await bot.send_message(
user_id,
MESSAGES[language]['SEND_MORNING_MSG'].format(username) + '\n' + MESSAGES[language]['NO_MORNING_ROUTINE']

Copilot uses AI. Check for mistakes.

)
return

dividers: str = "\n" + ("-" * int(len(MESSAGES[language]['MORNING_ROUTINE_SHOW']) * 1.65))
formatted_routine_items = "\n".join(
f"# {idx}. {routine['routine_name']}"
for idx, routine in enumerate(morning_routine, start=1)
)
formatted_morning_routine = (
MESSAGES[language]['MORNING_ROUTINE_SHOW'] +
dividers +
"\n" +
formatted_routine_items
)

await bot.send_message(user_id, formatted_morning_routine)

async def send_evening_message(bot: Bot, user_id: int):
language = await UserService.get_user_language(user_id) or "ENGLISH"
print(f"[INFO] - Sending evening routine to user with id, {user_id}")
await bot.send_message(
user_id,
MESSAGES[language]['SEND_EVENING_MSG'].format("👤")
Comment on lines +325 to +327
Copy link
Preview

Copilot AI Aug 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the morning message, the hardcoded "👤" emoji should be replaced with a more meaningful placeholder or the actual username.

Suggested change
await bot.send_message(
user_id,
MESSAGES[language]['SEND_EVENING_MSG'].format("👤")
username = await UserService.get_username(user_id) or "User"
await bot.send_message(
user_id,
MESSAGES[language]['SEND_EVENING_MSG'].format(username)

Copilot uses AI. Check for mistakes.

)
15 changes: 15 additions & 0 deletions telegram_bot_project/service/myday.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ async def create_daily_stats(
await session.commit()
return stat_id

@staticmethod
async def create_stats_for_all_users() -> None:
print("[INFO] - Creating daily stats for all users")
async with get_session() as session:
result = await session.execute(
text("SELECT id FROM users")
)
user_ids = [row.id for row in result.fetchall()]

for user_id in user_ids:
try:
await MyDayService.create_daily_stats(user_id)
except Exception as e:
print(f"[ERROR] - Failed to create stats for user {user_id}: {e}")

@staticmethod
async def get_today_stats(user_id: int) -> Optional[dict]:
async with get_session() as session:
Expand Down
9 changes: 9 additions & 0 deletions telegram_bot_project/service/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ async def create_user(user_id: int, user_name: str, language: str = "ENGLISH") -
await session.commit()
return result.scalar_one()

@staticmethod
async def get_all_users() -> list[dict]:
async with get_session() as session:
result = await session.execute(
text("SELECT id, wake_time, sleep_time FROM users")
)
rows = result.fetchall()
return [dict(row._mapping) for row in rows]

@staticmethod
async def get_user_by_id(user_id: int):
async with get_session() as session:
Expand Down