Telegram bot function with event handler not executing before program ends; how to fix and print results properly?

huangapple go评论72阅读模式
英文:

Telegram bot function with event handler not executing before program ends; how to fix and print results properly?

问题

Here is the translated part of your text:

我创建了一个函数来测试我的 Telegram 机器人,它向聊天机器人发送一个请求消息,以更改数据库中的某些值,用于这个用户。问题是,在函数 "first_handler" 的装饰器之前播放了所有的代码(这导致 "print (flag)" 输出 "false" )。即使从机器人的回复消息出现在代码执行到 "print" 之前,函数与装饰器的代码也不会在 "print" 之前触发。由于相同的问题,我必须使用 "client.run_until_disconnected()",因为没有它,机器人的消息处理程序根本不起作用,而且由于这种方法,我必须手动停止程序的执行,因为我不需要断开客户端连接。我的代码如下:

from telethon import TelegramClient, events, sync
import conf_tests as ct

import time

client = TelegramClient('TestClient', ct.api_id, ct.api_hash, system_version=ct.sys_ver)

def test_first():
    flag = False

    @client.on(events.NewMessage(chats=ct.bot_name))
    async def fist_handler(event):
        global flag, f2

        if (event.sender_id == ct.bot_id) and ('Enter new value' in event.raw_text):
            global f1
            f1 = True
            await client.send_message(ct.bot_name, 'Value')

        if (event.sender_id == ct.bot_id) and ('Value successfully changed!' in event.raw_text):
            f2 = True
            if f1 and f2:
                flag = True

    client.start()
    client.send_message(ct.bot_name, ct.change_group_btn)

    client.run_until_disconnected()
    print(flag)

test_first()

有一个与我对 Python 知识的不足更相关的额外问题:我不能在第一个 if 之前将 f1 和 f2 设置为 False,否则我将无法声明 f1 为全局变量,以便在下面的 if 中更改它。如果检查通过,就没有问题,但如果不通过,它将报告变量尚未分配值的错误。

我尝试使用以下方式,但没有改变任何东西,但我认为不应该改变,因为实际上我只是在不同的地方调用函数。

with client:
   client.loop.run_until_complete(test_first())

老实说,我不记得我是以什么形式添加了这些行,因为现在看来,由于异步性,它们似乎不会工作。

请注意,由于你要求只返回翻译好的部分,我将仅提供翻译和不会回答翻译问题。如果您需要进一步的帮助,请随时提出具体的问题。

英文:

I made a function to test my telegram bot, it sends a request message to the chat bot to change some value in the database for this user. The problem is that all the code is played before the code of the function "first_handler" with the decorator (due to which the "print (flag)" writes "false" ). Even if the reply message from the bot appears before the execution of the code reaches "print", then the function with the decorator does not trigger before the "print". Due to the same problem, I have to use "client.run_until_disconnected()" because without it, the bot's message handler doesn't work at all, and because of this method, I have to stop the program execution manually, since I don't need to disconnect the client. My scuffed code:

from telethon import TelegramClient, events, sync
import conf_tests as ct

import time

client = TelegramClient('TestClient', ct.api_id, ct.api_hash, system_version = ct.sys_ver)

def test_first():
    flag = False

    @client.on(events.NewMessage(chats=ct.bot_name))
    async def fist_handler(event):
        global flag, f2

        if (event.sender_id == ct.bot_id) and ('Enter new value' in event.raw_text):
            global f1
            f1 = True
            await client.send_message(ct.bot_name, 'Value')

        if (event.sender_id == ct.bot_id) and ('Value successfully changed!' in event.raw_text):
            f2 = True
            if f1 and f2:
                flag = True
    
    client.start()        
    client.send_message(ct.bot_name, ct.change_group_btn)
    
    client.run_until_disconnected() 
    print (flag)

test_first()       
  • Bonus problem, which is more related to my lack of knowledge of python: I cannot set f1 and f2 (no problem with f2 in this particular case) to False before the first if, because otherwise I will not be able to declare f1 a global variable to be able to change it in if below. If the check passes, there are no problems, but if it does not pass, it will give an error that the variables have not been assigned a value.

