Exchanging data between Python Telethon library and Node.js

Question:

I faced such a problem: in my small test app I have simple node.js (express) server and python script, which allows me to interact with Telegram API using Telethon library. In my scenario I have to provide my python script a phone number and a password. These data is asked in the input mode, so I can’t figure out, how am I able to:

  1. Accept input request from python script on node.js side;
  2. Provide these credentials by node.js and pass them back via python’s input;
  3. Repeat this actions several times to gain all info I need.

These are my test files:

file.py

import os

from telethon import TelegramClient

api_id = 12345
api_hash = 'hash'
session = 'testing'

proxy = None

client = TelegramClient(session, api_id, api_hash, proxy=proxy).start()


def get_ids_list():
    ids_dict = {}

    async def do_fetch():
        async for dialog in client.iter_dialogs():
            ids_dict[dialog.name] = dialog.id

    with client:
        client.loop.run_until_complete(do_fetch())

    return ids_dict


def print_ids_list():
    async def do_print():
        async for dialog in client.iter_dialogs():
            print(dialog.name, 'has ID', dialog.id)

    with client:
        client.loop.run_until_complete(do_print())


print_ids_list()

When this script is run, I’m prompted the following input:

Please enter your phone (or bot token):

And this is my index.js, in which I want to pass prepared data to this input:

import express from "express";
import { spawn } from "child_process";

const app = express();
const port = 3000;

app.get("/", (req, res) => {
  var myPythonScript = "path/to/file.py";
  var pythonExecutable = "python";

  var uint8arrayToString = function (data) {
    return String.fromCharCode.apply(null, data);
  };

  const scriptExecution = spawn(pythonExecutable, [myPythonScript]);

  scriptExecution.stdout.on("data", (data) => {
    console.log(uint8arrayToString(data));
  });

  scriptExecution.stderr.on("data", (data) => {
    console.log(uint8arrayToString(data));
  });

  scriptExecution.on("exit", (code) => {
    console.log("Process quit with code : " + code);
  });
});

app.listen(port, () =>
  console.log(`Example app listening on port ${port}!`)
);

So, is there a way to solve this case?

Asked By: M. Kuz.

||

Answers:

Using with client is equivalent to client.start(), and as stated:

By default, this method will be interactive (asking for user input if needed), and will handle 2FA if enabled too.

You need to instead do what it does manually, remove with block, and make a function to authenticate (or confirm if already authorized).

for a minimal func example:

    ....
    if not client.is_connected():
        await client.connect()
    if not await client.is_user_authorized():
        await client.send_code_request(phone)
        # get the code somehow, and in a reasonably fast way
        try:
            await client.sign_in(phone, code)
        except telethon.errors.SessionPasswordNeededError:
        '''
        Retry with password.
        note: it's necessary to make it error once 
        even if you know you have a pass, iow don't pass password the first time.
        '''
            await client.sign_in(phone, code, password=password)
        return client
    else:
        return client

Dealing with the steps sequentially and interactivly while waiting for needed params to login successfully while also keeping in mind you have time limit until code expires is your task to handle any of their undefined behavior dependant on your usecase.

Answered By: MustA
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.