From a94d0dc542669f20b8da928d79e1b944226ef93e Mon Sep 17 00:00:00 2001 From: Timm Ortloff Date: Tue, 19 May 2026 19:01:27 +0200 Subject: [PATCH] Add trigger support --- README.md | 11 +++------ javascript/README.md | 3 ++- javascript/lib/client.ts | 39 ++++++++++++++++++++++++++++++++ javascript/lib/types.ts | 27 +++++++++++++++++++++- rust/README.md | 8 ++----- rust/src/lib.rs | 14 ++++++++++-- rust/src/types/instance.rs | 46 +++++++++++++++++++++++++++++++++++++- 7 files changed, 129 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 6f768a9..bf84f54 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ This repository currently contains: Both implementations cover: - Health checks -- Server lifecycle management +- Server lifecycle management, including monthly subscription reactivation - Server lookup and runtime retrieval - Terrain changes - Resource metrics @@ -30,14 +30,9 @@ Both implementations cover: - Player kick / ban - SRS client inspection and moderation for servers with the SRS mod installed - Webconsole execution for servers with the webconsole mod installed +- Trigger create, list, and delete -The Rust client also includes trigger management: - -- Create trigger -- List triggers -- Delete trigger - -This feature is not stable yet and will change in the future. +Trigger management is not stable yet and will change in the future. ## Package-Specific Docs diff --git a/javascript/README.md b/javascript/README.md index acc1692..cbe41cf 100644 --- a/javascript/README.md +++ b/javascript/README.md @@ -41,7 +41,7 @@ const servers = await client.getServers(); ## Implemented Capabilities - Health checks -- Create, fetch, update, start, stop, restart, full restart, update, and delete servers +- Create, fetch, update, start, stop, restart, full restart, update, delete, and reactivate servers - Runtime lookup, chat retrieval, and resource metrics - Terrain changes - File listing, directory creation, upload, download, move, and delete @@ -49,6 +49,7 @@ const servers = await client.getServers(); - DCS pause / resume, settings save, kick, ban, and chat send - SRS client listing, kick, and ban for servers with the SRS mod installed - Webconsole execution for servers with the webconsole mod installed +- Trigger create, list, and delete ## Package Exports diff --git a/javascript/lib/client.ts b/javascript/lib/client.ts index 5d11d5f..e7b8736 100644 --- a/javascript/lib/client.ts +++ b/javascript/lib/client.ts @@ -4,6 +4,7 @@ import type { BanPlayerResponse, BillingType, CreateInstanceRequest, + CreateTriggerRequest, DcsChatSafe, DcsRuntimeSafe, DeleteMissionsResponse, @@ -28,6 +29,7 @@ import type { StartMissionResponse, StartServerResponse, Terrain, + Trigger, WebConsoleExecuteRequest, } from "./types.ts"; @@ -306,6 +308,12 @@ export default class Client { }); } + public async reactivateServer(id: string): Promise { + await this.requestVoid(this.buildUrl(`/game_servers/${id}/reactivate`), { + method: "POST", + }); + } + public async getServerResources( id: string, period: "now" | "hour" | "day" | "week", @@ -542,4 +550,35 @@ export default class Client { }, ); } + + public async createTrigger( + id: string, + request: CreateTriggerRequest, + ): Promise { + return await this.requestJson( + this.buildUrl(`/game_servers/${id}/triggers`), + { + method: "POST", + body: this.createJsonBody(request), + }, + ); + } + + public async listTriggers(id: string): Promise { + return await this.requestJson( + this.buildUrl(`/game_servers/${id}/triggers`), + { + method: "GET", + }, + ); + } + + public async deleteTrigger(id: string, triggerId: string): Promise { + await this.requestVoid( + this.buildUrl(`/game_servers/${id}/triggers/${triggerId}`), + { + method: "DELETE", + }, + ); + } } diff --git a/javascript/lib/types.ts b/javascript/lib/types.ts index e3aca7e..31aee99 100644 --- a/javascript/lib/types.ts +++ b/javascript/lib/types.ts @@ -177,8 +177,14 @@ export type GetPauseServerResponse = null; export type GetResumeServerResponse = null; +export type InstancePermissions = { + owner_user: UserResource; + permissions: Array; +}; + export type InstanceResource = { runtime: GameRuntime | null; + permissions: InstancePermissions | null; id: string; node_id: string; user_id: string; @@ -197,6 +203,7 @@ export type InstanceResource = { rented_at: number; rented_until: number | null; active_mods: Array; + subscription_cancel_at_period_end: boolean; created_at: string; dcs_settings: DcsSettingsSafe | null; region: Region; @@ -223,6 +230,7 @@ export type InstanceSafe = { rented_at: number; rented_until: number | null; active_mods: Array; + subscription_cancel_at_period_end: boolean; created_at: string; dcs_settings: DcsSettingsSafe | null; }; @@ -242,7 +250,8 @@ export type InstanceStatus = is_post_creation: boolean; }; } - | "InstallingMods" + | { InstallingMods: { is_post_creation: boolean } } + | "UninstallingMods" | "InstallingPost" | { UninstallingTerrains: { @@ -269,6 +278,7 @@ export type InstanceStoppedReason = | "ServerUpdating" | "RebootRequestedThroughFile" | "DcsSessionExpired" + | "DcsAuthFailed" | { StoppedForRestart: { scheduled: boolean } }; export type InstancesResponse = Array; @@ -279,6 +289,19 @@ export type KickPlayerResponse = boolean; export type MoveFileRequest = { source: string; destination: string }; +export type Permission = + | "instance:view" + | "instance:actions" + | "instance:chat" + | "instance:players:manage" + | "instance:missions" + | "instance:settings" + | "instance:infrastructure" + | "instance:mods" + | "instance:scheduled_tasks" + | "instance:file:read" + | "instance:file:write"; + export type Player = { ping: number; side: number; @@ -407,4 +430,6 @@ export type TriggerCondition = | { type: "OnEvent"; config: { event_type: string } } | { type: "Schedule"; config: { cron_expression: string } }; +export type UserResource = { id: string; name: string }; + export type WebConsoleExecuteRequest = { code: string }; diff --git a/rust/README.md b/rust/README.md index f23adec..1291e42 100644 --- a/rust/README.md +++ b/rust/README.md @@ -29,7 +29,7 @@ async fn main() -> anyhow::Result<()> { ## Implemented Capabilities - Health checks -- Create, fetch, update, start, stop, restart, full restart, update, and delete servers +- Create, fetch, update, start, stop, restart, full restart, update, delete, and reactivate servers - Runtime lookup, chat retrieval, and resource metrics - Terrain changes - File listing, directory creation, upload, download, move, and delete @@ -39,11 +39,7 @@ async fn main() -> anyhow::Result<()> { - Webconsole execution for servers with the webconsole mod installed - Trigger create, list, and delete -## Trigger Support - -Trigger management is currently Rust-only in this repository. - -This feature is not stable yet and will change in the future. +Trigger management is not stable yet and will change in the future. ## Development diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 694c982..38cdc1d 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -20,8 +20,9 @@ pub use types::files::{ FileDownloadResponse, FileInfo, FileListResponse, FileUploadRequest, MoveFileRequest, }; pub use types::instance::{ - ApiError, GameRuntime, GameType, Instance, InstanceNodeResource, InstanceResource, - InstanceStatus, InstanceStoppedReason, InstancesResponse, Terrain, + ApiError, GameRuntime, GameType, Instance, InstanceNodeResource, InstancePermissions, + InstanceResource, InstanceStatus, InstanceStoppedReason, InstancesResponse, Permission, + Terrain, UserResource, }; pub use types::region::Region; pub use types::srs::{SrsClient, SrsModRequest, SrsServerInfo}; @@ -292,6 +293,15 @@ impl Client { .await } + pub async fn reactivate_server(&self, id: &Uuid) -> Result<()> { + self.send_unit( + self.reqwest_client + .post(format!("{}/game_servers/{}/reactivate", Self::BASE_URL, id)), + "failed to reactivate server", + ) + .await + } + pub async fn list_files(&self, id: &Uuid, path: impl Into) -> Result { self.send_json(self.reqwest_client.get(format!( "{}/game_servers/{}/files?path={}", diff --git a/rust/src/types/instance.rs b/rust/src/types/instance.rs index 7e17d38..73cdc71 100644 --- a/rust/src/types/instance.rs +++ b/rust/src/types/instance.rs @@ -32,6 +32,7 @@ pub struct Instance { pub rented_at: i64, pub rented_until: Option, pub active_mods: Vec, + pub subscription_cancel_at_period_end: bool, pub created_at: String, pub dcs_settings: Option, } @@ -50,6 +51,7 @@ pub struct InstanceResource { #[serde(flatten)] pub node: InstanceNodeResource, pub runtime: Option, + pub permissions: Option, } pub type InstancesResponse = Vec; @@ -78,6 +80,44 @@ pub enum Terrain { GermanyCW, } +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct InstancePermissions { + pub owner_user: UserResource, + pub permissions: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub struct UserResource { + pub id: Uuid, + pub name: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +pub enum Permission { + #[serde(rename = "instance:view")] + InstanceView, + #[serde(rename = "instance:actions")] + InstanceActions, + #[serde(rename = "instance:chat")] + InstanceChat, + #[serde(rename = "instance:players:manage")] + InstancePlayersManage, + #[serde(rename = "instance:missions")] + InstanceMissions, + #[serde(rename = "instance:settings")] + InstanceSettings, + #[serde(rename = "instance:infrastructure")] + InstanceInfrastructure, + #[serde(rename = "instance:mods")] + InstanceMods, + #[serde(rename = "instance:scheduled_tasks")] + InstanceScheduledTasks, + #[serde(rename = "instance:file:read")] + InstanceFileRead, + #[serde(rename = "instance:file:write")] + InstanceFileWrite, +} + #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub enum InstanceStatus { AwaitingContainer, @@ -90,7 +130,10 @@ pub enum InstanceStatus { processing_progress: Option, is_post_creation: bool, }, - InstallingMods, + InstallingMods { + is_post_creation: bool, + }, + UninstallingMods, InstallingPost, UninstallingTerrains { want_uninstall: Vec, @@ -122,6 +165,7 @@ pub enum InstanceStoppedReason { ServerUpdating, RebootRequestedThroughFile, DcsSessionExpired, + DcsAuthFailed, StoppedForRestart { scheduled: bool }, }