use composio_sdk::client::ComposioClient;
use composio_sdk::models::triggers::{
TriggerCreateParams, TriggerInstanceListParams, TriggerTypeListParams, WebhookVerifyParams,
};
use std::collections::HashMap;
use std::env;
use base64::Engine;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("COMPOSIO_API_KEY")
.expect("COMPOSIO_API_KEY environment variable not set");
let client = ComposioClient::builder()
.api_key(api_key)
.build()?;
println!("=== Composio Triggers Examples ===\n");
println!("1. Listing trigger types for GitHub...");
list_trigger_types(&client).await?;
println!("\n2. Getting specific trigger type details...");
get_trigger_type(&client).await?;
println!("\n3. Creating a trigger instance...");
println!("\n4. Listing active triggers...");
list_active_triggers(&client).await?;
println!("\n5. Managing trigger state...");
println!("\n6. Verifying webhook signature...");
verify_webhook_example(&client)?;
println!("\n=== All examples completed successfully! ===");
Ok(())
}
async fn list_trigger_types(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let params = TriggerTypeListParams {
toolkit_slugs: Some(vec!["github".to_string()]),
limit: Some(5),
..Default::default()
};
let response = client.list_trigger_types(params).await?;
println!("Found {} trigger types:", response.items.len());
for trigger_type in response.items {
println!(" - {} ({})", trigger_type.name, trigger_type.slug);
println!(" Type: {}", trigger_type.trigger_type);
println!(" Description: {}", trigger_type.description);
}
if let Some(cursor) = response.next_cursor {
println!(" Next cursor: {}", cursor);
}
Ok(())
}
async fn get_trigger_type(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let trigger_slug = "GITHUB_COMMIT_EVENT";
match client.get_trigger_type(trigger_slug).await {
Ok(trigger_type) => {
println!("Trigger: {} ({})", trigger_type.name, trigger_type.slug);
println!("Type: {}", trigger_type.trigger_type);
println!("Toolkit: {}", trigger_type.toolkit.slug);
println!("Description: {}", trigger_type.description);
if let Some(instructions) = &trigger_type.instructions {
println!("Instructions: {}", instructions);
}
println!("\nConfiguration schema:");
println!("{}", serde_json::to_string_pretty(&trigger_type.config)?);
println!("\nPayload schema:");
println!("{}", serde_json::to_string_pretty(&trigger_type.payload)?);
}
Err(e) => {
println!("Error getting trigger type: {}", e);
}
}
Ok(())
}
#[allow(dead_code)]
async fn create_trigger(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let mut trigger_config = HashMap::new();
trigger_config.insert("repo".to_string(), serde_json::json!("composio"));
trigger_config.insert("owner".to_string(), serde_json::json!("composio"));
let params = TriggerCreateParams {
slug: "GITHUB_COMMIT_EVENT".to_string(),
user_id: Some("user_123".to_string()), connected_account_id: None,
trigger_config: Some(trigger_config),
toolkit_versions: None,
};
match client.create_trigger(params).await {
Ok(response) => {
println!("Trigger created successfully!");
println!(" ID: {}", response.id);
println!(" Trigger name: {}", response.trigger_name);
println!(" Connected account: {}", response.connected_account_id);
if let Some(user_id) = response.user_id {
println!(" User ID: {}", user_id);
}
}
Err(e) => {
println!("Error creating trigger: {}", e);
println!("Note: This requires a valid connected account for the user");
}
}
Ok(())
}
async fn list_active_triggers(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let params = TriggerInstanceListParams {
trigger_names: Some(vec!["GITHUB_COMMIT_EVENT".to_string()]),
show_disabled: Some(false),
limit: Some(10),
..Default::default()
};
match client.list_active_triggers(params).await {
Ok(response) => {
println!("Found {} active triggers:", response.items.len());
for trigger in response.items {
println!(" - ID: {}", trigger.id);
println!(" Trigger: {}", trigger.trigger_name);
println!(" Connected account: {}", trigger.connected_account_id);
if let Some(user_id) = &trigger.user_id {
println!(" User ID: {}", user_id);
}
if let Some(state) = &trigger.state {
println!(" State: {}", state);
}
if let Some(created_at) = &trigger.created_at {
println!(" Created: {}", created_at);
}
println!();
}
if let Some(cursor) = response.next_cursor {
println!(" Next cursor: {}", cursor);
}
}
Err(e) => {
println!("Error listing triggers: {}", e);
}
}
Ok(())
}
#[allow(dead_code)]
async fn manage_trigger_state(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let trigger_id = "ti_abc123";
println!("Disabling trigger {}...", trigger_id);
match client.disable_trigger(trigger_id).await {
Ok(_) => println!(" Trigger disabled successfully"),
Err(e) => println!(" Error disabling trigger: {}", e),
}
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
println!("Enabling trigger {}...", trigger_id);
match client.enable_trigger(trigger_id).await {
Ok(_) => println!(" Trigger enabled successfully"),
Err(e) => println!(" Error enabling trigger: {}", e),
}
Ok(())
}
fn verify_webhook_example(client: &ComposioClient) -> Result<(), Box<dyn std::error::Error>> {
let webhook_id = "msg_2mXqH9P8KQJKLdJKLdJKLd";
let webhook_timestamp = "1234567890";
let webhook_secret = "whsec_test_secret_key";
let payload = r#"{
"id": "evt_123",
"type": "composio.trigger.message",
"timestamp": "2024-01-01T00:00:00Z",
"metadata": {
"trigger_id": "ti_abc123",
"trigger_slug": "GITHUB_COMMIT_EVENT",
"user_id": "user_456",
"connected_account_id": "ca_789",
"auth_config_id": "ac_101",
"log_id": "log_202"
},
"data": {
"author": "john_doe",
"message": "Fix bug in authentication",
"sha": "abc123def456"
}
}"#;
use hmac::{Hmac, Mac};
use sha2::Sha256;
type HmacSha256 = Hmac<Sha256>;
let to_sign = format!("{}.{}.{}", webhook_id, webhook_timestamp, payload);
let mut mac = HmacSha256::new_from_slice(webhook_secret.as_bytes())?;
mac.update(to_sign.as_bytes());
let signature_bytes = mac.finalize().into_bytes();
let signature_b64 = base64::engine::general_purpose::STANDARD.encode(&signature_bytes);
let webhook_signature = format!("v1,{}", signature_b64);
println!("Webhook verification example:");
println!(" ID: {}", webhook_id);
println!(" Timestamp: {}", webhook_timestamp);
println!(" Signature: {}...", &webhook_signature[..30]);
let params = WebhookVerifyParams {
id: webhook_id.to_string(),
payload: payload.to_string(),
signature: webhook_signature,
timestamp: webhook_timestamp.to_string(),
secret: webhook_secret.to_string(),
tolerance: Some(999999), };
match client.verify_webhook(params) {
Ok(result) => {
println!("\n✓ Webhook verified successfully!");
println!(" Version: {:?}", result.version);
println!(" Trigger slug: {}", result.payload.trigger_slug);
println!(" User ID: {}", result.payload.user_id);
println!(" Toolkit: {}", result.payload.toolkit_slug);
if let Some(payload_data) = &result.payload.payload {
println!("\n Event data:");
println!("{}", serde_json::to_string_pretty(payload_data)?);
}
}
Err(e) => {
println!("✗ Webhook verification failed: {}", e);
}
}
Ok(())
}