systemprompt_cli/commands/analytics/content/
mod.rs1mod stats;
2mod top;
3mod trends;
4
5use anyhow::Result;
6use clap::Subcommand;
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use systemprompt_runtime::DatabaseContext;
10
11use crate::CliConfig;
12
13#[derive(Debug, Subcommand)]
14pub enum ContentCommands {
15 #[command(about = "Content engagement statistics")]
16 Stats(stats::StatsArgs),
17
18 #[command(about = "Top performing content")]
19 Top(top::TopArgs),
20
21 #[command(about = "Content trends over time")]
22 Trends(trends::TrendsArgs),
23}
24
25#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
26pub struct ContentStatsOutput {
27 pub period: String,
28 pub total_views: i64,
29 pub unique_visitors: i64,
30 pub avg_time_on_page_seconds: i64,
31 pub avg_scroll_depth: f64,
32 pub total_clicks: i64,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
36pub struct TopContentRow {
37 pub content_id: String,
38 pub views: i64,
39 pub unique_visitors: i64,
40 pub avg_time_seconds: i64,
41 pub trend: String,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
45pub struct TopContentOutput {
46 pub period: String,
47 pub content: Vec<TopContentRow>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
51pub struct ContentTrendPoint {
52 pub timestamp: String,
53 pub views: i64,
54 pub unique_visitors: i64,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
58pub struct ContentTrendsOutput {
59 pub period: String,
60 pub group_by: String,
61 pub points: Vec<ContentTrendPoint>,
62}
63
64pub async fn execute(command: ContentCommands, config: &CliConfig) -> Result<()> {
65 match command {
66 ContentCommands::Stats(args) => stats::execute(args, config).await,
67 ContentCommands::Top(args) => top::execute(args, config).await,
68 ContentCommands::Trends(args) => trends::execute(args, config).await,
69 }
70}
71
72pub async fn execute_with_pool(
73 command: ContentCommands,
74 db_ctx: &DatabaseContext,
75 config: &CliConfig,
76) -> Result<()> {
77 match command {
78 ContentCommands::Stats(args) => stats::execute_with_pool(args, db_ctx, config).await,
79 ContentCommands::Top(args) => top::execute_with_pool(args, db_ctx, config).await,
80 ContentCommands::Trends(args) => trends::execute_with_pool(args, db_ctx, config).await,
81 }
82}