-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cleanup Project Structure To Meet .NET Standards #352
base: main
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request encompasses a comprehensive update to the project's structure, including the deletion of several Visual Studio solution and project files, specifically Changes
Possibly related PRs
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Some comments:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Outside diff range and nitpick comments (100)
examples/Deepgram.Examples.Analyze.Sentiment/Deepgram.Examples.Analyze.Sentiment.csproj (1)
1-12
: Consider adding common propertiesTo align better with .NET standards, consider adding these common properties:
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <Nullable>enable</Nullable> + <ImplicitUsings>enable</ImplicitUsings> + <IsPackable>false</IsPackable> + <PublishAot>false</PublishAot> </PropertyGroup>These additions will:
- Enable implicit usings (C# 10+ feature for cleaner code)
- Explicitly mark as non-packable (it's an example project)
- Explicitly disable AOT compilation (examples typically don't need it)
examples/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld/Program.cs (4)
5-8
: Consider reorganizing using directives and modernizing namespace declaration.To better align with .NET conventions, consider:
- Grouping System namespaces first
- Using file-scoped namespace declaration
using System; using System.Threading.Tasks; using Deepgram; using Deepgram.Models.Speak.v1.REST; -namespace SampleApp -{ +namespace SampleApp;
Line range hint
31-32
: Remove redundant commented code.The commented WriteLine is identical to the active line below it and should be removed.
- //Console.WriteLine(response); Console.WriteLine(response);
Line range hint
16-36
: Add error handling and API key validation.The example would be more robust with proper error handling and API key validation. Consider:
- Validating the API key existence
- Adding try-catch for potential API exceptions
- Removing the blocking Console.ReadKey()
static async Task Main(string[] args) { + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + Console.WriteLine("Please set the DEEPGRAM_API_KEY environment variable"); + return; + } + // Initialize Library with default logging // Normal logging is "Info" level Library.Initialize(); + try + { // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable var deepgramClient = ClientFactory.CreateSpeakRESTClient(); var response = await deepgramClient.ToFile( new TextSource("Hello World!"), "test.mp3", new SpeakSchema() { Model = "aura-asteria-en", }); Console.WriteLine(response); - Console.ReadKey(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + finally + { // Teardown Library Library.Terminate(); + } }
Add file path validation to maintain consistency with other examples
Looking at the codebase, all other examples implement input file validation using
File.Exists()
. For output files in text-to-speech, we should similarly validate the path and warn about overwrites:var outputFile = "test.mp3"; if (File.Exists(outputFile)) { Console.WriteLine($"Warning: {outputFile} will be overwritten"); } var response = await deepgramClient.ToFile( new TextSource("Hello World!"), outputFile, new SpeakSchema() { Model = "aura-asteria-en", });🔗 Analysis chain
Line range hint
22-29
: Consider adding output file path validation.The example writes to "test.mp3" without checking if the path is writable or if the file already exists.
+ var outputFile = "test.mp3"; + if (File.Exists(outputFile)) + { + Console.WriteLine($"Warning: {outputFile} will be overwritten"); + } + var response = await deepgramClient.ToFile( new TextSource("Hello World!"), - "test.mp3", + outputFile, new SpeakSchema()
Let me check the actual implementation in these files to see how they handle file operations.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if other examples in the codebase implement file path validation rg -l "File\.(Exists|Create)" --type csLength of output: 572
Script:
#!/bin/bash # Check how these examples implement file operations rg "File\.(Exists|Create)" -A 3 --type csLength of output: 3807
examples/Deepgram.Examples.SpeechToText.Rest.Url/Program.cs (4)
5-10
: Consider organizing using directives by namespace hierarchy.For better readability and .NET conventions, consider grouping System namespaces separately from Deepgram namespaces.
-using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Deepgram; -using Deepgram.Models.Listen.v1.REST; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +using Deepgram; +using Deepgram.Models.Listen.v1.REST;
Line range hint
14-17
: Add XML documentation comments for the Program class.Following .NET conventions, public types should be documented with XML comments.
+/// <summary> +/// Example program demonstrating Deepgram's REST API usage for URL-based transcription. +/// </summary> class Program
Line range hint
18-41
: Add error handling and implement .NET best practices.Several improvements can be made to align with .NET standards and best practices:
- Add try-catch block for error handling
- Support cancellation tokens for async operations
- Extract configuration values to constants
- Implement proper resource disposal with
using
statementsHere's a suggested implementation:
- static async Task Main(string[] args) + private const string AudioUrl = "https://dpgr.am/bueller.wav"; + private const string ModelVersion = "nova-2"; + + static async Task Main(string[] args) { - // Initialize Library with default logging - // Normal logging is "Info" level - Library.Initialize(); + try + { + Library.Initialize(); + using var cts = new CancellationTokenSource(); + Console.CancelKeyPress += (s, e) => + { + e.Cancel = true; + cts.Cancel(); + }; - // create a ListenRESTClient directly (without using the factory method) with a API Key - // set using the "DEEPGRAM_API_KEY" environment variable - var deepgramClient = new ListenRESTClient(); + using var deepgramClient = new ListenRESTClient(); - var customOptions = new Dictionary<string, string>(); - customOptions["smart_format"] = "true"; + var customOptions = new Dictionary<string, string> + { + ["smart_format"] = "true" + }; - var response = await deepgramClient.TranscribeUrl( - new UrlSource("https://dpgr.am/bueller.wav"), - new PreRecordedSchema() - { - Model = "nova-2", - }, - null, // use the default timeout - customOptions); + var response = await deepgramClient.TranscribeUrl( + new UrlSource(AudioUrl), + new PreRecordedSchema + { + Model = ModelVersion, + }, + null, + customOptions, + cts.Token); - Console.WriteLine(response); - Console.ReadKey(); + Console.WriteLine(response); + Console.WriteLine("Press any key to exit..."); + Console.ReadKey(); + } + catch (OperationCanceledException) + { + Console.WriteLine("Operation cancelled by user."); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: {ex.Message}"); + } + finally + { + Library.Terminate(); + } }
⚠️ The example audio URL is not accessibleThe example URL
https://dpgr.am/bueller.wav
redirects to a non-functioning endpoint, resulting in a 404 error. This will cause the example to fail for users trying to test the code.
- The URL
https://dpgr.am/bueller.wav
redirects tohttps://dg-shorturls.fly.dev/redirect?path=bueller.wav
- The final destination returns a 404 HTTP status code
- Consider updating the example to use a consistently available audio file URL
🔗 Analysis chain
Line range hint
18-41
: Verify the API endpoint URL accessibility.The hard-coded URL should be verified to ensure it's consistently available for example purposes.
Let me follow the redirect URL to verify the final destination and accessibility of the audio file.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check if the audio URL is accessible curl -I https://dpgr.am/bueller.wavLength of output: 575
Script:
#!/bin/bash # Description: Follow redirects and check final audio URL curl -IL https://dpgr.am/bueller.wavLength of output: 886
examples/Deepgram.Examples.Analyze.Summary/Program.cs (1)
Line range hint
14-42
: Enhance error handling and resource management.While the basic functionality is present, there are several areas that could be improved to make this example more robust and maintainable:
- Consider using command-line arguments for the file path instead of hardcoding it
- Add proper exception handling for the API call
- Ensure proper cleanup in all code paths
- Remove the blocking
Console.ReadKey()
Here's a suggested improvement:
public static async Task Main(string[] args) { - // Initialize Library with default logging - // Normal logging is "Info" level - Library.Initialize(); + try + { + Library.Initialize(); + + if (args.Length == 0) + { + Console.WriteLine("Error: Please provide the path to the text file as an argument."); + return; + } + + var filePath = args[0]; + if (!File.Exists(filePath)) + { + Console.WriteLine($"Error: File '{filePath}' not found."); + return; + } - // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable - var deepgramClient = ClientFactory.CreateAnalyzeClient(); + var deepgramClient = ClientFactory.CreateAnalyzeClient(); + var audioData = await File.ReadAllBytesAsync(filePath); + + try + { + var response = await deepgramClient.AnalyzeFile( + audioData, + new AnalyzeSchema() + { + Language = "en", + Summarize = true, + }); - // check to see if the file exists - if (!File.Exists(@"conversation.txt")) - { - Console.WriteLine("Error: File 'conversation.txt' not found."); - return; + Console.WriteLine(response); + } + catch (Exception ex) + { + Console.WriteLine($"Error during API call: {ex.Message}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Initialization error: {ex.Message}"); + } + finally + { + Library.Terminate(); } - - var audioData = File.ReadAllBytes(@"conversation.txt"); - var response = await deepgramClient.AnalyzeFile( - audioData, - new AnalyzeSchema() - { - Language = "en", - Summarize = true, - }); - - Console.WriteLine(response); - Console.ReadKey(); - - // Teardown Library - Library.Terminate(); }examples/Deepgram.Examples.Analyze.Sentiment/Program.cs (4)
12-14
: Consider using top-level statements for a more concise example.While the current implementation is correct, consider using C# top-level statements to make the example more approachable for newcomers. This would eliminate the need for explicit Program class and Main method declarations.
Example of top-level statements:
-namespace Deepgram.Examples.Analyze.Sentiment -{ - public static class Program - { - public static async Task Main(string[] args) - { - // Initialize Library with default logging +// Initialize Library with default logging
Line range hint
24-26
: Use command-line arguments or configuration for file path.The hardcoded file path
conversation.txt
might cause issues across different environments. Consider accepting the file path as a command-line argument or through configuration.-if (!File.Exists(@"conversation.txt")) +if (args.Length == 0) +{ + Console.WriteLine("Error: Please provide the path to the conversation file."); + return; +} +if (!File.Exists(args[0])) { - Console.WriteLine("Error: File 'conversation.txt' not found."); + Console.WriteLine($"Error: File '{args[0]}' not found."); return; }
Line range hint
28-35
: Add error handling and use appropriate file reading method.The code needs the following improvements:
- Add try-catch for API calls
- Use ReadAllText instead of ReadAllBytes for text files
-var audioData = File.ReadAllBytes(@"conversation.txt"); -var response = await deepgramClient.AnalyzeFile( - audioData, - new AnalyzeSchema() - { - Language = "en", - Sentiment = true, - }); +try +{ + var text = await File.ReadAllTextAsync(args[0]); + var response = await deepgramClient.AnalyzeFile( + text, + new AnalyzeSchema() + { + Language = "en", + Sentiment = true, + }); + Console.WriteLine(response); +} +catch (Exception ex) +{ + Console.WriteLine($"Error: {ex.Message}"); + return; +}
Line range hint
37-38
: Remove Console.ReadKey() in example code.The
Console.ReadKey()
call is typically used during development/debugging and should not be included in example code as it can confuse users about its necessity.Console.WriteLine(response); -Console.ReadKey();
examples/Deepgram.Examples.SpeechToText.Rest.Topic/Program.cs (4)
5-8
: Consider organizing imports following Microsoft conventions.Consider organizing the imports in the following order:
- System namespaces
- Third-party namespaces (Deepgram)
using System; using System.IO; using System.Threading.Tasks; + using Deepgram; using Deepgram.Models.Listen.v1.REST;
Line range hint
24-29
: Improve file path handling and error messaging.The hardcoded file path might cause issues across different environments. Consider:
- Using
Path.Combine()
for cross-platform compatibility- Making the file path configurable
- Providing more detailed error information
- if (!File.Exists(@"CallCenterPhoneCall.mp3")) + string audioFile = Path.Combine(AppContext.BaseDirectory, "CallCenterPhoneCall.mp3"); + if (!File.Exists(audioFile)) { - Console.WriteLine("Error: File 'CallCenterPhoneCall.mp3' not found."); + Console.WriteLine($"Error: Audio file not found at: {audioFile}"); + Console.WriteLine("Please ensure the audio file is placed in the correct location."); return; }
Line range hint
31-42
: Add proper error handling and resource management.The current implementation lacks proper error handling and resource management. Consider:
- Using try-catch blocks for file operations and API calls
- Implementing proper resource disposal with
using
statements- Adding cancellation support for long-running operations
- var audioData = File.ReadAllBytes(@"CallCenterPhoneCall.mp3"); - var response = await deepgramClient.TranscribeFile( - audioData, - new PreRecordedSchema() - { - Model = "nova-2", - Punctuate = true, - Topics = true, - }); - - Console.WriteLine(response); - Console.ReadKey(); - - // Teardown Library - Library.Terminate(); + try + { + using var cts = new CancellationTokenSource(); + Console.CancelKeyPress += (s, e) => + { + e.Cancel = true; + cts.Cancel(); + }; + + byte[] audioData; + using (var fileStream = new FileStream(audioFile, FileMode.Open, FileAccess.Read)) + { + audioData = new byte[fileStream.Length]; + await fileStream.ReadAsync(audioData, 0, (int)fileStream.Length, cts.Token); + } + + var response = await deepgramClient.TranscribeFile( + audioData, + new PreRecordedSchema() + { + Model = "nova-2", + Punctuate = true, + Topics = true, + }, + cts.Token); + + Console.WriteLine(response); + Console.WriteLine("\nPress any key to exit..."); + Console.ReadKey(); + } + catch (OperationCanceledException) + { + Console.WriteLine("\nOperation cancelled by user."); + } + catch (Exception ex) + { + Console.WriteLine($"\nError: {ex.Message}"); + } + finally + { + Library.Terminate(); + }
Line range hint
19-20
: Consider adding configuration validation.The API key retrieval from environment variables should include validation to prevent runtime errors.
// use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + Console.WriteLine("Error: DEEPGRAM_API_KEY environment variable is not set."); + return; + } var deepgramClient = ClientFactory.CreateListenRESTClient();examples/Deepgram.Examples.SpeechToText.Rest.Intent/Program.cs (4)
Line range hint
15-21
: Add error handling for missing API key and improve comments.
- The comment about logging levels is redundant. Consider removing or clarifying.
- Add error handling for cases where the API key environment variable is not set.
// Initialize Library with default logging -// Normal logging is "Info" level Library.Initialize(); -// use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable -var deepgramClient = ClientFactory.CreateListenRESTClient(); +// Create client using API key from DEEPGRAM_API_KEY environment variable +var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); +if (string.IsNullOrEmpty(apiKey)) +{ + Console.WriteLine("Error: DEEPGRAM_API_KEY environment variable not set."); + return; +} +var deepgramClient = ClientFactory.CreateListenRESTClient();
Line range hint
23-28
: Improve file handling for better robustness.Consider the following improvements:
- Accept file path as a command-line argument instead of hardcoding
- Add file size checks to prevent out-of-memory issues with large files
- Use streaming for better memory efficiency
-if (!File.Exists(@"CallCenterPhoneCall.mp3")) +if (args.Length == 0) +{ + Console.WriteLine("Usage: dotnet run <audio-file-path>"); + return; +} + +var filePath = args[0]; +if (!File.Exists(filePath)) { - Console.WriteLine("Error: File 'CallCenterPhoneCall.mp3' not found."); + Console.WriteLine($"Error: File '{filePath}' not found."); return; } + +var fileInfo = new FileInfo(filePath); +if (fileInfo.Length > 100 * 1024 * 1024) // 100MB limit +{ + Console.WriteLine("Error: File size exceeds 100MB limit."); + return; +}
Line range hint
30-39
: Add error handling and improve response formatting.The transcription call needs proper error handling and the response could be formatted for better readability.
-var audioData = File.ReadAllBytes(@"CallCenterPhoneCall.mp3"); -var response = await deepgramClient.TranscribeFile( - audioData, - new PreRecordedSchema() - { - Model = "nova-2", - Punctuate = true, - Intents = true, - }); - -Console.WriteLine(response); +try +{ + var audioData = File.ReadAllBytes(filePath); + var response = await deepgramClient.TranscribeFile( + audioData, + new PreRecordedSchema() + { + Model = "nova-2", + Punctuate = true, + Intents = true, + }); + + Console.WriteLine("Transcription Results:"); + Console.WriteLine("---------------------"); + Console.WriteLine(response.ToString()); // Assuming there's a proper ToString() implementation +} +catch (Exception ex) +{ + Console.WriteLine($"Error during transcription: {ex.Message}"); + return; +}
Line range hint
41-42
: Ensure proper cleanup with try-finally.The library cleanup should be guaranteed using a try-finally block, and consider removing the Console.ReadKey() as it's not necessary for an example.
-Console.ReadKey(); - -// Teardown Library -Library.Terminate(); +finally +{ + // Teardown Library + Library.Terminate(); +}examples/Deepgram.Examples.SpeechToText.Rest.Summary/Program.cs (3)
Line range hint
14-24
: Add error handling for API key initialization.While using an environment variable for the API key is secure, the code should validate its presence and handle potential initialization failures.
Consider this improvement:
static async Task Main(string[] args) { // Initialize Library with default logging // Normal logging is "Info" level Library.Initialize(); + // Validate API key + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + Console.WriteLine("Error: DEEPGRAM_API_KEY environment variable not set"); + return; + } + + try + { // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable - var deepgramClient = ClientFactory.CreateListenRESTClient(); + var deepgramClient = ClientFactory.CreateListenRESTClient(); + } + catch (Exception ex) + { + Console.WriteLine($"Error initializing Deepgram client: {ex.Message}"); + return; + }
Line range hint
26-31
: Improve file handling for robustness and cross-platform compatibility.The current implementation has several potential issues:
- Hardcoded path may not work across platforms
- Loading entire file into memory could be problematic for large files
- No file size validation
Consider this more robust implementation:
- if (!File.Exists(@"CallCenterPhoneCall.mp3")) + var audioFile = Path.Combine(AppContext.BaseDirectory, "CallCenterPhoneCall.mp3"); + if (!File.Exists(audioFile)) { - Console.WriteLine("Error: File 'CallCenterPhoneCall.mp3' not found."); + Console.WriteLine($"Error: File '{audioFile}' not found."); return; } - var audioData = File.ReadAllBytes(@"CallCenterPhoneCall.mp3"); + var fileInfo = new FileInfo(audioFile); + if (fileInfo.Length > 100 * 1024 * 1024) // 100MB limit + { + Console.WriteLine("Error: File size exceeds 100MB limit."); + return; + } + + byte[] audioData; + using (var stream = new FileStream(audioFile, FileMode.Open, FileAccess.Read)) + { + audioData = new byte[stream.Length]; + await stream.ReadAsync(audioData, 0, (int)stream.Length); + }
Line range hint
33-47
: Enhance API usage with proper error handling and response formatting.The current implementation lacks error handling for the API call and could benefit from better response formatting.
Consider this improvement:
- var response = await deepgramClient.TranscribeFile( - audioData, - new PreRecordedSchema() - { - Model = "nova-2", - Punctuate = true, - Summarize = "v2", - }); - - Console.WriteLine(response); - Console.ReadKey(); + try + { + var response = await deepgramClient.TranscribeFile( + audioData, + new PreRecordedSchema() + { + Model = "nova-2", + Punctuate = true, + Summarize = "v2", + }); + + Console.WriteLine("Transcription Summary:"); + Console.WriteLine("--------------------"); + Console.WriteLine(response?.Results?.Summary ?? "No summary available"); + } + catch (Exception ex) + { + Console.WriteLine($"Error during transcription: {ex.Message}"); + } + finally + { + // Teardown Library + Library.Terminate(); + } - // Teardown Library - Library.Terminate();Also, consider removing
Console.ReadKey()
as it's not necessary for an example program and blocks the thread unnecessarily.examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Program.cs (3)
Line range hint
11-21
: Add error handling for API key configuration.While the code is functional, it could be more robust with proper error handling for the API key configuration.
Consider this improvement:
static async Task Main(string[] args) { // Initialize Library with default logging // Normal logging is "Info" level Library.Initialize(); + // Verify API key is configured + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + Console.WriteLine("Error: DEEPGRAM_API_KEY environment variable not set"); + return; + } + // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable var deepgramClient = ClientFactory.CreateListenRESTClient();
Line range hint
22-31
: Improve file handling robustness and resource management.The current implementation has several areas for improvement regarding file handling:
- Hardcoded file path may cause issues in different environments
- Loading entire file into memory could be problematic for large files
- Missing proper resource disposal
Consider this more robust implementation:
- if (!File.Exists(@"CallCenterPhoneCall.mp3")) + const string audioFile = "CallCenterPhoneCall.mp3"; + var filePath = Path.Combine(AppContext.BaseDirectory, audioFile); + + if (!File.Exists(filePath)) { - Console.WriteLine("Error: File 'CallCenterPhoneCall.mp3' not found."); + Console.WriteLine($"Error: File '{audioFile}' not found at: {filePath}"); return; } - var audioData = File.ReadAllBytes(@"CallCenterPhoneCall.mp3"); + // Check file size before loading + var fileInfo = new FileInfo(filePath); + if (fileInfo.Length > 100 * 1024 * 1024) // 100MB limit + { + Console.WriteLine($"Error: File size ({fileInfo.Length / 1024 / 1024}MB) exceeds recommended limit of 100MB"); + return; + } + + byte[] audioData; + using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) + { + audioData = new byte[fileStream.Length]; + await fileStream.ReadAsync(audioData, 0, (int)fileStream.Length); + }
Line range hint
32-46
: Enhance API interaction with proper error handling and response formatting.The current implementation could benefit from proper error handling and more user-friendly output formatting.
Consider this improvement:
- var response = await deepgramClient.TranscribeFile( - audioData, - new PreRecordedSchema() - { - Model = "nova-2", - Punctuate = true, - Utterances = true, - Sentiment = true, - }); - - Console.WriteLine(response); - Console.ReadKey(); + try + { + var response = await deepgramClient.TranscribeFile( + audioData, + new PreRecordedSchema() + { + Model = "nova-2", + Punctuate = true, + Utterances = true, + Sentiment = true, + }); + + // Format response for better readability + Console.WriteLine("Transcription Results:"); + Console.WriteLine("--------------------"); + Console.WriteLine($"Transcript: {response.Results?.Channels?[0]?.Alternatives?[0]?.Transcript}"); + Console.WriteLine("\nPress any key to exit..."); + + // Use GetAwaiter().GetResult() to properly wait in async context + Task.Run(() => Console.ReadKey()).GetAwaiter().GetResult(); + } + catch (Exception ex) + { + Console.WriteLine($"Error during transcription: {ex.Message}"); + } + finally + { + // Ensure cleanup runs even if an error occurs + Library.Terminate(); + } - - // Teardown Library - Library.Terminate();examples/Deepgram.Examples.Analyze.Topic/Program.cs (3)
5-7
: Consider organizing using directives according to .NET conventions.Group System namespaces together, followed by third-party namespaces:
-using System; -using System.IO; -using System.Threading.Tasks; +using System; +using System.IO; +using System.Threading.Tasks; + using Deepgram.Logger; using Deepgram.Models.Analyze.v1;
13-15
: LGTM! Changes align with .NET standards.The
public static
modifiers on theProgram
class follow .NET conventions for console applications. Note that thepublic
modifier onMain
is optional as it's implied for entry points, but it's fine to be explicit.
Line range hint
15-40
: Consider improving error handling and file path handling.A few suggestions to make the example more robust and maintainable:
- Add exception handling for API calls and file operations
- Use Path.Combine for file paths to ensure cross-platform compatibility
- Consider making the file path configurable
- Remove Console.ReadKey() as it blocks execution and complicates testing
Here's a suggested improvement:
public static async Task Main(string[] args) { + try + { // Initialize Library with default logging Library.Initialize(); var deepgramClient = new AnalyzeClient(); + string filePath = args.Length > 0 ? args[0] : "conversation.txt"; + filePath = Path.Combine(AppContext.BaseDirectory, filePath); - if (!File.Exists(@"conversation.txt")) + if (!File.Exists(filePath)) { - Console.WriteLine("Error: File 'conversation.txt' not found."); + Console.WriteLine($"Error: File '{filePath}' not found."); return; } - var audioData = File.ReadAllBytes(@"conversation.txt"); + var audioData = File.ReadAllBytes(filePath); var response = await deepgramClient.AnalyzeFile( audioData, new AnalyzeSchema() { Language = "en", Topics = true, }); Console.WriteLine(response); - Console.ReadKey(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + finally + { // Teardown Library Library.Terminate(); + } }examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Program.cs (4)
Line range hint
15-19
: Document debugging options in XML commentsConsider moving the logging level comments into XML documentation to make them more discoverable through IntelliSense.
class Program { + /// <summary> + /// Main entry point for the Deepgram Text-to-Speech example. + /// </summary> + /// <remarks> + /// Logging levels can be configured using Library.Initialize(): + /// - Default: Normal "Info" level logging + /// - Debug: Detailed debugging information + /// - Verbose: Very detailed logging for troubleshooting + /// </remarks> static async Task Main(string[] args)
Line range hint
29-36
: Make example more configurableConsider extracting the text content and model name into configuration variables at the top of the file. This would make the example more maintainable and demonstrate proper configuration practices.
class Program { + private const string SampleText = "How much wood could a woodchuck chuck? If a woodchuck could chuck wood? As much wood as a woodchuck could chuck, if a woodchuck could chuck wood."; + private const string ModelName = "aura-asteria-en"; + static async Task Main(string[] args) { // ... initialization code ... var response = await deepgramClient.ToFile( - new TextSource("How much wood could a woodchuck chuck? If a woodchuck could chuck wood? As much wood as a woodchuck could chuck, if a woodchuck could chuck wood."), + new TextSource(SampleText), "test.mp3", new SpeakSchema() { - Model = "aura-asteria-en", + Model = ModelName, });
Line range hint
38-43
: Add error handling for API callsThe example should demonstrate proper error handling for API calls to help users understand how to handle potential failures in production.
static async Task Main(string[] args) { Library.Initialize(); - var deepgramClient = new SpeakRESTClient(); + try + { + var deepgramClient = new SpeakRESTClient(); + var response = await deepgramClient.ToFile( + new TextSource(SampleText), + "test.mp3", + new SpeakSchema() + { + Model = ModelName, + }); + Console.WriteLine(response); + Console.ReadKey(); + } + catch (DeepgramException ex) + { + Console.WriteLine($"Deepgram API error: {ex.Message}"); + } + catch (Exception ex) + { + Console.WriteLine($"Unexpected error: {ex.Message}"); + } + finally + { + Library.Terminate(); + } - - // ... existing code ... - - Library.Terminate(); }
The review comment is valid - example should demonstrate proper API key configuration
Looking at the
SpeakRESTClient
implementation, while it does support a parameterless constructor, it's designed to accept an API key and client options. The example should demonstrate this best practice since:
- The client constructor explicitly supports API key configuration:
public SpeakRESTClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null)
- The commented-out code shows the intended pattern but was left incomplete
- Production usage would require proper API key configuration
Recommendations:
- Uncomment and complete the configuration code with environment variable usage
- Add comments explaining the configuration options
- Remove the parameterless constructor usage
🔗 Analysis chain
Line range hint
24-27
: Consider demonstrating proper API key configurationThe current implementation uses a parameterless constructor, which might not reflect best practices for production use. Consider demonstrating secure API key configuration using environment variables or configuration files.
Let me check the actual implementation of API key configuration in other examples to provide accurate guidance.
Let me check the actual implementation of the
SpeakRESTClient
constructor to understand the default behavior and best practices.
Let me try a different approach to check the client implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if there are other examples showing proper API key configuration rg -l "DeepgramHttpClientOptions" --type csLength of output: 1487
Script:
#!/bin/bash # Check implementation in tests and other examples rg -A 5 "DeepgramHttpClientOptions" examples/ tests/ --type csLength of output: 1588
Script:
#!/bin/bash # Check SpeakRESTClient implementation ast-grep --pattern 'public class SpeakRESTClient { $$$ }'Length of output: 61
Script:
#!/bin/bash # Check SpeakRESTClient implementation and constructor patterns rg -A 10 "class SpeakRESTClient" --type csLength of output: 475
examples/Deepgram.Examples.Analyze.Intent/Program.cs (4)
5-11
: Consider organizing using directivesWhile the using directives are appropriate for the functionality, consider grouping them by:
- System namespaces
- Third-party namespaces (Deepgram)
This improves readability and maintainability.
using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Deepgram.Models.Analyze.v1;
Line range hint
28-29
: Fix incorrect comment about timeout durationThe comment states "increase timeout to 60 seconds" but the code sets it to 120 seconds.
- // increase timeout to 60 seconds + // increase timeout to 120 seconds
Line range hint
19-47
: Consider improving error handling and configurationSeveral improvements could make this example more robust and maintainable:
- Add exception handling for API calls
- Make the file path configurable
- Consider removing the blocking
Console.ReadKey()
Here's a suggested improvement:
public static async Task Main(string[] args) { // Initialize Library with default logging // Normal logging is "Info" level Library.Initialize(); + try + { // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable var deepgramClient = ClientFactory.CreateAnalyzeClient(); + // Allow file path to be passed as argument or use default + string filePath = args.Length > 0 ? args[0] : "conversation.txt"; // check to see if the file exists - if (!File.Exists(@"conversation.txt")) + if (!File.Exists(filePath)) { - Console.WriteLine("Error: File 'conversation.txt' not found."); + Console.WriteLine($"Error: File '{filePath}' not found."); return; } // increase timeout to 120 seconds CancellationTokenSource cancelToken = new CancellationTokenSource(); cancelToken.CancelAfter(TimeSpan.FromSeconds(120)); - var audioData = File.ReadAllBytes(@"conversation.txt"); + var audioData = File.ReadAllBytes(filePath); var response = await deepgramClient.AnalyzeFile( audioData, new AnalyzeSchema() { Language = "en", Intents = true, }, cancelToken); Console.WriteLine(response); - Console.ReadKey(); + } + catch (Exception ex) + { + Console.WriteLine($"Error: {ex.Message}"); + } + finally + { // Teardown Library Library.Terminate(); + } }
Line range hint
22-27
: Add path validation for securityThe current file path handling could be vulnerable to path traversal attacks if user input is accepted. Consider adding path validation.
+ // Validate and normalize the file path + filePath = Path.GetFullPath(filePath); + if (!filePath.StartsWith(Path.GetFullPath(Directory.GetCurrentDirectory()))) + { + Console.WriteLine("Error: File path must be within the current directory."); + return; + }examples/Deepgram.Examples.SpeechToText.Rest.File/Program.cs (5)
Line range hint
19-23
: Consider enhancing logging documentation.While the comments explain logging levels, consider structuring them as XML documentation to provide better IntelliSense support:
- // Initialize Library with default logging - // Normal logging is "Info" level - //Library.Initialize(); - // OR very chatty logging - Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + /// <summary> + /// Available logging levels: + /// - LogLevel.Default: Normal logging (Info level) + /// - LogLevel.Debug: Detailed debugging information + /// - LogLevel.Verbose: Most detailed logging + /// </summary> + Library.Initialize(LogLevel.Debug);
Line range hint
28-33
: Improve file path handling for cross-platform compatibility.The current implementation uses a hardcoded file path which may not work across different operating systems. Consider:
- Using
Path.Combine
for cross-platform path handling- Making the file path configurable via command line arguments or environment variables
- Adding the audio file to the project resources
+ string audioFile = args.Length > 0 + ? args[0] + : Path.Combine(AppContext.BaseDirectory, "Bueller-Life-moves-pretty-fast.wav"); + - if (!File.Exists(@"Bueller-Life-moves-pretty-fast.wav")) + if (!File.Exists(audioFile)) { - Console.WriteLine("Error: File 'Bueller-Life-moves-pretty-fast.wav' not found."); + Console.WriteLine($"Error: Audio file '{audioFile}' not found."); + Console.WriteLine("Usage: dotnet run [path-to-audio-file]"); return; }
Line range hint
35-37
: Replace magic number and consider timeout configuration.The timeout duration is hardcoded as a magic number. Consider using
TimeSpan
for better readability and making it configurable:- CancellationTokenSource cancelToken = new CancellationTokenSource(); - cancelToken.CancelAfter(3600000); + // Default timeout of 1 hour, configurable via environment variable + var timeout = TimeSpan.FromHours( + double.TryParse(Environment.GetEnvironmentVariable("DEEPGRAM_TIMEOUT_HOURS"), out var hours) + ? hours + : 1); + using var cancelToken = new CancellationTokenSource(timeout);
Line range hint
39-46
: Consider using streaming for large files.Loading the entire file into memory using
ReadAllBytes
could cause issues with large audio files. Consider using a streaming approach for better memory efficiency:- var audioData = File.ReadAllBytes(@"Bueller-Life-moves-pretty-fast.wav"); - var response = await deepgramClient.TranscribeFile( - audioData, + using var fileStream = File.OpenRead(audioFile); + var response = await deepgramClient.TranscribeStream( + fileStream, new PreRecordedSchema() { Model = "nova-2", Punctuate = true, }, cancelToken);
Line range hint
48-53
: Enhance console interaction and cleanup.Consider adding proper console input handling and cleanup:
+ Console.CancelKeyPress += (s, e) => { + e.Cancel = true; + cancelToken.Cancel(); + }; + Console.WriteLine($"\n\n{response}\n\n"); - Console.WriteLine("Press any key to exit..."); - Console.ReadKey(); + Console.WriteLine("Press Ctrl+C to exit..."); + try { + await Task.Delay(-1, cancelToken.Token); + } catch (TaskCanceledException) { + // Expected when cancellation is requested + } // Teardown Library Library.Terminate();examples/Deepgram.Examples.Manage.Balances/Program.cs (3)
10-12
: LGTM! Class modifiers align with .NET conventions.The
public static
modifiers on theProgram
class andMain
method follow .NET best practices for console application entry points.Consider adjusting the indentation to use 4 spaces consistently:
- public static class Program - { - public static async Task Main(string[] args) +public static class Program +{ + public static async Task Main(string[] args)
Line range hint
33-34
: Fix typo in variable name.The variable
balanacesResponse
contains a typo and should bebalancesResponse
.-var balanacesResponse = await deepgramClient.GetBalances(projectId); -if (balanacesResponse == null) +var balancesResponse = await deepgramClient.GetBalances(projectId); +if (balancesResponse == null)
Line range hint
15-65
: Consider implementing structured logging.The current implementation uses
Console.WriteLine
for output. As mentioned in the PR objectives, a future update will implement conventional logging usingMicrosoft.Extensions.Logging.Abstractions
. Consider preparing for this transition by:
- Centralizing the logging calls
- Adding appropriate log levels for different message types
- Including structured data in log messages
Would you like me to provide an example implementation using Microsoft.Extensions.Logging?
examples/Deepgram.Examples.SpeechToText.Websocket.File/Program.cs (7)
5-9
: Consider organizing imports by namespace.Group the imports by namespace to improve readability:
using System; using System.IO; using System.Threading.Tasks; + using Deepgram; using Deepgram.Models.Listen.v2.WebSocket;
Line range hint
15-24
: Add environment variable validation.The code assumes
DEEPGRAM_API_KEY
is set but doesn't validate its presence. This could lead to runtime errors.static async Task Main(string[] args) { try { + string apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + throw new InvalidOperationException("DEEPGRAM_API_KEY environment variable is not set"); + } + // Initialize Library with default logging // Normal logging is "Info" level Library.Initialize(); // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable - var liveClient = ClientFactory.CreateListenWebSocketClient(); + var liveClient = ClientFactory.CreateListenWebSocketClient(apiKey);
Line range hint
26-35
: Improve event handler robustness and cleanup commented code.The event handler needs error handling and the commented code should be removed.
await liveClient.Subscribe(new EventHandler<ResultResponse>((sender, e) => { + try + { + if (e?.Channel?.Alternatives == null || e.Channel.Alternatives.Count == 0) + { + Console.WriteLine("Received empty or invalid transcription response"); + return; + } + if (e.Channel.Alternatives[0].Transcript == "") { return; } - // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Transcription)); Console.WriteLine($"\n\n\nSpeaker: {e.Channel.Alternatives[0].Transcript}\n\n\n"); + } + catch (Exception ex) + { + Console.WriteLine($"Error processing transcription: {ex.Message}"); + } }));
Line range hint
37-47
: Enhance connection configuration and error handling.The connection setup could benefit from timeout configuration and better error handling.
+const int CONNECTION_TIMEOUT_MS = 5000; + var liveSchema = new LiveSchema() { Model = "nova-2", Punctuate = true, SmartFormat = true, }; -bool bConnected = await liveClient.Connect(liveSchema); -if (!bConnected) +using var cts = new CancellationTokenSource(CONNECTION_TIMEOUT_MS); +bool connected = await liveClient.Connect(liveSchema, cts.Token); +if (!connected) { - Console.WriteLine("Failed to connect to the server"); + Console.WriteLine("Failed to establish WebSocket connection within timeout period"); return; }
Line range hint
49-63
: Improve file handling and resource management.The audio file handling needs validation, and the wait time should be configurable.
+const string AUDIO_FILE_PATH = "preamble.wav"; +const int RESPONSE_WAIT_TIME_MS = 45000; + +if (!File.Exists(AUDIO_FILE_PATH)) +{ + Console.WriteLine($"Audio file not found: {AUDIO_FILE_PATH}"); + return; +} + // Send some audio data -var audioData = File.ReadAllBytes(@"preamble.wav"); -liveClient.Send(audioData); +try +{ + var audioData = File.ReadAllBytes(AUDIO_FILE_PATH); + await liveClient.Send(audioData); +} +catch (IOException ex) +{ + Console.WriteLine($"Error reading audio file: {ex.Message}"); + return; +} // Wait for a while to receive responses -await Task.Delay(45000); +await Task.Delay(RESPONSE_WAIT_TIME_MS); // Stop the connection await liveClient.Stop();
Line range hint
64-67
: Enhance error handling with specific exceptions.The current catch-all exception handling could be more specific and informative.
-catch (Exception ex) +catch (InvalidOperationException ex) { - Console.WriteLine($"Exception: {ex.Message}"); + Console.WriteLine($"Configuration error: {ex.Message}"); +} +catch (WebSocketException ex) +{ + Console.WriteLine($"WebSocket error: {ex.Message}"); +} +catch (Exception ex) +{ + Console.WriteLine($"Unexpected error: {ex.Message}"); + Console.WriteLine($"Stack trace: {ex.StackTrace}"); +} +finally +{ + Library.Terminate(); }
Line range hint
11-13
: Add XML documentation for the Program class.As this is an example file, comprehensive documentation would help users understand the implementation better.
+/// <summary> +/// Example program demonstrating real-time speech-to-text functionality using Deepgram's WebSocket API. +/// This example shows how to: +/// - Initialize the Deepgram client +/// - Configure and establish a WebSocket connection +/// - Send audio data for transcription +/// - Handle transcription responses +/// </summary> class Programexamples/Deepgram.Examples.SpeechToText.Websocket.Http/Program.cs (2)
5-11
: Remove unused namespace import.The
System.Linq.Expressions
namespace is not used in this file and should be removed.using System; using System.IO; -using System.Linq.Expressions; using System.Net.Http; using System.Threading.Tasks; using Deepgram; using Deepgram.Models.Listen.v2.WebSocket;
Line range hint
41-66
: Consider architectural improvements for better example code.Several enhancements would make this example more robust and educational:
- Make the buffer size configurable and document the recommended sizes
- Add cancellation token support for graceful shutdown
- Add specific error handling for common streaming issues
- Make the stream URL configurable via command line or config file
Would you like me to provide a detailed implementation incorporating these improvements?
examples/Deepgram.Examples.Manage.Members/Program.cs (5)
Line range hint
14-14
: Consider moving configuration to appsettings.jsonThe
DELETE_MEMBER_BY_EMAIL
constant should be moved to a configuration file following .NET best practices.Consider using the following structure:
- private const string DELETE_MEMBER_BY_EMAIL = "MY_EMAIL";
And add an appsettings.json:
{ "DeepgramSettings": { "MemberEmail": "MY_EMAIL" } }Then use
IConfiguration
to load it:using Microsoft.Extensions.Configuration; var configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build(); var memberEmail = configuration.GetValue<string>("DeepgramSettings:MemberEmail");
Line range hint
20-24
: Add error handling for library initializationThe library initialization lacks error handling and logging configuration best practices.
Consider adding try-catch and proper logging:
- // Initialize Library with default logging - // Normal logging is "Info" level - Library.Initialize(); - - // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable - var deepgramClient = ClientFactory.CreateManageClient(); + try + { + Library.Initialize(); + + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY"); + if (string.IsNullOrEmpty(apiKey)) + { + throw new InvalidOperationException("DEEPGRAM_API_KEY environment variable is not set"); + } + + var deepgramClient = ClientFactory.CreateManageClient(); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to initialize Deepgram client: {ex.Message}"); + Environment.Exit(1); + }
Line range hint
26-36
: Improve project listing efficiency and readabilityThe project listing logic could be more efficient and readable using LINQ and string interpolation.
Consider this improvement:
- string myId = null; - foreach (var project in projectResp.Projects) - { - myId = project.ProjectId; - string myName = project.Name; - Console.WriteLine($"\n\nListProjects() - ID: {myId}, Name: {myName}\n\n"); - } + var selectedProject = projectResp.Projects.FirstOrDefault() + ?? throw new InvalidOperationException("No projects found"); + + var projectId = selectedProject.ProjectId; + Console.WriteLine( + $""" + + Project Details: + ID: {projectId} + Name: {selectedProject.Name} + + """);
Line range hint
38-93
: Refactor member management logic to reduce duplicationThe member listing and deletion logic contains repeated code and could benefit from better organization.
Consider extracting the member listing logic into a separate method and improving error handling:
+ private static async Task DisplayMembers(IDeepgramClient client, string projectId) + { + var members = await client.GetMembers(projectId); + if (members?.Members == null || !members.Members.Any()) + { + Console.WriteLine("No members found in the project."); + return; + } + + Console.WriteLine("\nProject Members:"); + foreach (var member in members.Members) + { + Console.WriteLine($"- {member.Email} (ID: {member.MemberId})"); + } + Console.WriteLine(); + } + + private static async Task<string> FindMemberIdByEmail( + IDeepgramClient client, + string projectId, + string email) + { + var members = await client.GetMembers(projectId); + return members?.Members + .FirstOrDefault(m => m.Email == email)? + .MemberId; + } - // List members - string delMemberId = null; - var listResp = await deepgramClient.GetMembers(myId); - // ... existing member listing code ... - - // Delete member - if (delMemberId == null) - { - Console.WriteLine(""); - Console.WriteLine("This example requires a project that already exists with a name specified in DELETE_MEMBER_BY_EMAIL."); - Console.WriteLine("This is required to exercise the RemoveMember function."); - Console.WriteLine("In the absence of this, this example will exit early."); - Console.WriteLine(""); - Environment.Exit(1); - } + await DisplayMembers(deepgramClient, projectId); + + var memberIdToDelete = await FindMemberIdByEmail( + deepgramClient, + projectId, + memberEmail); + + if (memberIdToDelete == null) + { + throw new InvalidOperationException( + $"Member with email {memberEmail} not found in the project."); + }Also, consider replacing
Console.ReadKey()
with a more appropriate termination method for production code:- Console.WriteLine("\n\nPress any key to exit."); - Console.ReadKey(); + // In a real application, you might want to implement proper + // shutdown handling using CancellationToken or similar mechanism
Line range hint
1-93
: Add XML documentation for public membersSince this is an example file that demonstrates SDK usage, it would be beneficial to add XML documentation to help users understand the code better.
Add documentation at the class level:
/// <summary> /// Example program demonstrating member management operations using the Deepgram SDK. /// This includes listing projects, listing members, and removing members. /// </summary> /// <remarks> /// Requires DEEPGRAM_API_KEY environment variable to be set with a valid API key. /// </remarks> class Programexamples/Deepgram.Examples.Manage.Usage/Program.cs (2)
Line range hint
24-29
: Consider implementing more robust error handling and loggingThe current error handling could be enhanced in several ways:
- Consider using a proper logging framework instead of Console.WriteLine
- Add more detailed error messages explaining why operations failed
- Consider implementing a consistent error handling strategy across all operations
Here's a suggested approach:
- Console.WriteLine("ListProjects failed."); - Environment.Exit(1); + var errorMessage = "Failed to retrieve projects. Please check your API key and network connection."; + Console.Error.WriteLine(errorMessage); + throw new InvalidOperationException(errorMessage);This aligns with the PR's future goals of implementing conventional logging using Microsoft.Extensions.Logging.Abstractions.
Also applies to: 65-70
Line range hint
15-102
: Improve resource management and program structureThe program could benefit from more structured resource management:
- Consider using a try-finally block or IDisposable pattern for Library cleanup
- The Console.ReadKey() blocking call might not be necessary for a sample program
Here's a suggested refactor:
- static async Task Main(string[] args) - { - Library.Initialize(); - // ... rest of the code ... - Console.WriteLine("\n\nPress any key to exit."); - Console.ReadKey(); - Library.Terminate(); - } + static async Task Main(string[] args) + { + try + { + Library.Initialize(); + // ... rest of the code ... + } + catch (Exception ex) + { + Console.Error.WriteLine($"An error occurred: {ex.Message}"); + Environment.Exit(1); + } + finally + { + Library.Terminate(); + } + }examples/Deepgram.Examples.Manage.Invitations/Program.cs (5)
Line range hint
6-12
: Align namespace with project name following .NET conventionsThe namespace
SampleApp
should match the project nameDeepgram.Examples.Manage.Invitations
to follow .NET naming conventions.-namespace SampleApp +namespace Deepgram.Examples.Manage.Invitations
Line range hint
16-20
: Improve initialization and logging configurationA few suggestions to enhance the initialization:
- Remove commented code for cleaner examples
- Consider using Info level logging by default as Debug might be too verbose
- Add error handling for missing API key environment variable
- // Initialize Library with default logging - // Normal logging is "Info" level - //Library.Initialize(); - // OR very chatty logging - Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + Library.Initialize(LogLevel.Info); + + if (Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY") == null) + { + Console.WriteLine("Error: DEEPGRAM_API_KEY environment variable not set"); + Environment.Exit(1); + }
Line range hint
22-35
: Enhance project management code with better error handling and LINQThe current implementation could be improved for better error handling and readability.
- var projectResp = await deepgramClient.GetProjects(); - if (projectResp == null) - { - Console.WriteLine("ListProjects failed."); - Environment.Exit(1); - } - - string myId = null; - string myName = null; - foreach (var project in projectResp.Projects) - { - myId = project.ProjectId; - myName = project.Name; - Console.WriteLine($"\n\nListProjects() - ID: {myId}, Name: {myName}\n\n"); - break; - } + var projectResponse = await deepgramClient.GetProjects(); + if (projectResponse?.Projects == null || !projectResponse.Projects.Any()) + { + Console.WriteLine("Failed to retrieve projects or no projects found."); + Environment.Exit(1); + } + + var firstProject = projectResponse.Projects.First(); + var projectId = firstProject.ProjectId; + var projectName = firstProject.Name; + Console.WriteLine($"\n\nFirst Project - ID: {projectId}, Name: {projectName}\n\n");
Line range hint
37-89
: Improve invite management code structure and error handlingSeveral improvements could enhance this example:
- Use a consistent placeholder email
- Consolidate error handling
- Structure console output for better readability
- Add comments explaining the workflow
+ const string EXAMPLE_EMAIL = "example@domain.com"; + Console.WriteLine("\n=== Managing Invites ===\n"); + // list invites var listResp = await deepgramClient.GetInvites(myId); - if (listResp.Invites.Count == 0) - { - Console.WriteLine("\n\nNo invites found\n\n"); - } - else - { - Console.WriteLine($"\n\n{listResp}\n\n"); - } + Console.WriteLine($"Current invites: {listResp.Invites.Count}"); + foreach (var invite in listResp.Invites) + { + Console.WriteLine($"- {invite.Email} ({invite.Scope})"); + } // send invite var createInvite = new InviteSchema() { - Email = "spam@spam.com", + Email = EXAMPLE_EMAIL, Scope = "member", }; var createResp = await deepgramClient.SendInvite(myId, createInvite); - Console.WriteLine($"\n\n{createResp}\n\n"); + Console.WriteLine($"\nInvite sent to {EXAMPLE_EMAIL}"); // list invites listResp = await deepgramClient.GetInvites(myId); - if (listResp == null) - { - Console.WriteLine("\n\nNo invites found\n\n"); - } - else + if (listResp?.Invites != null) { - Console.WriteLine($"\n\n{listResp}\n\n"); + Console.WriteLine($"\nUpdated invite count: {listResp.Invites.Count}"); } // delete invite - var delResp = await deepgramClient.DeleteInvite(myId, "spam@spam.com"); - Console.WriteLine($"\n\n{listResp}\n\n"); + var delResp = await deepgramClient.DeleteInvite(myId, EXAMPLE_EMAIL); + Console.WriteLine($"\nDeleted invite for {EXAMPLE_EMAIL}");
Line range hint
13-91
: Consider adding production-ready featuresWhile this is an example, consider adding the following features to demonstrate best practices:
- Proper exception handling with try-catch blocks for API calls
- Cancellation token support for async operations
- Using ILogger for structured logging instead of Console.WriteLine
Would you like me to provide an example implementation with these improvements?
examples/Deepgram.Examples.Manage.Keys/Program.cs (5)
Line range hint
11-13
: Align namespace with .NET naming conventionsThe namespace
SampleApp
should match the assembly name (project name)Deepgram.Examples.Manage.Keys
to follow .NET naming conventions.-namespace SampleApp +namespace Deepgram.Examples.Manage.Keys
Line range hint
29-33
: Enhance error handling and logging patternsThe current error handling has several areas for improvement:
- Direct
Environment.Exit
calls aren't ideal for example code- Error messages lack detail about what went wrong
- Inconsistent error handling patterns (some errors exit, others continue)
Consider implementing a more robust error handling pattern:
-if (projectResp == null) -{ - Console.WriteLine("ListProjects failed."); - Environment.Exit(1); -} +if (projectResp?.Projects == null) +{ + Console.WriteLine("Failed to retrieve projects. Please check your API key and network connection."); + return; +}Similar improvements should be applied to all error handling blocks for consistency.
Also applies to: 44-48, 66-71, 89-94, 98-103, 107-112
Line range hint
22-24
: Improve API client initialization and error handlingThe API client initialization could benefit from additional error handling and security considerations:
- Add validation for the environment variable
- Wrap API calls in try-catch blocks
- Implement proper disposal pattern for the client
Consider implementing these improvements:
+try +{ + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY") + ?? throw new InvalidOperationException("DEEPGRAM_API_KEY environment variable is not set"); var deepgramClient = ClientFactory.CreateManageClient(); + try + { + // Use client + } + finally + { + // Ensure proper cleanup if needed + } +} +catch (Exception ex) +{ + Console.WriteLine($"Failed to initialize Deepgram client: {ex.Message}"); + return; +}
Line range hint
15-17
: Add XML documentation to improve example usabilityAs this is an example project, adding XML documentation would help users understand the purpose and usage of the code better.
+/// <summary> +/// Example program demonstrating Deepgram API key management operations. +/// </summary> class Program { + /// <summary> + /// Demonstrates basic CRUD operations for Deepgram API keys. + /// </summary> static async Task Main(string[] args)
Line range hint
61-65
: Define constants for API scopesThe scope value "member" is used as a magic string. Consider defining constants or an enum for available scopes.
+private static class ApiScopes +{ + public const string Member = "member"; + // Add other available scopes +} var createKey = new KeySchema() { Comment = "MyTestKey", - Scopes = new List<string> { "member" }, + Scopes = new List<string> { ApiScopes.Member }, };examples/Deepgram.Examples.Manage.Models/Program.cs (1)
Line range hint
16-108
: Consider enhancing the example's robustness and consistency.As this is an example project demonstrating SDK usage, consider the following improvements:
- Replace direct
Environment.Exit(1)
calls with proper exception handling- Remove
Console.ReadKey()
as it's not necessary for example code- Standardize string interpolation style
- Add more descriptive comments explaining the API interactions
Example improvement for error handling:
- if (projectResp == null) - { - Console.WriteLine("ListProjects failed."); - Environment.Exit(1); - } + try + { + if (projectResp == null) + throw new InvalidOperationException("Failed to retrieve projects. The API response was null."); + } + catch (Exception ex) + { + Console.WriteLine($"Error listing projects: {ex.Message}"); + throw; + }Example of improved comments:
- // get projects + // Retrieve all projects associated with the API key + // This demonstrates basic project listing functionalityexamples/Deepgram.Examples.Manage.Scopes/Program.cs (4)
Line range hint
13-13
: Consider making MEMBER_BY_EMAIL configurableThe hardcoded email constant makes the example less flexible. Consider reading this value from environment variables or command line arguments to make the example more practical.
- private const string MEMBER_BY_EMAIL = "MEMBER_TO_DELETE_BY_EMAIL"; + private static string GetMemberEmail() => + Environment.GetEnvironmentVariable("DEEPGRAM_MEMBER_EMAIL") + ?? throw new InvalidOperationException("DEEPGRAM_MEMBER_EMAIL environment variable is required");
Line range hint
29-35
: Consolidate error handling patternsThe code repeats similar error handling patterns with Console.WriteLine and Environment.Exit. Consider creating a helper method to handle these cases consistently.
+ private static void HandleError(string message) + { + Console.WriteLine($"\n\nError: {message}\n\n"); + Environment.Exit(1); + }Then use it throughout the code:
- if (projectResp == null) - { - Console.WriteLine("ListProjects failed."); - Environment.Exit(1); - } + if (projectResp == null) HandleError("ListProjects failed.");Also applies to: 56-61, 73-78, 91-96, 108-113
Line range hint
82-104
: Extract scope update logic into a helper methodThe pattern of updating scope and getting member scopes is repeated. Consider extracting this into a reusable method to reduce code duplication.
+ private static async Task UpdateAndVerifyScope( + IManageClient client, + string projectId, + string memberId, + string newScope) + { + var scopeUpdate = new MemberScopeSchema { Scope = newScope }; + var updateResp = await client.UpdateMemberScope(projectId, memberId, scopeUpdate); + Console.WriteLine($"\n\n{updateResp}\n\n"); + + var memberResp = await client.GetMemberScopes(projectId, memberId); + if (memberResp == null) HandleError("No scopes found after update"); + Console.WriteLine($"\n\n{memberResp}\n\n"); + }
Console.WriteLine calls should be replaced with ILogger
The review comment is valid. The codebase already has Microsoft.Extensions.Logging infrastructure in place:
- Both Deepgram and Deepgram.Microphone projects reference Microsoft.Extensions.Logging packages
- The library has a dedicated logging system in the Logger namespace
- The README documents usage of Microsoft.Extensions.Logging
The example code should be updated to use the logging infrastructure instead of Console.WriteLine for consistency with the rest of the codebase.
🔗 Analysis chain
Line range hint
15-122
: Consider future logging implementationAs mentioned in the PR objectives, future updates will implement conventional logging using Microsoft.Extensions.Logging.Abstractions. The current direct Console.WriteLine usage will need to be updated.
Let's check if Microsoft.Extensions.Logging is already referenced in the project:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if logging package is referenced in any project files fd -e csproj . | xargs grep -l "Microsoft.Extensions.Logging"Length of output: 133
Script:
#!/bin/bash # Check the actual logging references in the main library cat Deepgram/Deepgram.csproj # Check if there's any ILogger usage in the codebase rg "ILogger|Microsoft.Extensions.Logging" -A 2Length of output: 13397
examples/Deepgram.Examples.Manage.Projects/Program.cs (4)
5-7
: Consider modernizing namespace declarations and using directives.The code could benefit from modern C# features to improve maintainability:
- Use file-scoped namespaces
- Consider moving common using directives to a central file using global using directives
-using System; -using System.Threading.Tasks; -using Deepgram; -using Deepgram.Models.Manage.v1; - -namespace SampleApp -{ +namespace SampleApp; + +using Deepgram; +using Deepgram.Models.Manage.v1;
Line range hint
14-22
: Enhance resource management and error handling.While the async setup is correct, consider these improvements:
- Add validation for the DEEPGRAM_API_KEY environment variable
- Implement proper disposal pattern for the client
- static async Task Main(string[] args) - { - // Initialize Library with default logging - // Normal logging is "Info" level - Library.Initialize(); - - // use the client factory with a API Key set with the "DEEPGRAM_API_KEY" environment variable - var deepgramClient = ClientFactory.CreateManageClient(); + static async Task Main(string[] args) + { + try + { + var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY") + ?? throw new InvalidOperationException("DEEPGRAM_API_KEY environment variable is not set"); + + // Initialize Library with default logging + Library.Initialize(); + + using var deepgramClient = ClientFactory.CreateManageClient();
Line range hint
24-40
: Improve project lookup logic using LINQ and null handling.The current implementation could be more concise and maintainable:
- Use LINQ for project searching
- Use more descriptive variable names
- Implement null-conditional operators
- string myId = null; - string myName = null; - string myDeleteId = null; - foreach (var project in listResp.Projects) - { - if (project.Name == DELETE_PROJECT_BY_NAME) - { - myDeleteId = project.ProjectId; - } - myId = project.ProjectId; - myName = project.Name; - } + var projectToDelete = listResp.Projects.FirstOrDefault(p => p.Name == DELETE_PROJECT_BY_NAME); + var lastProject = listResp.Projects.LastOrDefault(); + + var currentProjectId = lastProject?.ProjectId; + var currentProjectName = lastProject?.Name; + var projectIdToDelete = projectToDelete?.ProjectId;
Line range hint
42-124
: Refactor repetitive error handling and console output patterns.The code contains several areas that could be improved:
- Abstract common error handling logic
- Create helper methods for repeated operations
- Use consistent error messaging
Consider refactoring the code using this pattern:
private static async Task<T> ExecuteOperation<T>(string operationName, Func<Task<T>> operation) { var result = await operation(); if (result == null) { Console.WriteLine($"\n\n{operationName} failed.\n\n"); Environment.Exit(1); } Console.WriteLine($"\n\n{result}\n\n"); return result; } // Usage example: var project = await ExecuteOperation("GetProject", () => deepgramClient.GetProject(currentProjectId));This would significantly reduce code duplication and maintain consistent error handling.
examples/Deepgram.Examples.SpeechToText.Websocket.Microphone/Program.cs (6)
5-7
: Consider organizing using directives according to .NET conventions.Group using directives in the following order:
- System namespaces
- Third-party namespaces (Deepgram)
- Project namespaces
using System; using System.Threading.Tasks; + using Deepgram; using Deepgram.Logger; using Deepgram.Microphone; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Listen.v2.WebSocket;
Line range hint
26-27
: Security: Do not use empty API key string.The API key should be retrieved from environment variables or secure configuration. Currently, it's passed as an empty string which will fail authentication.
-var liveClient = ClientFactory.CreateListenWebSocketClient(apiKey: "", options: options); +var apiKey = Environment.GetEnvironmentVariable("DEEPGRAM_API_KEY") + ?? throw new InvalidOperationException("DEEPGRAM_API_KEY environment variable is not set"); +var liveClient = ClientFactory.CreateListenWebSocketClient(apiKey: apiKey, options: options);
Line range hint
19-24
: Improve error handling and logging initialization.Consider removing commented debug logging code and improve error handling by catching specific exceptions.
- // Initialize Library with default logging - // Normal logging is "Info" level Deepgram.Library.Initialize(); - // OR very chatty logging - //Deepgram.Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose // Initialize the microphone library Deepgram.Microphone.Library.Initialize();
Line range hint
47-49
: Remove commented code and improve transcript logging.Remove the commented JSON serialization code and consider adding more structured logging for the transcription results.
- // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Transcription)); Console.WriteLine($"----> Speaker: {e.Channel.Alternatives[0].Transcript}");
Line range hint
73-85
: Externalize configuration values and improve error handling.Consider moving the LiveSchema configuration to a separate configuration file or environment variables for better maintainability.
+ // TODO: Move to configuration var liveSchema = new LiveSchema() { Model = "nova-2", Encoding = "linear16", SampleRate = 16000, Punctuate = true, SmartFormat = true, InterimResults = true, UtteranceEnd = "1000", VadEvents = true, };
Line range hint
86-106
: Improve resource management using IDisposable pattern.Consider implementing proper resource cleanup using the IDisposable pattern or async using statements for the microphone and WebSocket client.
- bool bConnected = await liveClient.Connect(liveSchema); - if (!bConnected) - { - Console.WriteLine("Failed to connect to Deepgram WebSocket server."); - return; - } + if (!await liveClient.Connect(liveSchema)) + throw new InvalidOperationException("Failed to connect to Deepgram WebSocket server."); + await using var microphone = new Microphone(liveClient.Send); - var microphone = new Microphone(liveClient.Send); microphone.Start(); // Wait for the user to press a key Console.ReadKey(); - // Stop the microphone - microphone.Stop(); - - // Stop the connection - await liveClient.Stop(); - - // Terminate Libraries - Deepgram.Microphone.Library.Terminate(); - Deepgram.Library.Terminate();Deepgram.Microphone/Deepgram.Microphone.csproj (1)
Line range hint
9-67
: Optimize NuGet packaging configuration.The current structure has several opportunities for improvement:
- Duplicate properties between solution configurations can be centralized
- Copyright year should be dynamic to avoid manual updates
Consider refactoring the packaging configuration:
+ <PropertyGroup> + <!-- Common properties for both configurations --> + <IsPackable>true</IsPackable> + <Company>Deepgram</Company> + <Authors>Deepgram .NET SDK Contributors</Authors> + <Copyright>$([System.DateTime]::Now.Year) Deepgram</Copyright> + <PackageIcon>dg_logo.png</PackageIcon> + <PackageRequireLicenseAcceptance>False</PackageRequireLicenseAcceptance> + <PackageLicenseExpression>MIT</PackageLicenseExpression> + <PackageProjectUrl>https://developers.deepgram.com/sdks-tools/sdks/dotnet-sdk/</PackageProjectUrl> + <PackageReadmeFile>README.md</PackageReadmeFile> + <RepositoryUrl>https://github.com/deepgram/deepgram-dotnet-sdk</RepositoryUrl> + <PackageTags>speech-to-text,captions,speech-recognition,deepgram,dotnet</PackageTags> + <EnableNETAnalyzers>True</EnableNETAnalyzers> + <EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild> + <AnalysisLevel>latest</AnalysisLevel> + </PropertyGroup> <PropertyGroup Condition="'$(SolutionFileName)' == 'Deepgram.sln'"> - <!-- Remove duplicate properties --> + <PackageId>Deepgram.Microphone</PackageId> + <Title>Deepgram .NET Microphone</Title> + <Description>Helper Microphone Package</Description> + <Summary>Helper Microphone Package</Summary> </PropertyGroup> <PropertyGroup Condition="'$(SolutionFileName)' == 'Deepgram.DevBuild.sln'"> - <!-- Remove duplicate properties --> + <PackageId>Deepgram.Unstable.Microphone.Builds</PackageId> + <Title>Deepgram.Microphone - UNSTABLE DEVELOPER BUILDS</Title> + <Description>UNSTABLE DEVELOPER BUILDS - Deepgram .NET Microphone</Description> + <Summary>UNSTABLE DEVELOPER BUILDS - Deepgram .NET Microphone</Summary> </PropertyGroup>Deepgram/Deepgram.csproj (3)
72-82
: Consider using consistent version patterns across packages.While the package updates are good, there's inconsistency in version specificity:
- Some packages use exact versions (e.g., "8.0.2")
- Others in net8.0 section use wildcards (e.g., "8.*")
Consider using exact versions throughout for better reproducibility and dependency control.
Line range hint
113-121
: Align version specificity with other target frameworks.The net8.0 section uses wildcard versions (8.*) while other frameworks use specific versions. This could lead to unexpected package updates and inconsistent behavior across environments.
Consider using specific versions like the other target frameworks:
- <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.*"> + <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0"> - <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.*" /> + <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" /> - <PackageReference Include="Microsoft.Extensions.Logging" Version="8.*" /> + <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
Line range hint
1-150
: Consider simplifying the project configuration approach.The current setup maintains two separate configurations (stable and unstable) through different solution files. This isn't a common .NET practice and could be simplified:
- Consider using build configurations (Debug/Release) instead of separate solution files
- For unstable builds, consider using CI/CD pipeline configurations or build-time variables
- Look into using .NET's built-in preview package support instead of maintaining a separate unstable package feed
This would align better with standard .NET practices and simplify maintenance.
examples/Deepgram.Examples.TextToSpeech.Websocket.Simple/Program.cs (6)
5-13
: Organize using directives according to .NET conventions.Consider organizing the using directives into groups:
- System namespaces
- Third-party namespaces (Deepgram)
Also, remove the redundant
using Deepgram.Logger
as it's already included in theusing Deepgram
namespace.using System; using System.IO; using System.Threading.Tasks; using Deepgram; -using Deepgram.Logger; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Speak.v2.WebSocket;
Line range hint
19-28
: Consider adding cancellation token support for better async operation handling.For better async operation handling in a console application, consider adding a CancellationTokenSource to allow graceful shutdown.
static async Task Main(string[] args) { + using var cts = new CancellationTokenSource(); + Console.CancelKeyPress += (s, e) => { + e.Cancel = true; + cts.Cancel(); + }; try { // ... rest of the code
Line range hint
47-123
: Extract WAV header generation to a separate method and use modern file handling.The WAV header generation logic is complex and should be extracted to improve maintainability. Also, consider using more modern file handling patterns.
+ private static byte[] GenerateWavHeader(int sampleRate = 48000, short bitsPerSample = 16, short channels = 1) + { + byte[] wavHeader = new byte[44]; + int byteRate = sampleRate * channels * (bitsPerSample / 8); + short blockAlign = (short)(channels * (bitsPerSample / 8)); + + // RIFF header + wavHeader[0] = 0x52; // R + // ... rest of the header generation + return wavHeader; + } - if (appendWavHeader) - { - using (BinaryWriter writer = new BinaryWriter(File.Open("output.wav", FileMode.Append))) + if (appendWavHeader) + { + byte[] wavHeader = GenerateWavHeader(); + await File.WriteAllBytesAsync("output.wav", wavHeader, cancellationToken); + appendWavHeader = false; + }
Line range hint
125-132
: Use modern file handling patterns for audio data writing.Replace the BinaryWriter with modern async file operations.
- if (e.Stream != null) - { - using (BinaryWriter writer = new BinaryWriter(File.Open("output.wav", FileMode.Append))) - { - writer.Write(e.Stream.ToArray()); - } - } + if (e.Stream != null) + { + await File.WriteAllBytesAsync("output.wav", e.Stream.ToArray(), FileMode.Append, cancellationToken); + }
Line range hint
167-189
: Enhance connection handling and configuration management.Consider the following improvements:
- Move configuration to appsettings.json
- Add connection timeout
- Validate input text
+ var config = new SpeakSchema + { + Encoding = Configuration.GetValue<string>("Deepgram:Encoding", "linear16"), + SampleRate = Configuration.GetValue<int>("Deepgram:SampleRate", 48000) + }; - var speakSchema = new SpeakSchema() - { - Encoding = "linear16", - SampleRate = 48000, - }; - bool bConnected = await speakClient.Connect(speakSchema); + using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + bool bConnected = await speakClient.Connect(config, cts.Token); + if (string.IsNullOrEmpty(textToSpeak)) + throw new ArgumentException("Text to speak cannot be empty"); - speakClient.SpeakWithText("Hello World!"); + await speakClient.SpeakWithText(textToSpeak);
Line range hint
191-202
: Improve exception handling and resource cleanup.Consider implementing more specific exception handling and proper async resource cleanup.
- catch (Exception ex) + catch (DeepgramException ex) + { + Console.WriteLine($"Deepgram API error: {ex.Message}"); + } + catch (IOException ex) + { + Console.WriteLine($"File operation error: {ex.Message}"); + } + catch (Exception ex) { - Console.WriteLine($"Exception: {ex.Message}"); + Console.WriteLine($"Unexpected error: {ex.Message}"); + throw; } + finally + { + if (speakClient is IAsyncDisposable disposable) + await disposable.DisposeAsync(); + Library.Terminate(); + }.gitignore (1)
486-490
: Consider using user secrets for development.Currently ignoring
web.config
,app.config
, andsettings.json
for API keys. For development scenarios, consider using .NET User Secrets instead of configuration files:
- Right-click the project in Visual Studio and select "Manage User Secrets"
- Use
IConfiguration
to access secrets:builder.Configuration.GetValue<string>("ApiKey")This provides better security and follows .NET best practices for secret management.
Deepgram.sln (1)
12-61
: Consider consolidating example projectsWhile the current organization provides clear separation, having 24 separate example projects might increase maintenance overhead. Consider:
- Grouping related examples into fewer projects (e.g., all REST examples in one project)
- Using a consistent naming pattern for better discoverability
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (6)
examples/speech-to-text/rest/sentiment/CallCenterPhoneCall.mp3
is excluded by!**/*.mp3
,!**/*.mp3
examples/speech-to-text/rest/summary/CallCenterPhoneCall.mp3
is excluded by!**/*.mp3
,!**/*.mp3
examples/speech-to-text/rest/topic/CallCenterPhoneCall.mp3
is excluded by!**/*.mp3
,!**/*.mp3
extras/Bueller-Life-moves-pretty-fast.wav
is excluded by!**/*.wav
,!**/*.wav
extras/CallCenterPhoneCall.mp3
is excluded by!**/*.mp3
,!**/*.mp3
extras/preamble.wav
is excluded by!**/*.wav
,!**/*.wav
📒 Files selected for processing (82)
.gitignore
(1 hunks)Deepgram.Dev.sln
(0 hunks)Deepgram.DevBuild.sln
(0 hunks)Deepgram.Microphone/Deepgram.Microphone.csproj
(2 hunks)Deepgram.Tests/Deepgram.Tests.csproj
(1 hunks)Deepgram.sln
(1 hunks)Deepgram/Deepgram.csproj
(2 hunks)Directory.Build.props
(1 hunks)clean-up.sh
(0 hunks)examples/Deepgram.Examples.Analyze.Intent/Deepgram.Examples.Analyze.Intent.csproj
(1 hunks)examples/Deepgram.Examples.Analyze.Intent/Program.cs
(1 hunks)examples/Deepgram.Examples.Analyze.Sentiment/Deepgram.Examples.Analyze.Sentiment.csproj
(1 hunks)examples/Deepgram.Examples.Analyze.Sentiment/Program.cs
(1 hunks)examples/Deepgram.Examples.Analyze.Summary/Deepgram.Examples.Analyze.Summary.csproj
(1 hunks)examples/Deepgram.Examples.Analyze.Summary/Program.cs
(1 hunks)examples/Deepgram.Examples.Analyze.Topic/Deepgram.Examples.Analyze.Topic.csproj
(1 hunks)examples/Deepgram.Examples.Analyze.Topic/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Balances/Deepgram.Examples.Manage.Balances.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Balances/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Invitations/Deepgram.Examples.Manage.Invitations.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Invitations/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Keys/Deepgram.Examples.Manage.Keys.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Keys/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Members/Deepgram.Examples.Manage.Members.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Members/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Models/Deepgram.Examples.Manage.Models.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Models/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Projects/Deepgram.Examples.Manage.Projects.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Projects/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Scopes/Deepgram.Examples.Manage.Scopes.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Scopes/Program.cs
(1 hunks)examples/Deepgram.Examples.Manage.Usage/Deepgram.Examples.Manage.Usage.csproj
(1 hunks)examples/Deepgram.Examples.Manage.Usage/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.File/Deepgram.Examples.SpeechToText.Rest.File.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.File/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Intent/Deepgram.Examples.SpeechToText.Rest.Intent.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Intent/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Deepgram.Examples.SpeechToText.Rest.Sentiment.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Summary/Deepgram.Examples.SpeechToText.Rest.Summary.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Summary/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Topic/Deepgram.Examples.SpeechToText.Rest.Topic.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Topic/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Url/Deepgram.Examples.SpeechToText.Rest.Url.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Rest.Url/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.File/Deepgram.Examples.SpeechToText.Websocket.File.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.File/Program.cs
(1 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.Http/Deepgram.Examples.SpeechToText.Websocket.Http.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.Http/Program.cs
(2 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.Microphone/Deepgram.Examples.SpeechToText.Websocket.Microphone.csproj
(1 hunks)examples/Deepgram.Examples.SpeechToText.Websocket.Microphone/Program.cs
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld.csproj
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld/Program.cs
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck.csproj
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Program.cs
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Websocket.Simple/Deepgram.Examples.TextToSpeech.Websocket.Simple.csproj
(1 hunks)examples/Deepgram.Examples.TextToSpeech.Websocket.Simple/Program.cs
(1 hunks)examples/analyze/intent/Analyze.csproj
(0 hunks)examples/analyze/sentiment/Analyze.csproj
(0 hunks)examples/analyze/sentiment/conversation.txt
(0 hunks)examples/analyze/summary/Analyze.csproj
(0 hunks)examples/analyze/summary/conversation.txt
(0 hunks)examples/analyze/topic/Analyze.csproj
(0 hunks)examples/analyze/topic/conversation.txt
(0 hunks)examples/manage/balances/Manage.csproj
(0 hunks)examples/manage/invitations/Manage.csproj
(0 hunks)examples/manage/keys/Manage.csproj
(0 hunks)examples/manage/members/Manage.csproj
(0 hunks)examples/manage/models/Models.csproj
(0 hunks)examples/manage/projects/Manage.csproj
(0 hunks)examples/manage/scopes/Manage.csproj
(0 hunks)examples/manage/usage/Manage.csproj
(0 hunks)examples/speech-to-text/rest/file/PreRecorded.csproj
(0 hunks)examples/speech-to-text/rest/intent/PreRecorded.csproj
(0 hunks)examples/speech-to-text/rest/sentiment/PreRecorded.csproj
(0 hunks)examples/speech-to-text/rest/summary/PreRecorded.csproj
(0 hunks)examples/speech-to-text/rest/topic/PreRecorded.csproj
(0 hunks)examples/speech-to-text/rest/url/PreRecorded.csproj
(0 hunks)examples/speech-to-text/websocket/file/Streaming.csproj
(0 hunks)examples/speech-to-text/websocket/http/Streaming.csproj
(0 hunks)examples/speech-to-text/websocket/microphone/Streaming.csproj
(0 hunks)examples/text-to-speech/rest/file/hello-world/Speak.csproj
(0 hunks)
⛔ Files not processed due to max files limit (26)
- examples/text-to-speech/rest/file/woodchuck/Speak.csproj
- examples/text-to-speech/websocket/simple/Speak.csproj
- tests/Deepgram.Tests.EdgeCases.KeepAlive/Deepgram.Tests.EdgeCases.KeepAlive.csproj
- tests/Deepgram.Tests.EdgeCases.KeepAlive/Program.cs
- tests/Deepgram.Tests.EdgeCases.ReuseReconnect/Deepgram.Tests.EdgeCases.ReuseReconnect.csproj
- tests/Deepgram.Tests.EdgeCases.ReuseReconnect/Program.cs
- tests/Deepgram.Tests.EdgeCases.SpeechToText.V1.ClientExample/Deepgram.Tests.EdgeCases.SpeechToText.V1.ClientExample.csproj
- tests/Deepgram.Tests.EdgeCases.SpeechToText.V1.ClientExample/Program.cs
- tests/Deepgram.Tests.EdgeCases.TextToSpeech.V1.ClientExample/Deepgram.Tests.EdgeCases.TextToSpeech.V1.ClientExample.csproj
- tests/Deepgram.Tests.EdgeCases.TextToSpeech.V1.ClientExample/Program.cs
- tests/Deepgram.Tests.ExpectedFailures.Rest.BadHost/Deepgram.Tests.ExpectedFailures.Rest.BadHost.csproj
- tests/Deepgram.Tests.ExpectedFailures.Rest.BadHost/Program.cs
- tests/Deepgram.Tests.ExpectedFailures.Rest.ThrowException/Deepgram.Tests.ExpectedFailures.Rest.ThrowException.csproj
- tests/Deepgram.Tests.ExpectedFailures.Rest.ThrowException/Program.cs
- tests/Deepgram.Tests.ExpectedFailures.Rest.TriggerCancel/Deepgram.Tests.ExpectedFailures.Rest.TriggerCancel.csproj
- tests/Deepgram.Tests.ExpectedFailures.Rest.TriggerCancel/Program.cs
- tests/Deepgram.Tests.ExpectedFailures.Websocket.CreateTimeout/Deepgram.Tests.ExpectedFailures.Websocket.CreateTimeout.csproj
- tests/Deepgram.Tests.ExpectedFailures.Websocket.CreateTimeout/Program.cs
- tests/edge_cases/keepalive/KeepAlive.csproj
- tests/edge_cases/reconnect_same_object/ReconnectStreaming.csproj
- tests/edge_cases/stt_v1_client_example/Streaming.csproj
- tests/edge_cases/tts_v1_client_example/Speak.csproj
- tests/expected_failures/rest/bad_host/BadHost.csproj
- tests/expected_failures/rest/throw_exception/ThrowException.csproj
- tests/expected_failures/rest/trigger_cancel/TriggerCancel.csproj
- tests/expected_failures/websocket/exercise_timeout/ExerciseTimeout.csproj
💤 Files with no reviewable changes (28)
- Deepgram.Dev.sln
- Deepgram.DevBuild.sln
- clean-up.sh
- examples/analyze/intent/Analyze.csproj
- examples/analyze/sentiment/Analyze.csproj
- examples/analyze/sentiment/conversation.txt
- examples/analyze/summary/Analyze.csproj
- examples/analyze/summary/conversation.txt
- examples/analyze/topic/Analyze.csproj
- examples/analyze/topic/conversation.txt
- examples/manage/balances/Manage.csproj
- examples/manage/invitations/Manage.csproj
- examples/manage/keys/Manage.csproj
- examples/manage/members/Manage.csproj
- examples/manage/models/Models.csproj
- examples/manage/projects/Manage.csproj
- examples/manage/scopes/Manage.csproj
- examples/manage/usage/Manage.csproj
- examples/speech-to-text/rest/file/PreRecorded.csproj
- examples/speech-to-text/rest/intent/PreRecorded.csproj
- examples/speech-to-text/rest/sentiment/PreRecorded.csproj
- examples/speech-to-text/rest/summary/PreRecorded.csproj
- examples/speech-to-text/rest/topic/PreRecorded.csproj
- examples/speech-to-text/rest/url/PreRecorded.csproj
- examples/speech-to-text/websocket/file/Streaming.csproj
- examples/speech-to-text/websocket/http/Streaming.csproj
- examples/speech-to-text/websocket/microphone/Streaming.csproj
- examples/text-to-speech/rest/file/hello-world/Speak.csproj
✅ Files skipped from review due to trivial changes (23)
- Deepgram.Tests/Deepgram.Tests.csproj
- Directory.Build.props
- examples/Deepgram.Examples.Analyze.Intent/Deepgram.Examples.Analyze.Intent.csproj
- examples/Deepgram.Examples.Analyze.Summary/Deepgram.Examples.Analyze.Summary.csproj
- examples/Deepgram.Examples.Analyze.Topic/Deepgram.Examples.Analyze.Topic.csproj
- examples/Deepgram.Examples.Manage.Balances/Deepgram.Examples.Manage.Balances.csproj
- examples/Deepgram.Examples.Manage.Invitations/Deepgram.Examples.Manage.Invitations.csproj
- examples/Deepgram.Examples.Manage.Keys/Deepgram.Examples.Manage.Keys.csproj
- examples/Deepgram.Examples.Manage.Models/Deepgram.Examples.Manage.Models.csproj
- examples/Deepgram.Examples.Manage.Scopes/Deepgram.Examples.Manage.Scopes.csproj
- examples/Deepgram.Examples.Manage.Usage/Deepgram.Examples.Manage.Usage.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.File/Deepgram.Examples.SpeechToText.Rest.File.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.Intent/Deepgram.Examples.SpeechToText.Rest.Intent.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Deepgram.Examples.SpeechToText.Rest.Sentiment.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.Summary/Deepgram.Examples.SpeechToText.Rest.Summary.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.Topic/Deepgram.Examples.SpeechToText.Rest.Topic.csproj
- examples/Deepgram.Examples.SpeechToText.Rest.Url/Deepgram.Examples.SpeechToText.Rest.Url.csproj
- examples/Deepgram.Examples.SpeechToText.Websocket.File/Deepgram.Examples.SpeechToText.Websocket.File.csproj
- examples/Deepgram.Examples.SpeechToText.Websocket.Http/Deepgram.Examples.SpeechToText.Websocket.Http.csproj
- examples/Deepgram.Examples.SpeechToText.Websocket.Microphone/Deepgram.Examples.SpeechToText.Websocket.Microphone.csproj
- examples/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld.csproj
- examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck.csproj
- examples/Deepgram.Examples.TextToSpeech.Websocket.Simple/Deepgram.Examples.TextToSpeech.Websocket.Simple.csproj
🔇 Additional comments (33)
examples/Deepgram.Examples.Manage.Members/Deepgram.Examples.Manage.Members.csproj (3)
1-11
: Project structure follows .NET conventions.
The overall project structure adheres to .NET conventions with proper SDK reference, clear property definitions, and organized ItemGroup sections. The nullable enable flag is a good practice for new projects.
9-9
: Verify the $(ProjectRoot) variable resolution.
The project reference uses $(ProjectRoot)
which is not a standard MSBuild variable. This might cause build issues if the variable is not properly defined in a Directory.Build.props file or similar.
#!/bin/bash
# Check for Directory.Build.props or other files that might define ProjectRoot
fd "Directory.Build.props"
# Check if other .csproj files use the same variable
fd -e csproj . | xargs grep "ProjectRoot"
8-8
: Verify HTTP package compatibility with target framework.
The Microsoft.Extensions.Http package version 8.0.1 is the latest stable version, but it's designed for .NET 8. While it might work with .NET 9 preview, consider aligning the package version with the final target framework version when .NET 9 is released.
#!/bin/bash
# Check for other Microsoft.Extensions packages to ensure version consistency
fd -e csproj . | xargs grep -A 1 "Microsoft.Extensions"
examples/Deepgram.Examples.Manage.Projects/Deepgram.Examples.Manage.Projects.csproj (2)
7-10
: Verify Directory.Build.props setup
The project reference uses $(ProjectRoot)
variable which requires proper setup in Directory.Build.props.
Let's verify the build configuration:
✅ Verification successful
Directory.Build.props setup is correctly configured
The $(ProjectRoot)
variable is properly defined in Directory.Build.props at the repository root and is consistently used across multiple projects in the solution. The variable is set to $(MSBuildThisFileDirectory)
, which is the standard MSBuild way to reference the directory containing the props file.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if Directory.Build.props exists and defines ProjectRoot
echo "Checking for Directory.Build.props:"
fd -e props "Directory.Build" --exec grep -l "ProjectRoot"
# Verify consistent variable usage across projects
echo "Checking ProjectRoot usage in other projects:"
fd -e csproj . --exec grep -l "ProjectRoot"
Length of output: 3534
Script:
#!/bin/bash
# Check the content of Directory.Build.props to verify ProjectRoot definition
echo "Content of Directory.Build.props:"
cat Directory.Build.props
Length of output: 229
1-6
: Consider using a stable .NET version for examples
While upgrading dependencies is good, using .NET 9.0 (preview) in example projects might create challenges for users as:
- Preview versions may have breaking changes
- Users typically run stable .NET versions
- Example projects should prioritize stability and broad compatibility
Consider targeting .NET 8.0 (LTS) instead.
examples/Deepgram.Examples.Analyze.Sentiment/Deepgram.Examples.Analyze.Sentiment.csproj (1)
8-8
: Verify Microsoft.Extensions.Http version compatibility
The package reference to Microsoft.Extensions.Http 8.0.1 looks good and is the latest stable version.
✅ Verification successful
Microsoft.Extensions.Http version 8.0.1 is used consistently across the codebase
The version 8.0.1 of Microsoft.Extensions.Http is used consistently in all projects that reference it, including both example projects and the main SDK projects. This version is compatible with the project's target frameworks (net6.0, net7.0, net8.0, netstandard2.0) and aligns with other Microsoft.Extensions.* package versions used in the codebase.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if this version is used consistently across all example projects
# and verify if it resolves the security advisory GHSA-hh2w-p6rv-4g7w
# Test: Search for Microsoft.Extensions.Http package references
rg --type=xml 'PackageReference.*Microsoft\.Extensions\.Http.*Version'
Length of output: 221
Script:
#!/bin/bash
# Let's try a broader search for csproj files first and then look for the package reference
fd -e csproj --exec cat {}
Length of output: 29603
examples/Deepgram.Examples.Analyze.Summary/Program.cs (2)
5-10
: LGTM! File structure follows .NET conventions.
The file organization with proper copyright header, using statements, and namespace structure aligns well with standard .NET practices.
12-13
: LGTM! Appropriate class modifiers for an entry point.
Making the Program class public static
follows .NET best practices for entry point classes, preventing instantiation and providing proper accessibility.
examples/Deepgram.Examples.Analyze.Sentiment/Program.cs (1)
5-10
: LGTM! Namespace and using directives follow .NET conventions.
The namespace hierarchy properly reflects the physical folder structure, and using directives are well-organized.
examples/Deepgram.Examples.SpeechToText.Rest.Intent/Program.cs (1)
Line range hint 13-14
: LGTM!
The class and Main method follow modern C# practices with proper async/await support.
examples/Deepgram.Examples.SpeechToText.Rest.Summary/Program.cs (1)
Line range hint 1-8
: LGTM! Well-structured file header and imports.
The file includes proper copyright notice, license information, and organized imports.
examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Program.cs (2)
Line range hint 1-10
: LGTM! Well-structured file header and imports.
The copyright header with SPDX identifier and minimal required imports follow best practices.
Line range hint 1-46
: Verify security implications of file handling.
Given the security advisory mentioned in the PR (GHSA-hh2w-p6rv-4g7w), let's verify the file handling security implications.
examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Program.cs (1)
5-6
: LGTM: Required using directives added for async functionality
The addition of System and System.Threading.Tasks directives properly supports the async implementation.
examples/Deepgram.Examples.Analyze.Intent/Program.cs (1)
13-15
: LGTM! Changes align with modern .NET practices
The modifications to make the Program class public static
and the Main method public
follow recommended C# practices and improve testability.
examples/Deepgram.Examples.SpeechToText.Rest.File/Program.cs (1)
5-9
: LGTM: Using directives are properly organized.
The added using directives are necessary for file operations and async programming, following .NET conventions.
examples/Deepgram.Examples.Manage.Balances/Program.cs (1)
5-8
: LGTM! Namespace change aligns with .NET conventions.
The updated namespace Deepgram.Examples.Manage.Balances
follows .NET naming guidelines and properly reflects the hierarchical structure of the examples.
examples/Deepgram.Examples.Manage.Members/Program.cs (1)
5-7
: LGTM! Using directives are properly organized.
The using directives follow .NET conventions and include all necessary namespaces for the functionality.
examples/Deepgram.Examples.Manage.Usage/Program.cs (2)
5-6
: LGTM: Necessary namespace additions for async support
The added namespaces are required to support the async/await pattern implementation.
Line range hint 15-17
: Verify consistency across example projects
Let's ensure this async pattern and error handling approach is consistent across other example projects.
✅ Verification successful
Library initialization pattern is consistent across example projects
The verification shows a consistent pattern of Library initialization across all example projects:
- All projects use
Library.Initialize()
with either default logging or explicit log levels - Comments consistently explain logging options when log levels are specified
- Projects requiring microphone access correctly initialize both Deepgram and Microphone libraries
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for consistency in async Main methods and Library initialization across examples
echo "Checking for async Main patterns in example projects..."
ast-grep --pattern 'static async Task Main(string[] args)'
echo "\nChecking Library initialization patterns..."
rg -A 2 'Library.Initialize\(\);'
Length of output: 11985
examples/Deepgram.Examples.Manage.Models/Program.cs (1)
13-15
: LGTM! Changes align with modern .NET practices.
The modifications to make the Program
class and Main
method public static
follow current .NET conventions and improve the example's accessibility.
examples/Deepgram.Examples.Manage.Scopes/Program.cs (1)
5-6
: LGTM: Necessary namespace imports added correctly
The addition of System and Task namespaces is appropriate for enabling async operations in the program.
Deepgram.Microphone/Deepgram.Microphone.csproj (2)
Line range hint 3-7
: Framework targeting strategy looks good!
The multi-targeting approach with netstandard2.0 and modern .NET versions provides good compatibility while enabling the use of latest language features.
140-140
: Verify PortAudioSharp2 upgrade impact.
The upgrade from version 1.0.0 to 1.0.4 might introduce breaking changes. Please ensure that the new version is compatible with your usage.
✅ Verification successful
Let me gather more information about the package versions and changes.
Let me check the changelog or release notes for this package to understand the changes between versions.
PortAudioSharp2 upgrade appears safe
Based on the codebase analysis, the usage of PortAudioSharp2 is limited to basic Stream initialization with standard parameters. The API usage pattern is straightforward and focuses on core functionality:
- Single global import in GlobalUsings.cs
- Basic Stream creation with standard parameters in Microphone.cs
- No complex or deprecated API usage detected
Since no breaking changes are evident in the codebase usage patterns and the version bump is minor (1.0.0 to 1.0.4), this update appears to be safe.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for PortAudioSharp2 usage patterns that might be affected by the upgrade
rg -A 5 "PortAudioSharp"
Length of output: 1380
Script:
#!/bin/bash
# Check the git history for changes in PortAudioSharp2 usage
git log -p -- Deepgram.Microphone/Microphone.cs | grep -A 10 -B 10 "PortAudioSharp"
# Look for any API usage patterns
ast-grep --pattern 'using PortAudioSharp;'
ast-grep --pattern 'new PortAudioSharp.Stream($$$)'
Length of output: 2300
Script:
#!/bin/bash
# Look for any documentation about version changes
fd README.md
fd CHANGELOG.md
fd HISTORY.md
fd RELEASES.md
# Check if there are any tests that might show API usage
fd test -e cs | xargs rg "PortAudioSharp"
Length of output: 155
Deepgram/Deepgram.csproj (2)
86-110
: LGTM! Consistent package versions across frameworks.
The package versions are consistently maintained across net6.0 and net7.0 target frameworks, which is a good practice for dependency management.
146-148
: LGTM! Serilog packages updated to latest stable versions.
The Serilog package updates are appropriate and align with the project's modernization goals.
.gitignore (4)
1-67
: LGTM! Comprehensive core .NET ignores aligned with latest standards.
The core .NET and Visual Studio ignore patterns are up-to-date and comprehensive, including:
- Latest patterns from
dotnet new gitignore
- Build outputs and temporary files
- User-specific files
- Essential security considerations for secrets (.env)
249-252
: Review strong naming configuration.
The comment about strong name files (*.snk) presenting a security risk is noted. Given the PR's security focus:
✅ Verification successful
Strong name signing configuration is not actively used in this codebase
The codebase shows no evidence of using strong name key files (.snk) or strong naming configurations. The commented-out entry in .gitignore appears to be from a template and can be safely ignored since the feature is not in use.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if any .snk files exist in the repository
# Strong name keys should be managed securely
fd -e snk
Length of output: 103
Script:
#!/bin/bash
# Search for any references to .snk files in the codebase
rg -i "\.snk" -g "!.gitignore"
# Also check for strong naming related configurations in project files
rg -i "strongname|assemblykeypair|keyfile" -g "*.csproj" -g "*.config"
Length of output: 105
46-159
: Verify test coverage tool configurations.
The coverage tool configurations are comprehensive, including support for multiple tools (NCrunch, AxoCover, Coverlet, OpenCover). However, given the PR's security focus:
✅ Verification successful
Coverage tool configurations in .gitignore are properly set
The .gitignore rules for coverage tools are working as intended. No coverage reports, test results, or related configuration files were found in the repository, confirming that the ignore patterns are effectively preventing these files from being committed. This helps maintain repository security by keeping implementation details private.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if any coverage reports are accidentally committed
# This helps prevent potential security issues from exposed implementation details
rg -l "\.coverage$|coverage\.(json|xml|info)$"
Length of output: 48
Script:
#!/bin/bash
# Let's verify if there are any coverage files in the repository despite the gitignore
fd -H ".*coverage.*\.(json|xml|info)$|\.coverage$"
# Also check if there are any build artifacts or test results that should be ignored
fd -H "TestResult\.xml|nunit-.*\.xml|\.VisualState\.xml"
# Check if the project actually uses any of these coverage tools by looking for config files
fd -H "\.axocover|\.ncrunch|coverlet\.runsettings|\.coveragerc"
Length of output: 177
201-214
: Verify NuGet package security settings.
The NuGet ignore patterns are comprehensive. However, given the security advisory mentioned in the PR:
✅ Verification successful
NuGet security configuration appears to be properly maintained
The verification shows:
- No NuGet.config files are present in the repository
- No NuGet packages (*.nupkg, *.snupkg) are committed
- Project files only contain standard PackageReference entries
- No sensitive NuGet configurations or credentials are exposed
The .gitignore patterns are appropriate and working as intended.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for any committed NuGet config files that might contain credentials
rg -l "nuget\.config$"
Length of output: 103
Script:
#!/bin/bash
# Search for any NuGet config files with different casing
fd -i "nuget.config"
# Check for any NuGet package files that might have been committed
fd -e nupkg -e snupkg
# Look for potential NuGet related settings in project files
rg -l "PackageReference|RestoreSources|NuGetPackageRoot"
Length of output: 2496
Script:
#!/bin/bash
# Check project files for any NuGet source configurations
rg "RestoreSources|PackageSource" -A 2 -B 2
# Look for any potential credential or token configurations in project files
rg "ApiKey|Password|Token|Secret" --type=xml
Length of output: 241
Deepgram.sln (3)
4-11
: LGTM: Core solution structure follows .NET conventions
The solution structure maintains the essential projects with proper GUID assignments and follows standard .NET conventions.
62-78
: LGTM: Well-structured test organization
The test projects are well-organized with clear separation between:
- Edge case tests
- Expected failure scenarios
This structure will help in maintaining test coverage and debugging.
88-228
: LGTM: Standard build configurations
Build configurations are properly set up with both Debug and Release configurations for all projects.
examples/Deepgram.Examples.Manage.Members/Deepgram.Examples.Manage.Members.csproj
Show resolved
Hide resolved
examples/Deepgram.Examples.Analyze.Sentiment/Deepgram.Examples.Analyze.Sentiment.csproj
Show resolved
Hide resolved
examples/Deepgram.Examples.Analyze.Sentiment/Deepgram.Examples.Analyze.Sentiment.csproj
Show resolved
Hide resolved
using System; | ||
using System.IO; | ||
using System.Threading.Tasks; | ||
using Deepgram; | ||
using Deepgram.Models.Listen.v1.REST; | ||
|
||
namespace PreRecorded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Update namespace to match project structure.
The namespace PreRecorded
should be changed to Deepgram.Examples.SpeechToText.Rest.Intent
to follow .NET naming conventions and match the project structure.
-namespace PreRecorded
+namespace Deepgram.Examples.SpeechToText.Rest.Intent
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
namespace PreRecorded | |
namespace Deepgram.Examples.SpeechToText.Rest.Intent |
@@ -54,7 +59,7 @@ await liveClient.Subscribe(new EventHandler<ResultResponse>((sender, e) => | |||
while (liveClient.IsConnected()) | |||
{ | |||
byte[] buffer = new byte[2048]; | |||
await receiveStream.ReadAsync(buffer, 0, buffer.Length); | |||
await receiveStream.ReadExactlyAsync(buffer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
The context confirms the issues mentioned in the review comment. I can now provide the final response:
Critical: ReadExactlyAsync is unsuitable for streaming audio data
The current implementation in examples/Deepgram.Examples.SpeechToText.Websocket.Http/Program.cs
has serious streaming issues:
- Uses
ReadExactlyAsync
which blocks until exactly 2048 bytes are available - Sends the entire fixed buffer without accounting for partial reads
- Will throw an exception on stream end
- May cause indefinite blocking when streaming slows down
Suggested fix:
byte[] buffer = new byte[2048];
int bytesRead = await receiveStream.ReadAsync(buffer);
if (bytesRead > 0)
{
liveClient.Send(buffer.AsSpan(0, bytesRead).ToArray());
}
🔗 Analysis chain
Critical: Replace ReadExactlyAsync with ReadAsync for streaming audio.
Using ReadExactlyAsync
for streaming audio is problematic because:
- It blocks until exactly 2048 bytes are available, which may cause indefinite waiting
- It throws an exception if the stream ends before filling the buffer
- The fixed buffer size might not align with audio frames
Replace with a more appropriate streaming implementation:
-await receiveStream.ReadExactlyAsync(buffer);
+int bytesRead = await receiveStream.ReadAsync(buffer);
+if (bytesRead > 0)
+{
+ // Only send the actual bytes read
+ liveClient.Send(buffer.AsSpan(0, bytesRead).ToArray());
+}
Let's verify if this pattern is used consistently in other examples:
Let me gather more context about the streaming implementation to ensure a comprehensive verification.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for similar streaming patterns in other example files
rg -l "ReadExactlyAsync" examples/
Length of output: 100
Script:
#!/bin/bash
# Get the full context of the streaming implementation
rg -B 10 -A 10 "ReadExactlyAsync" examples/Deepgram.Examples.SpeechToText.Websocket.Http/Program.cs
Length of output: 935
using System; | ||
using System.Threading.Tasks; | ||
using Deepgram; | ||
using Deepgram.Logger; | ||
using Deepgram.Models.Manage.v1; | ||
|
||
namespace SampleApp | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Align namespace with folder structure to follow .NET conventions.
The namespace SampleApp
doesn't match the project's folder structure. According to .NET conventions, the namespace should reflect the project's hierarchy.
-namespace SampleApp
+namespace Deepgram.Examples.Manage.Models
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
using System; | |
using System.Threading.Tasks; | |
using Deepgram; | |
using Deepgram.Logger; | |
using Deepgram.Models.Manage.v1; | |
namespace SampleApp | |
{ | |
using System; | |
using System.Threading.Tasks; | |
using Deepgram; | |
using Deepgram.Logger; | |
using Deepgram.Models.Manage.v1; | |
namespace Deepgram.Examples.Manage.Models | |
{ |
public static class Program | ||
{ | ||
static async Task Main(string[] args) | ||
public static async Task Main(string[] args) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Inconsistency found in Program class declarations across example projects
The ripgrep results show that while some example projects use public static class Program
, others use just class Program
. This inconsistency should be addressed for better maintainability. Here are the files that need to be updated to match the public static
pattern:
- examples/Deepgram.Examples.SpeechToText.Rest.Url/Program.cs
- examples/Deepgram.Examples.SpeechToText.Rest.Topic/Program.cs
- examples/Deepgram.Examples.TextToSpeech.Rest.File.WoodChuck/Program.cs
- examples/Deepgram.Examples.TextToSpeech.Websocket.Simple/Program.cs
- examples/Deepgram.Examples.SpeechToText.Websocket.Microphone/Program.cs
- examples/Deepgram.Examples.TextToSpeech.Rest.File.HelloWorld/Program.cs
- examples/Deepgram.Examples.SpeechToText.Websocket.File/Program.cs
- examples/Deepgram.Examples.SpeechToText.Websocket.Http/Program.cs
- examples/Deepgram.Examples.SpeechToText.Rest.Sentiment/Program.cs
- examples/Deepgram.Examples.SpeechToText.Rest.Summary/Program.cs
- examples/Deepgram.Examples.SpeechToText.Rest.File/Program.cs
- examples/Deepgram.Examples.SpeechToText.Rest.Intent/Program.cs
- examples/Deepgram.Examples.Manage.Usage/Program.cs
- examples/Deepgram.Examples.Manage.Projects/Program.cs
- examples/Deepgram.Examples.Manage.Scopes/Program.cs
- examples/Deepgram.Examples.Manage.Invitations/Program.cs
- examples/Deepgram.Examples.Manage.Keys/Program.cs
- examples/Deepgram.Examples.Manage.Members/Program.cs
🔗 Analysis chain
Verify consistency across example projects.
Let's ensure the Program class modifications are consistent across all example projects.
Let me try again with the correct language specification for C# files.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check Program class declarations in all example projects
# Expect: All Program classes should be declared as public static
echo "Checking Program class declarations in example projects..."
ast-grep --pattern 'class Program' -l
ast-grep --pattern 'public static class Program'
echo -e "\nChecking Main method declarations..."
ast-grep --pattern 'Task Main(string[] args)'
ast-grep --pattern 'public static async Task Main(string[] args)'
Length of output: 528
Script:
#!/bin/bash
# Search for Program class declarations in C# files
echo "Checking Program class declarations in example projects..."
ast-grep --lang c-sharp --pattern 'class Program' -l
ast-grep --lang c-sharp --pattern 'public static class Program'
echo -e "\nChecking Main method declarations..."
ast-grep --lang c-sharp --pattern 'Task Main(string[] args)'
ast-grep --lang c-sharp --pattern 'public static async Task Main(string[] args)'
# Also use ripgrep as a backup to ensure we don't miss anything
echo -e "\nUsing ripgrep to verify..."
rg "class Program" --type cs -C 2
rg "Task Main\(string\[\] args\)" --type cs -C 2
Length of output: 29174
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0"> | ||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> | ||
<PrivateAssets>all</PrivateAssets> | ||
</PackageReference> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.*" /> | ||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="6.*" /> | ||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" /> | ||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" /> | ||
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="8.0.10" /> | ||
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" /> | ||
<PackageReference Include="System.Text.Json" Version="6.*" /> | ||
<PackageReference Include="System.Threading.Channels" Version="6.*" /> | ||
<PackageReference Include="System.Text.Json" Version="8.0.5" /> | ||
<PackageReference Include="System.Threading.Channels" Version="8.0.0" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Centralize package references to reduce duplication.
The current structure duplicates package references across different framework conditions, which increases maintenance overhead and the risk of version inconsistencies.
Consider centralizing common packages in a single ItemGroup and only specify framework-specific versions where necessary:
- <ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
- <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
- <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
- <PrivateAssets>all</PrivateAssets>
- </PackageReference>
- <!-- ... other duplicate references ... -->
- </ItemGroup>
- <!-- Similar ItemGroups for net6.0, net7.0 -->
+ <ItemGroup>
+ <PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+ <PrivateAssets>all</PrivateAssets>
+ </PackageReference>
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
+ <PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.1" />
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
+ <PackageReference Include="Microsoft.Extensions.Http.Polly" Version="8.0.10" />
+ <PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1" />
+ <PackageReference Include="System.Text.Json" Version="8.0.5" />
+ <PackageReference Include="System.Threading.Channels" Version="8.0.0" />
+ </ItemGroup>
+ <!-- Only keep framework-specific overrides if needed -->
+ <ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
+ <!-- Framework-specific versions -->
+ </ItemGroup>
Also applies to: 86-96, 100-110
GlobalSection(NestedProjects) = preSolution | ||
{BB208398-4B46-4DB5-B9E3-FAD1670A328D} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{D2B35409-FA31-4EAE-978B-BD32199D2341} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{6B4834B3-C9B4-47C3-8812-4743B26E42C9} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{4AF13653-3D33-4402-A68B-0E2C7591FC3C} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{E13D42EC-45D4-4493-B6D5-6FEEED12538A} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{D9480E28-9186-4F91-81C7-79CABCEDC990} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{736440F0-AC08-438E-BEBD-17E3B478DFCF} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{E9D90D83-9996-4B39-964D-A2F1DDEB2196} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{6C279B71-30A2-493C-82D8-1BE957E6F1FF} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{97616AC9-DFB6-443A-AA52-C8DB2CBA1265} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{FCBDF841-02AC-4C47-B6DE-CAAED5982E90} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{09903C4E-0FE6-4198-81D3-F4BD54E2F06B} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{AC8AB221-6623-4CEB-A12F-18F611B21566} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{5F6EF4BF-9322-4D0D-8E1D-EC4CE5AAF444} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{2F6288B7-7254-43A1-AEFF-8B0649230CAB} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{B820741C-6DE8-4AEB-B086-10AB4BA9E7AD} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{A23B61B4-A0D3-42F1-8923-F8BF9A9ED31D} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{E9A120AA-9F07-44E5-953B-FC3CEDACDB37} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{EE8BF074-539B-4573-A2BF-4C6A3F1D3956} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{07331F62-8816-4860-8674-02CCEDF8E58F} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{F5DB1ABF-429B-4406-BC3A-2A6BB7B14264} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{C02BE4D8-0F98-45B0-B66C-0795DA2ED44C} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{079D4774-A3F6-48E4-AE31-E117430CD12C} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{7000E1D8-BA6D-473C-B2FE-D835B0F42906} = {EB85CC21-9BCC-4265-96CC-655A17ADF86D} | ||
{1D0FBABE-6E50-4F02-996A-FFA0E63EE7E7} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{176F3607-9F53-4B4C-A6EB-70C6F5D3C884} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{2A1A1FC9-24A5-4FA9-84F2-2B3B578FE081} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{5FECDC3C-1D9F-437D-A212-5187D692E880} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{020AD025-F982-4703-931C-3A949B005854} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{4637C7EE-AF14-425A-BD1E-F5150B0A8845} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{D5F73F1F-D140-45A8-9E55-9F3C1F7D1F5C} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} | ||
{1CA0AFF4-7985-4F51-8F35-7FD9C458F2D5} = {1A015F52-9174-4A15-8C77-C8AA153DCC5F} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Missing project files in solution
The solution file references multiple .csproj files that are missing from the repository. This indicates a potential issue with project organization or missing files.
-
Main projects missing:
- Deepgram.Microphone/Deepgram.Microphone.csproj
- Deepgram.Tests/Deepgram.Tests.csproj
- Deepgram/Deepgram.csproj
-
All example projects under examples/ directory are missing
-
All test projects under tests/ directory are missing
🔗 Analysis chain
Verify project paths exist
The nested project structure looks good, but let's verify that all project paths exist in the repository.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that all project paths exist
# Test: Check if all .csproj files exist
echo "Checking project files..."
while IFS= read -r line; do
if [[ $line =~ \.csproj\" ]]; then
# Extract path from: Project(...) = "Name", "Path", "{GUID}"
path=$(echo "$line" | sed -n 's/.*"\([^"]*\.csproj\)".*/\1/p')
if [ ! -z "$path" ]; then
if [ ! -f "$path" ]; then
echo "Missing project: $path"
fi
fi
fi
done < Deepgram.sln
Length of output: 64649
Proposed changes
This PR does the following:
examples
andtests
directories per .NET convention.gitignore
fileTypes of changes
What types of changes does your code introduce to the community .NET SDK?
Put an
x
in the boxes that applyChecklist
Put an
x
in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.Further comments
This PR is the first of many for updating this repository to meet the standard .NET project layout and practices. The next PR will be cleaning up the example and test code, then using the conventional logging from
Microsoft.Extensions.Logging.Abstractions
.https://wakatime.com/@a8e4b5db-b8cc-469a-acce-099a0a2425be/projects/dammoujrda?branches=oolunar%2Fupdate-infra&start=2024-10-30&end=2024-11-05
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Documentation