sentrystr_api/
handlers.rs1use axum::{Json, extract::Query};
2use chrono::Utc;
3use nostr::PublicKey;
4use sentrystr::Level;
5use sentrystr_collector::{EventCollector, EventFilter};
6
7use crate::models::{EventQuery, EventResponse, EventsResponse, HealthResponse};
8use crate::{ApiError, Result};
9
10pub async fn health() -> Json<HealthResponse> {
11 Json(HealthResponse {
12 status: "ok".to_string(),
13 timestamp: Utc::now(),
14 })
15}
16
17pub async fn get_events(Query(params): Query<EventQuery>) -> Result<Json<EventsResponse>> {
18 let relays = vec!["wss://relay.damus.io".to_string()];
19
20 let collector = EventCollector::new(relays)
21 .await
22 .map_err(|e| ApiError::Collection(e.to_string()))?;
23
24 let mut filter = EventFilter::new();
25
26 if let Some(limit) = params.limit {
27 filter = filter.with_limit(limit);
28 } else {
29 filter = filter.with_limit(100);
30 }
31
32 if let Some(author_str) = params.author {
33 let author = PublicKey::parse(&author_str)
34 .map_err(|e| ApiError::BadRequest(format!("Invalid public key: {}", e)))?;
35 filter = filter.with_author(author);
36 }
37
38 if let Some(level_str) = params.level {
39 let level = match level_str.to_lowercase().as_str() {
40 "debug" => Level::Debug,
41 "info" => Level::Info,
42 "warning" => Level::Warning,
43 "error" => Level::Error,
44 "fatal" => Level::Fatal,
45 _ => return Err(ApiError::BadRequest("Invalid level".to_string())),
46 };
47 filter = filter.with_level(level);
48 }
49
50 if let Some(service) = params.service {
51 filter = filter.with_service_filter(service);
52 }
53
54 if let Some(environment) = params.environment {
55 filter = filter.with_environment_filter(environment);
56 }
57
58 if let Some(component) = params.component {
59 filter = filter.with_component_filter(component);
60 }
61
62 if let Some(severity) = params.severity {
63 filter = filter.with_severity_filter(severity);
64 }
65
66 if let Some(since) = params.since {
67 filter = filter.with_since(since);
68 }
69
70 if let Some(until) = params.until {
71 filter = filter.with_until(until);
72 }
73
74 let events = collector
75 .collect_events(filter)
76 .await
77 .map_err(|e| ApiError::Collection(e.to_string()))?;
78
79 collector
80 .disconnect()
81 .await
82 .map_err(|e| ApiError::Internal(e.to_string()))?;
83
84 let response_events: Vec<EventResponse> = events
85 .into_iter()
86 .map(|event| EventResponse {
87 nostr_event_id: event.nostr_event_id.to_string(),
88 author: event.author.to_string(),
89 received_at: event.received_at,
90 event: crate::models::EventData {
91 event_id: event.event.event_id,
92 timestamp: event.event.timestamp,
93 platform: event.event.platform,
94 level: event.event.level,
95 logger: event.event.logger,
96 transaction: event.event.transaction,
97 server_name: event.event.server_name,
98 release: event.event.release,
99 environment: event.event.environment,
100 message: event.event.message,
101 tags: event.event.tags,
102 extra: event.event.extra,
103 },
104 })
105 .collect();
106
107 let total = response_events.len();
108
109 Ok(Json(EventsResponse {
110 events: response_events,
111 total,
112 }))
113}