use anyhow::anyhow;
use cynic::{QueryBuilder, http::ReqwestExt};
use reqwest::Client;
use std::error::Error;
use lesspub_schema::{
Post, PostArguments, PostQuery, SelectorInput, Sequence, SequenceListInfo, SequencesListQuery,
SinglePostInput, SingleSequenceArguments, SingleSequenceInput, SingleSequenceQuery,
};
const LW_GRAPHQL_URL: &str = "https://www.lesswrong.com/graphql";
const EA_GRAPHQL_URL: &str = "https://forum.effectivealtruism.org/graphql";
pub async fn get_ea_post(client: &Client, id: &str) -> Result<Post, Box<dyn Error>> {
let operation = PostQuery::build(PostArguments {
input: Some(SinglePostInput {
selector: Some(SelectorInput {
_id: Some(id.to_string()),
documentId: None,
}),
allowNull: None,
}),
});
let response = client.post(EA_GRAPHQL_URL).run_graphql(operation).await?;
Ok(response
.data
.ok_or(match response.errors {
Some(errors) => {
anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
String::from("GraphQL error encountered when fetching ea post"),
))
}
None => anyhow!("no ea post response found"),
})?
.post
.ok_or(anyhow!("no ea post output found"))?
.result
.ok_or(anyhow!("no ea post found"))?)
}
pub async fn get_lw_post(client: &Client, id: &str) -> Result<Post, Box<dyn Error>> {
let operation = PostQuery::build(PostArguments {
input: Some(SinglePostInput {
selector: Some(SelectorInput {
_id: Some(id.to_string()),
documentId: None,
}),
allowNull: None,
}),
});
let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
Ok(response
.data
.ok_or(match response.errors {
Some(errors) => anyhow::Error::msg(
errors
.first()
.map(|e| e.message.clone())
.unwrap_or(String::from("GraphQL error encountered when fetching post")),
),
None => anyhow!("no post response found"),
})?
.post
.ok_or(anyhow!("no post output found"))?
.result
.ok_or(anyhow!("no post found"))?)
}
pub async fn get_lw_sequences(client: &Client) -> Result<Vec<SequenceListInfo>, Box<dyn Error>> {
let operation = SequencesListQuery::build(());
let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
Ok(response
.data
.ok_or(match response.errors {
Some(errors) => {
anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
String::from("GraphQL error encountered when fetching sequences list"),
))
}
None => anyhow!("no sequences list response found"),
})?
.sequences
.ok_or(anyhow!("no sequences list output found"))?
.results
.ok_or(anyhow!("no sequences list found"))?
.into_iter()
.filter_map(|s| {
s.map(|sequence| {
if sequence._id.is_some() {
Some(sequence)
} else {
None
}
})
.unwrap()
})
.collect())
}
pub async fn get_lw_sequence(client: &Client, id: &str) -> Result<Sequence, Box<dyn Error>> {
let operation = SingleSequenceQuery::build(SingleSequenceArguments {
input: Some(SingleSequenceInput {
selector: Some(SelectorInput {
_id: Some(id.to_string()),
documentId: None,
}),
allowNull: None,
}),
});
let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
if let Some(errors) = response.errors.clone() {
for error in errors {
log::error!("{error:?}");
}
}
Ok(response
.data
.ok_or(match response.errors {
Some(errors) => {
anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
String::from("GraphQL error encountered when fetching lw sequence"),
))
}
None => anyhow!("no lw sequence response found"),
})?
.sequence
.ok_or(anyhow!("no lw sequence output found"))?
.result
.ok_or(anyhow!("no lw sequence found"))?)
}