tradingview/
error.rs

1use serde::{Deserialize, Serialize};
2use thiserror::Error;
3use ustr::Ustr;
4
5#[derive(Debug, Clone, Error, Copy, Serialize, Deserialize)]
6pub enum Error {
7    #[error("Generic: {0}")]
8    Internal(Ustr),
9
10    #[error("Request failed: {0}")]
11    Request(Ustr),
12
13    #[error("JSON parsing failed: {0}")]
14    JsonParse(Ustr),
15
16    #[error("Type conversion failed: {0}")]
17    TypeConversion(Ustr),
18
19    #[error("Invalid header value: {0}")]
20    HeaderValue(Ustr),
21
22    #[error("Login failed: {source}")]
23    Login {
24        #[source]
25        source: LoginError,
26    },
27
28    #[error("Regex error: {0}")]
29    Regex(Ustr),
30
31    #[error("WebSocket connection failed: {0}")]
32    WebSocket(Ustr),
33
34    #[error("No chart token found")]
35    NoChartTokenFound,
36
37    #[error("No scan data found")]
38    NoScanDataFound,
39
40    #[error("Symbols are not in the same exchange")]
41    SymbolsNotInSameExchange,
42
43    #[error("Exchange not specified")]
44    ExchangeNotSpecified,
45
46    #[error("Invalid exchange")]
47    InvalidExchange,
48
49    #[error("Symbols not specified")]
50    SymbolsNotSpecified,
51
52    #[error("No search data found")]
53    NoSearchDataFound,
54
55    #[error("Indicator not found or unsupported: {0}")]
56    IndicatorDataNotFound(Ustr),
57
58    #[error("Task join failed: {0}")]
59    TokioJoin(Ustr),
60
61    #[error("URL parsing failed: {0}")]
62    UrlParse(Ustr),
63
64    #[error("Base64 decode failed: {0}")]
65    Base64Decode(Ustr),
66
67    #[error("ZIP error: {0}")]
68    Zip(Ustr),
69
70    #[error("Date/time parsing failed: {0}")]
71    ChronoParse(Ustr),
72
73    #[error("Date/time out of range: {0}")]
74    ChronoOutOfRange(Ustr),
75
76    #[error("Timeout: {0}")]
77    Timeout(Ustr),
78
79    #[error("I/O error: {0}")]
80    Io(Ustr),
81
82    #[error("TradingView error: {source}")]
83    TradingView {
84        #[source]
85        source: TradingViewError,
86    },
87}
88
89// Implement From traits for common error types
90impl From<reqwest::Error> for Error {
91    fn from(err: reqwest::Error) -> Self {
92        Error::Request(err.to_string().into())
93    }
94}
95
96impl From<serde_json::Error> for Error {
97    fn from(err: serde_json::Error) -> Self {
98        Error::JsonParse(err.to_string().into())
99    }
100}
101
102impl From<std::num::ParseIntError> for Error {
103    fn from(err: std::num::ParseIntError) -> Self {
104        Error::TypeConversion(err.to_string().into())
105    }
106}
107
108impl From<reqwest::header::InvalidHeaderValue> for Error {
109    fn from(err: reqwest::header::InvalidHeaderValue) -> Self {
110        Error::HeaderValue(err.to_string().into())
111    }
112}
113
114impl From<LoginError> for Error {
115    fn from(err: LoginError) -> Self {
116        Error::Login { source: err }
117    }
118}
119
120impl From<regex::Error> for Error {
121    fn from(err: regex::Error) -> Self {
122        Error::Regex(err.to_string().into())
123    }
124}
125
126impl From<tokio_tungstenite::tungstenite::Error> for Error {
127    fn from(err: tokio_tungstenite::tungstenite::Error) -> Self {
128        Error::WebSocket(err.to_string().into())
129    }
130}
131
132impl From<tokio::task::JoinError> for Error {
133    fn from(err: tokio::task::JoinError) -> Self {
134        Error::TokioJoin(err.to_string().into())
135    }
136}
137
138impl From<url::ParseError> for Error {
139    fn from(err: url::ParseError) -> Self {
140        Error::UrlParse(err.to_string().into())
141    }
142}
143
144impl From<base64::DecodeError> for Error {
145    fn from(err: base64::DecodeError) -> Self {
146        Error::Base64Decode(err.to_string().into())
147    }
148}
149
150impl From<zip::result::ZipError> for Error {
151    fn from(err: zip::result::ZipError) -> Self {
152        Error::Zip(err.to_string().into())
153    }
154}
155
156impl From<chrono::ParseError> for Error {
157    fn from(err: chrono::ParseError) -> Self {
158        Error::ChronoParse(err.to_string().into())
159    }
160}
161
162impl From<chrono::OutOfRangeError> for Error {
163    fn from(err: chrono::OutOfRangeError) -> Self {
164        Error::ChronoOutOfRange(err.to_string().into())
165    }
166}
167
168impl From<std::io::Error> for Error {
169    fn from(err: std::io::Error) -> Self {
170        Error::Io(err.to_string().into())
171    }
172}
173
174impl From<TradingViewError> for Error {
175    fn from(err: TradingViewError) -> Self {
176        Error::TradingView { source: err }
177    }
178}
179
180#[derive(Debug, Clone, Error, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)]
181pub enum TradingViewError {
182    #[error("Series error")]
183    SeriesError,
184    #[error("Symbol error")]
185    SymbolError,
186    #[error("Critical error")]
187    CriticalError,
188    #[error("Study error")]
189    StudyError,
190    #[error("Protocol error")]
191    ProtocolError,
192    #[error("Quote data status error: {0}")]
193    QuoteDataStatusError(Ustr),
194    #[error("Replay error")]
195    ReplayError,
196    #[error("Configuration error: missing exchange")]
197    MissingExchange,
198    #[error("Configuration error: missing symbol")]
199    MissingSymbol,
200    #[error("Invalid session ID or signature")]
201    InvalidSessionId,
202}
203
204#[derive(Debug, Clone, Error, PartialEq, Eq, Hash, Copy, Serialize, Deserialize)]
205pub enum LoginError {
206    #[error("Username or password is empty")]
207    EmptyCredentials,
208    #[error("Username or password is invalid")]
209    InvalidCredentials,
210    #[error("OTP secret is empty")]
211    OTPSecretNotFound,
212    #[error("OTP secret is invalid")]
213    InvalidOTPSecret,
214    #[error("Wrong or expired session ID/signature")]
215    InvalidSession,
216    #[error("Session ID/signature is empty")]
217    SessionNotFound,
218    #[error("Cannot parse user ID")]
219    ParseIDError,
220    #[error("Cannot parse username")]
221    ParseUsernameError,
222    #[error("Cannot parse session hash")]
223    ParseSessionHashError,
224    #[error("Cannot parse private channel")]
225    ParsePrivateChannelError,
226    #[error("Cannot parse auth token")]
227    ParseAuthTokenError,
228    #[error("Missing auth token")]
229    MissingAuthToken,
230}