mlb_api/endpoints/people/free_agents/
mod.rs1use serde_with::DefaultOnError;
2use crate::endpoints::person::Person;
3use crate::endpoints::teams::team::Team;
4use crate::endpoints::{Position, StatsAPIUrl};
5use crate::gen_params;
6use crate::types::Copyright;
7use chrono::NaiveDate;
8use serde::Deserialize;
9use std::fmt::{Display, Formatter};
10use serde_with::serde_as;
11
12#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
13#[serde(rename_all = "camelCase")]
14pub struct FreeAgentsResponse {
15 pub copyright: Copyright,
16 pub free_agents: Vec<FreeAgent>,
17}
18
19#[serde_as]
20#[derive(Deserialize)]
21#[serde(rename_all = "camelCase")]
22struct __FreeAgentStruct {
23 player: Person,
24 #[serde_as(deserialize_as = "DefaultOnError")]
25 original_team: Option<Team>,
26 #[serde_as(deserialize_as = "DefaultOnError")]
27 new_team: Option<Team>,
28 notes: Option<String>,
29 date_signed: Option<NaiveDate>,
30 date_declared: Option<NaiveDate>,
31 position: Position,
32}
33
34#[derive(Debug, Deserialize, PartialEq, Eq, Clone)]
35#[serde(from = "__FreeAgentStruct")]
36pub struct FreeAgent {
37 pub player: Person,
38 pub original_team: Team,
39 pub new_team: Team,
40 pub notes: Option<String>,
41 pub date_signed: NaiveDate,
42 pub date_declared: NaiveDate,
43 pub position: Position,
44}
45
46impl From<__FreeAgentStruct> for FreeAgent {
47 fn from(value: __FreeAgentStruct) -> Self {
48 FreeAgent {
49 player: value.player,
50 original_team: value.original_team.unwrap_or_else(Team::unknown_team),
51 new_team: value.new_team.unwrap_or_else(Team::unknown_team),
52 notes: value.notes,
53 date_signed: value.date_signed.or(value.date_declared).unwrap_or_default(),
54 date_declared: value.date_declared.or(value.date_signed).unwrap_or_default(),
55 position: value.position,
56 }
57 }
58}
59
60pub struct FreeAgentsEndpointUrl {
61 pub season: u16,
62}
63
64impl Display for FreeAgentsEndpointUrl {
65 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
66 write!(f, "http://statsapi.mlb.com/api/v1/people/freeAgents{}", gen_params! { "season": self.season })
67 }
68}
69
70impl StatsAPIUrl for FreeAgentsEndpointUrl {
71 type Response = FreeAgentsResponse;
72}
73
74#[cfg(test)]
75mod tests {
76 use crate::endpoints::people::free_agents::FreeAgentsEndpointUrl;
77 use crate::endpoints::StatsAPIUrl;
78 use chrono::{Datelike, Local};
79
80 #[tokio::test]
81 async fn test_2025() {
82 let _response = FreeAgentsEndpointUrl { season: 2025 }.get().await.unwrap();
83 }
84
85 #[tokio::test]
86 async fn test_all_seasons() {
87 for season in 2001..=Local::now().year() as _ {
88 let _response = FreeAgentsEndpointUrl { season }.get().await.unwrap();
89 }
90 }
91}