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