stack_cli/
lib.rs

1use flate2::read::GzDecoder;
2use reqwest::blocking::get;
3use serde::{Deserialize, Serialize};
4use std::{
5    env::{self, args},
6    error::Error,
7    io::{self, Read, Write},
8};
9
10#[derive(Debug)]
11pub struct Question {
12    pub name: String,
13    pub id: String,
14}
15
16#[derive(Serialize, Deserialize, Debug)]
17pub struct Answer {
18    pub body_markdown: String,
19    pub is_accepted: bool,
20}
21
22#[derive(Serialize, Deserialize, Debug)]
23pub struct JSONResponse {
24    items: Vec<Answer>,
25}
26
27pub fn construct_google_url() -> String {
28    let mut args: Vec<String> = args().collect();
29    args.remove(0);
30    let query_string = args.join("+");
31
32    format!("https://www.google.com/search?q=site:stackoverflow.com {query_string}")
33}
34
35pub fn prompt(questions: Vec<Question>) -> Result<Vec<Answer>, Box<dyn Error>> {
36    for (i, question) in questions.iter().enumerate() {
37        println!("{}. {}", i, question.name);
38    }
39    print!("> ");
40    io::stdout().flush()?;
41
42    let mut num = String::new();
43    io::stdin().read_line(&mut num)?;
44    let num: i32 = num.trim().parse()?;
45    if num as usize >= questions.len() {
46        return Err("Number too high".into());
47    }
48
49    let question = &questions[num as usize];
50    let answers = gather_answers(question)?;
51
52    Ok(answers)
53}
54
55pub fn gather_answers(question: &Question) -> Result<Vec<Answer>, Box<dyn Error>> {
56    let access_token = env::var("STACKOVERFLOW_API_KEY")?;
57    let key = env::var("STACKOVERFLOW_KEY")?;
58    let mut contents = Vec::new();
59    get(
60        format!("https://api.stackexchange.com/2.3/questions/{}/answers?site=stackoverflow&sort=activity&filter=!nOedRLr0Wi&access_token={}&key={}",
61                question.id, access_token, key))?
62        .read_to_end(&mut contents)?;
63
64    let mut decoded = String::new();
65    GzDecoder::new(&contents[..]).read_to_string(&mut decoded)?;
66    let answers: Vec<Answer> = serde_json::from_str::<JSONResponse>(&decoded)?.items;
67
68    Ok(answers)
69}