Skip to content

Commit

Permalink
Implement api struct
Browse files Browse the repository at this point in the history
  • Loading branch information
LostQuasar committed Jun 13, 2024
1 parent 9179d8c commit 7233ec9
Showing 1 changed file with 109 additions and 87 deletions.
196 changes: 109 additions & 87 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,81 +5,17 @@
pub mod data_type;

use data_type::data_type::*;
use reqwest::Client;
use reqwest::header;
use std::{error::Error, fmt::Debug};
use strum_macros::EnumString;

/// Sends a request to the openshock server to control the shocker device
pub async fn post_control(
client: &Client,
api_url: &str,
id: String,
control_type: ControlType,
) -> Result<String, Box<dyn Error>> {
let control_request = serde_json::to_string(&ControlRequest {
shocks: vec![Shock {
id: id,
control_type: control_type,
intensity: 1,
duration: 300,
exclusive: true,
}],
custom_name: "rusty".to_string(),
})?;

let resp = client
.post(format!("{api_url}/2/shockers/control"))
.body(control_request)
.send()
.await?;
let base_response: BaseResponse<String> = serde_json::from_str(resp.text().await?.as_str())?;
Ok(base_response.message.unwrap())
pub struct OpenShockAPI {
base_url: String,
client: reqwest::Client,
default_key: String,
}

///Gets a list of shockers including the device they are paired to
pub async fn get_shockers(
client: &Client,
api_url: &str,
source: ShockerSource,
) -> Result<Vec<ListShockersResponse>, Box<dyn Error>> {
let resp = client
.get(format!("{}/1/shockers/{:?}", api_url, source))
.send()
.await;
let list_shockers_response: BaseResponse<Vec<ListShockersResponse>> =
serde_json::from_str(resp?.text().await?.as_str())?;
//I dont like this
Ok(list_shockers_response.data.unwrap())
}

pub async fn get_user_info(client: &Client, api_url: &str) -> Result<SelfResponse, Box<dyn Error>> {
let resp = client.get(format!("{}/1/users/self", api_url)).send().await;
let self_base_response: BaseResponse<SelfResponse> =
serde_json::from_str(resp?.text().await?.as_str())?;
//I dont like this
Ok(self_base_response.data.unwrap())
}

#[derive(EnumString, Debug)]
pub enum ShockerSource {
Own,
Shared,
}

#[cfg(test)]
mod tests {
use std::hash::{DefaultHasher, Hash, Hasher};

use super::*;
use dotenv::dotenv;
use reqwest::header;

fn setup() -> (Client, String) {
dotenv().ok();
let openshock_token = dotenv::var("OPENSHOCK_TOKEN").expect("missing OPENSHOCK_TOKEN");
assert_ne!(openshock_token, "");
let api_url = "https://api.shocklink.net";

impl OpenShockAPI {
pub fn new(base_url: Option<String>, default_key: String) -> Self {
let mut headers = header::HeaderMap::new();
headers.insert(
"Content-type",
Expand All @@ -89,17 +25,100 @@ mod tests {
"accept",
header::HeaderValue::from_static("application/json"),
);
headers.insert(
"OpenShockToken",
header::HeaderValue::from_str(&openshock_token).unwrap(),
);
let client = reqwest::Client::builder()
.default_headers(headers)
.build()
.unwrap();
(client, api_url.to_string())
let base_url = base_url.unwrap_or("https://api.shocklink.net".to_string());
OpenShockAPI {
base_url,
client,
default_key,
}
}

pub async fn get_user_info(
&self,
api_key: Option<String>,
) -> Result<SelfResponse, Box<dyn Error>> {
let resp = self
.client
.get(format!("{}/1/users/self", self.base_url))
.header(
"OpenShockToken",
api_key.unwrap_or(self.default_key.clone()),
)
.send()
.await?;
let self_base_response: BaseResponse<SelfResponse> =
serde_json::from_str(resp.text().await?.as_str())?;
Ok(self_base_response.data.unwrap())
}

pub async fn get_shockers(
&self,
source: ShockerSource,
api_key: Option<String>,
) -> Result<Vec<ListShockersResponse>, Box<dyn Error>> {
let resp = self
.client
.get(format!("{}/1/shockers/{:?}", self.base_url, source))
.header(
"OpenShockToken",
api_key.unwrap_or(self.default_key.clone()),
)
.send()
.await?;
let list_shockers_response: BaseResponse<Vec<ListShockersResponse>> =
serde_json::from_str(resp.text().await?.as_str())?;
Ok(list_shockers_response.data.unwrap())
}

pub async fn post_control(
&self,
id: String,
control_type: ControlType,
api_key: Option<String>,
) -> Result<String, Box<dyn Error>> {
let control_request = serde_json::to_string(&ControlRequest {
shocks: vec![Shock {
id: id,
control_type: control_type,
intensity: 1,
duration: 300,
exclusive: true,
}],
custom_name: "rusty".to_string(),
})?;

let resp = self
.client
.post(format!("{}/2/shockers/control", self.base_url))
.body(control_request)
.header(
"OpenShockToken",
api_key.unwrap_or(self.default_key.clone()),
)
.send()
.await?;
let base_response: BaseResponse<String> =
serde_json::from_str(resp.text().await?.as_str())?;
Ok(base_response.message.unwrap())
}
}

#[derive(EnumString, Debug)]
pub enum ShockerSource {
Own,
Shared,
}

#[cfg(test)]
mod tests {
use super::*;
use dotenv::dotenv;
use std::hash::{DefaultHasher, Hash, Hasher};

fn calculate_hash<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
Expand All @@ -109,10 +128,14 @@ mod tests {
#[tokio::test]
async fn get_shockers_test() {
dotenv().ok();
let openshock_token = dotenv::var("OPENSHOCK_TOKEN").expect("missing OPENSHOCK_TOKEN");
let shocker_test_id = dotenv::var("SHOCKER_TEST_ID").expect("missing SHOCKER_TEST_ID");
assert_ne!(openshock_token, "");
assert_ne!(shocker_test_id, "");
let (client, api_url) = setup();
let result = get_shockers(&client, api_url.as_str(), ShockerSource::Own);

let openshock_api = OpenShockAPI::new(None, openshock_token);

let result = openshock_api.get_shockers(ShockerSource::Own, None);
assert_eq!(
calculate_hash(&result.await.unwrap()[0].shockers[0].id),
calculate_hash(&shocker_test_id)
Expand All @@ -122,16 +145,13 @@ mod tests {
#[tokio::test]
async fn post_control_test() {
dotenv().ok();
let openshock_token = dotenv::var("OPENSHOCK_TOKEN").expect("missing OPENSHOCK_TOKEN");
let shocker_test_id = dotenv::var("SHOCKER_TEST_ID").expect("missing SHOCKER_TEST_ID");
assert_ne!(openshock_token, "");
assert_ne!(shocker_test_id, "");

let (client, api_url) = setup();
let result = post_control(
&client,
api_url.as_str(),
shocker_test_id,
ControlType::Sound,
);
let openshock_api = OpenShockAPI::new(None, openshock_token);
let result = openshock_api.post_control(shocker_test_id, ControlType::Sound, None);
assert_eq!(
&result.await.unwrap(),
&"Successfully sent control messages"
Expand All @@ -142,10 +162,12 @@ mod tests {
async fn get_user_info_test() {
dotenv().ok();
let user_test_id = dotenv::var("USER_TEST_ID").expect("missing USER_TEST_ID");
let openshock_token = dotenv::var("OPENSHOCK_TOKEN").expect("missing OPENSHOCK_TOKEN");
assert_ne!(user_test_id, "");
assert_ne!(openshock_token, "");

let (client, api_url) = setup();
let result = get_user_info(&client, api_url.as_str());
let openshock_api = OpenShockAPI::new(None, openshock_token);
let result = openshock_api.get_user_info(None);
assert_eq!(
calculate_hash(&result.await.unwrap().id),
calculate_hash(&user_test_id)
Expand Down

0 comments on commit 7233ec9

Please sign in to comment.