Powrót do strony głównej

Lead-bot Telegram na Python: darmowa CRM

Artykuł opisuje realizację lead-bota w Telegramie na Pythonie dla mini-CRM. Używa Yandex Cloud Functions, tematy supergroup i bezstanową logikę. Nadaje się do obsługi do 20 leadów w miesiącu bez kosztów.

Darmowy Telegram-bot CRM dla leadów na Pythonie
Advertisement 728x90

Bezpłatny bot do generowania leadów w Telegramie na Pythonie z Yandex Cloud Functions

Rozwiązania dla samodzielnych projektów i małych zespołów pozwalają stworzyć prostą CRM bez kosztów. Bot kwalifikuje nowe leady poprzez dwa pytania z przyciskami inline, tworzy osobny temat w supergrupie dla każdego klienta oraz zapewnia dwukierunkowy przekaz wiadomości. Wdrożenie na Yandex Cloud Functions z darmowym poziomem: 1 milion wywołań miesięcznie i 1 GB Object Storage.

Schemat działania: użytkownik kliknie link głęboki ze strony → bot prosi o rodzaj działalności i cel → tworzy temat typu «Ivan — E-commerce — agent AI» → cała rozmowa jest agregowana w grupie z możliwością wyszukiwania i powiadomień.

Minimalna obudowa nad Telegram Bot API

Dla Cloud Functions idealne są lekkie rozwiązania bez frameworków takich jak aiogram. Zmniejsza to czas startu chłodnego do minimum, używając czystego httpx. Pełny warstwy API zajmuje tylko 57 linii:

Google AdInline article slot
"""telegram_api.py — cienka warstwa nad Bot API."""
import os
import httpx

BOT_TOKEN = os.environ.get("BOT_TOKEN", "")
BASE_URL = f"https://api.telegram.org/bot{BOT_TOKEN}"

def _call(method: str, **kwargs) -> dict:
    resp = httpx.post(f"{BASE_URL}/{method}", json=kwargs, timeout=10)
    return resp.json()

def send_message(chat_id, text, reply_markup=None, message_thread_id=None):
    params = {"chat_id": chat_id, "text": text, "parse_mode": "HTML"}
    if reply_markup:
        params["reply_markup"] = reply_markup
    if message_thread_id:
        params["message_thread_id"] = message_thread_id
    return _call("sendMessage", **params)

def create_forum_topic(chat_id, name):
    return _call("createForumTopic", chat_id=chat_id, name=name)

def copy_message(chat_id, from_chat_id, message_id, message_thread_id=None):
    params = {"chat_id": chat_id, "from_chat_id": from_chat_id, "message_id": message_id}
    if message_thread_id:
        params["message_thread_id"] = message_thread_id
    return _call("copyMessage", **params)

Funkcja copy_message jest lepsza niż forward_message: eliminuje znacznik «Przesłane od…», a wiadomość wygląda naturalnie.

Handler webhook z walidacją

Yandex Cloud Function obsługuje bezpośrednie żądania HTTPS od Telegrama (allow-unauthenticated-invoke). Walidacja odbywa się za pomocą X-Telegram-Bot-Api-Secret-Token:

def handler(event, context):
    """Punkt wejścia funkcji Yandex Cloud."""
    headers = event.get("headers", {})
    secret = headers.get("X-Telegram-Bot-Api-Secret-Token") or \
             headers.get("x-telegram-bot-api-secret-token", "")
    if secret != WEBHOOK_SECRET:
        return {"statusCode": 403, "body": "Forbidden"}

    body = event.get("body", "{}")
    update = json.loads(body) if isinstance(body, str) else body

    if "callback_query" in update:
        _handle_callback(update["callback_query"])
    elif "message" in update:
        _handle_message(update["message"])

    return {"statusCode": 200, "body": "ok"}

Podział na _handle_callback i _handle_message upraszcza logikę.

Google AdInline article slot

Bezstanowa kwalifikacja leadów

Komenda /start uruchamia ankietę: pierwsze pytanie – rodzaj działalności, drugie – cel. Dane callback kodują oba odpowiedzi: q2:sales:ecommerce. Limit 64 bajtów został zachowany dla ustawień domyślnych.

