Проблема с истечением кода из-за разных клиентов: "[400 PHONE_CODE_EXPIRED]"

Надо по запросам к API сделать создание и авторизацию pyrogram сессии.

get-code работает, а вот на sign-in падает по причине истечения кода. Я почти уверен, что это из-за того, что с разных Client отправляю код и делаю sign_in, но не знаю, как использовать один.

Есть идеи, что можно предпринять?

Код:

from fastapi import APIRouter, Body
from pyrogram import Client
from pyrogram.errors import SessionPasswordNeeded, BadRequest
from pyrogram.types import SentCode

from core import settings
from .redis_db import save_to_redis, get_from_redis, delete_from_redis

router = APIRouter(tags=['Telegram'])

@router.post('/telegram/get-code')
async def get_code(
    data=Body()
):
    phone = str(data['phone'])
    phone = phone.replace('+', '')

    client = Client(name=f"{phone}",
                    api_id=settings.API_ID,
                    api_hash=settings.API_HASH,
                    workdir=settings.WORKDIR
                    )

    await client.connect()

    try:
        code_data: SentCode = await client.send_code(
            phone_number=phone,
        )

        await save_to_redis(key=f"tg_client_{phone}", value={
            'phone': phone,
            'phone_code_hash': code_data.phone_code_hash
        })

        return {'success': True}
    except Exception as err:
        await client.disconnect()
        raise err

@router.post('/telegram/sign-in')
async def sign_in(
    data=Body()
):
    phone = str(data['phone'])
    phone = phone.replace('+', '')
    phone_code = data['phone_code']

    session_data = await get_from_redis(key=f"tg_client_{phone}")

    if not session_data:
        return {'success': False, 'message': 'Session not found'}

    client = Client(
        name=f"{phone}",
        api_id=settings.API_ID,
        api_hash=settings.API_HASH,
        workdir=settings.WORKDIR
    )

    await client.connect()

    phone_code_hash = session_data['phone_code_hash']

    try:
        await client.sign_in(phone_number=phone,
                             phone_code_hash=phone_code_hash,
                             phone_code=phone_code)

        await client.disconnect()
        await delete_from_redis(key=f"tg_client_{phone}")
        return {'success': True}
    except SessionPasswordNeeded:
        password = data.get('password', None)

        try:
            await client.check_password(password=password)
        except BadRequest:
            await client.disconnect()
            return {'success': False, 'message': 'Incorrect password'}
        else:
            await client.disconnect()
            return {'success': True}

Ошибка:

INFO:     127.0.0.1:41094 - "POST /api/v1/telegram/sign-in HTTP/1.1" 500 Internal Server Error
pyrogram.errors.exceptions.bad_request_400.PhoneCodeExpired: Telegram says: [400 PHONE_CODE_EXPIRED] - The confirmation code has expired (caused by "auth.SignIn")

Ответы (1 шт):

Автор решения: hhhscvx

Сделал через вебсокеты:

@router.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await manager.connect(websocket)
    try:
        while True:
            data: dict[str, str] = await websocket.receive_json()
            print(f"Received data: {data} | Type: {type(data).__name__}")
            if data.get('message_type') == 'get_code':
                await websocket.send_text("Мы в get_code")
                phone_number = data['phone_number'].replace('+', '')
                client = Client(name=f"{phone_number}",
                                api_id=settings.API_ID,
                                api_hash=settings.API_HASH,
                                workdir=settings.WORKDIR
                                )
                await client.connect()
                code_data = await client.send_code(
                    phone_number=phone_number,
                )

            if data.get('message_type') == 'sign_in':
                await websocket.send_text("Мы в sign_in")
                phone_code = data['phone_code']
                try:
                    await client.sign_in(phone_number,
                                         code_data.phone_code_hash,
                                         phone_code)
                except SessionPasswordNeeded:
                    password = data['password']
                    try:
                        await client.check_password(password=password)
                    except BadRequest:
                        await websocket.send_text("Incorrect Password")
                finally:
                    try:
                        await client.get_me()
                    except:
                        await websocket.send_text("Unathorized :(")
                    else:
                        await websocket.send_text("Success!")
                    await client.disconnect()

    except WebSocketDisconnect:
        manager.disconnect(websocket)

→ Ссылка