1use oauth2::basic::BasicErrorResponseType;
2use serde::Deserialize;
3use snafu::prelude::*;
4
5pub type Result<T, E = Error> = std::result::Result<T, E>;
7
8#[derive(Debug, Snafu)]
9#[snafu(visibility(pub(crate)))]
10pub enum Error {
11 NotAuthenticated,
13
14 ExpiredToken,
16
17 #[snafu(display(
21 "The supplied (CSRF) state parameter is not the same as the one sent to the authorisation server. Learn more about CSRF here: https://datatracker.ietf.org/doc/html/rfc6749#section-10.12"
22 ))]
23 InvalidStateParameter,
24
25 RefreshUnavailable,
27
28 NoRemainingPages,
30
31 #[snafu(display(
36 "Internal error: the client's PKCE verifier was missing when authenticating."
37 ))]
38 InvalidClientState,
39
40 InvalidResponse,
42
43 #[snafu(display("Error returned by the Spotify API: {status} {description}"))]
45 Spotify {
46 status: u16,
48 description: String,
50 },
51
52 #[snafu(display("An error ocurred during the authentication process."))]
53 Authentication {
54 source: OauthError,
55 },
56
57 #[snafu(display("{description}"))]
59 Parse {
60 description: String,
61 },
62
63 #[snafu(display("An error occurred during deserialization."))]
66 Deserialization {
67 source: serde_json::Error,
68 body: String,
69 },
70
71 #[snafu(display("An HTTP error occurred."))]
73 Http {
74 source: reqwest::Error,
75 },
76}
77
78#[derive(Deserialize)]
79pub(crate) struct SpotifyError {
80 error: Details,
81}
82
83#[derive(Deserialize)]
84struct Details {
85 status: u16,
86 message: String,
87}
88
89type OauthError = oauth2::RequestTokenError<
91 oauth2::reqwest::Error<reqwest::Error>,
92 oauth2::StandardErrorResponse<BasicErrorResponseType>,
93>;
94
95impl From<OauthError> for Error {
97 fn from(source: OauthError) -> Self {
98 Self::Authentication { source }
99 }
100}
101
102impl From<reqwest::Error> for Error {
104 fn from(source: reqwest::Error) -> Self {
105 Self::Http { source }
106 }
107}
108
109impl From<SpotifyError> for Error {
111 fn from(value: SpotifyError) -> Self {
112 Self::Spotify {
113 status: value.error.status,
114 description: value.error.message,
115 }
116 }
117}