Retour à l'accueil

Bot Telegram Prospect en Python : CRM gratuit

L'article décrit l'implémentation d'un bot prospect dans Telegram en Python pour mini-CRM. Utilise Yandex Cloud Functions, sujets de supergroupe et logique sans état. Adapté pour traiter jusqu'à 20 prospects par mois sans coûts.

Bot Telegram gratuit CRM pour prospects en Python
Advertisement 728x90

Bot Lead Gratuit sur Telegram avec Python et Yandex Cloud

Les développeurs indépendants et les petites équipes peuvent créer un CRM simple via un bot Telegram — sans aucun coût. Le bot qualifie les leads entrants en deux questions inline, crée un sujet dédié dans un supergroupe pour chaque client, et permet une relais complet des messages dans les deux sens. Déployez-le sur Yandex Cloud Functions avec le niveau gratuit : 1 million d'appels et 1 Go de stockage objet par mois.

Flux : l'utilisateur clique sur un lien profond depuis le site → le bot pose des questions sur le type d'activité et l'objectif → création d'un sujet comme "Ivan — E-commerce — Agent IA" → toutes les communications sont centralisées dans le groupe, avec recherche et notifications.

Wrapper léger sur l’API Telegram

Pour les fonctions cloud, les solutions légères sans frameworks lourds comme aiogram fonctionnent mieux. Le démarrage froid est réduit grâce à httpx pur. La couche API complète ne fait que 57 lignes :

Google AdInline article slot
"""telegram_api.py — wrapper minimal sur l’API Bot."""
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)

copy_message est préféré à forward_message : il supprime l’étiquette "Transmis de...", gardant les messages propres.

Gestionnaire de webhook avec validation

La fonction Yandex Cloud traite directement les requêtes HTTPS de Telegram (allow-unauthenticated-invoke). La validation utilise X-Telegram-Bot-Api-Secret-Token :

def handler(event, context):
    """Point d’entrée de la fonction 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"}

Séparer la logique en _handle_callback et _handle_message maintient le code propre et maintenable.

Google AdInline article slot

Qualification sans état des leads

La commande /start déclenche un sondage en deux questions : premièrement, le type d’activité ; deuxièmement, l’objectif. Les données de rappel encodent les deux réponses : q2:sales:ecommerce. La limite de 64 octets est respectée pour les options prédéfinies.

Exemple de la première question :

def _handle_start(chat_id, from_user):
    if storage.get_topic_id_by_user(chat_id):
        tg.send_message(chat_id,
            "Vous avez déjà soumis une demande. Nous vous contacterons bientôt.\n\n"
            "Si vous souhaitez ajouter quelque chose, répondez simplement ici.")
        return

    keyboard = {"inline_keyboard": [
        [{"text": "E-commerce / Marchés", "callback_data": "q1:ecommerce"}],
        [{"text": "Services / SaaS",           "callback_data": "q1:services"}],
        [{"text": "Manufacture",               "callback_data": "q1:production"}],
        [{"text": "IT / Startup",               "callback_data": "q1:it"}],
        [{"text": "Autre",                     "callback_data": "q1:other"}],
    ]}
    tg.send_message(chat_id, f"Salut, {from_user.get('first_name', '')} ! Je suis le bot VexAI.\n\n"
                      "Répondez à 2 questions rapides, et nous vous recontacterons.")
    tg.send_message(chat_id, "<b>Quel type d’activité exercez-vous ?</b>", reply_markup=keyboard)

Prévention des doublons : vérification dans le stockage objet. Pour "Autre", un fichier d’état temporaire est utilisé.

Google AdInline article slot

La deuxième question fonctionne de manière similaire, en transmettant la clé q1 dans les données de rappel.

Création de sujet et relais de messages

Après le sondage, un sujet est généré avec une limite de 128 caractères :

def _finalize(chat_id, from_user, q1_answer, q2_answer):
    tg.send_message(chat_id, "Merci ! Nous vous contacterons sous peu.")

    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>Nouveau lead</b>\n\n"
               f"<b>Nom :</b> {full_name}\n"
               f"<b>Activité :</b> {q1_answer}\n"
               f"<b>Objectif :</b> {q2_answer}\n"
               f"<b>Source :</b> site web")
    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)

Relais des messages dans _handle_message :

  • L’administrateur répond dans le sujet → copié vers le client.
  • Le client écrit au bot → copié dans le sujet.

Liens profonds pris en charge : /start website pour le suivi de source.

Configuration et limites

  • Créez un supergroupe et activez les sujets.
  • Ajoutez le bot en administrateur : gestion des sujets, envoi de messages.
  • Configurez Yandex Cloud : compte service avec storage.editor, bucket, clés d’accès.
  • Configurez le webhook avec un jeton secret.

Vous obtenez :

  • Historique des leads consultable par recherche.
  • Notifications en temps réel.
  • Cartes de lead épinglées.

Limites : pas de funnel commercial, d’analytiques ou de collaboration d’équipe. Idéal pour jusqu’à 20 leads/mois.

Points clés

  • Déploiement gratuit : Yandex Cloud Functions + Stockage Objet en version gratuite.
  • Conception sans état : les données de rappel conservent l’état ; stockage minimal requis.
  • Relais complet : conversation entière dans les sujets — aucun outil externe nécessaire.
  • Sécurité : jeton secret + protection contre les doublons.
  • Évolutivité : supporte jusqu’à 20 leads/mois sans CRM payant.

— Editorial Team

Advertisement 728x90

Lire ensuite