pandora_api/json/
errors.rs

1/*!
2Error codes that can be returned by the Pandora API.
3*/
4// SPDX-License-Identifier: MIT AND WTFPL
5
6/// https://6xq.net/pandora-apidoc/json/errorcodes/
7#[derive(Debug, Clone, Copy, PartialEq)]
8pub enum JsonErrorKind {
9    /// Code 0 - Internal error. It can denote that your account has been temporarily blocked due to having
10    /// too frequent station.getPlaylist calls.
11    InternalError,
12    /// Code 1 - MAINTENANCE_MODE
13    MaintenanceMode,
14    /// Code 2 - URL_PARAM_MISSING_METHOD
15    UrlParamMissingMethod,
16    /// Code 3 - URL_PARAM_MISSING_AUTH_TOKEN
17    UrlParamMissingAuthToken,
18    /// Code 4 - URL_PARAM_MISSING_PARTNER_ID
19    UrlParamMissingPartnerId,
20    /// Code 5 - URL_PARAM_MISSING_USER_ID
21    UrlParamMissingUserId,
22    /// Code 6 - SECURE_PROTOCOL_REQUIRED
23    SecureProtocolRequired,
24    /// Code 7 - CERTIFICATE_REQUIRED
25    CertificateRequired,
26    /// Code 8 - PARAMETER_TYPE_MISMATCH
27    ParameterTypeMismatch,
28    /// Code 9 - PARAMETER_MISSING. Usually occurs when one or more required parameters are missing
29    /// for the method called.
30    ParameterMissing,
31    /// Code 10 - PARAMETER_VALUE_INVALID
32    ParameterValueInvalid,
33    /// Code 11 - API_VERSION_NOT_SUPPORTED
34    ApiVersionNotSupported,
35    /// Code 12 - LICENSING_RESTRICTIONS. Pandora not available in this country.
36    LicensingRestrictions,
37    /// Code 13 - INSUFFICIENT_CONNECTIVITY. Bad sync time?
38    InsufficientConnectivity,
39    /// Code 14 - Unknown method name?
40    UnknownMethodName,
41    /// Code 15 - Wrong protocol (http/https)?
42    WrongProtocol,
43    /// Code 1000 - READ_ONLY_MODE
44    ReadOnlyMode,
45    /// Code 1001 - INVALID_AUTH_TOKEN. Occurs once a user auth token expires.
46    InvalidAuthToken,
47    /// Code 1002 - INVALID_PARTNER_LOGIN. auth.partnerLogin auth.userLogin. Can also occur for a
48    /// user login.
49    InvalidPartnerLogin,
50    /// Code 1003 - LISTENER_NOT_AUTHORIZED. station.getPlaylist - Pandora One Subscription or
51    /// Trial Expired. Possibly account suspended?
52    ListenerNotAuthorized,
53    /// Code 1004 - USER_NOT_AUTHORIZED. User not authorized to perform action. Is your station
54    /// token correct?
55    UserNotAuthorized,
56    /// Code 1005 - MAX_STATIONS_REACHED. Station limit reached.
57    MaxStationsReached,
58    /// Code 1006 - STATION_DOES_NOT_EXIST. Station does not exist.
59    StationDoesNotExist,
60    /// Code 1007 - COMPLIMENTARY_PERIOD_ALREADY_IN_USE
61    ComplimentaryPeriodAlreadyInUse,
62    /// Code 1008 - CALL_NOT_ALLOWED. station.addFeedback - Returned when attempting to add
63    /// feedback to shared station.
64    CallNotAllowed,
65    /// Code 1009 - DEVICE_NOT_FOUND
66    DeviceNotFound,
67    /// Code 1010 - PARTNER_NOT_AUTHORIZED
68    PartnerNotAuthorized,
69    /// Code 1011 - INVALID_USERNAME
70    InvalidUsername,
71    /// Code 1012 - INVALID_PASSWORD
72    InvalidPassword,
73    /// Code 1013 - USERNAME_ALREADY_EXISTS
74    UsernameAlreadyExists,
75    /// Code 1014 - DEVICE_ALREADY_ASSOCIATED_TO_ACCOUNT
76    DeviceAlreadyAssociatedToAccount,
77    /// Code 1015 - UPGRADE_DEVICE_MODEL_INVALID
78    UpgradeDeviceModelInvalid,
79    /// Code 1018 - EXPLICIT_PIN_INCORRECT
80    ExplicitPinIncorrect,
81    /// Code 1020 - EXPLICIT_PIN_MALFORMED
82    ExplicitPinMalformed,
83    /// Code 1023 - DEVICE_MODEL_INVALID
84    DeviceModelInvalid,
85    /// Code 1024 - ZIP_CODE_INVALID
86    ZipCodeInvalid,
87    /// Code 1025 - BIRTH_YEAR_INVALID
88    BirthYearInvalid,
89    /// Code 1026 - BIRTH_YEAR_TOO_YOUNG
90    BirthYearTooYoung,
91    /// Code 1027 - INVALID_COUNTRY_CODE
92    InvalidCountryCode,
93    /// Code 1027 - INVALID_GENDER
94    InvalidGender,
95    /// Code 1034 - DEVICE_DISABLED
96    DeviceDisabled,
97    /// Code 1035 - DAILY_TRIAL_LIMIT_REACHED
98    DailyTrialLimitReached,
99    /// Code 1036 - INVALID_SPONSOR
100    InvalidSponsor,
101    /// Code 1037 - USER_ALREADY_USED_TRIAL
102    UserAlreadyUsedTrial,
103    /// Code 1039 - PLAYLIST_EXCEEDED. Too many requests for a new playlist.
104    PlaylistExceeded,
105    /// Undocumented error code
106    UnknownErrorCode(u32),
107    /// No error code provided
108    UnknownErrorMessage,
109}
110
111impl From<u32> for JsonErrorKind {
112    /// Create a JsonError from an error code.
113    fn from(code: u32) -> Self {
114        match code {
115            0 => JsonErrorKind::InternalError,
116            1 => JsonErrorKind::MaintenanceMode,
117            2 => JsonErrorKind::UrlParamMissingMethod,
118            3 => JsonErrorKind::UrlParamMissingAuthToken,
119            4 => JsonErrorKind::UrlParamMissingPartnerId,
120            5 => JsonErrorKind::UrlParamMissingUserId,
121            6 => JsonErrorKind::SecureProtocolRequired,
122            7 => JsonErrorKind::CertificateRequired,
123            8 => JsonErrorKind::ParameterTypeMismatch,
124            9 => JsonErrorKind::ParameterMissing,
125            10 => JsonErrorKind::ParameterValueInvalid,
126            11 => JsonErrorKind::ApiVersionNotSupported,
127            12 => JsonErrorKind::LicensingRestrictions,
128            13 => JsonErrorKind::InsufficientConnectivity,
129            14 => JsonErrorKind::UnknownMethodName,
130            15 => JsonErrorKind::WrongProtocol,
131            1000 => JsonErrorKind::ReadOnlyMode,
132            1001 => JsonErrorKind::InvalidAuthToken,
133            1002 => JsonErrorKind::InvalidPartnerLogin,
134            1003 => JsonErrorKind::ListenerNotAuthorized,
135            1004 => JsonErrorKind::UserNotAuthorized,
136            1005 => JsonErrorKind::MaxStationsReached,
137            1006 => JsonErrorKind::StationDoesNotExist,
138            1007 => JsonErrorKind::ComplimentaryPeriodAlreadyInUse,
139            1008 => JsonErrorKind::CallNotAllowed,
140            1009 => JsonErrorKind::DeviceNotFound,
141            1010 => JsonErrorKind::PartnerNotAuthorized,
142            1011 => JsonErrorKind::InvalidUsername,
143            1012 => JsonErrorKind::InvalidPassword,
144            1013 => JsonErrorKind::UsernameAlreadyExists,
145            1014 => JsonErrorKind::DeviceAlreadyAssociatedToAccount,
146            1015 => JsonErrorKind::UpgradeDeviceModelInvalid,
147            1018 => JsonErrorKind::ExplicitPinIncorrect,
148            1020 => JsonErrorKind::ExplicitPinMalformed,
149            1023 => JsonErrorKind::DeviceModelInvalid,
150            1024 => JsonErrorKind::ZipCodeInvalid,
151            1025 => JsonErrorKind::BirthYearInvalid,
152            1026 => JsonErrorKind::BirthYearTooYoung,
153            /* TODO: these two error codes collide - verify value */
154            1027 => JsonErrorKind::InvalidCountryCode,
155            //1027 => JsonErrorKind::InvalidGender,
156            1034 => JsonErrorKind::DeviceDisabled,
157            1035 => JsonErrorKind::DailyTrialLimitReached,
158            1036 => JsonErrorKind::InvalidSponsor,
159            1037 => JsonErrorKind::UserAlreadyUsedTrial,
160            1039 => JsonErrorKind::PlaylistExceeded,
161            x => JsonErrorKind::UnknownErrorCode(x),
162        }
163    }
164}
165
166/*
167impl From<String> for JsonErrorKind {
168    /// Create an error message when there's no error code, only a text description.
169    fn from(_msg: String) -> Self {
170        JsonErrorKind::UnknownErrorMessage
171    }
172}
173*/
174
175impl std::fmt::Display for JsonErrorKind {
176    /// Format this type for display
177    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
178        match self {
179            // Seen in the wild, accompanied with a message "Service method not found"
180            JsonErrorKind::InternalError => write!(f, "Internal"),
181            JsonErrorKind::MaintenanceMode => write!(f, "Maintenance Mode"),
182            JsonErrorKind::UrlParamMissingMethod => write!(f, "Url Param Missing Method"),
183            JsonErrorKind::UrlParamMissingAuthToken => write!(f, "Url Param Missing Auth Token"),
184            JsonErrorKind::UrlParamMissingPartnerId => write!(f, "Url Param Missing Partner ID"),
185            JsonErrorKind::UrlParamMissingUserId => write!(f, "Url Param Missing User ID"),
186            JsonErrorKind::SecureProtocolRequired => write!(f, "Secure Protocol Required"),
187            JsonErrorKind::CertificateRequired => write!(f, "Certificate Required"),
188            JsonErrorKind::ParameterTypeMismatch => write!(f, "Parameter Type Mismatch"),
189            JsonErrorKind::ParameterMissing => write!(f, "Parameter Missing."),
190            JsonErrorKind::ParameterValueInvalid => write!(f, "Parameter Value Invalid"),
191            JsonErrorKind::ApiVersionNotSupported => write!(f, "API Version Not Supported"),
192            JsonErrorKind::LicensingRestrictions => write!(f, "Licensing Restriction"),
193            JsonErrorKind::InsufficientConnectivity => write!(f, "Insufficient Connectivity"),
194            JsonErrorKind::UnknownMethodName => write!(f, "Unknown Method Name"),
195            JsonErrorKind::WrongProtocol => write!(f, "Incorrect Protocol"),
196            JsonErrorKind::ReadOnlyMode => write!(f, "Read Only Mode"),
197            JsonErrorKind::InvalidAuthToken => write!(f, "Invalid Auth Token"),
198            JsonErrorKind::InvalidPartnerLogin => write!(f, "Invalid Partner Login"),
199            JsonErrorKind::ListenerNotAuthorized => write!(f, "Listener Not Authorized"),
200            JsonErrorKind::UserNotAuthorized => write!(f, "User Not Authorized"),
201            JsonErrorKind::MaxStationsReached => write!(f, "Max Stations Reached"),
202            JsonErrorKind::StationDoesNotExist => write!(f, "Station Does Not Exist"),
203            JsonErrorKind::ComplimentaryPeriodAlreadyInUse => {
204                write!(f, "Complimentary Period Already In Use")
205            }
206            JsonErrorKind::CallNotAllowed => write!(f, "Call Not Allowed"),
207            JsonErrorKind::DeviceNotFound => write!(f, "Device Not Found"),
208            JsonErrorKind::PartnerNotAuthorized => write!(f, "Partner Not Authorized"),
209            JsonErrorKind::InvalidUsername => write!(f, "Invalid Username"),
210            JsonErrorKind::InvalidPassword => write!(f, "Invalid Password"),
211            JsonErrorKind::UsernameAlreadyExists => write!(f, "Username Already Exists"),
212            JsonErrorKind::DeviceAlreadyAssociatedToAccount => {
213                write!(f, "Device Already Associated to Account")
214            }
215            JsonErrorKind::UpgradeDeviceModelInvalid => write!(f, "Upgrade Device Model Invalid"),
216            JsonErrorKind::ExplicitPinIncorrect => write!(f, "Explicit Pin Incorrect"),
217            JsonErrorKind::ExplicitPinMalformed => write!(f, "Explicit Pin Malformed"),
218            JsonErrorKind::DeviceModelInvalid => write!(f, "Device Model Invalid"),
219            JsonErrorKind::ZipCodeInvalid => write!(f, "Zip Code Invalid"),
220            JsonErrorKind::BirthYearInvalid => write!(f, "Birth Year Invalid"),
221            JsonErrorKind::BirthYearTooYoung => write!(f, "Birth Year Too Young"),
222            JsonErrorKind::InvalidCountryCode => write!(f, "Invalid Country Code"),
223            JsonErrorKind::InvalidGender => write!(f, "Invalid Gender"),
224            JsonErrorKind::DeviceDisabled => write!(f, "Device Disabled"),
225            JsonErrorKind::DailyTrialLimitReached => write!(f, "Daily Trial Limit Reached"),
226            JsonErrorKind::InvalidSponsor => write!(f, "Invalid Sponsor"),
227            JsonErrorKind::UserAlreadyUsedTrial => write!(f, "User Already Used Trial"),
228            JsonErrorKind::PlaylistExceeded => write!(
229                f,
230                "Playlist Exceeded. Too many requests for a new playlist."
231            ),
232            JsonErrorKind::UnknownErrorCode(x) => write!(f, "Unrecognized Error Code ({x})"),
233            JsonErrorKind::UnknownErrorMessage => write!(f, "Missing Error Code."),
234        }
235    }
236}
237
238/// Pandora JSON API call error description
239#[derive(Debug, Clone, PartialEq)]
240pub struct JsonError {
241    pub(crate) kind: JsonErrorKind,
242    pub(crate) message: Option<String>,
243}
244
245impl JsonError {
246    /// Initialize a JsonError from some combination of code and message.
247    pub fn new(code: Option<u32>, message: Option<String>) -> Self {
248        let kind = match code {
249            Some(code) => JsonErrorKind::from(code),
250            None => JsonErrorKind::UnknownErrorMessage,
251        };
252        JsonError { kind, message }
253    }
254
255    /// Return what kind of error this is.
256    pub fn kind(&self) -> JsonErrorKind {
257        self.kind
258    }
259}
260
261impl std::error::Error for JsonError {
262    /// Get the source error, if any, for this error.
263    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
264        None
265    }
266}
267
268impl std::fmt::Display for JsonError {
269    /// Format this error for display
270    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
271        write!(f, "Pandora API Call Error ({} Error)", self.kind)?;
272        if let Some(msg) = &self.message {
273            write!(f, ": {msg}")?;
274        }
275        Ok(())
276    }
277}