Skip to main content

itchio_api/endpoints/
my_games.rs

1use chrono::{DateTime, Utc};
2use serde::Deserialize;
3use url::Url;
4
5use crate::{parsers::{date_from_str, option_date_from_str}, Itchio, ItchioError};
6
7/// The original response this crate gets from the server, useless to crate users.
8#[derive(Clone, Debug, Deserialize)]
9struct Games {
10  games: Vec<Game>
11}
12
13/// A representation of a Game on the itch.io website.
14#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
15pub struct Game {
16  pub id: u32,
17  pub title: String,
18  pub short_text: Option<String>,
19  pub url: Url,
20  pub cover_url: Option<Url>,
21  pub r#type: String,
22  pub classification: String,
23  pub p_linux: bool,
24  pub p_android: bool,
25  pub p_windows: bool,
26  pub p_osx: bool,
27  #[serde(deserialize_with = "date_from_str")]
28  pub created_at: DateTime<Utc>,
29  pub min_price: u32,
30  pub can_be_bought: bool,
31  pub published: bool,
32  // Note to self: When using a custom deserializer function, if the property is an Option because it might be missing in the JSON,
33  // "default" needs to be added to cover the missing field case
34  #[serde(default, deserialize_with = "option_date_from_str")]
35  pub published_at: Option<DateTime<Utc>>,
36  pub has_demo: bool,
37  pub embed: Option<Embed>,
38  pub user: User,
39  pub views_count: u64,
40  pub purchases_count: u64,
41  pub downloads_count: u64,
42  pub in_press_system: bool,
43  pub earnings: Option<Vec<Earning>>,
44}
45
46#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
47pub struct User {
48  pub id: u32,
49  pub display_name: String,
50  pub username: String,
51  pub url: Url,
52  pub cover_url: Url,
53}
54
55#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
56pub struct Embed {
57  pub width: u32,
58  pub height: u32,
59  pub fullscreen: bool,
60}
61
62/// How much money a Game has earned its developers.
63#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
64pub struct Earning {
65  currency: String,
66  amount_formatted: String,
67  amount: u64,
68}
69
70impl Itchio {
71  /// Get the games you've uploaded or have edit access to: <https://itch.io/docs/api/serverside#reference/profilegames-httpsitchioapi1keymy-games>
72  pub async fn get_my_games(&self) -> Result<Vec<Game>, ItchioError> {
73    let response = self.request::<Games>("my-games".to_string()).await?;
74    Ok(response.games)
75  }
76}
77
78#[cfg(test)]
79mod tests {
80  use super::*;
81  use std::env;
82  use dotenv::dotenv;
83
84  #[tokio::test]
85  async fn good() {
86    dotenv().ok();
87    let client_secret = env::var("KEY").expect("KEY has to be set");
88    let api = Itchio::new(client_secret);
89    let games = api.get_my_games().await.inspect_err(|err| eprintln!("Error spotted: {}", err));
90    assert!(games.is_ok())
91  }
92
93  #[tokio::test]
94  async fn bad() {
95    let api = Itchio::new("bad_key".to_string());
96    let games = api.get_my_games().await;
97    assert!(games.is_err_and(|err| matches!(err, ItchioError::BadKey)))
98  }
99}