1use crate::card::{Card, CardId, CardRace, CardType, Language};
2use crate::error::Result;
3use std::borrow::Cow;
4use std::sync::LazyLock;
5use url::Url;
6
7static CARD_URL: LazyLock<Url> = LazyLock::new(|| {
8 let url = "https://db.ygoprodeck.com/api/v7/cardinfo.php";
9 Url::parse(url).expect("failed to parse card url")
10});
11
12#[derive(Clone, Debug)]
13pub struct CardQuery(Cow<'static, Url>);
14
15impl CardQuery {
16 pub fn new() -> Self {
17 Self(Cow::Borrowed(&CARD_URL))
18 }
19
20 pub async fn send(self) -> Result<Vec<Card>> {
21 crate::http::send(self).await
22 }
23
24 #[inline]
25 pub fn into_url(self) -> Url {
26 self.0.into_owned()
27 }
28
29 #[inline]
30 #[must_use]
31 pub fn archetype(self, archetype: &str) -> Self {
32 self.append_pair("archetype", archetype)
33 }
34
35 #[inline]
36 #[must_use]
37 pub fn atk(self, atk: &str) -> Self {
38 self.append_pair("atk", atk)
39 }
40
41 #[inline]
42 #[must_use]
43 pub fn attribute(self, attribute: &str) -> Self {
44 self.append_pair("attribute", attribute)
45 }
46
47 #[inline]
48 #[must_use]
49 pub fn banlist(self, banlist: &str) -> Self {
50 self.append_pair("banlist", banlist)
51 }
52
53 #[inline]
54 #[must_use]
55 pub fn cardset(self, set: &str) -> Self {
56 self.append_pair("cardset", set)
57 }
58
59 #[inline]
60 #[must_use]
61 pub fn def(self, def: &str) -> Self {
62 self.append_pair("def", def)
63 }
64
65 #[inline]
66 #[must_use]
67 pub fn id(self, id: CardId) -> Self {
68 self.append_pair("id", &id.to_string())
69 }
70
71 #[inline]
72 #[must_use]
73 pub fn fname(self, fname: &str) -> Self {
74 self.append_pair("fname", fname)
75 }
76
77 #[inline]
78 #[must_use]
79 pub fn format(self, format: &str) -> Self {
80 self.append_pair("format", format)
81 }
82
83 #[inline]
84 #[must_use]
85 pub fn konami_id(self, id: u32) -> Self {
86 self.append_pair("konami_id", &id.to_string())
87 }
88
89 #[inline]
90 #[must_use]
91 pub fn language(self, language: Language) -> Self {
92 self.append_pair("language", &language.to_string())
93 }
94
95 #[inline]
96 #[must_use]
97 pub fn level(self, level: &str) -> Self {
98 self.append_pair("level", level)
99 }
100
101 #[inline]
102 #[must_use]
103 pub fn link(self, value: u8) -> Self {
104 self.append_pair("link", &value.to_string())
105 }
106
107 #[inline]
108 #[must_use]
109 pub fn linkmarker(self, marker: &str) -> Self {
110 self.append_pair("linkmarker", marker)
111 }
112
113 #[inline]
114 #[must_use]
115 pub fn misc(self, yes: bool) -> Self {
116 if yes {
117 self.append_pair("misc", "yes")
118 } else {
119 self
120 }
121 }
122
123 #[inline]
124 #[must_use]
125 pub fn name(self, name: &str) -> Self {
126 self.append_pair("name", name)
127 }
128
129 #[inline]
130 #[must_use]
131 pub fn race(self, race: CardRace) -> Self {
132 self.append_pair("race", race.into())
133 }
134
135 #[inline]
136 #[must_use]
137 pub fn scale(self, scale: u8) -> Self {
138 self.append_pair("scale", &scale.to_string())
139 }
140
141 #[inline]
142 #[must_use]
143 pub fn sort(self, sort: &str) -> Self {
144 self.append_pair("sort", sort)
145 }
146
147 #[inline]
148 #[must_use]
149 pub fn staple(self, yes: bool) -> Self {
150 if yes {
151 self.append_pair("staple", "yes")
152 } else {
153 self
154 }
155 }
156
157 #[inline]
158 #[must_use]
159 pub fn r#type(self, r#type: CardType) -> Self {
160 self.append_pair("type", r#type.into())
161 }
162
163 #[must_use]
164 fn append_pair(mut self, name: &str, value: &str) -> Self {
165 self
166 .0
167 .to_mut()
168 .query_pairs_mut()
169 .append_pair(name, value);
170
171 self
172 }
173}
174
175impl Default for CardQuery {
176 fn default() -> Self {
177 Self::new()
178 }
179}
180
181impl From<CardQuery> for String {
182 fn from(query: CardQuery) -> Self {
183 query.0.to_string()
184 }
185}
186
187impl From<CardQuery> for Url {
188 fn from(query: CardQuery) -> Self {
189 query.into_url()
190 }
191}