diff --git a/.gitignore b/.gitignore index 080e076a..b75ada9c 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,10 @@ evals/results/ # Agent-specific local skills (installed via `npx skills add`) .claude/skills/ .cursor/ + +# C# / .NET +bin/ +obj/ +*.user +*.suo +sdk/csharp/examples/Examples.csproj diff --git a/sdk/csharp/examples/Main.cs b/sdk/csharp/examples/Main.cs deleted file mode 100644 index 5c8b11cc..00000000 --- a/sdk/csharp/examples/Main.cs +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Echo bot example demonstrating the Pachca C# SDK. - * - * Runs 8 steps that exercise the core API patterns: - * create, read, nested resource, idempotent POST, thread reply, pin, update, unpin. - * - * Usage: - * - * PACHCA_TOKEN=your_token PACHCA_CHAT_ID=12345 dotnet run - */ - -using Pachca.Sdk; - -var token = Environment.GetEnvironmentVariable("PACHCA_TOKEN") - ?? throw new InvalidOperationException("Set PACHCA_TOKEN environment variable"); -var chatId = int.Parse( - Environment.GetEnvironmentVariable("PACHCA_CHAT_ID") - ?? throw new InvalidOperationException("Set PACHCA_CHAT_ID environment variable")); - -using var client = new PachcaClient(token); - -// -- Step 1: POST -- Create a message -Console.WriteLine("1. Creating message..."); -var created = await client.Messages.CreateMessageAsync(new MessageCreateRequest -{ - Message = new MessageCreateRequestMessage - { - EntityId = chatId, - Content = "SDK test C# \ud83d\ude80", - } -}); -var msgId = created.Id; -Console.WriteLine($" Created message ID: {msgId}"); - -// -- Step 2: GET -- Read the message back -Console.WriteLine("2. Reading message..."); -var msg = await client.Messages.GetMessageAsync(msgId); -Console.WriteLine($" Got message: \"{msg.Content}\""); - -// -- Step 3: POST -- Add a reaction (nested resource) -Console.WriteLine("3. Adding reaction..."); -await client.Reactions.AddReactionAsync(msgId, new ReactionRequest { Code = "\ud83d\udc40" }); -Console.WriteLine(" Added reaction \ud83d\udc40"); - -// -- Step 4: POST -- Create a thread (idempotent) -Console.WriteLine("4. Creating thread..."); -var thread = await client.Threads.CreateThreadAsync(msgId); -Console.WriteLine($" Thread ID: {thread.Id}"); - -// -- Step 5: POST -- Reply inside the thread -Console.WriteLine("5. Replying in thread..."); -var reply = await client.Messages.CreateMessageAsync(new MessageCreateRequest -{ - Message = new MessageCreateRequestMessage - { - EntityType = MessageEntityType.Thread, - EntityId = thread.Id, - Content = $"Echo: {msg.Content}", - } -}); -var replyId = reply.Id; -Console.WriteLine($" Reply ID: {replyId}"); - -// -- Step 6: POST -- Pin the original message -Console.WriteLine("6. Pinning message..."); -await client.Messages.PinMessageAsync(msgId); -Console.WriteLine(" Pinned"); - -// -- Step 7: PUT -- Edit the reply -Console.WriteLine("7. Updating reply..."); -await client.Messages.UpdateMessageAsync(replyId, new MessageUpdateRequest -{ - Message = new MessageUpdateRequestMessage - { - Content = $"{reply.Content} (processed at {DateTimeOffset.UtcNow})", - } -}); -Console.WriteLine(" Updated"); - -// -- Step 8: DELETE -- Unpin the original message -Console.WriteLine("8. Unpinning message..."); -await client.Messages.UnpinMessageAsync(msgId); -Console.WriteLine(" Unpinned"); - -Console.WriteLine("\nDone! All 8 steps completed."); diff --git a/sdk/csharp/examples/MainExample.cs b/sdk/csharp/examples/MainExample.cs new file mode 100644 index 00000000..3e38f8d8 --- /dev/null +++ b/sdk/csharp/examples/MainExample.cs @@ -0,0 +1,92 @@ +/** + * Echo bot example demonstrating the Pachca C# SDK. + * + * Runs 8 steps that exercise the core API patterns: + * create, read, nested resource, idempotent POST, thread reply, pin, update, unpin. + * + * Usage: + * + * PACHCA_TOKEN=your_token PACHCA_CHAT_ID=12345 dotnet run -- main + */ + +namespace Pachca.Sdk.Examples; + +public static class MainExample +{ + public static async Task RunAsync() + { + var token = Environment.GetEnvironmentVariable("PACHCA_TOKEN") + ?? throw new InvalidOperationException("Set PACHCA_TOKEN environment variable"); + var chatId = int.Parse( + Environment.GetEnvironmentVariable("PACHCA_CHAT_ID") + ?? throw new InvalidOperationException("Set PACHCA_CHAT_ID environment variable")); + + using var client = new PachcaClient(token); + + // -- Step 1: POST -- Create a message + Console.WriteLine("1. Creating message..."); + var created = await client.Messages.CreateMessageAsync(new MessageCreateRequest + { + Message = new MessageCreateRequestMessage + { + EntityId = chatId, + Content = "SDK test C# \ud83d\ude80", + } + }); + var msgId = created.Id; + Console.WriteLine($" Created message ID: {msgId}"); + + // -- Step 2: GET -- Read the message back + Console.WriteLine("2. Reading message..."); + var msg = await client.Messages.GetMessageAsync(msgId); + Console.WriteLine($" Got message: \"{msg.Content}\""); + + // -- Step 3: POST -- Add a reaction (nested resource) + Console.WriteLine("3. Adding reaction..."); + await client.Reactions.AddReactionAsync(msgId, new ReactionRequest { Code = "\ud83d\udc40" }); + Console.WriteLine(" Added reaction \ud83d\udc40"); + + // -- Step 4: POST -- Create a thread (idempotent) + Console.WriteLine("4. Creating thread..."); + var thread = await client.Threads.CreateThreadAsync(msgId); + Console.WriteLine($" Thread ID: {thread.Id}"); + + // -- Step 5: POST -- Reply inside the thread + Console.WriteLine("5. Replying in thread..."); + var reply = await client.Messages.CreateMessageAsync(new MessageCreateRequest + { + Message = new MessageCreateRequestMessage + { + EntityType = MessageEntityType.Thread, + EntityId = (int)thread.Id, + Content = $"Echo: {msg.Content}", + } + }); + var replyId = reply.Id; + Console.WriteLine($" Reply ID: {replyId}"); + + // -- Step 6: POST -- Pin the original message + Console.WriteLine("6. Pinning message..."); + await client.Messages.PinMessageAsync(msgId); + Console.WriteLine(" Pinned"); + + // -- Step 7: PUT -- Edit the reply + Console.WriteLine("7. Updating reply..."); + await client.Messages.UpdateMessageAsync(replyId, new MessageUpdateRequest + { + Message = new MessageUpdateRequestMessage + { + Content = $"{reply.Content} (processed at {DateTimeOffset.UtcNow})", + } + }); + Console.WriteLine(" Updated"); + + // -- Step 8: DELETE -- Unpin the original message + Console.WriteLine("8. Unpinning message..."); + await client.Messages.UnpinMessageAsync(msgId); + Console.WriteLine(" Unpinned"); + + Console.WriteLine("\nDone! All 8 steps completed."); + return 0; + } +} diff --git a/sdk/csharp/examples/Program.cs b/sdk/csharp/examples/Program.cs new file mode 100644 index 00000000..ddac88d5 --- /dev/null +++ b/sdk/csharp/examples/Program.cs @@ -0,0 +1,25 @@ +using Pachca.Sdk.Examples; + +var example = args.Length > 0 ? args[0].ToLowerInvariant() : "main"; + +return example switch +{ + "main" => await MainExample.RunAsync(), + "upload" => await UploadExample.RunAsync(), + _ => PrintUsage() +}; + +static int PrintUsage() +{ + Console.WriteLine("Usage: dotnet run -- "); + Console.WriteLine(); + Console.WriteLine("Examples:"); + Console.WriteLine(" main - Echo bot (create, read, react, thread, pin, update, unpin)"); + Console.WriteLine(" upload - File upload (requires PACHCA_FILE_PATH)"); + Console.WriteLine(); + Console.WriteLine("Environment variables:"); + Console.WriteLine(" PACHCA_TOKEN - API token (required)"); + Console.WriteLine(" PACHCA_CHAT_ID - Chat ID (required)"); + Console.WriteLine(" PACHCA_FILE_PATH - File path (upload only)"); + return 1; +} diff --git a/sdk/csharp/examples/Upload.cs b/sdk/csharp/examples/Upload.cs deleted file mode 100644 index e286711a..00000000 --- a/sdk/csharp/examples/Upload.cs +++ /dev/null @@ -1,77 +0,0 @@ -/** - * File upload example demonstrating the Pachca C# SDK. - * - * Uploads a local file and sends it as a message attachment. - * - * Usage: - * - * PACHCA_TOKEN=your_token PACHCA_CHAT_ID=12345 PACHCA_FILE_PATH=./photo.png dotnet run - */ - -using Pachca.Sdk; - -var token = Environment.GetEnvironmentVariable("PACHCA_TOKEN") - ?? throw new InvalidOperationException("Set PACHCA_TOKEN environment variable"); -var chatId = int.Parse( - Environment.GetEnvironmentVariable("PACHCA_CHAT_ID") - ?? throw new InvalidOperationException("Set PACHCA_CHAT_ID environment variable")); -var filePath = Environment.GetEnvironmentVariable("PACHCA_FILE_PATH") - ?? throw new InvalidOperationException("Set PACHCA_FILE_PATH environment variable"); - -var fileName = Path.GetFileName(filePath); - -using var client = new PachcaClient(token); - -// -- Step 1: Read the local file -Console.WriteLine($"1. Reading file: {filePath}"); -var fileBytes = await File.ReadAllBytesAsync(filePath); -var fileSize = fileBytes.Length; -Console.WriteLine($" Size: {fileSize} bytes"); - -// -- Step 2: Get upload params -Console.WriteLine("2. Getting upload params..."); -var uploadParams = await client.Common.GetUploadParamsAsync(); -var key = uploadParams.Key.Replace("${filename}", fileName); -Console.WriteLine($" Got direct_url: {uploadParams.DirectUrl}"); - -// -- Step 3: Upload the file via SDK -Console.WriteLine("3. Uploading file..."); -await client.Common.UploadFileAsync( - uploadParams.DirectUrl, - new FileUploadRequest - { - ContentDisposition = uploadParams.ContentDisposition, - Acl = uploadParams.Acl, - Policy = uploadParams.Policy, - XAmzCredential = uploadParams.XAmzCredential, - XAmzAlgorithm = uploadParams.XAmzAlgorithm, - XAmzDate = uploadParams.XAmzDate, - XAmzSignature = uploadParams.XAmzSignature, - Key = key, - File = fileBytes, - }); -Console.WriteLine($" Uploaded, key: {key}"); - -// -- Step 4: Send message with the file attached -Console.WriteLine("4. Sending message with attachment..."); -var msg = await client.Messages.CreateMessageAsync(new MessageCreateRequest -{ - Message = new MessageCreateRequestMessage - { - EntityId = chatId, - Content = $"File upload test: {fileName} \ud83d\ude80", - Files = new List - { - new() - { - Key = key, - Name = fileName, - FileType = FileType.File, - Size = fileSize, - } - }, - } -}); -Console.WriteLine($" Message ID: {msg.Id}"); - -Console.WriteLine("\nDone! File uploaded and sent."); diff --git a/sdk/csharp/examples/UploadExample.cs b/sdk/csharp/examples/UploadExample.cs new file mode 100644 index 00000000..c6ddf404 --- /dev/null +++ b/sdk/csharp/examples/UploadExample.cs @@ -0,0 +1,84 @@ +/** + * File upload example demonstrating the Pachca C# SDK. + * + * Uploads a local file and sends it as a message attachment. + * + * Usage: + * + * PACHCA_TOKEN=your_token PACHCA_CHAT_ID=12345 PACHCA_FILE_PATH=./photo.png dotnet run -- upload + */ + +namespace Pachca.Sdk.Examples; + +public static class UploadExample +{ + public static async Task RunAsync() + { + var token = Environment.GetEnvironmentVariable("PACHCA_TOKEN") + ?? throw new InvalidOperationException("Set PACHCA_TOKEN environment variable"); + var chatId = int.Parse( + Environment.GetEnvironmentVariable("PACHCA_CHAT_ID") + ?? throw new InvalidOperationException("Set PACHCA_CHAT_ID environment variable")); + var filePath = Environment.GetEnvironmentVariable("PACHCA_FILE_PATH") + ?? throw new InvalidOperationException("Set PACHCA_FILE_PATH environment variable"); + + var fileName = System.IO.Path.GetFileName(filePath); + + using var client = new PachcaClient(token); + + // -- Step 1: Read the local file + Console.WriteLine($"1. Reading file: {filePath}"); + var fileBytes = await System.IO.File.ReadAllBytesAsync(filePath); + var fileSize = fileBytes.Length; + Console.WriteLine($" Size: {fileSize} bytes"); + + // -- Step 2: Get upload params + Console.WriteLine("2. Getting upload params..."); + var uploadParams = await client.Common.GetUploadParamsAsync(); + var key = uploadParams.Key.Replace("${filename}", fileName); + Console.WriteLine($" Got direct_url: {uploadParams.DirectUrl}"); + + // -- Step 3: Upload the file via SDK + Console.WriteLine("3. Uploading file..."); + await client.Common.UploadFileAsync( + uploadParams.DirectUrl, + new FileUploadRequest + { + ContentDisposition = uploadParams.ContentDisposition, + Acl = uploadParams.Acl, + Policy = uploadParams.Policy, + XAmzCredential = uploadParams.XAmzCredential, + XAmzAlgorithm = uploadParams.XAmzAlgorithm, + XAmzDate = uploadParams.XAmzDate, + XAmzSignature = uploadParams.XAmzSignature, + Key = key, + File = fileBytes, + }); + Console.WriteLine($" Uploaded, key: {key}"); + + // -- Step 4: Send message with the file attached + Console.WriteLine("4. Sending message with attachment..."); + var msg = await client.Messages.CreateMessageAsync(new MessageCreateRequest + { + Message = new MessageCreateRequestMessage + { + EntityId = chatId, + Content = $"File upload test: {fileName} \ud83d\ude80", + Files = new List + { + new() + { + Key = key, + Name = fileName, + FileType = FileType.File, + Size = fileSize, + } + }, + } + }); + Console.WriteLine($" Message ID: {msg.Id}"); + + Console.WriteLine("\nDone! File uploaded and sent."); + return 0; + } +}