Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
reqwest = { version = "0.12", features = ["json"] }
reqwest = { version = "0.12", features = ["json", "multipart"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tracing = "0.1"
Expand Down
25 changes: 22 additions & 3 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub mod manage;
pub mod status;

use crate::{Discloud, Error, TeamMember, TeamPerms};

use self::{
backup::AppBackup,
logs::AppLogs,
Expand All @@ -28,14 +27,33 @@ pub struct AppResponseUnique {
pub status: String,
}

#[derive(Deserialize, Debug, Clone)]
pub struct LastCommit {
pub message: String,
pub sha: String,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct SyncGit {
pub auto_deploy: bool,
#[serde(rename = "repositoryID")]
pub repository_id: u64,
pub branch_name: String,
pub last_commit: LastCommit
}

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct App {
pub auto_deploy_git: String,
pub auto_restart: bool,
#[serde(rename = "avatarURL")]
pub avatar_url: String,
pub added_at_timestamp: u64,
pub cluster_name: String,
pub exit_code: Option<i32>,
pub apts: Vec<String>,
pub id: String,
pub lang: String,
pub main_file: String,
Expand All @@ -44,6 +62,7 @@ pub struct App {
pub online: bool,
pub ram: i32,
pub ram_killed: bool,
pub sync_git: Option<SyncGit>,
pub r#type: i32,
}

Expand Down Expand Up @@ -76,8 +95,8 @@ impl App {
client.set_app_ram(&self.id, quantity).await
}

pub async fn commit(&self) {
todo!()
pub async fn commit(&self, client: &Discloud, id: &str, filepath: &str) -> Result<(), Error> {
client.commit_app(&self.id, filepath).await
}

pub async fn delete(&self, client: &Discloud) -> Result<(), Error> {
Expand Down
2 changes: 2 additions & 0 deletions src/app/manage.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
pub mod commit;
pub mod delete;
pub mod ram;
pub mod restart;
pub mod start;
pub mod stop;

pub use commit::*;
pub use delete::*;
pub use ram::*;
pub use restart::*;
Expand Down
9 changes: 9 additions & 0 deletions src/app/manage/commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use serde::Deserialize;

#[derive(Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AppCommitResponseUnique {
pub status: String,
pub status_code: i32,
pub message: String,
}
241 changes: 232 additions & 9 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
#![allow(unused)]

use std::fs;
use reqwest::{
header::{HeaderMap, HeaderName},
Client, Method, Request, StatusCode,
};
use serde::de::DeserializeOwned;

use crate::{
app::{backup::*, logs::*, manage::*, status::*, App, AppResponseAll, AppResponseUnique},
config::Config,
team_manager::{
app::{backup::*, logs::*, manage::*, status::*, App, AppResponseAll, AppResponseUnique}, config::Config, team::{TeamApp, TeamAppsResponseUnique}, team_manager::{
APITeamMember, AddTeamMemberResponse, GetTeamManagerResponse, TeamMember, TeamMemberBody,
TeamPerms,
},
user::{Locale, LocaleResponse, User, UserResponse},
util::{make_request, make_request_with_body, DiscloudDefaultResponse},
}, upload::{UploadApp, UploadOk}, user::{Locale, LocaleResponse, User, UserResponse}, util::{make_request, make_request_with_body, DiscloudDefaultResponse}
};

use tracing::{debug, trace};

use crate::util::make_request_with_file;
use super::error::Error;

#[derive(Clone)]
Expand Down Expand Up @@ -284,8 +281,27 @@ impl Discloud {
Ok(())
}

pub async fn commit_app(&self) {
todo!()
pub async fn commit_app(&self, id: &str, filepath: &str) -> Result<(), Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function.",
));
}

let file = match fs::read(filepath) {
Ok(buf) => buf,
Err(err) => {
return Err(Error::ReadFile(err))
}
};

let res: AppCommitResponseUnique = make_request_with_file(&self.config, Method::PUT, &format!("app/{id}/commit"), file).await?;

if res.status == "error" {
return Err(Error::Unknown);
}

Ok(())
}

pub async fn delete_app(&self, id: &str) -> Result<(), Error> {
Expand Down Expand Up @@ -315,4 +331,211 @@ impl Discloud {

Ok(res.apps)
}

// Upload

pub async fn upload_app(&self, filepath: &str) -> Result<UploadApp, Error> {
let file = match fs::read(filepath) {
Ok(buf) => buf,
Err(err) => {
return Err(Error::ReadFile(err))
}
};

let res: UploadOk = make_request_with_file(&self.config, Method::POST, &format!("upload"), file).await?;

if res.status == "error" {
return Err(Error::Unknown);
}

Ok(res.app)
}

// Team

pub async fn get_team_apps(&self) -> Result<Vec<TeamApp>, Error> {
let res: TeamAppsResponseUnique =
make_request(&self.config, Method::GET, &format!("team")).await?;

if res.status == "error" {
return Err(Error::Unknown);
}

Ok(res.apps)
}

pub async fn get_team_mods(&self, owner_id: &str) {
todo!()
}

pub async fn start_team_app(&self, id: &str) -> Result<AppStartStatus, AppStartError> {
if id == "all" {
return Err(AppStartError::Other(Error::InvalidRequest(
"Don't use all with that function. Use start_all_team_apps method instead.",
)));
}

let res: AppStartResponseUnique =
make_request(&self.config, Method::PUT, &format!("team/{id}/start")).await?;

if res.status == "error" {
return Err(AppStartError::AlreadyOnline);
}

res.app_status.ok_or(AppStartError::Other(Error::Unknown))
}

pub async fn start_all_team_apps(&self) -> Result<AppStartAll, Error> {
let res: AppStartResponseAll =
make_request(&self.config, Method::PUT, "team/all/start").await?;

Ok(res.apps)
}

pub async fn restart_team_app(&self, id: &str) -> Result<(), Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function. Use restart_all_team_apps method instead.",
));
}

let res: AppRestartResponseUnique =
make_request(&self.config, Method::PUT, &format!("team/{id}/restart")).await?;

if res.status == "error" {
return Err(Error::Unknown);
}

Ok(())
}

