quoter/src/data.rs

133 lines
4.3 KiB
Rust
Raw Normal View History

2023-10-12 21:46:55 +00:00
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION, CONTENT_TYPE};
2023-10-16 13:22:54 +00:00
use reqwest::Client as HTTPClient;
2023-10-13 21:37:14 +00:00
use serde_json::json;
2023-10-03 13:29:31 +00:00
use std::collections::HashMap;
2023-10-03 08:30:59 +00:00
use std::env;
2023-10-16 13:22:54 +00:00
use std::error::Error;
2023-10-03 08:30:59 +00:00
pub async fn get_auth_id(token: &str) -> Result<i32, Box<dyn Error>> {
2023-10-06 10:50:20 +00:00
let auth_api_base = env::var("AUTH_URL")?;
2023-10-12 21:46:55 +00:00
let (query_name, query_type) = match auth_api_base.contains("auth.discours.io") {
2023-10-16 13:22:54 +00:00
true => ("session", "query"), // authorizer
2023-10-12 21:46:55 +00:00
_ => ("getSession", "mutation"), // v2
2023-10-03 08:30:59 +00:00
};
2023-10-12 21:46:55 +00:00
let operation = "GetUserId";
let mut headers = HeaderMap::new();
headers.insert(AUTHORIZATION, HeaderValue::from_str(token)?);
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
2023-10-11 17:08:25 +00:00
2023-10-12 21:46:55 +00:00
let gql = json!({
"query": format!("{} {} {{ {} {{ user {{ id }} }} }}", query_type, operation, query_name),
"operationName": operation,
"variables": HashMap::<String, String>::new()
});
2023-10-16 13:22:54 +00:00
let client = HTTPClient::new();
let response = client
.post(&auth_api_base)
2023-10-12 21:46:55 +00:00
.headers(headers)
.json(&gql)
2023-10-03 08:30:59 +00:00
.send()
.await?;
2023-10-12 21:46:55 +00:00
if response.status().is_success() {
let r: HashMap<String, serde_json::Value> = response.json().await?;
2023-10-16 13:22:54 +00:00
let user_id = r
.get("data")
2023-10-12 21:46:55 +00:00
.and_then(|data| data.get(query_name))
.and_then(|query| query.get("user"))
.and_then(|user| user.get("id"))
.and_then(|id| id.as_i64());
match user_id {
Some(id) => {
println!("User ID retrieved: {}", id);
Ok(id as i32)
2023-10-16 13:22:54 +00:00
}
2023-10-12 21:46:55 +00:00
None => {
println!("No user ID found in the response");
2023-10-16 13:22:54 +00:00
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
"No user ID found in the response",
)))
2023-10-12 21:46:55 +00:00
}
}
} else {
println!("Request failed with status: {}", response.status());
2023-10-16 13:22:54 +00:00
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
format!("Request failed with status: {}", response.status()),
)))
2023-10-12 21:46:55 +00:00
}
2023-10-03 08:30:59 +00:00
}
2023-10-03 13:29:31 +00:00
async fn get_shout_followers(shout_id: &str) -> Result<Vec<i32>, Box<dyn Error>> {
let api_base = env::var("API_BASE")?;
2023-10-12 21:46:55 +00:00
let query = r#"query ShoutFollowers($shout: Int!) {
shoutFollowers(shout: $shout) {
follower {
2023-10-03 13:29:31 +00:00
id
2023-10-12 21:46:55 +00:00
}
}
}
"#;
let shout_id = shout_id.parse::<i32>()?;
let variables = json!({
"shout": shout_id
});
let body = json!({
"query": query,
2023-10-11 20:03:12 +00:00
"operationName": "ShoutFollowers",
2023-10-12 21:46:55 +00:00
"variables": variables
});
2023-10-03 13:29:31 +00:00
let client = reqwest::Client::new();
2023-10-16 13:22:54 +00:00
let response = client.post(&api_base).json(&body).send().await?;
2023-10-03 08:30:59 +00:00
2023-10-12 21:46:55 +00:00
if response.status().is_success() {
let response_body: serde_json::Value = response.json().await?;
let ids: Vec<i32> = response_body["data"]["shoutFollowers"]
.as_array()
.ok_or("Failed to parse follower array")?
.iter()
.filter_map(|f| f["follower"]["id"].as_i64().map(|id| id as i32))
.collect();
2023-10-03 13:29:31 +00:00
2023-10-12 21:46:55 +00:00
Ok(ids)
} else {
println!("Request failed with status: {}", response.status());
2023-10-16 13:22:54 +00:00
Err(Box::new(std::io::Error::new(
std::io::ErrorKind::Other,
format!("Request failed with status: {}", response.status()),
)))
2023-10-12 21:46:55 +00:00
}
2023-10-03 13:29:31 +00:00
}
2023-10-16 13:22:54 +00:00
pub async fn is_fitting(
listener_id: i32,
kind: String,
payload: HashMap<String, String>,
) -> Result<bool, &'static str> {
2023-10-16 14:03:57 +00:00
match &kind[0..9] {
"new_react" => {
// payload is Reaction, kind is new_reaction<reaction_kind>
2023-10-16 13:22:54 +00:00
let shout_id = payload.get("shout").unwrap();
let recipients = get_shout_followers(shout_id).await.unwrap();
2023-10-03 13:29:31 +00:00
2023-10-16 13:22:54 +00:00
Ok(recipients.contains(&listener_id))
}
"new_shout" => {
2023-10-16 14:03:57 +00:00
// payload is Shout, kind is "new_shout"
2023-10-16 13:22:54 +00:00
// TODO: check all community subscribers if no then
// check all topics subscribers if no then
// check all authors subscribers
Ok(true)
}
_ => {
eprintln!("unknown payload kind");
2023-10-03 13:33:32 +00:00
eprintln!("{:?}", payload);
Ok(false)
2023-10-16 13:22:54 +00:00
}
2023-10-03 13:29:31 +00:00
}
2023-10-16 13:22:54 +00:00
}