Обработка файлов и медиа в Telegram ботах
В этой статье мы рассмотрим, как работать с различными типами файлов и медиа в Telegram ботах: изображения, документы, аудио, видео и другие форматы.Содержание
- Типы медиа в Telegram
- Обработка изображений
- Работа с документами
- Аудио и видео
- Стикеры и анимации
- Голосовые сообщения
- Видеосообщения
- Обработка ошибок
Типы медиа в Telegram
Поддерживаемые форматы
# Основные типы медиа в Telegram
MEDIA_TYPES = {
'photo': {
'extensions': ['.jpg', '.jpeg', '.png', '.webp'],
'max_size': '10MB',
'description': 'Изображения'
},
'document': {
'extensions': ['.pdf', '.doc', '.docx', '.txt', '.zip', '.rar'],
'max_size': '2GB',
'description': 'Документы'
},
'video': {
'extensions': ['.mp4', '.avi', '.mov', '.mkv'],
'max_size': '2GB',
'description': 'Видео файлы'
},
'audio': {
'extensions': ['.mp3', '.wav', '.ogg', '.m4a'],
'max_size': '50MB',
'description': 'Аудио файлы'
},
'voice': {
'extensions': ['.ogg'],
'max_size': '20MB',
'description': 'Голосовые сообщения'
},
'video_note': {
'extensions': ['.mp4'],
'max_size': '1MB',
'description': 'Видеосообщения'
},
'sticker': {
'extensions': ['.webp', '.tgs'],
'max_size': '512KB',
'description': 'Стикеры'
},
'animation': {
'extensions': ['.gif', '.mp4'],
'max_size': '50MB',
'description': 'GIF анимации'
}
}Обработка изображений
Базовый обработчик фотографий
# handlers/media_handlers.py
import os
import requests
from PIL import Image
from telegram import Update
from telegram.ext import ContextTypes
import logging
logger = logging.getLogger(__name__)
async def handle_photo(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка фотографий"""
photo = update.message.photo[-1] # Берем фото наивысшего качества
user = update.effective_user
try:
# Получение информации о файле
file_info = await context.bot.get_file(photo.file_id)
# Создание директории для сохранения
os.makedirs('downloads/photos', exist_ok=True)
# Путь для сохранения
file_path = f"downloads/photos/{photo.file_id}.jpg"
# Скачивание файла
await file_info.download_to_drive(file_path)
# Получение метаданных изображения
with Image.open(file_path) as img:
width, height = img.size
format_type = img.format
mode = img.mode
# Отправка информации о фото
info_text = f"""
📸 Фото получено!
📏 Размер: {width}x{height} пикселей
📁 Формат: {format_type}
🎨 Режим: {mode}
💾 Размер файла: {os.path.getsize(file_path)} байт
🆔 File ID: {photo.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
# Отправка обработанного изображения
await send_processed_image(update, context, file_path)
except Exception as e:
logger.error(f"Ошибка при обработке фото: {e}")
await update.message.reply_text("❌ Произошла ошибка при обработке фото.")
async def send_processed_image(update: Update, context: ContextTypes.DEFAULT_TYPE, image_path: str):
"""Отправка обработанного изображения"""
try:
# Создание миниатюры
thumbnail_path = create_thumbnail(image_path)
# Отправка оригинального изображения с подписью
with open(image_path, 'rb') as photo_file:
await context.bot.send_photo(
chat_id=update.effective_chat.id,
photo=photo_file,
caption="🖼️ Обработанное изображение"
)
# Отправка миниатюры
with open(thumbnail_path, 'rb') as thumb_file:
await context.bot.send_photo(
chat_id=update.effective_chat.id,
photo=thumb_file,
caption="🔍 Миниатюра"
)
# Удаление временных файлов
os.remove(thumbnail_path)
except Exception as e:
logger.error(f"Ошибка при отправке обработанного изображения: {e}")
def create_thumbnail(image_path: str, size: tuple = (200, 200)) -> str:
"""Создание миниатюры изображения"""
thumbnail_path = image_path.replace('.jpg', '_thumb.jpg')
with Image.open(image_path) as img:
img.thumbnail(size, Image.Resampling.LANCZOS)
img.save(thumbnail_path, 'JPEG', quality=85)
return thumbnail_pathОбработка множественных фотографий
async def handle_photo_album(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка альбома фотографий"""
if update.message.media_group_id:
# Это часть медиа-группы (альбом)
media_group_id = update.message.media_group_id
# Проверяем, обрабатывали ли мы уже этот альбом
if hasattr(context, 'processed_albums'):
if media_group_id in context.processed_albums:
return
else:
context.processed_albums = set()
context.processed_albums.add(media_group_id)
# Обрабатываем только первое фото из альбома
photo = update.message.photo[-1]
try:
file_info = await context.bot.get_file(photo.file_id)
file_path = f"downloads/albums/{media_group_id}_{photo.file_id}.jpg"
os.makedirs('downloads/albums', exist_ok=True)
await file_info.download_to_drive(file_path)
await update.message.reply_text(
f"📸 Альбом получен!\n"
f"🆔 Media Group ID: {media_group_id}\n"
f"📁 Файл сохранен: {file_path}",
parse_mode='Markdown'
)
except Exception as e:
logger.error(f"Ошибка при обработке альбома: {e}")Работа с документами
Обработчик документов
``python
async def handle_document(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка документов"""
document = update.message.document
user = update.effective_user
try:
# Получение информации о документе
file_info = await context.bot.get_file(document.file_id)
# Проверка типа файла
file_extension = os.path.splitext(document.file_name)[1].lower()
allowed_extensions = ['.pdf', '.doc', '.docx', '.txt', '.py', '.js', '.html', '.css']
if file_extension not in allowed_extensions:
await update.message.reply_text(
f"❌ Неподдерживаемый тип файла: {file_extension}\n"
f"📋 Поддерживаемые форматы: {', '.join(allowed_extensions)}"
)
return
# Создание директории для сохранения
os.makedirs('downloads/documents', exist_ok=True)
# Путь для сохранения
file_path = f"downloads/documents/{document.file_name}"
# Скачивание файла
await file_info.download_to_drive(file_path)
# Информация о документе
file_size = os.path.getsize(file_path)
file_size_mb = file_size / (1024 * 1024)
info_text = f"""
📄 Документ получен!
📝 Название: {document.file_name}
📏 Размер: {file_size_mb:.2f} MB
🆔 File ID: {document.file_id}
📁 Путь: {file_path}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
# Обработка в зависимости от типа файла
await process_document_by_type(update, context, file_path, file_extension)
except Exception as e:
logger.error(f"Ошибка при обработке документа: {e}")
await update.message.reply_text("❌ Произошла ошибка при обработке документа.")
async def process_document_by_type(update: Update, context: ContextTypes.DEFAULT_TYPE, file_path: str, extension: str):
"""Обработка документа в зависимости от типа"""
try:
if extension == '.txt':
# Чтение текстового файла
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Отправка первых 1000 символов
preview = content[:1000] + "..." if len(content) > 1000 else content
await update.message.reply_text(f"📖 Содержимое файла:\n\n`\n{preview}\n`", parse_mode='Markdown')
elif extension == '.py':
# Анализ Python файла
with open(file_path, 'r', encoding='utf-8') as f:
lines = f.readlines()
# Подсчет строк кода
code_lines = [line for line in lines if line.strip() and not line.strip().startswith('#')]
comment_lines = [line for line in lines if line.strip().startswith('#')]
analysis_text = f"""
🐍 Анализ Python файла
📊 Всего строк: {len(lines)}
💻 Строк кода: {len(code_lines)}
💬 Комментариев: {len(comment_lines)}
📏 Пустых строк: {len(lines) - len(code_lines) - len(comment_lines)}
"""
await update.message.reply_text(analysis_text, parse_mode='Markdown')
elif extension == '.pdf':
# Информация о PDF (требует дополнительных библиотек)
await update.message.reply_text("📄 PDF файл получен. Для полного анализа требуется установка дополнительных библиотек.")
except Exception as e:
logger.error(f"Ошибка при обработке документа по типу: {e}")
`
Аудио и видео
Обработка аудио файлов
async def handle_audio(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка аудио файлов"""
audio = update.message.audio
try:
file_info = await context.bot.get_file(audio.file_id)
# Создание директории для аудио
os.makedirs('downloads/audio', exist_ok=True)
# Определение расширения файла
file_extension = '.mp3' # По умолчанию
if audio.mime_type:
if 'ogg' in audio.mime_type:
file_extension = '.ogg'
elif 'm4a' in audio.mime_type:
file_extension = '.m4a'
file_path = f"downloads/audio/{audio.file_id}{file_extension}"
# Скачивание файла
await file_info.download_to_drive(file_path)
# Информация об аудио
duration_minutes = audio.duration // 60
duration_seconds = audio.duration % 60
info_text = f"""
🎵 Аудио файл получен!
🎤 Исполнитель: {audio.performer or 'Не указан'}
🎼 Название: {audio.title or 'Не указано'}
⏱️ Длительность: {duration_minutes}:{duration_seconds:02d}
📏 Размер: {audio.file_size / (1024 * 1024):.2f} MB
🆔 File ID: {audio.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
except Exception as e:
logger.error(f"Ошибка при обработке аудио: {e}")
await update.message.reply_text("❌ Произошла ошибка при обработке аудио.")
async def handle_video(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка видео файлов"""
video = update.message.video
try:
file_info = await context.bot.get_file(video.file_id)
# Создание директории для видео
os.makedirs('downloads/video', exist_ok=True)
file_path = f"downloads/video/{video.file_id}.mp4"
# Скачивание файла
await file_info.download_to_drive(file_path)
# Информация о видео
duration_minutes = video.duration // 60
duration_seconds = video.duration % 60
info_text = f"""
🎬 Видео файл получен!
📏 Разрешение: {video.width}x{video.height}
⏱️ Длительность: {duration_minutes}:{duration_seconds:02d}
📏 Размер: {video.file_size / (1024 * 1024):.2f} MB
🆔 File ID: {video.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
except Exception as e:
logger.error(f"Ошибка при обработке видео: {e}")
await update.message.reply_text("❌ Произошла ошибка при обработке видео.")
Стикеры и анимации
Обработка стикеров
async def handle_sticker(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка стикеров"""
sticker = update.message.sticker
try:
# Информация о стикере
info_text = f"""
😀 Стикер получен!
📦 Набор: {sticker.set_name or 'Не указан'}
🎨 Тип: {sticker.type}
📏 Размер: {sticker.width}x{sticker.height}
🆔 File ID: {sticker.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
# Отправка информации о файле стикера
file_info = await context.bot.get_file(sticker.file_id)
# Создание директории для стикеров
os.makedirs('downloads/stickers', exist_ok=True)
file_path = f"downloads/stickers/{sticker.file_id}.webp"
await file_info.download_to_drive(file_path)
await update.message.reply_text(f"💾 Стикер сохранен: {file_path}")
except Exception as e:
logger.error(f"Ошибка при обработке стикера: {e}")
async def handle_animation(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка GIF анимаций"""
animation = update.message.animation
try:
file_info = await context.bot.get_file(animation.file_id)
# Создание директории для анимаций
os.makedirs('downloads/animations', exist_ok=True)
file_path = f"downloads/animations/{animation.file_id}.gif"
await file_info.download_to_drive(file_path)
# Информация об анимации
duration_minutes = animation.duration // 60
duration_seconds = animation.duration % 60
info_text = f"""
🎭 GIF анимация получена!
📏 Размер: {animation.width}x{animation.height}
⏱️ Длительность: {duration_minutes}:{duration_seconds:02d}
📏 Размер файла: {animation.file_size / (1024 * 1024):.2f} MB
🆔 File ID: {animation.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
except Exception as e:
logger.error(f"Ошибка при обработке анимации: {e}")
Голосовые сообщения
Обработка голосовых сообщений
async def handle_voice(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка голосовых сообщений"""
voice = update.message.voice
try:
file_info = await context.bot.get_file(voice.file_id)
# Создание директории для голосовых сообщений
os.makedirs('downloads/voice', exist_ok=True)
file_path = f"downloads/voice/{voice.file_id}.ogg"
await file_info.download_to_drive(file_path)
# Информация о голосовом сообщении
duration_minutes = voice.duration // 60
duration_seconds = voice.duration % 60
info_text = f"""
🎤 Голосовое сообщение получено!
⏱️ Длительность: {duration_minutes}:{duration_seconds:02d}
📏 Размер: {voice.file_size / 1024:.2f} KB
🆔 File ID: {voice.file_id}
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
# Отправка обратно голосового сообщения
with open(file_path, 'rb') as voice_file:
await context.bot.send_voice(
chat_id=update.effective_chat.id,
voice=voice_file,
caption="🔄 Ваше голосовое сообщение"
)
except Exception as e:
logger.error(f"Ошибка при обработке голосового сообщения: {e}")
Видеосообщения
Обработка видеосообщений
async def handle_video_note(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Обработка видеосообщений"""
video_note = update.message.video_note
try:
file_info = await context.bot.get_file(video_note.file_id)
# Создание директории для видеосообщений
os.makedirs('downloads/video_notes', exist_ok=True)
file_path = f"downloads/video_notes/{video_note.file_id}.mp4"
await file_info.download_to_drive(file_path)
# Информация о видеосообщении
duration_minutes = video_note.duration // 60
duration_seconds = video_note.duration % 60
info_text = f"""
📹 Видеосообщение получено!
📏 Размер: {video_note.length}x{video_note.length} (квадратное)
⏱️ Длительность: {duration_minutes}:{duration_seconds:02d}
📏 Размер файла: {video_note.file_size / (1024 * 1024):.2f} MB
🆔 File ID: {video_note.file_id}`
"""
await update.message.reply_text(info_text, parse_mode='Markdown')
except Exception as e:
logger.error(f"Ошибка при обработке видеосообщения: {e}")
Обработка ошибок
Универсальный обработчик ошибок
# utils/error_handler.py
import logging
from telegram import Update
from telegram.ext import ContextTypes
logger = logging.getLogger(__name__)
async def handle_media_error(update: Update, context: ContextTypes.DEFAULT_TYPE, error: Exception):
"""Универсальный обработчик ошибок медиа"""
error_messages = {
'FileNotFoundError': '❌ Файл не найден. Возможно, он был удален.',
'PermissionError': '❌ Нет прав доступа к файлу.',
'OSError': '❌ Ошибка операционной системы при работе с файлом.',
'ValueError': '❌ Некорректные данные файла.',
'MemoryError': '❌ Недостаточно памяти для обработки файла.',
'TimeoutError': '❌ Превышено время ожидания при загрузке файла.'
}
error_type = type(error).__name__
user_message = error_messages.get(error_type, f'❌ Произошла ошибка: {error_type}')
await update.message.reply_text(user_message)
logger.error(f"Ошибка при обработке медиа: {error}", exc_info=True)
# Декоратор для обработки ошибок
def media_error_handler(func):
"""Декоратор для обработки ошибок в медиа-функциях"""
async def wrapper(update: Update, context: ContextTypes.DEFAULT_TYPE):
try:
await func(update, context)
except Exception as e:
await handle_media_error(update, context, e)
return wrapper
Интеграция с основным ботом
# bot_with_media.py
import logging
from telegram import Update
from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes
from handlers.media_handlers import *
from utils.error_handler import media_error_handler
import os
from dotenv import load_dotenv
load_dotenv()
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.INFO
)
logger = logging.getLogger(__name__)
BOT_TOKEN = os.getenv('BOT_TOKEN')
@media_error_handler
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
"""Команда /start"""
await update.message.reply_text(
"🤖 Добро пожаловать в бот для обработки медиа!\n\n"
"Отправьте мне:\n"
"📸 Фото\n"
"📄 Документ\n"
"🎵 Аудио\n"
"🎬 Видео\n"
"🎤 Голосовое сообщение\n"
"📹 Видеосообщение\n"
"😀 Стикер\n"
"🎭 GIF анимацию"
)
def main():
"""Основная функция запуска бота"""
if not BOT_TOKEN:
logger.error("BOT_TOKEN не найден!")
return
# Создание приложения
application = Application.builder().token(BOT_TOKEN).build()
# Добавление обработчиков команд
application.add_handler(CommandHandler("start", start))
# Добавление обработчиков медиа
application.add_handler(MessageHandler(filters.PHOTO, handle_photo))
application.add_handler(MessageHandler(filters.Document.ALL, handle_document))
application.add_handler(MessageHandler(filters.AUDIO, handle_audio))
application.add_handler(MessageHandler(filters.VIDEO, handle_video))
application.add_handler(MessageHandler(filters.VOICE, handle_voice))
application.add_handler(MessageHandler(filters.VIDEO_NOTE, handle_video_note))
application.add_handler(MessageHandler(filters.STICKER, handle_sticker))
application.add_handler(MessageHandler(filters.ANIMATION, handle_animation))
# Запуск бота
logger.info("Бот для обработки медиа запущен!")
application.run_polling()
if __name__ == '__main__':
main()
Заключение
В этой статье мы рассмотрели:
- ✅ Типы медиа в Telegram и их ограничения
- ✅ Обработку изображений с созданием миниатюр
- ✅ Работу с документами различных форматов
- ✅ Обработку аудио и видео файлов
- ✅ Работу со стикерами и анимациями
- ✅ Обработку голосовых и видеосообщений
- ✅ Универсальную обработку ошибок
Теперь ваш бот может полноценно работать с любыми типами медиа-файлов!
Полезные ссылки
1475 просмотров
4 лайков
0 комментариев
Комментарии (0)
Пока нет комментариев. Будьте первым!