Search code examples
pythonpython-3.xdynamic-programmingpython-decoratorstelethon

How to edit the parameter in the decorator dynamically in the runtime in Python


can anyone help me to make the "FROM" variable dynamic in the decorator in the runtime?

The script is a message forwarder, in the beginning it is working with the Chat IDs I provide in FROM list. Then When I want to update with the handler() function I can not add a new Chat ID into FROM list in the decorator because the script is running already.

Can someone give me a hand?

from telethon import TelegramClient, events
from telethon.sessions import StringSession

telethon_client = TelegramClient(StringSession(SESSION), APP_ID, API_HASH)
telethon_client.start()
# some code here

FROM=[CHAT_ID_1, CHAT_ID_2, CHAT_ID_3]

@telethon_client.on(events.NewMessage(outgoing=outgoing, incoming=True, chats=FROM))
async def catch_messages(event):
    global FROM
    # some codes here
    await telethon_client.send_message(entity=TO, message=event.message)

@telethon_client.on(events.NewMessage(pattern=r"\/", chats=BOT_CHAT_ID, incoming=False))
async def handler(event):
    global FROM
    # some code here
    FROM.append(CHAT_ID_4)

telethon_client.run_until_disconnected()

Solution

  • As mentioned by @Barmar in the comments, you can't change a decorator after it's been applied to the function. In theory, you could pass assign a list to a variable and use that variable in the decorator, so that mutating it would mutate what the decorator has.

    But Telethon's decorators make a copy (for performance reasons) so that won't work.

    The easiest thing to do is to check inside the function:

    FROM=[CHAT_ID_1, CHAT_ID_2, CHAT_ID_3]
    
    @telethon_client.on(events.NewMessage(outgoing=outgoing, incoming=True))
    async def catch_messages(event):
        global FROM
        if event.chat_id not in FROM:  # <- this essentially does the same thing as chats=, except FROM must only contain integer IDs for it to work as intended
            return
        # some codes here
        await telethon_client.send_message(entity=TO, message=event.message)