Tried to use this, but nothing has changed, but it shouldn't i guess, because in fact I just call the function, just in a different place.

with client:
   client.loop.run_until_complete(test_first())

And, to be honest, I don’t remember in what form I added these lines, cos now, it seems, they will not work due to asynchrony.

答案1

得分: 0

以下是翻译好的部分:

我认为主要问题在于 test_first 函数应该是异步的。以下代码应该有助于解决您的问题。

from telethon import TelegramClient, events
import conf_tests as ct

import asyncio # 推荐由 telethon 包使用

client = TelegramClient('TestClient', ct.api_id, ct.api_hash, system_version=ct.sys_ver)

async def test_first():
    flag = False
    f1 = False
    f2 = False

    @client.on(events.NewMessage(chats=ct.bot_name))
    async def first_handler(event):
        nonlocal flag, f1, f2 # 让您可以在稍早定义的 flag、f1 和 f2 变量之外使用它们,但不使它们成为全局变量
        if event.sender_id == ct.bot_id:
            if 'Enter new value' in event.raw_text:
                f1 = True
                await client.send_message(ct.bot_name, 'Value')
            elif 'Value successfully changed!' in event.raw_text:
                f2 = True
                if f1 and f2:
                    flag = True
                    client.disconnect()

    async with client: # 正确连接和断开客户端
        await client.send_message(ct.bot_name, ct.change_group_btn)
        await client.run_until_disconnected()

    print(flag)

asyncio.run(test_first()) # 创建一个新的异步事件循环,以异步运行 "test_first" 函数

正如您所看到的它使用了在[Telethon文档](https://docs.telethon.dev/en/stable/basic/quick-start.html)中推荐的 `asyncio`它将 `flag`、`f1``f2` 变量设置为非本地变量以便它们可以在 `first_handler` 函数之外使用它还将 `test_first` 函数设置为异步并在客户端上等待

我在代码中留下了一些注释解释了一些更改的目的如果这对您有帮助或者没有请在评论中告诉我如果您尚未如此做也可以使用上面的链接查看文档

<details>
<summary>英文:</summary>

I think the main issue is that the `test_first` function should be asynchronous. The following code should help you fix your issues. 

    from telethon import TelegramClient, events
    import conf_tests as ct
    
    import asyncio # Recommended to be used by the telethon package
    
    client = TelegramClient(&#39;TestClient&#39;, ct.api_id, ct.api_hash, system_version=ct.sys_ver)

    async def test_first():
        flag = False
        f1 = False
        f2 = False
    
        @client.on(events.NewMessage(chats=ct.bot_name))
        async def first_handler(event):
            nonlocal flag, f1, f2 # lets you use the flag, f1, and f2 variables that were defined earlier but doesnt make them global
            if event.sender_id == ct.bot_id:
                if &#39;Enter new value&#39; in event.raw_text:
                    f1 = True
                    await client.send_message(ct.bot_name, &#39;Value&#39;)
                elif &#39;Value successfully changed!&#39; in event.raw_text:
                    f2 = True
                    if f1 and f2:
                        flag = True
                        client.disconnect()
    
        async with client: # properly connect and disconnect the client
            await client.send_message(ct.bot_name, ct.change_group_btn)
            await client.run_until_disconnected()
        
        print(flag)

    asyncio.run(test_first()) # Creates a new asyncio event loop asynchronously running &quot;test_first&quot;

As you can see, it uses the `asyncio` package that is recommended in the [Telethon Documentation][1]. It sets the `flag`, `f1`, and `f2` variables as nonlocal so they can be used outside the `first_handler` function. It also makes the `test_first` function async and awaits on the client. 

I left comments in the code explaining what some of the changes are for. Let me know if this was helpful or not in the comments. You can also check out the documentation using the link above if you have not done so already.


  [1]: https://docs.telethon.dev/en/stable/basic/quick-start.html

</details>



huangapple
  • 本文由 发表于 2023年5月7日 03:27:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定