EtherAssist.psm1
<#
.SYNOPSIS This module contains functions for managing and interacting with the EtherAssist API, including setting and retrieving API keys, and sending queries to the API. .DESCRIPTION The EtherAssist module provides a set of PowerShell functions for securely managing the EtherAssist API key and querying the EtherAssist API. It includes functions to set and get the API key, and to send questions to the API with customizable response options. .NOTES File Name : EtherAssist.psm1 Author : Ryan Mangan Prerequisite : PowerShell V5.1 Copyright 2024 - EfficientEther Ltd # Functions 1. Set-EtherAssistApiKey: Sets and securely stores the EtherAssist API Key. 2. Get-EtherAssistApiKey: Retrieves the stored EtherAssist API Key. 3. Get-EtherAssistResponse: Sends a question to the EtherAssist API and processes the response. 4. Invoke-EtherAssistQuery: Prompts for a user question and sends it to the EtherAssist API with options to mute certain parts of the response. 5. Get-EtherAssistResponseAsObject: Sends a question to the EtherAssist API and returns the response as a structured PowerShell object. 6. Get-EtherAssistResponseAsJson: Sends a question to the EtherAssist API and returns the response as a JSON string with additional details. 7. Get-EtherAssistBasicResponse: Sends a basic question to the EtherAssist API and processes the response. #> # Requires -Version 5.1 # Function: Set-EtherAssistApiKey function Set-EtherAssistApiKey { <# .SYNOPSIS Sets and securely stores the EtherAssist API Key and URL. .DESCRIPTION Stores the API key and URL securely in an encrypted format within the user's profile directory. .PARAMETER ApiKey The API key to be securely stored. .PARAMETER ApiUrl The URL of the EtherAssist API to be stored. .EXAMPLE Set-EtherAssistApiKey -ApiKey "your_api_key_here" -ApiUrl "https://<your_api_url_here>" #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ApiKey, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$ApiUrl ) try { $KeyFilePath = Join-Path $env:USERPROFILE "EtherAssistApiKey.xml" $secureApiKey = ConvertTo-SecureString $ApiKey -AsPlainText -Force $settings = @{ ApiKey = $secureApiKey ApiUrl = $ApiUrl } $settings | Export-Clixml -Path $KeyFilePath } catch { Write-Error "Error storing API Key: $_" } } # Function: Get-EtherAssistApiKey function Get-EtherAssistApiKey { <# .SYNOPSIS Retrieves the stored EtherAssist API Key and URL. .DESCRIPTION Fetches and decrypts the stored API Key and URL from the user's profile directory. .OUTPUTS Hashtable. Returns a hashtable containing the API key and URL. .EXAMPLE $settings = Get-EtherAssistApiKey #> [CmdletBinding()] $KeyFilePath = Join-Path $env:USERPROFILE "EtherAssistApiKey.xml" if (Test-Path $KeyFilePath) { try { $settings = Import-Clixml -Path $KeyFilePath $settings.ApiKey = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($settings.ApiKey)) return $settings } catch { Write-Error "Error retrieving API Key: $_" } } else { Write-Error "API Key and URL are not set. Use Set-EtherAssistApiKey to configure." } } # Function: Invoke-EtherAssistApi function Invoke-EtherAssistApi { <# .SYNOPSIS Invokes a query to the EtherAssist API. .DESCRIPTION Sends a request to the specified EtherAssist API endpoint with the given body. .PARAMETER Endpoint The specific API endpoint to send the request to. .PARAMETER Body The body of the request to be sent to the API. .EXAMPLE $response = Invoke-EtherAssistApi -Endpoint "/question" -Body $body #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Endpoint, [Parameter(Mandatory = $true)] [ValidateNotNull()] [hashtable]$Body ) $settings = Get-EtherAssistApiKey if (-not $settings) { Write-Error "API settings are not set. Use Set-EtherAssistApiKey to set the key and URL." return } $uri = "$($settings.ApiUrl)$Endpoint" $headers = @{ Authorization = "Bearer $($settings.ApiKey)" } try { $response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body ($Body | ConvertTo-Json) -ContentType "application/json" return $response } catch { Write-Error "Error in calling EtherAssist API: $_" } } # Function: Get-EtherAssistResponse function Get-EtherAssistResponse { <# .SYNOPSIS Sends a query to the EtherAssist API and processes the response. .DESCRIPTION Interacts with the EtherAssist API, sending a user-defined question and allowing response customization. The MuteAnswer switch only removes the 'Answer:' label from the response, keeping the answer text. .PARAMETER Question The question to be sent to the EtherAssist API. .PARAMETER UseAdvancedModel If set, uses the advanced model for generating the response. .PARAMETER MuteQuestion If set, omits the question from the response. .PARAMETER MuteDateTime If set, omits the date/time from the response. .PARAMETER MuteAnswer If set, removes the 'Answer:' label from the response, keeping the answer text. .PARAMETER SummarizeText If set, summarizes the provided text into a title. .PARAMETER GenerateErrorCodeDescription If set, generates an error code description and possible solutions. .PARAMETER ConvertVbsToPs If set, converts VBS scripts to PowerShell scripts. .PARAMETER GetAppDescription If set, provides a description for an application. .PARAMETER Title If set, provides a title for the given text. .NOTE Only one of the following switches can be used at a time: -UseAdvancedModel, -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, -Title .EXAMPLE Get-EtherAssistResponse -Question "What is Cyber Essentials?" .EXAMPLE Get-EtherAssistResponse -Question "Tell me a joke" -MuteQuestion -MuteDateTime -MuteAnswer #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Question, [switch]$UseAdvancedModel, [switch]$MuteQuestion, [switch]$MuteDateTime, [switch]$MuteAnswer, [switch]$SummarizeText, [switch]$GenerateErrorCodeDescription, [switch]$ConvertVbsToPs, [switch]$GetAppDescription, [switch]$Title ) # Ensure only one processing option is selected $optionsSelected = @($SummarizeText, $GenerateErrorCodeDescription, $ConvertVbsToPs, $GetAppDescription, $Title) | Where-Object { $_.IsPresent } if ($optionsSelected.Count -gt 1) { Write-Error "You can only select one of -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, or -Title at a time." return } $endpoint = "/question" $body = @{ question = $Question useAdvancedModel = $UseAdvancedModel.IsPresent } if ($SummarizeText.IsPresent) { $endpoint = "/utils/Summarize" } elseif ($Title.IsPresent) { $endpoint = "/utils/title" # Correct endpoint for title generation } elseif ($GenerateErrorCodeDescription.IsPresent) { $endpoint = "/gen/errorcode" } elseif ($ConvertVbsToPs.IsPresent) { $endpoint = "/gen/convert-vbs-to-ps" } elseif ($GetAppDescription.IsPresent) { $endpoint = "/apps/app-description" } $responseObject = Invoke-EtherAssistApi -Endpoint $endpoint -Body $body if ($responseObject.success -eq $true) { $responseMessage = @() if (-not $MuteQuestion) { $responseMessage += "Question: $Question" } if (-not $MuteDateTime) { $responseMessage += "Date/Time: $(Get-Date)" } $answerText = $responseObject.answer if (-not $MuteAnswer) { $responseMessage += "Answer: $answerText" } else { $responseMessage += $answerText } $responseMessage -join "`n" } else { Write-Error "API request was not successful: $($responseObject.errorMessage)" } } # Function: Invoke-EtherAssistQuery function Invoke-EtherAssistQuery { <# .SYNOPSIS Prompts for a user question and sends it to the EtherAssist API with options to mute certain parts of the response. .DESCRIPTION This function prompts the user to enter a question, which is then sent to the EtherAssist API. The user can choose to mute the question, date/time, and/or answer label in the response. .PARAMETER UseAdvancedModel If set, uses the advanced model for generating the response. .PARAMETER MuteQuestion If set, omits the question from the response. .PARAMETER MuteDateTime If set, omits the date/time from the response. .PARAMETER MuteAnswer If set, removes the 'Answer:' label from the response, keeping only the answer text. .EXAMPLE Invoke-EtherAssistQuery -MuteQuestion -MuteDateTime -MuteAnswer #> [CmdletBinding()] param ( [switch]$UseAdvancedModel, [switch]$MuteQuestion, [switch]$MuteDateTime, [switch]$MuteAnswer ) try { # Prompt the user to input the question $question = Read-Host "Please enter the question for EtherAssist" # Call the Get-EtherAssistResponse function with the user's question and muting options Get-EtherAssistResponse -Question $question -UseAdvancedModel:$UseAdvancedModel -MuteQuestion:$MuteQuestion -MuteDateTime:$MuteDateTime -MuteAnswer:$MuteAnswer } catch { Write-Error "An error occurred while invoking EtherAssist query: $_" } } # Function: Get-EtherAssistResponseAsObject function Get-EtherAssistResponseAsObject { <# .SYNOPSIS Sends a question to the EtherAssist API and returns the response as a structured PowerShell object. .PARAMETER Question The question to be sent to the EtherAssist API. .PARAMETER UseAdvancedModel If set, uses the advanced model for generating the response. .PARAMETER SummarizeText If set, summarizes the provided text into a title. .PARAMETER GenerateErrorCodeDescription If set, generates an error code description and possible solutions. .PARAMETER ConvertVbsToPs If set, converts VBS scripts to PowerShell scripts. .PARAMETER GetAppDescription If set, provides a description for an application. .PARAMETER Title If set, provides a title for the given text. .NOTE Only one of the following switches can be used at a time: -UseAdvancedModel, -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, -Title .EXAMPLE Get-EtherAssistResponseAsObject -Question "What is Cyber Essentials?" #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Question, [switch]$UseAdvancedModel, [switch]$SummarizeText, [switch]$GenerateErrorCodeDescription, [switch]$ConvertVbsToPs, [switch]$GetAppDescription, [switch]$Title ) # Ensure only one processing option is selected $optionsSelected = @($SummarizeText, $GenerateErrorCodeDescription, $ConvertVbsToPs, $GetAppDescription, $Title) | Where-Object { $_.IsPresent } if ($optionsSelected.Count -gt 1) { Write-Error "You can only select one of -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, or -Title at a time." return } $endpoint = "/question" $body = @{ question = $Question useAdvancedModel = $UseAdvancedModel.IsPresent } if ($SummarizeText.IsPresent) { $endpoint = "/utils/Summarize" } elseif ($Title.IsPresent) { $endpoint = "/utils/title" # Correct endpoint for title generation } elseif ($GenerateErrorCodeDescription.IsPresent) { $endpoint = "/gen/errorcode" } elseif ($ConvertVbsToPs.IsPresent) { $endpoint = "/gen/convert-vbs-to-ps" } elseif ($GetAppDescription.IsPresent) { $endpoint = "/apps/app-description" } $responseObject = Invoke-EtherAssistApi -Endpoint $endpoint -Body $body if ($responseObject.success -eq $true) { # Create a custom object to hold the desired properties $resultObject = [PSCustomObject]@{ Question = $Question Answer = $responseObject.answer TimeOfQuery = Get-Date AdditionalData = $responseObject | Select-Object * -ExcludeProperty question, answer } return $resultObject } else { Write-Error "API request was not successful: $($responseObject.errorMessage)" return $null } } # Function: Get-EtherAssistResponseAsJson function Get-EtherAssistResponseAsJson { <# .SYNOPSIS Sends a question to the EtherAssist API and returns the response as a JSON string with additional details. .PARAMETER Question The question to be sent to the EtherAssist API. .PARAMETER UseAdvancedModel If set, uses the advanced model for generating the response. .PARAMETER SummarizeText If set, summarizes the provided text into a title. .PARAMETER GenerateErrorCodeDescription If set, generates an error code description and possible solutions. .PARAMETER ConvertVbsToPs If set, converts VBS scripts to PowerShell scripts. .PARAMETER GetAppDescription If set, provides a description for an application. .PARAMETER Title If set, provides a title for the given text. .NOTE Only one of the following switches can be used at a time: -UseAdvancedModel, -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, -Title .EXAMPLE Get-EtherAssistResponseAsJson -Question "What is Cyber Essentials?" #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Question, [switch]$UseAdvancedModel, [switch]$SummarizeText, [switch]$GenerateErrorCodeDescription, [switch]$ConvertVbsToPs, [switch]$GetAppDescription, [switch]$Title ) # Ensure only one processing option is selected $optionsSelected = @($SummarizeText, $GenerateErrorCodeDescription, $ConvertVbsToPs, $GetAppDescription, $Title) | Where-Object { $_.IsPresent } if ($optionsSelected.Count -gt 1) { Write-Error "You can only select one of -SummarizeText, -GenerateErrorCodeDescription, -ConvertVbsToPs, -GetAppDescription, or -Title at a time." return } $endpoint = "/question" $body = @{ question = $Question useAdvancedModel = $UseAdvancedModel.IsPresent } if ($SummarizeText.IsPresent) { $endpoint = "/utils/Summarize" } elseif ($Title.IsPresent) { $endpoint = "/utils/title" # Correct endpoint for title generation } elseif ($GenerateErrorCodeDescription.IsPresent) { $endpoint = "/gen/errorcode" } elseif ($ConvertVbsToPs.IsPresent) { $endpoint = "/gen/convert-vbs-to-ps" } elseif ($GetAppDescription.IsPresent) { $endpoint = "/apps/app-description" } $responseObject = Invoke-EtherAssistApi -Endpoint $endpoint -Body $body if ($responseObject.success -eq $true) { # Create a custom object and then convert it to a JSON string $resultObject = [PSCustomObject]@{ Question = $Question Answer = $responseObject.answer TimeOfQuery = Get-Date -Format 'o' # ISO 8601 format AdditionalData = $responseObject | Select-Object * -ExcludeProperty question, answer } return $resultObject | ConvertTo-Json -Depth 10 } else { Write-Error "API request was not successful: $($responseObject.errorMessage)" return $null } } # Function: Get-EtherAssistBasicResponse function Get-EtherAssistBasicResponse { <# .SYNOPSIS Sends a basic question to the EtherAssist API and processes the response. .DESCRIPTION Interacts with the EtherAssist API, sending a user-defined question and allowing response customization. The MuteAnswer switch only removes the 'Answer:' label from the response, keeping the answer text. .PARAMETER Question The question to be sent to the EtherAssist API. .PARAMETER MuteQuestion If set, omits the question from the response. .PARAMETER MuteDateTime If set, omits the date/time from the response. .PARAMETER MuteAnswer If set, removes the 'Answer:' label from the response, keeping the answer text. .PARAMETER Advanced If set, uses the advanced model for generating the response. .EXAMPLE Get-EtherAssistBasicResponse -Question "What is Cyber Essentials?" .EXAMPLE Get-EtherAssistBasicResponse -Question "Tell me a joke" -MuteQuestion -MuteDateTime -MuteAnswer .EXAMPLE Get-EtherAssistBasicResponse -Question "Explain the benefits of PowerShell" -Advanced #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Question, [switch]$MuteQuestion, [switch]$MuteDateTime, [switch]$MuteAnswer, [switch]$Advanced ) $body = @{ question = $Question useAdvancedModel = $Advanced.IsPresent } $responseObject = Invoke-EtherAssistApi -Endpoint "/question-basic" -Body $body if ($responseObject.success -eq $true) { $responseMessage = @() if (-not $MuteQuestion) { $responseMessage += "Question: $Question" } if (-not $MuteDateTime) { $responseMessage += "Date/Time: $(Get-Date)" } $answerText = $responseObject.answer if (-not $MuteAnswer) { $responseMessage += "Answer: $answerText" } else { $responseMessage += $answerText } $responseMessage -join "`n" } else { Write-Error "API request was not successful: $($responseObject.errorMessage)" } } Export-ModuleMember -Function Set-EtherAssistApiKey, Get-EtherAssistApiKey, Get-EtherAssistResponse, Invoke-EtherAssistQuery, Get-EtherAssistResponseAsObject, Get-EtherAssistResponseAsJson, Get-EtherAssistBasicResponse |