1use crate::auth::AuthToken;
3use crate::auth::noauth::NoAuthToken;
4#[cfg_attr(
6 feature = "rustls",
7 doc = r##"
8## Example
9Basic usage with a pre-created cookie file forcing use of rustls
10```no_run
11#[tokio::main]
12pub async fn main() -> Result<(), ytmapi_rs::Error> {
13 let cookie_path = std::path::Path::new("./cookie.txt");
14 let yt = ytmapi_rs::builder::YtMusicBuilder::new_rustls_tls()
15 .with_browser_token_cookie_file(cookie_path)
16 .build()
17 .await?;
18 yt.get_search_suggestions("Beatles").await?;
19 let result = yt.get_search_suggestions("Beatles").await?;
20 println!("{:?}", result);
21 Ok(())
22}
23```
24"##
25)]
26use crate::{
27 Result, YtMusic,
28 auth::{BrowserToken, OAuthToken},
29 client::Client,
30};
31use std::path::Path;
32
33#[derive(Default)]
34pub enum ClientOptions {
35 #[default]
36 Default,
37 #[cfg(feature = "rustls")]
38 Rustls,
39 #[cfg(feature = "native-tls")]
40 NativeTls,
41 Existing(Client),
42}
43
44pub struct NoToken;
46pub struct FromCookie(String);
48pub struct FromCookieFile<T>(T);
50
51pub struct YtMusicBuilder<T> {
53 client_options: ClientOptions,
54 token: T,
55}
56
57impl<T> YtMusicBuilder<T> {
58 pub fn with_default_tls(mut self) -> Self {
59 self.client_options = ClientOptions::Default;
60 self
61 }
62 pub fn with_client(mut self, client: Client) -> Self {
63 self.client_options = ClientOptions::Existing(client);
64 self
65 }
66 #[cfg(feature = "rustls")]
67 #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
68 pub fn with_rustls_tls(mut self) -> Self {
69 self.client_options = ClientOptions::Rustls;
70 self
71 }
72 #[cfg(feature = "native-tls")]
73 #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
74 pub fn with_native_tls(mut self) -> Self {
75 self.client_options = ClientOptions::NativeTls;
76 self
77 }
78 pub fn with_auth_token<A: AuthToken>(self, token: A) -> YtMusicBuilder<A> {
79 let YtMusicBuilder {
80 client_options,
81 token: _,
82 } = self;
83 YtMusicBuilder {
84 client_options,
85 token,
86 }
87 }
88 pub fn with_browser_token_cookie(self, cookie: String) -> YtMusicBuilder<FromCookie> {
90 let YtMusicBuilder {
91 client_options,
92 token: _,
93 } = self;
94 let token = FromCookie(cookie);
95 YtMusicBuilder {
96 client_options,
97 token,
98 }
99 }
100 pub fn with_browser_token_cookie_file<P: AsRef<Path>>(
102 self,
103 cookie_file: P,
104 ) -> YtMusicBuilder<FromCookieFile<P>> {
105 let YtMusicBuilder {
106 client_options,
107 token: _,
108 } = self;
109 let token = FromCookieFile(cookie_file);
110 YtMusicBuilder {
111 client_options,
112 token,
113 }
114 }
115 #[deprecated = "Use generic `with_auth_token` instead"]
116 pub fn with_browser_token(self, token: BrowserToken) -> YtMusicBuilder<BrowserToken> {
117 let YtMusicBuilder {
118 client_options,
119 token: _,
120 } = self;
121 YtMusicBuilder {
122 client_options,
123 token,
124 }
125 }
126 #[deprecated = "Use generic `with_auth_token` instead"]
127 pub fn with_oauth_token(self, token: OAuthToken) -> YtMusicBuilder<OAuthToken> {
128 let YtMusicBuilder {
129 client_options,
130 token: _,
131 } = self;
132 YtMusicBuilder {
133 client_options,
134 token,
135 }
136 }
137}
138impl YtMusicBuilder<FromCookie> {
139 pub async fn build(self) -> Result<YtMusic<BrowserToken>> {
140 let YtMusicBuilder {
141 client_options,
142 token: FromCookie(cookie),
143 } = self;
144 let client = build_client(client_options)?;
145 let token = BrowserToken::from_str(cookie.as_ref(), &client).await?;
146 Ok(YtMusic { client, token })
147 }
148}
149impl<P: AsRef<Path>> YtMusicBuilder<FromCookieFile<P>> {
150 pub async fn build(self) -> Result<YtMusic<BrowserToken>> {
151 let YtMusicBuilder {
152 client_options,
153 token: FromCookieFile(cookie_file),
154 } = self;
155 let client = build_client(client_options)?;
156 let token = BrowserToken::from_cookie_file(cookie_file, &client).await?;
157 Ok(YtMusic { client, token })
158 }
159}
160impl YtMusicBuilder<NoToken> {
161 #[allow(clippy::new_without_default)]
165 pub fn new() -> YtMusicBuilder<NoToken> {
166 YtMusicBuilder {
167 client_options: ClientOptions::Default,
168 token: NoToken,
169 }
170 }
171 pub fn new_with_client(client: Client) -> YtMusicBuilder<NoToken> {
172 YtMusicBuilder {
173 client_options: ClientOptions::Existing(client),
174 token: NoToken,
175 }
176 }
177 #[cfg(feature = "rustls")]
178 #[cfg_attr(docsrs, doc(cfg(feature = "rustls")))]
179 pub fn new_rustls_tls() -> YtMusicBuilder<NoToken> {
180 YtMusicBuilder {
181 client_options: ClientOptions::Rustls,
182 token: NoToken,
183 }
184 }
185 #[cfg(feature = "native-tls")]
186 #[cfg_attr(docsrs, doc(cfg(feature = "native-tls")))]
187 pub fn new_native_tls() -> Self {
188 YtMusicBuilder {
189 client_options: ClientOptions::NativeTls,
190 token: NoToken,
191 }
192 }
193 pub async fn build(self) -> Result<YtMusic<NoAuthToken>> {
194 let YtMusicBuilder { client_options, .. } = self;
195 let client = build_client(client_options)?;
196 let token = NoAuthToken::new(&client).await?;
197 Ok(YtMusic { client, token })
198 }
199}
200
201impl<A: AuthToken> YtMusicBuilder<A> {
202 pub fn build(self) -> Result<YtMusic<A>> {
203 let YtMusicBuilder {
204 client_options,
205 token,
206 } = self;
207 let client = build_client(client_options)?;
208 Ok(YtMusic { client, token })
209 }
210}
211
212fn build_client(client_options: ClientOptions) -> Result<Client> {
213 match client_options {
214 ClientOptions::Default => Client::new(),
215 #[cfg(feature = "rustls")]
216 ClientOptions::Rustls => Client::new_rustls_tls(),
217 #[cfg(feature = "native-tls")]
218 ClientOptions::NativeTls => Client::new_native_tls(),
219 ClientOptions::Existing(client) => Ok(client),
220 }
221}