grammers icon indicating copy to clipboard operation
grammers copied to clipboard

Cannot download "GIF" mp4

Open frozenspider opened this issue 7 months ago • 2 comments

With latest commit of grammers (ed516f5), attempting to download "GIF" (so, mp4 file document) results in request error: rpc error 400: AUTH_BYTES_INVALID caused by auth.importAuthorization. Other media seem to be downloaded fine. To make matters worse, sometimes - very rarely - downloading GIF works, and I can't figure out what causes this.

Code doing the download, when stripped of unrelated stuff, looks like this:

use grammers_client::types::Media;
use grammers_client::{grammers_tl_types as tl, types};
use grammers_client::{Client, Config, InitParams};
use grammers_session::Session;

async fn try_download_media_raw(
    media_path: &Path,
    raw_message: &tl::enums::Message,
    client: &Client,
) -> Result<Option<String>> {
    use tl::enums::*;

    let Message::Message(raw_message) = raw_message else {
        return Ok(None); // Only Messages can have media
    };
    let Some(ref raw_media) = raw_message.media else {
        return Ok(None); // No media in this message
    };
    let Some(media) = Media::from_raw(raw_media.clone()) else {
        return Ok(None); // No media in this message
    };

    // Code to determine chat name and file name/extension is removed for simplicity
    let chat_name = format!("my_chat");
    let file_name = format!("my_file.mp4");

    let file_path = media_path.join(&chat_name).join(&file_name);
    fs::create_dir_all(file_path.parent().unwrap())?;
    let rel_path = format!("{chat_name}/{file_name}");
    client.download_media(&media, &file_path).await?;

    Ok(Some(rel_path))
}

frozenspider avatar May 11 '25 11:05 frozenspider

Sounds like the GIF happens to live in a different datacenter, whcih is why auth.importAuthorization is being called.

I'd suggest looking at https://github.com/Lonami/grammers/blob/ed516f5e8ff1ab537ad40c6ef37063bb59c8778c/lib/grammers-client/src/client/net.rs#L324-L351, and making sure that this is only reached if the file's DC ID is actually different than the current one (otherwise it'll fail).

Lonami avatar May 11 '25 15:05 Lonami

Yeah, it seems to live in a different DC indeed:

[2025-05-11T21:25:02Z INFO  grammers_client::client::net] creating a new sender and auth key in dc 2 Tcp { address: 149.154.167.50:443 }
...

[2025-05-11T21:26:25Z DEBUG grammers_mtsender] got rpc error RpcError { error_code: 303, error_message: "FILE_MIGRATE_4" }
[2025-05-11T21:26:30Z DEBUG grammers_client::client::net] Connecting new datacenter 4

But eventually code hits line 456: https://github.com/Lonami/grammers/blob/ed516f5e8ff1ab537ad40c6ef37063bb59c8778c/lib/grammers-client/src/client/net.rs#L435-L456 Stack trace:

  * frame #0: 0x0000000102324eb0 tg-keeper`grammers_client::client::net::<impl grammers_client::client::client::Connection>::invoke::{{closure}}((null)=0x000000016eb45230) at net.rs:456:25
    frame #1: 0x00000001023216f8 tg-keeper`grammers_client::client::net::<impl grammers_client::client::client::Client>::connect_sender::{{closure}}((null)=0x000000016eb45230) at net.rs:341:22
    frame #2: 0x0000000102320aa8 tg-keeper`grammers_client::client::net::<impl grammers_client::client::client::Client>::invoke_in_dc::{{closure}}((null)=0x000000016eb45230) at net.rs:366:48
    frame #3: 0x000000010235afb8 tg-keeper`grammers_client::client::files::DownloadIter::next::{{closure}}((null)=0x000000016eb45230) at files.rs:108:75
    frame #4: 0x000000010235dfec tg-keeper`grammers_client::client::files::<impl grammers_client::client::client::Client>::load::{{closure}}((null)=0x000000016eb45230) at files.rs:230:14
    frame #5: 0x000000010235bb38 tg-keeper`grammers_client::client::files::<impl grammers_client::client::client::Client>::download_media::{{closure}}((null)=0x000000016eb45230) at files.rs:222:43
    frame #6: 0x000000010236ee9c tg-keeper`tg_keeper::download_media_in_background::{{closure}}((null)=0x000000016eb45230) at main.rs:359:64
    ...

Error:

0 = {grammers_mtsender::errors::RpcError} 
 code = {i32} 400
 name = {alloc::string::String} "AUTH_BYTES_INVALID"
 value = {core::option::Option<u32>::None} None
 caused_by = {core::option::Option<u32>::Some} 2776268205

At that point, dc_id in ClientState is 2, and invoke_in_dc is called with dc_id == 4 (as expected from logs)

frozenspider avatar May 11 '25 21:05 frozenspider