Files
botPillbox/app/utils.py
2026-01-06 13:32:39 +07:00

94 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# utils.py
from datetime import datetime, date
from typing import List, Optional
from zoneinfo import ZoneInfo
from telegram import ReplyKeyboardMarkup, InlineKeyboardMarkup, InlineKeyboardButton
from config import BTN_ADD, BTN_LIST, BTN_EDIT, BTN_DELETE, BTN_HISTORY, BTN_TZ, BTN_CANCEL, TZ_SUGGESTIONS
# ----------------- UI HELPERS -----------------
def main_menu_kb():
kb = [
[BTN_ADD, BTN_LIST],
[BTN_EDIT, BTN_DELETE],
[BTN_HISTORY, BTN_TZ]
]
return ReplyKeyboardMarkup(kb, resize_keyboard=True, one_time_keyboard=False)
def tz_keyboard():
kb = [[tz] for tz in TZ_SUGGESTIONS]
kb.append(["Ввести вручную"])
kb.append([BTN_CANCEL])
return ReplyKeyboardMarkup(kb, one_time_keyboard=True, resize_keyboard=True)
def build_wd_keyboard(wd_sel: set):
labels = ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"]
kb = []
row = []
for i, lab in enumerate(labels):
prefix = "" if i in wd_sel else "◻️"
row.append(InlineKeyboardButton(f"{prefix} {lab}", callback_data=f"wd_toggle:{i}"))
if (i + 1) % 3 == 0:
kb.append(row)
row = []
if row:
kb.append(row)
kb.append([
InlineKeyboardButton("Готово", callback_data="wd_done"),
InlineKeyboardButton("Отмена", callback_data="wd_cancel")
])
return InlineKeyboardMarkup(kb)
# ----------------- DATA HELPERS -----------------
def parse_hhmm(s: str) -> Optional[str]:
s = s.strip()
try:
dt = datetime.strptime(s, "%H:%M")
return dt.strftime("%H:%M")
except ValueError:
return None
def weekdays_list_to_csv(lst: List[int]) -> str:
return ",".join(str(i) for i in sorted(set(lst))) if lst else ""
def weekdays_csv_to_list(csv: Optional[str]) -> List[int]:
if not csv:
return []
return [int(x) for x in csv.split(",") if x.isdigit()]
def now_utc() -> datetime:
return datetime.utcnow()
def utc_str_min(dt: datetime) -> str:
return dt.strftime("%Y-%m-%d %H:%M")
def utc_str_full(dt: datetime) -> str:
return dt.strftime("%Y-%m-%d %H:%M:%S")
def localized_now_for_tz(tzname: str) -> datetime:
try:
tz = ZoneInfo(tzname)
except Exception:
tz = ZoneInfo("UTC")
return datetime.now(tz)
def local_time_hhmm_for_user(tzname: str, when_utc: datetime) -> str:
try:
tz = ZoneInfo(tzname)
except Exception:
tz = ZoneInfo("UTC")
local = when_utc.astimezone(tz)
return local.strftime("%H:%M")
def user_local_hhmm_to_utc_dt(tzname: str, local_date: date, hhmm: str) -> datetime:
hour, minute = map(int, hhmm.split(":"))
local_dt = datetime(local_date.year, local_date.month, local_date.day, hour, minute)
try:
tz = ZoneInfo(tzname)
local_dt = local_dt.replace(tzinfo=tz)
except Exception:
tz = ZoneInfo("UTC")
local_dt = local_dt.replace(tzinfo=tz)
return local_dt.astimezone(ZoneInfo("UTC")).replace(tzinfo=None)