usernein / pyromod

A monkeypatcher add-on for Pyrogram
https://pyromod.pauxis.dev/
GNU Lesser General Public License v3.0
222 stars 69 forks source link

Bug in multi client and not work with uvloop #42

Open river7816 opened 8 months ago

river7816 commented 8 months ago

I utilize a client and a bot client. The 'app' client is a part of a private group and it listens for text containing 🚨🚨 or a photo with the caption 🚨🚨. Afterwards, I utilize the 'app_bot' to transmit the message to my channel. It is essential for both of them to function properly, hence I employ 'await idle()' in order to avoid any blocking.

I want to receive the callback of the message with a button, so I use @app_bot.on_callback_query(). If the user selects Manual Input, I need to obtain the user's input. For this, I use coin = await chat.ask('Please input the coin: '). However, I am encountering an error message:

/Users/river/miniforge3/envs/tlg/bin/python /Users/river/Desktop/Troia-Crypto/main.py 
Pyromod is working! If you like pyromod, please star it at https://github.com/usernein/pyromod
[2023-11-08 19:25:42,034] [   ERROR] dispatcher.py:253 - <Queue at 0x2a07ced70 maxsize=1 _queue=[pyrogram.raw.functions.upload.SaveFilePart(file_id=7299050994019598340, file_part=0, bytes=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x07\x05\x05\x06\x05\x04\x07\x06\x06\x06\x08\x07\x07\x08\x0b\x12\x0b\x0b\n\n\x0b\x16\x0f\x10\r\x12\x1a\x16\x1b\x1a\x19\x16\x19\x18\x1c  tasks=1> is bound to a different event loop
[2023-11-08 19:25:42,048] [   ERROR] save_file.py:111 - Task <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() running at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:109>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Users/river/miniforge3/envs/tlg/lib/python3.10/asyncio/futures.py:385]> attached to a different loop
Traceback (most recent call last):
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py", line 109, in worker
    await session.invoke(data)
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/session/session.py", line 389, in invoke
    return await self.send(query, timeout=timeout)
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/session/session.py", line 326, in send
    payload = await self.loop.run_in_executor(
RuntimeError: Task <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() running at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:109>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Users/river/miniforge3/envs/tlg/lib/python3.10/asyncio/futures.py:385]> attached to a different loop
[2023-11-08 19:26:00,717] [   ERROR] threading.py:251 - Task was destroyed but it is pending!
task: <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() done, defined at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:101> wait_for=<Future cancelled>>

Here is my code


async def main():
    app_bot = Client("crybot", api_id, api_hash, bot_token=bot_token, hide_password=True)
    app = Client("river", api_id, api_hash, hide_password=True)
    @app.on_message(filters.regex('🚨{2}') & filters.chat(group_id))
    async def listen(client, message):
        text = message.text
        if text is None:  # return is picture
            photo = await app.download_media(message.photo.file_id, in_memory=True)  # δΈ‹θ½½ε›Ύη‰‡εˆ°ε†…ε­˜
            coin = text_from_image(photo.getvalue(), on_server=False, remove=False)
            coin, matched = match(coin)
        else:  # return is text
            coin, matched = find_coin_name(text)

        if matched:  # if matched
            response = post_data(coin, url)
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            output = f'[{current_time}] Buy coin {response}'
            if text is None:
                await app.send_photo(our_group_id, photo=photo, caption=output)
            else:
                await app.send_message(our_group_id, text=output)
        else:  # if not matched
            buttons = [[InlineKeyboardButton(text='πŸͺ™ ' + c, callback_data=c)] for c in coin]
            buttons.append([InlineKeyboardButton(text='βš™οΈ Manual Input', callback_data='Manual Input')])
            markup = InlineKeyboardMarkup(buttons)
            if text is None:
                await app_bot.send_photo(our_group_id, photo=photo, caption='Please Select the Button Bellow: ',
                                     reply_markup=markup)
            else:
                await app_bot.send_message(our_group_id, 'Please Select the Button Bellow: ', reply_markup=markup)

    @app_bot.on_callback_query()
    async def echo(client, callback_query):
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        if callback_query.data == 'Manual Input':
            chat = callback_query.message.chat
            coin = await chat.ask('Please input the coin: ')
            coin = coin.text.upper()
            while coin not in known_coins:
                coin = await chat.ask('Invalid Coin Name, Please reinput the coin: ')
                coin = coin.text.upper()
        else:
            coin = callback_query.data

        # await client.send_message(our_group_id, f'[{current_time}] Buy coin {coin}')
        await callback_query.message.edit_reply_markup(reply_markup=None)

    await app.start()
    await app_bot.start()
    await idle()

uvloop.install()
asyncio.run(main())
river7816 commented 8 months ago

I utilize a client and a bot client. The 'app' client is a part of a private group and it listens for text containing 🚨🚨 or a photo with the caption 🚨🚨. Afterwards, I utilize the 'app_bot' to transmit the message to my channel. It is essential for both of them to function properly, hence I employ 'await idle()' in order to avoid any blocking.

I want to receive the callback of the message with a button, so I use @app_bot.on_callback_query(). If the user selects Manual Input, I need to obtain the user's input. For this, I use coin = await chat.ask('Please input the coin: '). However, I am encountering an error message:

/Users/river/miniforge3/envs/tlg/bin/python /Users/river/Desktop/Troia-Crypto/main.py 
Pyromod is working! If you like pyromod, please star it at https://github.com/usernein/pyromod
[2023-11-08 19:25:42,034] [   ERROR] dispatcher.py:253 - <Queue at 0x2a07ced70 maxsize=1 _queue=[pyrogram.raw.functions.upload.SaveFilePart(file_id=7299050994019598340, file_part=0, bytes=b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x07\x05\x05\x06\x05\x04\x07\x06\x06\x06\x08\x07\x07\x08\x0b\x12\x0b\x0b\n\n\x0b\x16\x0f\x10\r\x12\x1a\x16\x1b\x1a\x19\x16\x19\x18\x1c  tasks=1> is bound to a different event loop
[2023-11-08 19:25:42,048] [   ERROR] save_file.py:111 - Task <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() running at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:109>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Users/river/miniforge3/envs/tlg/lib/python3.10/asyncio/futures.py:385]> attached to a different loop
Traceback (most recent call last):
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py", line 109, in worker
    await session.invoke(data)
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/session/session.py", line 389, in invoke
    return await self.send(query, timeout=timeout)
  File "/Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/session/session.py", line 326, in send
    payload = await self.loop.run_in_executor(
RuntimeError: Task <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() running at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:109>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Users/river/miniforge3/envs/tlg/lib/python3.10/asyncio/futures.py:385]> attached to a different loop
[2023-11-08 19:26:00,717] [   ERROR] threading.py:251 - Task was destroyed but it is pending!
task: <Task pending name='Task-516' coro=<SaveFile.save_file.<locals>.worker() done, defined at /Users/river/miniforge3/envs/tlg/lib/python3.10/site-packages/pyrogram/methods/advanced/save_file.py:101> wait_for=<Future cancelled>>

Here is my code

async def main():
    app_bot = Client("crybot", api_id, api_hash, bot_token=bot_token, hide_password=True)
    app = Client("river", api_id, api_hash, hide_password=True)
    @app.on_message(filters.regex('🚨{2}') & filters.chat(group_id))
    async def listen(client, message):
        text = message.text
        if text is None:  # return is picture
            photo = await app.download_media(message.photo.file_id, in_memory=True)  # δΈ‹θ½½ε›Ύη‰‡εˆ°ε†…ε­˜
            coin = text_from_image(photo.getvalue(), on_server=False, remove=False)
            coin, matched = match(coin)
        else:  # return is text
            coin, matched = find_coin_name(text)

        if matched:  # if matched
            response = post_data(coin, url)
            current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            output = f'[{current_time}] Buy coin {response}'
            if text is None:
                await app.send_photo(our_group_id, photo=photo, caption=output)
            else:
                await app.send_message(our_group_id, text=output)
        else:  # if not matched
            buttons = [[InlineKeyboardButton(text='πŸͺ™ ' + c, callback_data=c)] for c in coin]
            buttons.append([InlineKeyboardButton(text='βš™οΈ Manual Input', callback_data='Manual Input')])
            markup = InlineKeyboardMarkup(buttons)
            if text is None:
                await app_bot.send_photo(our_group_id, photo=photo, caption='Please Select the Button Bellow: ',
                                     reply_markup=markup)
            else:
                await app_bot.send_message(our_group_id, 'Please Select the Button Bellow: ', reply_markup=markup)

    @app_bot.on_callback_query()
    async def echo(client, callback_query):
        current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        if callback_query.data == 'Manual Input':
            chat = callback_query.message.chat
            coin = await chat.ask('Please input the coin: ')
            coin = coin.text.upper()
            while coin not in known_coins:
                coin = await chat.ask('Invalid Coin Name, Please reinput the coin: ')
                coin = coin.text.upper()
        else:
            coin = callback_query.data

        # await client.send_message(our_group_id, f'[{current_time}] Buy coin {coin}')
        await callback_query.message.edit_reply_markup(reply_markup=None)

    await app.start()
    await app_bot.start()
    await idle()

uvloop.install()
asyncio.run(main())

I also tried to put uvloop.install() before from pyromod import Client, still the same bug