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:
- Accept input request from python script on node.js side;
- Provide these credentials by node.js and pass them back via python's input;
- 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?
CodePudding user response:
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.