quoter/src/data.rs

107 lines
3.4 KiB
Rust
Raw Normal View History

2023-10-03 08:30:59 +00:00
use reqwest::Client as HTTPClient;
use serde_json::Value;
2023-10-03 13:29:31 +00:00
use std::collections::HashMap;
2023-10-03 08:30:59 +00:00
use std::error::Error;
use std::env;
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-11 18:19:23 +00:00
let (query_name, query_type) = match auth_api_base.contains("discours.io") {
true => ("getSession", "mutation"), // v2
_ => ("session", "query") // authorizer
2023-10-03 08:30:59 +00:00
};
2023-10-11 17:08:25 +00:00
let body = format!(r#"{{
2023-10-11 18:19:23 +00:00
"query": "{} GetSession {{ {} {{ user {{ id }} }} }}",
"operationName": "GetSession",
2023-10-11 17:08:25 +00:00
"variables": {{}}
2023-10-11 18:19:23 +00:00
}}"#, query_type, query_name);
2023-10-11 17:08:25 +00:00
2023-10-03 08:30:59 +00:00
let client = HTTPClient::new();
let response = client
2023-10-06 10:50:20 +00:00
.post(auth_api_base)
2023-10-03 08:30:59 +00:00
.bearer_auth(token) // NOTE: auth token is here
2023-10-11 17:08:25 +00:00
.body(body)
2023-10-03 08:30:59 +00:00
.send()
.await?;
let response_body: Value = response.json().await?;
2023-10-11 18:19:23 +00:00
let id = response_body["data"][query_name]["user"]["id"]
2023-10-03 08:30:59 +00:00
.as_i64()
.ok_or("Failed to get user id by token")? as i32;
Ok(id)
}
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")?;
let gql = format!(r#"
query {{
2023-10-03 13:33:32 +00:00
shoutFollowers(shout: {}) {{
2023-10-03 13:29:31 +00:00
follower {{
id
}}
}}
}}
"#, shout_id);
let client = reqwest::Client::new();
let response = client
.post(&api_base)
.body(gql)
.send()
2023-10-03 08:30:59 +00:00
.await?;
2023-10-03 13:29:31 +00:00
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();
Ok(ids)
}
pub async fn is_fitting(listener_id: i32, payload: HashMap<String, String>) -> Result<bool, &'static str> {
match payload.get("kind") {
Some(kind) => {
match kind.as_str() {
"new_follower" => {
// payload is AuthorFollower
Ok(payload.get("author").unwrap().to_string() == listener_id.to_string())
},
"new_reaction" => {
// payload is Reaction
let shout_id = payload.get("shout").unwrap();
let recipients = get_shout_followers(shout_id).await.unwrap();
Ok(recipients.contains(&listener_id))
},
"new_shout" => {
// payload is Shout
// TODO: check all community subscribers if no then
// check all topics subscribers if no then
// check all authors subscribers
Ok(true)
},
"new_message" => {
// payload is Chat
let members_str = payload.get("members").unwrap();
let members = serde_json::from_str::<Vec<String>>(members_str).unwrap();
Ok(members.contains(&listener_id.to_string()))
},
2023-10-03 13:33:32 +00:00
_ => {
eprintln!("unknown payload kind");
eprintln!("{:?}", payload);
Ok(false)
},
2023-10-03 13:29:31 +00:00
}
},
2023-10-03 13:33:32 +00:00
None => {
eprintln!("payload has no kind");
eprintln!("{:?}", payload);
Ok(false)
},
2023-10-03 13:29:31 +00:00
}
2023-10-03 08:30:59 +00:00
}