From 9c6bea8b498708da255861379e93b800cba8831c Mon Sep 17 00:00:00 2001 From: Pasindu Akalpa Date: Sat, 9 Mar 2024 12:41:18 +0530 Subject: [PATCH] :necktie: Update Logic --- src/logics.rs | 66 +++++++++++++++++++++++++++++++++----------- src/main.rs | 12 ++------ src/models.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 25 deletions(-) diff --git a/src/logics.rs b/src/logics.rs index 5b5b82b..638226e 100644 --- a/src/logics.rs +++ b/src/logics.rs @@ -1,7 +1,7 @@ use reqwest::Error; use reqwest::header::{ACCEPT, AUTHORIZATION, USER_AGENT}; use rocket::serde::json::Json; -use crate::models::{Configs, GetLatestReleaseResponse, UpdateContent}; +use crate::models::{Arch, Configs, GetLatestReleaseResponse, LatestJSONContent, OSType, TargetPlatform, UpdateContent}; use version_compare::{Version}; fn is_older_version(request_version: &str, release_version: &str) -> bool { @@ -26,25 +26,59 @@ fn extract_url(response: &GetLatestReleaseResponse, category: &str) -> Vec Option> { + let latest_json_url: Vec = response.assets.iter().filter(|asset| { + asset.name.eq_ignore_ascii_case("latest.json") + }).map(|asset| asset.browser_download_url.clone()).collect(); + + if &latest_json_url.len() > &0 { + let config = envy::from_env::().unwrap(); + let client = reqwest::Client::new(); + let response = client.get(&latest_json_url[0]).header(USER_AGENT, config.github_repo_owner).send().await.ok(); + let res = response?.json::().await; + match res { + Ok(re) => { + if let Some(platform_info) = re.platforms.get(&platform.to_string()) { + Some(Json(UpdateContent { + version: re.version, + pub_date: re.pub_date, + url: platform_info.url.clone(), + signature: platform_info.signature.clone(), + notes: re.notes, + })) + } else { + None + } + }, + Err(_e) => None + } + } else { None } +} + async fn get_signature(url: String) -> Result { let response = reqwest::get(url).await?.text().await?; Ok(response) } -pub async fn windows_logic(version: &str) -> Option> { - let response = get_latest_release_data().await.unwrap(); - if is_older_version(version, response.tag_name.as_str()) { - let zip_url = extract_url(&response, ".msi.zip")[0].to_owned(); - let sig_url = extract_url(&response, ".msi.zip.sig")[0].to_owned(); - let signature = get_signature(sig_url).await.unwrap(); - Some(Json(UpdateContent { - version: response.tag_name, - pub_date: response.published_at, - url: zip_url, - signature, - notes: response.body - })) - } else { - None +pub async fn get_release_data(version: &str, arch: &str, target: &str) -> Option> { + let response = get_latest_release_data().await; + match response { + Ok(res) => { + if !is_older_version(version, &res.tag_name) { + return None; + } + + let target_os = target.parse::().ok()?; + let architecture = arch.parse::().ok()?; + + match (target_os, architecture) { + (OSType::Windows, Arch::X86_64) => extract_data_from_latest_json(&res, TargetPlatform::WindowsX86_64).await, + (OSType::Linux, Arch::X86_64) => extract_data_from_latest_json(&res, TargetPlatform::LinuxX86_64).await, + (OSType::Darwin, Arch::X86_64) => extract_data_from_latest_json(&res, TargetPlatform::DarwinX86_64).await, + (OSType::Darwin, Arch::Aarch64) => extract_data_from_latest_json(&res, TargetPlatform::DarwinAarch64).await, + _ => None, + } + }, + Err(_) => { None } } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 48d1537..4a61e3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use crate::models::{Configs, UpdateContent}; use rocket::http::Header; use rocket::{Request, Response}; use rocket::fairing::{Fairing, Info, Kind}; -use crate::logics::windows_logic; +use crate::logics::{get_release_data}; pub struct CORS; @@ -46,18 +46,12 @@ fn index() -> Redirect { #[get("/?&")] async fn get_update_data(target: &str, version: &str, arch: &str) -> Result, Status> { return match target { - "windows" => { - match windows_logic(version).await { + "windows" | "linux" | "darwin" => { + match get_release_data(version, arch, target).await { Some(data) => Ok(data), None => Err(Status::NoContent) } }, - "linux" => { - Err(Status::NoContent) - }, - "darwin" => { - Err(Status::NoContent) - }, _ => Err(Status::NoContent) } } diff --git a/src/models.rs b/src/models.rs index d811106..8e4f998 100644 --- a/src/models.rs +++ b/src/models.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::{fmt::{Formatter, Display}, collections::HashMap, str::FromStr}; #[derive(Serialize)] pub struct UpdateContent { @@ -34,6 +35,81 @@ pub struct GetLatestReleaseResponse { pub body: String } +#[derive(Serialize, Deserialize, Debug)] +pub struct PlatformInfo { + pub signature: String, + pub url: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct LatestJSONContent { + pub version: String, + pub notes: String, + pub pub_date: String, + pub platforms: HashMap, +} + +#[derive(Debug, PartialEq)] +pub enum TargetPlatform { + DarwinX86_64, + DarwinAarch64, + LinuxX86_64, + WindowsX86_64 +} + +#[derive(Debug, PartialEq)] +pub enum Arch { + X86_64, + Aarch64, + I686, + Armv7 +} + +#[derive(Debug, PartialEq)] +pub enum OSType { + Windows, + Linux, + Darwin +} + +impl FromStr for OSType { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "windows" => Ok(OSType::Windows), + "linux" => Ok(OSType::Linux), + "darwin" => Ok(OSType::Darwin), + _ => Err(()) + } + } +} + +impl FromStr for Arch { + type Err = (); + + fn from_str(s: &str) -> Result { + match s { + "x86_64" => Ok(Arch::X86_64), + "aarch64" => Ok(Arch::Aarch64), + "i686" => Ok(Arch::I686), + "armv7" => Ok(Arch::Armv7), + _ => Err(()) + } + } +} + +impl Display for TargetPlatform { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match *self { + TargetPlatform::DarwinX86_64 => write!(f, "darwin-x86_64"), + TargetPlatform::DarwinAarch64 => write!(f, "darwin-aarch64"), + TargetPlatform::LinuxX86_64 => write!(f, "linux-x86_64"), + TargetPlatform::WindowsX86_64 => write!(f, "windows-x86_64") + } + } +} + fn default_github_api_url() -> String { String::from("https://api.github.com") }