1
0
Fork 0
forked from zovos/bot_tg

auto send to smoke

This commit is contained in:
q 2026-03-05 12:05:30 +03:00
parent 8bc905331c
commit 6afc30570f
2 changed files with 85 additions and 1 deletions

86
main.py
View file

@ -83,6 +83,84 @@ def minutes_until_break(now: datetime | None = None) -> str:
return "Пары закончились, перекур только завтра." return "Пары закончились, перекур только завтра."
def next_break_window(now: datetime | None = None) -> tuple[datetime | None, datetime | None]:
"""Возвращает (начало, конец) ближайшего перекура или (None, None)."""
if now is None:
now = datetime.now(ZoneInfo(config.DEFAULT_TZ))
elif now.tzinfo is None:
now = now.replace(tzinfo=ZoneInfo(config.DEFAULT_TZ))
day = now.weekday()
today_schedule = config.SCHEDULE.get(day, [])
if not today_schedule:
return None, None
def dt_for(t: time) -> datetime:
return now.replace(hour=t.hour, minute=t.minute, second=0, microsecond=0)
for start_t, end_t, br_minutes in today_schedule:
if not br_minutes:
continue
end_dt = dt_for(end_t)
br_start = end_dt
br_end = end_dt + timedelta(minutes=br_minutes)
# Ближайший будущий или текущий перекур
if now < br_end:
return br_start, br_end
return None, None
# --- Авто-напоминание о перекуре ---
_break_tasks: dict[int, tuple[datetime, asyncio.Task]] = {}
_break_notified: dict[int, datetime] = {}
async def _send_break_photo(chat_id: int, bot: Bot, start_dt: datetime) -> None:
last = _break_notified.get(chat_id)
if last and last == start_dt:
return # Уже кидали уведомление для этого слота
photo_path = config.BASE_DIR / "vape.jpg"
if not photo_path.exists():
logger.warning("vape.jpg not found, skip break photo")
return
try:
await bot.send_photo(chat_id=chat_id, photo=FSInputFile(photo_path), caption="идем курить")
_break_notified[chat_id] = start_dt
except Exception:
logger.exception("Failed to send break photo")
async def _break_notification(chat_id: int, bot: Bot, start_dt: datetime) -> None:
try:
now = datetime.now(start_dt.tzinfo)
delay = (start_dt - now).total_seconds()
if delay > 0:
await asyncio.sleep(delay)
await _send_break_photo(chat_id, bot, start_dt)
except asyncio.CancelledError:
pass
finally:
stored = _break_tasks.get(chat_id)
if stored and stored[0] == start_dt:
_break_tasks.pop(chat_id, None)
def schedule_break_notification(chat_id: int, bot: Bot, start_dt: datetime) -> None:
existing = _break_tasks.get(chat_id)
if existing:
scheduled_start, task = existing
if scheduled_start == start_dt and not task.done():
return # Уже ждём этот же слот
if not task.done():
task.cancel()
task = asyncio.create_task(_break_notification(chat_id, bot, start_dt))
_break_tasks[chat_id] = (start_dt, task)
# --- Работа с изображениями (Макеты и Мемы) --- # --- Работа с изображениями (Макеты и Мемы) ---
def load_font(size: int) -> ImageFont.FreeTypeFont: def load_font(size: int) -> ImageFont.FreeTypeFont:
@ -414,7 +492,13 @@ async def handle_start(message: Message):
await message.answer("Соси") await message.answer("Соси")
async def handle_break_cmd(message: Message): async def handle_break_cmd(message: Message):
await message.answer(minutes_until_break()) now = datetime.now(ZoneInfo(config.DEFAULT_TZ))
await message.answer(minutes_until_break(now))
# Ставим будильник на ближайший перекур для этого чата
start_dt, _ = next_break_window(now)
if start_dt:
schedule_break_notification(message.chat.id, message.bot, start_dt)
async def handle_penis_cmd(message: Message): async def handle_penis_cmd(message: Message):
if not message.from_user: if not message.from_user:

BIN
vape.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB