How to Build a Telegram Bot That Captures Leads 24/7
Here's a comprehensive guide to building a lead-capturing Telegram bot with Python, covering everything from code to deployment.
Building a Lead-Capturing Telegram Bot
This guide will walk you through creating a Python Telegram bot using aiogram (or Telethon if you prefer, though aiogram is generally more straightforward for bot development). We'll cover essential features like commands, inline buttons, lead storage, anti-spam, and deployment.
1. Project Setup and Dependencies
First, ensure you have Python installed. We'll use pip for package management.
Create a project directory:
mkdir telegram_lead_bot
cd telegram_lead_bot
Create a virtual environment:
python -m venv venv
Activate the virtual environment:
- Windows:
venv\Scripts\activate - macOS/Linux:
source venv/bin/activate
Install necessary libraries:
pip install aiogram python-dotenv google-api-python-client google-auth-httplib2 google-auth-oauthlib
aiogram: The asynchronous Telegram Bot API framework.python-dotenv: To manage environment variables (like your bot token).google-api-python-client,google-auth-httplib2,google-auth-oauthlib: For interacting with Google Sheets.
2. Telegram Bot Token
You need a bot token from BotFather.
- Open Telegram and search for
@BotFather. - Start a chat with it.
- Send
/newbot. - Follow the prompts to name your bot and choose a username (must end with "bot").
- BotFather will give you an API token. Keep this token secret!
3. Google Sheets Setup (for Lead Storage)
We'll use Google Sheets as a simple CRM.
- Go to Google Sheets.
- Create a new spreadsheet. Name it something like "Telegram Leads".
- Create columns for the data you want to capture (e.g., "Name", "Email", "Phone", "Message", "Timestamp").
- Enable Google Sheets API:
- Go to the Google Cloud Console.
- Create a new project or select an existing one.
- Navigate to "APIs & Services" -> "Library".
- Search for "Google Sheets API" and enable it.
- Navigate to "APIs & Services" -> "Credentials".
- Click "Create Credentials" -> "OAuth client ID".
- Select "Desktop app" as the application type.
- Give it a name (e.g., "Telegram Bot Credentials").
- Click "Create".
- Download the JSON file containing your client secrets. Rename it to
client_secrets.jsonand place it in your project directory.
- Share your Sheet:
- In your Google Sheet, click "Share".
- Under "General access", change "Restricted" to "Anyone with the link".
- Copy the link. This will be your Sheet ID. The Sheet ID is the long string of characters in the URL between
/d/and/edit.
4. Bot Code Skeleton (main.py)
Create a file named main.py in your project directory.
import logging
import os
from dotenv import load_dotenv
from aiogram import Bot, Dispatcher, types, executor
from aiogram.contrib.middlewares.logging import LoggingMiddleware
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from google.oauth2 import service_account
from googleapiclient.discovery import build
from datetime import datetime
# Load environment variables
load_dotenv()
BOT_TOKEN = os.getenv("BOT_TOKEN")
SHEET_ID = os.getenv("SHEET_ID") # Your Google Sheet ID
SERVICE_ACCOUNT_FILE = 'client_secrets.json' # Path to your downloaded JSON
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Initialize bot and dispatcher
bot = Bot(token=BOT_TOKEN)
dp = Dispatcher(bot)
# Google Sheets API setup
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
creds = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
service = build('sheets', 'v4', credentials=creds)
sheet = service.spreadsheets()
# --- Anti-Spam ---
# Basic rate limiting: store user message timestamps
user_timestamps = {}
MESSAGE_COOLDOWN = 5 # seconds
def is_spam(user_id):
current_time = datetime.now().timestamp()
if user_id in user_timestamps:
if current_time - user_timestamps[user_id] < MESSAGE_COOLDOWN:
return True
user_timestamps[user_id] = current_time
return False
# --- Command Handlers ---
@dp.message_handler(commands=['start'])
async def send_welcome(message: types.Message):
"""
Handles the /start command.
"""
markup = InlineKeyboardMarkup(row_width=1)
btn_lead = InlineKeyboardButton("Submit Lead Info", callback_data="submit_lead")
markup.add(btn_lead)
await message.reply(
"Welcome! I can help you capture leads. Click the button below to submit your information.",
reply_markup=markup
)
@dp.message_handler(commands=['help'])
async def send_help(message: types.Message):
"""
Handles the /help command.
"""
await message.reply("Use /start to begin. I'll guide you through submitting your lead details.")
# --- Callback Query Handlers ---
@dp.callback_query_handler(lambda c: c.data == 'submit_lead')
async def process_submit_lead_callback(callback_query: types.CallbackQuery):
"""
Handles the 'submit_lead' inline button click.
"""
await bot.send_message(callback_query.from_user.id, "Please provide your name:")
# Store state to know what information is expected next
await dp.current_state(user=callback_query.from_user.id).set_state('awaiting_name')
await bot.answer_callback_query(callback_query.id)
# --- Message Handlers for Lead Capture ---
@dp.message_handler(state='awaiting_name')
async def process_name(message: types.Message):
"""
Processes the name provided by the user.
"""
user_data = {
'name': message.text,
'user_id': message.from_user.id,
'username': message.from_user.username
}
await dp.current_state(user=message.from_user.id).set_state('awaiting_email')
await dp.current_state(user=message.from_user.id).update_data(**user_data)
await message.reply("Thanks, {}! Now, please provide your email:".format(message.text))
@dp.message_handler(state='awaiting_email')
async def process_email(message: types.Message):
"""
Processes the email provided by the user.
"""
if is_spam(message.from_user.id):
await message.reply("Please wait a moment before sending another message.")
return
user_data = await dp.current_state(user=message.from_user.id).get_data()
user_data['email'] = message.text
await dp.current_state(user=message.from_user.id).set_state('awaiting_phone')
await dp.current_state(user=message.from_user.id).update_data(**user_data)
await message.reply("Got it. What's your phone number?")
@dp.message_handler(state='awaiting_phone')
async def process_phone(message: types.Message):
"""
Processes the phone number provided by the user.
"""
if is_spam(message.from_user.id):
await message.reply("Please wait a moment before sending another message.")
return
user_data = await dp.current_state(user=message.from_user.id).get_data()
user_data['phone'] = message.text
await dp.current_state(user=message.from_user.id).set_state('awaiting_message')
await dp.current_state(user=message.from_user.id).update_data(**user_data)
await message.reply("And finally, any additional message you'd like to add?")
@dp.message_handler(state='awaiting_message')
async def process_final_message(message: types.Message):
"""
Processes the final message and saves the lead.
"""
if is_spam(message.from_user.id):
await message.reply("Please wait a moment before sending another message.")
return
user_data = await dp.current_state(user=message.from_user.id).get_data()
user_data['message'] = message.text
user_data['timestamp'] = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Save lead to Google Sheets
try:
values = [
[
user_data.get('name', ''),
user_data.get('email', ''),
user_data.get('phone', ''),
user_data.get('message', ''),
user_data.get('timestamp', ''),
user_data.get('user_id', ''),
user_data.get('username', '')
]
]
body = {'values': values}
# Assuming your sheet has columns: Name, Email, Phone, Message, Timestamp, TelegramUserID, TelegramUsername
# Adjust 'Sheet1!A2' if your sheet name or starting row is different
result = sheet.values().append(
spreadsheetId=SHEET_ID,
range='Sheet1!A2', # Append to the first empty row in Sheet1, starting from column A
valueInputOption='USER_ENTERED',
body=body
).execute()
logger.info(f"Lead saved to sheet: {result}")
await message.reply("Thank you! Your lead information has been successfully submitted.")
except Exception as e:
logger.error(f"Error saving lead to Google Sheets: {e}")
await message.reply("Sorry, there was an error saving your lead. Please try again later.")
# Clear state for the user
await dp.current_state(user=message.from_user.id).finish()
# --- Main Execution ---
if __name__ == '__main__':
# Add LoggingMiddleware for debugging
dp.middleware.setup(LoggingMiddleware())
# Start polling
executor.start_polling(dp, skip_updates=True)
5. Environment Variables (.env file)
Create a file named .env in your project directory and add your bot token and sheet ID:
BOT_TOKEN=YOUR_TELEGRAM_BOT_TOKEN
SHEET_ID=YOUR_GOOGLE_SHEET_ID
Replace YOUR_TELEGRAM_BOT_TOKEN with your actual bot token and YOUR_GOOGLE_SHEET_ID with the ID of your Google Sheet.
6. Running the Bot Locally
Make sure your virtual environment is activated.
python main.py
You should see log messages indicating the bot has started polling. Test it in Telegram by sending /start to your bot.
7. Deploying on a VPS with Systemd
Deploying on a VPS ensures your bot runs 24/7.
7.1. VPS Setup
- Choose a VPS Provider: DigitalOcean, Linode, AWS EC2, etc.
- Launch a Linux Instance: Ubuntu 20.04/22.04 LTS is a good choice.
- Connect via SSH:
bash ssh your_user@your_vps_ip_address - Update System:
bash sudo apt update && sudo apt upgrade -y - Install Python and Pip:
bash sudo apt install python3 python3-pip python3-venv -y - Create a dedicated user for the bot (recommended for security):
bash sudo adduser telegram_bot_user sudo su - telegram_bot_user(You'll be logged in astelegram_bot_user)
7.2. Transfer Project Files
- On your local machine:
bash # Install scp if you don't have it # sudo apt install openssh-client (Linux/macOS) # scp -r /path/to/your/telegram_lead_bot your_user@your_vps_ip_address:/home/your_user/Then, on the VPS, move the project directory to thetelegram_bot_user's home directory:bash sudo mv /home/your_user/telegram_lead_bot /home/telegram_bot_user/
7.3. Set up Project on VPS
- Log in as
telegram_bot_user:bash sudo su - telegram_bot_user cd telegram_lead_bot - Create and activate virtual environment:
bash python3 -m venv venv source venv/bin/activate - Install dependencies:
bash pip install -r requirements.txt # Create this file first: pip freeze > requirements.txt # Or directly install from the list if you didn't create requirements.txt pip install aiogram python-dotenv google-api-python-client google-auth-httplib2 google-auth-oauthlib - Upload
client_secrets.jsonand.env:- Use
scpfrom your local machine to upload these files to/home/telegram_bot_user/telegram_lead_bot/on the VPS. - Crucially, ensure
.envcontains your actual secrets. - Ensure
client_secrets.jsonis also in the same directory.
- Use
7.4. Create Systemd Service File
This file tells systemd how to manage your bot process.
- Exit
telegram_bot_usershell and log in as root or usesudo:bash exit # if you were in telegram_bot_user shell sudo nano /etc/systemd/system/telegram-lead-bot.service -
Paste the following content:
```ini [Unit] Description=Telegram Lead Capture Bot After=network.target
[Service] User=telegram_bot_user Group=telegram_bot_user WorkingDirectory=/home/telegram_bot_user/telegram_lead_bot ExecStart=/home/telegram_bot_user/telegram_lead_bot/venv/bin/python /home/telegram_bot_user/telegram_lead_bot/main.py Restart=always RestartSec=10 StandardOutput=syslog StandardError=syslog SyslogIdentifier=telegram-lead-bot
[Install] WantedBy=multi-user.target ```
UserandGroup: Should match the user you created for the bot.WorkingDirectory: Path to your bot's project directory.ExecStart: The command to run your bot, ensuring it uses the Python interpreter from your virtual environment.
-
Save and exit Nano:
Ctrl+X,Y,Enter.
7.5. Manage the Service
- Reload systemd to recognize the new service:
bash sudo systemctl daemon-reload - Start the bot service:
bash sudo systemctl start telegram-lead-bot - Check the bot's status:
bash sudo systemctl status telegram-lead-botYou should see "active (running)". If not, check the logs. - Enable the bot to start on boot:
bash sudo systemctl enable telegram-lead-bot - View logs:
bash sudo journalctl -u telegram-lead-bot -f(PressCtrl+Cto exit the log view) - To stop the bot:
bash sudo systemctl stop telegram-lead-bot - To restart the bot:
bash sudo systemctl restart telegram-lead-bot
Checklist
- [ ] Telegram Bot Token obtained from BotFather.
- [ ] Google Sheet created with necessary columns.
- [ ] Google Sheets API enabled and
client_secrets.jsondownloaded. - [ ]
.envfile created withBOT_TOKENandSHEET_ID. - [ ]
client_secrets.jsonfile in the project root. - [ ]
main.pycode written and tested locally. - [ ] Virtual environment created and activated.
- [ ] Dependencies installed (
aiogram,python-dotenv, Google API clients). - [ ] VPS provisioned and accessible via SSH.
- [ ] Python 3 and
venvinstalled on VPS. - [ ] Project files transferred to VPS.
- [ ] Project set up on VPS (venv, dependencies).
- [ ]
client_secrets.jsonand.envuploaded to VPS. - [ ]
systemdservice file (telegram-lead-bot.service) created and configured correctly. - [ ]
systemdservice started, enabled, and status checked. - [ ] Bot tested on Telegram after deployment.
Common Mistakes
- Forgetting to activate the virtual environment: Leads to using system Python and missing dependencies.
- Hardcoding secrets: Never put your
BOT_TOKENorSHEET_IDdirectly in the code. Use.env. - Incorrect Google Sheets API setup: Wrong scopes, incorrect
client_secrets.jsonpath, or sheet not shared properly. SHEET_IDformat: Ensure you're using the correct ID from the Sheet URL.- Incorrect
rangein Google Sheets API:Sheet1!A2is crucial for appending. If you have headers, start from row 2. systemdservice file typos: Incorrect paths, wrong user/group, orExecStartcommand issues.- Firewall issues: Ensure your VPS firewall allows outgoing connections for Telegram API and Google API.
- Not handling
skip_updates=True: Can lead to duplicate messages if the bot restarts. - State management errors: Bot not transitioning between states correctly, leading to broken conversation flows.
- Google API rate limits: For very high-traffic bots, you might hit Google API limits. Consider caching or alternative storage.
Need this done for you? Hire me on Freelancehunt: https://freelancehunt.com/freelancer/sspoisk
Комментарии
Отправить комментарий