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}