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
//! Functionality dealing with an account's friends
use crate::client::SteamClient;
use crate::errors::SteamError;
use serde::Deserialize;
use std::fmt::Formatter;
// The "GetFriendList (v0001)" endpoint
const ENDPOINT_GET_FRIENDLIST: &str = "https://api.steampowered.com/ISteamUser/GetFriendList/v0001";
/// Helper struct used during deserializing the API response.
#[derive(Debug, Deserialize)]
struct FriendsResponse {
/// A list of [`Friend`]s
#[serde(rename(deserialize = "friendslist"))]
response: Option<FriendsList>,
}
/// This is the response that comes from the GetFriendList API.
#[derive(Debug, Default, Deserialize)]
pub struct FriendsList {
/// A list of [`Friend`]s
pub friends: Vec<Friend>,
}
impl From<FriendsResponse> for FriendsList {
fn from(value: FriendsResponse) -> Self {
let v = value.response.unwrap_or_default();
Self { friends: v.friends }
}
}
/// Represents a Steam friend and its metadata
#[derive(Debug, Deserialize, PartialEq)]
pub struct Friend {
/// The friend's Steam ID
#[serde(rename(deserialize = "steamid"))]
pub steam_id: String,
/// The relationship you have with the Steam user
pub relationship: SteamRelationship,
/// Unix timestamp of the time when the relationship was created.
pub friend_since: i64,
}
impl std::fmt::Display for Friend {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Friend ID: {}, friends since {}",
self.steam_id, self.friend_since
)
}
}
/// Enumeration of possible relationship qualifiers.
#[derive(Debug, Deserialize, PartialEq)]
#[non_exhaustive]
pub enum SteamRelationship {
/// You are friends with that person
#[serde(rename(deserialize = "friend"))]
Friend,
}
impl SteamClient {
/// Gets all friends from the user with the provided Steam ID.
///
/// Example:
///
/// ```no_run
/// # use steamr::client::SteamClient;
/// # use steamr::errors::SteamError;
///
/// fn main() -> Result<(), SteamError> {
/// let steam_client = SteamClient::from("an-api-key".to_string());
/// let steam_friends = steam_client.get_friends("some-steam-ID")?;
///
/// // Print friends
/// steam_friends.iter().for_each(|f| println!("{}", f));
///
/// Ok(())
/// }
/// ```
///
/// The standard format of "friends since" is the UNIX timestamp, you might want to get a
/// more intuitive time format. You could use the `chrono` crate for this:
/// ```ignore
/// let steam_friends = steam_client.get_friends("some-steam-ID")?;
/// steam_friends.iter().for_each(|f| {
/// println!(
/// "me and {} are friends since {}",
/// f.steam_id,
/// chrono::NaiveDateTime::from_timestamp(f.friend_since, 0)
/// )
/// });
/// ```
pub fn get_friends(&self, steam_id: &str) -> Result<Vec<Friend>, SteamError> {
let response = self.get_request(
ENDPOINT_GET_FRIENDLIST,
vec![("steamid", steam_id), ("relationship", "friend")],
)?;
let friends_list = self
.parse_response::<FriendsResponse, FriendsList>(response)
.unwrap();
Ok(friends_list.friends)
}
}