librespot_metadata/playlist/
annotation.rs

1use std::fmt::Debug;
2
3use protobuf::Message;
4
5use crate::{
6    Metadata,
7    image::TranscodedPictures,
8    request::{MercuryRequest, RequestResult},
9};
10
11use librespot_core::{Error, Session, SpotifyId};
12
13use librespot_protocol as protocol;
14pub use protocol::playlist_annotate3::AbuseReportState;
15
16#[derive(Debug, Clone)]
17pub struct PlaylistAnnotation {
18    pub description: String,
19    pub picture: String,
20    pub transcoded_pictures: TranscodedPictures,
21    pub has_abuse_reporting: bool,
22    pub abuse_report_state: AbuseReportState,
23}
24
25#[async_trait]
26impl Metadata for PlaylistAnnotation {
27    type Message = protocol::playlist_annotate3::PlaylistAnnotation;
28
29    async fn request(session: &Session, playlist_id: &SpotifyId) -> RequestResult {
30        let current_user = session.username();
31        Self::request_for_user(session, &current_user, playlist_id).await
32    }
33
34    fn parse(msg: &Self::Message, _: &SpotifyId) -> Result<Self, Error> {
35        Ok(Self {
36            description: msg.description().to_owned(),
37            picture: msg.picture().to_owned(), // TODO: is this a URL or Spotify URI?
38            transcoded_pictures: msg.transcoded_picture.as_slice().try_into()?,
39            has_abuse_reporting: msg.is_abuse_reporting_enabled(),
40            abuse_report_state: msg.abuse_report_state(),
41        })
42    }
43}
44
45impl PlaylistAnnotation {
46    async fn request_for_user(
47        session: &Session,
48        username: &str,
49        playlist_id: &SpotifyId,
50    ) -> RequestResult {
51        let uri = format!(
52            "hm://playlist-annotate/v1/annotation/user/{}/playlist/{}",
53            username,
54            playlist_id.to_base62()?
55        );
56        <Self as MercuryRequest>::request(session, &uri).await
57    }
58
59    #[allow(dead_code)]
60    async fn get_for_user(
61        session: &Session,
62        username: &str,
63        playlist_id: &SpotifyId,
64    ) -> Result<Self, Error> {
65        let response = Self::request_for_user(session, username, playlist_id).await?;
66        let msg = <Self as Metadata>::Message::parse_from_bytes(&response)?;
67        Self::parse(&msg, playlist_id)
68    }
69}
70
71impl MercuryRequest for PlaylistAnnotation {}
72
73impl TryFrom<&<PlaylistAnnotation as Metadata>::Message> for PlaylistAnnotation {
74    type Error = librespot_core::Error;
75    fn try_from(
76        annotation: &<PlaylistAnnotation as Metadata>::Message,
77    ) -> Result<Self, Self::Error> {
78        Ok(Self {
79            description: annotation.description().to_owned(),
80            picture: annotation.picture().to_owned(),
81            transcoded_pictures: annotation.transcoded_picture.as_slice().try_into()?,
82            has_abuse_reporting: annotation.is_abuse_reporting_enabled(),
83            abuse_report_state: annotation.abuse_report_state(),
84        })
85    }
86}