ytmapi_rs/query/playlist/
create.rs1use super::PrivacyStatus;
2use crate::{
3 auth::AuthToken,
4 common::{PlaylistID, VideoID},
5 query::{PostMethod, PostQuery, Query},
6};
7use serde_json::json;
8use std::borrow::Cow;
9
10pub trait CreatePlaylistType {
11 fn additional_header(&self) -> Option<(String, serde_json::Value)>;
12}
13
14#[derive(Debug, Clone, PartialEq)]
17pub struct CreatePlaylistQuery<'a, C: CreatePlaylistType> {
18 title: Cow<'a, str>,
19 description: Option<Cow<'a, str>>,
20 privacy_status: PrivacyStatus,
21 query_type: C,
22}
23
24#[derive(Default, Debug, Clone, PartialEq)]
26pub struct BasicCreatePlaylist {}
27#[derive(Default, Debug, Clone, PartialEq)]
29pub struct CreatePlaylistFromVideos<'a> {
30 video_ids: Vec<VideoID<'a>>,
31}
32#[derive(Debug, Clone, PartialEq)]
34pub struct CreatePlaylistFromPlaylist<'a> {
35 source_playlist: PlaylistID<'a>,
36}
37
38impl CreatePlaylistType for BasicCreatePlaylist {
39 fn additional_header(&self) -> Option<(String, serde_json::Value)> {
40 None
41 }
42}
43impl CreatePlaylistType for CreatePlaylistFromVideos<'_> {
44 fn additional_header(&self) -> Option<(String, serde_json::Value)> {
45 Some(("videoIds".into(), json!(self.video_ids)))
46 }
47}
48impl CreatePlaylistType for CreatePlaylistFromPlaylist<'_> {
49 fn additional_header(&self) -> Option<(String, serde_json::Value)> {
50 Some(("sourcePlaylistId".into(), json!(self.source_playlist)))
51 }
52}
53
54impl<'a> CreatePlaylistQuery<'a, BasicCreatePlaylist> {
55 pub fn new(
56 title: &'a str,
57 description: Option<&'a str>,
58 privacy_status: PrivacyStatus,
59 ) -> CreatePlaylistQuery<'a, BasicCreatePlaylist> {
60 CreatePlaylistQuery {
61 title: title.into(),
62 description: description.map(|d| d.into()),
63 privacy_status,
64 query_type: BasicCreatePlaylist {},
65 }
66 }
67}
68
69impl<'a> CreatePlaylistQuery<'a, BasicCreatePlaylist> {
70 pub fn with_source<T: Into<PlaylistID<'a>>>(
71 self,
72 source_playlist: T,
73 ) -> CreatePlaylistQuery<'a, CreatePlaylistFromPlaylist<'a>> {
74 let CreatePlaylistQuery {
75 title,
76 description,
77 privacy_status,
78 ..
79 } = self;
80 CreatePlaylistQuery {
81 title,
82 description,
83 privacy_status,
84 query_type: CreatePlaylistFromPlaylist {
85 source_playlist: source_playlist.into(),
86 },
87 }
88 }
89}
90
91impl<'a> CreatePlaylistQuery<'a, BasicCreatePlaylist> {
92 pub fn with_video_ids(
93 self,
94 video_ids: Vec<VideoID<'a>>,
95 ) -> CreatePlaylistQuery<'a, CreatePlaylistFromVideos<'a>> {
96 let CreatePlaylistQuery {
97 title,
98 description,
99 privacy_status,
100 ..
101 } = self;
102 CreatePlaylistQuery {
103 title,
104 description,
105 privacy_status,
106 query_type: CreatePlaylistFromVideos { video_ids },
107 }
108 }
109}
110
111impl<A: AuthToken, C: CreatePlaylistType> Query<A> for CreatePlaylistQuery<'_, C> {
112 type Output = PlaylistID<'static>;
113 type Method = PostMethod;
114}
115impl<C: CreatePlaylistType> PostQuery for CreatePlaylistQuery<'_, C> {
116 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
117 let serde_json::Value::Object(mut map) = json!({
119 "title" : self.title,
120 "privacyStatus" : self.privacy_status.to_string(),
121 }) else {
122 unreachable!()
123 };
124 if let Some(description) = &self.description {
125 map.insert("description".to_string(), description.as_ref().into());
129 }
130 if let Some(additional_header) = self.query_type.additional_header() {
131 map.insert(additional_header.0, additional_header.1);
132 }
133 map
134 }
135 fn path(&self) -> &str {
136 "playlist/create"
137 }
138 fn params(&self) -> Vec<(&str, Cow<str>)> {
139 vec![]
140 }
141}