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