1use reqwest::{
2 Response,
3 header::{self, HeaderMap, HeaderValue},
4};
5use serde::de::DeserializeOwned;
6
7use crate::Error;
8
9#[derive(Default)]
10pub struct Cookie(String);
11
12impl std::fmt::Display for Cookie {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 write!(f, "{}", self.0)
15 }
16}
17
18impl From<&str> for Cookie {
19 fn from(value: &str) -> Self {
20 Self(format!(".ROBLOSECURITY={}", value))
21 }
22}
23
24#[derive(Default, Debug)]
25pub struct ClientRequestor {
26 pub(crate) client: reqwest::Client,
27 pub(crate) default_headers: HeaderMap,
28}
29
30#[derive(Default, Debug)]
31pub struct Client {
32 pub requestor: ClientRequestor,
33}
34
35impl Client {
36 pub fn from_cookie(cookie: Cookie) -> Self {
37 let client = reqwest::Client::new();
38 let mut default_headers = HeaderMap::new();
39
40 default_headers.insert(
41 header::USER_AGENT,
42 HeaderValue::from_str("Roblox/WinInet").unwrap(),
43 );
44
45 default_headers.insert(
46 header::COOKIE,
47 HeaderValue::from_str(&cookie.to_string()).unwrap(),
48 );
49
50 Client {
51 requestor: ClientRequestor {
52 client,
53 default_headers,
54 },
55 }
56 }
57}
58
59impl ClientRequestor {
60 pub(crate) async fn parse_json<T: DeserializeOwned>(
61 &self,
62 response: Response,
63 ) -> Result<T, Error> {
64 match response.json::<T>().await {
65 Ok(result) => Ok(result),
66 Err(_) => Err(Error::BadResponse),
67 }
68 }
69}