implement stripe and idenfy webhooks support
This commit is contained in:
		
							
								
								
									
										189
									
								
								cmd/dispatcher.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								cmd/dispatcher.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,189 @@ | ||||
| use clap::Parser; | ||||
| use rhai_client::{RhaiClient, RhaiClientBuilder}; | ||||
| use log::{error, info}; | ||||
| use std::io::{self, Write}; | ||||
| use std::time::Duration; | ||||
|  | ||||
| #[derive(Parser, Debug)] | ||||
| #[command(author, version, about = "Circles Client - Rhai script execution client", long_about = None)] | ||||
| struct Args { | ||||
|     /// Caller public key (caller ID) | ||||
|     #[arg(short = 'c', long = "caller-key", help = "Caller public key (your identity)")] | ||||
|     caller_public_key: String, | ||||
|  | ||||
|     /// Circle public key (context ID) | ||||
|     #[arg(short = 'k', long = "circle-key", help = "Circle public key (execution context)")] | ||||
|     circle_public_key: String, | ||||
|  | ||||
|     /// Worker public key (defaults to circle public key if not provided) | ||||
|     #[arg(short = 'w', long = "worker-key", help = "Worker public key (defaults to circle key)")] | ||||
|     worker_public_key: Option<String>, | ||||
|  | ||||
|     /// Redis URL | ||||
|     #[arg(short, long, default_value = "redis://localhost:6379", help = "Redis connection URL")] | ||||
|     redis_url: String, | ||||
|  | ||||
|     /// Rhai script to execute | ||||
|     #[arg(short, long, help = "Rhai script to execute")] | ||||
|     script: Option<String>, | ||||
|  | ||||
|     /// Path to Rhai script file | ||||
|     #[arg(short, long, help = "Path to Rhai script file")] | ||||
|     file: Option<String>, | ||||
|  | ||||
|     /// Timeout for script execution (in seconds) | ||||
|     #[arg(short, long, default_value = "30", help = "Timeout for script execution in seconds")] | ||||
|     timeout: u64, | ||||
|  | ||||
|     /// Increase verbosity (can be used multiple times) | ||||
|     #[arg(short, long, action = clap::ArgAction::Count, help = "Increase verbosity (-v for debug, -vv for trace)")] | ||||
|     verbose: u8, | ||||
| } | ||||
|  | ||||
| #[tokio::main] | ||||
| async fn main() -> Result<(), Box<dyn std::error::Error>> { | ||||
|     let args = Args::parse(); | ||||
|  | ||||
|     // Configure logging based on verbosity level | ||||
|     let log_config = match args.verbose { | ||||
|         0 => "warn,circles_client=info,rhai_client=info", | ||||
|         1 => "info,circles_client=debug,rhai_client=debug", | ||||
|         2 => "debug", | ||||
|         _ => "trace", | ||||
|     }; | ||||
|      | ||||
|     std::env::set_var("RUST_LOG", log_config); | ||||
|     env_logger::init(); | ||||
|  | ||||
|     // Use worker key or default to circle key | ||||
|     let worker_key = args.worker_public_key.unwrap_or_else(|| args.circle_public_key.clone()); | ||||
|  | ||||
|     info!("🔗 Starting Circles Client"); | ||||
|     info!("📋 Configuration:"); | ||||
|     info!("   Caller Key: {}", args.caller_public_key); | ||||
|     info!("   Circle Key: {}", args.circle_public_key); | ||||
|     info!("   Worker Key: {}", worker_key); | ||||
|     info!("   Redis URL: {}", args.redis_url); | ||||
|     info!("   Timeout: {}s", args.timeout); | ||||
|     info!(); | ||||
|  | ||||
|     // Create the Rhai client | ||||
|     let client = RhaiClientBuilder::new() | ||||
|         .caller_id(&args.caller_public_key) | ||||
|         .redis_url(&args.redis_url) | ||||
|         .build()?; | ||||
|  | ||||
|     info!("✅ Connected to Redis at {}", args.redis_url); | ||||
|  | ||||
|     // Determine execution mode | ||||
|     if let Some(script_content) = args.script { | ||||
|         // Execute inline script | ||||
|         info!("📜 Executing inline script"); | ||||
|         execute_script(&client, &worker_key, script_content, args.timeout).await?; | ||||
|     } else if let Some(file_path) = args.file { | ||||
|         // Execute script from file | ||||
|         info!("📁 Loading script from file: {}", file_path); | ||||
|         let script_content = std::fs::read_to_string(&file_path) | ||||
|             .map_err(|e| format!("Failed to read script file '{}': {}", file_path, e))?; | ||||
|         execute_script(&client, &worker_key, script_content, args.timeout).await?; | ||||
|     } else { | ||||
|         // Interactive mode | ||||
|         info!("🎮 Entering interactive mode"); | ||||
|         info!("Type Rhai scripts and press Enter to execute. Type 'exit' or 'quit' to close."); | ||||
|         run_interactive_mode(&client, &worker_key, args.timeout).await?; | ||||
|     } | ||||
|  | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| async fn execute_script( | ||||
|     client: &RhaiClient, | ||||
|     worker_key: &str, | ||||
|     script: String, | ||||
|     timeout_secs: u64, | ||||
| ) -> Result<(), Box<dyn std::error::Error>> { | ||||
|     info!("⚡ Executing script: {:.50}...", script); | ||||
|      | ||||
|     let timeout = Duration::from_secs(timeout_secs); | ||||
|      | ||||
|     match client | ||||
|         .new_play_request() | ||||
|         .recipient_id(worker_key) | ||||
|         .script(&script) | ||||
|         .timeout(timeout) | ||||
|         .await_response() | ||||
|         .await | ||||
|     { | ||||
|         Ok(result) => { | ||||
|             info!("✅ Script execution completed"); | ||||
|             println!("Status: {}", result.status); | ||||
|             if let Some(output) = result.output { | ||||
|                 println!("Output: {}", output); | ||||
|             } | ||||
|             if let Some(error) = result.error { | ||||
|                 println!("Error: {}", error); | ||||
|             } | ||||
|         } | ||||
|         Err(e) => { | ||||
|             error!("❌ Script execution failed: {}", e); | ||||
|             return Err(Box::new(e)); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| async fn run_interactive_mode( | ||||
|     client: &RhaiClient, | ||||
|     worker_key: &str, | ||||
|     timeout_secs: u64, | ||||
| ) -> Result<(), Box<dyn std::error::Error>> { | ||||
|     let timeout = Duration::from_secs(timeout_secs); | ||||
|      | ||||
|     loop { | ||||
|         print!("rhai> "); | ||||
|         io::stdout().flush()?; | ||||
|          | ||||
|         let mut input = String::new(); | ||||
|         io::stdin().read_line(&mut input)?; | ||||
|          | ||||
|         let input = input.trim(); | ||||
|          | ||||
|         if input.is_empty() { | ||||
|             continue; | ||||
|         } | ||||
|          | ||||
|         if input == "exit" || input == "quit" { | ||||
|             info!("👋 Goodbye!"); | ||||
|             break; | ||||
|         } | ||||
|          | ||||
|         info!("⚡ Executing: {}", input); | ||||
|          | ||||
|         match client | ||||
|             .new_play_request() | ||||
|             .recipient_id(worker_key) | ||||
|             .script(input) | ||||
|             .timeout(timeout) | ||||
|             .await_response() | ||||
|             .await | ||||
|         { | ||||
|             Ok(result) => { | ||||
|                 println!("Status: {}", result.status); | ||||
|                 if let Some(output) = result.output { | ||||
|                     println!("Output: {}", output); | ||||
|                 } | ||||
|                 if let Some(error) = result.error { | ||||
|                     println!("Error: {}", error); | ||||
|                 } | ||||
|             } | ||||
|             Err(e) => { | ||||
|                 error!("❌ Execution failed: {}", e); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         println!(); // Add blank line for readability | ||||
|     } | ||||
|      | ||||
|     Ok(()) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user