pub async fn restart_all_team_apps(&self) -> Result<AppRestartAll, Error> {
let res: AppRestartResponseAll =
make_request(&self.config, Method::PUT, "team/all/restart").await?;

Ok(res.apps)
}

pub async fn stop_team_app(&self, id: &str) -> Result<(), AppStopError> {
if id == "all" {
return Err(AppStopError::Other(Error::InvalidRequest(
"Don't use all with that function. Use stop_all_team_apps method instead.",
)));
}

let res: AppStartResponseUnique =
make_request(&self.config, Method::PUT, &format!("team/{id}/stop")).await?;

if res.status == "error" {
return Err(AppStopError::AlreadyOffline);
}

Ok(())
}

pub async fn stop_all_team_apps(&self) -> Result<AppStopAll, Error> {
let res: AppStopResponseAll =
make_request(&self.config, Method::PUT, "team/all/stop").await?;

Ok(res.apps)
}

pub async fn commit_team_app(&self, id: &str, filepath: &str) -> Result<(), Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function.",
));
}

let file = match fs::read(filepath) {
Ok(buf) => buf,
Err(err) => {
return Err(Error::ReadFile(err))
}
};

let res: AppCommitResponseUnique = make_request_with_file(&self.config, Method::PUT, &format!("team/{id}/commit"), file).await?;

if res.status == "error" {
return Err(Error::Unknown);
}

Ok(())
}

pub async fn get_team_app_backup(&self, id: &str) -> Result<AppBackup, Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function. Use get_all_team_apps_backup method instead.",
));
}

let res: AppBackupResponseUnique =
make_request(&self.config, Method::GET, &format!("team/{id}/backup")).await?;

Ok(res.backups)
}

pub async fn get_team_all_apps_backup(&self) -> Result<Vec<AppBackup>, Error> {
let res: AppBackupResponseAll =
make_request(&self.config, Method::GET, "team/all/backup").await?;

Ok(res.backups)
}

pub async fn get_team_app_logs(&self, id: &str) -> Result<AppLogs, Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function. Use get_all_team_apps_logs method instead.",
));
}

let res: AppLogsResponseUnique =
make_request(&self.config, Method::GET, &format!("team/{id}/logs")).await?;

Ok(res.apps)
}

pub async fn get_all_team_apps_logs(&self) -> Result<Vec<AppLogs>, Error> {
let res: AppLogsResponseAll =
make_request(&self.config, Method::GET, "team/all/logs").await?;

Ok(res.apps)
}

pub async fn set_team_app_ram(&self, id: &str, quantity: u32) -> Result<(), AppRamError> {
let res: AppRamResponse = make_request_with_body(
&self.config,
Method::PUT,
&format!("team/{id}/ram"),
AppRamBody { ram: quantity },
)
.await?;

if res.status == "error" {
return Err(AppRamError::ForbiddenQuantity(res.message));
}

Ok(())
}

pub async fn get_all_team_apps_status(&self) -> Result<Vec<AppStatus>, Error> {
let res: AppStatusResponseAll =
make_request(&self.config, Method::GET, "team/all/status").await?;

Ok(res.apps)
}

pub async fn get_team_app_status(&self, id: &str) -> Result<AppStatus, Error> {
if id == "all" {
return Err(Error::InvalidRequest(
"Don't use all with that function. Use get_all_team_apps_status method instead.",
));
}

let res: AppStatusResponseUnique =
make_request(&self.config, Method::GET, &format!("team/{id}/status")).await?;

Ok(res.apps)
}
}
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ pub enum Error {
ServerError,
Forbidden,
InvalidRequest(&'static str),
ReadFile(std::io::Error),
NotFound(&'static str),
Conflict(&'static str),
Unknown,
Expand All @@ -20,6 +21,7 @@ impl fmt::Display for Error {
Error::InvalidToken => write!(f, "Invalid API token provided"),
Error::Ratelimited => write!(f, "You have been ratelimited"),
Error::InvalidRequest(r) => write!(f, "Invalid request: {r}"),
Error::ReadFile(ref e) => write!(f, "Error trying to read file: {e}"),
Error::ServerError => write!(f, "Server error"),
Error::Forbidden => write!(f, "Forbidden access"),
Error::NotFound(r) => write!(f, "Not found: {r}"),
Expand Down
Loading