425 lines
16 KiB
Python
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}") |