Adding code for getting contact #12

Merged
phoenix merged 3 commits from get_contact into v0.3.0 2026-06-25 21:40:03 -04:00
5 changed files with 197 additions and 121 deletions
+116
View File
@@ -0,0 +1,116 @@
pub struct Auth {
pub app: crate::app::App,
}
impl Auth {
pub async fn get_token(&self) -> Result<textsender_models::token::Login, std::io::Error> {
let client = reqwest::Client::new();
let endpoint = String::from("api/v1/service/login");
let api_url = format!("{}/{endpoint}", self.app.auth_url);
println!("Url: {api_url:?}");
let payload = serde_json::json!({
"username": &self.app.service_username,
"passphrase": &self.app.service_passphrase,
});
println!("Payload: {payload:?}");
match client.post(api_url).json(&payload).send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => {
println!("Response: {response:?}");
match response.text().await {
Ok(val) => match parse_token_response(&val).await {
Ok(login_result) => Ok(login_result),
Err(err) => Err(err),
},
Err(err) => Err(std::io::Error::other(err)),
}
}
_ => Err(std::io::Error::other("Error getting token")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
pub async fn get_refresh_token(
&self,
login_result: &textsender_models::token::Login,
) -> Result<textsender_models::token::Login, std::io::Error> {
let client = reqwest::Client::new();
let endpoint = String::from("api/v1/token/refresh");
let api_url = format!("{}/{endpoint}", self.app.auth_url);
println!("Url: {api_url:?}");
let payload = serde_json::json!({
"access_token": login_result.access_token
});
match client.post(api_url).json(&payload).send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => {
println!("Response: {response:?}");
match response.text().await {
Ok(val) => match parse_token_response(&val).await {
Ok(login_result) => Ok(login_result),
Err(err) => Err(err),
},
Err(err) => Err(std::io::Error::other(err)),
}
}
_ => Err(std::io::Error::other("Error getting token")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
}
async fn parse_token_response(
response: &str,
) -> Result<textsender_models::token::LoginResult, std::io::Error> {
match serde_json::from_str::<serde_json::Value>(response) {
Ok(j) => {
println!("Good");
let message = &j["message"];
let data = &j["data"];
println!("Message: {message:?}");
println!("Data: {data:?}");
match j.get("data") {
Some(serde_json::Value::Array(lrs)) => {
if lrs.is_empty() {
Err(std::io::Error::other("Error response is empty"))
} else {
let lr = lrs[0].clone();
let ll: textsender_models::token::LoginResult =
match serde_json::from_value(lr) {
Ok(lr) => lr,
Err(err) => {
return Err(std::io::Error::other(err.to_string()));
}
};
Ok(ll)
}
}
_ => Err(std::io::Error::other("Error parsing response")),
}
}
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
pub async fn has_token_expired(token: &textsender_models::token::LoginResult) -> bool {
let now = time::OffsetDateTime::now_utc();
let expire = match time::OffsetDateTime::from_unix_timestamp(token.expires_in) {
Ok(res) => res,
Err(err) => {
eprintln!("Error: {err:?}");
return false;
}
};
now > expire
}
+64
View File
@@ -0,0 +1,64 @@
pub struct Contact {
pub app: crate::app::App,
pub token: textsender_models::token::LoginResult,
}
impl Contact {
pub async fn get(
&self,
contact_id: &uuid::Uuid,
) -> Result<Vec<textsender_models::contact::Contact>, std::io::Error> {
let client = reqwest::Client::new();
let endpoint = format!("api/v1/contact?id={contact_id}");
let api_url = format!("{}/{endpoint}", self.app.api_url);
println!("Url: {api_url:?}");
let (key, header) = super::auth_header(&self.token.access_token);
match client.get(api_url).header(key, header).send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => match response.text().await {
Ok(val) => match parse_response(&val).await {
Ok(login_result) => Ok(login_result),
Err(err) => Err(err),
},
Err(err) => Err(std::io::Error::other(err)),
},
_ => Err(std::io::Error::other("Error getting token")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
}
async fn parse_response(
response: &str,
) -> Result<Vec<textsender_models::contact::Contact>, std::io::Error> {
match serde_json::from_str::<serde_json::Value>(response) {
Ok(j) => match j.get("data") {
Some(serde_json::Value::Array(lrs)) => {
if lrs.is_empty() {
Err(std::io::Error::other("Error response is empty"))
} else {
let mut events: Vec<textsender_models::contact::Contact> = Vec::new();
for event in lrs.iter() {
let ll: textsender_models::contact::Contact =
match serde_json::from_value(event.clone()) {
Ok(lr) => lr,
Err(err) => {
return Err(std::io::Error::other(err.to_string()));
}
};
events.push(ll);
}
Ok(events)
}
}
_ => Err(std::io::Error::other("Error parsing response")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
+15 -2
View File
@@ -51,9 +51,22 @@ impl Service {
} }
}; };
let contacts = super::contact::Contact {
app: self.app.clone(),
token: self.token.clone(),
};
let events = events.unwrap_or_default(); let events = events.unwrap_or_default();
for event in events { for event in events {
println!("Event: {event:?}"); println!("Event: {event:?}");
let contact = &match contacts.get(&event.contact_id).await {
Ok(contact) => contact,
Err(err) => {
eprintln!("Error: {err:?}");
continue;
}
}[0];
println!("Contact Id: {:?}", contact.id);
} }
todo!( todo!(
@@ -69,8 +82,8 @@ impl Service {
2. If there is an item, get the data - Done 2. If there is an item, get the data - Done
3. Evaluate if it is schedulable - Done 3. Evaluate if it is schedulable - Done
4. Get the events and iterate each one - Done 4. Get the events and iterate each one - Done
5. starting with the message 5. Starting with the message
6. Get the contact 6. Get the contact - Done
7. Send the message 7. Send the message
8. Record the message event response 8. Record the message event response
9. Add to scheduler 9. Add to scheduler
View File
+2 -119
View File
@@ -1,126 +1,9 @@
pub mod auth;
pub mod contact;
pub mod core; pub mod core;
pub mod event; pub mod event;
pub mod queue; pub mod queue;
pub mod auth {
pub struct Auth {
pub app: crate::app::App,
}
impl Auth {
pub async fn get_token(&self) -> Result<textsender_models::token::Login, std::io::Error> {
let client = reqwest::Client::new();
let endpoint = String::from("api/v1/service/login");
let api_url = format!("{}/{endpoint}", self.app.auth_url);
println!("Url: {api_url:?}");
let payload = serde_json::json!({
"username": &self.app.service_username,
"passphrase": &self.app.service_passphrase,
});
println!("Payload: {payload:?}");
match client.post(api_url).json(&payload).send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => {
println!("Response: {response:?}");
match response.text().await {
Ok(val) => match parse_token_response(&val).await {
Ok(login_result) => Ok(login_result),
Err(err) => Err(err),
},
Err(err) => Err(std::io::Error::other(err)),
}
}
_ => Err(std::io::Error::other("Error getting token")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
pub async fn get_refresh_token(
&self,
login_result: &textsender_models::token::Login,
) -> Result<textsender_models::token::Login, std::io::Error> {
let client = reqwest::Client::new();
let endpoint = String::from("api/v1/token/refresh");
let api_url = format!("{}/{endpoint}", self.app.auth_url);
println!("Url: {api_url:?}");
let payload = serde_json::json!({
"access_token": login_result.access_token
});
match client.post(api_url).json(&payload).send().await {
Ok(response) => match response.status() {
reqwest::StatusCode::OK => {
println!("Response: {response:?}");
match response.text().await {
Ok(val) => match parse_token_response(&val).await {
Ok(login_result) => Ok(login_result),
Err(err) => Err(err),
},
Err(err) => Err(std::io::Error::other(err)),
}
}
_ => Err(std::io::Error::other("Error getting token")),
},
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
}
async fn parse_token_response(
response: &str,
) -> Result<textsender_models::token::LoginResult, std::io::Error> {
match serde_json::from_str::<serde_json::Value>(response) {
Ok(j) => {
println!("Good");
let message = &j["message"];
let data = &j["data"];
println!("Message: {message:?}");
println!("Data: {data:?}");
match j.get("data") {
Some(serde_json::Value::Array(lrs)) => {
if lrs.is_empty() {
Err(std::io::Error::other("Error response is empty"))
} else {
let lr = lrs[0].clone();
let ll: textsender_models::token::LoginResult =
match serde_json::from_value(lr) {
Ok(lr) => lr,
Err(err) => {
return Err(std::io::Error::other(err.to_string()));
}
};
Ok(ll)
}
}
_ => Err(std::io::Error::other("Error parsing response")),
}
}
Err(err) => Err(std::io::Error::other(err.to_string())),
}
}
pub async fn has_token_expired(token: &textsender_models::token::LoginResult) -> bool {
let now = time::OffsetDateTime::now_utc();
let expire = match time::OffsetDateTime::from_unix_timestamp(token.expires_in) {
Ok(res) => res,
Err(err) => {
eprintln!("Error: {err:?}");
return false;
}
};
now > expire
}
}
pub fn auth_header( pub fn auth_header(
access_token: &str, access_token: &str,
) -> (reqwest::header::HeaderName, reqwest::header::HeaderValue) { ) -> (reqwest::header::HeaderName, reqwest::header::HeaderValue) {