From ee78d8fc2a1fccbdb983b813d30746c9f0278c0c Mon Sep 17 00:00:00 2001 From: Ollie <69084614+olijeffers0n@users.noreply.github.com> Date: Wed, 7 Aug 2024 21:29:06 +0100 Subject: [PATCH] Update docs and fix issues with the ws closing --- docs/SUMMARY.md | 2 -- .../api-methods/getting-current-map-events.md | 12 ----------- .../api-methods/getting-entity-information.md | 4 ++++ docs/api-methods/removing-listeners.md | 16 ++++++++++++-- docs/api-methods/toggling-smart-switches.md | 8 ------- docs/command-system/command-decorator.md | 16 +++++++------- docs/command-system/command-options.md | 11 ++++------ docs/command-system/commands-overview.md | 9 ++++---- .../getting-player-details/README.md | 2 +- .../getting-player-details/fcm-listener.md | 2 +- docs/getting-started/quick-start.md | 7 ++++--- rustplus/remote/ratelimiter/__init__.py | 21 +++++++------------ rustplus/remote/websocket/ws.py | 13 +++++++++--- 13 files changed, 60 insertions(+), 63 deletions(-) delete mode 100644 docs/api-methods/getting-current-map-events.md delete mode 100644 docs/api-methods/toggling-smart-switches.md diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index e5265e9..b23524b 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -21,10 +21,8 @@ * [Getting the Time](api-methods/getting-the-time.md) * [Getting Entity Information](api-methods/getting-entity-information.md) * [Getting Map Markers](api-methods/getting-map-markers.md) -* [Getting Current Map Events](api-methods/getting-current-map-events.md) * [Getting Contents of Monitors](api-methods/getting-contents-of-monitors.md) * [Promoting Players to Team Leader](api-methods/promoting-players-to-team-leader.md) -* [Toggling Smart Switches](api-methods/toggling-smart-switches.md) ## Command System diff --git a/docs/api-methods/getting-current-map-events.md b/docs/api-methods/getting-current-map-events.md deleted file mode 100644 index c0f1532..0000000 --- a/docs/api-methods/getting-current-map-events.md +++ /dev/null @@ -1,12 +0,0 @@ -# Getting Current Map Events - -The following are all defined as "events": - -* Explosions (Bradley / Attack Helicopter) -* Cargo Ship -* CH47 (Chinook) -* Locked Crates -* Attack Helicopter - -Calling `rust_socket.get_current_events()` returns a list of all current `RustMarker`'s that are the above events. This can be used for working out whether Cargo Ship / Oil Rig etc has been taken / is being taken. See [Here ](getting-map-markers.md)for information on `RustMarker` - diff --git a/docs/api-methods/getting-entity-information.md b/docs/api-methods/getting-entity-information.md index 7b774d5..d74884f 100644 --- a/docs/api-methods/getting-entity-information.md +++ b/docs/api-methods/getting-entity-information.md @@ -27,3 +27,7 @@ Alarm = 2 StorageMonitor = 3 ``` +## Setting Entity Information + +Calling `rust_socket.set_entity_value(entity_id: int, value: bool)` will set the value of the entity with the given ID to the given value. + diff --git a/docs/api-methods/removing-listeners.md b/docs/api-methods/removing-listeners.md index 16f0245..f6e0a7b 100644 --- a/docs/api-methods/removing-listeners.md +++ b/docs/api-methods/removing-listeners.md @@ -2,9 +2,21 @@ ### Registered Listeners -A registered listener is a wrapper object around the coroutine itself that will allow the listener to be removed later on. Should you need the coroutine back, call `RegisteredListener.get_coro()`. +A registered listener is a wrapper object around the coroutine itself that will allow the listener to be removed later +on. Should you need the coroutine back, call `RegisteredListener.get_coro()`. ### Removing The listener -Removing a listener is as simple as calling `RustSocket.remove_listener(RegisteredListener)` and will return a boolean value. True if a listener was removed and false otherwise +Removing a listener is as simple as using an Event's HandlerList. This is one example: +```python +@EntityEvent(server_details, 25743493) +async def on_entity_event(payload: EntityEventPayload): + await rust_socket.set_entity_value(payload.entity_id, not payload.value) + + +EntityEventPayload.HANDLER_LIST.unregister(on_entity_event, server_details) + +# You can also unregister all listeners for a specific event +EntityEventPayload.HANDLER_LIST.unregister_all() +``` diff --git a/docs/api-methods/toggling-smart-switches.md b/docs/api-methods/toggling-smart-switches.md deleted file mode 100644 index 86d4f26..0000000 --- a/docs/api-methods/toggling-smart-switches.md +++ /dev/null @@ -1,8 +0,0 @@ -# Toggling Smart Switches - -Calling `rust_socket.turn_on_smart_switch(eid: int)` and `rust_socket.turn_off_smart_switch(eid: int)` can be used to toggle smart switches on and off from code. To get the entity\_ids look at: - -{% content-ref url="../getting-started/getting-player-details/getting-entity-ids.md" %} -[getting-entity-ids.md](../getting-started/getting-player-details/getting-entity-ids.md) -{% endcontent-ref %} - diff --git a/docs/command-system/command-decorator.md b/docs/command-system/command-decorator.md index ad6f780..1c1e5de 100644 --- a/docs/command-system/command-decorator.md +++ b/docs/command-system/command-decorator.md @@ -1,16 +1,18 @@ +from main import server_details + # Command Decorator The command decorator is used to mark a coroutine as a command listener. Usage: ```python -@rust_socket.command -async def hi(command: Command): +@Command(server_details) +async def hi(command: ChatCommand): print("Command Ran!") ``` The fact that the coroutine's name is `hi` means that the command will be `hi` . -You also get access to this `Command` object which has a slew of useful information about the how the command was called. +You also get access to this `ChatCommand` object which has a slew of useful information about the how the command was called. | Field | Value | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------- | @@ -27,16 +29,16 @@ This decorator returns a [`RegisteredListener`](../api-methods/removing-listener You don't want to have to register 100's of commands for every permutation of phrasing, so why should you! ```python -@rust_socket.command(aliases=["hello", "hey"]) -async def hi(command: Command): +@ChatCommand(server_details, aliases=["hello", "hey"]) +async def hi(command: ChatCommand): print("Command Ran!") ``` This is a simple example of how you could incorporate different function names into one command, but sometimes we need more than that! ```python -@rust_socket.command(alais_func=lambda x: x.lower() == "test") -async def pair(command: Command): +@ChatCommand(server_details, alais_func=lambda x: x.lower() == "test") +async def pair(command: ChatCommand): print("Command Ran!") ``` diff --git a/docs/command-system/command-options.md b/docs/command-system/command-options.md index 5d2848c..656ef97 100644 --- a/docs/command-system/command-options.md +++ b/docs/command-system/command-options.md @@ -1,14 +1,11 @@ # Command Options -Command options are what you use to tell the [`RustSocket`](../getting-started/rustsocket/) what the general structure of your commands will be. These define the prefix for the command, as well as any "overruling commands" which are commands that do not require a prefix. Usage: +Command options are what you use to tell the [`RustSocket`](../getting-started/rustsocket/) what the general structure of your commands will be. +These define the prefix for the command, as well as any "overruling commands" which are commands that do not require a prefix. Usage: ```python -from rustplus import RustSocket +from rustplus import RustSocket, CommandOptions -options = CommandOptions(prefix="!", overruling_commands = ["time"]) - -# Prefix is a string, and the overruling_commands are a list of strings which would be the name of the coroutines +options = CommandOptions(prefix="!") ``` -You can then just pass these into the RustSocket constructor using the `overruling_commands` kwarg. - diff --git a/docs/command-system/commands-overview.md b/docs/command-system/commands-overview.md index 962709d..a167683 100644 --- a/docs/command-system/commands-overview.md +++ b/docs/command-system/commands-overview.md @@ -4,13 +4,14 @@ Commands allow the triggering of custom coroutines when a specific keyword is se {% code title="main.py" %} ```python -from rustplus import RustSocket, CommandOptions, Command +from rustplus import RustSocket, CommandOptions, Command, ServerDetails, Command, ChatCommand options = CommandOptions(prefix="!") # Use whatever prefix you want here -rust_socket = RustSocket("IP", "PORT", STEAMID, PLAYERTOKEN, command_options=options) +server_details = ServerDetails("IP", "PORT", STEAMID, PLAYERTOKEN) +socket = RustSocket(server_details) -@rust_socket.command -async def hi(command : Command): +@Command(server_details) +async def hi(command : ChatCommand): await socket.send_team_message(f"Hi, {command.sender_name}") ``` {% endcode %} diff --git a/docs/getting-started/getting-player-details/README.md b/docs/getting-started/getting-player-details/README.md index 2ae2c26..fafbf4c 100644 --- a/docs/getting-started/getting-player-details/README.md +++ b/docs/getting-started/getting-player-details/README.md @@ -1,5 +1,5 @@ --- -description: This will show you how to get your personal player details using the RustCli +description: This will show you how to get your personal player details using the Web tool --- # Getting Player Details diff --git a/docs/getting-started/getting-player-details/fcm-listener.md b/docs/getting-started/getting-player-details/fcm-listener.md index bf13f09..f1b4a35 100644 --- a/docs/getting-started/getting-player-details/fcm-listener.md +++ b/docs/getting-started/getting-player-details/fcm-listener.md @@ -19,7 +19,7 @@ FCM(fcm_details).start() ``` {% endcode %} -The `on_notification` method will be called everytime a message is recieved from the game server. +The `on_notification` method will be called everytime a message is received from the game server. The `rustplus.py.config.json` is the file created by the RustCli, when you register for FCM notifications. See: diff --git a/docs/getting-started/quick-start.md b/docs/getting-started/quick-start.md index 2360b5f..98f217a 100644 --- a/docs/getting-started/quick-start.md +++ b/docs/getting-started/quick-start.md @@ -6,7 +6,7 @@ In order to access the API, you must first install the package using pip: pip install rustplus ``` -You must then get your Personal details using the RustCli, as shown here: +You must then get your Personal details using the web tool, as shown here: {% content-ref url="getting-player-details/" %} [getting-player-details](getting-player-details/) @@ -15,10 +15,11 @@ You must then get your Personal details using the RustCli, as shown here: {% code title="main.py" %} ```python import asyncio -from rustplus import RustSocket +from rustplus import RustSocket, ServerDetails async def main(): - socket = RustSocket("IP", "PORT", STEAMID, PLAYERTOKEN) + server_details = ServerDetails("IP", "PORT", STEAMID, PLAYERTOKEN) + socket = RustSocket(server_details) await socket.connect() print(f"It is {(await socket.get_time()).time}") diff --git a/rustplus/remote/ratelimiter/__init__.py b/rustplus/remote/ratelimiter/__init__.py index f39ff86..370d86a 100644 --- a/rustplus/remote/ratelimiter/__init__.py +++ b/rustplus/remote/ratelimiter/__init__.py @@ -19,21 +19,16 @@ def __init__( self.refresh_per_second = self.refresh_amount / self.refresh_rate def can_consume(self, amount) -> bool: - if (self.current - amount) >= 0: - return True - - return False + return (self.current - amount) >= 0 def consume(self, amount: int = 1) -> None: self.current -= amount def refresh(self) -> None: time_now = time.time() - time_delta = time_now - self.last_update self.last_update = time_now - - self.current = min([self.current + time_delta * self.refresh_amount, self.max]) + self.current = min(self.current + time_delta * self.refresh_per_second, self.max) class RateLimiter: @@ -73,17 +68,14 @@ async def can_consume(self, server_details: ServerDetails, amount: int = 1) -> b Returns whether the user can consume the amount of tokens provided """ async with self.lock: - can_consume = True - for bucket in [ self.socket_buckets.get(server_details), self.server_buckets.get(server_details.get_server_string()), ]: bucket.refresh() if not bucket.can_consume(amount): - can_consume = False - - return can_consume + return False + return True async def consume(self, server_details: ServerDetails, amount: int = 1) -> None: """ @@ -96,8 +88,11 @@ async def consume(self, server_details: ServerDetails, amount: int = 1) -> None: ]: bucket.refresh() if not bucket.can_consume(amount): - self.lock.release() raise RateLimitError("Not Enough Tokens") + for bucket in [ + self.socket_buckets.get(server_details), + self.server_buckets.get(server_details.get_server_string()), + ]: bucket.consume(amount) async def get_estimated_delay_time( diff --git a/rustplus/remote/websocket/ws.py b/rustplus/remote/websocket/ws.py index 61d5e29..98dfcb2 100644 --- a/rustplus/remote/websocket/ws.py +++ b/rustplus/remote/websocket/ws.py @@ -1,7 +1,7 @@ import shlex import base64 import betterproto -from websockets.exceptions import InvalidURI, InvalidHandshake +from websockets.exceptions import InvalidURI, InvalidHandshake, ConnectionClosedError from websockets.legacy.client import WebSocketClientProtocol from websockets.client import connect from asyncio import TimeoutError, Task, AbstractEventLoop @@ -110,9 +110,16 @@ async def run(self) -> None: app_message = AppMessage() app_message.parse(data) + except ConnectionClosedError as e: + if self.debug: + self.logger.exception("Connection Interrupted: %s", e) + else: + self.logger.warning("Connection Interrupted: %s", e) + break + except Exception as e: self.logger.exception( - "An Error occurred whilst parsing the message from the server", e + "An Error occurred whilst parsing the message from the server: %s", e ) continue @@ -215,7 +222,7 @@ async def handle_message(self, app_message: AppMessage) -> None: self.server_details ).get(str(app_message.broadcast.entity_changed.entity_id), []) for handler in handlers: - handler.get_coro()( + await handler.get_coro()( EntityEventPayload( entity_changed=app_message.broadcast.entity_changed, )