ytmapi_rs/simplified_queries.rs
1//! This module contains the implementation for more convenient ways to call the
2//! API, in many cases without the need of building Query structs.
3//! This module contains purely additional implementations for YtMusic. To see
4//! the documentation, refer to the [`YtMusic`] documentation itself.
5//! # Optional
6//! To enable this module, feature `simplified-queries` must be enabled (enabled
7//! by default)
8use crate::auth::AuthToken;
9use crate::common::{
10 AlbumID, ApiOutcome, ArtistChannelID, BrowseParams, EpisodeID, LyricsID, MoodCategoryParams,
11 PodcastChannelID, PodcastChannelParams, PodcastID, SetVideoID, SongTrackingUrl, VideoID,
12};
13use crate::common::{
14 FeedbackTokenRemoveFromHistory, PlaylistID, SearchSuggestion, UploadAlbumID, UploadArtistID,
15};
16use crate::common::{LikeStatus, TasteToken};
17use crate::parse::{
18 AddPlaylistItem, ArtistParams, GetAlbum, GetArtistAlbumsAlbum, GetLibraryAlbums,
19 GetLibraryArtistSubscriptions, GetLibraryArtists, GetLibraryPlaylists, GetPlaylist,
20 HistoryPeriod, Lyrics, SearchResultAlbum, SearchResultArtist, SearchResultEpisode,
21 SearchResultFeaturedPlaylist, SearchResultPlaylist, SearchResultPodcast, SearchResultProfile,
22 SearchResultSong, SearchResultVideo, SearchResults, WatchPlaylist,
23};
24use crate::query::song::GetSongTrackingUrlQuery;
25use crate::query::{
26 filteredsearch::{
27 AlbumsFilter, ArtistsFilter, CommunityPlaylistsFilter, EpisodesFilter,
28 FeaturedPlaylistsFilter, FilteredSearch, PlaylistsFilter, PodcastsFilter, ProfilesFilter,
29 SongsFilter, VideosFilter,
30 },
31 lyrics::GetLyricsQuery,
32 rate::{RatePlaylistQuery, RateSongQuery},
33 watch::GetWatchPlaylistQuery,
34 AddPlaylistItemsQuery, BasicSearch, CreatePlaylistQuery, CreatePlaylistType,
35 DeletePlaylistQuery, EditPlaylistQuery, EditSongLibraryStatusQuery, GetAlbumQuery,
36 GetArtistAlbumsQuery, GetArtistQuery, GetHistoryQuery, GetLibraryAlbumsQuery,
37 GetLibraryArtistSubscriptionsQuery, GetLibraryArtistsQuery, GetLibraryPlaylistsQuery,
38 GetLibrarySongsQuery, GetLibraryUploadAlbumQuery, GetLibraryUploadAlbumsQuery,
39 GetLibraryUploadArtistQuery, GetLibraryUploadArtistsQuery, GetLibraryUploadSongsQuery,
40 GetPlaylistQuery, GetSearchSuggestionsQuery, Query, RemoveHistoryItemsQuery,
41 RemovePlaylistItemsQuery, SearchQuery,
42};
43use crate::query::{
44 AddHistoryItemQuery, DuplicateHandlingMode, GetChannelEpisodesQuery, GetChannelQuery,
45 GetEpisodeQuery, GetMoodCategoriesQuery, GetMoodPlaylistsQuery, GetNewEpisodesQuery,
46 GetPodcastQuery, GetTasteProfileQuery, SetTasteProfileQuery,
47};
48use crate::{common::UploadEntityID, query::DeleteUploadEntityQuery};
49use crate::{Result, YtMusic};
50
51impl<A: AuthToken> YtMusic<A> {
52 /// API Search Query that returns results for each category if available.
53 /// # Usage
54 /// ```no_run
55 /// # async {
56 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
57 /// yt.search("Beatles").await
58 /// # };
59 pub async fn search<'a, Q: Into<SearchQuery<'a, BasicSearch>>>(
60 &self,
61 query: Q,
62 ) -> Result<SearchResults> {
63 let query = query.into();
64 self.query(query).await
65 }
66 /// API Search Query for Artists only.
67 /// ```no_run
68 /// # async {
69 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
70 /// yt.search_artists("Beatles").await
71 /// # };
72 pub async fn search_artists<'a, Q: Into<SearchQuery<'a, FilteredSearch<ArtistsFilter>>>>(
73 &self,
74 query: Q,
75 ) -> Result<Vec<SearchResultArtist>> {
76 let query = query.into();
77 self.query(query).await
78 }
79 /// API Search Query for Albums only.
80 /// ```no_run
81 /// # async {
82 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
83 /// yt.search_albums("Beatles").await
84 /// # };
85 pub async fn search_albums<'a, Q: Into<SearchQuery<'a, FilteredSearch<AlbumsFilter>>>>(
86 &self,
87 query: Q,
88 ) -> Result<Vec<SearchResultAlbum>> {
89 let query = query.into();
90 self.query(query).await
91 }
92 /// API Search Query for Songs only.
93 /// ```no_run
94 /// # async {
95 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
96 /// yt.search_songs("Beatles").await
97 /// # };
98 pub async fn search_songs<'a, Q: Into<SearchQuery<'a, FilteredSearch<SongsFilter>>>>(
99 &self,
100 query: Q,
101 ) -> Result<Vec<SearchResultSong>> {
102 let query = query.into();
103 self.query(query).await
104 }
105 /// API Search Query for Playlists only.
106 /// ```no_run
107 /// # async {
108 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
109 /// yt.search_playlists("Beatles").await
110 /// # };
111 pub async fn search_playlists<'a, Q: Into<SearchQuery<'a, FilteredSearch<PlaylistsFilter>>>>(
112 &self,
113 query: Q,
114 ) -> Result<Vec<SearchResultPlaylist>> {
115 let query = query.into();
116 self.query(query).await
117 }
118 /// API Search Query for Community Playlists only.
119 /// ```no_run
120 /// # async {
121 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
122 /// yt.search_community_playlists("Beatles").await
123 /// # };
124 pub async fn search_community_playlists<
125 'a,
126 Q: Into<SearchQuery<'a, FilteredSearch<CommunityPlaylistsFilter>>>,
127 >(
128 &self,
129 query: Q,
130 ) -> Result<Vec<SearchResultPlaylist>> {
131 let query = query.into();
132 self.query(query).await
133 }
134 /// API Search Query for Featured Playlists only.
135 /// ```no_run
136 /// # async {
137 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
138 /// yt.search_featured_playlists("Beatles").await
139 /// # };
140 pub async fn search_featured_playlists<
141 'a,
142 Q: Into<SearchQuery<'a, FilteredSearch<FeaturedPlaylistsFilter>>>,
143 >(
144 &self,
145 query: Q,
146 ) -> Result<Vec<SearchResultFeaturedPlaylist>> {
147 let query = query.into();
148 self.query(query).await
149 }
150 /// API Search Query for Episodes only.
151 /// ```no_run
152 /// # async {
153 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
154 /// yt.search_episodes("Beatles").await
155 /// # };
156 pub async fn search_episodes<'a, Q: Into<SearchQuery<'a, FilteredSearch<EpisodesFilter>>>>(
157 &self,
158 query: Q,
159 ) -> Result<Vec<SearchResultEpisode>> {
160 let query = query.into();
161 self.query(query).await
162 }
163 /// API Search Query for Podcasts only.
164 /// ```no_run
165 /// # async {
166 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
167 /// yt.search_podcasts("Beatles").await
168 /// # };
169 pub async fn search_podcasts<'a, Q: Into<SearchQuery<'a, FilteredSearch<PodcastsFilter>>>>(
170 &self,
171 query: Q,
172 ) -> Result<Vec<SearchResultPodcast>> {
173 let query = query.into();
174 self.query(query).await
175 }
176 /// API Search Query for Videos only.
177 /// ```no_run
178 /// # async {
179 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
180 /// yt.search_videos("Beatles").await
181 /// # };
182 pub async fn search_videos<'a, Q: Into<SearchQuery<'a, FilteredSearch<VideosFilter>>>>(
183 &self,
184 query: Q,
185 ) -> Result<Vec<SearchResultVideo>> {
186 let query = query.into();
187 self.query(query).await
188 }
189 /// API Search Query for Profiles only.
190 /// ```no_run
191 /// # async {
192 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
193 /// yt.search_profiles("Beatles").await
194 /// # };
195 pub async fn search_profiles<'a, Q: Into<SearchQuery<'a, FilteredSearch<ProfilesFilter>>>>(
196 &self,
197 query: Q,
198 ) -> Result<Vec<SearchResultProfile>> {
199 let query = query.into();
200 self.query(query).await
201 }
202 /// Gets information about an artist and their top releases.
203 /// ```no_run
204 /// # async {
205 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
206 /// let results = yt.search_artists("Beatles").await.unwrap();
207 /// yt.get_artist(&results[0].browse_id).await
208 /// # };
209 pub async fn get_artist<'a>(
210 &self,
211 query: impl Into<GetArtistQuery<'a>>,
212 ) -> Result<ArtistParams> {
213 self.query(query.into()).await
214 }
215 /// Gets a full list albums for an artist.
216 /// ```no_run
217 /// # async {
218 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
219 /// let results = yt.search_artists("Beatles").await.unwrap();
220 /// let artist_top_albums = yt.get_artist(&results[0].browse_id).await.unwrap().top_releases.albums.unwrap();
221 /// yt.get_artist_albums(
222 /// artist_top_albums.browse_id.unwrap(),
223 /// artist_top_albums.params.unwrap(),
224 /// ).await
225 /// # };
226 pub async fn get_artist_albums<'a, T: Into<ArtistChannelID<'a>>, U: Into<BrowseParams<'a>>>(
227 &self,
228 channel_id: T,
229 browse_params: U,
230 ) -> Result<Vec<GetArtistAlbumsAlbum>> {
231 let query = GetArtistAlbumsQuery::new(channel_id.into(), browse_params.into());
232 self.query(query).await
233 }
234 /// Gets information about an album and its tracks.
235 /// ```no_run
236 /// # async {
237 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
238 /// let results = yt.search_albums("Dark Side Of The Moon").await.unwrap();
239 /// yt.get_album(&results[0].album_id).await
240 /// # };
241 pub async fn get_album<'a, T: Into<AlbumID<'a>>>(&self, album_id: T) -> Result<GetAlbum> {
242 let query = GetAlbumQuery::new(album_id);
243 self.query(query).await
244 }
245 /// Gets the information that's available when playing a song or playlist;
246 /// upcoming tracks and lyrics.
247 /// # Partially implemented
248 /// Tracks are not implemented - empty vector always returned.
249 /// See [`GetWatchPlaylistQuery`] and [`YtMusic.query()`]
250 /// for more ways to construct and run
251 /// a GetWatchPlaylistQuery.
252 ///
253 /// [`YtMusic.query()`]: crate::YtMusic::query
254 /// [GetWatchPlaylistQuery]: crate::query::watch::GetWatchPlaylistQuery
255 ///
256 /// ```no_run
257 /// # async {
258 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
259 /// let results = yt.search_songs("While My Guitar Gently Weeps").await.unwrap();
260 /// yt.get_watch_playlist_from_video_id(&results[0].video_id).await
261 /// # };
262 // NOTE: Could be generic across PlaylistID or VideoID using
263 // Into<GetWatchPlaylistQuery>
264 pub async fn get_watch_playlist_from_video_id<'a, S: Into<VideoID<'a>>>(
265 &self,
266 video_id: S,
267 ) -> Result<WatchPlaylist> {
268 let query = GetWatchPlaylistQuery::new_from_video_id(video_id.into());
269 self.query(query).await
270 }
271 /// Gets song lyrics and the source.
272 /// ```no_run
273 /// # async {
274 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
275 /// let results = yt.search_songs("While My Guitar Gently Weeps").await.unwrap();
276 /// let watch_playlist = yt.get_watch_playlist_from_video_id(&results[0].video_id).await.unwrap();
277 /// yt.get_lyrics(watch_playlist.lyrics_id).await
278 /// # };
279 pub async fn get_lyrics<'a, T: Into<LyricsID<'a>>>(&self, lyrics_id: T) -> Result<Lyrics> {
280 let query = GetLyricsQuery::new(lyrics_id.into());
281 self.query(query).await
282 }
283 /// Gets information about a playlist and its tracks.
284 /// ```no_run
285 /// # async {
286 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
287 /// let results = yt.search_featured_playlists("Heavy metal").await.unwrap();
288 /// yt.get_playlist(&results[0].playlist_id).await
289 /// # };
290 pub async fn get_playlist<'a, T: Into<PlaylistID<'a>>>(
291 &self,
292 playlist_id: T,
293 ) -> Result<GetPlaylist> {
294 let query = GetPlaylistQuery::new(playlist_id.into());
295 self.query(query).await
296 }
297 /// Gets search suggestions
298 /// ```no_run
299 /// # async {
300 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
301 /// yt.get_search_suggestions("The Beat").await;
302 /// # };
303 pub async fn get_search_suggestions<'a, S: Into<GetSearchSuggestionsQuery<'a>>>(
304 &self,
305 query: S,
306 ) -> Result<Vec<SearchSuggestion>> {
307 let query = query.into();
308 self.query(query).await
309 }
310 /// Gets a list of all playlists in your Library.
311 /// ```no_run
312 /// # async {
313 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
314 /// yt.get_library_playlists().await;
315 /// # };
316 pub async fn get_library_playlists(&self) -> Result<GetLibraryPlaylists> {
317 let query = GetLibraryPlaylistsQuery;
318 self.query(query).await
319 }
320 /// Gets a list of all artists in your Library.
321 /// # Additional functionality
322 /// See [`GetLibraryArtistsQuery`] and [`YtMusic.query()`]
323 /// for more ways to construct and run.
324 ///
325 /// [`YtMusic.query()`]: crate::YtMusic::query
326 /// [GetLibraryArtistsQuery]: crate::query::GetLibraryArtistsQuery
327 ///
328 /// ```no_run
329 /// # async {
330 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
331 /// let results = yt.get_library_artists().await;
332 /// # };
333 pub async fn get_library_artists(&self) -> Result<GetLibraryArtists> {
334 let query = GetLibraryArtistsQuery::default();
335 self.query(query).await
336 }
337 /// Gets a list of all songs in your Library.
338 /// # Additional functionality
339 /// See [`GetLibrarySongsQuery`] and [`YtMusic.query()`]
340 /// for more ways to construct and run.
341 ///
342 /// [`YtMusic.query()`]: crate::YtMusic::query
343 /// [GetLibrarySongsQuery]: crate::query::GetLibrarySongsQuery
344 ///
345 /// ```no_run
346 /// # async {
347 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
348 /// let results = yt.get_library_songs().await;
349 /// # };
350 pub async fn get_library_songs(&self) -> Result<<GetLibrarySongsQuery as Query<A>>::Output> {
351 let query = GetLibrarySongsQuery::default();
352 self.query(query).await
353 }
354 /// Gets a list of all albums in your Library.
355 /// # Additional functionality
356 /// See [`GetLibraryAlbumsQuery`] and [`YtMusic.query()`]
357 /// for more ways to construct and run.
358 ///
359 /// [`YtMusic.query()`]: crate::YtMusic::query
360 /// [GetLibraryAlbumsQuery]: crate::query::GetLibraryAlbumsQuery
361 ///
362 /// ```no_run
363 /// # async {
364 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
365 /// let results = yt.get_library_albums().await;
366 /// # };
367 pub async fn get_library_albums(&self) -> Result<GetLibraryAlbums> {
368 let query = GetLibraryAlbumsQuery::default();
369 self.query(query).await
370 }
371 /// Gets a list of all artist subscriptions in your Library.
372 /// # Additional functionality
373 /// See [`GetLibraryArtistSubscriptionsQuery`] and [`YtMusic.query()`]
374 /// for more ways to construct and run.
375 ///
376 /// [`YtMusic.query()`]: crate::YtMusic::query
377 /// [GetLibraryArtistSubscriptionsQuery]: crate::query::GetLibraryArtistSubscriptionsQuery
378 ///
379 /// ```no_run
380 /// # async {
381 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
382 /// let results = yt.get_library_artist_subscriptions().await;
383 /// # };
384 pub async fn get_library_artist_subscriptions(&self) -> Result<GetLibraryArtistSubscriptions> {
385 let query = GetLibraryArtistSubscriptionsQuery::default();
386 self.query(query).await
387 }
388 /// Gets your recently played history.
389 /// ```no_run
390 /// # async {
391 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
392 /// let results = yt.get_history().await;
393 /// # };
394 pub async fn get_history(&self) -> Result<Vec<HistoryPeriod>> {
395 let query = GetHistoryQuery;
396 self.query(query).await
397 }
398 /// Removes a list of items from your recently played history.
399 /// ```no_run
400 /// # async {
401 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
402 /// let history = yt.get_history().await.unwrap();
403 /// let first_history_token = match history.first().unwrap().items.first().unwrap() {
404 /// ytmapi_rs::parse::HistoryItem::Song(i) => &i.feedback_token_remove,
405 /// ytmapi_rs::parse::HistoryItem::Video(i) => &i.feedback_token_remove,
406 /// ytmapi_rs::parse::HistoryItem::Episode(i) => &i.feedback_token_remove,
407 /// ytmapi_rs::parse::HistoryItem::UploadSong(i) => &i.feedback_token_remove,
408 /// }.into();
409 /// yt.remove_history_items(vec![first_history_token]).await
410 /// # };
411 pub async fn remove_history_items(
412 &self,
413 feedback_tokens: Vec<FeedbackTokenRemoveFromHistory<'_>>,
414 ) -> Result<Vec<ApiOutcome>> {
415 let query = RemoveHistoryItemsQuery::new(feedback_tokens);
416 self.query(query).await
417 }
418 // TODO: Docs / alternative constructors.
419 pub async fn edit_song_library_status(
420 &self,
421 query: EditSongLibraryStatusQuery<'_>,
422 ) -> Result<Vec<ApiOutcome>> {
423 self.query(query).await
424 }
425 /// Sets the like status for a song.
426 /// ```no_run
427 /// # async {
428 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
429 /// let results = yt.search_songs("While My Guitar Gently Weeps").await.unwrap();
430 /// yt.rate_song(&results[0].video_id, ytmapi_rs::common::LikeStatus::Liked).await
431 /// # };
432 pub async fn rate_song<'a, T: Into<VideoID<'a>>>(
433 &self,
434 video_id: T,
435 rating: LikeStatus,
436 ) -> Result<()> {
437 let query = RateSongQuery::new(video_id.into(), rating);
438 self.query(query).await
439 }
440 /// Sets the like status for a playlist.
441 /// A 'Liked' playlist will be added to your library, an 'Indifferent' will
442 /// be removed, and a 'Disliked' will reduce the chance of it appearing in
443 /// your recommendations.
444 /// ```no_run
445 /// # async {
446 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
447 /// let results = yt.search_featured_playlists("Heavy metal")
448 /// .await
449 /// .unwrap();
450 /// yt.rate_playlist(
451 /// &results[0].playlist_id,
452 /// ytmapi_rs::common::LikeStatus::Liked,
453 /// ).await
454 /// # };
455 pub async fn rate_playlist<'a, T: Into<PlaylistID<'a>>>(
456 &self,
457 playlist_id: T,
458 rating: LikeStatus,
459 ) -> Result<()> {
460 let query = RatePlaylistQuery::new(playlist_id.into(), rating);
461 self.query(query).await
462 }
463 /// Deletes a playlist you own.
464 /// ```no_run
465 /// # async {
466 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
467 /// let results = yt.get_library_playlists().await.unwrap();
468 /// yt.delete_playlist(&results.playlists[0].playlist_id).await
469 /// # };
470 pub async fn delete_playlist<'a, T: Into<PlaylistID<'a>>>(&self, playlist_id: T) -> Result<()> {
471 let query = DeletePlaylistQuery::new(playlist_id.into());
472 self.query(query).await
473 }
474 /// Creates a new playlist.
475 /// ```no_run
476 /// # async {
477 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
478 /// let playlists = yt.search_featured_playlists("Heavy metal")
479 /// .await
480 /// .unwrap();
481 /// let query = ytmapi_rs::query::CreatePlaylistQuery::new(
482 /// "My heavy metal playlist",
483 /// None,
484 /// ytmapi_rs::query::PrivacyStatus::Public,
485 /// )
486 /// .with_source(&playlists[0].playlist_id);
487 /// yt.create_playlist(query).await
488 /// # };
489 pub async fn create_playlist<T: CreatePlaylistType>(
490 &self,
491 query: CreatePlaylistQuery<'_, T>,
492 ) -> Result<PlaylistID<'static>> {
493 self.query(query).await
494 }
495 /// Adds video items to a playlist you own.
496 /// ```no_run
497 /// # async {
498 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
499 /// let ytmapi_rs::parse::LibraryPlaylist { playlist_id, .. } =
500 /// yt.get_library_playlists().await.unwrap().playlists.pop().unwrap();
501 /// let songs = yt.search_songs("Master of puppets").await.unwrap();
502 /// yt.add_video_items_to_playlist(
503 /// playlist_id,
504 /// songs.iter().map(|s| (&s.video_id).into()).collect()
505 /// ).await
506 /// # };
507 pub async fn add_video_items_to_playlist<'a, T: Into<PlaylistID<'a>>>(
508 &self,
509 playlist_id: T,
510 video_ids: Vec<VideoID<'a>>,
511 ) -> Result<Vec<AddPlaylistItem>> {
512 let query = AddPlaylistItemsQuery::new_from_videos(
513 playlist_id.into(),
514 video_ids,
515 DuplicateHandlingMode::default(),
516 );
517 self.query(query).await
518 }
519 /// Appends another playlist to a playlist you own.
520 /// ```no_run
521 /// # async {
522 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
523 /// let ytmapi_rs::parse::LibraryPlaylist { playlist_id, .. } =
524 /// yt.get_library_playlists().await.unwrap().playlists.pop().unwrap();
525 /// let source_playlist = yt.search_featured_playlists("Heavy metal")
526 /// .await
527 /// .unwrap();
528 /// yt.add_playlist_to_playlist(
529 /// playlist_id,
530 /// &source_playlist[0].playlist_id
531 /// ).await
532 /// # };
533 pub async fn add_playlist_to_playlist<'a, T: Into<PlaylistID<'a>>, U: Into<PlaylistID<'a>>>(
534 &self,
535 destination_playlist: T,
536 source_playlist: U,
537 ) -> Result<Vec<AddPlaylistItem>> {
538 let query = AddPlaylistItemsQuery::new_from_playlist(
539 destination_playlist.into(),
540 source_playlist.into(),
541 );
542 self.query(query).await
543 }
544 /// Removes items from a playlist you own.
545 /// ```no_run
546 /// # async {
547 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
548 /// let ytmapi_rs::parse::LibraryPlaylist { playlist_id, .. } =
549 /// yt.get_library_playlists().await.unwrap().playlists.pop().unwrap();
550 /// let source_playlist = yt.search_featured_playlists("Heavy metal")
551 /// .await
552 /// .unwrap();
553 /// let outcome = yt.add_playlist_to_playlist(
554 /// &playlist_id,
555 /// &source_playlist[0].playlist_id
556 /// ).await.unwrap();
557 /// yt.remove_playlist_items(
558 /// playlist_id,
559 /// outcome.iter().map(|o| (&o.set_video_id).into()).collect(),
560 /// ).await
561 /// # };
562 pub async fn remove_playlist_items<'a, T: Into<PlaylistID<'a>>>(
563 &self,
564 playlist_id: T,
565 video_items: Vec<SetVideoID<'a>>,
566 ) -> Result<()> {
567 let query = RemovePlaylistItemsQuery::new(playlist_id.into(), video_items);
568 self.query(query).await
569 }
570 /// Makes changes to a playlist.
571 /// ```no_run
572 /// # async {
573 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
574 /// let playlists = yt.get_library_playlists()
575 /// .await
576 /// .unwrap()
577 /// .playlists;
578 /// let query = ytmapi_rs::query::EditPlaylistQuery::new_title(
579 /// &playlists[0].playlist_id,
580 /// "Better playlist title",
581 /// )
582 /// .with_new_description("Edited description");
583 /// yt.edit_playlist(query).await
584 /// # };
585 pub async fn edit_playlist(&self, query: EditPlaylistQuery<'_>) -> Result<ApiOutcome> {
586 self.query(query).await
587 }
588 /// Gets a list of all uploaded songs in your Library.
589 /// # Additional functionality
590 /// See [`GetLibraryUploadSongsQuery`] and [`YtMusic.query()`]
591 /// for more ways to construct and run.
592 ///
593 /// [`YtMusic.query()`]: crate::YtMusic::query
594 /// [GetLibraryUploadSongsQuery]: crate::query::GetLibraryUploadSongsQuery
595 ///
596 /// ```no_run
597 /// # async {
598 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
599 /// yt.get_library_upload_songs().await
600 /// # };
601 pub async fn get_library_upload_songs(
602 &self,
603 ) -> Result<<GetLibraryUploadSongsQuery as Query<A>>::Output> {
604 let query = GetLibraryUploadSongsQuery::default();
605 self.query(query).await
606 }
607 /// Gets a list of all uploaded artists in your Library.
608 /// # Additional functionality
609 /// See [`GetLibraryUploadArtistsQuery`] and [`YtMusic.query()`]
610 /// for more ways to construct and run.
611 ///
612 /// [`YtMusic.query()`]: crate::YtMusic::query
613 /// [GetLibraryUploadArtistsQuery]: crate::query::GetLibraryUploadArtistsQuery
614 ///
615 /// ```no_run
616 /// # async {
617 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
618 /// yt.get_library_upload_artists().await
619 /// # };
620 pub async fn get_library_upload_artists(
621 &self,
622 ) -> Result<<GetLibraryUploadArtistsQuery as Query<A>>::Output> {
623 let query = GetLibraryUploadArtistsQuery::default();
624 self.query(query).await
625 }
626 /// Gets a list of all uploaded albums in your Library.
627 /// # Additional functionality
628 /// See [`GetLibraryUploadAlbumsQuery`] and [`YtMusic.query()`]
629 /// for more ways to construct and run.
630 ///
631 /// [`YtMusic.query()`]: crate::YtMusic::query
632 /// [GetLibraryUploadAlbumsQuery]: crate::query::GetLibraryUploadAlbumsQuery
633 ///
634 /// ```no_run
635 /// # async {
636 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
637 /// yt.get_library_upload_albums().await
638 /// # };
639 pub async fn get_library_upload_albums(
640 &self,
641 ) -> Result<<GetLibraryUploadAlbumsQuery as Query<A>>::Output> {
642 let query = GetLibraryUploadAlbumsQuery::default();
643 self.query(query).await
644 }
645 /// Gets information and tracks for an uploaded album in your Library.
646 /// ```no_run
647 /// # async {
648 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
649 /// let albums = yt.get_library_upload_albums().await.unwrap();
650 /// yt.get_library_upload_album(&albums[0].album_id).await
651 /// # };
652 pub async fn get_library_upload_album<'a, T: Into<UploadAlbumID<'a>>>(
653 &self,
654 upload_album_id: T,
655 ) -> Result<<GetLibraryUploadAlbumQuery as Query<A>>::Output> {
656 let query = GetLibraryUploadAlbumQuery::new(upload_album_id.into());
657 self.query(query).await
658 }
659 /// Gets all tracks for an uploaded artist in your Library.
660 /// ```no_run
661 /// # async {
662 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
663 /// let artists = yt.get_library_upload_artists().await.unwrap();
664 /// yt.get_library_upload_artist(&artists[0].artist_id).await
665 /// # };
666 pub async fn get_library_upload_artist<'a, T: Into<UploadArtistID<'a>>>(
667 &self,
668 upload_artist_id: T,
669 ) -> Result<<GetLibraryUploadArtistQuery as Query<A>>::Output> {
670 let query = GetLibraryUploadArtistQuery::new(upload_artist_id.into());
671 self.query(query).await
672 }
673 /// Deletes an upload entity from your library - this is either a song or an
674 /// album.
675 /// ```no_run
676 /// # async {
677 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
678 /// let albums = yt.get_library_upload_albums().await.unwrap();
679 /// yt.delete_upload_entity(&albums[0].entity_id).await
680 /// # };
681 pub async fn delete_upload_entity<'a, T: Into<UploadEntityID<'a>>>(
682 &self,
683 upload_entity_id: T,
684 ) -> Result<<DeleteUploadEntityQuery as Query<A>>::Output> {
685 let query = DeleteUploadEntityQuery::new(upload_entity_id.into());
686 self.query(query).await
687 }
688 /// Fetches suggested artists from taste profile
689 /// <https://music.youtube.com/tasteprofile>.
690 /// Tasteprofile allows users to pick artists to update their
691 /// recommendations.
692 /// ```no_run
693 /// # async {
694 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
695 /// yt.get_taste_profile().await
696 /// # };
697 pub async fn get_taste_profile(&self) -> Result<<GetTasteProfileQuery as Query<A>>::Output> {
698 self.query(GetTasteProfileQuery).await
699 }
700 /// Sets artists as favourites to influence your recommendations.
701 /// ```no_run
702 /// # async {
703 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
704 /// let results = yt.get_taste_profile().await.unwrap();
705 /// yt.set_taste_profile(results.into_iter()
706 /// .take(5)
707 /// .map(|r| r.taste_tokens))
708 /// .await
709 /// # };
710 pub async fn set_taste_profile<'a, I, II>(
711 &self,
712 taste_tokens: II,
713 ) -> Result<<SetTasteProfileQuery<'a, I> as Query<A>>::Output>
714 where
715 I: Iterator<Item = TasteToken<'a>> + Clone,
716 II: IntoIterator<IntoIter = I>,
717 {
718 self.query(SetTasteProfileQuery::new(taste_tokens)).await
719 }
720 /// Fetches 'Moods & Genres' categories.
721 /// ```no_run
722 /// # async {
723 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
724 /// yt.get_mood_categories().await
725 /// # };
726 pub async fn get_mood_categories(
727 &self,
728 ) -> Result<<GetMoodCategoriesQuery as Query<A>>::Output> {
729 self.query(GetMoodCategoriesQuery).await
730 }
731 /// Returns a list of playlists for a given mood category.
732 /// ```no_run
733 /// # async {
734 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
735 /// let results = yt.get_mood_categories().await.unwrap();
736 /// yt.get_mood_playlists(&results[0].mood_categories[0].params).await
737 /// # };
738 pub async fn get_mood_playlists<'a, T: Into<MoodCategoryParams<'a>>>(
739 &self,
740 mood_params: T,
741 ) -> Result<<GetMoodPlaylistsQuery as Query<A>>::Output> {
742 self.query(GetMoodPlaylistsQuery::new(mood_params.into()))
743 .await
744 }
745 /// Get the 'SongTrackingUrl' for a song. This is used to add items to
746 /// history using `add_history_item()`.
747 /// ```no_run
748 /// # async {
749 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
750 /// let song = yt.search_songs("While My Guitar Gently Weeps")
751 /// .await
752 /// .unwrap()
753 /// .into_iter()
754 /// .next()
755 /// .unwrap();
756 /// yt.get_song_tracking_url(song.video_id).await
757 /// # };
758 pub async fn get_song_tracking_url<'a, T: Into<VideoID<'a>>>(
759 &self,
760 video_id: T,
761 ) -> Result<SongTrackingUrl<'static>> {
762 let query = GetSongTrackingUrlQuery::new(video_id.into())?;
763 self.query(query).await
764 }
765 /// Adds an item to the accounts history.
766 /// ```no_run
767 /// # async {
768 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
769 /// let song = yt.search_songs("While My Guitar Gently Weeps")
770 /// .await
771 /// .unwrap()
772 /// .into_iter()
773 /// .next()
774 /// .unwrap();
775 /// let url = yt.get_song_tracking_url(song.video_id).await.unwrap();
776 /// yt.add_history_item(url).await
777 /// # };
778 pub async fn add_history_item<'a, T: Into<SongTrackingUrl<'a>>>(
779 &self,
780 song_url: T,
781 ) -> Result<<AddHistoryItemQuery<'a> as Query<A>>::Output> {
782 self.query(AddHistoryItemQuery::new(song_url.into())).await
783 }
784 /// Gets information about a Channel of Podcasts.
785 /// ```no_run
786 /// # async {
787 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
788 /// let podcasts = yt.search_podcasts("Rustacean").await.unwrap();
789 /// let podcast = yt.get_podcast(&podcasts[0].podcast_id).await.unwrap();
790 /// yt.get_channel(podcast.channels[0].id.as_ref().unwrap()).await
791 /// # };
792 pub async fn get_channel(
793 &self,
794 channel_id: impl Into<PodcastChannelID<'_>>,
795 ) -> Result<<GetChannelQuery as Query<A>>::Output> {
796 self.query(GetChannelQuery::new(channel_id)).await
797 }
798 /// Gets a list of all Episodes for a Channel. Note, if GetPodcastChannel
799 /// doesn't contain `episode_params`, you can be sure that all episodes are
800 /// already included at `episodes` key.
801 /// ```no_run
802 /// # async {
803 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
804 /// let podcasts = yt.search_podcasts("Rustacean").await.unwrap();
805 /// let podcast = yt.get_podcast(&podcasts[0].podcast_id).await.unwrap();
806 /// let channel_id = podcast.channels[0].id.as_ref().unwrap();
807 /// let channel = yt.get_channel(channel_id).await.unwrap();
808 /// match channel.episode_params {
809 /// Some(p) => yt.get_channel_episodes(channel_id, p).await,
810 /// None => Ok(channel.episodes),
811 /// }
812 /// # };
813 pub async fn get_channel_episodes<'a>(
814 &self,
815 channel_id: impl Into<PodcastChannelID<'a>>,
816 podcast_channel_params: impl Into<PodcastChannelParams<'a>>,
817 ) -> Result<<GetChannelEpisodesQuery as Query<A>>::Output> {
818 self.query(GetChannelEpisodesQuery::new(
819 channel_id,
820 podcast_channel_params,
821 ))
822 .await
823 }
824 /// Gets information about a Podcast, including Episodes.
825 /// ```no_run
826 /// # async {
827 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
828 /// let podcasts = yt.search_podcasts("Rustacean").await.unwrap();
829 /// yt.get_podcast(&podcasts[0].podcast_id).await
830 /// # };
831 pub async fn get_podcast(
832 &self,
833 podcast_id: impl Into<PodcastID<'_>>,
834 ) -> Result<<GetPodcastQuery as Query<A>>::Output> {
835 self.query(GetPodcastQuery::new(podcast_id)).await
836 }
837 /// ```no_run
838 /// # async {
839 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
840 /// let episodes = yt.search_episodes("Ratatui").await.unwrap();
841 /// yt.get_episode(&episodes[0].episode_id).await
842 /// # };
843 pub async fn get_episode(
844 &self,
845 episode_id: impl Into<EpisodeID<'_>>,
846 ) -> Result<<GetEpisodeQuery as Query<A>>::Output> {
847 self.query(GetEpisodeQuery::new(episode_id)).await
848 }
849 /// Gets the special 'New Episodes' playlist.
850 /// ```no_run
851 /// # async {
852 /// let yt = ytmapi_rs::YtMusic::from_cookie("FAKE COOKIE").await.unwrap();
853 /// yt.get_new_episodes().await
854 /// # };
855 pub async fn get_new_episodes(&self) -> Result<<GetNewEpisodesQuery as Query<A>>::Output> {
856 self.query(GetNewEpisodesQuery).await
857 }
858}