def _download_gif(self, file: telegram.File, channel_id: str = "") -> Tuple[IO[bytes], str, str, str]: """ Download and convert GIF image. Args: file: Telegram File object channel_id: Destination channel ID of the message Returns: Tuple[IO[bytes], str, str, str]: ``tempfile`` file-like object, MIME type, proposed file name """ file, _, filename, path = self._download_file(file, 'video/mpeg') gif_file = tempfile.NamedTemporaryFile(suffix='.gif') v = VideoFileClip(path) self.logger.info( "Convert Telegram MP4 to GIF from " "channel %s with size %s", channel_id, v.size) if channel_id == "blueset.wechat" and v.size[0] > 600: # Workaround: Compress GIF for slave channel `blueset.wechat` # TODO: Move this logic to `blueset.wechat` in the future subprocess.Popen([ "ffmpeg", "-y", "-i", path, '-vf', "scale=600:-2", gif_file.name ], bufsize=0).wait() else: v.write_gif(gif_file.name, program="ffmpeg") file.close() gif_file.seek(0) return gif_file, "image/gif", os.path.basename( gif_file.name), gif_file.name
def get_text_from_image(image_file: File) -> str: """Get text from image with google vision api""" # Get temp file path with tempfile library fd, temp_file_path = tempfile.mkstemp() # Download image image_file.download(temp_file_path) # Read image file as binary with open(temp_file_path, "rb") as image_file: content = image_file.read() # Create vision.Image object to use it in document_text_detection function image = vision.Image(content=content) # Get response from google vision api # client field will be add to function in telegram_bot.py script response = Ocr.client.document_text_detection(image=image) # Get text from response text = response.full_text_annotation.text # Close file, automatic deletion will occur os.close(fd) # Return text return text
def make_assertion(_, data, timeout=DEFAULT_NONE, df_value=DEFAULT_NONE): expected_timeout = method_timeout if df_value == DEFAULT_NONE else df_value if timeout != expected_timeout: pytest.fail( f'Got value {timeout} for "timeout", expected {expected_timeout}' ) for arg in (dkw for dkw in kwargs_need_default if dkw != 'timeout'): # 'None' should not be passed along to Telegram if df_value in [None, DEFAULT_NONE]: if arg in data: pytest.fail( f'Got value {data[arg]} for argument {arg}, expected it to be absent' ) else: value = data.get(arg, '`not passed at all`') if value != df_value: pytest.fail( f'Got value {value} for argument {arg} instead of {df_value}' ) if method.__name__ in ['get_file', 'get_small_file', 'get_big_file']: # This is here mainly for PassportFile.get_file, which calls .set_credentials on the # return value out = File(file_id='result', file_unique_id='result') nonlocal expected_return_values expected_return_values = [out] return out.to_dict() # Otherwise return None by default, as TGObject.de_json/list(None) in [None, []] # That way we can check what gets passed to Request.post without having to actually # make a request # Some methods expect specific output, so we allow to customize that return return_value
def get_file(file: telegram.File) -> BytesIO: attachment = BytesIO() attachment.name = str(uuid.uuid4()) + '.' + path.splitext(file.file_path)[1] file.download(out=attachment) attachment.seek(0, 0) return attachment
def getFile(self, file_id, **kwargs): """Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. Args: file_id: File identifier to get info about. Keyword Args: timeout (Optional[float]): If this value is specified, use it as the definitive timeout (in seconds) for urlopen() operations. Returns: :class:`telegram.File`: On success, a :class:`telegram.File` object is returned. Raises: :class:`telegram.TelegramError` """ url = '{0}/getFile'.format(self.base_url) data = {'file_id': file_id} result = request.post(url, data, timeout=kwargs.get('timeout')) if result.get('file_path'): result['file_path'] = '%s/%s' % (self.base_file_url, result['file_path']) return File.de_json(result)
def getFile(self, file_id): """Use this method to get basic info about a file and prepare it for downloading. For the moment, bots can download files of up to 20MB in size. Args: file_id: File identifier to get info about. Returns: Returns a telegram.File object """ url = '%s/getFile' % self.base_url data = {'file_id': file_id} result = request.post(url, data) if result.get('file_path'): result['file_path'] = '%s/%s' % (self.base_file_url, result['file_path']) return File.de_json(result)
def local_file(bot): return File( TestFile.file_id, TestFile.file_unique_id, file_path=str(data_file("local_file.txt")), file_size=TestFile.file_size, bot=bot, )
def file(bot): return File( TestFile.file_id, TestFile.file_unique_id, file_path=TestFile.file_path, file_size=TestFile.file_size, bot=bot, )
def local_file(bot): return File( TestFile.file_id, TestFile.file_unique_id, file_path=str(Path.cwd() / 'tests' / 'data' / 'local_file.txt'), file_size=TestFile.file_size, bot=bot, )
def append_photo(self, photo: File): extension_of_photo = photo.file_path[photo.file_path.rfind(".")::].lower() name_photo = f"ph{self.index_of_photo}" path = self.path_to_directory + name_photo + extension_of_photo photo.download(custom_path=path) self.photo_to_convert.append(path) self.index_of_photo += 1 if self.index_of_photo == self.amount_of_photo: return True else: return False
def _download_gif(self, file: telegram.File) -> Tuple[IO[bytes], str, str, str]: """ Download and convert GIF image. Args: file: Telegram File object Returns: Tuple[IO[bytes], str, str, str]: ``tempfile`` file-like object, MIME type, proposed file name """ file, _, filename, path = self._download_file(file, 'video/mpeg') gif_file = tempfile.NamedTemporaryFile(suffix='.gif') VideoFileClip(path).write_gif(gif_file.name, program="ffmpeg") file.close() gif_file.seek(0) return gif_file, "image/gif", os.path.basename( gif_file.name), gif_file.name
def test_equality(self, bot): a = File(self.file_id, self.file_unique_id, bot) b = File('', self.file_unique_id, bot) c = File(self.file_id, self.file_unique_id, None) d = File('', '', bot) e = Voice(self.file_id, self.file_unique_id, 0) assert a == b assert hash(a) == hash(b) assert a is not b assert a == c assert hash(a) == hash(c) assert a != d assert hash(a) != hash(d) assert a != e assert hash(a) != hash(e)
def test_de_json(self, bot): json_dict = { 'file_id': self.file_id, 'file_path': self.file_path, 'file_size': self.file_size } new_file = File.de_json(json_dict, bot) assert new_file.file_id == self.file_id assert new_file.file_path == self.file_path assert new_file.file_size == self.file_size
def test_de_json(self, bot): json_dict = { "file_id": self.file_id, "file_unique_id": self.file_unique_id, "file_path": self.file_path, "file_size": self.file_size, } new_file = File.de_json(json_dict, bot) assert new_file.file_id == self.file_id assert new_file.file_unique_id == self.file_unique_id assert new_file.file_path == self.file_path assert new_file.file_size == self.file_size
def make_assertion(**kw): # name == value makes sure that # a) we receive non-None input for all parameters # b) we receive the correct input for each kwarg received_kwargs = { name for name, value in kw.items() if name in ignored_args or value == name } if not received_kwargs == expected_args: raise Exception( f'{orig_bot_method.__name__} did not receive correct value for the parameters ' f'{expected_args - received_kwargs}' ) if bot_method_name == 'get_file': # This is here mainly for PassportFile.get_file, which calls .set_credentials on the # return value return File(file_id='result', file_unique_id='result') return True
def download_file(self, file: File, content_type: str): custom_path = os.environ['TG_BOT_TEMP'] if self.media_group: custom_path = os.path.join(custom_path, str(self.message.chat_id), str(self.message.media_group_id)) custom_path = os.path.realpath(custom_path) os.makedirs(custom_path, exist_ok=True) lock_file = os.path.join(custom_path, '.lock') if not os.path.exists(lock_file): open(lock_file, 'wt').close() basename = file.file_path and os.path.basename( file.file_path) or EXT[content_type] file_path = os.path.join(custom_path, f'{file.file_id}_{basename}') filename = file.download(custom_path=file_path) log.debug('File downloaded to dir `%s` filename `%s`', custom_path, filename) data = { 'type': content_type, 'filename': filename, 'caption': self.caption, } if self.media_group: json_file_path = os.path.join(custom_path, MEDIA_GROUP_FILE) json_dump = [] if os.path.exists(json_file_path): with open(json_file_path, 'rt') as json_file: json_dump = json.load(json_file) with open(json_file_path, 'wt') as json_file: json_dump.append(data) json.dump(json_dump, json_file, indent=4) setattr(self, content_type, [data]) os.remove(lock_file)
def get_file(*args, **kwargs): return File(args[1])
async def make_assertion(url, request_data: RequestData, df_value=DEFAULT_NONE, *args, **kwargs): data = request_data.parameters # Check regular arguments that need defaults for arg in (dkw for dkw in kwargs_need_default if dkw != "timeout"): # 'None' should not be passed along to Telegram if df_value in [None, DEFAULT_NONE]: if arg in data: pytest.fail( f"Got value {data[arg]} for argument {arg}, expected it to be absent" ) else: value = data.get(arg, "`not passed at all`") if value != df_value: pytest.fail( f"Got value {value} for argument {arg} instead of {df_value}" ) # Check InputMedia (parse_mode can have a default) def check_input_media(m: Dict): parse_mode = m.get("parse_mode", None) if df_value is DEFAULT_NONE: if parse_mode is not None: pytest.fail("InputMedia has non-None parse_mode") elif parse_mode != df_value: pytest.fail( f"Got value {parse_mode} for InputMedia.parse_mode instead of {df_value}" ) media = data.pop("media", None) if media: if isinstance(media, dict) and isinstance(media.get("type", None), InputMediaType): check_input_media(media) else: for m in media: check_input_media(m) # Check InlineQueryResults results = data.pop("results", []) for result in results: if df_value in [DEFAULT_NONE, None]: if "parse_mode" in result: pytest.fail( "ILQR has a parse mode, expected it to be absent") # Here we explicitly use that we only pass ILQRPhoto and ILQRArticle for testing # so ILQRPhoto is expected to have parse_mode if df_value is not in [DF_NONE, NONE] elif "photo" in result and result.get("parse_mode") != df_value: pytest.fail(f'Got value {result.get("parse_mode")} for ' f"ILQR.parse_mode instead of {df_value}") imc = result.get("input_message_content") if not imc: continue for attr in ["parse_mode", "disable_web_page_preview"]: if df_value in [DEFAULT_NONE, None]: if attr in imc: pytest.fail( f"ILQR.i_m_c has a {attr}, expected it to be absent" ) # Here we explicitly use that we only pass InputTextMessageContent for testing # which has both attributes elif imc.get(attr) != df_value: pytest.fail( f"Got value {imc.get(attr)} for ILQR.i_m_c.{attr} instead of {df_value}" ) # Check datetime conversion until_date = data.pop("until_date", None) if until_date: if df_value == "non-None-value": if until_date != 946681200: pytest.fail( "Non-naive until_date was interpreted as Europe/Berlin." ) if df_value is DEFAULT_NONE: if until_date != 946684800: pytest.fail("Naive until_date was not interpreted as UTC") if df_value == "custom_default": if until_date != 946702800: pytest.fail( "Naive until_date was not interpreted as America/New_York" ) if method.__name__ in ["get_file", "get_small_file", "get_big_file"]: # This is here mainly for PassportFile.get_file, which calls .set_credentials on the # return value out = File(file_id="result", file_unique_id="result") nonlocal expected_return_values expected_return_values = [out] return out.to_dict() # Otherwise return None by default, as TGObject.de_json/list(None) in [None, []] # That way we can check what gets passed to Request.post without having to actually # make a request # Some methods expect specific output, so we allow to customize that return return_value
def make_assertion(*_, **kwargs): result = kwargs[ 'file_id'] == passport_file.file_id and check_shortcut_call( kwargs, get_file) # we need to be a bit hacky here, b/c PF.get_file needs Bot.get_file to return a File return File(file_id=result, file_unique_id=result)
def save_xls(update, context): f = File() name = f.download() return SAVING_RESUME
async def get_file(*_, **kwargs): return File(kwargs["file_id"], selfie.file_unique_id)
async def make_assertion(*_, **kwargs): result = kwargs["file_id"] == passport_file.file_id # we need to be a bit hacky here, b/c PF.get_file needs Bot.get_file to return a File return File(file_id=result, file_unique_id=result)
def getPhoto(bot, update): logger.info('Someone had send me photo') update.message.reply_text("Thanks") picture = bot.getFile(update.message.photo[-1]['file_id']) filename = basename(picture['file_path']) File.download(picture, CONF['BOT']['DOWNLOADFOLDER'] + filename)
def download_file(file: File) -> Text: """Request the download of a file""" file_path = os.path.join(downloads_dir, file.file_unique_id) with open(file_path, 'wb') as out: file.download(custom_path=None, out=out) return file_path
def get_file(*_, **kwargs): return File(kwargs['file_id'], selfie.file_unique_id)
def file(bot): return File(file_id=TestFile.file_id, file_path=TestFile.file_path, file_size=TestFile.file_size, bot=bot)
def get_file(*args, **kwargs): return File(args[0], selfie.file_unique_id)
class TestSticker: # sticker_file_url = 'https://python-telegram-bot.org/static/testfiles/telegram.webp' # Serving sticker from gh since our server sends wrong content_type sticker_file_url = ( "https://github.com/python-telegram-bot/python-telegram-bot/blob/master" "/tests/data/telegram.webp?raw=true") emoji = "💪" width = 510 height = 512 is_animated = False is_video = False file_size = 39518 thumb_width = 319 thumb_height = 320 thumb_file_size = 21472 sticker_file_id = "5a3128a4d2a04750b5b58397f3b5e812" sticker_file_unique_id = "adc3145fd2e84d95b64d68eaa22aa33e" premium_animation = File("this_is_an_id", "this_is_an_unique_id") def test_slot_behaviour(self, sticker, mro_slots, recwarn): for attr in sticker.__slots__: assert getattr(sticker, attr, "err") != "err", f"got extra slot '{attr}'" assert len(mro_slots(sticker)) == len(set( mro_slots(sticker))), "duplicate slot" def test_creation(self, sticker): # Make sure file has been uploaded. assert isinstance(sticker, Sticker) assert isinstance(sticker.file_id, str) assert isinstance(sticker.file_unique_id, str) assert sticker.file_id != "" assert sticker.file_unique_id != "" assert isinstance(sticker.thumb, PhotoSize) assert isinstance(sticker.thumb.file_id, str) assert isinstance(sticker.thumb.file_unique_id, str) assert sticker.thumb.file_id != "" assert sticker.thumb.file_unique_id != "" def test_expected_values(self, sticker): assert sticker.width == self.width assert sticker.height == self.height assert sticker.is_animated == self.is_animated assert sticker.is_video == self.is_video assert sticker.file_size == self.file_size assert sticker.thumb.width == self.thumb_width assert sticker.thumb.height == self.thumb_height assert sticker.thumb.file_size == self.thumb_file_size # we need to be a premium TG user to send a premium sticker, so the below is not tested # assert sticker.premium_animation == self.premium_animation @flaky(3, 1) async def test_send_all_args(self, bot, chat_id, sticker_file, sticker): message = await bot.send_sticker(chat_id, sticker=sticker_file, disable_notification=False, protect_content=True) assert isinstance(message.sticker, Sticker) assert isinstance(message.sticker.file_id, str) assert isinstance(message.sticker.file_unique_id, str) assert message.sticker.file_id != "" assert message.sticker.file_unique_id != "" assert message.sticker.width == sticker.width assert message.sticker.height == sticker.height assert message.sticker.is_animated == sticker.is_animated assert message.sticker.is_video == sticker.is_video assert message.sticker.file_size == sticker.file_size # we need to be a premium TG user to send a premium sticker, so the below is not tested # assert message.sticker.premium_animation == sticker.premium_animation assert isinstance(message.sticker.thumb, PhotoSize) assert isinstance(message.sticker.thumb.file_id, str) assert isinstance(message.sticker.thumb.file_unique_id, str) assert message.sticker.thumb.file_id != "" assert message.sticker.thumb.file_unique_id != "" assert message.sticker.thumb.width == sticker.thumb.width assert message.sticker.thumb.height == sticker.thumb.height assert message.sticker.thumb.file_size == sticker.thumb.file_size assert message.has_protected_content @flaky(3, 1) async def test_get_and_download(self, bot, sticker): path = Path("telegram.webp") if path.is_file(): path.unlink() new_file = await bot.get_file(sticker.file_id) assert new_file.file_size == sticker.file_size assert new_file.file_id == sticker.file_id assert new_file.file_unique_id == sticker.file_unique_id assert new_file.file_path.startswith("https://") await new_file.download("telegram.webp") assert path.is_file() @flaky(3, 1) async def test_resend(self, bot, chat_id, sticker): message = await bot.send_sticker(chat_id=chat_id, sticker=sticker.file_id) assert message.sticker == sticker @flaky(3, 1) async def test_send_on_server_emoji(self, bot, chat_id): server_file_id = "CAADAQADHAADyIsGAAFZfq1bphjqlgI" message = await bot.send_sticker(chat_id=chat_id, sticker=server_file_id) sticker = message.sticker assert sticker.emoji == self.emoji @flaky(3, 1) async def test_send_from_url(self, bot, chat_id): message = await bot.send_sticker(chat_id=chat_id, sticker=self.sticker_file_url) sticker = message.sticker assert isinstance(message.sticker, Sticker) assert isinstance(message.sticker.file_id, str) assert isinstance(message.sticker.file_unique_id, str) assert message.sticker.file_id != "" assert message.sticker.file_unique_id != "" assert message.sticker.width == sticker.width assert message.sticker.height == sticker.height assert message.sticker.is_animated == sticker.is_animated assert message.sticker.is_video == sticker.is_video assert message.sticker.file_size == sticker.file_size assert isinstance(message.sticker.thumb, PhotoSize) assert isinstance(message.sticker.thumb.file_id, str) assert isinstance(message.sticker.thumb.file_unique_id, str) assert message.sticker.thumb.file_id != "" assert message.sticker.thumb.file_unique_id != "" assert message.sticker.thumb.width == sticker.thumb.width assert message.sticker.thumb.height == sticker.thumb.height assert message.sticker.thumb.file_size == sticker.thumb.file_size def test_de_json(self, bot, sticker): json_dict = { "file_id": self.sticker_file_id, "file_unique_id": self.sticker_file_unique_id, "width": self.width, "height": self.height, "is_animated": self.is_animated, "is_video": self.is_video, "thumb": sticker.thumb.to_dict(), "emoji": self.emoji, "file_size": self.file_size, "premium_animation": self.premium_animation.to_dict(), } json_sticker = Sticker.de_json(json_dict, bot) assert json_sticker.file_id == self.sticker_file_id assert json_sticker.file_unique_id == self.sticker_file_unique_id assert json_sticker.width == self.width assert json_sticker.height == self.height assert json_sticker.is_animated == self.is_animated assert json_sticker.is_video == self.is_video assert json_sticker.emoji == self.emoji assert json_sticker.file_size == self.file_size assert json_sticker.thumb == sticker.thumb assert json_sticker.premium_animation == self.premium_animation async def test_send_with_sticker(self, monkeypatch, bot, chat_id, sticker): async def make_assertion(url, request_data: RequestData, *args, **kwargs): return request_data.json_parameters["sticker"] == sticker.file_id monkeypatch.setattr(bot.request, "post", make_assertion) message = await bot.send_sticker(sticker=sticker, chat_id=chat_id) assert message async def test_send_sticker_local_files(self, monkeypatch, bot, chat_id): # For just test that the correct paths are passed as we have no local bot API set up test_flag = False file = data_file("telegram.jpg") expected = file.as_uri() async def make_assertion(_, data, *args, **kwargs): nonlocal test_flag test_flag = data.get("sticker") == expected monkeypatch.setattr(bot, "_post", make_assertion) await bot.send_sticker(chat_id, file) assert test_flag monkeypatch.delattr(bot, "_post") @flaky(3, 1) @pytest.mark.parametrize( "default_bot,custom", [ ({ "allow_sending_without_reply": True }, None), ({ "allow_sending_without_reply": False }, None), ({ "allow_sending_without_reply": False }, True), ], indirect=["default_bot"], ) async def test_send_sticker_default_allow_sending_without_reply( self, default_bot, chat_id, sticker, custom): reply_to_message = await default_bot.send_message(chat_id, "test") await reply_to_message.delete() if custom is not None: message = await default_bot.send_sticker( chat_id, sticker, allow_sending_without_reply=custom, reply_to_message_id=reply_to_message.message_id, ) assert message.reply_to_message is None elif default_bot.defaults.allow_sending_without_reply: message = await default_bot.send_sticker( chat_id, sticker, reply_to_message_id=reply_to_message.message_id) assert message.reply_to_message is None else: with pytest.raises(BadRequest, match="message not found"): await default_bot.send_sticker( chat_id, sticker, reply_to_message_id=reply_to_message.message_id) @flaky(3, 1) @pytest.mark.parametrize("default_bot", [{ "protect_content": True }], indirect=True) async def test_send_sticker_default_protect_content( self, chat_id, sticker, default_bot): protected = await default_bot.send_sticker(chat_id, sticker) assert protected.has_protected_content unprotected = await default_bot.send_sticker(chat_id, sticker, protect_content=False) assert not unprotected.has_protected_content def test_to_dict(self, sticker): sticker_dict = sticker.to_dict() assert isinstance(sticker_dict, dict) assert sticker_dict["file_id"] == sticker.file_id assert sticker_dict["file_unique_id"] == sticker.file_unique_id assert sticker_dict["width"] == sticker.width assert sticker_dict["height"] == sticker.height assert sticker_dict["is_animated"] == sticker.is_animated assert sticker_dict["is_video"] == sticker.is_video assert sticker_dict["file_size"] == sticker.file_size assert sticker_dict["thumb"] == sticker.thumb.to_dict() @flaky(3, 1) async def test_error_send_empty_file(self, bot, chat_id): with pytest.raises(TelegramError): await bot.send_sticker(chat_id, open(os.devnull, "rb")) @flaky(3, 1) async def test_error_send_empty_file_id(self, bot, chat_id): with pytest.raises(TelegramError): await bot.send_sticker(chat_id, "") async def test_error_without_required_args(self, bot, chat_id): with pytest.raises(TypeError): await bot.send_sticker(chat_id) @flaky(3, 1) async def test_premium_animation(self, bot): # testing animation sucks a bit since we can't create a premium sticker. What we can do is # get a sticker set which includes a premium sticker and check that specific one. premium_sticker_set = await bot.get_sticker_set("Flame") # the first one to appear here is a sticker with unique file id of AQADOBwAAifPOElr # this could change in the future ofc. premium_sticker = premium_sticker_set.stickers[20] assert premium_sticker.premium_animation.file_unique_id == "AQADOBwAAifPOElr" assert isinstance(premium_sticker.premium_animation.file_id, str) assert premium_sticker.premium_animation.file_id != "" premium_sticker_dict = { "file_unique_id": "AQADOBwAAifPOElr", "file_id": premium_sticker.premium_animation.file_id, "file_size": premium_sticker.premium_animation.file_size, } assert premium_sticker.premium_animation.to_dict( ) == premium_sticker_dict def test_equality(self, sticker): a = Sticker( sticker.file_id, sticker.file_unique_id, self.width, self.height, self.is_animated, self.is_video, ) b = Sticker("", sticker.file_unique_id, self.width, self.height, self.is_animated, self.is_video) c = Sticker(sticker.file_id, sticker.file_unique_id, 0, 0, False, True) d = Sticker("", "", self.width, self.height, self.is_animated, self.is_video) e = PhotoSize(sticker.file_id, sticker.file_unique_id, self.width, self.height, self.is_animated) assert a == b assert hash(a) == hash(b) assert a is not b assert a == c assert hash(a) == hash(c) assert a != d assert hash(a) != hash(d) assert a != e assert hash(a) != hash(e)