- Что такое Telegram Mini Apps и зачем их создавать
- Обновления Мини-приложений Телеграм
- Подготовка окружения для разработки Telegram Mini App
- Создание базовой структуры Telegram Mini App на Python
- Реализация основных функций Telegram Mini App
- Интеграция Telegram Mini App с веб-интерфейсом
- Оптимизация производительности Telegram Mini App
- Тестирование и отладка Telegram Mini App
- Развертывание Telegram Mini App на сервере
- Оптимизация SEO для Telegram Mini App
- Мониторинг и аналитика Telegram Mini App
- Обеспечение безопасности Telegram Mini App
- Будущее Telegram Mini Apps
- Полезные материалы по теме:
Что такое Telegram Mini Apps и зачем их создавать
Telegram Mini Apps — это веб-приложения, которые можно запускать прямо внутри Telegram. Они позволяют расширить функциональность ботов и предоставить пользователям удобный интерфейс для взаимодействия. В этой статье мы рассмотрим, как создать Telegram Mini App с нуля, используя Python.
Для всех, кто не хочет разбираться в коде — собрал список конструкторов Telegram Mini App
Обновления Мини-приложений Телеграм
Подготовка окружения для разработки Telegram Mini App
Для разработки нам понадобится:
- Python 3.8+
- FastAPI — современный и быстрый веб-фреймворк для Python
- python-telegram-bot — библиотека для работы с Telegram Bot API
- uvicorn — ASGI сервер для запуска FastAPI приложения
Установим необходимые зависимости:
pip install fastapi python-telegram-bot uvicorn
Я выбрал FastAPI, так как он обеспечивает высокую производительность и имеет встроенную поддержку асинхронного программирования, что важно для работы с Telegram API.
Создание базовой структуры Telegram Mini App на Python
Создадим файл main.py
с базовой структурой нашего приложения:
from fastapi import FastAPI
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
app = FastAPI()
# Telegram bot token
TOKEN = "YOUR_BOT_TOKEN"
# Initialize bot
bot = ApplicationBuilder().token(TOKEN).build()
@app.get("/")
async def root():
return {"message": "Telegram Mini App is running"}
# Telegram command handler
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await update.message.reply_text("Welcome to our Telegram Mini App!")
# Add command handler to bot
bot.add_handler(CommandHandler("start", start))
# Run bot polling in the background
@app.on_event("startup")
async def startup_event():
await bot.initialize()
await bot.start()
@app.on_event("shutdown")
async def shutdown_event():
await bot.stop()
Этот код создает базовую структуру для Telegram Mini App, используя FastAPI для веб-сервера и python-telegram-bot для обработки команд бота.
Реализация основных функций Telegram Mini App
Теперь добавим функциональность для нашего Mini App. Создадим простое приложение для заметок:
from fastapi import FastAPI, Request
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler, ContextTypes
app = FastAPI()
TOKEN = "YOUR_BOT_TOKEN"
bot = ApplicationBuilder().token(TOKEN).build()
notes = {}
@app.get("/")
async def root():
return {"message": "Telegram Mini App is running"}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
keyboard = [
[InlineKeyboardButton("Add Note", callback_data="add_note")],
[InlineKeyboardButton("View Notes", callback_data="view_notes")]
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Welcome to NotesApp!", reply_markup=reply_markup)
async def button_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
query = update.callback_query
await query.answer()
if query.data == "add_note":
await query.message.reply_text("Please send your note:")
context.user_data["expecting_note"] = True
elif query.data == "view_notes":
user_id = query.from_user.id
if user_id in notes:
note_list = "\n".join(notes[user_id])
await query.message.reply_text(f"Your notes:\n{note_list}")
else:
await query.message.reply_text("You don't have any notes yet.")
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
if context.user_data.get("expecting_note"):
user_id = update.message.from_user.id
note = update.message.text
if user_id not in notes:
notes[user_id] = []
notes[user_id].append(note)
context.user_data["expecting_note"] = False
await update.message.reply_text("Note added successfully!")
bot.add_handler(CommandHandler("start", start))
bot.add_handler(CallbackQueryHandler(button_callback))
bot.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message))
@app.on_event("startup")
async def startup_event():
await bot.initialize()
await bot.start()
@app.on_event("shutdown")
async def shutdown_event():
await bot.stop()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Этот код реализует простое приложение для заметок, где пользователи могут добавлять и просматривать свои заметки.
Интеграция Telegram Mini App с веб-интерфейсом
Для создания пользовательского интерфейса Mini App, мы будем использовать HTML, CSS и JavaScript. Создадим файл index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NotesApp Mini App</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background-color: var(--tg-theme-bg-color, #ffffff);
color: var(--tg-theme-text-color, #000000);
}
.button {
background-color: var(--tg-theme-button-color, #3390ec);
color: var(--tg-theme-button-text-color, #ffffff);
border: none;
padding: 10px 20px;
margin: 5px;
cursor: pointer;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>NotesApp</h1>
<button class="button" id="addNoteBtn">Add Note</button>
<button class="button" id="viewNotesBtn">View Notes</button>
<div id="notesList"></div>
<script>
let tg = window.Telegram.WebApp;
tg.expand();
document.getElementById('addNoteBtn').addEventListener('click', () => {
tg.showPopup({
title: 'Add Note',
message: 'Enter your note:',
buttons: [{type: 'ok', text: 'Add'}]
}, (buttonId) => {
if (buttonId === 'ok') {
// Here you would typically send the note to your server
alert('Note added!');
}
});
});
document.getElementById('viewNotesBtn').addEventListener('click', () => {
// Here you would typically fetch notes from your server
let notes = ['Sample note 1', 'Sample note 2'];
let notesList = document.getElementById('notesList');
notesList.innerHTML = notes.map(note => `<p>${note}</p>`).join('');
});
</script>
</body>
</html>
Этот HTML файл создает простой интерфейс для нашего Mini App, используя Telegram Web App JS SDK для интеграции с Telegram.
Оптимизация производительности Telegram Mini App
Для оптимизации производительности нашего Mini App, мы можем использовать кэширование и асинхронные операции:
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler, ContextTypes
import aioredis
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
TOKEN = "YOUR_BOT_TOKEN"
bot = ApplicationBuilder().token(TOKEN).build()
# Redis для кэширования
redis = aioredis.from_url("redis://localhost")
@app.get("/", response_class=HTMLResponse)
async def root():
with open("index.html", "r") as f:
return f.read()
async def get_notes(user_id: int):
cached_notes = await redis.get(f"notes:{user_id}")
if cached_notes:
return cached_notes.decode().split(",")
return []
async def add_note(user_id: int, note: str):
notes = await get_notes(user_id)
notes.append(note)
await redis.set(f"notes:{user_id}", ",".join(notes))
@app.post("/add_note")
async def add_note_api(request: Request):
data = await request.json()
user_id = data["user_id"]
note = data["note"]
await add_note(user_id, note)
return {"status": "success"}
@app.get("/get_notes/{user_id}")
async def get_notes_api(user_id: int):
notes = await get_notes(user_id)
return {"notes": notes}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
keyboard = [
[InlineKeyboardButton("Open Mini App", web_app={"url": "https://your-domain.com"})],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Welcome to NotesApp!", reply_markup=reply_markup)
bot.add_handler(CommandHandler("start", start))
@app.on_event("startup")
async def startup_event():
await bot.initialize()
await bot.start()
@app.on_event("shutdown")
async def shutdown_event():
await bot.stop()
await redis.close()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
В этом оптимизированном коде мы используем Redis для кэширования заметок пользователей, что значительно ускоряет работу приложения при большом количестве пользователей.
Тестирование и отладка Telegram Mini App
Для тестирования нашего Mini App мы можем использовать инструменты разработчика в браузере и логирование на сервере:
import logging
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import ApplicationBuilder, CommandHandler, CallbackQueryHandler, ContextTypes
import aioredis
# Настройка логирования
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
TOKEN = "YOUR_BOT_TOKEN"
bot = ApplicationBuilder().token(TOKEN).build()
redis = aioredis.from_url("redis://localhost")
@app.get("/", response_class=HTMLResponse)
async def root():
with open("index.html", "r") as f:
return f.read()
async def get_notes(user_id: int):
cached_notes = await redis.get(f"notes:{user_id}")
if cached_notes:
return cached_notes.decode().split(",")
return []
async def add_note(user_id: int, note: str):
notes = await get_notes(user_id)
notes.append(note)
await redis.set(f"notes:{user_id}", ",".join(notes))
logger.info(f"Added note for user {user_id}: {note}")
@app.post("/add_note")
async def add_note_api(request: Request):
data = await request.json()
user_id = data["user_id"]
note = data["note"]
await add_note(user_id, note)
return {"status": "success"}
@app.get("/get_notes/{user_id}")
async def get_notes_api(user_id: int):
notes = await get_notes(user_id)
logger.info(f"Retrieved notes for user {user_id}: {notes}")
return {"notes": notes}
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
keyboard = [
[InlineKeyboardButton("Open Mini App", web_app={"url": "https://your-domain.com"})],
]
reply_markup = InlineKeyboardMarkup(keyboard)
await update.message.reply_text("Welcome to NotesApp!", reply_markup=reply_markup)
logger.info(f"User {update.effective_user.id} started the bot")
bot.add_handler(CommandHandler("start", start))
@app.on_event("startup")
async def startup_event():
await bot.initialize()
await bot.start()
logger.info("Bot started")
@app.on_event("shutdown")
async def shutdown_event():
await bot.stop()
await redis.close()
logger.info("Bot stopped")
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
Этот код добавляет логирование, что поможет в отладке приложения.
Развертывание Telegram Mini App на сервере
Для развертывания нашего Mini App мы можем использовать Docker. Создадим Dockerfile
:
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Создадим файл docker-compose.yml
:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
environment:
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
depends_on:
- redis
redis:
image: "redis:alpine"
ports:
- "6379:6379"
Этот файл определяет два сервиса: наше веб-приложение и Redis для кэширования.
Теперь создадим файл .env
для хранения конфиденциальных данных:
TELEGRAM_BOT_TOKEN=your_bot_token_here
Для развертывания приложения выполните следующие команды:
docker-compose build
docker-compose up -d
Эти команды соберут и запустят ваше приложение в контейнерах Docker.
Оптимизация SEO для Telegram Mini App
Хотя Telegram Mini Apps работают внутри Telegram и не индексируются поисковыми системами напрямую, мы можем оптимизировать наше веб-приложение для лучшего обнаружения пользователями:
- Используйте осмысленные URL-адреса для различных функций вашего приложения.
- Добавьте метатеги для улучшения отображения ссылок на ваше приложение в чатах Telegram.
Обновим наш index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NotesApp - Your Personal Note Taking Telegram Mini App</title>
<meta name="description" content="NotesApp is a Telegram Mini App that allows you to create and manage your personal notes directly within Telegram.">
<meta property="og:title" content="NotesApp - Personal Note Taking in Telegram">
<meta property="og:description" content="Create, view, and manage your notes easily with NotesApp Telegram Mini App.">
<meta property="og:image" content="https://your-domain.com/static/notesapp-preview.jpg">
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<!-- Остальной код остается без изменений -->
</head>
<body>
<!-- Содержимое body остается без изменений -->
</body>
</html>
Мониторинг и аналитика Telegram Mini App
Для отслеживания производительности и использования вашего Mini App, добавим базовую аналитику. Мы будем использовать простой подход с логированием в файл, но в реальном проекте вы можете использовать более продвинутые инструменты аналитики.
Добавим следующий код в main.py
:
import logging
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
import time
# Настройка логирования
logging.basicConfig(
filename='app_analytics.log',
level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
app = FastAPI()
# Добавляем middleware для CORS и аналитики
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
logging.info(f"Path: {request.url.path}, Method: {request.method}, Process Time: {process_time:.4f}s")
return response
# Остальной код остается без изменений
Этот код будет логировать каждый запрос к вашему приложению, включая путь, метод и время обработки.
Обеспечение безопасности Telegram Mini App
Безопасность критически важна для любого веб-приложения. Вот несколько мер, которые мы можем предпринять:
- Используйте HTTPS для всех соединений.
- Валидируйте все входные данные от пользователя.
- Используйте безопасные заголовки HTTP.
Обновим наш main.py
:
from fastapi import FastAPI, Request, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from starlette.middleware.sessions import SessionMiddleware
import hashlib
import hmac
import json
app = FastAPI()
# Добавляем middleware
app.add_middleware(SessionMiddleware, secret_key="your-secret-key")
app.add_middleware(TrustedHostMiddleware, allowed_hosts=["your-domain.com"])
app.add_middleware(
CORSMiddleware,
allow_origins=["https://your-domain.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
security = HTTPBearer()
def verify_telegram_data(init_data: str, bot_token: str) -> bool:
try:
data = dict(param.split('=') for param in init_data.split('&'))
received_hash = data.pop('hash')
data_check_string = '\n'.join(f"{k}={v}" for k, v in sorted(data.items()))
secret_key = hmac.new("WebAppData".encode(), bot_token.encode(), hashlib.sha256).digest()
calculated_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest()
return calculated_hash == received_hash
except Exception:
return False
@app.post("/api/secure_endpoint")
async def secure_endpoint(request: Request, credentials: HTTPAuthorizationCredentials = Depends(security)):
init_data = credentials.credentials
if not verify_telegram_data(init_data, "YOUR_BOT_TOKEN"):
raise HTTPException(status_code=403, detail="Invalid authentication")
# Ваш защищенный код здесь
return {"message": "Authenticated successfully"}
# Остальной код остается без изменений
Этот код добавляет проверку подлинности данных, полученных от Telegram, и использует безопасные заголовки и CORS настройки.
Будущее Telegram Mini Apps
Telegram Mini Apps открывают новые возможности для разработчиков и пользователей, позволяя создавать богатые интерактивные приложения прямо внутри Telegram. С помощью Python и современных веб-технологий мы можем создавать мощные, безопасные и эффективные Mini Apps.
В этой статье мы рассмотрели основы создания Telegram Mini App на Python, начиная с базовой структуры и заканчивая развертыванием, оптимизацией и обеспечением безопасности. Продолжайте экспериментировать и расширять возможности вашего Mini App, и не забывайте следить за обновлениями Telegram Bot API для использования новых функций по мере их появления.
Надеюсь, это руководство поможет вам начать свой путь в разработке Telegram Mini Apps!