roblox_api/
lib.rs

1pub mod api;
2pub mod challenge;
3pub mod client;
4pub mod validation;
5
6use challenge::Challenge;
7use chrono::{Datelike, TimeZone, Utc};
8use serde::{Deserialize, Serialize};
9
10// TODO: using this wrapper as I couldn't figure out how to use chronos datetime alone
11#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
12pub struct DateTime(String);
13impl DateTime {
14    pub fn from_ymd(year: i32, month: u8, day: u8) -> Self {
15        Self(
16            Utc.with_ymd_and_hms(year, month as u32, day as u32, 0, 0, 0)
17                .unwrap()
18                .to_rfc3339(),
19        )
20    }
21
22    pub fn day(&self) -> u8 {
23        chrono::DateTime::parse_from_rfc3339(&self.0).unwrap().day() as u8
24    }
25
26    pub fn month(&self) -> u8 {
27        chrono::DateTime::parse_from_rfc3339(&self.0)
28            .unwrap()
29            .month() as u8
30    }
31
32    pub fn year(&self) -> i32 {
33        chrono::DateTime::parse_from_rfc3339(&self.0)
34            .unwrap()
35            .year()
36    }
37}
38
39impl std::fmt::Display for DateTime {
40    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
41        write!(f, "{}", self.0)
42    }
43}
44
45#[derive(Debug)]
46pub enum Error {
47    ApiError(ApiError),
48    BadResponse,
49    ReqwestError(reqwest::Error),
50    IoError(std::io::Error),
51}
52
53#[derive(Clone, Debug, PartialEq, Eq)]
54pub enum ApiError {
55    Internal,
56    BadRequest,
57    RequestMissingArgument(String),
58    Ratelimited,
59    Unknown(u16),
60    Unauthorized,
61    InvalidBirthdate,
62    InvalidDisplayName,
63    InvalidGender,
64    UserNotFound,
65    InvalidUserId,
66    PinIsLocked,
67    TokenValidation,
68    CaptchaFailed,
69    ChallengeRequired(Challenge),
70    ChallengeFailed,
71    InvalidChallengeId,
72    InvalidTwoStepVerificationCode,
73    TwoStepVerificationMaintenance,
74    Multiple(Vec<ApiError>),
75    PermissionError,
76    AccontLocked,
77    AccountIssue,
78    InvalidCredentials,
79    UnverifiedCredentials,
80    ExistingLoginSession,
81    DefaultLoginRequired,
82    VNGAppLoginRequired,
83    LuoBuAppLoginRequired,
84    SocialNetworkLoginRequired,
85    InvalidAssetId,
86}
87
88#[repr(u8)]
89#[derive(Copy, Clone, Debug, Deserialize, PartialEq, Eq)]
90pub enum AssetTypeId {
91    Image = 1,
92    TShirt,
93    Audio,
94    Mesh,
95    Lua,
96    Hat = 8,
97    Place,
98    Model,
99    Shirt,
100    Pants,
101    Decal,
102    Head = 17,
103    Face,
104    Gear,
105    Badge = 21,
106    Animation = 24,
107    Torso = 27,
108    RightArm,
109    LeftArm,
110    LeftLeg,
111    RightLeg,
112    Package,
113    Gamepass = 34,
114    Plugin = 38,
115    MeshPart = 40,
116    HairAccessory,
117    FaceAccessory,
118    NeckAccessory,
119    ShoulderAccessory,
120    FrontAccessory,
121    BackAccessory,
122    WaistAccessory,
123    ClimbAnimation,
124    DeathAnimation,
125    FallAnimation,
126    IdleAnimation,
127    JumpAnimation,
128    RunAnimation,
129    SwimAnimation,
130    WalkAnimation,
131    PoseAnimation,
132    EarAccessory,
133    EyeAccessory,
134    EmoteAnimation = 61,
135    Video,
136    TShirtAccessory = 64,
137    ShirtAccessory,
138    PantsAccessory,
139    JacketAccessory,
140    SweaterAccessory,
141    ShortsAccessory,
142    LeftShoeAccessory,
143    RightShoeAccessory,
144    DressSkirtAccessory,
145    FontFamily,
146    EyebrowAccessory = 76,
147    EyelashAccessory,
148    MoodAnimation,
149    DynamicHead,
150}
151
152#[repr(u8)]
153#[derive(Clone, Debug, Default, Serialize, PartialEq, Eq)]
154pub enum Currency {
155    #[default]
156    Robux = 1,
157    Tickets,
158}
159
160#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub struct Paging<'a> {
162    pub cursor: Option<&'a str>,
163    pub limit: Option<u16>,
164    pub order: Option<SortOrder>,
165}
166
167#[derive(Clone, Copy, Debug, Default, Serialize, PartialEq, Eq)]
168pub enum SortOrder {
169    #[default]
170    #[serde(rename = "Asc")]
171    Ascending,
172    #[serde(rename = "Desc")]
173    Descending,
174}
175
176impl std::fmt::Display for SortOrder {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        write!(
179            f,
180            "{}",
181            match self {
182                SortOrder::Ascending => "Asc",
183                SortOrder::Descending => "Desc",
184            }
185        )
186    }
187}
188
189impl Default for Paging<'_> {
190    fn default() -> Self {
191        Self {
192            cursor: None,
193            limit: Some(10),
194            order: Some(SortOrder::Ascending),
195        }
196    }
197}
198
199impl<'a> Paging<'a> {
200    pub fn new(
201        cursor: Option<&'a str>,
202        limit: Option<u16>,
203        order: Option<SortOrder>,
204    ) -> Paging<'a> {
205        Self {
206            cursor,
207            limit,
208            order,
209        }
210    }
211}