romm_api/endpoints/
sync.rs1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use super::Endpoint;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct SyncOperation {
11 pub action: String,
12 pub rom_id: u64,
13 pub save_id: Option<u64>,
14 pub file_name: String,
15 pub slot: Option<String>,
16 pub emulator: Option<String>,
17 pub reason: String,
18 pub server_updated_at: Option<String>,
19 pub server_content_hash: Option<String>,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
24pub struct SyncNegotiateResponse {
25 pub session_id: u64,
26 pub operations: Vec<SyncOperation>,
27 pub total_upload: u64,
28 pub total_download: u64,
29 pub total_conflict: u64,
30 pub total_no_op: u64,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct SyncSessionSchema {
36 pub id: u64,
37 pub device_id: String,
38 pub user_id: u64,
39 pub status: String,
40 pub initiated_at: String,
41 pub completed_at: Option<String>,
42 pub operations_planned: u64,
43 pub operations_completed: u64,
44 pub operations_failed: u64,
45 pub error_message: Option<String>,
46 pub created_at: String,
47 pub updated_at: String,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct SyncCompleteResponse {
52 pub session: SyncSessionSchema,
53 pub play_session_ingest: Option<Value>,
54}
55
56#[derive(Debug, Clone)]
58pub struct NegotiateSync {
59 pub body: Value,
60}
61
62impl Endpoint for NegotiateSync {
63 type Output = SyncNegotiateResponse;
64
65 fn method(&self) -> &'static str {
66 "POST"
67 }
68
69 fn path(&self) -> String {
70 "/api/sync/negotiate".into()
71 }
72
73 fn body(&self) -> Option<Value> {
74 Some(self.body.clone())
75 }
76}
77
78#[derive(Debug, Clone)]
80pub struct CompleteSyncSession {
81 pub session_id: u64,
82 pub body: Value,
83}
84
85impl Endpoint for CompleteSyncSession {
86 type Output = SyncCompleteResponse;
87
88 fn method(&self) -> &'static str {
89 "POST"
90 }
91
92 fn path(&self) -> String {
93 format!("/api/sync/sessions/{}/complete", self.session_id)
94 }
95
96 fn body(&self) -> Option<Value> {
97 Some(self.body.clone())
98 }
99}
100
101#[derive(Debug, Clone, Default)]
103pub struct ListSyncSessions {
104 pub device_id: Option<String>,
105 pub limit: Option<u32>,
106}
107
108impl Endpoint for ListSyncSessions {
109 type Output = Vec<SyncSessionSchema>;
110
111 fn method(&self) -> &'static str {
112 "GET"
113 }
114
115 fn path(&self) -> String {
116 "/api/sync/sessions".into()
117 }
118
119 fn query(&self) -> Vec<(String, String)> {
120 let mut out = Vec::new();
121 if let Some(ref device_id) = self.device_id {
122 if !device_id.is_empty() {
123 out.push(("device_id".into(), device_id.clone()));
124 }
125 }
126 if let Some(limit) = self.limit {
127 out.push(("limit".into(), limit.to_string()));
128 }
129 out
130 }
131}
132
133#[derive(Debug, Clone)]
135pub struct GetSyncSession {
136 pub session_id: u64,
137}
138
139impl Endpoint for GetSyncSession {
140 type Output = SyncSessionSchema;
141
142 fn method(&self) -> &'static str {
143 "GET"
144 }
145
146 fn path(&self) -> String {
147 format!("/api/sync/sessions/{}", self.session_id)
148 }
149}
150
151#[derive(Debug, Clone)]
153pub struct TriggerPushPull {
154 pub device_id: String,
155}
156
157impl Endpoint for TriggerPushPull {
158 type Output = SyncSessionSchema;
159
160 fn method(&self) -> &'static str {
161 "POST"
162 }
163
164 fn path(&self) -> String {
165 format!("/api/sync/devices/{}/push-pull", self.device_id)
166 }
167}