mlb_api/endpoints/people/free_agents/
mod.rs

1use 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}