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, endpoint};
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
87endpoint! {
88    asset(id: u64) -> AssetInfo {
89        GET "{URL}/assets/{id}";
90    }
91
92    status(operation_id: &str) -> AssetUploadStatus {
93        GET "{URL}/operations/{operation_id}";
94    }
95}
96
97// TODO: this api also takes in a patch request to update an exists asset "{URL}/assets/{id}"
98pub async fn upload(
99    client: &mut Client,
100    path: impl AsRef<Path>,
101    title: &str,
102    description: &str,
103    asset_type: AssetTypeId,
104    creation_context: CreationContext,
105) -> Result<AssetUploadStatus, Error> {
106    let mut headers = client.requestor.default_headers.clone();
107    headers.insert(header::ACCEPT, HeaderValue::from_str("*/*").unwrap());
108
109    #[derive(Clone, Debug, Deserialize, Serialize)]
110    #[serde(rename_all = "camelCase")]
111    struct Request<'a> {
112        #[serde(rename = "displayName")]
113        title: &'a str,
114        description: &'a str,
115        asset_type: AssetTypeId,
116        creation_context: CreationContext,
117    }
118
119    let request = serde_json::to_string(&Request {
120        title,
121        description,
122        asset_type,
123        creation_context,
124    })
125    .unwrap();
126
127    let result = client
128        .requestor
129        .client
130        .post(format!("{URL}/assets"))
131        .headers(headers)
132        .multipart(
133            Form::new()
134                .text("request", request)
135                .file("fileContent", &path)
136                .await
137                .unwrap(),
138        )
139        .send()
140        .await;
141
142    let response = client.requestor.validate_response(result).await?;
143    client
144        .requestor
145        .parse_json::<AssetUploadStatus>(response)
146        .await
147}