torn_api/request/
mod.rs

1use bon::Builder;
2use bytes::Bytes;
3use http::StatusCode;
4
5use crate::{
6    executor::Executor,
7    models::{FactionChainsResponse, FactionId},
8};
9
10pub mod models;
11
12#[derive(Default)]
13pub struct ApiRequest<D = ()> {
14    pub disriminant: D,
15    pub path: String,
16    pub parameters: Vec<(&'static str, String)>,
17}
18
19impl<D> ApiRequest<D> {
20    pub fn url(&self) -> String {
21        let mut url = format!("https://api.torn.com/v2{}?", self.path);
22
23        for (name, value) in &self.parameters {
24            url.push_str(&format!("{name}={value}"));
25        }
26
27        url
28    }
29}
30
31pub struct ApiResponse<D = ()> {
32    pub discriminant: D,
33    pub body: Option<Bytes>,
34    pub status: StatusCode,
35}
36
37pub trait IntoRequest: Send {
38    type Discriminant: Send;
39    type Response: for<'de> serde::Deserialize<'de> + Send;
40    fn into_request(self) -> ApiRequest<Self::Discriminant>;
41}
42
43pub struct FactionScope<'e, E>(&'e E)
44where
45    E: Executor;
46
47impl<E> FactionScope<'_, E>
48where
49    E: Executor,
50{
51    pub async fn chains_for_id<S>(
52        &self,
53        id: FactionId,
54        builder: impl FnOnce(
55            FactionChainsRequestBuilder<faction_chains_request_builder::Empty>,
56        ) -> FactionChainsRequestBuilder<S>,
57    ) -> Result<FactionChainsResponse, E::Error>
58    where
59        S: faction_chains_request_builder::IsComplete,
60    {
61        let r = builder(FactionChainsRequest::with_id(id)).build();
62
63        self.0.fetch(r).await
64    }
65}
66
67#[derive(Builder)]
68#[builder(start_fn = with_id)]
69pub struct FactionChainsRequest {
70    #[builder(start_fn)]
71    pub id: FactionId,
72    pub limit: Option<usize>,
73}
74
75impl IntoRequest for FactionChainsRequest {
76    type Discriminant = FactionId;
77    type Response = FactionChainsResponse;
78    fn into_request(self) -> ApiRequest<Self::Discriminant> {
79        ApiRequest {
80            disriminant: self.id,
81            path: format!("/faction/{}/chains", self.id),
82            parameters: self
83                .limit
84                .into_iter()
85                .map(|l| ("limit", l.to_string()))
86                .collect(),
87        }
88    }
89}
90
91#[cfg(test)]
92mod test {
93    use crate::executor::ReqwestClient;
94
95    use super::*;
96
97    #[tokio::test]
98    async fn test_request() {
99        let client = ReqwestClient::new("nAYRXaoqzBAGalWt");
100
101        let r = models::TornItemsForIdsRequest::builder("1".to_owned()).build();
102        client.fetch(r).await.unwrap();
103    }
104}