Напоминалки: выбор часового пояса кнопками городов + ручной ввод
При гейте часового пояса теперь показывается клавиатура с частыми российскими городами-поясами (Калининград..Камчатка). Клик по кнопке шлёт 'Город, UTC+N' — _parse_tz_offset распознаёт и это, и обычный ручной ввод вида '+3'/'-5', если своего города в списке нет. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -488,12 +488,16 @@ class VKBotApplication:
|
||||
return f"{name} (vk.com/id{uid})" if name else f"vk.com/id{uid}"
|
||||
|
||||
def _parse_tz_offset(self, raw: str) -> Optional[int]:
|
||||
"""Парсит смещение от UTC вида '+3', '-5', '0'. None, если не число
|
||||
или вне диапазона реальных часовых поясов (-12..+14)."""
|
||||
"""Парсит смещение от UTC: либо чистое число '+3'/'-5'/'0' (ручной ввод),
|
||||
либо 'Город, UTC+N' (клик по кнопке get_timezone_keyboard). None, если
|
||||
не удалось распознать или число вне диапазона реальных поясов (-12..+14)."""
|
||||
raw = raw.strip()
|
||||
if not re.match(r"^[+-]?\d{1,2}$", raw):
|
||||
m = re.search(r"UTC\s*([+-]?\d{1,2})\s*$", raw, re.I)
|
||||
if not m:
|
||||
m = re.match(r"^([+-]?\d{1,2})$", raw)
|
||||
if not m:
|
||||
return None
|
||||
val = int(raw)
|
||||
val = int(m.group(1))
|
||||
return val if -12 <= val <= 14 else None
|
||||
|
||||
def _require_reminder_tz(self, user_id: int) -> bool:
|
||||
@@ -505,9 +509,10 @@ class VKBotApplication:
|
||||
db.update_user_state(user_id, "ADMIN_REMINDER_TZ_SETUP")
|
||||
self.send_message(
|
||||
user_id,
|
||||
"🌐 Прежде чем пользоваться напоминалками, укажите свой часовой пояс "
|
||||
"относительно UTC.\nНапример: +3 (Москва), +5 (Екатеринбург), 0 (UTC).",
|
||||
keyboard=get_cancel_admin_keyboard()
|
||||
"🌐 Прежде чем пользоваться напоминалками, укажите свой часовой пояс.\n"
|
||||
"Выберите город кнопкой ниже, либо введите смещение от UTC вручную "
|
||||
"(например, +3), если своего города в списке нет.",
|
||||
keyboard=get_timezone_keyboard()
|
||||
)
|
||||
return False
|
||||
|
||||
@@ -1784,8 +1789,9 @@ class VKBotApplication:
|
||||
if state == "ADMIN_REMINDER_TZ_SETUP":
|
||||
offset = self._parse_tz_offset(text)
|
||||
if offset is None:
|
||||
self.send_message(user_id, "⚠️ Формат: число от -12 до +14, например +3 или -5.",
|
||||
keyboard=get_cancel_admin_keyboard())
|
||||
self.send_message(user_id, "⚠️ Выберите город кнопкой ниже, либо введите число "
|
||||
"от -12 до +14 вручную, например +3 или -5.",
|
||||
keyboard=get_timezone_keyboard())
|
||||
return
|
||||
db.set_admin_tz_offset(user_id, offset)
|
||||
db.update_user_state(user_id, "FREE_CHAT")
|
||||
|
||||
@@ -213,6 +213,27 @@ def get_reminders_admin_keyboard() -> str:
|
||||
return keyboard.get_keyboard()
|
||||
|
||||
|
||||
def get_timezone_keyboard() -> str:
|
||||
"""Клавиатура выбора часового пояса: частые российские города-пояса
|
||||
кнопками (кнопка шлёт 'Город, UTC±N' — _parse_tz_offset вытаскивает
|
||||
смещение из этого текста), плюс можно просто ввести своё смещение
|
||||
вручную, если города в списке нет."""
|
||||
cities = [
|
||||
("Калининград", 2), ("Москва", 3), ("Самара", 4),
|
||||
("Екатеринбург", 5), ("Омск", 6), ("Красноярск", 7),
|
||||
("Иркутск", 8), ("Якутск", 9), ("Владивосток", 10),
|
||||
("Магадан", 11), ("Камчатка", 12),
|
||||
]
|
||||
keyboard = VkKeyboard(one_time=False)
|
||||
for i, (city, offset) in enumerate(cities):
|
||||
if i and i % 2 == 0:
|
||||
keyboard.add_line()
|
||||
keyboard.add_button(f"{city}, UTC+{offset}", color=VkKeyboardColor.SECONDARY)
|
||||
keyboard.add_line()
|
||||
keyboard.add_button("Отмена ❌", color=VkKeyboardColor.NEGATIVE)
|
||||
return keyboard.get_keyboard()
|
||||
|
||||
|
||||
def get_pick_keyboard(items: list) -> str:
|
||||
"""Клавиатура выбора из списка пар (id, label). Кнопка отправляет '<id>. <label>'."""
|
||||
keyboard = VkKeyboard(one_time=False)
|
||||
|
||||
@@ -459,6 +459,19 @@ def test_reminder_tz_gate_before_list(app, monkeypatch):
|
||||
assert _state(admin) == "FREE_CHAT"
|
||||
|
||||
|
||||
def test_reminder_tz_setup_via_city_button(app, monkeypatch):
|
||||
"""Часовой пояс можно выбрать кнопкой города, а не только вводом числа."""
|
||||
admin = 80010
|
||||
monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin])
|
||||
|
||||
app.handle_message(admin, "⏰ Напоминалки")
|
||||
assert _state(admin) == "ADMIN_REMINDER_TZ_SETUP"
|
||||
|
||||
app.handle_message(admin, "Екатеринбург, UTC+5") # клик по кнопке клавиатуры
|
||||
assert _state(admin) == "FREE_CHAT"
|
||||
assert bot.db.get_admin_tz_offset(admin) == 5
|
||||
|
||||
|
||||
def test_reminder_creation_converts_author_local_time_to_server(app, monkeypatch):
|
||||
admin = 80007
|
||||
monkeypatch.setattr(bot.config, "ADMIN_IDS", [admin])
|
||||
|
||||
Reference in New Issue
Block a user