Альтернативная авторизация в Pyrogram через чат-бота Телеграм
Создаю юзербота на Pyrogram с управлением через чат-бота телеграм, который в свою очередь работает на PyTelegrambotApi. Создаю авторизацию через чат-бота, чтобы создавался файл сессии в Pyrogram. По сути пользователь вводит свой номер телефона чат-боту, потом код подтверждения, должен быть создан файл сессии. Добавил асинхронность, так как без неё не работает ничего. Теперь вылазит ошибка Telegram says: [400 PHONE_COED_EXPIRED] - The confirmation code has expired (caused by "auth.SignIn").
import telebot
import db
import asyncio
from telebot import types
from pyrogram import Client
bot = telebot.TeleBot('token')
user_dict = {}
class User:
def __init__(self, id):
self.id = id
self.api_id = None
self.api_hash = None
self.number = None
auth_dict = {}
class Auth:
def __init__(self, id):
self.id = id
self.number = None
self.app = None
self.sc = None
self.loop = None
self.code = None
def sendcode(self, number):
#async
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
self.app = Client(f"users/{self.id}/{self.id}", api_id=apiid, api_hash='apihash')
self.app.connect()
self.number = number
self.sc = Client.send_code(self.app, phone_number=self.number)
self.app.disconnect()
def signin(self, code):
try:
self.app.connect()
except:
pass
print(self.sc.phone_code_hash)
Client.sign_in(self.app, phone_number=self.number, phone_code_hash=self.sc.phone_code_hash, phone_code=str(self.code))
self.app.disconnect()
self.loop.close()
В самом боте Telegram я сначала спрашиваю у пользователя номер, потом вызываю функцию sendcode, затем через bot.register_next_step_handler получаю код и вызываю функцию signin
Ответы (1 шт):
я тоже столкнулся с необходимостью авторизацией через отдельного бота, посмотрел ваше сообщение, набросал код и тоже полезли ошибки.
Возможно вопрос уже решён, но оставлю разяснение последующим пользователям,которые захотят повторить это.
Проблемма в том, что хЭш кода авторизации можна использовать в текущем сеансе а у вас в функциях "sendcode" и "signin" приложение подключается и отключается между шагами авторизации и ето не подходит. По этому нужно избежать отключения пока не передастся код авторизации и не произойдёт вход в учётную запись. Наводку на суть проблеммы получил вот здесь
Сразу скажу, я нуб, только начал изучать питон и нашел только способ избежать отключение, сделав одну функцию (вместо 2х) и подерил её на 2 этапа с использованием переменной "menu" и её логической проверкой, чтобы ненужный код не выполнился в ненужный момент. И заранее извиняюсь за возможный баг в передачи номера телефона аккаунта на который происходит авторизация в переменную. Там можно на прямую прописать номер и оно точно заработает. (ну есть нуб)
Также, всех кто хочет попробовать повторить данный способ, хочу предупредить - если в бота передавать чистый код авторизации с того аккаунта в который происходит авторизация (надеюсь нормально объяснил хд) - он (код авторизации) аннулируется, потому я использую лайфхак с вводом кода через пробел и он работает
Вот мой говнокод (да, я для бота использую тот же пирограм, но суть дела не меняет)(upd спустя сутки, перепроверил код, поправил, что бы не било ошибки, тысяча извиненй, скопировал не с того тестового файла):
import asyncio
from pyrogram import Client, filters
api_id = 00000000
api_hash = "xxxxxxxxxxxxxx"
bot_token = "000000:xxxxxxxxxxx"
menu = 0
phone_number = ""
sc = None
bot = Client("cp_bot", api_id=api_id, api_hash=api_hash, bot_token=bot_token)
app = Client("test_auth", api_id=api_id, api_hash=api_hash, phone_number=phone_number)
async def auth(number):
global api_id
global api_hash
global phone_number
global sc
global menu
global app
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
print(number)
if menu == 1:
await app.connect()
print("trying send code")
sc = await app.send_code(phone_number=number)
print("OK")
elif menu == 2:
code = number
ch = sc.phone_code_hash
print(ch)
await app.sign_in(phone_number=phone_number, phone_code_hash=ch, phone_code=str(code))
await app.disconnect()
loop.close()
@bot.on_message(filters.command(["start"]) & filters.text)
async def command_start(client, message):
global menu
await message.reply_text("Старт аутентификации! Отправь номер телефона в международном формате (+1234567890)")
menu = 1
@bot.on_message(filters.text)
async def command_start(client, message):
global menu
global phone_number
global code
if menu == 1:
phone = message.text
phone = phone.replace("+", "")
if phone.isdigit():
print(phone)
phone_number = phone
await auth(phone_number)
menu = 2
print("is ok")
await message.reply_text("DONE!\nТеперь отправь код авторизации, с цифрами через пробел (прим. \"1 2 266\" и подобное)")
else:
await message.reply_text("Phone incorrect! try again")
elif menu == 2:
v_dig = message.text
v_dig = v_dig.replace(" ", "") # если в бота или личку ТГ с которого производится авторизация, пересылается
# чистый код авторизации - он аннулируется, потому я использую лайфхак с вводом кода через пробел и он работает
print(v_dig)
if v_dig.isdigit():
code = v_dig
print(code)
await auth(code)
await message.reply_text("DONE!\nАвторизация прошла успешно!")
menu = 0
else:
await message.reply_text("CODE incorrect! try again")
bot.run()