python-telegram-bot/telegram/files/inputfile.py

174 lines
5.2 KiB
Python
Raw Normal View History

#!/usr/bin/env python
# pylint: disable=W0622,E0611
2015-08-11 21:58:17 +02:00
#
# A library that provides a Python interface to the Telegram Bot API
# Copyright (C) 2015-2017
# Leandro Toledo de Souza <devs@python-telegram-bot.org>
2015-08-11 21:58:17 +02:00
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser Public License for more details.
#
# You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/].
2016-10-17 00:22:40 +02:00
"""This module contains an object that represents a Telegram InputFile."""
2015-08-10 18:57:31 +02:00
try:
# python 3
from email.generator import _make_boundary as choose_boundary
except ImportError:
# python 2
from mimetools import choose_boundary
import imghdr
import mimetypes
import os
import sys
from telegram import TelegramError
DEFAULT_MIME_TYPE = 'application/octet-stream'
2016-05-15 04:26:56 +02:00
USER_AGENT = 'Python Telegram Bot (https://github.com/python-telegram-bot/python-telegram-bot)'
2017-05-21 13:50:52 +02:00
FILE_TYPES = ('audio', 'document', 'photo', 'sticker', 'video', 'voice', 'certificate',
'video_note')
class InputFile(object):
"""This object represents a Telegram InputFile."""
def __init__(self, data):
self.data = data
self.boundary = choose_boundary()
2017-05-25 14:13:35 +02:00
for t in FILE_TYPES:
if t in data:
self.input_name = t
self.input_file = data.pop(t)
break
else:
raise TelegramError('Unknown inputfile type')
if hasattr(self.input_file, 'read'):
self.filename = None
2015-07-11 00:46:15 +02:00
self.input_file_content = self.input_file.read()
2015-09-08 20:52:10 +02:00
if 'filename' in data:
self.filename = self.data.pop('filename')
elif hasattr(self.input_file, 'name'):
# on py2.7, pylint fails to understand this properly
# pylint: disable=E1101
self.filename = os.path.basename(self.input_file.name)
try:
self.mimetype = self.is_image(self.input_file_content)
if not self.filename or '.' not in self.filename:
self.filename = self.mimetype.replace('/', '.')
except TelegramError:
if self.filename:
self.mimetype = mimetypes.guess_type(
self.filename)[0] or DEFAULT_MIME_TYPE
else:
self.mimetype = DEFAULT_MIME_TYPE
@property
def headers(self):
"""
Returns:
2017-06-07 13:07:45 +02:00
str
"""
return {'User-agent': USER_AGENT, 'Content-type': self.content_type}
@property
def content_type(self):
"""
Returns:
2017-06-07 13:07:45 +02:00
str
"""
return 'multipart/form-data; boundary=%s' % self.boundary
def to_form(self):
"""
Returns:
2017-06-07 13:07:45 +02:00
str
"""
form = []
form_boundary = '--' + self.boundary
# Add data fields
for name in iter(self.data):
value = self.data[name]
form.extend([
form_boundary, 'Content-Disposition: form-data; name="%s"' % name, '', str(value)
])
2017-05-25 14:13:35 +02:00
# Add input_file to upload
form.extend([
2016-08-26 11:17:05 +02:00
form_boundary, 'Content-Disposition: form-data; name="%s"; filename="%s"' %
(self.input_name,
self.filename), 'Content-Type: %s' % self.mimetype, '', self.input_file_content
])
form.append('--' + self.boundary + '--')
form.append('')
return self._parse(form)
@staticmethod
def _parse(form):
"""
Returns:
2017-06-07 13:07:45 +02:00
str
"""
if sys.version_info > (3,):
# on Python 3 form needs to be byte encoded
encoded_form = []
for item in form:
try:
encoded_form.append(item.encode())
except AttributeError:
encoded_form.append(item)
return b'\r\n'.join(encoded_form)
return '\r\n'.join(form)
2015-07-13 23:53:30 +02:00
@staticmethod
def is_image(stream):
"""Check if the content file is an image by analyzing its headers.
Args:
stream (str): A str representing the content of a file.
Returns:
str: The str mimetype of an image.
"""
image = imghdr.what(None, stream)
if image:
return 'image/%s' % image
raise TelegramError('Could not parse file content')
@staticmethod
def is_inputfile(data):
"""Check if the request is a file request.
Args:
data (dict): A dict of (str, unicode) key/value pairs
Returns:
bool
"""
if data:
file_type = [i for i in iter(data) if i in FILE_TYPES]
if file_type:
file_content = data[file_type[0]]
2015-07-13 23:53:30 +02:00
return hasattr(file_content, 'read')
2015-07-13 23:53:30 +02:00
return False