Files
happening/server/src/api.rs
T
2026-05-19 19:34:56 +01:00

138 lines
3.5 KiB
Rust

use warp::Filter;
use crate::
{
// internal code
character,
UnwrapOrExit,
// libraries
json,
HashMap,
Arc,
Mutex,
VecDeque,
config,
mpsc::Sender,
info,
debug,
warn,
Serialize,
Deserialize,
};
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct DataToSend {
pub action_type: String,
pub content: String,
pub character: String,
pub choices: Vec<String>,
}
// Async function that runs the api server in the background.
// Waits for the client to load it, at which point it sends a 1 over
// tx to allow the program executor to move onto the next bit of code
pub async fn api_process
(
happening_queue: Arc<Mutex<VecDeque<DataToSend>>>,
characters: Arc<Mutex<HashMap::<String,character::Character>>>,
tx: Sender<(usize, String)>,
)
{
// This data must be passed through to the api route in order to be used
let happening_queue_filter = warp::any().map(move || Arc::clone(&happening_queue));
let characters_filter = warp::any().map(move || Arc::clone(&characters));
let tx_filter1 = warp::any().map(move || tx.clone());
let tx_filter2 = tx_filter1.clone();
info!("Running server");
// The server route is loaded at address:port/happening
let main = warp::path("happening")
.and(warp::get())
.and(happening_queue_filter)
// Perform this code on a GET request
.map(|queue: Arc<Mutex<VecDeque<DataToSend>>>|
{
//debug!("GET: {state:?}");
let mut queue = queue.lock().unwrap_or_exit("Queue Mutex was poisoned", 2);
let reply = queue.pop_front().unwrap_or_default();
drop(queue);
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
}).boxed();
let characters = warp::path("character")
.and(warp::get())
.and(warp::path::param::<String>())
.and(characters_filter)
.map(|name: String, characters: Arc<Mutex<HashMap<String, character::Character>>>|
{
let reply =
{
let characters = match characters.lock()
{
Ok(data) => data,
Err(poisoned) =>
{
warn!("Character Mutex is poisoned");
poisoned.into_inner()
},
};
characters.get(&name).cloned()
};
let Some(reply) = reply else
{
warn!("Client requested character that does not exist");
return warp::reply::json(&json!({"reply": "invalid character"}));
};
debug!("GET: name: {name}");
warp::reply::json(&reply)
}).boxed();
let choice = warp::path("choice")
.and(warp::post())
.and(warp::body::json())
.and(tx_filter1)
.map(|index: usize, tx_handle: Sender<(usize,String)>| {
debug!("Choice: {index}");
let _ = tx_handle.send((index,String::new()));
let reply = "ack";
warp::reply::json(&reply)
}).boxed();
let input = warp::path("input")
.and(warp::post())
.and(warp::body::json())
.and(tx_filter2)
.map(|input: String, tx_handle: Sender<(usize, String)>|
{
let _ = tx_handle.send((0,input));
let reply = "ack";
warp::reply::json(&reply)
}).boxed();
let routes = main.or(characters).or(choice).or(input);
// Start the server
warp::serve(routes)
.run(([127, 0, 0, 1],config::API_PORT))
.await;
}
// On fail, quit safely
// If successful, return nothing
pub fn modify_data // TODO rename
(
happening_queue: &Arc<Mutex<VecDeque<DataToSend>>>,
action_type: String,
content: String,
character: String,
choices: Vec<String>,
)
{
let mut queue = happening_queue.lock().unwrap_or_exit("Data to send Mutex was poisoned",2);
let new_data = DataToSend {
action_type,
content,
character,
choices,
};
queue.push_back(new_data);
drop(queue);
}