Teekeks / pyTwitchAPI

A Python 3.7 compatible implementation of the Twitch API, EventSub, PubSub and Chat
https://pytwitchapi.dev
MIT License
253 stars 38 forks source link

EventSub Websocket fails reconnect after some time #316

Open Maaster opened 2 months ago

Maaster commented 2 months ago

Made a tool to track the bits and subs, it works fine overall, but at some point it just fails to reconnect. The timing of this isnt clear, but it seems to be around 1-3 hours. Happened 4 times so far.

I dont see an immediate trigger, as there is no event that is triggered. Also happened on 2 seperate machines, so I doubt its just a machine or network issue. (This log happened on stream too, as an example)

(Censored some names/ids and cut out a lot of keep-alives)

Loading old data...
Bits file doesnt exist.
Subs file doesnt exist.

Init Twitch...
15:46:50 DEBUG    generating fresh app token
15:46:51 DEBUG    Using proactor: IocpProactor
15:46:51 INFO     running oauth Webserver
15:46:57 DEBUG    got callback with state fe179e30-8e65-40b9-aa2c-20446fe27e16
15:46:57 INFO     127.0.0.1 [27/Jun/2024:14:46:57 +0200] "GET /?code=130*&scope=bits%3Aread+channel%3Aread%3Asubscriptions+user%3Aread%3Achat&state=fe179e30-8e65-40b9-aa2c-20446fe27e16 HTTP/1.1" 200 452 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36"
15:46:58 INFO     shutting down oauth Webserver
15:46:59 DEBUG    making GET request to https://api.twitch.tv/helix/users
Logged in as T*!
15:46:59 DEBUG    starting websocket EventSub...
15:46:59 DEBUG    Using proactor: IocpProactor
15:46:59 DEBUG    connecting to wss://eventsub.wss.twitch.tv/ws...
15:47:00 DEBUG    new session id: Ago*
15:47:00 DEBUG    EventSubWebsocket started up!
15:47:00 DEBUG    subscribe to channel.chat.notification version 1 with condition {'broadcaster_user_id': '77*', 'user_id': '77*'}
15:47:01 DEBUG    subscription for channel.chat.notification version 1 with condition {'broadcaster_user_id': '77*', 'user_id': '77*'} has id a3284990-cdb0-46f3-b181-df74f6cfa3f9
15:47:01 DEBUG    subscribe to channel.cheer version 1 with condition {'broadcaster_user_id': '77*'}
15:47:02 DEBUG    subscription for channel.cheer version 1 with condition {'broadcaster_user_id': '77*'} has id 1b1a0287-4bd3-4f04-8d17-30f06641459d
Listening to subs and cheers...
15:47:10 DEBUG    got session keep alive
[....]
18:01:00 DEBUG    got session keep alive
N* just re-subscribed!
18:01:14 DEBUG    got session keep alive
[...]
18:06:44 DEBUG    got session keep alive
C* just subscribed at tier 1000 with Prime!
[...]
20:10:04 DEBUG    got session keep alive
20:10:14 DEBUG    got session keep alive
20:10:24 DEBUG    got session keep alive
20:10:34 DEBUG    got session keep alive
20:10:35 DEBUG    got request from websocket to reconnect, reconnect url: wss://cell-c.eventsub.wss.twitch.tv/ws?challenge=825e84c0-4b73-4a3a-9b05-4e393f6563d0&id=AgoQZdVLuY79S7217k6bb9jPRxIGY2VsbC1j
20:10:35 DEBUG    reconnecting using wss://cell-c.eventsub.wss.twitch.tv/ws?challenge=825e84c0-4b73-4a3a-9b05-4e393f6563d0&id=AgoQZdVLuY79S7217k6bb9jPRxIGY2VsbC1j...
20:10:35 WARNING  connection attempt failed, retry in 0 seconds...
Exception ignored in: <function _ProactorBasePipeTransport.__del__ at 0x000002581062C4C0>
Traceback (most recent call last):
  File "C:\Users\M*\AppData\Local\Programs\Python\Python310\lib\asyncio\proactor_events.py", line 116, in __del__
    self.close()
  File "C:\Users\M*\AppData\Local\Programs\Python\Python310\lib\asyncio\proactor_events.py", line 108, in close
    self._loop.call_soon(self._call_connection_lost, None)
  File "C:\Users\M*\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 745, in call_soon
    self._check_closed()
  File "C:\Users\M*\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 510, in _check_closed
    raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed
