Specified API errors
This commit is contained in:
parent
1484ecabe9
commit
eaec68dff0
5 changed files with 140 additions and 79 deletions
|
@ -15,6 +15,8 @@
|
|||
- Additional metadata fields are now indexed: lyricist, composer, genre and label (thanks @pmphfm)
|
||||
- Endpoints returning thumbnail images or audio files no longer use HTTP `content-encoding`
|
||||
- The `/thumbnail` endpoint now supports an optional parameter for small/large/native image sizing. (thanks @Saecki)
|
||||
- Log file now contain more details about the cause of failed HTTP requests (3xx, 4xx, 5xx)
|
||||
- Startup errors emit clearer messages
|
||||
|
||||
### Web client
|
||||
|
||||
|
|
|
@ -8,12 +8,12 @@ use crate::db::{self, misc_settings, DB};
|
|||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Auth secret does not have the expected format")]
|
||||
AuthenticationSecretInvalid,
|
||||
#[error("Missing auth secret")]
|
||||
AuthSecretNotFound,
|
||||
AuthenticationSecretNotFound,
|
||||
#[error(transparent)]
|
||||
DatabaseConnection(#[from] db::Error),
|
||||
#[error("Auth secret does not have the expected format")]
|
||||
InvalidAuthSecret,
|
||||
#[error("Missing settings")]
|
||||
MiscSettingsNotFound,
|
||||
#[error("Index album art pattern is not a valid regex")]
|
||||
|
@ -56,12 +56,12 @@ impl Manager {
|
|||
.select(auth_secret)
|
||||
.get_result(&mut connection)
|
||||
.map_err(|e| match e {
|
||||
diesel::result::Error::NotFound => Error::AuthSecretNotFound,
|
||||
diesel::result::Error::NotFound => Error::AuthenticationSecretNotFound,
|
||||
e => e.into(),
|
||||
})?;
|
||||
secret
|
||||
.try_into()
|
||||
.map_err(|_| Error::InvalidAuthSecret)
|
||||
.map_err(|_| Error::AuthenticationSecretInvalid)
|
||||
.map(|key| AuthSecret { key })
|
||||
}
|
||||
|
||||
|
|
|
@ -11,16 +11,16 @@ use crate::utils::{get_audio_format, AudioFormat};
|
|||
pub enum Error {
|
||||
#[error("No embedded artwork was found in `{0}`")]
|
||||
EmbeddedArtworkNotFound(PathBuf),
|
||||
#[error(transparent)]
|
||||
Id3(#[from] id3::Error),
|
||||
#[error(transparent)]
|
||||
Image(#[from] image::error::ImageError),
|
||||
#[error("Could not read thumbnail from ID3 tag in `{0}`:\n\n{1}")]
|
||||
Id3(PathBuf, id3::Error),
|
||||
#[error("Could not read thumbnail image in `{0}`:\n\n{1}")]
|
||||
Image(PathBuf, image::error::ImageError),
|
||||
#[error("Filesystem error for `{0}`: `{1}`")]
|
||||
Io(PathBuf, std::io::Error),
|
||||
#[error(transparent)]
|
||||
Metaflac(#[from] metaflac::Error),
|
||||
#[error(transparent)]
|
||||
Mp4aMeta(#[from] mp4ameta::Error),
|
||||
#[error("Could not read thumbnail from flac file in `{0}`:\n\n{1}")]
|
||||
Metaflac(PathBuf, metaflac::Error),
|
||||
#[error("Could not read thumbnail from mp4 file in `{0}`:\n\n{1}")]
|
||||
Mp4aMeta(PathBuf, mp4ameta::Error),
|
||||
#[error("This file format is not supported: {0}")]
|
||||
UnsupportedFormat(&'static str),
|
||||
}
|
||||
|
@ -94,7 +94,9 @@ impl Manager {
|
|||
let path = self.get_thumbnail_path(image_path, thumbnailoptions);
|
||||
let mut out_file =
|
||||
File::create(&path).map_err(|e| Error::Io(self.thumbnails_dir_path.clone(), e))?;
|
||||
thumbnail.write_to(&mut out_file, ImageOutputFormat::Jpeg(quality))?;
|
||||
thumbnail
|
||||
.write_to(&mut out_file, ImageOutputFormat::Jpeg(quality))
|
||||
.map_err(|e| Error::Image(image_path.to_owned(), e))?;
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
|
@ -130,11 +132,13 @@ fn generate_thumbnail(image_path: &Path, options: &Options) -> Result<DynamicIma
|
|||
out_dimension,
|
||||
background,
|
||||
));
|
||||
final_image.copy_from(
|
||||
&scaled_image,
|
||||
(out_dimension - scaled_width) / 2,
|
||||
(out_dimension - scaled_height) / 2,
|
||||
)?;
|
||||
final_image
|
||||
.copy_from(
|
||||
&scaled_image,
|
||||
(out_dimension - scaled_width) / 2,
|
||||
(out_dimension - scaled_height) / 2,
|
||||
)
|
||||
.map_err(|e| Error::Image(image_path.to_owned(), e))?;
|
||||
} else {
|
||||
final_image = source_image.thumbnail(out_dimension, out_dimension);
|
||||
}
|
||||
|
@ -153,7 +157,7 @@ fn read(image_path: &Path) -> Result<DynamicImage, Error> {
|
|||
Some(AudioFormat::OGG) => read_vorbis(image_path),
|
||||
Some(AudioFormat::OPUS) => read_opus(image_path),
|
||||
Some(AudioFormat::WAVE) => read_wave(image_path),
|
||||
None => Ok(image::open(image_path)?),
|
||||
None => image::open(image_path).map_err(|e| Error::Image(image_path.to_owned(), e)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,40 +166,44 @@ fn read_ape(_: &Path) -> Result<DynamicImage, Error> {
|
|||
}
|
||||
|
||||
fn read_flac(path: &Path) -> Result<DynamicImage, Error> {
|
||||
let tag = metaflac::Tag::read_from_path(path)?;
|
||||
let tag =
|
||||
metaflac::Tag::read_from_path(path).map_err(|e| Error::Metaflac(path.to_owned(), e))?;
|
||||
if let Some(p) = tag.pictures().next() {
|
||||
return Ok(image::load_from_memory(&p.data)?);
|
||||
return image::load_from_memory(&p.data).map_err(|e| Error::Image(path.to_owned(), e));
|
||||
}
|
||||
Err(Error::EmbeddedArtworkNotFound(path.to_owned()))
|
||||
}
|
||||
|
||||
fn read_mp3(path: &Path) -> Result<DynamicImage, Error> {
|
||||
let tag = id3::Tag::read_from_path(path)?;
|
||||
let tag = id3::Tag::read_from_path(path).map_err(|e| Error::Id3(path.to_owned(), e))?;
|
||||
read_id3(path, &tag)
|
||||
}
|
||||
|
||||
fn read_aiff(path: &Path) -> Result<DynamicImage, Error> {
|
||||
let tag = id3::Tag::read_from_aiff_path(path)?;
|
||||
let tag = id3::Tag::read_from_aiff_path(path).map_err(|e| Error::Id3(path.to_owned(), e))?;
|
||||
read_id3(path, &tag)
|
||||
}
|
||||
|
||||
fn read_wave(path: &Path) -> Result<DynamicImage, Error> {
|
||||
let tag = id3::Tag::read_from_wav_path(path)?;
|
||||
let tag = id3::Tag::read_from_wav_path(path).map_err(|e| Error::Id3(path.to_owned(), e))?;
|
||||
read_id3(path, &tag)
|
||||
}
|
||||
|
||||
fn read_id3(path: &Path, tag: &id3::Tag) -> Result<DynamicImage, Error> {
|
||||
if let Some(p) = tag.pictures().next() {
|
||||
return Ok(image::load_from_memory(&p.data)?);
|
||||
}
|
||||
Err(Error::EmbeddedArtworkNotFound(path.to_owned()))
|
||||
tag.pictures()
|
||||
.next()
|
||||
.ok_or_else(|| Error::EmbeddedArtworkNotFound(path.to_owned()))
|
||||
.and_then(|d| {
|
||||
image::load_from_memory(&d.data).map_err(|e| Error::Image(path.to_owned(), e))
|
||||
})
|
||||
}
|
||||
|
||||
fn read_mp4(path: &Path) -> Result<DynamicImage, Error> {
|
||||
let tag = mp4ameta::Tag::read_from_path(path)?;
|
||||
let tag =
|
||||
mp4ameta::Tag::read_from_path(path).map_err(|e| Error::Mp4aMeta(path.to_owned(), e))?;
|
||||
tag.artwork()
|
||||
.and_then(|d| image::load_from_memory(d.data).ok())
|
||||
.ok_or_else(|| Error::EmbeddedArtworkNotFound(path.to_owned()))
|
||||
.and_then(|d| image::load_from_memory(d.data).map_err(|e| Error::Image(path.to_owned(), e)))
|
||||
}
|
||||
|
||||
fn read_vorbis(_: &Path) -> Result<DynamicImage, Error> {
|
||||
|
|
|
@ -73,22 +73,40 @@ pub fn make_config() -> impl FnOnce(&mut ServiceConfig) + Clone {
|
|||
impl ResponseError for APIError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
APIError::AuthorizationTokenEncoding => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::AdminPermissionRequired => StatusCode::UNAUTHORIZED,
|
||||
APIError::AudioFileIOError => StatusCode::NOT_FOUND,
|
||||
APIError::AuthenticationRequired => StatusCode::UNAUTHORIZED,
|
||||
APIError::BrancaTokenEncoding => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::DdnsUpdateQueryFailed(s) => {
|
||||
StatusCode::from_u16(*s).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
APIError::Database(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::DeletingOwnAccount => StatusCode::CONFLICT,
|
||||
APIError::EmbeddedArtworkNotFound => StatusCode::NOT_FOUND,
|
||||
APIError::EmptyPassword => StatusCode::BAD_REQUEST,
|
||||
APIError::EmptyUsername => StatusCode::BAD_REQUEST,
|
||||
APIError::IncorrectCredentials => StatusCode::UNAUTHORIZED,
|
||||
APIError::Internal => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::Io(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::LastFMAccountNotLinked => StatusCode::NO_CONTENT,
|
||||
APIError::LastFMLinkContentBase64DecodeError => StatusCode::BAD_REQUEST,
|
||||
APIError::LastFMLinkContentEncodingError => StatusCode::BAD_REQUEST,
|
||||
APIError::LastFMNowPlaying(_) => StatusCode::FAILED_DEPENDENCY,
|
||||
APIError::LastFMScrobble(_) => StatusCode::FAILED_DEPENDENCY,
|
||||
APIError::LastFMScrobblerAuthentication(_) => StatusCode::FAILED_DEPENDENCY,
|
||||
APIError::OwnAdminPrivilegeRemoval => StatusCode::CONFLICT,
|
||||
APIError::PasswordHashing => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::PlaylistNotFound => StatusCode::NOT_FOUND,
|
||||
APIError::Settings(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::SongMetadataNotFound => StatusCode::NOT_FOUND,
|
||||
APIError::ThumbnailFlacDecoding(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::ThumbnailFileIOError => StatusCode::NOT_FOUND,
|
||||
APIError::ThumbnailId3Decoding(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::ThumbnailImageDecoding(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::ThumbnailMp4Decoding(_, _) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::TomlDeserialization(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::UnsupportedThumbnailFormat(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
APIError::UserNotFound => StatusCode::NOT_FOUND,
|
||||
APIError::VFSPathNotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::path::PathBuf;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::app::index::QueryError;
|
||||
|
@ -6,51 +7,83 @@ use crate::db;
|
|||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum APIError {
|
||||
#[error("Could not encode authorization token")]
|
||||
AuthorizationTokenEncoding,
|
||||
#[error("Administrator permission is required")]
|
||||
AdminPermissionRequired,
|
||||
#[error("Audio file could not be opened")]
|
||||
AudioFileIOError,
|
||||
#[error("Authentication is required")]
|
||||
AuthenticationRequired,
|
||||
#[error("Incorrect Credentials")]
|
||||
IncorrectCredentials,
|
||||
#[error("Could not encode Branca token")]
|
||||
BrancaTokenEncoding,
|
||||
#[error("Database error:\n\n{0}")]
|
||||
Database(diesel::result::Error),
|
||||
#[error("DDNS update query failed with HTTP status {0}")]
|
||||
DdnsUpdateQueryFailed(u16),
|
||||
#[error("Cannot delete your own account")]
|
||||
DeletingOwnAccount,
|
||||
#[error("EmbeddedArtworkNotFound")]
|
||||
EmbeddedArtworkNotFound,
|
||||
#[error("EmptyUsername")]
|
||||
EmptyUsername,
|
||||
#[error("EmptyPassword")]
|
||||
EmptyPassword,
|
||||
#[error("Cannot delete your own account")]
|
||||
DeletingOwnAccount,
|
||||
#[error("Cannot remove your own admin privilege")]
|
||||
OwnAdminPrivilegeRemoval,
|
||||
#[error("Audio file could not be opened")]
|
||||
AudioFileIOError,
|
||||
#[error("Thumbnail file could not be opened")]
|
||||
ThumbnailFileIOError,
|
||||
#[error("Incorrect Credentials")]
|
||||
IncorrectCredentials,
|
||||
#[error("No last.fm account has been linked")]
|
||||
LastFMAccountNotLinked,
|
||||
#[error("Could not decode content as base64 after linking last.fm account")]
|
||||
LastFMLinkContentBase64DecodeError,
|
||||
#[error("Could not decode content as UTF-8 after linking last.fm account")]
|
||||
LastFMLinkContentEncodingError,
|
||||
#[error("Path not found in virtual filesystem")]
|
||||
VFSPathNotFound,
|
||||
#[error("User not found")]
|
||||
UserNotFound,
|
||||
#[error("Playlist not found")]
|
||||
PlaylistNotFound,
|
||||
#[error("Song not found")]
|
||||
SongMetadataNotFound,
|
||||
#[error("Could send Now Playing update to last.fm:\n\n{0}")]
|
||||
LastFMNowPlaying(rustfm_scrobble::ScrobblerError),
|
||||
#[error("Could emit scrobble with last.fm:\n\n{0}")]
|
||||
LastFMScrobble(rustfm_scrobble::ScrobblerError),
|
||||
#[error("Could authenticate with last.fm:\n\n{0}")]
|
||||
LastFMScrobblerAuthentication(rustfm_scrobble::ScrobblerError),
|
||||
#[error("Internal server error")]
|
||||
Internal,
|
||||
#[error("File I/O error for `{0}`:\n\n{1}")]
|
||||
Io(PathBuf, std::io::Error),
|
||||
#[error("Cannot remove your own admin privilege")]
|
||||
OwnAdminPrivilegeRemoval,
|
||||
#[error("Could not hash password")]
|
||||
PasswordHashing,
|
||||
#[error("Playlist not found")]
|
||||
PlaylistNotFound,
|
||||
#[error("Settings error:\n\n{0}")]
|
||||
Settings(settings::Error),
|
||||
#[error("Song not found")]
|
||||
SongMetadataNotFound,
|
||||
#[error("Could not decode thumbnail from flac file `{0}`:\n\n{1}")]
|
||||
ThumbnailFlacDecoding(PathBuf, metaflac::Error),
|
||||
#[error("Thumbnail file could not be opened")]
|
||||
ThumbnailFileIOError,
|
||||
#[error("Could not decode thumbnail from ID3 tag in `{0}`:\n\n{1}")]
|
||||
ThumbnailId3Decoding(PathBuf, id3::Error),
|
||||
#[error("Could not decode image thumbnail in `{0}`:\n\n{1}")]
|
||||
ThumbnailImageDecoding(PathBuf, image::error::ImageError),
|
||||
#[error("Could not decode thumbnail from mp4 file `{0}`:\n\n{1}")]
|
||||
ThumbnailMp4Decoding(PathBuf, mp4ameta::Error),
|
||||
#[error("Toml deserialization error:\n\n{0}")]
|
||||
TomlDeserialization(toml::de::Error),
|
||||
#[error("Unsupported thumbnail format: `{0}`")]
|
||||
UnsupportedThumbnailFormat(&'static str),
|
||||
#[error("User not found")]
|
||||
UserNotFound,
|
||||
#[error("Path not found in virtual filesystem")]
|
||||
VFSPathNotFound,
|
||||
}
|
||||
|
||||
impl From<config::Error> for APIError {
|
||||
fn from(error: config::Error) -> APIError {
|
||||
match error {
|
||||
config::Error::Ddns(e) => e.into(),
|
||||
config::Error::Io(_, _) => APIError::Internal,
|
||||
config::Error::Io(p, e) => APIError::Io(p, e),
|
||||
config::Error::Settings(e) => e.into(),
|
||||
config::Error::Toml(_) => APIError::Internal,
|
||||
config::Error::Toml(e) => APIError::TomlDeserialization(e),
|
||||
config::Error::User(e) => e.into(),
|
||||
config::Error::Vfs(e) => e.into(),
|
||||
}
|
||||
|
@ -60,7 +93,7 @@ impl From<config::Error> for APIError {
|
|||
impl From<playlist::Error> for APIError {
|
||||
fn from(error: playlist::Error) -> APIError {
|
||||
match error {
|
||||
playlist::Error::Database(_) => APIError::Internal,
|
||||
playlist::Error::Database(e) => APIError::Database(e),
|
||||
playlist::Error::DatabaseConnection(e) => e.into(),
|
||||
playlist::Error::PlaylistNotFound => APIError::PlaylistNotFound,
|
||||
playlist::Error::UserNotFound => APIError::UserNotFound,
|
||||
|
@ -72,7 +105,7 @@ impl From<playlist::Error> for APIError {
|
|||
impl From<QueryError> for APIError {
|
||||
fn from(error: QueryError) -> APIError {
|
||||
match error {
|
||||
QueryError::Database(_) => APIError::Internal,
|
||||
QueryError::Database(e) => APIError::Database(e),
|
||||
QueryError::DatabaseConnection(e) => e.into(),
|
||||
QueryError::SongNotFound(_) => APIError::SongMetadataNotFound,
|
||||
QueryError::Vfs(e) => e.into(),
|
||||
|
@ -83,12 +116,12 @@ impl From<QueryError> for APIError {
|
|||
impl From<settings::Error> for APIError {
|
||||
fn from(error: settings::Error) -> APIError {
|
||||
match error {
|
||||
settings::Error::AuthSecretNotFound => APIError::Internal,
|
||||
settings::Error::AuthenticationSecretNotFound => APIError::Settings(error),
|
||||
settings::Error::DatabaseConnection(e) => e.into(),
|
||||
settings::Error::InvalidAuthSecret => APIError::Internal,
|
||||
settings::Error::MiscSettingsNotFound => APIError::Internal,
|
||||
settings::Error::IndexAlbumArtPatternInvalid => APIError::Internal,
|
||||
settings::Error::Database(_) => APIError::Internal,
|
||||
settings::Error::AuthenticationSecretInvalid => APIError::Settings(error),
|
||||
settings::Error::MiscSettingsNotFound => APIError::Settings(error),
|
||||
settings::Error::IndexAlbumArtPatternInvalid => APIError::Settings(error),
|
||||
settings::Error::Database(e) => APIError::Database(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,18 +129,18 @@ impl From<settings::Error> for APIError {
|
|||
impl From<user::Error> for APIError {
|
||||
fn from(error: user::Error) -> APIError {
|
||||
match error {
|
||||
user::Error::AuthorizationTokenEncoding => APIError::Internal,
|
||||
user::Error::BrancaTokenEncoding => APIError::Internal,
|
||||
user::Error::Database(_) => APIError::Internal,
|
||||
user::Error::AuthorizationTokenEncoding => APIError::AuthorizationTokenEncoding,
|
||||
user::Error::BrancaTokenEncoding => APIError::BrancaTokenEncoding,
|
||||
user::Error::Database(e) => APIError::Database(e),
|
||||
user::Error::DatabaseConnection(e) => e.into(),
|
||||
user::Error::EmptyUsername => APIError::EmptyUsername,
|
||||
user::Error::EmptyPassword => APIError::EmptyPassword,
|
||||
user::Error::IncorrectUsername => APIError::IncorrectCredentials,
|
||||
user::Error::IncorrectPassword => APIError::IncorrectCredentials,
|
||||
user::Error::InvalidAuthToken => APIError::IncorrectCredentials,
|
||||
user::Error::EmptyUsername => APIError::EmptyUsername,
|
||||
user::Error::IncorrectAuthorizationScope => APIError::IncorrectCredentials,
|
||||
user::Error::PasswordHashing => APIError::Internal,
|
||||
user::Error::IncorrectPassword => APIError::IncorrectCredentials,
|
||||
user::Error::IncorrectUsername => APIError::IncorrectCredentials,
|
||||
user::Error::InvalidAuthToken => APIError::IncorrectCredentials,
|
||||
user::Error::MissingLastFMSessionKey => APIError::IncorrectCredentials,
|
||||
user::Error::PasswordHashing => APIError::PasswordHashing,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +150,7 @@ impl From<vfs::Error> for APIError {
|
|||
match error {
|
||||
vfs::Error::CouldNotMapToVirtualPath(_) => APIError::VFSPathNotFound,
|
||||
vfs::Error::CouldNotMapToRealPath(_) => APIError::VFSPathNotFound,
|
||||
vfs::Error::Database(_) => APIError::Internal,
|
||||
vfs::Error::Database(e) => APIError::Database(e),
|
||||
vfs::Error::DatabaseConnection(e) => e.into(),
|
||||
}
|
||||
}
|
||||
|
@ -126,9 +159,9 @@ impl From<vfs::Error> for APIError {
|
|||
impl From<ddns::Error> for APIError {
|
||||
fn from(error: ddns::Error) -> APIError {
|
||||
match error {
|
||||
ddns::Error::Database(_) => APIError::Internal,
|
||||
ddns::Error::Database(e) => APIError::Database(e),
|
||||
ddns::Error::DatabaseConnection(e) => e.into(),
|
||||
ddns::Error::UpdateQueryFailed(_) => APIError::Internal,
|
||||
ddns::Error::UpdateQueryFailed(s) => APIError::DdnsUpdateQueryFailed(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,7 +171,7 @@ impl From<db::Error> for APIError {
|
|||
match error {
|
||||
db::Error::ConnectionPoolBuild => APIError::Internal,
|
||||
db::Error::ConnectionPool => APIError::Internal,
|
||||
db::Error::Io(_, _) => APIError::Internal,
|
||||
db::Error::Io(p, e) => APIError::Io(p, e),
|
||||
db::Error::Migration => APIError::Internal,
|
||||
}
|
||||
}
|
||||
|
@ -147,9 +180,9 @@ impl From<db::Error> for APIError {
|
|||
impl From<lastfm::Error> for APIError {
|
||||
fn from(error: lastfm::Error) -> APIError {
|
||||
match error {
|
||||
lastfm::Error::ScrobblerAuthentication(_) => APIError::Internal,
|
||||
lastfm::Error::Scrobble(_) => APIError::Internal,
|
||||
lastfm::Error::NowPlaying(_) => APIError::Internal,
|
||||
lastfm::Error::ScrobblerAuthentication(e) => APIError::LastFMScrobblerAuthentication(e),
|
||||
lastfm::Error::Scrobble(e) => APIError::LastFMScrobble(e),
|
||||
lastfm::Error::NowPlaying(e) => APIError::LastFMNowPlaying(e),
|
||||
lastfm::Error::Query(e) => e.into(),
|
||||
lastfm::Error::User(e) => e.into(),
|
||||
}
|
||||
|
@ -160,12 +193,12 @@ impl From<thumbnail::Error> for APIError {
|
|||
fn from(error: thumbnail::Error) -> APIError {
|
||||
match error {
|
||||
thumbnail::Error::EmbeddedArtworkNotFound(_) => APIError::EmbeddedArtworkNotFound,
|
||||
thumbnail::Error::Id3(_) => APIError::Internal,
|
||||
thumbnail::Error::Image(_) => APIError::Internal,
|
||||
thumbnail::Error::Io(_, _) => APIError::Internal,
|
||||
thumbnail::Error::Metaflac(_) => APIError::Internal,
|
||||
thumbnail::Error::Mp4aMeta(_) => APIError::Internal,
|
||||
thumbnail::Error::UnsupportedFormat(_) => APIError::Internal,
|
||||
thumbnail::Error::Id3(p, e) => APIError::ThumbnailId3Decoding(p, e),
|
||||
thumbnail::Error::Image(p, e) => APIError::ThumbnailImageDecoding(p, e),
|
||||
thumbnail::Error::Io(p, e) => APIError::Io(p, e),
|
||||
thumbnail::Error::Metaflac(p, e) => APIError::ThumbnailFlacDecoding(p, e),
|
||||
thumbnail::Error::Mp4aMeta(p, e) => APIError::ThumbnailMp4Decoding(p, e),
|
||||
thumbnail::Error::UnsupportedFormat(f) => APIError::UnsupportedThumbnailFormat(f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue