Skip to main content

polyoxide_gamma/api/
events.rs

1use polyoxide_core::{HttpClient, QueryBuilder, Request};
2
3use crate::{
4    error::GammaError,
5    types::{CountResponse, Event, Tag},
6};
7
8/// Events namespace for event-related operations
9#[derive(Clone)]
10pub struct Events {
11    pub(crate) http_client: HttpClient,
12}
13
14impl Events {
15    /// List events with optional filtering
16    pub fn list(&self) -> ListEvents {
17        ListEvents {
18            request: Request::new(self.http_client.clone(), "/events"),
19        }
20    }
21
22    /// Get an event by ID
23    pub fn get(&self, id: impl Into<String>) -> GetEvent {
24        GetEvent {
25            request: Request::new(
26                self.http_client.clone(),
27                format!("/events/{}", urlencoding::encode(&id.into())),
28            ),
29        }
30    }
31
32    /// Get an event by slug
33    pub fn get_by_slug(&self, slug: impl Into<String>) -> GetEvent {
34        GetEvent {
35            request: Request::new(
36                self.http_client.clone(),
37                format!("/events/slug/{}", urlencoding::encode(&slug.into())),
38            ),
39        }
40    }
41
42    /// Get related events by slug
43    pub fn get_related_by_slug(&self, slug: impl Into<String>) -> Request<Vec<Event>, GammaError> {
44        Request::new(
45            self.http_client.clone(),
46            format!("/events/slug/{}/related", urlencoding::encode(&slug.into())),
47        )
48    }
49
50    /// Get tags for an event
51    pub fn tags(&self, id: impl Into<String>) -> Request<Vec<Tag>, GammaError> {
52        Request::new(
53            self.http_client.clone(),
54            format!("/events/{}/tags", urlencoding::encode(&id.into())),
55        )
56    }
57
58    /// Get tweet count for an event
59    pub fn tweet_count(&self, id: impl Into<String>) -> Request<CountResponse, GammaError> {
60        Request::new(
61            self.http_client.clone(),
62            format!("/events/{}/tweet-count", urlencoding::encode(&id.into())),
63        )
64    }
65
66    /// Get comment count for an event
67    pub fn comment_count(&self, id: impl Into<String>) -> Request<CountResponse, GammaError> {
68        Request::new(
69            self.http_client.clone(),
70            format!("/events/{}/comments/count", urlencoding::encode(&id.into())),
71        )
72    }
73}
74
75/// Request builder for getting a single event
76pub struct GetEvent {
77    request: Request<Event, GammaError>,
78}
79
80impl GetEvent {
81    /// Include chat data in response
82    pub fn include_chat(mut self, include: bool) -> Self {
83        self.request = self.request.query("include_chat", include);
84        self
85    }
86
87    /// Include template data in response
88    pub fn include_template(mut self, include: bool) -> Self {
89        self.request = self.request.query("include_template", include);
90        self
91    }
92
93    /// Execute the request
94    pub async fn send(self) -> Result<Event, GammaError> {
95        self.request.send().await
96    }
97}
98
99/// Request builder for listing events
100pub struct ListEvents {
101    request: Request<Vec<Event>, GammaError>,
102}
103
104impl ListEvents {
105    /// Set maximum number of results (minimum: 0)
106    pub fn limit(mut self, limit: u32) -> Self {
107        self.request = self.request.query("limit", limit);
108        self
109    }
110
111    /// Set pagination offset (minimum: 0)
112    pub fn offset(mut self, offset: u32) -> Self {
113        self.request = self.request.query("offset", offset);
114        self
115    }
116
117    /// Set order fields (comma-separated list)
118    pub fn order(mut self, order: impl Into<String>) -> Self {
119        self.request = self.request.query("order", order.into());
120        self
121    }
122
123    /// Set sort direction
124    pub fn ascending(mut self, ascending: bool) -> Self {
125        self.request = self.request.query("ascending", ascending);
126        self
127    }
128
129    /// Filter by specific event IDs
130    pub fn id(mut self, ids: impl IntoIterator<Item = i64>) -> Self {
131        self.request = self.request.query_many("id", ids);
132        self
133    }
134
135    /// Filter by tag identifier
136    pub fn tag_id(mut self, tag_id: i64) -> Self {
137        self.request = self.request.query("tag_id", tag_id);
138        self
139    }
140
141    /// Exclude events with specified tag IDs
142    pub fn exclude_tag_id(mut self, tag_ids: impl IntoIterator<Item = i64>) -> Self {
143        self.request = self.request.query_many("exclude_tag_id", tag_ids);
144        self
145    }
146
147    /// Filter by event slugs
148    pub fn slug(mut self, slugs: impl IntoIterator<Item = impl ToString>) -> Self {
149        self.request = self.request.query_many("slug", slugs);
150        self
151    }
152
153    /// Filter by tag slug
154    pub fn tag_slug(mut self, slug: impl Into<String>) -> Self {
155        self.request = self.request.query("tag_slug", slug.into());
156        self
157    }
158
159    /// Include related tags in response
160    pub fn related_tags(mut self, include: bool) -> Self {
161        self.request = self.request.query("related_tags", include);
162        self
163    }
164
165    /// Filter active events only
166    pub fn active(mut self, active: bool) -> Self {
167        self.request = self.request.query("active", active);
168        self
169    }
170
171    /// Filter archived events
172    pub fn archived(mut self, archived: bool) -> Self {
173        self.request = self.request.query("archived", archived);
174        self
175    }
176
177    /// Filter featured events
178    pub fn featured(mut self, featured: bool) -> Self {
179        self.request = self.request.query("featured", featured);
180        self
181    }
182
183    /// Filter create-your-own-market events
184    pub fn cyom(mut self, cyom: bool) -> Self {
185        self.request = self.request.query("cyom", cyom);
186        self
187    }
188
189    /// Include chat data in response
190    pub fn include_chat(mut self, include: bool) -> Self {
191        self.request = self.request.query("include_chat", include);
192        self
193    }
194
195    /// Include template data
196    pub fn include_template(mut self, include: bool) -> Self {
197        self.request = self.request.query("include_template", include);
198        self
199    }
200
201    /// Filter by recurrence pattern
202    pub fn recurrence(mut self, recurrence: impl Into<String>) -> Self {
203        self.request = self.request.query("recurrence", recurrence.into());
204        self
205    }
206
207    /// Filter closed events
208    pub fn closed(mut self, closed: bool) -> Self {
209        self.request = self.request.query("closed", closed);
210        self
211    }
212
213    /// Set minimum liquidity threshold
214    pub fn liquidity_min(mut self, min: f64) -> Self {
215        self.request = self.request.query("liquidity_min", min);
216        self
217    }
218
219    /// Set maximum liquidity threshold
220    pub fn liquidity_max(mut self, max: f64) -> Self {
221        self.request = self.request.query("liquidity_max", max);
222        self
223    }
224
225    /// Set minimum trading volume
226    pub fn volume_min(mut self, min: f64) -> Self {
227        self.request = self.request.query("volume_min", min);
228        self
229    }
230
231    /// Set maximum trading volume
232    pub fn volume_max(mut self, max: f64) -> Self {
233        self.request = self.request.query("volume_max", max);
234        self
235    }
236
237    /// Set earliest start date (ISO 8601 format)
238    pub fn start_date_min(mut self, date: impl Into<String>) -> Self {
239        self.request = self.request.query("start_date_min", date.into());
240        self
241    }
242
243    /// Set latest start date (ISO 8601 format)
244    pub fn start_date_max(mut self, date: impl Into<String>) -> Self {
245        self.request = self.request.query("start_date_max", date.into());
246        self
247    }
248
249    /// Set earliest end date (ISO 8601 format)
250    pub fn end_date_min(mut self, date: impl Into<String>) -> Self {
251        self.request = self.request.query("end_date_min", date.into());
252        self
253    }
254
255    /// Set latest end date (ISO 8601 format)
256    pub fn end_date_max(mut self, date: impl Into<String>) -> Self {
257        self.request = self.request.query("end_date_max", date.into());
258        self
259    }
260
261    /// Execute the request
262    pub async fn send(self) -> Result<Vec<Event>, GammaError> {
263        self.request.send().await
264    }
265}
266
267#[cfg(test)]
268mod tests {
269    use crate::Gamma;
270
271    fn gamma() -> Gamma {
272        Gamma::new().unwrap()
273    }
274
275    /// Verify that all event builder methods chain correctly
276    #[test]
277    fn test_list_events_full_chain() {
278        let _list = gamma()
279            .events()
280            .list()
281            .limit(10)
282            .offset(20)
283            .order("volume")
284            .ascending(true)
285            .id(vec![1i64, 2])
286            .tag_id(42)
287            .exclude_tag_id(vec![99i64])
288            .slug(vec!["slug-a"])
289            .tag_slug("politics")
290            .related_tags(true)
291            .active(true)
292            .archived(false)
293            .featured(true)
294            .cyom(false)
295            .include_chat(true)
296            .include_template(false)
297            .recurrence("daily")
298            .closed(false)
299            .liquidity_min(1000.0)
300            .liquidity_max(50000.0)
301            .volume_min(100.0)
302            .volume_max(10000.0)
303            .start_date_min("2024-01-01")
304            .start_date_max("2025-01-01")
305            .end_date_min("2024-06-01")
306            .end_date_max("2025-12-31");
307    }
308
309    #[test]
310    fn test_get_event_accepts_str_and_string() {
311        let _req1 = gamma().events().get("evt-123");
312        let _req2 = gamma().events().get(String::from("evt-123"));
313    }
314
315    #[test]
316    fn test_get_by_slug_accepts_str_and_string() {
317        let _req1 = gamma().events().get_by_slug("slug");
318        let _req2 = gamma().events().get_by_slug(String::from("slug"));
319    }
320
321    #[test]
322    fn test_get_related_by_slug_accepts_str_and_string() {
323        let _req1 = gamma().events().get_related_by_slug("slug");
324        let _req2 = gamma().events().get_related_by_slug(String::from("slug"));
325    }
326
327    #[test]
328    fn test_get_event_with_query_params() {
329        let _req = gamma()
330            .events()
331            .get("evt-123")
332            .include_chat(true)
333            .include_template(false);
334    }
335
336    #[test]
337    fn test_event_tags_accepts_str_and_string() {
338        let _req1 = gamma().events().tags("evt-123");
339        let _req2 = gamma().events().tags(String::from("evt-123"));
340    }
341
342    #[test]
343    fn test_event_tweet_count() {
344        let _req = gamma().events().tweet_count("evt-123");
345    }
346
347    #[test]
348    fn test_event_comment_count() {
349        let _req = gamma().events().comment_count("evt-123");
350    }
351}