systemprompt_cli/commands/core/content/analytics/
campaign.rs1use crate::cli_settings::CliConfig;
2use crate::commands::core::content::types::CampaignAnalyticsOutput;
3use crate::shared::CommandOutput;
4use anyhow::{Result, anyhow};
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(args: CampaignArgs, config: &CliConfig) -> Result<CommandOutput> {
18 let ctx = AppContext::new().await?;
19 execute_with_pool(args, ctx.db_pool(), config).await
20}
21
22pub async fn execute_with_pool(
23 args: CampaignArgs,
24 pool: &DbPool,
25 _config: &CliConfig,
26) -> Result<CommandOutput> {
27 let service = LinkAnalyticsService::new(pool)?;
28
29 let campaign_id = CampaignId::new(args.campaign_id.clone());
30 let performance = service
31 .get_campaign_performance(&campaign_id)
32 .await?
33 .ok_or_else(|| anyhow!("Campaign not found: {}", args.campaign_id))?;
34
35 let output = CampaignAnalyticsOutput {
36 campaign_id: performance.campaign_id,
37 total_clicks: performance.total_clicks,
38 link_count: performance.link_count,
39 unique_visitors: performance.unique_visitors.unwrap_or(0),
40 conversion_count: performance.conversion_count.unwrap_or(0),
41 };
42
43 Ok(CommandOutput::card_value("Campaign Analytics", &output))
44}