nvrs 0.1.8-pre1

🚦 fast new version checker for software releases 🦀
Documentation
use reqwest::{
    Response,
    header::{ACCEPT, AUTHORIZATION, HeaderValue},
};
use serde_json::Value;

use crate::{api, error};

#[derive(serde::Deserialize)]
struct GitHubResponse {
    tag_name: String,
    html_url: String,
}

/// get the latest version of a package from GitHub
pub fn get_latest(args: api::ApiArgs) -> api::ReleaseFuture {
    Box::pin(async move {
        let repo_url = format!("https://api.github.com/repos/{}", args.args[0]);

        if args.use_max_tag.is_some_and(|x| x) {
            let url = format!("{}/tags", repo_url);
            let result = request(url, &args).await?;
            let json: Value = result.json().await?;

            let max_tag = json
                .get(0)
                .unwrap()
                .get("name")
                .unwrap()
                .to_string()
                .replace("\"", "");

            Ok(api::Release {
                name: max_tag.clone(),
                tag: Some(max_tag.clone()),
                url: format!(
                    "https://github.com/{}/releases/tag/{}",
                    args.args[0], max_tag
                ),
            })
        } else {
            let url = format!("{}/releases/latest", repo_url);
            let result = request(url, &args).await?;
            let json: GitHubResponse = result.json().await?;

            Ok(api::Release {
                name: json.tag_name.clone(),
                tag: Some(json.tag_name),
                url: json.html_url,
            })
        }
    })
}

async fn request(url: String, args: &api::ApiArgs) -> error::Result<Response> {
    let mut headers = api::setup_headers();
    headers.insert(
        ACCEPT,
        HeaderValue::from_static("application/vnd.github+json"),
    );
    headers.insert(
        "X-GitHub-Api-Version",
        HeaderValue::from_static("2022-11-28"),
    );
    if !args.api_key.is_empty() {
        let bearer = format!("Bearer {}", args.api_key);
        headers.insert(AUTHORIZATION, HeaderValue::from_str(&bearer).unwrap());
    }
    let client = &args.request_client;

    let result = client.get(url).headers(headers).send().await?;
    api::match_statuscode(&result.status(), args.package.clone())?;

    Ok(result)
}

#[tokio::test]
async fn request_test() {
    let package = "nvrs".to_string();
    let args = api::ApiArgs {
        request_client: reqwest::Client::new(),
        package: package.clone(),
        use_max_tag: None,
        args: vec![format!("adamperkowski/{}", package)],
        api_key: String::new(),
    };

    assert!(get_latest(args).await.is_ok());
}