Skip to content

Commit 95b8c17

Browse files
committed
fix RECONNECT crash
1 parent 7b67774 commit 95b8c17

File tree

5 files changed

+26
-5
lines changed

5 files changed

+26
-5
lines changed

docs/changelog.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Master
44
======
55
- TwitchIO
66
- Additions
7+
- Added :func:`~twitchio.Client.event_reconnect` to :class:`~twitchio.Client`
78
- Add attribute docs to :class:`~twitchio.PartialUser` and :class:`~twitchio.User`
89
- Added following new :class:`~twitchio.PartialUser` methods:
910
- :func:`twitchio.PartialUser.create_custom_reward`
@@ -39,6 +40,7 @@ Master
3940
- Updated IRC parser to not remove multiple spaces when clumped together
4041
- Fixed :func:`twitchio.Client.start` exiting immediatly
4142
- Chatters will now update correctly when someone leaves chat
43+
- Fixed a crash when twitch sends a RECONNECT notice
4244

4345
- ext.commands
4446
- Bug fixes

docs/twitchio.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Event Reference
2424
-----------------
2525

2626
.. automethod:: Client.event_ready()
27+
.. automethod:: Client.event_reconnect()
2728
.. automethod:: Client.event_raw_data(data: str)
2829
.. automethod:: Client.event_message(message: Message)
2930
.. automethod:: Client.event_join(channel: Channel, user: User)

twitchio/client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -969,6 +969,13 @@ async def event_ready():
969969
"""
970970
pass
971971

972+
async def event_reconnect(self):
973+
"""|coro|
974+
975+
Event called when twitch sends a RECONNECT notice.
976+
The library will automatically handle reconnecting when such an event is received
977+
"""
978+
972979
async def event_raw_data(self, data: str):
973980
"""|coro|
974981

twitchio/parse.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,13 @@
3939
"PRIVMSG(ECHO)",
4040
"USERSTATE",
4141
"MODE",
42-
"RECONNECT",
4342
"WHISPER",
4443
"USERNOTICE",
4544
)
4645
ACTIONS2 = ("USERSTATE", "ROOMSTATE", "PRIVMSG", "USERNOTICE", "WHISPER")
4746
USER_SUB = re.compile(r":(?P<user>.*)!")
4847
MESSAGE_RE = re.compile(r":(?P<useraddr>\S+) (?P<action>\S+) #(?P<channel>\S+)( :(?P<message>.*))?$")
48+
FAST_RETURN = {"RECONNECT": {"code": 0, "action": "RECONNECT"}, "PING": {"action": "PING"}}
4949

5050
logger = logging.getLogger("twitchio.parser")
5151

@@ -58,11 +58,18 @@ def parser(data: str, nick: str):
5858
user = None
5959
badges = None
6060

61-
if action == "PING":
62-
return dict(action="PING")
61+
_group_len = len(groups)
62+
63+
if action in FAST_RETURN:
64+
return FAST_RETURN[action]
65+
66+
elif groups[1] in FAST_RETURN:
67+
return FAST_RETURN[groups[1]]
6368

6469
elif (
65-
groups[1] in ACTIONS or groups[2] in ACTIONS or (len(groups) > 3 and groups[3] in {"PRIVMSG", "PRIVMSG(ECHO)"})
70+
groups[1] in ACTIONS
71+
or (_group_len > 2 and groups[2] in ACTIONS)
72+
or (_group_len > 3 and groups[3] in {"PRIVMSG", "PRIVMSG(ECHO)"})
6673
):
6774
result = re.search(MESSAGE_RE, data)
6875
if not result:

twitchio/websocket.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ async def _keep_alive(self):
148148

149149
if not self._last_ping:
150150
self._last_ping = time.time()
151-
while not self._websocket.closed:
151+
while not self._websocket.closed and not self._reconnect_requested:
152152
msg = await self._websocket.receive() # Receive data...
153153

154154
if msg.type is aiohttp.WSMsgType.CLOSED:
@@ -165,6 +165,7 @@ async def _keep_alive(self):
165165
continue
166166
task = asyncio.create_task(self._process_data(event))
167167
task.add_done_callback(partial(self._task_callback, event)) # Process our raw data
168+
168169
asyncio.create_task(self._connect())
169170

170171
def _task_callback(self, data, task):
@@ -487,6 +488,9 @@ async def _mode(self, parsed): # TODO
487488
async def _reconnect(self, parsed):
488489
log.debug("ACTION: RECONNECT:: Twitch has gracefully closed the connection and will reconnect.")
489490
self._reconnect_requested = True
491+
self._keeper.cancel()
492+
self._loop.create_task(self._connect())
493+
self.dispatch("reconnect")
490494

491495
def dispatch(self, event: str, *args, **kwargs):
492496
log.debug(f"Dispatching event: {event}")

0 commit comments

Comments
 (0)