wp_mini/error.rs
1//! Defines the primary error handling types for the library.
2//!
3//! This module contains the central `WattpadError` enum, which consolidates all
4//! possible errors that can occur, from network issues to specific API responses.
5//! It also includes the logic for parsing raw error messages from the Wattpad API
6//! into more specific, user-friendly error variants.
7
8use serde::Deserialize;
9use thiserror::Error;
10
11/// The primary error type for all operations in the `wattpad` crate.
12#[derive(Error, Debug)]
13pub enum WattpadError {
14 /// An error occurred during a network request (e.g., connection timeout, DNS failure).
15 #[error("Network or request error: {0}")]
16 RequestError(#[from] reqwest::Error),
17
18 /// An error occurred while parsing the JSON response from the API.
19 #[error("Failed to parse JSON response: {0}")]
20 ParseError(#[from] serde_json::Error),
21
22 /// An authentication attempt failed, likely due to invalid credentials.
23 #[error("Authentication failed: Invalid credentials or missing cookies.")]
24 AuthenticationFailed,
25
26 /// A requested field or endpoint requires authentication, but the client is not logged in.
27 #[error("Authentication required for '{field}': {context}")]
28 AuthenticationRequired {
29 /// The name of the field or endpoint that requires authentication.
30 field: String,
31 /// Additional context about the requirement.
32 context: String,
33 },
34
35 /// A required field was missing from the API response.
36 #[error("Missing a required field: '{field}'. Context: {context}")]
37 MissingRequiredField {
38 /// The name of the field that was expected.
39 field: String,
40 /// Additional context about where the field was expected.
41 context: String,
42 },
43
44 /// A specific API error (code 1014) indicating the requested user was not found.
45 #[error("API Error 1014: User not found.")]
46 UserNotFound,
47
48 /// A specific API error (code 1017) indicating the requested story was not found.
49 #[error("API Error 1017: Story not found.")]
50 StoryNotFound,
51
52 /// A specific API error (code 1018) indicating permission was denied because the user is not logged in.
53 #[error("API Error 1018: Permission Denied. User not logged in.")]
54 PermissionDeniedNotLoggedIn,
55
56 /// A specific API error (code 1154) indicating access to a resource was denied.
57 #[error("API Error 1154: Access Denied.")]
58 AccessDenied,
59
60 /// A catch-all for any other error returned by the Wattpad API.
61 #[error("API Error {code} ({error_type}): {message}")]
62 ApiError {
63 /// The numerical error code from the API.
64 code: i64,
65 /// The string error type from the API.
66 error_type: String,
67 /// The descriptive error message from the API.
68 message: String,
69 },
70}
71
72/// An internal struct to deserialize the raw error response from the Wattpad API.
73///
74/// This is a temporary representation that gets converted into a `WattpadError`.
75#[derive(Deserialize)]
76pub(crate) struct ApiErrorResponse {
77 pub code: i64,
78 #[serde(rename = "error")]
79 pub error_type: String,
80 pub message: String,
81}
82
83impl From<ApiErrorResponse> for WattpadError {
84 /// Converts the raw API error response into a more specific and user-friendly `WattpadError`.
85 ///
86 /// This implementation maps known error codes to specific enum variants, providing clearer
87 /// error types to the end-user. Unknown codes are mapped to the generic `ApiError` variant.
88 fn from(res: ApiErrorResponse) -> Self {
89 match res.code {
90 1014 => WattpadError::UserNotFound,
91 1017 => WattpadError::StoryNotFound,
92 1018 => WattpadError::PermissionDeniedNotLoggedIn,
93 1154 => WattpadError::AccessDenied,
94 _ => WattpadError::ApiError {
95 code: res.code,
96 error_type: res.error_type,
97 message: res.message,
98 },
99 }
100 }
101}