From 3014b89d0ff161cb2af4e4a32d209916501ced9f Mon Sep 17 00:00:00 2001 From: wasrusgen Date: Sat, 30 May 2026 16:27:57 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20Telegram=20bot=20@wasrusgen1=5Fconsulti?= =?UTF-8?q?ng=5Fbot=20=E2=80=94=20webhook=20handler=20/start=20/status=20/?= =?UTF-8?q?help,=20tg=5Fchat=5Fid=20in=20projects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 --- backend/elena_app.py | 86 +++++++++++++++++++++++++++++++- backend/legal/dogovor_oferta.md | 4 +- backend/legal/soglashenie_pep.md | 4 +- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/backend/elena_app.py b/backend/elena_app.py index a5ced4a..8a58628 100644 --- a/backend/elena_app.py +++ b/backend/elena_app.py @@ -92,7 +92,8 @@ def init_db(): niche TEXT, description TEXT, status TEXT DEFAULT 'interview', - created_at TEXT + created_at TEXT, + tg_chat_id TEXT ); CREATE TABLE IF NOT EXISTS messages ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -131,6 +132,14 @@ def init_db(): accepted_at TEXT NOT NULL -- append-only, не редактируется ); """) + # Миграции — добавляем колонки если нет (идемпотентно) + for sql in [ + "ALTER TABLE projects ADD COLUMN tg_chat_id TEXT", + ]: + try: + con.execute(sql) + except Exception: + pass con.commit() con.close() @@ -1092,6 +1101,81 @@ def get_project_state(token): "documents": [json.loads(r["data_json"]) and {"filename": json.loads(r["data_json"])["filename"], "size": json.loads(r["data_json"]).get("size",0)} for r in db().execute("SELECT data_json FROM artifacts WHERE project_id=? AND kind='document' ORDER BY id", (proj["id"],)).fetchall()] }) +# ── Telegram Bot ───────────────────────────────────── +TG_TOKEN = "8767209545:AAEVgfL-bAhg6j0fHUyKWUze4SLTfJbLklM" +TG_API = f"https://api.telegram.org/bot{TG_TOKEN}" +CABINET_URL = "https://wasrusgen1.ru/consulting/cabinet.html" + +def tg_send(chat_id, text, reply_markup=None): + import urllib.request as ur + payload = {"chat_id": chat_id, "text": text, "parse_mode": "HTML"} + if reply_markup: + payload["reply_markup"] = json.dumps(reply_markup) + body = json.dumps(payload).encode() + req = ur.Request(f"{TG_API}/sendMessage", data=body, + headers={"Content-Type": "application/json"}) + try: + ur.urlopen(req, timeout=8) + except Exception as e: + app.logger.error(f"tg_send error: {e}") + +@app.route("/consulting/api/tg/webhook", methods=["POST"]) +def tg_webhook(): + data = request.get_json(silent=True) or {} + msg = data.get("message") or data.get("callback_query", {}).get("message") + if not msg: + return jsonify({"ok": True}) + chat_id = msg["chat"]["id"] + text = (msg.get("text") or "").strip() + cmd = text.split()[0].split("@")[0].lower() if text.startswith("/") else "" + + # /start [token] — открыть кабинет или прислать ссылку + if cmd == "/start": + parts = text.split() + token = parts[1] if len(parts) > 1 else None + if token: + proj = get_project(token) + if proj: + url = f"{CABINET_URL}?t={token}" + tg_send(chat_id, + f"Привет! Ваш проект: {proj['client_name'] or 'без названия'}\n" + f"Кабинет: {url}", + reply_markup={"inline_keyboard": [[ + {"text": "Открыть кабинет", "web_app": {"url": url}} + ]]} + ) + return jsonify({"ok": True}) + tg_send(chat_id, + "Добро пожаловать в @wasrusgen1 | КОНСАЛТИНГ\n\n" + "Для доступа к кабинету вам нужна персональная ссылка от консультанта.\n\n" + "Напишите нам: @wasrusgen1", + ) + + # /status — статус проекта по tg_id (если привязан) + elif cmd == "/status": + row = db().execute( + "SELECT token, client_name, status FROM projects WHERE tg_chat_id=? ORDER BY id DESC LIMIT 1", + (str(chat_id),) + ).fetchone() + if row: + tg_send(chat_id, + f"Проект: {row['client_name']}\n" + f"Статус: {row['status']}\n" + f"Кабинет: {CABINET_URL}?t={row['token']}" + ) + else: + tg_send(chat_id, "Привязанный проект не найден. Откройте кабинет по ссылке от консультанта.") + + elif cmd == "/help": + tg_send(chat_id, + "/start — открыть кабинет\n" + "/status — статус проекта\n\n" + "По вопросам: @wasrusgen1" + ) + + return jsonify({"ok": True}) + + if __name__ == "__main__": init_db() app.run(host="0.0.0.0", port=5002) diff --git a/backend/legal/dogovor_oferta.md b/backend/legal/dogovor_oferta.md index b90bc09..0a060ba 100644 --- a/backend/legal/dogovor_oferta.md +++ b/backend/legal/dogovor_oferta.md @@ -2,7 +2,7 @@ # @wasrusgen1 | КОНСАЛТИНГ · ИП Васильев Р.Г. # Редакция от «__» __________ 20__ г. · версия 1.0 -> ⚠️ Заполнить: 781909921730, 325784700271898, 40802810355710022284, СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК, 044030653, 30101810500000000653, [адрес], i@wasrusgen.ru, [телефон], wasrusgen1.ru/consulting +> ⚠️ Заполнить: 781909921730, 325784700271898, 40802810355710022284, СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК, 044030653, 30101810500000000653, [адрес], i@wasrusgen.ru, +7 911 279-45-42, wasrusgen1.ru/consulting > Подготовлено ⚖️ Юрием. УСН 6%. Перед публикацией — проверка профильным юристом + подать уведомление в РКН об обработке ПДн. --- @@ -118,5 +118,5 @@ ИНН: 781909921730 · ОГРНИП: 325784700271898 Адрес: [адрес] Р/с: 40802810355710022284 · Банк: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК · БИК: 044030653 · К/с: 30101810500000000653 -E-mail: i@wasrusgen.ru · Телефон: [телефон] · Сайт: wasrusgen1.ru/consulting +E-mail: i@wasrusgen.ru · Телефон: +7 911 279-45-42 · Сайт: wasrusgen1.ru/consulting УСН, объект «доходы» (НДС не облагается) diff --git a/backend/legal/soglashenie_pep.md b/backend/legal/soglashenie_pep.md index c3f3f4d..3189a5f 100644 --- a/backend/legal/soglashenie_pep.md +++ b/backend/legal/soglashenie_pep.md @@ -2,7 +2,7 @@ # @wasrusgen1 | КОНСАЛТИНГ · ИП Васильев Р.Г. # Редакция от «__» __________ 20__ г. · версия 1.0 -> ⚠️ Заполнить плейсхолдеры: 781909921730, 325784700271898, [адрес], i@wasrusgen.ru, [телефон], wasrusgen1.ru/consulting +> ⚠️ Заполнить плейсхолдеры: 781909921730, 325784700271898, [адрес], i@wasrusgen.ru, +7 911 279-45-42, wasrusgen1.ru/consulting > Подготовлено ⚖️ Юрием по 63-ФЗ. Перед публикацией — проверка профильным юристом. --- @@ -94,4 +94,4 @@ 8.3. Недействительность отдельного положения не влечёт недействительности остальных. **Исполнитель: ИП Васильев Руслан Геннадьевич** -ИНН 781909921730 · ОГРНИП 325784700271898 · [адрес] · i@wasrusgen.ru · [телефон] +ИНН 781909921730 · ОГРНИП 325784700271898 · [адрес] · i@wasrusgen.ru · +7 911 279-45-42