Skip to main content

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)]
14#[serde(rename_all = "camelCase")]
15pub enum Creator {
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    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    // TODO: cast to u64 please
61    #[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.requestor.validate_response(result).await?;
97    client.requestor.parse_json::<AssetInfo>(response).await
98}
99
100// this api also takes in a patch request to update an exists asset "{URL}/assets/{id}"
101pub 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.requestor.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.requestor.validate_response(result).await?;
162    client
163        .requestor
164        .parse_json::<AssetUploadStatus>(response)
165        .await
166}