tuitbot_server/routes/
activity.rs1use std::sync::Arc;
4
5use axum::extract::{Query, State};
6use axum::Json;
7use serde::Deserialize;
8use serde_json::{json, Value};
9use tuitbot_core::storage::{action_log, rate_limits};
10
11use crate::error::ApiError;
12use crate::state::AppState;
13
14#[derive(Deserialize)]
16pub struct ActivityQuery {
17 #[serde(default = "default_limit")]
19 pub limit: u32,
20 #[serde(default)]
22 pub offset: u32,
23 #[serde(rename = "type")]
25 pub action_type: Option<String>,
26 pub status: Option<String>,
28}
29
30fn default_limit() -> u32 {
31 50
32}
33
34pub async fn list_activity(
36 State(state): State<Arc<AppState>>,
37 Query(params): Query<ActivityQuery>,
38) -> Result<Json<Value>, ApiError> {
39 let type_filter =
40 params
41 .action_type
42 .as_deref()
43 .and_then(|t| if t == "all" { None } else { Some(t) });
44 let status_filter = params.status.as_deref();
45
46 let actions = action_log::get_actions_paginated(
47 &state.db,
48 params.limit,
49 params.offset,
50 type_filter,
51 status_filter,
52 )
53 .await?;
54
55 let total = action_log::get_actions_count(&state.db, type_filter, status_filter).await?;
56
57 Ok(Json(json!({
58 "actions": actions,
59 "total": total,
60 "limit": params.limit,
61 "offset": params.offset,
62 })))
63}
64
65pub async fn rate_limit_usage(State(state): State<Arc<AppState>>) -> Result<Json<Value>, ApiError> {
67 let usage = rate_limits::get_daily_usage(&state.db).await?;
68 Ok(Json(json!(usage)))
69}