scores

football-data.org terminal interface
Log | Files | Refs | README | LICENSE

api.rs (1427B)


      1 use crate::error::{AppError, Result};
      2 use crate::league::League;
      3 use crate::models::{MatchesResponse, StandingsResponse};
      4 
      5 pub struct ApiClient {
      6     client: reqwest::Client,
      7     api_token: String,
      8 }
      9 
     10 impl ApiClient {
     11     pub fn new(api_token: String) -> Self {
     12         Self {
     13             client: reqwest::Client::new(),
     14             api_token,
     15         }
     16     }
     17 
     18     async fn fetch<T: for<'de> serde::Deserialize<'de>>(&self, path: &str) -> Result<T> {
     19         let url = format!("https://api.football-data.org/v4/{path}");
     20 
     21         let response = self
     22             .client
     23             .get(&url)
     24             .header("X-Auth-Token", &self.api_token)
     25             .send()
     26             .await?;
     27 
     28         if !response.status().is_success() {
     29             return Err(AppError::ApiStatus(response.status().as_u16()));
     30         }
     31 
     32         Ok(response.json::<T>().await?)
     33     }
     34 
     35     pub async fn fetch_matches(&self, league: League) -> Result<MatchesResponse> {
     36         self.fetch(&format!("competitions/{}/matches", league.code()))
     37             .await
     38     }
     39 
     40     pub async fn fetch_standings(&self, league: League) -> Result<StandingsResponse> {
     41         self.fetch(&format!("competitions/{}/standings", league.code()))
     42             .await
     43     }
     44 
     45     /// Fetch all matches across every available competition (`GET /v4/matches`).
     46     pub async fn fetch_all_matches(&self) -> Result<MatchesResponse> {
     47         self.fetch("matches").await
     48     }
     49 }