yt_live_rs/error.rs
1//! Error types for the yt-live-rs library.
2//!
3//! This module defines all error types that can occur when using the library.
4//! The main error type is [`Error`], and [`Result<T>`] is a type alias for
5//! `std::result::Result<T, Error>`.
6
7use thiserror::Error;
8
9/// Result type alias for the library.
10pub type Result<T> = std::result::Result<T, Error>;
11
12/// Error types that can occur when using the library.
13///
14/// This enum covers all possible errors from network requests, parsing,
15/// stream availability, and download operations.
16#[derive(Debug, Clone, Error)]
17pub enum Error {
18 /// HTTP request failed.
19 ///
20 /// This can occur due to network issues, timeouts, or server errors.
21 #[error("HTTP request failed: {0}")]
22 Http(String),
23
24 /// URL parsing failed.
25 ///
26 /// The provided URL could not be parsed as a valid URL.
27 #[error("Invalid URL: {0}")]
28 Url(String),
29
30 /// JSON parsing failed.
31 ///
32 /// The response from YouTube could not be parsed as valid JSON.
33 #[error("JSON parsing failed: {0}")]
34 Json(String),
35
36 /// XML parsing failed.
37 ///
38 /// The DASH manifest could not be parsed as valid XML.
39 #[error("XML parsing failed: {0}")]
40 Xml(String),
41
42 /// IO operation failed.
43 ///
44 /// File reading/writing or other IO operations failed.
45 #[error("IO error: {0}")]
46 Io(String),
47
48 /// Invalid YouTube URL format.
49 ///
50 /// The URL is not a recognized YouTube URL format.
51 /// Supported formats include:
52 /// - `https://youtube.com/watch?v=VIDEO_ID`
53 /// - `https://youtu.be/VIDEO_ID`
54 /// - `https://youtube.com/@channel/live`
55 #[error("Invalid YouTube URL: {0}")]
56 InvalidYouTubeUrl(String),
57
58 /// Video not found.
59 ///
60 /// The video ID does not exist or is not accessible.
61 #[error("Video not found: {0}")]
62 VideoNotFound(String),
63
64 /// The video is not a live stream.
65 ///
66 /// This library only supports live streams, not regular videos.
67 #[error("Stream is not a live stream")]
68 NotLiveStream,
69
70 /// Stream is currently offline.
71 ///
72 /// The live stream exists but is not currently broadcasting.
73 /// Check `scheduled_start` for when it might go live.
74 #[error("Stream is offline: {reason}")]
75 StreamOffline {
76 /// Reason the stream is offline.
77 reason: String,
78 /// Scheduled start time, if known.
79 scheduled_start: Option<String>,
80 },
81
82 /// Stream is unplayable.
83 ///
84 /// YouTube has blocked playback for some reason (geo-restriction, etc.).
85 #[error("Stream is unplayable: {0}")]
86 Unplayable(String),
87
88 /// Error in the player response from YouTube.
89 #[error("Player response error: {0}")]
90 PlayerResponseError(String),
91
92 /// No DASH manifest available.
93 ///
94 /// The stream doesn't have a DASH manifest, which is required for downloading.
95 #[error("No DASH manifest available")]
96 NoDashManifest,
97
98 /// Requested quality is not available.
99 ///
100 /// The stream doesn't offer the requested quality level.
101 #[error("Quality {0} not available")]
102 QualityNotAvailable(String),
103
104 /// Download operation failed.
105 #[error("Download failed: {0}")]
106 DownloadFailed(String),
107
108 /// Fragment download failed after retries.
109 #[error("Fragment {seq} download failed after {tries} tries")]
110 FragmentFailed {
111 /// Sequence number of the failed fragment.
112 seq: u64,
113 /// Number of retry attempts made.
114 tries: u32,
115 },
116
117 /// Cookie file parsing failed.
118 ///
119 /// The cookies file is not in valid Netscape format.
120 #[error("Cookie parsing failed: {0}")]
121 CookieParseFailed(String),
122
123 /// Required data is missing from the response.
124 #[error("Missing required data: {0}")]
125 MissingData(String),
126
127 /// PO Token is required for this stream.
128 ///
129 /// Some streams require a PO token for authentication.
130 /// Use [`ClientBuilder::po_token`](crate::ClientBuilder::po_token) to provide one.
131 #[error("PO Token is required for this stream")]
132 PoTokenRequired,
133
134 /// Login is required to access this stream.
135 ///
136 /// Provide cookies from a logged-in session using
137 /// [`ClientBuilder::cookies_file`](crate::ClientBuilder::cookies_file).
138 #[error("Login required - please provide cookies")]
139 LoginRequired,
140
141 /// This is a members-only stream.
142 ///
143 /// Access requires channel membership. Provide cookies from
144 /// a logged-in account with an active membership.
145 #[error("This is a members-only stream")]
146 MembersOnly,
147
148 /// Regex compilation or matching error.
149 #[error("Regex error: {0}")]
150 Regex(String),
151}
152
153impl From<reqwest::Error> for Error {
154 fn from(e: reqwest::Error) -> Self {
155 Error::Http(e.to_string())
156 }
157}
158
159impl From<url::ParseError> for Error {
160 fn from(e: url::ParseError) -> Self {
161 Error::Url(e.to_string())
162 }
163}
164
165impl From<serde_json::Error> for Error {
166 fn from(e: serde_json::Error) -> Self {
167 Error::Json(e.to_string())
168 }
169}
170
171impl From<quick_xml::DeError> for Error {
172 fn from(e: quick_xml::DeError) -> Self {
173 Error::Xml(e.to_string())
174 }
175}
176
177impl From<std::io::Error> for Error {
178 fn from(e: std::io::Error) -> Self {
179 Error::Io(e.to_string())
180 }
181}
182
183impl From<regex::Error> for Error {
184 fn from(e: regex::Error) -> Self {
185 Error::Regex(e.to_string())
186 }
187}