1use std::path::Path;
2
3use reqwest::{
4 header::{self, HeaderValue},
5 multipart::Form,
6};
7use serde::{Deserialize, Serialize};
8
9use crate::{AssetTypeId, DateTime, Error, client::Client};
10
11pub const URL: &str = "https://apis.roblox.com/assets/user-auth/v1";
12
13#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
14#[serde(rename_all = "camelCase")]
15pub enum Creator {
16 UserId(String), GroupId(String),
19}
20
21#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
22#[serde(rename_all = "camelCase")]
23pub struct CreationContext {
24 pub creator: Creator,
25 pub expected_price: Option<u64>,
26}
27
28#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
29pub struct ModerationResult {
30 #[serde(rename = "moderationState")]
31 pub state: String,
32}
33
34#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
35#[serde(rename_all = "camelCase")]
36pub struct AssetInfo {
37 #[serde(rename = "assetId")]
38 pub id: String,
39 pub icon: Option<String>,
40 #[serde(rename = "displayName")]
41 pub name: String,
42 pub description: String,
43
44 pub path: String,
45 pub state: String,
46 pub asset_type: AssetTypeId,
47
48 pub revision_id: String,
49 #[serde(rename = "revisionCreateTime")]
50 pub revision_creation_time: DateTime,
51
52 pub creation_context: CreationContext,
53 pub moderation_result: ModerationResult,
54}
55
56#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
57#[serde(rename_all = "camelCase")]
58pub struct AssetUploadResponse {
59 pub path: String,
60 #[serde(rename = "assetId")]
62 pub id: String,
63 #[serde(rename = "displayName")]
64 pub name: String,
65
66 pub state: String,
67 pub asset_type: AssetTypeId,
68
69 pub revision_id: String,
70 #[serde(rename = "revisionCreateTime")]
71 pub revision_creation_time: DateTime,
72
73 pub creation_context: CreationContext,
74 pub moderation_result: ModerationResult,
75}
76
77#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
78#[serde(rename_all = "camelCase")]
79pub struct AssetUploadStatus {
80 pub path: String,
81 pub operation_id: String,
82 #[serde(rename = "done")]
83 pub complete: bool,
84 pub response: Option<AssetUploadResponse>,
85}
86
87pub async fn asset(client: &mut Client, id: u64) -> Result<AssetInfo, Error> {
88 let result = client
89 .requestor
90 .client
91 .get(format!("{URL}/assets/{id}"))
92 .headers(client.requestor.default_headers.clone())
93 .send()
94 .await;
95
96 let response = client.validate_response(result).await?;
97 client.requestor.parse_json::<AssetInfo>(response).await
98}
99
100pub async fn upload(
102 client: &mut Client,
103 path: impl AsRef<Path>,
104 title: &str,
105 description: &str,
106 asset_type: AssetTypeId,
107 creation_context: CreationContext,
108) -> Result<AssetUploadStatus, Error> {
109 let mut headers = client.requestor.default_headers.clone();
110 headers.insert(header::ACCEPT, HeaderValue::from_str("*/*").unwrap());
111
112 #[derive(Clone, Debug, Deserialize, Serialize)]
113 #[serde(rename_all = "camelCase")]
114 struct Request<'a> {
115 #[serde(rename = "displayName")]
116 title: &'a str,
117 description: &'a str,
118 asset_type: AssetTypeId,
119 creation_context: CreationContext,
120 }
121
122 let request = serde_json::to_string(&Request {
123 title,
124 description,
125 asset_type,
126 creation_context,
127 })
128 .unwrap();
129
130 let result = client
131 .requestor
132 .client
133 .post(format!("{URL}/assets"))
134 .headers(headers)
135 .multipart(
136 Form::new()
137 .text("request", request)
138 .file("fileContent", &path)
139 .await
140 .unwrap(),
141 )
142 .send()
143 .await;
144
145 let response = client.validate_response(result).await?;
146 client
147 .requestor
148 .parse_json::<AssetUploadStatus>(response)
149 .await
150}
151
152pub async fn status(client: &mut Client, operation_id: &str) -> Result<AssetUploadStatus, Error> {
153 let result = client
154 .requestor
155 .client
156 .get(format!("{URL}/operations/{operation_id}"))
157 .headers(client.requestor.default_headers.clone())
158 .send()
159 .await;
160
161 let response = client.validate_response(result).await?;
162 client
163 .requestor
164 .parse_json::<AssetUploadStatus>(response)
165 .await
166}