From 98d42558a2336cbbd566b0f07507aece89e5251d Mon Sep 17 00:00:00 2001 From: Ardis Lu Date: Wed, 8 Dec 2021 23:28:19 -0800 Subject: [PATCH 1/1] Initial commit --- ArdisUtilities/ArdisUtilities.psd1 | 16 +++ ArdisUtilities/ArdisUtilities.psm1 | 182 +++++++++++++++++++++++++++++ README.md | 31 +++++ 3 files changed, 229 insertions(+) create mode 100644 ArdisUtilities/ArdisUtilities.psd1 create mode 100644 ArdisUtilities/ArdisUtilities.psm1 create mode 100644 README.md diff --git a/ArdisUtilities/ArdisUtilities.psd1 b/ArdisUtilities/ArdisUtilities.psd1 new file mode 100644 index 0000000..6ed1a11 --- /dev/null +++ b/ArdisUtilities/ArdisUtilities.psd1 @@ -0,0 +1,16 @@ +@{ + RootModule = 'ArdisUtilities.psm1' + ModuleVersion = '0.1.0' + GUID = '57a6bea3-0ea5-44b3-95d2-71d122772f1c' + Author = 'Ardis Lu' + Description = 'My personal utility functions.' + FunctionsToExport = @('Invoke-RandomFile', 'ConvertTo-Base64String', 'Get-StringHash') + CmdletsToExport = @() + VariablesToExport = @() + AliasesToExport = @() + PrivateData = @{ + PSData = @{ + ProjectUri = '' + } + } +} diff --git a/ArdisUtilities/ArdisUtilities.psm1 b/ArdisUtilities/ArdisUtilities.psm1 new file mode 100644 index 0000000..698acac --- /dev/null +++ b/ArdisUtilities/ArdisUtilities.psm1 @@ -0,0 +1,182 @@ +function Invoke-RandomFile { + <# + .SYNOPSIS + Selects and opens a random file in the current directory. + + .DESCRIPTION + Recursively scan the current directory and subdirectories for all file paths, and record it into a text + cache file in the same root directory. Then pick a random line or lines from the text cache file that + meet the file extension requirements. Finally, call Invoke-Item on each of the random files selected. + + .PARAMETER FileCount + The number of files to select and invoke. Must be an integer greater than 0. Default value is 1. + + .PARAMETER FileCategory + The high-level category of file to select. Valid values are "all", "video", "audio", "image", and "document". + Common file extensions for each file category are hardcoded in the function. The default value is "all". + + .PARAMETER SearchFolder + The file path to a specific subfolder to open the random file from. Omitting this parameter will open + a random file from the same directory this command was executed in. + + .EXAMPLE + PS> Invoke-RandomFile + + Creates a file called "all-cache.txt" in the current directory, and opens a random file from this directory. + + .EXAMPLE + PS> Invoke-RandomFile -FileCategory video + + Creates a file called "video-cache.txt" in the current directory, and opens a random video file from this directory. + + .EXAMPLE + PS> Invoke-RandomFile -FileCount 2 -FileCategory video "./path/to/subfolder" + + Creates a file called "video-cache.txt" in the current directory, and opens 2 random video files from the + "./path/to/subfolder" folder. + #> + + [CmdletBinding(PositionalBinding = $false)] # Allows $SearchFolder to be passed from any position + param( + [ValidateRange(1, [int]::MaxValue)] + [Int]$FileCount = 1, + + [ValidateSet('all', 'video', 'audio', 'image', 'document')] + [String]$FileCategory = 'all', + + [Parameter(ValueFromRemainingArguments)] # Allows dragging a subfolder to the shortcut to pass it as a parameter + [ValidateScript({ Test-Path -LiteralPath $_ })] + [String]$SearchFolder + ) + + begin { + # Define common extensions for each file category + $videoExtensions = @('*.mp4', '*.flv', '*.m4v', '*.mkv', '*.avi', '*.webm', '*.wmv', '*.mov') + $audioExtensions = @('*.mp3', '*.wav', '*.wma', '*.ogg', '*.m4a', '*.flac') + $imageExtensions = @('*.jpeg', '*.jpg', '*.png', '*.gif', '*.svg', '*.tif', '*.tiff') + $documentExtensions = @('*.txt', '*.doc', '*.docx', '*.pdf') + + # Define the folder in which this command was executed + $rootFolder = Split-Path $script:MyInvocation.MyCommand.Path + } + + process { + switch ($FileCategory) { + 'video' { $allowedExtensions = $videoExtensions; Break } + 'audio' { $allowedExtensions = $audioExtensions; Break } + 'image' { $allowedExtensions = $imageExtensions; Break } + 'document' { $allowedExtensions = $documentExtensions; Break } + default { $allowedExtensions = '*.*' } + } + + if (-not($PSBoundParameters.ContainsKey('SearchFolder'))) { + $SearchFolder = $rootFolder + } + + # Caches a list of all file paths to disk for better performance on future runs. To refresh the cache, delete the .txt file + if (-not(Test-Path -LiteralPath "$rootFolder/$FileCategory.txt")) { + Get-ChildItem "$rootFolder/*" -Include $allowedExtensions -Recurse | Set-Content "$rootFolder/$FileCategory-cache.txt" + } + + # Check if the cache file was successfully created. If not, that means no valid content was found. + if (-not(Test-Path -LiteralPath "$rootFolder/$FileCategory-cache.txt")) { + throw "No files found in the file category '$FileCategory'." + } + + # Get $FileCount random files from the folder passed to the shortcut (or the command root, if no folder was passed) + $tempFile = New-TemporaryFile # Set-Content -PassThru does not work, needs to write to file + Get-Content "$rootFolder/$FileCategory-cache.txt" | Select-String $SearchFolder -SimpleMatch | Get-Random -Count $FileCount | Set-Content $tempFile # Set-Content is to convert the stream object into a string + $randomFiles = Get-Content $tempFile + Remove-Item $tempFile + + Invoke-Item -LiteralPath $randomFiles # Must use -LiteralPath to take special characters in file paths, like []. Can't pipe to -LiteralPath + } +} + +function ConvertTo-Base64String { + <# + .SYNOPSIS + Converts a string into base64. + + .DESCRIPTION + Uses UTF8Encoding.GetBytes to convert the input string into a byte array, then passes it to + System.Convert.ToBase64String to return the base64-encoded string. + + .PARAMETER InputString + The string to convert to base64. + + .EXAMPLE + PS> ConvertTo-Base64String "Example" + + RXhhbXBsZQ== + + .EXAMPLE + PS> "Example from pipe" | ConvertTo-Base64String + + RXhhbXBsZSBmcm9tIHBpcGU= + #> + + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline)] + [String]$InputString + ) + + process { + [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($InputString)) + } +} + +function Get-StringHash { + <# + .SYNOPSIS + Hashes a string. + + .DESCRIPTION + Converts a string into an input stream, then passes that stream to Get-FileHash to hash the string. + + .PARAMETER InputString + The string to hash. + + .PARAMETER Algorithm + The hashing algorithm to use. Must be an algorithm accepted by Get-FileHash. + + .EXAMPLE + PS> Get-StringHash "Example" + + Algorithm Hash Path + --------- ---- ---- + SHA1 0F01ED56A1E32A05E5EF96E4D779F34784AF9A96 + + .EXAMPLE + PS> Get-StringHash "Example" -Algorithm SHA256 + + + Algorithm Hash Path + --------- ---- ---- + SHA256 D029F87E3D80F8FD9B1BE67C7426B4CC1FF47B4A9D0A8461C826A59D8C5EB6CD + + + .EXAMPLE + PS> "Example from pipe" | Get-StringHash -Algorithm MD5 + + + Algorithm Hash Path + --------- ---- ---- + MD5 B5E635A46089D9BB16C688383D1E98C6 + #> + + [CmdletBinding()] + param( + [Parameter(ValueFromPipeline)] + [String]$InputString = '', + + [ValidateSet('SHA1', 'SHA256', 'SHA384', 'SHA512', 'MD5')] + [String]$Algorithm = 'SHA1' + ) + + process { + $stream = [System.IO.MemoryStream]::new([byte[]][char[]]$InputString) + Get-FileHash -InputStream $stream -Algorithm $Algorithm + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..5fb17cf --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +# ArdisUtilities + +A [PowerShell module](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_modules) containing my personal utility functions. + +## Installation + +1. Download the `ArdisUtilities` folder + +2. In PowerShell: + +```PowerShell +Import-Module ./path/to/ArdisUtilities/ +``` + +To persist this module on new sessions: +- Copy the `ArdisUtilities` folder to any folder on `$env:PSModulePath` ([reference](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_psmodulepath)), or +- Add the `Import-Module` command to your `$profile` ([reference](https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles)) + +## Usage + +View the imported utility functions: + +```PowerShell +Get-Command -Module ArdisUtilities +``` + +Get usage help and examples for a specific function: + +```PowerShell +Get-Help Invoke-RandomFile +``` -- 2.47.3