Files
drb-server-discord-bot/app/internal/drb_srv_api.py
Logan Cusano f34241acac Init
2025-05-24 02:09:35 -04:00

425 lines
16 KiB
Python

import requests
import json
import os
class CoreAPI:
def _handle_response(self, response):
"""
Handles the API response, checking for successful status codes and
raising exceptions for errors.
Args:
response (requests.Response): The response object from a requests call.
Returns:
dict or list: The JSON response body if the request was successful.
Raises:
requests.exceptions.HTTPError: If the response status code indicates an error.
requests.exceptions.RequestException: For other request-related errors.
json.JSONDecodeError: If the response body is not valid JSON.
"""
try:
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
if response.content:
return response.json()
return None # Handle cases with no response body (e.g., 204 No Content)
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
raise
except json.JSONDecodeError:
print(f"Failed to decode JSON from response: {response.text}")
raise
class NodeAPIWrapper(CoreAPI):
"""
A wrapper class for interacting with the Node API endpoints.
"""
def __init__(self):
"""
Initializes the API wrapper with the base URL of the Quart application.
Args:
base_url (str): The base URL of your Quart application (e.g., "http://localhost:5000").
"""
self.base_url = f"{os.getenv('API_BASE_URL', 'http://localhost:5000')}/nodes"
async def get_nodes(self) -> requests.Response:
"""
API endpoint to list currently connected client IDs.
Returns:
requests.Response: The response object from the API.
On success (200), response.json() will be a list of client IDs.
"""
url = self.base_url
try:
response = requests.get(url)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error creating system: {e}")
raise
async def join(self, client_id: str, system_id: str, guild_id: str, channel_id: str) -> requests.Response:
"""
Send a join command to the specific system specified.
Args:
client_id (str): The ID of the client to send the command to.
system_id (str): The system ID for the join command.
guild_id (str): The guild ID for the join command.
channel_id (str): The channel ID for the join command.
Returns:
requests.Response: The response object from the API.
On success (200), response.json() will contain status information.
"""
url = f"{self.base_url}/join"
payload = {
"client_id": client_id,
"system_id": system_id,
"guild_id": guild_id,
"channel_id": channel_id
}
try:
response = requests.post(url, json=payload)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error creating system: {e}")
raise
async def leave(self, client_id: str, guild_id: str) -> requests.Response:
"""
Send a leave command to the specific client.
Args:
client_id (str): The ID of the client to send the command to.
guild_id (str): The guild ID for the leave command.
Returns:
requests.Response: The response object from the API.
On success (200), response.json() will contain status information.
"""
url = f"{self.base_url}/leave"
payload = {
"client_id": client_id,
"guild_id": guild_id
}
try:
response = requests.post(url, json=payload)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error creating system: {e}")
raise
class SystemAPIWrapper(CoreAPI):
"""
A Python wrapper class for interacting with the System API endpoints
using the requests library.
"""
def __init__(self):
"""
Initializes the SystemAPIWrapper with the base URL of the API.
Args:
base_url (str): The base URL of the System API (e.g., "http://localhost:5000/systems").
"""
self.base_url = f"{os.getenv('API_BASE_URL', 'http://localhost:5000')}/systems"
async def create_system(self, system_data):
"""
Creates a new system.
Args:
system_data (dict): A dictionary containing the system data.
Returns:
dict: The created system object.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/"
try:
response = requests.post(url, json=system_data)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error creating system: {e}")
raise
async def list_systems(self):
"""
Retrieves a list of all systems.
Returns:
list: A list of system objects.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/"
try:
response = requests.get(url)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error listing systems: {e}")
raise
async def get_system_by_id(self, system_id):
"""
Retrieves details for a specific system by ID.
Args:
system_id (str): The ID of the system.
Returns:
dict: The system object.
Raises:
requests.exceptions.RequestException: If the request fails (e.g., 404 if not found).
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/{system_id}"
try:
response = requests.get(url)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error getting system by ID {system_id}: {e}")
raise
async def get_systems_by_client_id(self, client_id):
"""
Retrieves a list of systems available on a specific client ID.
Args:
client_id (str): The ID of the client.
Returns:
list: A list of system objects.
Raises:
requests.exceptions.RequestException: If the request fails (e.g., 404 if client not found or no systems).
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/client/{client_id}"
try:
response = requests.get(url)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error getting systems by client ID {client_id}: {e}")
raise
async def update_system(self, system_id, updated_system_data):
"""
Updates a specific system by ID.
Args:
system_id (str): The ID of the system to update.
updated_system_data (dict): A dictionary containing the updated system data.
Returns:
dict: The updated system object.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/{system_id}"
try:
response = requests.put(url, json=updated_system_data)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error updating system {system_id}: {e}")
raise
async def delete_system(self, system_id):
"""
Deletes a specific system by ID.
Args:
system_id (str): The ID of the system to delete.
Returns:
dict: The deleted system object.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/{system_id}"
try:
response = requests.delete(url)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error deleting system {system_id}: {e}")
raise
async def search_systems(self, **kwargs):
"""
Searches for systems based on provided query parameters.
Args:
**kwargs: Keyword arguments representing the query parameters
(e.g., name="MySystem", frequency_khz=1000).
Returns:
list: A list of system objects matching the criteria.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/search"
try:
# requests.get automatically handles the params dictionary
response = requests.get(url, params=kwargs)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error searching systems with parameters {kwargs}: {e}")
raise
async def assign_client_to_system(self, system_id, client_id):
"""
Assigns a client ID to a system's available_on_nodes list.
Args:
system_id (str): The ID of the system.
client_id (str): The ID of the client to assign.
Returns:
dict: A dictionary containing the status and the updated system object.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/{system_id}/assign"
payload = {"client_id": client_id}
try:
response = requests.post(url, json=payload)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error assigning client {client_id} to system {system_id}: {e}")
raise
async def dismiss_client_from_system(self, system_id, client_id):
"""
Dismisses (removes) a client ID from a system's available_on_nodes list.
Args:
system_id (str): The ID of the system.
client_id (str): The ID of the client to dismiss.
Returns:
dict: A dictionary containing the status and the updated system object.
Raises:
requests.exceptions.RequestException: If the request fails.
json.JSONDecodeError: If the response is not valid JSON.
"""
url = f"{self.base_url}/{system_id}/dismiss"
payload = {"client_id": client_id}
try:
response = requests.post(url, json=payload)
return self._handle_response(response)
except (requests.exceptions.RequestException, json.JSONDecodeError) as e:
print(f"Error dismissing client {client_id} from system {system_id}: {e}")
raise
# Example Usage (assuming your Quart app is running on http://localhost:5000)
if __name__ == '__main__':
api = SystemAPIWrapper("http://localhost:5000/systems")
# Example: Create a new system
new_system_data = {
"name": "Test System",
"frequency_khz": 100,
"avail_on_nodes": []
}
try:
created_system = api.create_system(new_system_data)
print("Created System:", created_system)
except requests.exceptions.HTTPError as e:
print(f"Failed to create system: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: List all systems
try:
all_systems = api.list_systems()
print("\nAll Systems:", all_systems)
except requests.exceptions.RequestException as e:
print(f"Failed to list systems: {e}")
# Example: Get a system by ID (replace with a known system ID)
system_id_to_get = "some_system_id" # Replace with an actual ID
try:
system = api.get_system_by_id(system_id_to_get)
print(f"\nSystem with ID {system_id_to_get}:", system)
except requests.exceptions.HTTPError as e:
print(f"Failed to get system by ID {system_id_to_get}: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: Get systems by client ID (replace with a known client ID)
client_id_to_get = "some_client_id" # Replace with an actual ID
try:
client_systems = api.get_systems_by_client_id(client_id_to_get)
print(f"\nSystems for client ID {client_id_to_get}:", client_systems)
except requests.exceptions.HTTPError as e:
print(f"Failed to get systems by client ID {client_id_to_get}: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: Update a system (replace with a known system ID)
system_id_to_update = "some_system_id" # Replace with an actual ID
updated_data = {"frequency_khz": 120}
try:
updated_system = api.update_system(system_id_to_update, updated_data)
print(f"\nUpdated system {system_id_to_update}:", updated_system)
except requests.exceptions.HTTPError as e:
print(f"Failed to update system {system_id_to_update}: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: Assign a client to a system (replace with known IDs)
system_id_to_assign = "some_system_id" # Replace with an actual ID
client_id_to_assign = "new_client_1" # Replace with an actual ID
try:
assign_result = api.assign_client_to_system(system_id_to_assign, client_id_to_assign)
print(f"\nAssign client {client_id_to_assign} to system {system_id_to_assign} result:", assign_result)
except requests.exceptions.HTTPError as e:
print(f"Failed to assign client to system: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: Dismiss a client from a system (replace with known IDs)
system_id_to_dismiss = "some_system_id" # Replace with an actual ID
client_id_to_dismiss = "new_client_1" # Replace with an actual ID
try:
dismiss_result = api.dismiss_client_from_system(system_id_to_dismiss, client_id_to_dismiss)
print(f"\nDismiss client {client_id_to_dismiss} from system {system_id_to_dismiss} result:", dismiss_result)
except requests.exceptions.HTTPError as e:
print(f"Failed to dismiss client from system: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
# Example: Delete a system (replace with a known system ID)
system_id_to_delete = "some_system_id" # Replace with an actual ID
try:
deleted_system = api.delete_system(system_id_to_delete)
print(f"\nDeleted system {system_id_to_delete}:", deleted_system)
except requests.exceptions.HTTPError as e:
print(f"Failed to delete system {system_id_to_delete}: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An unexpected error occurred: {e}")