Implemented bot endpoint with DB requests and other tweaks

This commit is contained in:
Logan Cusano
2025-05-24 18:12:59 -04:00
parent 15b12ecd5f
commit 107ab049ff
6 changed files with 350 additions and 35 deletions

84
app/routers/bot.py Normal file
View File

@@ -0,0 +1,84 @@
import json
from quart import Blueprint, jsonify, request, abort, current_app
from werkzeug.exceptions import HTTPException
from internal.types import ActiveClient
from internal.db_wrappers import DiscordIdDbController
bot_bp = Blueprint('bot', __name__)
@bot_bp.route("/", methods=['GET'])
async def get_online_bots_route():
"""API endpoint to list bots (by name) currently online."""
return jsonify(list(current_app.active_clients.keys()))
@bot_bp.route('/request_token', methods=['POST'])
async def request_token_route():
"""
API endpoint to request a token for a client.
Expects 'client_id' in the JSON request body.
"""
try:
request_data = await request.get_json()
if not request_data or 'client_id' not in request_data:
abort(400, "Missing 'client_id' in request body.")
client_id = request_data['client_id']
print(f"Request received for client_id: {client_id}")
# get the available IDs
active_d_ids = await current_app.d_id_db_h.find_discord_ids(active_only=True)
# init available IDs list
avail_ids = []
# Init the selected ID
selected_id = None
# Check which IDs are currently in use by other bots
for d_id in active_d_ids:
if not find_token_in_active_clients(d_id.token):
avail_ids.append(d_id)
if not avail_ids:
abort(404, "No available active Discord IDs found.")
# --- Logic for selecting a preferred ID based on client_id (TODO) ---
selected_id = avail_ids[0]
# --- End of logic for selecting a preferred ID ---
return jsonify(selected_id.to_dict())
except Exception as e:
print(f"Error in request_token_route: {e}")
abort(500, f"An internal error occurred: {e}")
def find_token_in_active_clients(target_token: str) -> bool:
"""
Checks if a target_token exists in the active_token of any ActiveClient object in a list.
Args:
clients: A list of ActiveClient objects.
target_token: The token string to search for.
Returns:
True if the token is found in any ActiveClient, False otherwise.
"""
for client in current_app.active_clients:
if client.active_token == target_token:
return True
return False
# query_params = dict(request.args)
# systems = await current_app.sys_db_h.find_systems(query_params)

View File

@@ -2,17 +2,14 @@ import json
from quart import Blueprint, jsonify, request, abort, current_app
from werkzeug.exceptions import HTTPException
from enum import Enum
from internal.types import ActiveClient, NodeCommands
nodes_bp = Blueprint('nodes', __name__)
class NodeCommands(str, Enum):
JOIN = "join_server"
LEAVE = "leave_server"
async def register_client(websocket, client_id):
"""Registers a new client connection."""
current_app.active_clients[client_id] = websocket
current_app.active_clients[client_id] = ActiveClient(websocket)
print(f"Client {client_id} connected.")
@@ -26,7 +23,7 @@ async def unregister_client(client_id):
async def send_command_to_client(client_id, command_name, *args):
"""Sends a command to a specific client."""
if client_id in current_app.active_clients:
websocket = current_app.active_clients[client_id]
websocket = current_app.active_clients[client_id].websocket
message = json.dumps({"type": "command", "name": command_name, "args": args})
try:
await websocket.send(message)
@@ -52,7 +49,6 @@ async def send_command_to_all_clients(command_name, *args):
await unregister_client(client_id)
@nodes_bp.route("/", methods=['GET'])
async def get_nodes():
"""API endpoint to list currently connected client IDs."""

View File

