ytmapi_rs/query/playlist/
edit.rs1use super::PrivacyStatus;
2use crate::{
3 auth::AuthToken,
4 common::{ApiOutcome, PlaylistID, SetVideoID, YoutubeID},
5 query::{PostMethod, PostQuery, Query},
6};
7use serde_json::json;
8use std::borrow::Cow;
9
10pub struct EditPlaylistQuery<'a> {
12 id: PlaylistID<'a>,
13 new_title: Option<Cow<'a, str>>,
14 new_description: Option<Cow<'a, str>>,
15 new_privacy_status: Option<PrivacyStatus>,
16 swap_videos_order: Option<(SetVideoID<'a>, SetVideoID<'a>)>,
17 change_add_order: Option<AddOrder>,
18 add_playlist: Option<PlaylistID<'a>>,
19}
20
21#[derive(Default)]
22pub enum AddOrder {
23 AddToTop,
24 #[default]
25 AddToBottom,
26}
27
28impl<'a> EditPlaylistQuery<'a> {
29 pub fn new_title<T: Into<PlaylistID<'a>>, S: Into<Cow<'a, str>>>(id: T, new_title: S) -> Self {
30 let id = id.into();
31 Self {
32 id,
33 new_title: Some(new_title.into()),
34 new_description: None,
35 new_privacy_status: None,
36 swap_videos_order: None,
37 change_add_order: None,
38 add_playlist: None,
39 }
40 }
41 pub fn new_description<T: Into<PlaylistID<'a>>, S: Into<Cow<'a, str>>>(
42 id: T,
43 new_description: S,
44 ) -> Self {
45 let id = id.into();
46 Self {
47 id,
48 new_title: None,
49 new_description: Some(new_description.into()),
50 new_privacy_status: None,
51 swap_videos_order: None,
52 change_add_order: None,
53 add_playlist: None,
54 }
55 }
56 pub fn new_privacy_status<T: Into<PlaylistID<'a>>>(
57 id: T,
58 new_privacy_status: PrivacyStatus,
59 ) -> Self {
60 let id = id.into();
61 Self {
62 id,
63 new_title: None,
64 new_privacy_status: Some(new_privacy_status),
65 new_description: None,
66 swap_videos_order: None,
67 change_add_order: None,
68 add_playlist: None,
69 }
70 }
71 pub fn swap_videos_order<T: Into<PlaylistID<'a>>>(
72 id: T,
73 video_1: SetVideoID<'a>,
74 video_2: SetVideoID<'a>,
75 ) -> Self {
76 let id = id.into();
77 Self {
78 id,
79 new_title: None,
80 swap_videos_order: Some((video_1, video_2)),
81 new_privacy_status: None,
82 new_description: None,
83 change_add_order: None,
84 add_playlist: None,
85 }
86 }
87 pub fn change_add_order<T: Into<PlaylistID<'a>>>(id: T, change_add_order: AddOrder) -> Self {
88 let id = id.into();
89 Self {
90 id,
91 new_title: None,
92 change_add_order: Some(change_add_order),
93 new_privacy_status: None,
94 swap_videos_order: None,
95 new_description: None,
96 add_playlist: None,
97 }
98 }
99 pub fn add_playlist<T: Into<PlaylistID<'a>>>(id: T, add_playlist: PlaylistID<'a>) -> Self {
100 let id = id.into();
101 Self {
102 id,
103 new_title: None,
104 add_playlist: Some(add_playlist),
105 new_privacy_status: None,
106 swap_videos_order: None,
107 change_add_order: None,
108 new_description: None,
109 }
110 }
111 pub fn with_new_description<S: Into<Cow<'a, str>>>(mut self, new_description: S) -> Self {
112 self.new_description = Some(new_description.into());
113 self
114 }
115 pub fn with_new_privacy_status(mut self, new_privacy_status: PrivacyStatus) -> Self {
116 self.new_privacy_status = Some(new_privacy_status);
117 self
118 }
119 pub fn with_change_add_order(mut self, change_add_order: AddOrder) -> Self {
120 self.change_add_order = Some(change_add_order);
121 self
122 }
123 pub fn with_add_playlist(mut self, add_playlist: PlaylistID<'a>) -> Self {
124 self.add_playlist = Some(add_playlist);
125 self
126 }
127 pub fn with_swap_videos_order(
128 mut self,
129 first_video: SetVideoID<'a>,
130 second_video: SetVideoID<'a>,
131 ) -> Self {
132 self.swap_videos_order = Some((first_video, second_video));
133 self
134 }
135}
136
137impl<A: AuthToken> Query<A> for EditPlaylistQuery<'_> {
138 type Output = ApiOutcome;
139 type Method = PostMethod;
140}
141impl PostQuery for EditPlaylistQuery<'_> {
142 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
143 let mut actions = Vec::new();
144 if let Some(new_title) = &self.new_title {
145 actions.push(json!({
146 "action" : "ACTION_SET_PLAYLIST_NAME",
147 "playlistName" : new_title
148 }))
149 };
150 if let Some(new_description) = &self.new_description {
151 actions.push(json!({
152 "action" : "ACTION_SET_PLAYLIST_DESCRIPTION",
153 "playlistDescription" : new_description
154 }))
155 };
156 if let Some(new_privacy_status) = &self.new_privacy_status {
157 actions.push(json!({
158 "action" : "ACTION_SET_PLAYLIST_PRIVACY",
159 "playlistPrivacy" : new_privacy_status
160 }))
161 };
162 if let Some((video_1, video_2)) = &self.swap_videos_order {
163 actions.push(json!({
164 "action" : "ACTION_MOVE_VIDEO_BEFORE",
165 "setVideoId" : video_1,
166 "movedSetVideoIdSuccessor" : video_2
167 }))
168 };
169 if let Some(add_playlist) = &self.add_playlist {
170 actions.push(json!({
171 "action" : "ACTION_ADD_PLAYLIST",
172 "addedFullListId" : add_playlist
173 }))
174 };
175 if let Some(change_add_order) = &self.change_add_order {
176 let add_to_top = match change_add_order {
177 AddOrder::AddToTop => true,
178 AddOrder::AddToBottom => false,
179 };
180 actions.push(json!({
181 "action" : "ACTION_SET_ADD_TO_TOP",
182 "addToTop" : add_to_top
183 }))
184 };
185 if let Some(new_privacy_status) = &self.new_privacy_status {
186 actions.push(json!({
187 "action" : "ACTION_SET_PLAYLIST_PRIVACY",
188 "playlistPrivacy" : new_privacy_status
189 }))
190 };
191 let serde_json::Value::Object(map) = json!({
194 "playlistId" : self.id.get_raw(),
195 "actions" : actions,
196 }) else {
197 unreachable!()
198 };
199 map
200 }
201 fn path(&self) -> &str {
202 "browse/edit_playlist"
203 }
204 fn params(&self) -> Vec<(&str, Cow<str>)> {
205 vec![]
206 }
207}