1use anyhow::anyhow;
2use cynic::{QueryBuilder, http::ReqwestExt};
3use reqwest::Client;
4use std::error::Error;
5
6use lesspub_schema::{
7 Post, PostArguments, PostQuery, SelectorInput, Sequence, SequenceListInfo, SequencesListQuery,
8 SinglePostInput, SingleSequenceArguments, SingleSequenceInput, SingleSequenceQuery,
9};
10
11const LW_GRAPHQL_URL: &str = "https://www.lesswrong.com/graphql";
12const EA_GRAPHQL_URL: &str = "https://forum.effectivealtruism.org/graphql";
13
14pub async fn get_ea_post(client: &Client, id: &str) -> Result<Post, Box<dyn Error>> {
15 let operation = PostQuery::build(PostArguments {
16 input: Some(SinglePostInput {
17 selector: Some(SelectorInput {
18 _id: Some(id.to_string()),
19 documentId: None,
20 }),
21 allowNull: None,
22 }),
23 });
24 let response = client.post(EA_GRAPHQL_URL).run_graphql(operation).await?;
25 Ok(response
26 .data
27 .ok_or(match response.errors {
28 Some(errors) => {
29 anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
30 String::from("GraphQL error encountered when fetching ea post"),
31 ))
32 }
33 None => anyhow!("no ea post response found"),
34 })?
35 .post
36 .ok_or(anyhow!("no ea post output found"))?
37 .result
38 .ok_or(anyhow!("no ea post found"))?)
39}
40
41pub async fn get_lw_post(client: &Client, id: &str) -> Result<Post, Box<dyn Error>> {
42 let operation = PostQuery::build(PostArguments {
43 input: Some(SinglePostInput {
44 selector: Some(SelectorInput {
45 _id: Some(id.to_string()),
46 documentId: None,
47 }),
48 allowNull: None,
49 }),
50 });
51 let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
52 Ok(response
53 .data
54 .ok_or(match response.errors {
55 Some(errors) => anyhow::Error::msg(
56 errors
57 .first()
58 .map(|e| e.message.clone())
59 .unwrap_or(String::from("GraphQL error encountered when fetching post")),
60 ),
61 None => anyhow!("no post response found"),
62 })?
63 .post
64 .ok_or(anyhow!("no post output found"))?
65 .result
66 .ok_or(anyhow!("no post found"))?)
67}
68
69pub async fn get_lw_sequences(client: &Client) -> Result<Vec<SequenceListInfo>, Box<dyn Error>> {
70 let operation = SequencesListQuery::build(());
71 let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
72 Ok(response
73 .data
74 .ok_or(match response.errors {
75 Some(errors) => {
76 anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
77 String::from("GraphQL error encountered when fetching sequences list"),
78 ))
79 }
80 None => anyhow!("no sequences list response found"),
81 })?
82 .sequences
83 .ok_or(anyhow!("no sequences list output found"))?
84 .results
85 .ok_or(anyhow!("no sequences list found"))?
86 .into_iter()
87 .filter_map(|s| {
88 s.map(|sequence| {
89 if sequence._id.is_some() {
90 Some(sequence)
91 } else {
92 None
93 }
94 })
95 .unwrap()
96 })
97 .collect())
98}
99
100pub async fn get_lw_sequence(client: &Client, id: &str) -> Result<Sequence, Box<dyn Error>> {
101 let operation = SingleSequenceQuery::build(SingleSequenceArguments {
102 input: Some(SingleSequenceInput {
103 selector: Some(SelectorInput {
104 _id: Some(id.to_string()),
105 documentId: None,
106 }),
107 allowNull: None,
108 }),
109 });
110 let response = client.post(LW_GRAPHQL_URL).run_graphql(operation).await?;
111 if let Some(errors) = response.errors.clone() {
112 for error in errors {
113 log::error!("{:?}", error);
114 }
115 }
116 Ok(response
117 .data
118 .ok_or(match response.errors {
119 Some(errors) => {
120 anyhow::Error::msg(errors.first().map(|e| e.message.clone()).unwrap_or(
121 String::from("GraphQL error encountered when fetching lw sequence"),
122 ))
123 }
124 None => anyhow!("no lw sequence response found"),
125 })?
126 .sequence
127 .ok_or(anyhow!("no lw sequence output found"))?
128 .result
129 .ok_or(anyhow!("no lw sequence found"))?)
130}