LonamiWebs / Telethon

Pure Python 3 MTProto API Telegram client library, for bots too!
https://docs.telethon.dev
MIT License
9.68k stars 1.38k forks source link

EventBuilder.self_id acts as a global and breaks when multiple clients are used #1218

Closed vanyakosmos closed 5 years ago

vanyakosmos commented 5 years ago

Checklist

Code that causes the issue

import os
import glob
import asyncio

from telethon import TelegramClient, events

API_ID = os.getenv('API_ID')
API_HASH = os.getenv('API_HASH')

async def foo(event):
    await event.reply('bar')

async def make_client(session, loop):
    client = TelegramClient(session, API_ID, API_HASH, loop=loop)
    client.add_event_handler(foo, events.NewMessage(outgoing=True, pattern='foo'))
    if not client.is_connected():
        await client.connect()
    me = await client.get_me()
    print(me)
    return client

def main():
    loop = asyncio.get_event_loop()
    clients = []

    # load all available sessions
    for file in glob.glob('sessions/*.session'):
        c = loop.run_until_complete(make_client(file, loop))
        clients.append(c)

    loop.run_forever()

if __name__ == '__main__':
    main()

Missbehaviour In a chat with one another, both users respond to outgoing messages of one of them.

For example: let's say that we have 2 users (A and B), both have userbots, userbots' clients have shared event loop. If users chat with one another then we will see that user A will also respond to the outgoing command of user B. (> denotes reply)

Expected dialog:

A: hello
B: foo
B: > bar

Actual dialog:

A: hello
B: foo
B: > bar
A: > bar
x0x8x commented 5 years ago

Can't reproduce

2019-07-02_120203

2019-07-02_133105

2019-07-02_132333

loop-debug.log

vanyakosmos commented 5 years ago

@x0x8x because you've loaded only one session. Typo in tester_two.sesSion and in the logs you have only 1 user printed out.

Lonami commented 5 years ago

Thanks for the help.

Lonami commented 5 years ago

Oh wait, I read that wrong. I still haven't tried this myself but I doubt it's a bug anyway.

Lonami commented 5 years ago

Seems to work fine. Shared loops have nothing to do with different clients, at all.

vanyakosmos commented 5 years ago

wow, you can't just trust twitface. I can share with you session file of one of my accounts and you can check it yourself. And the problem wasn't specific to private chats. Just chats in general. Chats where we have several users with a shared loop on clients.

Lonami commented 5 years ago

If I can't trust Twitface, can I trust anyone? We had your report for the issue, and his to say there is no issue, and I lean on the side that shared loops are not an issue. If anything, outgoing= may be buggy. I will try myself and post results some time.

Lonami commented 5 years ago

I tried in a private conversation:

async def foo(event):
    await event.reply('bar')

with client, alt:
    print('Are the loops the same?', client.loop == alt.loop)
    client.add_event_handler(foo, events.NewMessage(outgoing=True, pattern='foo'))
    alt.add_event_handler(foo, events.NewMessage(outgoing=True, pattern='foo'))
    client.loop.run_forever()

Which prints:

Are the loops the same? True

Where client and alt are different accounts. I messaged from the client account to the alt account using an official client with the following result: image

Only client responded. The same occurred in a small group chat and megagroup. So this is not an issue. I can't reproduce.

vanyakosmos commented 5 years ago

Then what can possibly be wrong with my code?

code:

Screen Shot 2019-08-07 at 00 59 55
code ```python import glob import asyncio from telethon import TelegramClient, events from config import API_ID, API_HASH async def foo(event): print(f'> printing foo for event: {event}') await event.reply('bad') async def make_client(session, loop): client = TelegramClient(session, API_ID, API_HASH, loop=loop) client.add_event_handler(foo, events.NewMessage(outgoing=True, pattern='foo')) if not client.is_connected(): await client.connect() me = await client.get_me() print(me) return client def main(): loop = asyncio.get_event_loop() clients = [] for file in glob.glob('sessions/*.session'): c = loop.run_until_complete(make_client(file, loop)) clients.append(c) assert all([c.loop == loop for c in clients]) print('running...') loop.run_forever() if __name__ == '__main__': main() ```

logs:

