Skip to main content

systemprompt_cli/commands/analytics/content/
mod.rs

1mod 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}