steam_webapi_rust_sdk/
lib.rs

1//! # Steam Web API Rust SDK
2//!
3//! `steam-webapi-rust-sdk` is a set of utility functions to access Steam Web API.
4//!
5//! In order to use this library make sure to set STEAM_WEB_API_KEY system environment variable.
6//!
7//! The library itself tries to minimize number of networks calls through the caching relevant
8//! responses to the 'steam-webapi-cache' folder.
9//!
10//! There is already prebuilt cache for all steam apps, in order to use it,
11//! simply clone [steam-webapi-cache](https://github.com/bohdaq/steam-webapi-cache)
12//! into the root folder of your project.
13
14use crate::idota2match_570::get_match_history::ResponseMatchHistory;
15use crate::isteam_apps::get_app_list::SteamApp;
16use crate::store_steampowered_com::appdetails::SteamAppDetails;
17
18pub mod util;
19pub mod isteam_apps;
20pub mod store_steampowered_com;
21pub mod idota2match_570;
22
23#[cfg(test)]
24mod tests;
25
26/// Retrieves details for the given app id from the local cache. It may return an error
27/// if requested resource is absent, malformed or not readable from local cache.
28///
29/// # Examples
30///
31/// ```
32/// let app_id = 570;
33/// let boxed_result = steam_webapi_rust_sdk::get_cached_app_details(app_id);
34/// if boxed_result.is_ok() {
35///     let app_details = boxed_result.unwrap();
36///     println!("result is ok for {} app id {}", app_details.name, app_details.app_id);
37///
38/// } else {
39///     let error_message = boxed_result.err().unwrap();
40///     println!("{} {}", error_message, app_id);
41///
42/// };
43/// ```
44pub fn get_cached_app_details(app_id: i64) -> Result<SteamAppDetails, String> {
45    let boxed_result = store_steampowered_com::appdetails::get_cached(app_id);
46    boxed_result
47}
48
49/// Retrieves details for the given app id. It will make an API call to Steam and cache response.
50/// It may return an error if API responded with error response. As an example it may be exceeding
51/// the limit of calls from one IP address or if the response contains not valid UTF-8 characters.
52/// Usually Steam API allows 200 requests from single IP address within 5 minutes range.
53///
54/// # Examples
55///
56/// ```
57/// let app_id = 570;
58/// let boxed_result = steam_webapi_rust_sdk::get_app_details(app_id);
59/// if boxed_result.is_ok() {
60///     let app_details = boxed_result.unwrap();
61///     println!("result is ok for {} app id {}", app_details.name, app_details.app_id);
62///
63/// } else {
64///     let error_message = boxed_result.err().unwrap();
65///     println!("{} {}", error_message, app_id);
66///
67///     let is_steam_unsuccessful_response = error_message == "steampowered api returned failed response";
68///     let is_invalid_utf8_sequence = error_message == "invalid utf-8 sequence";
69///     let no_response_from_api = error_message == "no response from API";
70///     let exceeded_api_calls_limit = (!is_steam_unsuccessful_response && !is_invalid_utf8_sequence) || no_response_from_api;
71///
72///     // you can do a retry or continue execution...
73/// };
74/// ```
75pub fn get_app_details(app_id: i64) -> Result<SteamAppDetails, String> {
76    let boxed_result = store_steampowered_com::appdetails::get(app_id);
77    boxed_result
78}
79
80/// Retrieves list of apps available on Steam. Each item consists of 2 fields: appid and name
81///
82/// # Examples
83///
84/// ```
85/// let steam_app_list = steam_webapi_rust_sdk::get_app_list().unwrap();
86///
87/// assert!(steam_app_list.len()>0);
88/// let steam_app = steam_app_list.get(0).unwrap();
89/// assert!(steam_app.appid > 0);
90///
91/// assert!(steam_app.name.len() > 0);
92/// ```
93pub fn get_app_list() -> Result<Vec<SteamApp>, String> {
94    let boxed_result = isteam_apps::get_app_list::get();
95    boxed_result
96}
97
98
99/// Retrieves list of apps available on Steam. First tries to get it from local cache.
100/// Each item consists of 2 fields: appid and name
101///
102/// # Examples
103///
104/// ```
105/// let steam_app_list = steam_webapi_rust_sdk::get_cached_app_list().unwrap();
106///
107/// assert!(steam_app_list.len()>0);
108/// let steam_app = steam_app_list.get(0).unwrap();
109/// assert!(steam_app.appid > 0);
110///
111/// assert!(steam_app.name.len() > 0);
112/// ```
113pub fn get_cached_app_list() -> Result<Vec<SteamApp>, String> {
114    let boxed_result = isteam_apps::get_app_list::get_cached();
115    boxed_result
116}
117
118/// Retrieves list of matches from Dota2
119///
120/// # Examples
121///
122/// ```
123/// let boxed_dota2_match_list = steam_webapi_rust_sdk::get_dota2_match_history(
124///     Some(76561197960361544),
125///     None,
126///     None,
127///     None,
128///     None,
129///     None,
130///     None
131/// );
132///
133/// assert!(boxed_dota2_match_list.is_ok());
134/// if boxed_dota2_match_list.is_ok() {
135///     let dota2_match_list = boxed_dota2_match_list.unwrap();
136///     assert!(dota2_match_list.matches.len()>0);
137/// }
138///
139/// ```
140pub fn get_dota2_match_history(account_id: Option<i64>,
141                               game_mode: Option<u8>,
142                               skill: Option<u8>,
143                               min_players: Option<u32>,
144                               start_at_match_id: Option<i64>,
145                               matches_requested: Option<u32>,
146                               tournament_games_only: Option<bool>)
147    -> Result<ResponseMatchHistory, String> {
148    idota2match_570::get_dota2_match_history(
149        account_id,
150        game_mode,
151        skill,
152        min_players,
153        start_at_match_id,
154        matches_requested,
155        tournament_games_only
156    )
157
158}
159
160/// Converts given 32 bit Steam account id to 64 bit
161///
162/// # Examples
163///
164/// ```
165/// use steam_webapi_rust_sdk::convert_32bit_account_id_to_64bit;
166///
167/// let _32bit_id = 95816;
168/// let converted = convert_32bit_account_id_to_64bit(_32bit_id);
169///
170/// let expected_id = 76561197960361544;
171/// assert_eq!(expected_id, converted);
172///
173/// ```
174pub fn convert_32bit_account_id_to_64bit(account_id_32bit: i64) -> i64 {
175    let valves_magic_constant = 76561197960265728;
176    let mut converted_to_64_bit = account_id_32bit;
177    converted_to_64_bit += valves_magic_constant;
178    converted_to_64_bit
179}
180
181
182/// Converts given 64 bit Steam account id to 32 bit
183///
184/// # Examples
185///
186/// ```
187/// use steam_webapi_rust_sdk::convert_64bit_account_id_to_32bit;
188///
189/// let _64bit_id = 76561197960361544;
190/// let converted = convert_64bit_account_id_to_32bit(_64bit_id);
191///
192/// let expected_id = 95816;
193/// assert_eq!(expected_id, converted);
194///
195/// ```
196pub fn convert_64bit_account_id_to_32bit(account_id_32bit: i64) -> i64 {
197    let valves_magic_constant = 76561197960265728;
198    let mut converted_to_32_bit = account_id_32bit;
199    converted_to_32_bit -= valves_magic_constant;
200    converted_to_32_bit
201}
202
203
204pub(crate) fn get_scheme() -> String {
205    "https".to_string()
206}
207
208pub(crate) fn get_host() -> String {
209    let host = "api.steampowered.com".to_string();
210    host
211}
212
213pub(crate) fn make_api_call(url: String) -> Result<String, String> {
214
215    let boxed_response = minreq::get(url).send();
216    if boxed_response.is_err() {
217        return Err("Operation timed out (API call)".to_string());
218    }
219
220    let raw_response : Vec<u8> = boxed_response.unwrap().into_bytes();
221
222    let response_string_boxed = String::from_utf8(raw_response);
223    if response_string_boxed.is_err() {
224        let error_message = response_string_boxed.err().unwrap().to_string();
225        if error_message == "invalid utf-8 sequence of 1 bytes from index 1" {
226            return Err("no response from API".to_string());
227        }
228        return Err("invalid utf-8 sequence".to_string());
229    }
230    let response_string: String = response_string_boxed.unwrap();
231
232    Ok(response_string)
233}