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}