Skip to main content

itchio_api/
search.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#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
8struct WrappedGames {
9  games: Vec<Game>,
10  page: u16,
11  per_page: u16,
12}
13
14/// A representation of a publicly visible Game on the itch.io website.
15#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
16pub struct Game {
17  pub id: u32,
18  pub title: String,
19  pub short_text: Option<String>,
20  pub url: Url,
21  pub cover_url: Option<Url>,
22  pub still_cover_url: Option<Url>,
23  pub r#type: String,
24  pub classification: String,
25  pub p_linux: bool,
26  pub p_android: bool,
27  pub p_windows: bool,
28  pub p_osx: bool,
29  #[serde(deserialize_with = "date_from_str")]
30  pub created_at: DateTime<Utc>,
31  pub min_price: u32,
32  pub can_be_bought: bool,
33  #[serde(default, deserialize_with = "option_date_from_str")]
34  pub published_at: Option<DateTime<Utc>>,
35  pub has_demo: bool,
36  pub embed: Option<Embed>,
37  pub in_press_system: bool,
38}
39
40impl Itchio {
41  /// Perform a text search for published (and non-deindexed) games.
42  pub async fn search_games(&self, query: &str, page: u16) -> Result<Vec<Game>, ItchioError> {
43    let endpoint = format!("search/games?query={}&page={}", query, page);
44    let response = self.request::<WrappedGames>(endpoint).await?;
45    Ok(response.games)
46  }
47}
48
49#[cfg(test)]
50mod tests {
51  use super::*;
52  use std::env;
53  use dotenv::dotenv;
54
55  #[tokio::test]
56  async fn good() {
57    dotenv().ok();
58    let client_secret = env::var("KEY").expect("KEY has to be set");
59    let api = Itchio::new(client_secret);
60    let search = api.search_games("a", 1).await.inspect_err(|err| eprintln!("Error spotted: {}", err));
61    assert!(search.is_ok())
62  }
63
64  #[tokio::test]
65  async fn bad_key() {
66    let api = Itchio::new("bad_key".to_string());
67    let search = api.search_games("a", 1).await;
68    assert!(search.is_err_and(|err| matches!(err, ItchioError::BadKey)))
69  }
70}