Screen Shot 2019-08-07 at 00 59 02
logs ``` User(id=674821365, is_self=True, contact=True, mutual_contact=False, deleted=False, bot=False, bot_chat_history=False, bot_nochats=False, verified=False, restricted=False, min=False, bot_inline_geo=False, support=False, scam=False, access_hash=4439462715826273760, first_name='π–“π–Žπ–Šπ–’π–†π–“π–‰', last_name=None, username='npcomplete', phone='380938234159', photo=UserProfilePhoto(photo_id=2898335693773318059, photo_small=FileLocationToBeDeprecated(volume_id=263708388, local_id=105865), photo_big=FileLocationToBeDeprecated(volume_id=263708388, local_id=105867), dc_id=2), status=UserStatusOffline(was_online=datetime.datetime(2019, 8, 6, 21, 19, 51, tzinfo=datetime.timezone.utc)), bot_info_version=None, restriction_reason=None, bot_inline_placeholder=None, lang_code=None) User(id=89599420, is_self=True, contact=True, mutual_contact=True, deleted=False, bot=False, bot_chat_history=False, bot_nochats=False, verified=False, restricted=False, min=False, bot_inline_geo=False, support=False, scam=False, access_hash=6106815302761471165, first_name='π–†π–Žπ–›π–Šπ–“', last_name=None, username='vanyakosmos', phone='380668765053', photo=UserProfilePhoto(photo_id=384826579096809929, photo_small=FileLocationToBeDeprecated(volume_id=257013556, local_id=111395), photo_big=FileLocationToBeDeprecated(volume_id=257013556, local_id=111397), dc_id=2), status=UserStatusOffline(was_online=datetime.datetime(2019, 8, 6, 21, 57, 50, tzinfo=datetime.timezone.utc)), bot_info_version=None, restriction_reason=None, bot_inline_placeholder=None, lang_code=None) running... > printing foo for event: NewMessage.Event(original_update=UpdateShortMessage(id=272583, user_id=674821365, message='foo', pts=556851, pts_count=1, date=datetime.datetime(2019, 8, 6, 21, 58, 28, tzinfo=datetime.timezone.utc), out=True, mentioned=False, media_unread=False, silent=False, fwd_from=None, via_bot_id=None, reply_to_msg_id=None, entities=[]), pattern_match=<_sre.SRE_Match object; span=(0, 3), match='foo'>, message=Message(id=272583, to_id=PeerUser(user_id=674821365), date=datetime.datetime(2019, 8, 6, 21, 58, 28, tzinfo=datetime.timezone.utc), message='foo', out=True, mentioned=False, media_unread=False, silent=False, post=None, from_scheduled=None, legacy=None, from_id=None, fwd_from=None, via_bot_id=None, reply_to_msg_id=None, media=None, reply_markup=None, entities=[], views=None, edit_date=None, post_author=None, grouped_id=None)) > printing foo for event: NewMessage.Event(original_update=UpdateShortMessage(id=14329, user_id=89599420, message='foo', pts=29857, pts_count=1, date=datetime.datetime(2019, 8, 6, 21, 58, 28, tzinfo=datetime.timezone.utc), out=False, mentioned=False, media_unread=False, silent=False, fwd_from=None, via_bot_id=None, reply_to_msg_id=None, entities=[]), pattern_match=<_sre.SRE_Match object; span=(0, 3), match='foo'>, message=Message(id=14329, to_id=PeerUser(user_id=89599420), date=datetime.datetime(2019, 8, 6, 21, 58, 28, tzinfo=datetime.timezone.utc), message='foo', out=True, mentioned=False, media_unread=False, silent=False, post=None, from_scheduled=None, legacy=None, from_id=89599420, fwd_from=None, via_bot_id=None, reply_to_msg_id=None, media=None, reply_markup=None, entities=[], views=None, edit_date=None, post_author=None, grouped_id=None)) ```

And here is a result:

Screen Shot 2019-08-07 at 00 58 48
vanyakosmos commented 5 years ago

@Lonami, you weren't able to reproduce, because alt client wasn't active/connected at the moment.

this code "works"

Screen Shot 2019-08-07 at 01 11 48

BUT, if your alt type foo then you will see a bug. Or you can just connect both clients beforehand (commented code).

Lonami commented 5 years ago

In my code I do with client, alt: which calls start() on both client and alt.

vanyakosmos commented 5 years ago

but why after adding explicit "connect" the bug magically appears? or when alt also type something in the chat

Lonami commented 5 years ago

Could you also register events.Raw for both and print(event)?

Lonami commented 5 years ago

…which leads the following code to issues: https://github.com/LonamiWebs/Telethon/blob/b1eed82b7f7c793c05defeb0a504659f6f2ae761/telethon/events/newmessage.py#L92-L97

Lonami commented 5 years ago

Does that fix it? (pip3 install -U https://github.com/LonamiWebs/Telethon/archive/master.zip)

vanyakosmos commented 5 years ago

yep, it's all good now

Lonami commented 5 years ago

Okay thanks for confirming and sorry for refusing this was a bug at the beginning (although the original issue never existed, this edited one did).