#![warn(missing_docs)]
use serde::{Deserialize, Serialize};
use url::Url;
const AUR_RPC_URL: &str = "https://aur.archlinux.org/rpc/v5";
#[derive(Serialize, Deserialize, Debug)]
pub struct Request {
pub endpoint: String,
}
impl Default for Request {
fn default() -> Self {
Self {
endpoint: AUR_RPC_URL.to_string(),
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ReturnData {
version: u32,
#[serde(rename = "type")]
type_: String,
pub resultcount: u32,
pub results: Vec<Package>,
error: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Package {
#[serde(rename = "Name")]
pub name: String,
#[serde(rename = "Version")]
pub version: String,
#[serde(rename = "Description")]
pub description: Option<String>,
#[serde(rename = "Maintainer")]
pub maintainer: Option<String>,
#[serde(rename = "URL")]
pub url: Option<String>,
#[serde(rename = "NumVotes")]
pub num_votes: u32,
#[serde(rename = "Popularity")]
pub popularity: f32,
#[serde(rename = "OutOfDate")]
pub out_of_date: Option<u32>,
#[serde(rename = "PackageBase")]
pub package_base: String,
#[serde(rename = "PackageBaseID")]
pub package_base_id: u32,
#[serde(rename = "FirstSubmitted")]
pub first_submitted: u32,
#[serde(rename = "LastModified")]
pub last_modified: u32,
#[serde(rename = "URLPath")]
pub url_path: Option<String>,
#[serde(rename = "ID")]
pub id: u32,
#[serde(rename = "Depends")]
pub depends: Option<Vec<String>>,
#[serde(rename = "MakeDepends")]
pub make_depends: Option<Vec<String>>,
#[serde(rename = "OptDepends")]
pub opt_depends: Option<Vec<String>>,
#[serde(rename = "CheckDepends")]
pub check_depends: Option<Vec<String>>,
#[serde(rename = "Conflicts")]
pub conflicts: Option<Vec<String>>,
#[serde(rename = "Provides")]
pub provides: Option<Vec<String>>,
#[serde(rename = "Replaces")]
pub replaces: Option<Vec<String>>,
#[serde(rename = "Groups")]
pub groups: Option<Vec<String>>,
#[serde(rename = "License")]
pub license: Option<Vec<String>>,
#[serde(rename = "Keywords")]
pub keywords: Option<Vec<String>>,
}
impl Request {
async fn search(&self, search_term: &str) -> Result<ReturnData, Box<dyn std::error::Error>> {
let resp = reqwest::get(search_term).await?.text().await?;
let search_response: ReturnData = serde_json::from_str(&resp)?;
Ok(search_response)
}
async fn starts_with(&self, url: &str) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let resp = reqwest::get(url).await?.text().await?;
let search_response: Vec<String> = serde_json::from_str(&resp)?;
Ok(search_response)
}
pub async fn search_package_by_name(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=name", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_name_desc(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=name-desc", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_depends(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=depends", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_checkdepends(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=checkdepends", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_optdepends(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=optdepends", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_makedepends(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=optdepends", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_maintainer(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=maintainer", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_submitter(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=submitter", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_provides(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=provides", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_conflicts(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=conflicts", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_replaces(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=replaces", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_keywords(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=keywords", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_groups(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=groups", self.endpoint, package);
self.search(&url).await
}
pub async fn search_package_by_comaintainers(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/search/{}?by=comaintainers", self.endpoint, package);
self.search(&url).await
}
pub async fn search_info_by_name(
&self,
package: &str,
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url = format!("{}/info/{}", self.endpoint, package);
self.search(&url).await
}
pub async fn search_multi_info_by_names(
&self,
packages: &[&str],
) -> Result<ReturnData, Box<dyn std::error::Error>> {
let url_str = format!("{}/info", self.endpoint);
let mut args: Vec<(&str, &str)> = vec![];
for package in packages {
args.push(("arg[]", package))
}
let url = Url::parse_with_params(&url_str, args)?;
return self.search(url.as_str()).await;
}
pub async fn starts_with_name(
&self,
starts_with: &str,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let url = format!("{}/suggest/{}", self.endpoint, starts_with);
self.starts_with(&url).await
}
pub async fn starts_with_basename(
&self,
base_start: &str,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let url = format!("{}/suggest-pkgbase/{}", self.endpoint, base_start);
self.starts_with(&url).await
}
}