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