Skip to main content

systemprompt_cli/commands/core/content/analytics/
campaign.rs

1use crate::cli_settings::CliConfig;
2use crate::commands::core::content::types::CampaignAnalyticsOutput;
3use crate::shared::CommandResult;
4use anyhow::{anyhow, Result};
5use clap::Args;
6use systemprompt_content::LinkAnalyticsService;
7use systemprompt_database::DbPool;
8use systemprompt_identifiers::CampaignId;
9use systemprompt_runtime::AppContext;
10
11#[derive(Debug, Args)]
12pub struct CampaignArgs {
13    #[arg(help = "Campaign ID")]
14    pub campaign_id: String,
15}
16
17pub async fn execute(
18    args: CampaignArgs,
19    config: &CliConfig,
20) -> Result<CommandResult<CampaignAnalyticsOutput>> {
21    let ctx = AppContext::new().await?;
22    execute_with_pool(args, ctx.db_pool(), config).await
23}
24
25pub async fn execute_with_pool(
26    args: CampaignArgs,
27    pool: &DbPool,
28    _config: &CliConfig,
29) -> Result<CommandResult<CampaignAnalyticsOutput>> {
30    let service = LinkAnalyticsService::new(pool)?;
31
32    let campaign_id = CampaignId::new(args.campaign_id.clone());
33    let performance = service
34        .get_campaign_performance(&campaign_id)
35        .await?
36        .ok_or_else(|| anyhow!("Campaign not found: {}", args.campaign_id))?;
37
38    let output = CampaignAnalyticsOutput {
39        campaign_id: performance.campaign_id,
40        total_clicks: performance.total_clicks,
41        link_count: performance.link_count,
42        unique_visitors: performance.unique_visitors.unwrap_or(0),
43        conversion_count: performance.conversion_count.unwrap_or(0),
44    };
45
46    Ok(CommandResult::card(output).with_title("Campaign Analytics"))
47}