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}