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