Telethon icon indicating copy to clipboard operation
Telethon copied to clipboard

FilePart0Missing Error While Editing Inline Medias.

Open StarkGang opened this issue 3 years ago • 15 comments

Checklist

  • [X] The error is in the library's code, and not in my own.
  • [X] I have searched for this issue before posting it and there isn't a duplicate.
  • [X] I ran pip install -U https://github.com/LonamiWebs/Telethon/archive/master.zip and triggered the bug in the latest version.

Code that causes the issue

from telethon import TelegramClient, events, Button
client = TelegramClient("..", 1, "...").start(bot_token="...")

@client.on(events.NewMessage)
async def _(e):
  await e.reply("...", buttons=Button.inline('Click me', b'clk1'))

@client.on(events.callbackquery.CallbackQuery(data=re.compile(b"clk1")))
async def _(e):
  uploaded_file = await client.upload_file(
  		file='test.txt'
        )
  await e.edit(file=uploaded_file)

Traceback

- telethon.client.telegrambaseclient - INFO - Exporting auth for new borrowed sender in DcOption(id=2, ip_address='149.154.167.51', port=443, ipv6=False, media_only=False, tcpo_only=False, cdn=False, static=False, secret=None)
- telethon.client.uploads - INFO - Uploading file of 9781769 bytes in 75 chunks of 131072
- telethon.errors.rpcerrorlist.FilePart0MissingError: File part 0 missing (caused by EditInlineBotMessageRequest)
- telethon.client.telegrambaseclient - INFO - Disconnecting borrowed sender for DC 2
- telethon.network.mtprotosender - INFO - Disconnecting from 149.154.167.51:443/TcpFull...
- telethon.network.mtprotosender - INFO - Disconnection from 149.154.167.51:443/TcpFull complete!

StarkGang avatar Jan 09 '21 04:01 StarkGang

I cannot reproduce this issue. Does it need to be tested in a private conversation, small group chat, megagroup channel, or broadcast channel? Does the bot's datacenter matter? Does the group's datacenter matter? Does the datacenter of the user making the query matter?

Lonami avatar Jan 09 '21 16:01 Lonami

I got this error on a mega group, where the owner's Dc is 5 and bot's Dc is also 5 and I got this error my Dc is also 5.

StarkGang avatar Jan 10 '21 04:01 StarkGang

Please upload or otherwise provide the contents of the file somehow so that I can test with a file that triggers the bug.

Lonami avatar Jan 10 '21 09:01 Lonami

Its a media file. happens with videos mostly.

StarkGang avatar Jan 12 '21 08:01 StarkGang

