Skip to content

Commit

Permalink
Work (Amend Next)
Browse files Browse the repository at this point in the history
  • Loading branch information
RustyNova016 committed May 8, 2024
1 parent 4f64862 commit f9d05fc
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 2 deletions.
11 changes: 11 additions & 0 deletions src/raw/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,17 @@ impl Client {

ResponseType::from_response(response)
}

// ---------- Popularity Endpoints
pub fn popularity_top_recordings_for_artist(&self, artist_mbid: &str) -> Result<ListenbrainzResponse<PopularityTopRecordingsForArtistResponse>, Error>{
let endpoint = format!("{}{}", self.api_root_url, Endpoint::PopularityTopReleaseGroupsForArtist(artist_mbid));

let mut request = attohttpc::get(endpoint);
let response = request.send()?;

// API returns 204 and an empty document if there are no statistics
ResponseType::from_response(response)
}
}

impl Default for Client {
Expand Down
16 changes: 16 additions & 0 deletions src/raw/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ pub enum Endpoint<'a> {
StatsUserArtists(&'a str),
StatsReleaseGroupListeners(&'a str),
StatusGetDumpInfo,

// Popularity endpoints
PopularityTopRecordingsForArtist(&'a str),
PopularityTopReleaseGroupsForArtist(&'a str),
PopularityRecording,
PopularityArtist,
PopularityRelease,
PopularityReleaseGroup,
}

impl<'a> fmt::Display for Endpoint<'a> {
Expand All @@ -42,6 +50,14 @@ impl<'a> fmt::Display for Endpoint<'a> {
Self::StatsUserArtists(user) => return write!(f, "stats/user/{user}/artists"),
Self::StatsReleaseGroupListeners(release_group_mbid) => return write!(f, "stats/release-group/{release_group_mbid}/listeners"),
Self::StatusGetDumpInfo => "status/get-dump-info",

// Popularity endpoints
Self::PopularityTopRecordingsForArtist(artist) => return write!(f, "popularity/top-recordings-for-artist/{artist}"),
Self::PopularityTopReleaseGroupsForArtist(artist) => return write!(f, "popularity/top-release-groups-for-artist/{artist}"),
Self::PopularityRecording => "popularity/recording",
Self::PopularityArtist => "popularity/artist",
Self::PopularityRelease => "popularity/release",
Self::PopularityReleaseGroup => "popularity/release-group",
};
write!(f, "{s}")
}
Expand Down
78 changes: 76 additions & 2 deletions src/raw/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use std::collections::HashMap;

use attohttpc::Response;
use serde::de::DeserializeOwned;
use serde::Deserialize;
use serde::{Deserialize, Serialize};

use crate::Error;

Expand All @@ -21,7 +21,7 @@ use crate::Error;
/// as the former is resilient against clients with incorrect clocks.
///
/// [API docs]: https://listenbrainz.readthedocs.io/en/production/dev/api/#rate-limiting
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct RateLimit {
pub limit: u64,
pub remaining: u64,
Expand Down Expand Up @@ -107,6 +107,27 @@ macro_rules! response_type {
}
}

/// A generic response type for listenbrainz responses
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct ListenbrainzResponse<T> {
pub rate_limit: Option<RateLimit>,
pub data: T
}

impl<T> ResponseType for ListenbrainzResponse<T> where T: DeserializeOwned {
fn from_response(response: Response) -> Result<Self, Error> {
let response = Error::try_from_error_response(response)?;

let rate_limit = RateLimit::from_headers(&response);
let mut inner_data: T = response.json()?;

Ok(Self {
rate_limit,
data: inner_data,
})
}
}

// --------- submit-listens

response_type! {
Expand Down Expand Up @@ -544,3 +565,56 @@ pub struct StatsReleaseGroupListenersListeners {
pub username_name: String,
}

// ---------- Popularity Endpoints Responses

// ---------- popularity/top-recordings-for-artist/(artist_mbid)
pub type PopularityTopRecordingsForArtistResponse = Vec<PopularityTopRecordingsForArtistResponseItem>;

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct PopularityTopRecordingsForArtistResponseItem {
pub artist_mbids: Vec<String>,
pub artist_name: String,
pub caa_id: Option<i64>,
pub caa_release_mbid: Option<String>,
pub length: u64,
pub recording_mbid: String,
pub recording_name: String,
pub release_color: ReleaseColor,
pub release_mbid: String,
pub total_listen_count: u64,
pub total_user_count: u64
}

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct ReleaseColor {
blue: u8,
green: u8,
red: u8
}

// ---------- popularity/top-release-groups-for-artist/(artist_mbid)

// TODO

// ---------- popularity/recording

pub type PopularityRecordingResponse = Vec<PopularityTopRecordingsForArtistResponseItem>;

#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct PopularityRecordingResponseItem {
pub recording_mbid: String,
pub total_listen_count: u64,
pub total_user_count: u64
}

// ---------- popularity/artist

// TODO

// ---------- popularity/release

// TODO

// ---------- popularity/release-grou

// TODO

0 comments on commit f9d05fc

Please sign in to comment.