1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate hyper;
pub mod models;
use std::io::Read;
use hyper::Client;
use std::fmt::Display;
use hyper::status::StatusCode;
use models::*;
#[derive(Debug)]
pub enum Error {
Http(hyper::Error),
Json(serde_json::Error),
Forbidden(&'static str),
Message(String),
}
impl From<hyper::Error> for Error {
fn from(e: hyper::Error) -> Error {
Error::Http(e)
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::Json(e)
}
}
#[derive(Debug)]
pub struct Dota2Api<'a> {
http_client: Client,
pub key: &'a str,
}
impl<'a> Dota2Api<'a> {
pub fn new(key: &'a str) -> Dota2Api<'a> {
Dota2Api {
http_client: Client::new(),
key: key,
}
}
pub fn get_match_history(&mut self, options: Option<&MatchHistoryOptions>) -> Result<MatchHistory, Error> {
let mut url = String::from("http://api.steampowered.com/IDOTA2Match_570/GetMatchHistory/V001/?");
Dota2Api::add_param(&mut url, "key", self.key);
if let Some(opt) = options {
Dota2Api::add_optional_param(&mut url, "hero_id", opt.hero_id);
if let Some(skill) = opt.skill {
Dota2Api::add_param::<i32>(&mut url, "skill", i32::from(skill));
}
Dota2Api::add_optional_param(&mut url, "date_min", opt.date_min);
Dota2Api::add_optional_param(&mut url, "date_max", opt.date_max);
Dota2Api::add_optional_param(&mut url, "account_id", opt.account_id);
Dota2Api::add_optional_param(&mut url, "league_id", opt.league_id);
Dota2Api::add_optional_param(&mut url, "start_at_match_id", opt.start_at_match_id);
Dota2Api::add_optional_param(&mut url, "matches_requested", opt.matches_requested);
}
let response = self.get(url.as_str())?;
let data_result: MatchHistoryResult = serde_json::from_str(response.as_str())?;
let data = data_result.result;
Ok(data)
}
pub fn get_match_details(&mut self, match_id: u64) -> Result<MatchDetails, Error> {
let mut url = String::from("http://api.steampowered.com/IDOTA2Match_570/GetMatchDetails/V001/?");
Dota2Api::add_param(&mut url, "key", self.key);
Dota2Api::add_param(&mut url, "match_id", match_id);
let response = self.get(url.as_str())?;
let data_result: MatchDetailsResult = match serde_json::from_str(response.as_str()) {
Err(e) => {
match serde_json::from_str::<ApiErrorResult>(response.as_str()) {
Err(_) => return Err(Error::Json(e)),
Ok(er) => return Err(Error::Message(er.result.error)),
};
}
Ok(r) => r,
};
let data = data_result.result;
Ok(data)
}
pub fn get_top_live_games(&mut self) -> Result<Vec<TopLiveGame>, Error> {
let mut url = String::from("http://api.steampowered.com/IDOTA2Match_570/GetTopLiveGame/V001/?partner=&");
Dota2Api::add_param(&mut url, "key", self.key);
let response = self.get(url.as_str())?;
let data_result: TopLiveGameList = serde_json::from_str(response.as_str())?;
let data: Vec<TopLiveGame> = data_result.game_list;
Ok(data)
}
fn get(&mut self, url: &str) -> Result<String, Error> {
let mut response = self.http_client.get(url).send()?;
let mut tmp = String::new();
if response.status == StatusCode::Forbidden {
return Err(Error::Forbidden("Access is denied. Retrying will not help. Please check your API key."));
}
let _ = response.read_to_string(&mut tmp);
Ok(tmp)
}
fn add_param<T: Display>(url: &mut String, param_name: &str, param_value: T) {
url.push_str(format!("{}={}&", param_name, param_value).as_str());
}
fn add_optional_param<T: Display>(url: &mut String, param_name: &str, param_value: Option<T>) {
if let Some(val) = param_value {
url.push_str(format!("{}={}&", param_name, val).as_str());
}
}
}