zerobias / telegram-mtproto

Telegram client api (MTProto) library
MIT License
617 stars 136 forks source link

Error: Invalid vector object, on sending document. #212

Closed xbeat closed 5 years ago

xbeat commented 5 years ago

Using the following code i got the error in the subject when i try to send a document to a chat with inputMediaUploadedDocument method:


const { Storage } = require('mtproto-storage-fs');
const { pluck } = require('ramda');

const prompt = require( 'prompt' );
const readline = require( 'readline' );
const fs = require( 'fs' );

// The api_id and api_hash values can be obtained here: https://my.telegram.org/
const config = {
    phone_number: "phonenumber",
    api_id: 22222,
    api_hash: "api_hash"
};

const app = {
    storage: new Storage('./storage.json')
};

const phone = {
    num: config.phone_number
};

const api = {
    layer         : 57,
    initConnection: 0x69796de9,
    api_id        : config.api_id
};

const server = {
    dev: false
};

const telegram  = MTProto( { server, api, app } );

// This function will stop execution of the program until you enter the code
// that is sent via SMS or Telegram.
const askForCode = function() {

    return new Promise( function( resolve ) {
        const rl = readline.createInterface({
                            input : process.stdin,
                            output: process.stdout
        });

        rl.question( 'Please enter passcode for ' + phone.num + ':\n', function( num ) {
                rl.close()
                resolve( num )
        });

    });

};

// First you will receive a code via SMS or Telegram, which you have to enter
// directly in the command line. If you entered the correct code, you will be
// logged in and the credentials are saved.
const login = async function( telegram, phone ) {

    const { phone_code_hash } = await telegram( 'auth.sendCode', {
                                                phone_number  : phone.num,
                                                current_number: false,
                                                api_id        : config.api_id,
                                                api_hash      : config.api_hash
                                        });

    const phone_code = await askForCode()
    console.log( `Your code: ${phone_code}` );

    const { user } = await telegram( 'auth.signIn', {
        phone_number   : phone.num,
        phone_code_hash: phone_code_hash,
        phone_code     : phone_code
    });

    console.log( 'signed as ', user );

};

const fileToBuffer = async function ( filename, chat ){

    let file_id = Date.now();

    var CHUNK_SIZE = 1024; // 1KB       
        buffer = new Buffer.alloc( CHUNK_SIZE );

    const stats = fs.statSync( filename );
    const fileSizeInBytes = stats.size;

    let file_total_parts = Math.floor( fileSizeInBytes / CHUNK_SIZE );
    let remainder = fileSizeInBytes % CHUNK_SIZE;
    let file_part = 0;
    if ( remainder > 0 ){
        file_total_parts++;
    };

    fs.open( filename, 'r', function( err, fd ) {
        if ( err ) throw err;
        const readNextChunk = async function readNextChunk() {
            fs.read( fd, buffer, 0, CHUNK_SIZE, null, async function( err, nread ) {
                if ( err ) throw err;

                if ( nread === 0 ) {
                    // done reading file, do any necessary finalization steps

                    fs.close( fd, function( err ) {
                        if ( err ) throw err;
                    });

                    await sendMedia( chat, file_id, file_part );

                    process.exit(0);

                    return;
                };

                var data;
                if ( nread < CHUNK_SIZE )
                    data = buffer.slice( 0, nread );
                else
                    data = buffer;

                // do something with `data`, then call `readNextChunk();`

                console.log( "data:" + data );
                await saveFilePart( file_id, ++file_part, file_total_parts, data )

                readNextChunk();

            });
        };
        readNextChunk();
    });

};

const saveFilePart = async function saveFilePart( file_id, file_part, file_total_parts, bytes ) {

    console.log ( file_id, file_part, file_total_parts, bytes );

    let file = await telegram( 'upload.saveFilePart', {

        file_id: file_id,
        file_part: file_part,
        bytes: bytes

    });

    console.log ( file );

};

const sendMedia = async function sendMedia( chat, file_id, parts ) {

    console.log( file_id, parts );

    let file = await telegram( 'messages.sendMedia', {
        peer: {
                _ : 'inputPeerChannel',
                channel_id : chat.id,
                access_hash: chat.access_hash
            },
        media: {
                _ : "inputMediaUploadedDocument",
                file: {
                    _: "inputFile",
                    id: file_id, 
                    parts: parts,
                    name: "test.txt"
                },
                mime_type: "text/plain",
                attributes: [{
                    _ : "DocumentAttributeFilename",
                    file_name: "test.txt"
                }]
            },
        random_id: Date.now()
    });

    console.log ( file );

};
///////////////
// getChat
const getChat = async function getChat() {

    const dialogs = await telegram( 'messages.getDialogs', {
        limit: 50,
    });

    const { chats } = dialogs;

    console.log( "*" + dialogs );

    const selectedChat = await selectChat( chats );

    return selectedChat;

};

///////////////
// Select chat
const selectChat = async function selectChat( chats ) {

    const chatNames = pluck( 'title', chats );

    console.log( 'Your chat list' );

    chatNames.map( function( name, id ) { 
        console.log( `${id}  ${name}` );
    });

    console.log( 'Select chat by index' );
    const chatIndex = await inputField( 'index' );

    return chats[ +chatIndex ];

};

////////////
// prompt
prompt.start();

const input = function( cfg ){

    return new Promise( function ( rs, rj ){

        return prompt.get( cfg, function( err, res ){

            return err ? rj ( err ) : rs ( res );

        });

    });

};

/////////////
//inputField
const inputField = function ( field ){

    return input ( [ { name: field, required: true  } ] )
    .then( function ( res ){
                return res [ field ];
            });

};

// First check if we are already signed in (if credentials are stored). If we
// are logged in, execution continues, otherwise the login process begins.
( async function() {

    if ( !( await app.storage.get( 'signedin' ) ) ) {

        console.log('not signed in');

        await login( telegram, phone ).catch( console.error );

        console.log( 'signed in successfully' );
        app.storage.set( 'signedin', true );

    } else {

        console.log( 'already signed in' );

    };

    const chat = await getChat();

    fileToBuffer( "example.txt", chat );

} )()```