lesspub_query/
lib.rs

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}