use chrono::{DateTime, Utc};
use serde::Deserialize;
use url::Url;
use crate::{Embed, Itchio, ItchioError, parsers::{date_from_str, option_date_from_str}};
#[derive(Clone, Debug, Deserialize)] #[allow(dead_code)]
struct WrappedGames {
games: Vec<Game>,
page: u16,
per_page: u16,
}
#[derive(Clone, Debug, Deserialize)]
pub struct Game {
pub id: u32,
pub title: String,
pub short_text: Option<String>,
pub url: Url,
pub cover_url: Option<Url>,
pub still_cover_url: Option<Url>,
pub r#type: String,
pub classification: String,
pub p_linux: bool,
pub p_android: bool,
pub p_windows: bool,
pub p_osx: bool,
#[serde(deserialize_with = "date_from_str")]
pub created_at: DateTime<Utc>,
pub min_price: u32,
pub can_be_bought: bool,
#[serde(default, deserialize_with = "option_date_from_str")]
pub published_at: Option<DateTime<Utc>>,
pub has_demo: bool,
pub embed: Option<Embed>,
pub in_press_system: bool,
}
impl Itchio {
pub async fn search_games(&self, query: &str, page: u16) -> Result<Vec<Game>, ItchioError> {
let endpoint = format!("search/games?query={}&page={}", query, page);
let response = self.request::<WrappedGames>(endpoint).await?;
Ok(response.games)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
use dotenv::dotenv;
#[tokio::test]
async fn good() {
dotenv().ok();
let client_secret = env::var("KEY").expect("KEY has to be set");
let api = Itchio::new(client_secret).unwrap();
let search = api.search_games("a", 1).await.inspect_err(|err| eprintln!("Error spotted: {}", err));
assert!(search.is_ok())
}
#[tokio::test]
async fn bad_key() {
let api = Itchio::new("bad_key".to_string()).unwrap();
let search = api.search_games("a", 1).await;
assert!(search.is_err_and(|err| matches!(err, ItchioError::BadKey)))
}
}