@Lonami, I am too having this Error, I am. Trying to edit media send via Inline Queries, it's Occuring with Text files too, (while when used with send_file, they are fine)

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/telethon/client/updates.py", line 454, in _dispatch_update
    await callback(event)
  File "/root/TeamUltroid/assistant/othervars.py", line 62, in send
    await eve.edit(file=plugin, buttons=buttons)
  File "/usr/local/lib/python3.9/site-packages/telethon/events/callbackquery.py", line 316, in edit
    return await self._client.edit_message(
  File "/usr/local/lib/python3.9/site-packages/telethon/client/messages.py", line 1148, in edit_message
    return await self._call(sender, request)
  File "/usr/local/lib/python3.9/site-packages/telethon/client/users.py", line 79, in _call
    result = await future
telethon.errors.rpcerrorlist.FilePart0MissingError: File part 0 missing (caused by EditInlineBotMessageRequest)

It's going for if statement ( dc_id are not same) - https://github.com/LonamiWebs/Telethon/blob/6b53d45ce27510335f5f33db510a4ee4e3a29a91/telethon/client/messages.py#L1120

Maybe something with invoking request from right DC

New-dev0 avatar Jun 06 '21 05:06 New-dev0

Yeah, maybe both the upload and request have to be invoked in the other DC.

Lonami avatar Jun 08 '21 17:06 Lonami

Yeah, maybe both the upload and request have to be invoked in the other DC.

Lonami, how it can be achieved?

New-dev0 avatar Jun 09 '21 13:06 New-dev0

Presumably, the exported sender needs to be used for the upload too, and not just the request invocation.

Lonami avatar Jun 09 '21 13:06 Lonami

Just encountered the same bug, in a public channel (with a handle).

A log, if that helps at all. I was replacing an image with an mp4

2021-06-09 23:34:12,929:INFO:fa_search_bot.sites.fa_submission:Loading gif from cache, submission ID 42264312
2021-06-09 23:34:12,934:INFO:usage:Pretty gif: from cache
2021-06-09 23:34:12,934:INFO:telethon.client.uploads:Uploading file of 709092 bytes in 6 chunks of 131072
2021-06-09 23:34:13,678:INFO:telethon.network.mtprotosender:Connecting to 149.154.167.51:443/TcpFull...
2021-06-09 23:34:13,704:INFO:telethon.network.mtprotosender:Connection to 149.154.167.51:443/TcpFull complete!
2021-06-09 23:34:13,757:ERROR:fa_search_bot.sites.fa_submission:Failed to convert gif to video. Submission ID: 42264312
Traceback (most recent call last):
  File "/home/spangle/FA-search-bot/fa_search_bot/sites/fa_submission.py", line 309, in _send_gif
    await send_partial(open(filename, "rb"))
  File "/home/spangle/FA-search-bot/fa_search_bot/sites/fa_submission.py", line 247, in send_partial
    await client.edit_message(
  File "/home/spangle/FA-search-bot/venv/lib/python3.8/site-packages/telethon/client/messages.py", line 1093, in edit_message
    return await self._call(sender, request)
  File "/home/spangle/FA-search-bot/venv/lib/python3.8/site-packages/telethon/client/users.py", line 79, in _call
    result = await future
telethon.errors.rpcerrorlist.FilePart0MissingError: File part 0 missing (caused by EditInlineBotMessageRequest)
2021-06-09 23:34:13,981:INFO:telethon.client.uploads:Uploading file of 122679 bytes in 1 chunks of 131072

Deer-Spangle avatar Jun 09 '21 23:06 Deer-Spangle

I've tried uploading the file to a different datacenter, but I constantly get PHONE_MIGRATED, so that does not seem to be the solution.

Support upload to other DCs patch
diff --git a/telethon/client/messages.py b/telethon/client/messages.py
index 6bdb7f5d..367e3180 100644
--- a/telethon/client/messages.py
+++ b/telethon/client/messages.py
@@ -1114,9 +1114,11 @@ class MessageMethods:
                 # or
                 await client.edit_message(message, 'hello!!!')
         """
+        dc_id = None
         if isinstance(entity, types.InputBotInlineMessageID):
             text = text or message
             message = entity
+            dc_id = message.dc_id
         elif isinstance(entity, types.Message):
             text = message  # Shift the parameters to the right
             message = entity
@@ -1124,11 +1126,15 @@ class MessageMethods:
 
         if formatting_entities is None:
             text, formatting_entities = await self._parse_message_text(text, parse_mode)
-        file_handle, media, image = await self._file_to_media(file,
-                supports_streaming=supports_streaming,
-                thumb=thumb,
-                attributes=attributes,
-                force_document=force_document)
+
+        file_handle, media, image = await self._file_to_media(
+            file,
+            supports_streaming=supports_streaming,
+            thumb=thumb,
+            attributes=attributes,
+            force_document=force_document,
+            dc_id=dc_id
+        )
 
         if isinstance(entity, types.InputBotInlineMessageID):
             request = functions.messages.EditInlineBotMessageRequest(
@@ -1141,10 +1147,10 @@ class MessageMethods:
             )
             # Invoke `messages.editInlineBotMessage` from the right datacenter.
             # Otherwise, Telegram will error with `MESSAGE_ID_INVALID` and do nothing.
-            exported = self.session.dc_id != entity.dc_id
+            exported = self.session.dc_id != dc_id
             if exported:
                 try:
-                    sender = await self._borrow_exported_sender(entity.dc_id)
+                    sender = await self._borrow_exported_sender(dc_id)
                     return await self._call(sender, request)
                 finally:
                     await self._return_exported_sender(sender)
diff --git a/telethon/client/uploads.py b/telethon/client/uploads.py
index 544b7087..b0c442de 100644
--- a/telethon/client/uploads.py
+++ b/telethon/client/uploads.py
@@ -35,6 +35,30 @@ class _CacheType:
         return self._cls == other
 
 
+# TODO use this as opposed to borrow sender? (context manager)
+class _Sender:
+    def __init__(self, client, dc_id):
+        self._client = client
+        self._dc_id = None if dc_id is None or client.session.dc_id == dc_id else dc_id
+        self._sender = None
+
+    async def __aenter__(self):
+        if self._dc_id is not None:
+            self._sender = await self._client._borrow_exported_sender(self._dc_id)
+        return self
+
+    async def __aexit__(self, exc_type, exc_val, exc_tb):
+        if self._sender:
+            await self._client._return_exported_sender(self._sender)
+
+    async def invoke(self, *args, **kwargs):
+        if self._sender:
+            print('CALLING ON EXPORTED', self._dc_id, args, kwargs)
+            return await self._client._call(self._sender, *args, **kwargs)
+        else:
+            return await self._client(*args, **kwargs)
+
+
 def _resize_photo_if_needed(
         file, is_image, width=1280, height=1280, background=(255, 255, 255)):
 
@@ -473,7 +497,9 @@ class UploadMethods:
             use_cache: type = None,
             key: bytes = None,
             iv: bytes = None,
-            progress_callback: 'hints.ProgressCallback' = None) -> 'types.TypeInputFile':
+            progress_callback: 'hints.ProgressCallback' = None,
+            dc_id: int = None
+    ) -> 'types.TypeInputFile':
         """
         Uploads a file to Telegram's servers, without sending it.
 
@@ -527,6 +553,9 @@ class UploadMethods:
                 A callback function accepting two parameters:
                 ``(sent bytes, total)``.
 
+            dc_id (`int`, optional):
+                Upload the file to a different DC. You probably shouldn't use this.
+
         Returns
             :tl:`InputFileBig` if the file size is larger than 10MB,
             `InputSizedFile <telethon.tl.custom.inputsizedfile.InputSizedFile>`
@@ -552,7 +581,8 @@ class UploadMethods:
             return file  # Already uploaded
 
         pos = 0
-        async with helpers._FileStream(file, file_size=file_size) as stream:
+        async with helpers._FileStream(file, file_size=file_size) as stream, \
+                _Sender(self, dc_id) as sender:
             # Opening the stream will determine the correct file size
             file_size = stream.file_size
 
@@ -625,7 +655,7 @@ class UploadMethods:
                     request = functions.upload.SaveFilePartRequest(
                         file_id, part_index, part)
 
-                result = await self(request)
+                result = await sender.invoke(request)
                 if result:
                     self._log[__name__].debug('Uploaded %d/%d',
                                               part_index + 1, part_count)
@@ -648,7 +678,8 @@ class UploadMethods:
             self, file, force_document=False, file_size=None,
             progress_callback=None, attributes=None, thumb=None,
             allow_cache=True, voice_note=False, video_note=False,
-            supports_streaming=False, mime_type=None, as_image=None):
+            supports_streaming=False, mime_type=None, as_image=None,
+            dc_id=None):
         if not file:
             return None, None, None

