roblox_api/api/assets/
v1.rs

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)]
14pub enum Creator {
15    #[serde(rename = "userId")]
16    // TODO: cast to u64
17    UserId(String), // can be sent as a u64, but it's returned as a string in some cases
18    #[serde(rename = "groupId")]
19    GroupId(String),
20}
21
22#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
23pub struct CreationContext {
24    pub creator: Creator,
25    #[serde(rename = "expectedPrice")]
26    pub expected_price: Option<u64>,
27}
28
29#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
30pub struct ModerationResult {
31    #[serde(rename = "moderationState")]
32    pub state: String,
33}
34
35#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
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    #[serde(rename = "assetType")]
47    pub asset_type: AssetTypeId,
48
49    #[serde(rename = "revisionId")]
50    pub revision_id: String,
51    #[serde(rename = "revisionCreateTime")]
52    pub revision_creation_time: DateTime,
53
54    #[serde(rename = "creationContext")]
55    pub creation_context: CreationContext,
56    #[serde(rename = "moderationResult")]
57    pub moderation_result: ModerationResult,
58}
59
60#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
61pub struct AssetUploadResponse {
62    pub path: String,
63    // TODO: cast to u64 please
64    #[serde(rename = "assetId")]
65    pub id: String,
66    #[serde(rename = "displayName")]
67    pub name: String,
68
69    pub state: String,
70    #[serde(rename = "assetType")]
71    pub asset_type: AssetTypeId,
72
73    #[serde(rename = "revisionId")]
74    pub revision_id: String,
75    #[serde(rename = "revisionCreateTime")]
76    pub revision_creation_time: DateTime,
77
78    #[serde(rename = "creationContext")]
79    pub creation_context: CreationContext,
80    #[serde(rename = "moderationResult")]
81    pub moderation_result: ModerationResult,
82}
83
84#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
85pub struct AssetUploadStatus {
86    pub path: String,
87    #[serde(rename = "operationId")]
88    pub operation_id: String,
89    #[serde(rename = "done")]
90    pub complete: bool,
91    pub response: Option<AssetUploadResponse>,
92}
93
94pub async fn asset(client: &mut Client, id: u64) -> Result<AssetInfo, Error> {
95    let result = client
96        .requestor
97        .client
98        .get(format!("{URL}/assets/{id}"))
99        .headers(client.requestor.default_headers.clone())
100        .send()
101        .await;
102
103    let response = client.validate_response(result).await?;
104    client.requestor.parse_json::<AssetInfo>(response).await
105}
106
107// this api also takes in a patch request to update an exists asset "{URL}/assets/{id}"
108pub async fn upload(
109    client: &mut Client,
110    path: impl AsRef<Path>,
111    title: &str,
112    description: &str,
113    asset_type: AssetTypeId,
114    creation_context: CreationContext,
115) -> Result<AssetUploadStatus, Error> {
116    let mut headers = client.requestor.default_headers.clone();
117    headers.insert(header::ACCEPT, HeaderValue::from_str("*/*").unwrap());
118
119    #[derive(Clone, Debug, Deserialize, Serialize)]
120    struct Request<'a> {
121        #[serde(rename = "displayName")]
122        title: &'a str,
123        description: &'a str,
124        #[serde(rename = "assetType")]
125        asset_type: AssetTypeId,
126        #[serde(rename = "creationContext")]
127        creation_context: CreationContext,
128    }
129
130    let request = serde_json::to_string(&Request {
131        title,
132        description,
133        asset_type,
134        creation_context,
135    })
136    .unwrap();
137
138    let result = client
139        .requestor
140        .client
141        .post(format!("{URL}/assets"))
142        .headers(headers)
143        .multipart(
144            Form::new()
145                .text("request", request)
146                .file("fileContent", &path)
147                .await
148                .unwrap(),
149        )
150        .send()
151        .await;
152
153    let response = client.validate_response(result).await?;
154    client
155        .requestor
156        .parse_json::<AssetUploadStatus>(response)
157        .await
158}
159
160pub async fn status(client: &mut Client, operation_id: &str) -> Result<AssetUploadStatus, Error> {
161    let result = client
162        .requestor
163        .client
164        .get(format!("{URL}/operations/{operation_id}"))
165        .headers(client.requestor.default_headers.clone())
166        .send()
167        .await;
168
169    let response = client.validate_response(result).await?;
170    client
171        .requestor
172        .parse_json::<AssetUploadStatus>(response)
173        .await
174}