use log::debug;
use serde::{Deserialize, Serialize};
use crate::KonarrError;
use super::{
ApiResponse, KonarrClient, Pagination, security::SecuritySummary, snapshot::KonarrSnapshot,
};
#[cfg(feature = "agent")]
pub mod agent;
pub struct KonarrProjects;
impl KonarrProjects {
pub async fn list(client: &KonarrClient) -> Result<Pagination<KonarrProject>, KonarrError> {
debug!("Listing Projects");
match client
.get("/projects")
.await?
.json::<ApiResponse<Pagination<KonarrProject>>>()
.await?
{
ApiResponse::Ok(pagination) => Ok(pagination),
ApiResponse::Error(err) => Err(err.into()),
}
}
pub async fn list_top(client: &KonarrClient) -> Result<Pagination<KonarrProject>, KonarrError> {
debug!("Listing Top Projects");
match client
.get("/projects?top=true")
.await?
.json::<ApiResponse<Pagination<KonarrProject>>>()
.await?
{
ApiResponse::Ok(pagination) => Ok(pagination),
ApiResponse::Error(err) => Err(err.into()),
}
}
pub async fn search(
client: &KonarrClient,
search: impl Into<String>,
) -> Result<Pagination<KonarrProject>, KonarrError> {
let search = search.into();
debug!("Searching Projects: {}", search);
match client
.get(&format!("/projects?search={}", search))
.await?
.json::<ApiResponse<Pagination<KonarrProject>>>()
.await?
{
ApiResponse::Ok(pagination) => Ok(pagination),
ApiResponse::Error(err) => Err(err.into()),
}
}
pub async fn by_id(
client: &KonarrClient,
id: u32,
) -> Result<Option<KonarrProject>, KonarrError> {
debug!("Getting Project by ID: {}", id);
Ok(client
.get(&format!("/projects/{}", id))
.await?
.json::<KonarrProject>()
.await
.ok())
}
pub async fn by_name(
client: &KonarrClient,
name: &str,
) -> Result<Option<KonarrProject>, KonarrError> {
debug!("Getting Project by Name: {}", name);
let search = Self::search(client, name).await?;
for result in search.data {
if result.title == name || result.name == name {
return Ok(Some(result));
}
}
return Ok(None);
}
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct KonarrProject {
#[serde(skip_serializing)]
pub id: u32,
pub name: String,
#[serde(skip_serializing)]
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(rename = "type")]
pub project_type: String,
#[serde(skip_serializing)]
pub status: Option<bool>,
#[serde(skip_serializing)]
pub snapshot: Option<KonarrSnapshot>,
#[serde(skip_serializing)]
pub snapshots: u32,
#[serde(skip_serializing)]
pub security: Option<SecuritySummary>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent: Option<u32>,
#[serde(skip_serializing)]
pub children: Option<Vec<KonarrProject>>,
#[serde(skip_serializing)]
pub created_at: chrono::DateTime<chrono::Utc>,
}
impl KonarrProject {
pub fn new(name: impl Into<String>, r#type: impl Into<String>) -> Self {
Self {
name: name.into(),
project_type: r#type.into(),
..Default::default()
}
}
pub async fn create(&mut self, client: &KonarrClient) -> Result<Self, KonarrError> {
debug!("Creating Project: {}", self.name);
match client
.post("/projects", &self)
.await?
.json::<ApiResponse<Self>>()
.await?
{
ApiResponse::Ok(project) => {
*self = project;
Ok(self.clone())
}
ApiResponse::Error(err) => Err(err.into()),
}
}
pub async fn get(&mut self, client: &KonarrClient) -> Result<ApiResponse<Self>, KonarrError> {
debug!("Getting Project by ID: {}", self.id);
match client
.get(&format!("/projects/{}", self.id))
.await?
.json::<ApiResponse<Self>>()
.await?
{
ApiResponse::Ok(project) => {
*self = project;
Ok(ApiResponse::Ok(self.clone()))
}
ApiResponse::Error(err) => Ok(ApiResponse::Error(err)),
}
}
pub async fn get_snapshot(
&self,
client: &KonarrClient,
) -> Result<ApiResponse<Self>, KonarrError> {
debug!("Getting Project Snapshot: {}", self.id);
Ok(client
.get(&format!("/projects/{}/snapshot", self.id))
.await?
.json::<ApiResponse<Self>>()
.await?)
}
}