/
Noriyki
/
VibeCodeBot
Обзор
Документация
Войти
/
Noriyki
/
VibeCodeBot
Код
Запросы
2
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/services/everyday.py
137 строк
5 KB
Noriyki
refactor:соединение мейнов, запуск страниц через эндпоинты, выделение фласк в отдельный поток
11 фев 2026, 20:06
11 фев 2026, 20:06
361ea2e
Код
Авторство
О чём код?
import time import schedule import telebot import datetime as dt from pytz import timezone from config import BOT_TOKEN, DAILY_TIME, TZ from src.DB.connection import get_connection from src.DB.repositories import user_repo from src.services.problem_picker import pick_random_by_rating, format_problem from src.keyboards.main_menu import daily_done_keyboard bot = telebot.TeleBot(BOT_TOKEN) def set_daily_rating(user_id: int, username: str, rating: int): """Пользователь выбирает рейтинг ежедневной задачи.""" user_repo.add_or_update_user(user_id, username, everyday_rating=rating) def get_daily_problem(user_id: int, username: str) -> tuple[str, bool]: """ Возвращает (text, is_new_today). is_new_today=True только если сейчас назначили новую задачу на today. """ today = dt.date.today().isoformat() # YYYY-MM-DD mkey = dt.date.today().strftime("%Y-%m") # YYYY-MM with get_connection() as con: cur = con.cursor() # 1) Получаем текущий ежедневный рейтинг cur.execute("SELECT everyday_rating FROM Users WHERE id = ?", (user_id,)) row = cur.fetchone() if row is None: user_repo.add_or_update_user(user_id, username, everyday_rating=800, last_rating=0) everyday_rating = 800 else: everyday_rating = row[0] or 800 # 2) Сброс счётчика при смене месяца cur.execute("SELECT month_key FROM Users WHERE id = ?", (user_id,)) row = cur.fetchone() if not row or row[0] != mkey: cur.execute( "UPDATE Users SET month_key = ?, month_done = 0 WHERE id = ?", (mkey, user_id), ) # 3) Если уже назначена на сегодня — вернуть ту же, но is_new_today=False cur.execute( "SELECT daily_date, daily_problem_key FROM Users WHERE id = ?", (user_id,), ) row = cur.fetchone() if row and row[0] == today and row[1]: return f"✅ Ежедневная задача на сегодня уже назначена: *{row[1]}*", False # 4) Назначаем новую problem = pick_random_by_rating(everyday_rating) if not problem: return f"Нет задач с рейтингом {everyday_rating}", False daily_key = f"{problem.get('contestId', '')}{problem.get('index', '')}" cur.execute( "UPDATE Users SET daily_date = ?, daily_problem_key = ?, last_problem_rating = ? WHERE id = ?", (today, daily_key, everyday_rating, user_id), ) return "📌 Ежедневная задача:\n\n" + format_problem(problem), True # Оставим старое имя, если где-то вызывается def get_daily_problem_text(user_id: int, username: str) -> str: text, _is_new = get_daily_problem(user_id, username) return text def mark_daily_done(user_id: int) -> int: """Увеличивает счётчик выполненных задач за текущий месяц и возвращает значение.""" mkey = dt.date.today().strftime("%Y-%m") with get_connection() as con: cur = con.cursor() cur.execute("SELECT month_key, month_done FROM Users WHERE id = ?", (user_id,)) row = cur.fetchone() if not row: return 0 month_key, month_done = row if month_key != mkey: month_done = 0 month_key = mkey month_done += 1 cur.execute( "UPDATE Users SET month_key = ?, month_done = ? WHERE id = ?", (month_key, month_done, user_id), ) return month_done # ================== DAILY SCHEDULER ================== def send_daily_to_all_users(): with get_connection() as con: cur = con.cursor() cur.execute("SELECT id, username, chat_id FROM Users WHERE chat_id IS NOT NULL AND chat_id != 0") users = cur.fetchall() for user_id, username, chat_id in users: try: text, is_new = get_daily_problem(user_id, username) # 1) Защита от повторной отправки: если задача уже была назначена сегодня, не шлём if not is_new: continue # 2) В рассылке добавляем кнопку "выполнил" bot.send_message(chat_id, text, reply_markup=daily_done_keyboard()) except Exception as e: print(f"Не удалось отправить {user_id}: {e}") def scheduler_loop(): schedule.every().day.at(DAILY_TIME, timezone(TZ)).do(send_daily_to_all_users) while True: schedule.run_pending() time.sleep(1)