Skip to main content

bitculator/resources/
content.rs

1use std::fmt::Display;
2use std::sync::Arc;
3
4use serde::de::DeserializeOwned;
5use serde::Serialize;
6use serde_json::{json, Value};
7
8use crate::error::Error;
9use crate::http::{enc, HttpClient};
10use crate::pagination::Page;
11use crate::params::Params;
12
13/// Editorial content: articles, videos, and insights.
14pub struct Editorial {
15    http: Arc<HttpClient>,
16}
17
18impl Editorial {
19    pub(crate) fn new(http: Arc<HttpClient>) -> Self {
20        Self { http }
21    }
22
23    /// Videos for a coin (paginated). Params: page, per_page, type, search.
24    pub fn coin_videos<T: DeserializeOwned>(&self, slug: &str, params: Params) -> Result<Page<T>, Error> {
25        Page::fetch(self.http.clone(), &format!("/api/v1/coins/{}/videos", enc(slug)), params)
26    }
27
28    /// Insight timeline for a coin. Params: locale, offset, limit.
29    pub fn coin_insights<T: DeserializeOwned>(&self, slug: &str, params: Params) -> Result<T, Error> {
30        self.http.get(&format!("/api/v1/coins/{}/insights", enc(slug)), &params)
31    }
32
33    /// List articles (paginated). Params: page, per_page, locale, tag, coin,
34    /// exchange, wallet, search.
35    pub fn articles<T: DeserializeOwned>(&self, params: Params) -> Result<Page<T>, Error> {
36        Page::fetch(self.http.clone(), "/api/v1/articles", params)
37    }
38
39    /// Get a single article by slug. Params: locale.
40    pub fn article<T: DeserializeOwned>(&self, slug: &str, params: Params) -> Result<T, Error> {
41        self.http.get(&format!("/api/v1/articles/{}", enc(slug)), &params)
42    }
43
44    /// Submit helpful/unhelpful feedback on an article.
45    pub fn submit_article_feedback(&self, slug: &str, helpful: bool) -> Result<Value, Error> {
46        self.http.post_value(&format!("/api/v1/articles/{}/feedback", enc(slug)), Some(json!({ "helpful": helpful })))
47    }
48
49    /// Get a single video by id.
50    pub fn video<T: DeserializeOwned>(&self, id: impl Display) -> Result<T, Error> {
51        self.http.get(&format!("/api/v1/videos/{}", enc(&id.to_string())), &Params::new())
52    }
53
54    /// List insights (paginated). Params: page, per_page, locale, type, coin, search, sort.
55    pub fn insights<T: DeserializeOwned>(&self, params: Params) -> Result<Page<T>, Error> {
56        Page::fetch(self.http.clone(), "/api/v1/insights", params)
57    }
58
59    /// Get a single insight by id. Params: locale.
60    pub fn insight<T: DeserializeOwned>(&self, id: impl Display, params: Params) -> Result<T, Error> {
61        self.http.get(&format!("/api/v1/insights/{}", enc(&id.to_string())), &params)
62    }
63}
64
65/// Body for creating an alarm.
66#[derive(Debug, Clone, Serialize)]
67pub struct NewAlarm {
68    pub name: String,
69    pub coin: String,
70    pub metric: String,
71    pub direction: String,
72    pub target: f64,
73    pub notification: String,
74}
75
76/// Price alarms owned by the API key.
77pub struct Alarms {
78    http: Arc<HttpClient>,
79}
80
81impl Alarms {
82    pub(crate) fn new(http: Arc<HttpClient>) -> Self {
83        Self { http }
84    }
85
86    /// List your alarms (paginated). Params: page, per_page, status, direction, notification.
87    pub fn list<T: DeserializeOwned>(&self, params: Params) -> Result<Page<T>, Error> {
88        Page::fetch(self.http.clone(), "/api/v1/alarms", params)
89    }
90
91    /// Create an alarm.
92    pub fn create(&self, alarm: &NewAlarm) -> Result<Value, Error> {
93        let body = serde_json::to_value(alarm).map_err(|e| Error::Decode(e.to_string()))?;
94        self.http.post_value("/api/v1/alarms", Some(body))
95    }
96
97    /// Delete an alarm by id.
98    pub fn delete(&self, id: impl Display) -> Result<Value, Error> {
99        self.http.delete_value(&format!("/api/v1/alarms/{}", enc(&id.to_string())))
100    }
101}
102
103/// Body for registering a webhook endpoint.
104#[derive(Debug, Clone, Serialize)]
105pub struct NewWebhook {
106    pub url: String,
107    pub events: Vec<String>,
108}
109
110/// Webhook endpoints and their delivery log.
111pub struct Webhooks {
112    http: Arc<HttpClient>,
113}
114
115impl Webhooks {
116    pub(crate) fn new(http: Arc<HttpClient>) -> Self {
117        Self { http }
118    }
119
120    /// List your webhook endpoints.
121    pub fn list<T: DeserializeOwned>(&self) -> Result<T, Error> {
122        self.http.get("/api/v1/webhooks", &Params::new())
123    }
124
125    /// Register a webhook endpoint for a set of events.
126    pub fn create(&self, webhook: &NewWebhook) -> Result<Value, Error> {
127        let body = serde_json::to_value(webhook).map_err(|e| Error::Decode(e.to_string()))?;
128        self.http.post_value("/api/v1/webhooks", Some(body))
129    }
130
131    /// Delete a webhook endpoint by id.
132    pub fn delete(&self, id: impl Display) -> Result<Value, Error> {
133        self.http.delete_value(&format!("/api/v1/webhooks/{}", enc(&id.to_string())))
134    }
135
136    /// Send a test event to a webhook endpoint.
137    pub fn test(&self, id: impl Display) -> Result<Value, Error> {
138        self.http.post_value(&format!("/api/v1/webhooks/{}/test", enc(&id.to_string())), None)
139    }
140
141    /// Delivery log for a webhook endpoint (paginated). Params: page, per_page.
142    pub fn deliveries<T: DeserializeOwned>(&self, id: impl Display, params: Params) -> Result<Page<T>, Error> {
143        Page::fetch(self.http.clone(), &format!("/api/v1/webhooks/{}/deliveries", enc(&id.to_string())), params)
144    }
145}
146
147/// Service metadata: spec, health, and key usage.
148pub struct Meta {
149    http: Arc<HttpClient>,
150}
151
152impl Meta {
153    pub(crate) fn new(http: Arc<HttpClient>) -> Self {
154        Self { http }
155    }
156
157    /// The raw OpenAPI specification for the API.
158    pub fn openapi<T: DeserializeOwned>(&self) -> Result<T, Error> {
159        self.http.get("/api/v1/openapi.json", &Params::new())
160    }
161
162    /// Health check.
163    pub fn ping<T: DeserializeOwned>(&self) -> Result<T, Error> {
164        self.http.get("/api/v1/ping", &Params::new())
165    }
166
167    /// Current key usage and quota.
168    pub fn usage<T: DeserializeOwned>(&self) -> Result<T, Error> {
169        self.http.get("/api/v1/usage", &Params::new())
170    }
171}