Lonami avatar Jun 19 '21 16:06 Lonami

Lonami, I just Tried What you did, and got KeyError.

Complete TraceBack - https://hastebin.com/udavanapic.sql

New-dev0 avatar Jun 29 '21 14:06 New-dev0

Seems connection failed on __aenter__ so the exit fails too.

Lonami avatar Jun 29 '21 18:06 Lonami

Editing Inline Media is already working fine for document already on Telegram. Problem is/was only for local Files.

So I just Tried

msg_media = await client.upload_file('file.txt')
media = await client(functions.messages.UploadMediaRequest(types.InputPeerSelf(), msg_media))
await event.edit(file=media)

And luckily it worked

New-dev0 avatar Jul 04 '21 14:07 New-dev0

Lately , I found

FILE_PART_Х_MISSING: Part X (where X is a number) 
of the file is missing from storage. Try repeating the 
method call to resave the part.

Is Mentioned at https://core.telegram.org/api/files

Maybe, that's what https://github.com/LonamiWebs/Telethon/issues/1668#issuecomment-873602782, is doing

New-dev0 avatar Jul 05 '21 13:07 New-dev0

I think, apparently it is not allowed, the BOT API docs was updated,.

I think for editing inline messages, you need to send message to some chat, and edit using the sent message file_id,

I think, getting the file id is currently broken in master branch, due to the layer 130 update.

SpEcHiDe avatar Aug 07 '21 08:08 SpEcHiDe