tuitbot_server/routes/
costs.rs1use std::sync::Arc;
4
5use axum::extract::{Query, State};
6use axum::Json;
7use serde::Deserialize;
8use tuitbot_core::storage::{llm_usage, x_api_usage};
9
10use crate::account::AccountContext;
11use crate::error::ApiError;
12use crate::state::AppState;
13
14#[derive(Deserialize)]
16pub struct DaysQuery {
17 #[serde(default = "default_days")]
18 pub days: u32,
19}
20
21fn default_days() -> u32 {
22 30
23}
24
25pub async fn summary(
27 State(state): State<Arc<AppState>>,
28 ctx: AccountContext,
29) -> Result<Json<llm_usage::CostSummary>, ApiError> {
30 let summary = llm_usage::get_cost_summary_for(&state.db, &ctx.account_id).await?;
31 Ok(Json(summary))
32}
33
34pub async fn daily(
36 State(state): State<Arc<AppState>>,
37 ctx: AccountContext,
38 Query(params): Query<DaysQuery>,
39) -> Result<Json<Vec<llm_usage::DailyCostSummary>>, ApiError> {
40 let data = llm_usage::get_daily_costs_for(&state.db, &ctx.account_id, params.days).await?;
41 Ok(Json(data))
42}
43
44pub async fn by_model(
46 State(state): State<Arc<AppState>>,
47 ctx: AccountContext,
48 Query(params): Query<DaysQuery>,
49) -> Result<Json<Vec<llm_usage::ModelCostBreakdown>>, ApiError> {
50 let data = llm_usage::get_model_breakdown_for(&state.db, &ctx.account_id, params.days).await?;
51 Ok(Json(data))
52}
53
54pub async fn by_type(
56 State(state): State<Arc<AppState>>,
57 ctx: AccountContext,
58 Query(params): Query<DaysQuery>,
59) -> Result<Json<Vec<llm_usage::TypeCostBreakdown>>, ApiError> {
60 let data = llm_usage::get_type_breakdown_for(&state.db, &ctx.account_id, params.days).await?;
61 Ok(Json(data))
62}
63
64pub async fn x_api_summary(
68 State(state): State<Arc<AppState>>,
69 ctx: AccountContext,
70) -> Result<Json<x_api_usage::XApiUsageSummary>, ApiError> {
71 let summary = x_api_usage::get_usage_summary_for(&state.db, &ctx.account_id).await?;
72 Ok(Json(summary))
73}
74
75pub async fn x_api_daily(
77 State(state): State<Arc<AppState>>,
78 ctx: AccountContext,
79 Query(params): Query<DaysQuery>,
80) -> Result<Json<Vec<x_api_usage::DailyXApiUsage>>, ApiError> {
81 let data = x_api_usage::get_daily_usage_for(&state.db, &ctx.account_id, params.days).await?;
82 Ok(Json(data))
83}
84
85pub async fn x_api_by_endpoint(
87 State(state): State<Arc<AppState>>,
88 ctx: AccountContext,
89 Query(params): Query<DaysQuery>,
90) -> Result<Json<Vec<x_api_usage::EndpointBreakdown>>, ApiError> {
91 let data =
92 x_api_usage::get_endpoint_breakdown_for(&state.db, &ctx.account_id, params.days).await?;
93 Ok(Json(data))
94}