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