GitHubToolsBD.psm1

function Copy-GithubFile {
  <#
  .SYNOPSIS
    This comand will download one or more files from a GitHub Repo
  .DESCRIPTION
    This command requires a Github username and Repository name, if a filename is
    supplied it will download that file from the repo. If no filename is given then
    the blobs in the repository will be listed for selection in a GridView selection
    window.
  .PARAMETER GithubUsername
    This refers to the name of the GitHub account
  .PARAMETER GithubRepository
    This refers to the name of the Repository
  .PARAMETER DownloadPath
    This is the local directory that the files will be downloaded to
  .PARAMETER FileName
    This is the names of the files that are to be downloaded, this can be any part of the file name, if there are
    more than one github file that matches the filename a selection window will appear asking you to select the
    correct file.
  .EXAMPLE
    Copy-GithubFile -GithubUsername 'MSSA-AU' -GithubRepository 'ClassInfo' -DownloadPath 'e:\' -FileName 'Test.csv'
    This will download the Test.csv file from the GitHub Repo Classinfo that is in the MSSA-AU GitHub account.
    The file will be downloaded to the E:\ directory.
  .EXAMPLE
    Copy-GithubFile -GithubUsername 'MSSA-AU' -GithubRepository 'ClassInfo' -DownloadPath 'e:\'
    This will list all of the blobs in the repo in a selection window where you can manually choose which files
    will be downloaded.
  .EXAMPLE
    Copy-GithubFile
    This will prompt for the github username, repo name and the download directory. It will then list all of the blobs
    in the repo in a selection window where you can manually choose which files will be downloaded.
  .NOTES
    Created By: Brent Denny
    Created On: 30 Jun 2023
 
    Changelog
    ---------
    Version Date Changes made
    ------- ---- ------------
    1.8 30 Jun 2023 Created the Copy-GithubFile to retrieve files from github and convert them from base64 encoding
    1.9 30 Jun 2023 Fixed the constant showing of the selection window even if there was just one file to download
    2.0 30 Jun 2023 Fixed an issue that gave a file error on a matching file
  #>

  
  
  [CmdletBinding()]
  param (
    [Parameter(Mandatory=$true)]
    [string]$GithubUsername,
    [Parameter(Mandatory=$true)]
    [string]$GithubRepository,
    [Parameter(Mandatory=$true)]
    [string]$DownloadPath,
    [string[]]$FileNames
  )
  try {
    $RepoInfo = Invoke-RestMethod -Uri "https://api.github.com/repos/$GithubUsername/$GithubRepository" -ErrorAction stop
  }
  catch {
    Write-Warning 'The GitHub Repository could not be located'
    break
  } 
  $MatchingBlobs = @()
  $RestResult = Invoke-RestMethod -uri "https://api.github.com/repos/$GithubUsername/$GithubRepository/git/trees/$($RepoInfo.default_branch)?recursive=1"
  $BlobNames = ($RestResult.tree | Where-Object {$_.type -eq 'blob'}).path
  if ($FileNames.Count -eq 0) { $FileNames = $BlobNames | Out-GridView -OutputMode Multiple -Title 'Select which files to download' }
  foreach ($File in $FileNames) {
    $MatchingBlobs = $BlobNames | Where-Object {$_ -match $File}
    if ($MatchingBlobs.Count -eq 0) {Write-Warning "$File could not be located"; continue}
    elseif ($MatchingBlobs.Count -gt 1) {$SelectedBlob = $MatchingBlobs | Out-GridView -OutputMode Single -Title 'Select which file to download'}
    else {$SelectedBlob = $MatchingBlobs} 
    try {
      $RestResult = Invoke-RestMethod -uri "https://api.github.com/repos/$GithubUsername/$GithubRepository/contents/$SelectedBlob" -ErrorAction Stop 
      $StringArray = [System.Convert]::FromBase64String($RestResult.content) | ForEach-Object {[char]$_} 
      $FileContents = $StringArray -join ''
      $LeafName = Split-Path $SelectedBlob -Leaf
      if (-not (Test-Path $DownloadPath)) {
        try {
          New-Item -Path $DownloadPath -ItemType Directory -ErrorAction Stop
        }
        catch {
          Write-Warning "Download path cannot be resolved"
          break
        }
      }
      $FileContents | Out-File -FilePath ($DownloadPath.trim('\') + '\' + $LeafName) -ErrorAction Stop
    } 
    catch {
      Write-Warning "$File - could not be located"
    }
  }
}