From 7588d74ceb32102f26caf76229f81a5dd62b5359 Mon Sep 17 00:00:00 2001 From: Artemii Peretiachenko Date: Sat, 29 Aug 2026 19:00:21 +0200 Subject: [PATCH] Show the wait-ack only on a client's first relayed message. Stops repeating the ack on every client message so the private chat is not cluttered after the first contact. Co-authored-by: Cursor --- .env.example | 4 ++-- README.md | 4 ++-- bot/db/repository.py | 32 ++++++++++++++++++++++++++++++-- bot/handlers/client.py | 4 +++- bot/i18n.py | 4 ++-- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/.env.example b/.env.example index 2c307c6..b63e9f9 100644 --- a/.env.example +++ b/.env.example @@ -7,8 +7,8 @@ DATABASE_PATH=data/bot.db # (so UK keeps catalog strings and the services button stays in sync). # WELCOME_TEXT_RU=Здравствуйте! Напишите ваш запрос. # WELCOME_TEXT_UK=Вітаємо! Напишіть ваш запит. -# ACK_TEXT_RU=Спасибо, подождите ответ. -# ACK_TEXT_UK=Дякуємо, зачекайте на відповідь. +# ACK_TEXT_RU=Спасибо, дальше вам будет отвечать менеджер +# ACK_TEXT_UK=Дякуємо, далі вам буде відповідати менеджер. # COOLDOWN_TEXT_RU=Подождите немного, не спамьте. # COOLDOWN_TEXT_UK=Зачекайте трохи, не спамте. CLIENT_COOLDOWN_SECONDS=5 diff --git a/README.md b/README.md index 953490e..2432d44 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ python -m bot | `MANAGER_GROUP_ID` | Id супергруппы с Topics | | `DATABASE_PATH` | Путь к SQLite (по умолчанию `data/bot.db`) | | `WELCOME_TEXT_RU` / `WELCOME_TEXT_UK` | Опционально: приветствие для языка | -| `ACK_TEXT_RU` / `ACK_TEXT_UK` | Опционально: текст после сообщения клиента | +| `ACK_TEXT_RU` / `ACK_TEXT_UK` | Опционально: текст после первого сообщения клиента | | `COOLDOWN_TEXT_RU` / `COOLDOWN_TEXT_UK` | Опционально: ответ при кулдауне | | `WELCOME_TEXT` / `ACK_TEXT` / `COOLDOWN_TEXT` | Legacy: только для RU (UK не перезаписывается) | | `CLIENT_COOLDOWN_SECONDS` | Кулдаун клиента в секундах (по умолчанию `5`) | @@ -50,7 +50,7 @@ python -m bot ## Как это работает 1. Клиент: `/start` → выбор языка (RU/UK) → приветствие, запись в SQLite. -2. Клиент пишет сообщение → бот создаёт тему (если ещё нет) и копирует сообщение менеджерам → «Спасибо, подождите ответ». +2. Клиент пишет сообщение → бот создаёт тему (если ещё нет) и копирует сообщение менеджерам. На первое сообщение — «Спасибо, дальше вам будет отвечать менеджер»; дальше ack не повторяется. 3. Менеджер пишет в теме клиента → бот копирует содержимое клиенту в личку от своего имени. 4. Правки сообщений синхронизируются в обе стороны (текст и подписи). 5. Реакции синхронизируются в обе стороны. diff --git a/bot/db/repository.py b/bot/db/repository.py index 76c0795..4690340 100644 --- a/bot/db/repository.py +++ b/bot/db/repository.py @@ -15,6 +15,7 @@ CREATE TABLE IF NOT EXISTS clients ( last_name TEXT, topic_id INTEGER UNIQUE, language TEXT, + ack_sent INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL, updated_at TEXT NOT NULL ); @@ -44,6 +45,7 @@ class Client: last_name: Optional[str] topic_id: Optional[int] language: Optional[str] + ack_sent: bool created_at: str updated_at: str @@ -81,6 +83,19 @@ class ClientRepository: columns = {row[1] for row in rows} if "language" not in columns: await conn.execute("ALTER TABLE clients ADD COLUMN language TEXT") + if "ack_sent" not in columns: + await conn.execute( + "ALTER TABLE clients ADD COLUMN ack_sent INTEGER NOT NULL DEFAULT 0" + ) + await conn.execute( + """ + UPDATE clients + SET ack_sent = 1 + WHERE telegram_id IN ( + SELECT DISTINCT client_telegram_id FROM message_links + ) + """ + ) async def close(self) -> None: if self._conn is not None: @@ -101,6 +116,7 @@ class ClientRepository: last_name=row["last_name"], topic_id=row["topic_id"], language=row["language"], + ack_sent=bool(row["ack_sent"]), created_at=row["created_at"], updated_at=row["updated_at"], ) @@ -118,8 +134,8 @@ class ClientRepository: """ INSERT INTO clients ( telegram_id, username, first_name, last_name, topic_id, language, - created_at, updated_at - ) VALUES (?, ?, ?, ?, NULL, NULL, ?, ?) + ack_sent, created_at, updated_at + ) VALUES (?, ?, ?, ?, NULL, NULL, 0, ?, ?) ON CONFLICT(telegram_id) DO UPDATE SET username = excluded.username, first_name = excluded.first_name, @@ -176,6 +192,18 @@ class ClientRepository: ) await conn.commit() + async def mark_ack_sent(self, telegram_id: int) -> None: + conn = self._require_conn() + await conn.execute( + """ + UPDATE clients + SET ack_sent = 1, updated_at = ? + WHERE telegram_id = ? + """, + (_utcnow(), telegram_id), + ) + await conn.commit() + async def set_language(self, telegram_id: int, language: str) -> None: conn = self._require_conn() await conn.execute( diff --git a/bot/handlers/client.py b/bot/handlers/client.py index adcd42b..b5378f0 100644 --- a/bot/handlers/client.py +++ b/bot/handlers/client.py @@ -174,6 +174,7 @@ async def client_message( message: Message, relay: RelayService, cooldown: CooldownService, + repo: ClientRepository, ) -> None: if message.from_user is None or not is_relayable_content(message): return @@ -196,5 +197,6 @@ async def client_message( return cooldown.commit(message.from_user.id, message.media_group_id) - if decision.should_ack: + if decision.should_ack and not client.ack_sent: await _answer_bot(message, client.language, "ack") + await repo.mark_ack_sent(message.from_user.id) diff --git a/bot/i18n.py b/bot/i18n.py index 1a05552..f7c8f29 100644 --- a/bot/i18n.py +++ b/bot/i18n.py @@ -52,7 +52,7 @@ TEXTS: Dict[str, Dict[str, str]] = { "Укажите что конкретно вам нужно сделать.\n\n" "🔶 Все наши услуги посмотрите по кнопке ниже." ), - "ack": "Спасибо, подождите ответ.", + "ack": "Спасибо, дальше вам будет отвечать менеджер", "cooldown": "Подождите немного, не спамьте.", "send_failed": ( "Не удалось отправить сообщение менеджеру. Попробуйте позже." @@ -78,7 +78,7 @@ TEXTS: Dict[str, Dict[str, str]] = { "Вкажіть, що саме вам потрібно зробити.\n\n" "🔶 Всі наші послуги подивіться по кнопці нижче." ), - "ack": "Дякуємо, зачекайте на відповідь.", + "ack": "Дякуємо, далі вам буде відповідати менеджер.", "cooldown": "Зачекайте трохи, не спамте.", "send_failed": ( "Не вдалося надіслати повідомлення менеджеру. Спробуйте пізніше."