Przykład pierwszego pytania:

def _handle_start(chat_id, from_user):
    if storage.get_topic_id_by_user(chat_id):
        tg.send_message(chat_id,
            "Już podałeś zgłoszenie. Skontaktujemy się z Tobą w najbliższym czasie.\n\n"
            "Jeśli chcesz coś dodać — po prostu napisz tu wiadomość.")
        return

    keyboard = {"inline_keyboard": [
        [{"text": "E-commerce / Platformy handlowe", "callback_data": "q1:ecommerce"}],
        [{"text": "Usługi / Serwis",           "callback_data": "q1:services"}],
        [{"text": "Produkcja",               "callback_data": "q1:production"}],
        [{"text": "IT / Startup",               "callback_data": "q1:it"}],
        [{"text": "Inne",                     "callback_data": "q1:other"}],
    ]}
    tg.send_message(chat_id, f"Cześć, {from_user.get('first_name', '')}! Jestem bot VexAI.\n\n"
                      "Odpowiedz na 2 krótkie pytania, a skontaktujemy się z Tobą.")
    tg.send_message(chat_id, "<b>Jak wygląda Twoja działalność?</b>", reply_markup=keyboard)

Ochrona przed duplikatami: sprawdzenie mapowania w Object Storage. Dla opcji «Inne» — tymczasowy plik stanu.

Google AdInline article slot

Drugie pytanie działa podobnie, z przekazaniem q1_key w danych.

Tworzenie tematu i relay

Po zakończeniu ankiety generowany jest temat o limicie 128 znaków:

def _finalize(chat_id, from_user, q1_answer, q2_answer):
    tg.send_message(chat_id, "Dziękujemy! Skontaktujemy się z Tobą wkrótce.")

    full_name = f"{from_user.get('first_name', '')} {from_user.get('last_name', '')}".strip()
    topic_title = f"{full_name} — {q1_answer} — {q2_answer}"
    if len(topic_title) > 128:
        topic_title = topic_title[:125] + "..."

    result = tg.create_forum_topic(ADMIN_GROUP_ID, topic_title)
    topic_id = result["result"]["message_thread_id"]

    summary = (f"<b>Nowy lead</b>\n\n"
               f"<b>Imię:</b> {full_name}\n"
               f"<b>Działalność:</b> {q1_answer}\n"
               f"<b>Zadanie:</b> {q2_answer}\n"
               f"<b>Źródło:</b> website")
    tg.send_message(ADMIN_GROUP_ID, summary, message_thread_id=topic_id)

    storage.save_topic_mapping(topic_id, chat_id)
    storage.save_user_mapping(chat_id, topic_id)

Relay w _handle_message:

  • Administrator pisze w temacie → kopiowane do klienta.
  • Klient pisze do bota → kopiowane do tematu.

Obsługa linków głębokich: /start website do śledzenia źródła.

Konfiguracja i ograniczenia

  • Utwórz supergrupę z włączonymi tematami.
  • Dodaj bota jako administratora: zarządzanie tematami i wysyłanie wiadomości.
  • Skonfiguruj Yandex Cloud: usługa konta storage.editor, kontener, klucze dostępu.
  • Ustaw webhook z tokenem tajnym.

Otrzymujesz:

  • Wyszukiwanie leadów.
  • Powiadomienia.
  • Przypięte karty.

Ograniczenia: brak funneli, analizy, współpracy zespołowej. Idealne dla 20 leadów/miesiąc.

Co ważne

  • Bezpłatne wdrożenie: Yandex Cloud Functions + Object Storage w warstwie darmowej.
  • Projekt bezstanowy: dane callback przechowują stan, minimalne magazynowanie.
  • Funkcja relay: pełna komunikacja w tematach bez dodatkowych aplikacji.
  • Ochrona: token tajny + ochrona przed duplikatami.
  • Skalowalność: do 20 leadów/miesiąc bez płatnej CRM.

— Editorial Team

Advertisement 728x90

Czytaj dalej