use crate::{
error::{APIError, Result},
API_VERSION,
};
use reqwest::{Client, Response};
use serde_json::{from_value, Map, Value};
use std::collections::HashMap;
pub type Params = HashMap<String, String>;
#[derive(Debug)]
pub struct APIClient {
client: Client,
token: String,
}
impl APIClient {
pub fn new(token: impl Into<String>) -> APIClient {
APIClient {
client: Client::new(),
token: token.into(),
}
}
pub fn call_method(&self, method_name: &str, mut params: Params) -> Result<Value> {
params.insert("v".into(), API_VERSION.into());
params.insert("access_token".into(), self.token.clone());
let response_result: Result<Response> = self
.client
.get(&("https://api.vk.com/method/".to_owned() + method_name))
.query(¶ms)
.send()
.map_err(|e| e.into());
let mut response = response_result?;
let value_result: Result<Value> = response.json().map_err(|e| e.into());
let value = value_result?;
let api_response_result: Result<&Map<String, Value>> = value
.as_object()
.ok_or_else(|| "API response is not an object!".into());
let api_response = api_response_result?;
match api_response.get("response") {
Some(ok) => Ok(ok.clone()),
None => match api_response.get("error") {
Some(err) => Err(from_value::<APIError>(err.clone())?.into()),
None => Err("The API responded with neither a response nor an error!".into()),
},
}
}
}