The cross-platform version manager toolset crates.io/crates/hyper-jump
at main 94 lines 2.8 kB view raw
1use anyhow::anyhow; 2use anyhow::Result; 3use reqwest::Client; 4use serde::de::DeserializeOwned; 5use serde::Deserialize; 6use serde::Serialize; 7 8/// Represents an error response from the GitHub API. 9/// 10/// This struct contains information about an error response from the GitHub 11/// API, including the error message and the URL of the documentation related to 12/// the error. 13/// 14/// # Fields 15/// 16/// * `message: String` - The error message from the GitHub API. 17/// * `documentation_url: String` - The URL of the documentation related to the 18/// error. 19/// 20/// # Example 21/// 22/// ```rust 23/// let error_response = ErrorResponse { 24/// message: "Not Found".to_string(), 25/// documentation_url: "https://docs.github.com/rest".to_string(), 26/// }; 27/// println!("The error message is {}", error_response.message); 28/// println!( 29/// "The documentation URL is {}", 30/// error_response.documentation_url 31/// ); 32/// ``` 33#[derive(Debug, Deserialize, Serialize)] 34pub struct ErrorResponse { 35 pub message: String, 36 pub documentation_url: String, 37} 38 39pub async fn api(client: Option<&Client>, url: String) -> Result<String> { 40 let response = client 41 .expect("Client not found") 42 .get(url) 43 .header(reqwest::header::USER_AGENT, "hyper-jump") 44 .header(reqwest::header::ACCEPT, "application/vnd.github.v3+json") 45 .send() 46 .await? 47 .error_for_status()? 48 .text() 49 .await?; 50 51 Ok(response) 52} 53 54/// Deserializes a JSON response from the GitHub API. 55/// 56/// # Parameters 57/// 58/// * `response: String` - The JSON response from the GitHub API as a string. 59/// 60/// # Returns 61/// 62/// * `Result<T>` - The deserialized response as the specified type `T`, or an 63/// error if the response could not be deserialized or contains an error 64/// message. 65/// 66/// # Errors 67/// 68/// This function will return an error if the response contains a "message" 69/// field (indicating an error from the GitHub API), or if the response could 70/// not be deserialized into the specified type `T`. 71/// 72/// # Example 73/// 74/// ```rust 75/// let response = "{\"data\": \"some data\"}"; 76/// let result: Result<MyType> = deserialize_response(response); 77/// match result { 78/// Ok(data) => println!("Received data: {:?}", data), 79/// Err(e) => println!("An error occurred: {:?}", e), 80/// } 81/// ``` 82pub fn deserialize_response<T: DeserializeOwned>(response: String) -> Result<T> { 83 let value: serde_json::Value = serde_json::from_str(&response)?; 84 if value.get("message").is_some() { 85 let result: ErrorResponse = serde_json::from_value(value)?; 86 if result.documentation_url.contains("rate-limiting") { 87 return Err(anyhow!("Rate limited by GitHub API")); 88 } 89 90 return Err(anyhow!(result.message)); 91 } 92 93 Ok(serde_json::from_value(value)?) 94}