You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
4.2 KiB
Rust
170 lines
4.2 KiB
Rust
use std::{borrow::Cow, fmt::Display};
|
|
|
|
use askama::Template;
|
|
use serde::{Deserialize, Serialize};
|
|
use time::{format_description::well_known::Rfc3339, OffsetDateTime};
|
|
|
|
use crate::{
|
|
providers::{
|
|
bandcamp::{BandcampArtistId, BandcampReleaseId},
|
|
spotify::SpotifyId,
|
|
Provider,
|
|
},
|
|
templates, Configuration,
|
|
};
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub(crate) struct FeedData {
|
|
pub(crate) artist: Artist,
|
|
pub(crate) releases: Vec<Release>,
|
|
pub(crate) retrieved_at: OffsetDateTime,
|
|
}
|
|
|
|
impl FeedData {
|
|
pub(crate) fn feed_id(&self) -> String {
|
|
let domain = &Configuration::get().http.domain;
|
|
format!(
|
|
"tag:{},2022:artist:{}:{}",
|
|
domain,
|
|
self.provider().id(),
|
|
self.artist_id(),
|
|
)
|
|
}
|
|
|
|
pub(crate) fn feed_url(&self) -> String {
|
|
let domain = &Configuration::get().http.domain;
|
|
format!(
|
|
"https://{}/releases/{}/{}",
|
|
domain,
|
|
self.provider().id(),
|
|
self.artist_id(),
|
|
)
|
|
}
|
|
|
|
pub(crate) fn provider(&self) -> Provider {
|
|
match &self.artist.id {
|
|
ArtistId::Spotify(_) => Provider::Spotify,
|
|
ArtistId::Bandcamp(_) => Provider::Bandcamp,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn retrieved_at(&self) -> String {
|
|
self.retrieved_at.format(&Rfc3339).unwrap()
|
|
}
|
|
|
|
pub(crate) fn feed_entries(&self) -> impl Iterator<Item = (&'_ Release, String)> {
|
|
self.releases.iter().map(|r| {
|
|
let entry_content = templates::FeedEntry::new(r).render().unwrap();
|
|
(r, entry_content)
|
|
})
|
|
}
|
|
|
|
fn artist_id(&self) -> &dyn Display {
|
|
match &self.artist.id {
|
|
ArtistId::Spotify(id) => id,
|
|
ArtistId::Bandcamp(id) => id,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub(crate) struct Artist {
|
|
pub(crate) name: String,
|
|
pub(crate) id: ArtistId,
|
|
}
|
|
|
|
impl Artist {
|
|
pub(crate) fn url(&self) -> Cow<'_, str> {
|
|
match &self.id {
|
|
ArtistId::Spotify(id) => Cow::Owned(format!("https://open.spotify.com/artist/{}", id)),
|
|
ArtistId::Bandcamp(id) => Cow::Owned(id.url()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub(crate) enum ArtistId {
|
|
Spotify(SpotifyId),
|
|
Bandcamp(BandcampArtistId),
|
|
}
|
|
|
|
impl ArtistId {
|
|
pub(crate) fn cache_key(&self) -> String {
|
|
format!("{}:{}", self.provider().id(), self.id())
|
|
}
|
|
|
|
fn provider(&self) -> Provider {
|
|
match self {
|
|
ArtistId::Spotify(_) => Provider::Spotify,
|
|
ArtistId::Bandcamp(_) => Provider::Bandcamp,
|
|
}
|
|
}
|
|
|
|
fn id(&self) -> &dyn Display {
|
|
match &self {
|
|
ArtistId::Spotify(id) => id,
|
|
ArtistId::Bandcamp(id) => id,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub(crate) struct Release {
|
|
pub(crate) id: ReleaseId,
|
|
pub(crate) name: String,
|
|
pub(crate) artists: Vec<Artist>,
|
|
pub(crate) release_date: OffsetDateTime,
|
|
pub(crate) cover_image: Option<String>,
|
|
}
|
|
|
|
impl Release {
|
|
pub(crate) fn entry_id(&self) -> String {
|
|
let domain = &Configuration::get().http.domain;
|
|
format!(
|
|
"tag:{},2022:release:{}:{}",
|
|
domain,
|
|
self.provider().id(),
|
|
self.id()
|
|
)
|
|
}
|
|
|
|
pub(crate) fn artists(&self) -> &[Artist] {
|
|
&self.artists
|
|
}
|
|
|
|
pub(crate) fn release_date(&self) -> String {
|
|
self.release_date.format(&Rfc3339).unwrap()
|
|
}
|
|
|
|
pub(crate) fn url(&self) -> String {
|
|
match &self.id {
|
|
ReleaseId::Spotify(id) => format!("https://open.spotify.com/album/{}", id),
|
|
ReleaseId::Bandcamp(id) => id.to_string(),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn provider(&self) -> Provider {
|
|
match &self.id {
|
|
ReleaseId::Spotify(_) => Provider::Spotify,
|
|
ReleaseId::Bandcamp(_) => Provider::Bandcamp,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn cover_art(&self) -> Option<&str> {
|
|
self.cover_image.as_deref()
|
|
}
|
|
|
|
fn id(&self) -> &dyn Display {
|
|
match &self.id {
|
|
ReleaseId::Spotify(id) => id,
|
|
ReleaseId::Bandcamp(id) => id,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub(crate) enum ReleaseId {
|
|
Spotify(SpotifyId),
|
|
Bandcamp(BandcampReleaseId),
|
|
}
|