Skip to content
This repository has been archived by the owner on Sep 4, 2024. It is now read-only.

API messages.sendMultiMedia Always Fails (400 MEDIA_INVALID) for valid media #148

Open
mvdicarlo opened this issue Jan 22, 2021 · 10 comments

Comments

@mvdicarlo
Copy link

I have been trying to get this particular api method to work (https://core.telegram.org/method/messages.sendMultiMedia).

I have provided sample code below that I am using to test this behavior. It shouldn't be an issue of the actual file being invalid as if you attempt to send the media using https://core.telegram.org/method/messages.sendMedia it works just fine.

It appears to be a bug, but I don't know enough about the protocol implementation to be able to fix it myself.

const { MTProto } = require("@mtproto/core");
const readline = require("readline");
const fs = require("fs");

const api_id = "<app id>";
const api_hash = "<app hash>";
const phone_number = "<phone>";
const file = fs.readFileSync("test.jpg"); // assumes under 512kb

// 1. Create an instance
const mtproto = new MTProto({
  api_id,
  api_hash,
});

async function auth() {
  const send = await mtproto.call("auth.sendCode", {
    phone_number,
    settings: {
      _: "codeSettings",
    },
  });

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  const code = await new Promise((resolve) => {
    rl.question("Code: ", (answer) => {
      rl.close();
      resolve(answer);
    });
  });

  const authed = await mtproto.call("auth.signIn", {
    phone_code: code,
    phone_number,
    phone_code_hash: send.phone_code_hash,
  });

  console.log(authed);
}

async function getChats() {
  return await mtproto
    .call("messages.getAllChats", {
      except_ids: [],
    })
    .then(({ chats }) => chats);
}

function wait() {
  return new Promise((resolve) => {
    setTimeout(resolve, 2000);
  });
}

async function upload(file) {
  const id = Date.now();
  await mtproto.call("upload.saveFilePart", {
    file_id: id,
    file_part: 0,
    bytes: file,
  });
  return id;
}

// This does all the stuff
async function run() {
  mtproto.setDefaultDc(
    await mtproto.call("help.getNearestDc").then((result) => {
      return result.nearest_dc;
    })
  );

  let chats;
  try {
    chats = await getChats();
  } catch {
    await auth();
    chats = await getChats();
  }

  const chat = chats[0];
  await wait();
  const upl = await upload(file);
  await wait();

// I AM BROKEN
  const res = await mtproto
    .call("messages.sendMultiMedia", {
      peer: {
        _: "inputPeerChannel",
        channel_id: chat.id,
        access_hash: chat.access_hash,
      },
      multi_media: [
        {
          _: "inputSingleMedia",
          random_id: Date.now(),
          //   message: "Hello, World!",
          media: {
            _: "inputMediaUploadedPhoto",
            file: {
              _: "inputFile",
              id: upl,
              name: "test.jpg",
              parts: 1,
            },
          },
        },
      ],
    })
    .catch((err) => err);
  // UNCOMMENT ME TO SEE THAT messages.sendMedia works correctly.
  //   const res = await mtproto
  //     .call("messages.sendMedia", {
  //       random_id: Date.now(),
  //       peer: {
  //         _: "inputPeerChannel",
  //         channel_id: chat.id,
  //         access_hash: chat.access_hash,
  //       },
  //       message: "Hello, World",
  //       media: {
  //         _: "inputMediaUploadedPhoto",
  //         file: {
  //           _: "inputFile",
  //           id: upl,
  //           name: "test.jpg",
  //           parts: 1,
  //         },
  //       },
  //     })
  //     .catch((err) => err);

  console.log(res);
}

run()
  .catch(console.error)
  .finally(() => process.exit(0));

process.on("unhandledRejection", console.error);

@meylisatamuradov
Copy link

https://stackoverflow.com/questions/65628877/in-nodejs-telegram-api-messages-sendmultimedia-method-is-not-working

@bigbigsir
Copy link

I have the same question. Have you solved your problem

@bigbigsir
Copy link

@alik0211

@ember999
Copy link

@mvdicarlo Have you solved your problem? I need help

@mvdicarlo
Copy link
Author

No. I just accepted the less preferable way of sending individually for now.
Wasn't able to tell if this was a limitation of the library or some limitation of the Telegram API.

I don't know enough about the protocol to debug it myself

@ember999
Copy link

ember999 commented May 18, 2021 via email

@milad7290
Copy link

Any update on this issue? I try all kinds of ways but still the response is "400 MEDIA_INVALID"

@VityaSchel
Copy link

This is just fuck this is so stupid, why python has everything while js developers has to deal with dead library with "call" method that pretty much don't do anything, what the actual fuck why just why

@VityaSchel
Copy link

I'm going to try to patch this error. It seems that problem is at src/tl/builder/index.js:7159

'messages.sendMultiMedia': function(params) {
    this.int32(-134016113);
    const flags = (this.has(params.silent) << 5) | (this.has(params.background) << 6) | (this.has(params.clear_draft) << 7) | (this.has(params.noforwards) << 14) | (this.has(params.reply_to_msg_id) << 0) | (this.has(params.schedule_date) << 10) | (this.has(params.send_as) << 13);
    this.int32(flags);
    this.predicate(params.peer);
    this.flag(this.int, params.reply_to_msg_id);
    this.vector(this.predicate, params.multi_media);
    this.flag(this.int, params.schedule_date);
    this.flag(this.predicate, params.send_as);
  },

@ghost
Copy link

ghost commented Sep 11, 2022

you may use uploadMedia to upload each photo

...
...
// step 1 ,upload the file
const chat = chats[0];
await wait();
const upl_id = await upload(file);
await wait();
// step2, uploadMedia
const upl_media = await mtproto('messages.uploadMedia', {
    peer: target_peer,
    media: {
        "_": "inputMediaUploadedPhoto",
        "file": {
            "_": "inputFile",
            "id": upl_id,
            "parts": 1,
            "name": 'upload.png',
            "md5_checksum": ""
        },
        "mime_type": "image/png",
        "attributes": [{
            "_": "documentAttributeFilename",
            "file_name": 'upload.png'
        }]
    }
})
// step 3 send multi media
const res = await mtproto
    .call("messages.sendMultiMedia", {
        peer: {
            _: "inputPeerChannel",
            channel_id: chat.id,
            access_hash: chat.access_hash,
        },
        multi_media: [{
            "_": "inputSingleMedia",
            "random_id": this.createSendMessageId(),
            "message": text,
            "entities": entities,
            "media": {
                "_": "inputMediaPhoto",
                "id": {
                    "_": 'inputPhoto',
                    "id": upl_media.photo.id,
                    "access_hash": upl_media.photo.access_hash,
                    "file_reference": upl_media.photo.file_reference
                }
            }
        }, {
            "_": "inputSingleMedia",
            "random_id": this.createSendMessageId(),
            "media": {
                "_": "inputMediaPhoto",
                "id": {
                    "_": 'inputPhoto',
                    "id": upl_media.photo.id,
                    "access_hash": upl_media.photo.access_hash,
                    "file_reference": upl_media.photo.file_reference
                }
            }
        }],
    })
    .catch((err) => err);

===========================================================================================
the code is work for me.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants