Skip to main content

zan_test_lib/
client.rs

1use anyhow::{Result, anyhow};
2use serde::Deserialize;
3
4const BIRDEYE_CREDITS_URL: &str = "https://public-api.birdeye.so/utils/v1/credits";
5
6#[derive(Deserialize, Debug)]
7pub struct BirdeyeCreditsResponse {
8    data: Option<BirdeyeCreditsData>,
9    remaining: Option<BirdeyeRemaining>, // For backward compatibility with older responses
10}
11
12#[derive(Deserialize, Debug)]
13pub struct BirdeyeCreditsData {
14    remaining: BirdeyeRemaining,
15    usage: BirdeyeUsage,
16}
17
18#[derive(Deserialize, Debug)]
19pub struct BirdeyeRemaining {
20    total: f64,
21}
22
23#[derive(Deserialize, Debug)]
24pub struct BirdeyeUsage {
25    total: f64,
26}
27
28#[derive(Clone)]
29pub struct BirdeyeClient {
30    api_key: String,
31    client: reqwest::Client,
32}
33
34impl BirdeyeClient {
35    pub fn new(api_key: &str) -> Self {
36        Self {
37            api_key: api_key.to_string(),
38            client: reqwest::Client::new(),
39        }
40    }
41
42    pub async fn get_credits(&self) -> Result<(f64, f64)> {
43        let res = self
44            .client
45            .get(BIRDEYE_CREDITS_URL)
46            .header("X-API-KEY", &self.api_key)
47            .header("accept", "application/json")
48            .send()
49            .await?;
50
51        if !res.status().is_success() {
52            let status = res.status();
53            let text = res.text().await?;
54            return Err(anyhow!(
55                "Birdeye credits request failed: {} - {}",
56                status,
57                text
58            ));
59        }
60
61        let json: BirdeyeCreditsResponse = res.json().await?;
62
63        let (remaining, total) = if let Some(data) = json.data {
64            let remaining = data.remaining.total;
65            let usage_total = data.usage.total;
66            (remaining, remaining + usage_total)
67        } else if let Some(remaining_data) = json.remaining {
68            // Fallback for older format
69            let remaining = remaining_data.total;
70            (remaining, remaining) // Assuming total is just remaining if usage is not present
71        } else {
72            (0.0, 0.0)
73        };
74
75        Ok((remaining, total))
76    }
77}