Skip to main content

itchio_api/
my_games.rs

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