20:10:35 WARNING  connection attempt failed, retry in 1 seconds...
20:10:35 DEBUG    websocket is closing
20:10:36 WARNING  connection attempt failed, retry in 2 seconds...
20:10:38 WARNING  connection attempt failed, retry in 4 seconds...
20:10:42 WARNING  connection attempt failed, retry in 8 seconds...
20:10:50 WARNING  connection attempt failed, retry in 16 seconds...
20:11:06 WARNING  connection attempt failed, retry in 32 seconds...
20:11:38 WARNING  connection attempt failed, retry in 64 seconds...
20:12:42 WARNING  connection attempt failed, retry in 128 seconds...
20:14:50 ERROR    Task exception was never retrieved
future: <Task finished name='Task-1652' coro=<EventSubWebsocket._handle_reconnect() done, defined at C:\Users\Melis\AppData\Local\Programs\Python\Python310\lib\site-packages\twitchAPI\eventsub\websocket.py:397> exception=TwitchBackendException("can't connect to EventSub websocket wss://cell-c.eventsub.wss.twitch.tv/ws?challenge=825e84c0-4b73-4a3a-9b05-4e393f6563d0&id=AgoQZdVLuY79S7217k6bb9jPRxIGY2VsbC1j")>
Traceback (most recent call last):
  File "C:\Users\Melis\AppData\Local\Programs\Python\Python310\lib\site-packages\twitchAPI\eventsub\websocket.py", line 401, in _handle_reconnect
    await self._connect(False)
  File "C:\Users\Melis\AppData\Local\Programs\Python\Python310\lib\site-packages\twitchAPI\eventsub\websocket.py", line 262, in _connect
    raise TwitchBackendException(f'can\'t connect to EventSub websocket {_con_url}')
twitchAPI.type.TwitchBackendException: can't connect to EventSub websocket wss://cell-c.eventsub.wss.twitch.tv/ws?challenge=825e84c0-4b73-4a3a-9b05-4e393f6563d0&id=AgoQZdVLuY79S7217k6bb9jPRxIGY2VsbC1j

Code:

async def initTwitch():

    loadOldData()

    logging.basicConfig(format='%(asctime)s %(levelname)-8s %(message)s',level=logging.DEBUG,datefmt='%H:%M:%S')

    target_scope = [AuthScope.BITS_READ,AuthScope.CHANNEL_READ_SUBSCRIPTIONS,AuthScope.USER_READ_CHAT]

    #Connect to twitch via Storage Helper
    print("\nInit Twitch...")
    if DEBUG_MODE:
        [...]
    else:
        twitch = await Twitch(TWITCH_CLIENT_ID, TWITCH_SECRET)
        helper = UserAuthenticationStorageHelper(twitch,target_scope)
        await helper.bind()

        # get the currently logged in user
        user = await first(twitch.get_users())
        print(f"Logged in as {user.display_name}!")

        # create eventsub websocket instance and start the client.
        eventsub = EventSubWebsocket(twitch)
        eventsub.start()
        await eventsub.listen_channel_chat_notification(user.id, user.id, on_subscribe)
        await eventsub.listen_channel_cheer(user.id, on_bits)
        print("Listening to subs and cheers...")

asyncio.run(initTwitch())

Omitted the callback functions of the eventsub. If you want, I can post them though.

twitchAPI is version 4.2.0, Python version is 3.10.

Latent-Logic commented 1 month ago

This is solved by https://github.com/Teekeks/pyTwitchAPI/pull/310 which has been merged but not released yet