ytmapi_rs/query/
history.rs1use super::{GetMethod, GetQuery, PostMethod, PostQuery, Query};
2use crate::auth::LoggedIn;
3use crate::common::{ApiOutcome, FeedbackTokenRemoveFromHistory, SongTrackingUrl, YoutubeID};
4use crate::parse::HistoryPeriod;
5use rand::Rng;
6use serde_json::json;
7use std::borrow::Cow;
8
9pub struct GetHistoryQuery;
10pub struct RemoveHistoryItemsQuery<'a> {
11 feedback_tokens: Vec<FeedbackTokenRemoveFromHistory<'a>>,
12}
13pub struct AddHistoryItemQuery<'a> {
14 song_url: SongTrackingUrl<'a>,
15}
16
17impl<'a> RemoveHistoryItemsQuery<'a> {
18 pub fn new(
19 feedback_tokens: impl IntoIterator<Item = FeedbackTokenRemoveFromHistory<'a>>,
20 ) -> Self {
21 Self {
22 feedback_tokens: feedback_tokens.into_iter().collect(),
23 }
24 }
25}
26
27impl<'a> AddHistoryItemQuery<'a> {
28 pub fn new(song_url: SongTrackingUrl<'a>) -> Self {
29 Self { song_url }
30 }
31}
32
33impl<A: LoggedIn> Query<A> for GetHistoryQuery {
35 type Output = Vec<HistoryPeriod>;
36 type Method = PostMethod;
37}
38impl PostQuery for GetHistoryQuery {
39 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
40 serde_json::Map::from_iter([("browseId".to_string(), json!("FEmusic_history"))])
41 }
42 fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
43 vec![]
44 }
45 fn path(&self) -> &str {
46 "browse"
47 }
48}
49
50impl<A: LoggedIn> Query<A> for RemoveHistoryItemsQuery<'_> {
52 type Output = Vec<ApiOutcome>;
53 type Method = PostMethod;
54}
55impl PostQuery for RemoveHistoryItemsQuery<'_> {
56 fn header(&self) -> serde_json::Map<String, serde_json::Value> {
57 serde_json::Map::from_iter([("feedbackTokens".to_string(), json!(self.feedback_tokens))])
58 }
59 fn params(&self) -> std::vec::Vec<(&str, std::borrow::Cow<'_, str>)> {
60 vec![]
61 }
62 fn path(&self) -> &str {
63 "feedback"
64 }
65}
66
67impl<A: LoggedIn> Query<A> for AddHistoryItemQuery<'_> {
68 type Output = ();
69 type Method = GetMethod;
70}
71
72impl GetQuery for AddHistoryItemQuery<'_> {
73 fn url(&self) -> &str {
74 self.song_url.get_raw()
75 }
76 fn params(&self) -> Vec<(&str, Cow<'_, str>)> {
77 let possible_chars: Vec<char> =
80 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
81 .chars()
82 .collect();
83 let random_cpn: String = rand::rng()
84 .sample_iter(
85 rand::distr::slice::Choose::new(&possible_chars)
86 .expect("Provided a hard-coded non-empty slice"),
87 )
88 .take(16)
89 .collect();
90 vec![
91 ("ver", "2".into()),
92 ("c", "WEB_REMIX".into()),
93 ("cpn", random_cpn.into()),
94 ]
95 }
96}