@@ -1,10 +1,8 @@
from quart import Blueprint, jsonify, request, abort
from internal.db_wrappers import SystemDbController
from quart import Blueprint, jsonify, request, abort, current_app
from werkzeug.exceptions import HTTPException
from internal.types import System
systems_bp = Blueprint('systems', __name__)
db_h = SystemDbController()
@systems_bp.route("/", methods=['POST'])
@@ -19,24 +17,24 @@ async def create_system_route():
abort(400, "Request body must be JSON") # Bad Request
if '_id' in request_data:
id_search_result = await db_h.find_system({"_id": request_data["_id"]})
id_search_result = await current_app.sys_db_h.find_system({"_id": request_data["_id"]})
if id_search_result:
# If _id is provided and exists, return conflict
abort(409, f"System with ID '{request_data['_id']}' already exists")
# Check if name exists (optional, depending on requirements)
if 'name' in request_data:
name_search_result = await db_h.find_system({"name": request_data["name"]})
name_search_result = await current_app.sys_db_h.find_system({"name": request_data["name"]})
if name_search_result:
abort(409, f"System with name '{request_data['name']}' already exists")
# Check if frequency_khz exists (optional, depending on requirements)
if 'frequency_khz' in request_data:
freq_search_result = await db_h.find_system({"frequency_khz": request_data["frequency_khz"]})
freq_search_result = await current_app.sys_db_h.find_system({"frequency_khz": request_data["frequency_khz"]})
if freq_search_result:
abort(409, f"System with frequency '{request_data['frequency_khz']}' already exists")
created_system = await db_h.create_system(request_data)
created_system = await current_app.sys_db_h.create_system(request_data)
if created_system:
print("Created new system:", created_system)
@@ -56,7 +54,7 @@ async def list_systems_route():
"""API endpoint to get a list of all systems."""
print("\n--- Handling GET /systems ---")
try:
all_systems = await db_h.find_all_systems()
all_systems = await current_app.sys_db_h.find_all_systems()
return jsonify([system.to_dict() for system in all_systems]), 200 # 200 OK status code
except HTTPException:
@@ -72,7 +70,7 @@ async def get_system_route(system_id: str):
print(f"\n--- Handling GET /systems/{system_id} ---")
try:
# Fix the query dictionary syntax
system = await db_h.find_system({'_id': system_id})
system = await current_app.sys_db_h.find_system({'_id': system_id})
if system:
# system is a System object, jsonify will convert it
@@ -93,7 +91,7 @@ async def get_system_by_client_route(client_id: str):
print(f"\n--- Handling GET /systems/client/{client_id} ---")
try:
# Fix the query dictionary syntax
systems = await db_h.find_systems({'avail_on_nodes': client_id})
systems = await current_app.sys_db_h.find_systems({'avail_on_nodes': client_id})
if systems:
# system is a System object, jsonify will convert it
@@ -111,7 +109,7 @@ async def get_system_by_client_route(client_id: str):
@systems_bp.route('/<string:system_id>', methods=['PUT'])
async def update_system_route(system_id: str, updated_system_data):
try:
update_system = await db_h.update_system({"_id", system_id}, updated_system_data)
update_system = await current_app.sys_db_h.update_system({"_id", system_id}, updated_system_data)
if update_system:
print("Updated system:", update_system)
@@ -130,7 +128,7 @@ async def update_system_route(system_id: str, updated_system_data):
@systems_bp.route('/<string:system_id>', methods=['DELETE'])
async def delete_system_route(system_id: str):
try:
deleted_system = await db_h.delete_system({"_id", system_id})
deleted_system = await current_app.sys_db_h.delete_system({"_id", system_id})
if deleted_system:
print("Deleted system:", deleted_system)
@@ -166,7 +164,7 @@ async def assign_client_to_system_route(system_id: str):
abort(400, "'client_id' must be a non-empty string")
# First, check if the system exists
existing_system = await db_h.find_system({"_id": system_id})
existing_system = await current_app.sys_db_h.find_system({"_id": system_id})
if existing_system is None:
abort(404, f"System with ID '{system_id}' not found")
@@ -175,7 +173,7 @@ async def assign_client_to_system_route(system_id: str):
update_query = {"_id": system_id}
update_data = {"$addToSet": {"avail_on_nodes": client_id}}
update_result = await db_h.update_system(update_query, update_data)
update_result = await current_app.sys_db_h.update_system(update_query, update_data)
if update_result > 0:
print(f"Client '{client_id}' assigned to system '{system_id}'.")
@@ -184,7 +182,7 @@ async def assign_client_to_system_route(system_id: str):
print(f"Client '{client_id}' was already assigned to system '{system_id}'.")
status = "already_assigned"
updated_system = await db_h.find_system({"_id": system_id})
updated_system = await current_app.sys_db_h.find_system({"_id": system_id})
if updated_system:
return jsonify({
"status": status,
@@ -222,7 +220,7 @@ async def dismiss_client_from_system_route(system_id: str):
abort(400, "'client_id' must be a non-empty string")
# First, check if the system exists
existing_system = await db_h.find_system({"_id": system_id})
existing_system = await current_app.sys_db_h.find_system({"_id": system_id})
if existing_system is None:
abort(404, f"System with ID '{system_id}' not found")
@@ -231,7 +229,7 @@ async def dismiss_client_from_system_route(system_id: str):
update_query = {"_id": system_id}
update_data = {"$pull": {"avail_on_nodes": client_id}}
update_result = await db_h.update_system(update_query, update_data)
update_result = await current_app.sys_db_h.update_system(update_query, update_data)
if update_result > 0:
print(f"Client '{client_id}' dismissed from system '{system_id}'.")
@@ -242,7 +240,7 @@ async def dismiss_client_from_system_route(system_id: str):
# Note: update_result.matched_count will be 1 even if modified_count is 0
# Optionally fetch the updated document to return its current state
updated_system = await db_h.find_system({"_id": system_id})
updated_system = await current_app.sys_db_h.find_system({"_id": system_id})
if updated_system:
return jsonify({
"status": status,
@@ -271,7 +269,9 @@ async def search_systems_route():
try:
query_params = dict(request.args)
systems = await db_h.find_systems(query_params)
systems = await current_app.sys_db_h.find_systems(query_params)
print("Found systems", systems)
if systems:
# If systems are found, return them as a list of dictionaries