diff --git a/rustplus/__init__.py b/rustplus/__init__.py index 2ddcaa4..b764171 100644 --- a/rustplus/__init__.py +++ b/rustplus/__init__.py @@ -8,5 +8,5 @@ __name__ = "rustplus" __author__ = "olijefferson" -__version__ = "4.1.1" +__version__ = "4.1.2" __support__ = "Discord: https://discord.gg/nQqJe8qvP8" diff --git a/rustplus/api/api.py b/rustplus/api/api.py index a804664..598e711 100644 --- a/rustplus/api/api.py +++ b/rustplus/api/api.py @@ -1,13 +1,12 @@ from typing import List -from websocket import create_connection, WebSocketConnectionClosedException from PIL import Image from io import BytesIO from collections import defaultdict from datetime import datetime from importlib import resources -import threading import asyncio +from .socket import EchoClient from .rustplus_pb2 import * from .structures import RustTime, RustInfo, RustMap, RustMarker, RustChatMessage, RustSuccess, RustTeamInfo, RustTeamMember, RustTeamNote, RustEntityInfo, RustContents, RustItem from ..utils import MonumentNameToImage, TimeParser, CoordUtil, ErrorChecker, IdToName, MapMarkerConverter @@ -46,44 +45,11 @@ def __initProto(self) -> AppRequest: request.playerToken = self.playertoken return request - def __start_listener(self) -> None: - - loop = asyncio.new_event_loop() - - loop.run_until_complete(self.__listener()) - loop.close() - - async def __listener(self) -> None: - - while self.ws != None: - - try: - - data = self.ws.recv() - - app_message = AppMessage() - app_message.ParseFromString(data) - - if app_message.broadcast.teamMessage.message.message == "": - if app_message.response.seq not in self.ignored_responses: - self.responses[app_message.response.seq] = app_message - else: - self.ignored_responses.remove(app_message.response.seq) - else: - message = RustChatMessage(app_message.broadcast.teamMessage.message) - - if message.message.startswith(self.prefix): - await self.command_handler.run_command(message=message) - - except WebSocketConnectionClosedException: - return - async def __getResponse(self, seq): while seq not in self.responses: await asyncio.sleep(0.1) - response = self.responses[seq] - del self.responses[seq] + response = self.responses.pop(seq) return response async def __sendAndRecieve(self, request, response = True) -> AppMessage: @@ -93,7 +59,7 @@ async def __sendAndRecieve(self, request, response = True) -> AppMessage: if self.ws == None: raise ClientNotConnectedError("Not Connected") - self.ws.send_binary(data) + self.ws.send(data, binary=True) if response: @@ -313,23 +279,31 @@ async def __getCurrentEvents(self): ################################################ + async def __start_websocket(self) -> None: + + self.ws = EchoClient(ip=self.ip, port=self.port, api=self, protocols=['http-only', 'chat']) + self.ws.daemon = False + self.ws.connect() + async def connect(self) -> None: """ Connect to the Rust Server """ - try: - self.ws = create_connection("ws://{}:{}".format(self.ip,self.port)) - except: - raise ServerNotResponsiveError("The sever is not available to connect to - your ip/port are either correct or the server is offline") + + await self.__start_websocket() - threading.Thread(target=self.__start_listener).start() + #except: + # raise ServerNotResponsiveError("The sever is not available to connect to - your ip/port are either correct or the server is offline") async def closeConnection(self) -> None: """ Close the connection to the Rust Server """ - self.ws.abort() + self.ws.close() self.ws = None + self.seq = 1 + self.responses = {} + self.ignored_responses = [] async def disconnect(self) -> None: """ diff --git a/rustplus/api/socket/__init__.py b/rustplus/api/socket/__init__.py new file mode 100644 index 0000000..67e5434 --- /dev/null +++ b/rustplus/api/socket/__init__.py @@ -0,0 +1 @@ +from .echo_client import EchoClient \ No newline at end of file diff --git a/rustplus/api/socket/echo_client.py b/rustplus/api/socket/echo_client.py new file mode 100644 index 0000000..ba2c61a --- /dev/null +++ b/rustplus/api/socket/echo_client.py @@ -0,0 +1,34 @@ +from ws4py.client.threadedclient import WebSocketClient +import asyncio + +from ..rustplus_pb2 import * +from ..structures import RustChatMessage + +class EchoClient(WebSocketClient): + + def __init__(self, ip, port, api, protocols=None, extensions=None, heartbeat_freq=None, ssl_options=None, headers=None, exclude_headers=None): + super().__init__(f"ws://{ip}:{port}", protocols=protocols, extensions=extensions, heartbeat_freq=heartbeat_freq, ssl_options=ssl_options, headers=headers, exclude_headers=exclude_headers) + + self.api = api + + def opened(self): + pass + + def closed(self, code, reason): + pass + + def received_message(self, message): + + app_message = AppMessage() + app_message.ParseFromString(message.data) + + if app_message.broadcast.teamMessage.message.message == "": + if app_message.response.seq not in self.api.ignored_responses: + self.api.responses[app_message.response.seq] = app_message + else: + self.api.ignored_responses.remove(app_message.response.seq) + else: + message = RustChatMessage(app_message.broadcast.teamMessage.message) + + if message.message.startswith(self.api.prefix): + asyncio.new_event_loop().run_until_complete(self.api.command_handler.run_command(message=message)) diff --git a/setup.py b/setup.py index 08a5414..3d9349c 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ project_urls={ "Issue tracker": "https://github.com/olijeffers0n/rustplus/issues", }, - version="4.1.1", + version="4.1.2", include_package_data=True, packages = ['rustplus', 'rustplus.api', 'rustplus.api.icons', 'rustplus.exceptions', 'rustplus.utils', 'rustplus.api.structures', 'rustplus.commands'], license='MIT', @@ -21,7 +21,7 @@ long_description_content_type='text/markdown', install_requires=[ "Pillow", - "websocket-client", + "ws4py", "protobuf", "asyncio" ],