Created
March 27, 2024 05:47
-
-
Save janovak/06664d9d3c1443d697ca07c602a8edfc to your computer and use it in GitHub Desktop.
Add lock to guard writing to connection
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/twitchAPI/chat/__init__.py b/twitchAPI/chat/__init__.py | |
| index d1b7ce8..b36f089 100644 | |
| --- a/twitchAPI/chat/__init__.py | |
| +++ b/twitchAPI/chat/__init__.py | |
| @@ -371,7 +371,7 @@ class HypeChat: | |
| self.currency: str = parsed['tags'].get('pinned-chat-paid-currency') | |
| """The ISO 4217 alphabetic currency code the user has sent the Hype Chat in.""" | |
| self.exponent: int = int(parsed['tags'].get('pinned-chat-paid-exponent')) | |
| """Indicates how many decimal points this currency represents partial amounts in. | |
| Decimal points start from the right side of the value defined in :const:`~twitchAPI.chat.HypeChat.amount`""" | |
| self.level: str = parsed['tags'].get('pinned-chat-paid-level') | |
| """The level of the Hype Chat, in English.\n | |
| @@ -589,6 +589,7 @@ class Chat: | |
| self.log_no_registered_command_handler: bool = True | |
| """Controls if instances of commands being issued in chat where no handler exists should be logged. |default|:code:`True`""" | |
| self.__connection = None | |
| + self.__connection_lock = threading.Lock() | |
| self._session = None | |
| self.__socket_thread: Optional[threading.Thread] = None | |
| self.__running: bool = False | |
| @@ -1069,7 +1070,8 @@ class Chat: | |
| async def _handle_ping(self, parsed: dict): | |
| self.logger.debug('got PING') | |
| - await self._send_message('PONG ' + parsed['parameters']) | |
| + with self.__connection_lock: | |
| + await self._send_message('PONG ' + parsed['parameters']) | |
| # noinspection PyUnusedLocal | |
| async def _handle_ready(self, parsed: dict): | |
| @@ -1122,10 +1124,11 @@ class Chat: | |
| t.add_done_callback(self._task_callback) | |
| async def __task_startup(self): | |
| - await self._send_message('CAP REQ :twitch.tv/membership twitch.tv/tags twitch.tv/commands') | |
| - await self._send_message(f'PASS oauth:{await self.twitch.get_refreshed_user_auth_token()}') | |
| - await self._send_message(f'NICK {self.username}') | |
| - self.__startup_complete = True | |
| + with self.__connection_lock: | |
| + await self._send_message('CAP REQ :twitch.tv/membership twitch.tv/tags twitch.tv/commands') | |
| + await self._send_message(f'PASS oauth:{await self.twitch.get_refreshed_user_auth_token()}') | |
| + await self._send_message(f'NICK {self.username}') | |
| + self.__startup_complete = True | |
| def _get_message_bucket(self, channel) -> RateLimitBucket: | |
| bucket = self._send_buckets.get(channel) | |
| @@ -1304,13 +1307,16 @@ class Chat: | |
| if len(target) > self._join_bucket.left(): | |
| # we want to join more than the current bucket has left, join slowly one after another | |
| # TODO we could join the current remaining bucket size in blocks | |
| - for r in target: | |
| - await self._join_bucket.put() | |
| - await self._send_message(f'JOIN #{r}') | |
| + | |
| + with self.__connection_lock: | |
| + for r in target: | |
| + await self._join_bucket.put() | |
| + await self._send_message(f'JOIN #{r}') | |
| else: | |
| # enough space in the current bucket left, join all at once | |
| - await self._join_bucket.put(len(target)) | |
| - await self._send_message(f'JOIN {",".join([f"#{x}" for x in target])}') | |
| + with self.__connection_lock: | |
| + await self._join_bucket.put(len(target)) | |
| + await self._send_message(f'JOIN {",".join([f"#{x}" for x in target])}') | |
| # wait for us to join all rooms | |
| timeout = datetime.datetime.now() + datetime.timedelta(seconds=self.join_timeout) | |
| while any([r in self._room_join_locks for r in target]) and timeout > datetime.datetime.now(): | |
| @@ -1335,7 +1341,8 @@ class Chat: | |
| await asyncio.sleep(0.1) | |
| if message is None or len(message) == 0: | |
| raise ValueError('message must be a non empty string') | |
| - await self._send_message(message) | |
| + with self.__connection_lock: | |
| + await self._send_message(message) | |
| async def send_message(self, room: CHATROOM_TYPE, text: str): | |
| """Send a message to the given channel | |
| @@ -1362,7 +1369,9 @@ class Chat: | |
| room = f'#{room}'.lower() | |
| bucket = self._get_message_bucket(room[1:]) | |
| await bucket.put() | |
| - await self._send_message(f'PRIVMSG {room} :{text}') | |
| + | |
| + with self.__connection_lock: | |
| + await self._send_message(f'PRIVMSG {room} :{text}') | |
| async def leave_room(self, chat_rooms: Union[List[str], str]): | |
| """leave one or more chat rooms\n | |
| @@ -1375,7 +1384,8 @@ class Chat: | |
| target = [c[1:].lower() if c[0] == '#' else c.lower() for c in chat_rooms] | |
| for r in target: | |
| self._room_leave_locks.append(r) | |
| - await self._send_message(f'PART {room_str}') | |
| + with self.__connection_lock: | |
| + await self._send_message(f'PART {room_str}') | |
| for x in target: | |
| if x in self._join_target: | |
| self._join_target.remove(x) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment