GitHub.psm1

[Cmdletbinding()]
param()

$scriptName = $MyInvocation.MyCommand.Name
Write-Verbose "[$scriptName] Importing subcomponents"

#region - Data import
Write-Verbose "[$scriptName] - [data] - Processing folder"
$dataFolder = (Join-Path $PSScriptRoot 'data')
Write-Verbose "[$scriptName] - [data] - [$dataFolder]"
Get-ChildItem -Path "$dataFolder" -Recurse -Force -Include '*.psd1' -ErrorAction SilentlyContinue | ForEach-Object {
    Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Importing"
    New-Variable -Name $_.BaseName -Value (Import-PowerShellDataFile -Path $_.FullName) -Force
    Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Done"
}

Write-Verbose "[$scriptName] - [data] - Done"
#endregion - Data import

#region - From private
Write-Verbose "[$scriptName] - [private] - Processing folder"

#region - From private/Auth
Write-Verbose "[$scriptName] - [private/Auth] - Processing folder"

#region - From private/Auth/DeviceFlow
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow] - Processing folder"

#region - From private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1] - Importing"

function Invoke-GitHubDeviceFlowLogin {
    <#
        .SYNOPSIS
        Starts the GitHub Device Flow login process.

        .DESCRIPTION
        Starts the GitHub Device Flow login process. This will prompt the user to visit a URL and enter a code.

        .EXAMPLE
        Invoke-GitHubDeviceFlowLogin

        This will start the GitHub Device Flow login process.
        The user gets prompted to visit a URL and enter a code.

        .NOTES
        For more info about the Device Flow visit:
        https://docs.github.com/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app
        https://docs.github.com/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps#device-flow
    #>

    [OutputType([void])]
    [CmdletBinding()]
    param(
        # The Client ID of the GitHub App.
        [Parameter(Mandatory)]
        [string] $ClientID,

        # The scope of the access token, when using OAuth authentication.
        # Provide the list of scopes as space-separated values.
        # For more information on scopes visit:
        # https://docs.github.com/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
        [Parameter()]
        [string] $Scope,

        # The refresh token to use for re-authentication.
        [Parameter()]
        [securestring] $RefreshToken
    )

    do {
        if ($RefreshToken) {
            $tokenResponse = Wait-GitHubAccessToken -ClientID $ClientID -RefreshToken $RefreshToken
        } else {
            $deviceCodeResponse = Request-GitHubDeviceCode -ClientID $ClientID -Scope $Scope

            $deviceCode = $deviceCodeResponse.device_code
            $interval = $deviceCodeResponse.interval
            $userCode = $deviceCodeResponse.user_code
            $verificationUri = $deviceCodeResponse.verification_uri

            Write-Host '! ' -ForegroundColor DarkYellow -NoNewline
            Write-Host "We added the code to your clipboard: [$userCode]"
            $userCode | Set-Clipboard
            Read-Host 'Press Enter to open github.com in your browser...'
            Start-Process $verificationUri

            $tokenResponse = Wait-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID -Interval $interval
        }
    } while ($tokenResponse.error)
    $tokenResponse
}

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1] - Done"
#endregion - From private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1
#region - From private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1] - Importing"

function Request-GitHubAccessToken {
    <#
        .SYNOPSIS
        Request a GitHub token using the Device Flow.

        .DESCRIPTION
        Request a GitHub token using the Device Flow.
        This will poll the GitHub API until the user has entered the code.

        .EXAMPLE
        Request-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID

        This will poll the GitHub API until the user has entered the code.

        .NOTES
        For more info about the Device Flow visit:
        https://docs.github.com/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app
    #>

    [OutputType([PSCustomObject])]
    [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')]
    param(
        # The Client ID of the GitHub App.
        [Parameter(Mandatory)]
        [string] $ClientID,

        # The 'device_code' used to request the access token.
        [Parameter(
            Mandatory,
            ParameterSetName = 'DeviceFlow'
        )]
        [string] $DeviceCode,

        # The refresh token used create a new access token.
        [Parameter(
            Mandatory,
            ParameterSetName = 'RefreshToken'
        )]
        [securestring] $RefreshToken
    )

    $body = @{
        'client_id' = $ClientID
    }

    if ($PSBoundParameters.ContainsKey('RefreshToken')) {
        $body += @{
            'refresh_token' = (ConvertFrom-SecureString $RefreshToken -AsPlainText)
            'grant_type'    = 'refresh_token'
        }
    }

    if ($PSBoundParameters.ContainsKey('DeviceCode')) {
        $body += @{
            'device_code' = $DeviceCode
            'grant_type'  = 'urn:ietf:params:oauth:grant-type:device_code'
        }
    }

    $RESTParams = @{
        Uri     = 'https://github.com/login/oauth/access_token'
        Method  = 'POST'
        Body    = $body
        Headers = @{ 'Accept' = 'application/json' }
    }

    try {
        Write-Verbose ($RESTParams.GetEnumerator() | Out-String)

        $tokenResponse = Invoke-RestMethod @RESTParams -Verbose:$false

        Write-Verbose ($tokenResponse | ConvertTo-Json | Out-String)
        return $tokenResponse
    } catch {
        Write-Error $_
        throw $_
    }
}

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1] - Done"
#endregion - From private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1
#region - From private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1] - Importing"

function Request-GitHubDeviceCode {
    <#
        .SYNOPSIS
        Request a GitHub Device Code.

        .DESCRIPTION
        Request a GitHub Device Code.

        .EXAMPLE
        Request-GitHubDeviceCode -ClientID $ClientID -Mode $Mode

        This will request a GitHub Device Code.

        .NOTES
        For more info about the Device Flow visit:
        https://docs.github.com/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app
    #>

    [OutputType([PSCustomObject])]
    [CmdletBinding()]
    param(
        # The Client ID of the GitHub App.
        [Parameter(Mandatory)]
        [string] $ClientID,

        # The scope of the access token, when using OAuth authentication.
        # Provide the list of scopes as space-separated values.
        # For more information on scopes visit:
        # https://docs.github.com/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
        [Parameter()]
        [string] $Scope = 'gist, read:org, repo, workflow'
    )

    $headers = @{
        Accept = 'application/json'
    }

    $body = @{
        client_id = $ClientID
        scope     = $Scope
    }

    $RESTParams = @{
        Uri     = 'https://github.com/login/device/code'
        Method  = 'POST'
        Body    = $body
        Headers = $headers
    }

    try {
        Write-Verbose ($RESTParams.GetEnumerator() | Out-String)

        $deviceCodeResponse = Invoke-RestMethod @RESTParams -Verbose:$false
        return $deviceCodeResponse
    } catch {
        Write-Error $_
        throw $_
    }
}

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1] - Done"
#endregion - From private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1
#region - From private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1] - Importing"

function Test-GitHubAccessTokenRefreshRequired {
    <#
        .SYNOPSIS
        Test if the GitHub access token should be refreshed.

        .DESCRIPTION
        Test if the GitHub access token should be refreshed.

        .EXAMPLE
        Test-GitHubAccessTokenRefreshRequired

        This will test if the GitHub access token should be refreshed.
    #>

    [CmdletBinding()]
    param()

    $tokenType = Get-GitHubConfig -Name 'AccessTokenType' -ErrorAction SilentlyContinue
    if ($tokenType -ne 'ghu_*') {
        Write-Verbose "The access token is not a user token. No need to refresh."
        return $false
    }

    $tokenExpirationDate = Get-GitHubConfig -Name 'AccessTokenExpirationDate' -ErrorAction SilentlyContinue
    $currentDateTime = Get-Date
    $remainingDuration = [datetime]$tokenExpirationDate - $currentDateTime

    # If the remaining time is less that $script:Auth.AccessTokenGracePeriodInHours then the token should be refreshed
    $remainingDuration.TotalHours -lt $script:Auth.AccessTokenGracePeriodInHours
}

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1] - Done"
#endregion - From private/Auth/DeviceFlow/Test-GitHubAccessTokenRefreshRequired.ps1
#region - From private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1
Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1] - Importing"

function Wait-GitHubAccessToken {
    <#
        .SYNOPSIS
        Waits for the GitHub Device Flow to complete.

        .DESCRIPTION
        Waits for the GitHub Device Flow to complete.
        This will poll the GitHub API until the user has entered the code.

        .EXAMPLE
        Wait-GitHubAccessToken -DeviceCode $deviceCode -ClientID $ClientID -Interval $interval

        This will poll the GitHub API until the user has entered the code.

        .EXAMPLE
        Wait-GitHubAccessToken -Refresh -ClientID $ClientID

        .NOTES
        For more info about the Device Flow visit:
        https://docs.github.com/apps/creating-github-apps/writing-code-for-a-github-app/building-a-cli-with-a-github-app
    #>

    [OutputType([PSCustomObject])]
    [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')]
    param(
        # The Client ID of the GitHub App.
        [Parameter(Mandatory)]
        [string] $ClientID,

        # The device code used to request the access token.
        [Parameter(
            Mandatory,
            ParameterSetName = 'DeviceFlow'
        )]
        [string] $DeviceCode,

        # The refresh token used to request a new access token.
        [Parameter(
            Mandatory,
            ParameterSetName = 'RefreshToken'
        )]
        [securestring] $RefreshToken,

        # The interval to wait between polling for the token.
        [Parameter()]
        [int] $Interval = 5

    )

    do {
        if ($RefreshToken) {
            $response = Request-GitHubAccessToken -ClientID $ClientID -RefreshToken $RefreshToken
        } else {
            $response = Request-GitHubAccessToken -ClientID $ClientID -DeviceCode $DeviceCode
        }
        if ($response.error) {
            switch ($response.error) {
                'authorization_pending' {
                    # The user has not yet entered the code.
                    # Wait, then poll again.
                    Write-Verbose $response.error_description
                    Start-Sleep -Seconds $interval
                    continue
                }
                'slow_down' {
                    # The app polled too fast.
                    # Wait for the interval plus 5 seconds, then poll again.
                    Write-Verbose $response.error_description
                    Start-Sleep -Seconds ($interval + 5)
                    continue
                }
                'expired_token' {
                    # The 'device_code' expired, and the process needs to restart.
                    Write-Error $response.error_description
                    exit 1
                }
                'unsupported_grant_type' {
                    # The 'grant_type' is not supported.
                    Write-Error $response.error_description
                    exit 1
                }
                'incorrect_client_credentials' {
                    # The 'client_id' is not valid.
                    Write-Error $response.error_description
                    exit 1
                }
                'incorrect_device_code' {
                    # The 'device_code' is not valid.
                    Write-Error $response.error_description
                    exit 2
                }
                'access_denied' {
                    # The user cancelled the process. Stop polling.
                    Write-Error $response.error_description
                    exit 1
                }
                'device_flow_disabled' {
                    # The GitHub App does not support the Device Flow.
                    Write-Error $response.error_description
                    exit 1
                }
                default {
                    # The response contains an access token. Stop polling.
                    Write-Error 'Unknown error:'
                    Write-Error $response.error
                    Write-Error $response.error_description
                    Write-Error $response.error_uri
                    break
                }
            }
        }
    } until ($response.access_token)
    $response
}

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1] - Done"
#endregion - From private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1

Write-Verbose "[$scriptName] - [private/Auth/DeviceFlow] - Done"
#endregion - From private/Auth/DeviceFlow


Write-Verbose "[$scriptName] - [private/Auth] - Done"
#endregion - From private/Auth

#region - From private/Config
Write-Verbose "[$scriptName] - [private/Config] - Processing folder"

#region - From private/Config/Initialize-SecretVault.ps1
Write-Verbose "[$scriptName] - [private/Config/Initialize-SecretVault.ps1] - Importing"

#Requires -Version 7.0
#Requires -Modules Microsoft.PowerShell.SecretManagement
#Requires -Modules Microsoft.PowerShell.SecretStore

function Initialize-SecretVault {
    <#
    .SYNOPSIS
    Initialize a secret vault.

    .DESCRIPTION
    Initialize a secret vault. If the vault does not exist, it will be created.

    .EXAMPLE
    Initialize-SecretVault -Name 'SecretStore' -Type 'Microsoft.PowerShell.SecretStore'

    Initializes a secret vault named 'SecretStore' using the 'Microsoft.PowerShell.SecretStore' module.

    .NOTES
    For more information about secret vaults, see https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules
    #>


    [OutputType([void])]
    [CmdletBinding()]
    param (
        # The name of the secret vault.
        [Parameter()]
        [string] $Name = 'SecretStore',

        # The type of the secret vault.
        [Parameter()]
        [Alias('ModuleName')]
        [string] $Type = 'Microsoft.PowerShell.SecretStore'
    )

    $functionName = $MyInvocation.MyCommand.Name

    $vault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type }
    if (-not $vault) {
        Write-Verbose "[$functionName] - [$Type] - Registering"

        switch ($Type) {
            'Microsoft.PowerShell.SecretStore' {
                $vaultParameters = @{
                    Authentication  = 'None'
                    PasswordTimeout = -1
                    Interaction     = 'None'
                    Scope           = 'CurrentUser'
                    WarningAction   = 'SilentlyContinue'
                    Confirm         = $false
                    Force           = $true
                }
                Reset-SecretStore @vaultParameters
            }
        }
        Write-Verbose "[$functionName] - [$Type] - Done"
    } else {
        Write-Verbose "[$functionName] - [$Type] - already registered"
    }

    $secretStore = Get-SecretVault | Where-Object { $_.Name -eq $Name }
    if (-not $secretStore) {
        Write-Verbose "[$functionName] - [$Name] - Registering"
        $secretVault = @{
            Name         = $Name
            ModuleName   = $Type
            DefaultVault = $true
            Description  = 'SecretStore'
        }
        Register-SecretVault @secretVault
        Write-Verbose "[$functionName] - [$Name] - Done"
    } else {
        Write-Verbose "[$functionName] - [$Name] - already registered"
    }
}

Write-Verbose "[$scriptName] - [private/Config/Initialize-SecretVault.ps1] - Done"
#endregion - From private/Config/Initialize-SecretVault.ps1
#region - From private/Config/Reset-GitHubConfig.ps1
Write-Verbose "[$scriptName] - [private/Config/Reset-GitHubConfig.ps1] - Importing"

function Reset-GitHubConfig {
    <#
        .SYNOPSIS
        Reset the GitHub configuration.

        .DESCRIPTION
        Reset the GitHub configuration. Specific scopes can be reset by using the Scope parameter.

        .EXAMPLE
        Reset-GitHubConfig

        Resets the entire GitHub configuration.

        .EXAMPLE
        Reset-GitHubConfig -Scope 'Auth'

        Resets the Auth related variables of the GitHub configuration.
    #>

    [Alias('Reset-GHConfig')]
    [OutputType([void])]
    [CmdletBinding()]
    param(
        # Reset the GitHub configuration for a specific scope.
        [Parameter()]
        [ValidateSet('Auth', 'All')]
        [string] $Scope = 'All'
    )

    Write-Verbose "Resetting GitHub configuration for scope '$Scope'..."
    switch ($Scope) {
        'Auth' {
            $Settings = @{
                AccessToken                = [securestring]::new()
                AccessTokenExpirationDate  = [datetime]::MinValue
                AccessTokenType            = ''
                AuthType                   = ''
                DeviceFlowType             = ''
                RefreshToken               = [securestring]::new()
                RefreshTokenExpirationDate = [datetime]::MinValue
                Scope                      = ''
            }
        }
        'All' {
            $Settings = @{
                AccessToken                = [securestring]::new()
                AccessTokenExpirationDate  = [datetime]::MinValue
                AccessTokenType            = ''
                ApiBaseUri                 = 'https://api.github.com'
                ApiVersion                 = '2022-11-28'
                AuthType                   = ''
                DeviceFlowType             = ''
                Owner                      = ''
                RefreshToken               = [securestring]::new()
                RefreshTokenExpirationDate = [datetime]::MinValue
                Repo                       = ''
                Scope                      = ''
                UserName                   = ''
            }
        }
    }
    Set-GitHubConfig @Settings
}

Write-Verbose "[$scriptName] - [private/Config/Reset-GitHubConfig.ps1] - Done"
#endregion - From private/Config/Reset-GitHubConfig.ps1

Write-Verbose "[$scriptName] - [private/Config] - Done"
#endregion - From private/Config

#region - From private/Menu
Write-Verbose "[$scriptName] - [private/Menu] - Processing folder"

#region - From private/Menu/Invoke-DrawMenu.ps1
Write-Verbose "[$scriptName] - [private/Menu/Invoke-DrawMenu.ps1] - Importing"

function Invoke-DrawMenu {
    ## supportfunction to the Menu function below
    param (
        $menuItems,
        $menuPosition,
        $menuTitel
    )
    $fcolor = $host.UI.RawUI.ForegroundColor
    $bcolor = $host.UI.RawUI.BackgroundColor
    $l = $menuItems.length + 1
    Clear-Host
    $menuwidth = $menuTitel.length + 4
    Write-Host "`t" -NoNewline
    Write-Host ('*' * $menuwidth) -fore $fcolor -back $bcolor
    Write-Host "`t" -NoNewline
    Write-Host "* $menuTitel *" -fore $fcolor -back $bcolor
    Write-Host "`t" -NoNewline
    Write-Host ('*' * $menuwidth) -fore $fcolor -back $bcolor
    Write-Host ''
    Write-Debug "L: $l MenuItems: $menuItems MenuPosition: $menuposition"
    for ($i = 0; $i -le $l; $i++) {
        Write-Host "`t" -NoNewline
        if ($i -eq $menuPosition) {
            Write-Host "$($menuItems[$i])" -fore $bcolor -back $fcolor
        } else {
            Write-Host "$($menuItems[$i])" -fore $fcolor -back $bcolor
        }
    }
}

Write-Verbose "[$scriptName] - [private/Menu/Invoke-DrawMenu.ps1] - Done"
#endregion - From private/Menu/Invoke-DrawMenu.ps1
#region - From private/Menu/Invoke-Meny.ps1
Write-Verbose "[$scriptName] - [private/Menu/Invoke-Meny.ps1] - Importing"

function Menu {
    ## Generate a small "DOS-like" menu.
    ## Choose a menuitem using up and down arrows, select by pressing ENTER
    param (
        [array]$menuItems,
        $menuTitel = 'MENU'
    )
    $vkeycode = 0
    $pos = 0
    Invoke-DrawMenu $menuItems $pos $menuTitel
    while ($vkeycode -ne 13) {
        $press = $host.ui.rawui.readkey('NoEcho,IncludeKeyDown')
        $vkeycode = $press.virtualkeycode
        Write-Host "$($press.character)" -NoNewline
        if ($vkeycode -eq 38) { $pos-- }
        if ($vkeycode -eq 40) { $pos++ }
        if ($pos -lt 0) { $pos = 0 }
        if ($pos -ge $menuItems.length) { $pos = $menuItems.length - 1 }
        Invoke-DrawMenu $menuItems $pos $menuTitel
    }
    $($menuItems[$pos])
}


<#
? What account do you want to log into? [Use arrows to move, type to filter]
> GitHub.com
  GitHub Enterprise Server
#>


Write-Verbose "[$scriptName] - [private/Menu/Invoke-Meny.ps1] - Done"
#endregion - From private/Menu/Invoke-Meny.ps1

Write-Verbose "[$scriptName] - [private/Menu] - Done"
#endregion - From private/Menu

#region - From private/Organization
Write-Verbose "[$scriptName] - [private/Organization] - Processing folder"

#region - From private/Organization/Blocking
Write-Verbose "[$scriptName] - [private/Organization/Blocking] - Processing folder"

#region - From private/Organization/Blocking/Block-GitHubUserByOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Blocking/Block-GitHubUserByOrganization.ps1] - Importing"

filter Block-GitHubUserByOrganization {
    <#
        .SYNOPSIS
        Block a user from an organization

        .DESCRIPTION
        Blocks the given user on behalf of the specified organization and returns a 204. If the organization cannot block the given user a 422 is returned.

        .EXAMPLE
        Block-GitHubUserByOrganization -OrganizationName 'github' -Username 'octocat'

        Blocks the user 'octocat' from the organization 'github'.
        Returns $true if successful, $false if not.

        .NOTES
        https://docs.github.com/rest/orgs/blocking#block-a-user-from-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName/blocks/$Username"
        Method      = 'PUT'
    }

    try {
        $null = (Invoke-GitHubAPI @inputObject)
        # Should we check if user is already blocked and return true if so?
        return $true
    } catch {
        if ($_.Exception.Response.StatusCode.Value__ -eq 422) {
            return $false
        } else {
            Write-Error $_.Exception.Response
            throw $_
        }
    }
}

Write-Verbose "[$scriptName] - [private/Organization/Blocking/Block-GitHubUserByOrganization.ps1] - Done"
#endregion - From private/Organization/Blocking/Block-GitHubUserByOrganization.ps1
#region - From private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1] - Importing"

filter Get-GitHubBlockedUserByOrganization {
    <#
        .SYNOPSIS
        List users blocked by an organization

        .DESCRIPTION
        List the users blocked by an organization.

        .EXAMPLE
        Get-GitHubBlockedUserByOrganization -OrganizationName 'github'

        Lists all users blocked by the organization `github`.

        .NOTES
        https://docs.github.com/rest/orgs/blocking#list-users-blocked-by-an-organization
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(Mandatory)]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName/blocks"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1] - Done"
#endregion - From private/Organization/Blocking/Get-GitHubBlockedUserByOrganization.ps1
#region - From private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1] - Importing"

filter Test-GitHubBlockedUserByOrganization {
    <#
        .SYNOPSIS
        Check if a user is blocked by an organization

        .DESCRIPTION
        Returns a 204 if the given user is blocked by the given organization. Returns a 404 if the organization is not blocking the user, or if the user account has been identified as spam by GitHub.

        .EXAMPLE
        Test-GitHubBlockedUserByOrganization -OrganizationName 'PSModule' -Username 'octocat'

        Checks if the user `octocat` is blocked by the organization `PSModule`.
        Returns true if the user is blocked, false if not.

        .NOTES
        https://docs.github.com/rest/orgs/blocking#check-if-a-user-is-blocked-by-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName/blocks/$Username"
        Method      = 'GET'
    }

    try {
        (Invoke-GitHubAPI @inputObject).StatusCode -eq 204
    } catch {
        if ($_.Exception.Response.StatusCode.Value__ -eq 404) {
            return $false
        } else {
            throw $_
        }
    }
}

Write-Verbose "[$scriptName] - [private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1] - Done"
#endregion - From private/Organization/Blocking/Test-GitHubBlockedUserByOrganization.ps1
#region - From private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1] - Importing"

filter Unblock-GitHubUserByOrganization {
    <#
        .SYNOPSIS
        Unblock a user from an organization

        .DESCRIPTION
        Unblocks the given user on behalf of the specified organization.

        .EXAMPLE
        Unblock-GitHubUserByOrganization -OrganizationName 'github' -Username 'octocat'

        Unblocks the user 'octocat' from the organization 'github'.
        Returns $true if successful.

        .NOTES
        https://docs.github.com/rest/orgs/blocking#unblock-a-user-from-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/user/blocks/$Username"
        Method      = 'DELETE'
    }

    try {
        $null = (Invoke-GitHubAPI @inputObject)
        return $true
    } catch {
        Write-Error $_.Exception.Response
        throw $_
    }
}

Write-Verbose "[$scriptName] - [private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1] - Done"
#endregion - From private/Organization/Blocking/Unblock-GitHubUserByOrganization.ps1

Write-Verbose "[$scriptName] - [private/Organization/Blocking] - Done"
#endregion - From private/Organization/Blocking

#region - From private/Organization/Get-GitHubAllOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubAllOrganization.ps1] - Importing"

filter Get-GitHubAllOrganization {
    <#
        .SYNOPSIS
        List organizations

        .DESCRIPTION
        Lists all organizations, in the order that they were created on GitHub.

        **Note:** Pagination is powered exclusively by the `since` parameter. Use the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers) to get the URL for the next page of organizations.

        .EXAMPLE
        Get-GitHubAllOrganization -Since 142951047

        List organizations, starting with PSModule

        .NOTES
        https://docs.github.com/rest/orgs/orgs#list-organizations

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # A organization ID. Only return organizations with an ID greater than this ID.
        [Parameter()]
        [int] $Since = 0,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        since    = $Since
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = '/organizations'
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubAllOrganization.ps1] - Done"
#endregion - From private/Organization/Get-GitHubAllOrganization.ps1
#region - From private/Organization/Get-GitHubMyOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubMyOrganization.ps1] - Importing"

filter Get-GitHubMyOrganization {
    <#
        .SYNOPSIS
        List organizations for the authenticated user

        .DESCRIPTION
        List organizations for the authenticated user.

        **OAuth scope requirements**

        This only lists organizations that your authorization allows you to operate on in some way (e.g., you can list teams with `read:org` scope, you can publicize your organization membership with `user` scope, etc.). Therefore, this API requires at least `user` or `read:org` scope. OAuth requests with insufficient scope receive a `403 Forbidden` response.

        .EXAMPLE
        Get-GitHubMyOrganization

        List organizations for the authenticated user.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = '/user/orgs'
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubMyOrganization.ps1] - Done"
#endregion - From private/Organization/Get-GitHubMyOrganization.ps1
#region - From private/Organization/Get-GitHubOrganizationByName.ps1
Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubOrganizationByName.ps1] - Importing"

filter Get-GitHubOrganizationByName {
    <#
        .SYNOPSIS
        Get an organization

        .DESCRIPTION
        To see many of the organization response values, you need to be an authenticated organization owner with the `admin:org` scope. When the value of `two_factor_requirement_enabled` is `true`, the organization requires all members, billing managers, and outside collaborators to enable [two-factor authentication](https://docs.github.com/articles/securing-your-account-with-two-factor-authentication-2fa/).

        GitHub Apps with the `Organization plan` permission can use this endpoint to retrieve information about an organization's GitHub plan. See "[Authenticating with GitHub Apps](https://docs.github.com/apps/building-github-apps/authenticating-with-github-apps/)" for details. For an example response, see 'Response with GitHub plan information' below."

        .EXAMPLE
        Get-GitHubOrganizationByName -OrganizationName 'github'

        Get the 'GitHub' organization

        .NOTES
        https://docs.github.com/rest/orgs/orgs#get-an-organization
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [Alias('org')]
        [Alias('owner')]
        [string] $OrganizationName
    )


    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubOrganizationByName.ps1] - Done"
#endregion - From private/Organization/Get-GitHubOrganizationByName.ps1
#region - From private/Organization/Get-GitHubUserOrganization.ps1
Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubUserOrganization.ps1] - Importing"

filter Get-GitHubUserOrganization {
    <#
        .SYNOPSIS
        List organizations for a user

        .DESCRIPTION
        List [public organization memberships](https://docs.github.com/articles/publicizing-or-concealing-organization-membership) for the specified user.

        This method only lists _public_ memberships, regardless of authentication. If you need to fetch all of the organization memberships (public and private) for the authenticated user, use the [List organizations for the authenticated user](https://docs.github.com/rest/orgs/orgs#list-organizations-for-the-authenticated-user) API instead.

        .EXAMPLE
        Get-GitHubUserOrganization -Username 'octocat'

        List public organizations for the user 'octocat'.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#list-organizations-for-a-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(Mandatory)]
        [string] $Username,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = "/users/$Username/orgs"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Organization/Get-GitHubUserOrganization.ps1] - Done"
#endregion - From private/Organization/Get-GitHubUserOrganization.ps1

Write-Verbose "[$scriptName] - [private/Organization] - Done"
#endregion - From private/Organization

#region - From private/Users
Write-Verbose "[$scriptName] - [private/Users] - Processing folder"

#region - From private/Users/Blocking
Write-Verbose "[$scriptName] - [private/Users/Blocking] - Processing folder"

#region - From private/Users/Blocking/Block-GitHubUserByUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Blocking/Block-GitHubUserByUser.ps1] - Importing"

filter Block-GitHubUserByUser {
    <#
        .SYNOPSIS
        Block a user

        .DESCRIPTION
        Blocks the given user and returns a 204. If the authenticated user cannot block the given user a 422 is returned.

        .EXAMPLE
        Block-GitHubUserByUser -Username 'octocat'

        Blocks the user 'octocat' for the authenticated user.
        Returns $true if successful, $false if not.

        .NOTES
        https://docs.github.com/rest/users/blocking#block-a-user
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/user/blocks/$Username"
        Method      = 'PUT'
    }

    try {
        $null = (Invoke-GitHubAPI @inputObject)
        # Should we check if user is already blocked and return true if so?
        return $true
    } catch {
        if ($_.Exception.Response.StatusCode.Value__ -eq 422) {
            return $false
        } else {
            Write-Error $_.Exception.Response
            throw $_
        }
    }
}

Write-Verbose "[$scriptName] - [private/Users/Blocking/Block-GitHubUserByUser.ps1] - Done"
#endregion - From private/Users/Blocking/Block-GitHubUserByUser.ps1
#region - From private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1] - Importing"

filter Get-GitHubBlockedUserByUser {
    <#
        .SYNOPSIS
        List users blocked by the authenticated user

        .DESCRIPTION
        List the users you've blocked on your personal account.

        .EXAMPLE
        Get-GitHubBlockedUserByUser

        Returns a list of users blocked by the authenticated user.

        .NOTES
        https://docs.github.com/rest/users/blocking#list-users-blocked-by-the-authenticated-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/user/blocks"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1] - Done"
#endregion - From private/Users/Blocking/Get-GitHubBlockedUserByUser.ps1
#region - From private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1] - Importing"

filter Test-GitHubBlockedUserByUser {
    <#
        .SYNOPSIS
        Check if a user is blocked by the authenticated user

        .DESCRIPTION
        Returns a 204 if the given user is blocked by the authenticated user. Returns a 404 if the given user is not blocked by the authenticated user, or if the given user account has been identified as spam by GitHub.

        .EXAMPLE
        Test-GitHubBlockedUserByUser -Username 'octocat'

        Checks if the user `octocat` is blocked by the authenticated user.
        Returns true if the user is blocked, false if not.

        .NOTES
        https://docs.github.com/rest/users/blocking#check-if-a-user-is-blocked-by-the-authenticated-user
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/user/blocks/$Username"
        Method      = 'GET'
        Body        = $body
    }

    try {
        (Invoke-GitHubAPI @inputObject).StatusCode -eq 204
    } catch {
        if ($_.Exception.Response.StatusCode.Value__ -eq 404) {
            return $false
        } else {
            throw $_
        }
    }

}

Write-Verbose "[$scriptName] - [private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1] - Done"
#endregion - From private/Users/Blocking/Test-GitHubBlockedUserByUser.ps1
#region - From private/Users/Blocking/Unblock-GitHubUserByUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Blocking/Unblock-GitHubUserByUser.ps1] - Importing"

filter Unblock-GitHubUserByUser {
    <#
        .SYNOPSIS
        Unblock a user

        .DESCRIPTION
        Unblocks the given user and returns a 204.

        .EXAMPLE
        Unblock-GitHubUserByUser -Username 'octocat'

        Unblocks the user 'octocat' for the authenticated user.
        Returns $true if successful.

        .NOTES
        https://docs.github.com/rest/users/blocking#unblock-a-user
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/user/blocks/$Username"
        Method      = 'DELETE'
    }

    try {
        $null = (Invoke-GitHubAPI @inputObject)
        return $true
    } catch {
        Write-Error $_.Exception.Response
        throw $_
    }
}

Write-Verbose "[$scriptName] - [private/Users/Blocking/Unblock-GitHubUserByUser.ps1] - Done"
#endregion - From private/Users/Blocking/Unblock-GitHubUserByUser.ps1

Write-Verbose "[$scriptName] - [private/Users/Blocking] - Done"
#endregion - From private/Users/Blocking

#region - From private/Users/Social-Accounts
Write-Verbose "[$scriptName] - [private/Users/Social-Accounts] - Processing folder"

#region - From private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1
Write-Verbose "[$scriptName] - [private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1] - Importing"

filter Get-GitHubMyUserSocials {
    <#
        .SYNOPSIS
        List social accounts for the authenticated user

        .DESCRIPTION
        Lists all of your social accounts.

        .EXAMPLE
        Get-GitHubMyUserSocials

        Lists all of your social accounts.

        .NOTES
        https://docs.github.com/rest/users/social-accounts#list-social-accounts-for-the-authenticated-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = '/user/social_accounts'
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1] - Done"
#endregion - From private/Users/Social-Accounts/Get-GitHubMyUserSocials.ps1
#region - From private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1
Write-Verbose "[$scriptName] - [private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1] - Importing"

filter Get-GitHubUserSocialsByName {
    <#
        .SYNOPSIS
        List social accounts for a user

        .DESCRIPTION
        Lists social media accounts for a user. This endpoint is accessible by anyone.

        .EXAMPLE
        Get-GitHubUserSocialsByName -Username 'octocat'

        Lists social media accounts for the user 'octocat'.

        .NOTES
        https://docs.github.com/rest/users/social-accounts#list-social-accounts-for-a-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/users/$Username/social_accounts"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1] - Done"
#endregion - From private/Users/Social-Accounts/Get-GitHubUserSocialsByName.ps1

Write-Verbose "[$scriptName] - [private/Users/Social-Accounts] - Done"
#endregion - From private/Users/Social-Accounts

#region - From private/Users/Get-GitHubAllUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Get-GitHubAllUser.ps1] - Importing"

filter Get-GitHubAllUser {
    <#
        .SYNOPSIS
        List users

        .DESCRIPTION
        Lists all users, in the order that they signed up on GitHub. This list includes personal user accounts and organization accounts.

        Note: Pagination is powered exclusively by the `since` parameter. Use the [Link header](https://docs.github.com/rest/guides/using-pagination-in-the-rest-api#using-link-headers) to get the URL for the next page of users.

        .EXAMPLE
        Get-GitHubAllUser -Since 17722253

        Get a list of users, starting with the user 'MariusStorhaug'.

        .NOTES
        https://docs.github.com/rest/users/users#list-users
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # A user ID. Only return users with an ID greater than this ID.
        [Parameter()]
        [int] $Since = 0,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/users"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Get-GitHubAllUser.ps1] - Done"
#endregion - From private/Users/Get-GitHubAllUser.ps1
#region - From private/Users/Get-GitHubMyUser.ps1
Write-Verbose "[$scriptName] - [private/Users/Get-GitHubMyUser.ps1] - Importing"

filter Get-GitHubMyUser {
    <#
        .SYNOPSIS
        Get the authenticated user

        .DESCRIPTION
        If the authenticated user is authenticated with an OAuth token with the `user` scope, then the response lists public and private profile information.
        If the authenticated user is authenticated through OAuth without the `user` scope, then the response lists only public profile information.

        .EXAMPLE
        Get-GitHubMyUser

        Get the authenticated user

        .NOTES
        https://docs.github.com/rest/users/users#get-the-authenticated-user
    #>

    [OutputType([pscustomobject])]
    [Alias('Get-GitHubContext')]
    [CmdletBinding()]
    param ()

    $inputObject = @{
        APIEndpoint = '/user'
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Get-GitHubMyUser.ps1] - Done"
#endregion - From private/Users/Get-GitHubMyUser.ps1
#region - From private/Users/Get-GitHubUserByName.ps1
Write-Verbose "[$scriptName] - [private/Users/Get-GitHubUserByName.ps1] - Importing"

filter Get-GitHubUserByName {
    <#
        .SYNOPSIS
        Get a user

        .DESCRIPTION
        Provides publicly available information about someone with a GitHub account.
        GitHub Apps with the `Plan` user permission can use this endpoint to retrieve information about a user's GitHub plan. The GitHub App must be authenticated as a user. See "[Identifying and authorizing users for GitHub Apps](https://docs.github.com/apps/building-github-apps/identifying-and-authorizing-users-for-github-apps/)" for details about authentication. For an example response, see 'Response with GitHub plan information' below"
        The `email` key in the following response is the publicly visible email address from your GitHub [profile page](https://github.com/settings/profile). When setting up your profile, you can select a primary email address to be ΓǣpublicΓǥ which provides an email entry for this endpoint. If you do not set a public email address for `email`, then it will have a value of `null`. You only see publicly visible email addresses when authenticated with GitHub. For more information, see [Authentication](https://docs.github.com/rest/overview/resources-in-the-rest-api#authentication).
        The Emails API enables you to list all of your email addresses, and toggle a primary email to be visible publicly. For more information, see "[Emails API](https://docs.github.com/rest/users/emails)".

        .EXAMPLE
        Get-GitHubUserByName -Username 'octocat'

        Get the 'octocat' user.

        .NOTES
        https://docs.github.com/rest/users/users#get-a-user
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username
    )

    $inputObject = @{
        APIEndpoint = "/users/$Username"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [private/Users/Get-GitHubUserByName.ps1] - Done"
#endregion - From private/Users/Get-GitHubUserByName.ps1

Write-Verbose "[$scriptName] - [private/Users] - Done"
#endregion - From private/Users

#region - From private/Utilities
Write-Verbose "[$scriptName] - [private/Utilities] - Processing folder"

#region - From private/Utilities/Casing
Write-Verbose "[$scriptName] - [private/Utilities/Casing] - Processing folder"

#region - From private/Utilities/Casing/Convert-StringCasingStyle.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Casing/Convert-StringCasingStyle.ps1] - Importing"

filter Convert-StringCasingStyle {
    <#
    .SYNOPSIS
    Convert a string to a different casing style

    .DESCRIPTION
    This function converts a string to a different casing style.

    .EXAMPLE
    'thisIsCamelCase' | Convert-StringCasingStyle -To 'snake_case'

    Convert the string 'thisIsCamelCase' to 'this_is_camel_case'

    .EXAMPLE
    'thisIsCamelCase' | Convert-StringCasingStyle -To 'UPPER_SNAKE_CASE'

    Convert the string 'thisIsCamelCase' to 'THIS_IS_CAMEL_CASE'

    .EXAMPLE
    'thisIsCamelCase' | Convert-StringCasingStyle -To 'kebab-case'

    .NOTES
    General notes
    #>

    [OutputType([string])]
    [CmdletBinding()]
    param (
        # The string to convert
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [string] $Text,

        # The casing style to convert the string to
        [Parameter(Mandatory)]
        [ValidateSet(
            'lowercase',
            'UPPERCASE',
            'Title Case',
            'Sentencecase',
            'PascalCase',
            'camelCase',
            'kebab-case',
            'UPPER-KEBAB-CASE',
            'snake_case',
            'UPPER_SNAKE_CASE'
        )]
        [string] $To
    )

    $currentStyle = Get-StringCasingStyle -Text $Text

    $words = Split-StringByCasingStyle -Text $Text -By $currentStyle

    # Convert the words into the target style
    switch ($To) {
        'lowercase' { ($words -join '').toLower() }
        'UPPERCASE' { ($words -join '').toUpper() }
        'Title Case' { ($words | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1).ToLower() }) -join ' ' }
        'Sentencecase' { $words -join '' | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1).ToLower() } }
        'kebab-case' { ($words -join '-').ToLower() }
        'snake_case' { ($words -join '_').ToLower() }
        'PascalCase' { ($words | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1).ToLower() }) -join '' }
        'camelCase' { $words[0].toLower() + (($words | Select-Object -Skip 1 | ForEach-Object { $_.Substring(0, 1).ToUpper() + $_.Substring(1) }) -join '') }
        'UPPER_SNAKE_CASE' { ($words -join '_').toUpper() }
        'UPPER-KEBAB-CASE' { ($words -join '-').toUpper() }
    }
}

Write-Verbose "[$scriptName] - [private/Utilities/Casing/Convert-StringCasingStyle.ps1] - Done"
#endregion - From private/Utilities/Casing/Convert-StringCasingStyle.ps1
#region - From private/Utilities/Casing/Get-StringCasingStyle.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Casing/Get-StringCasingStyle.ps1] - Importing"

filter Get-StringCasingStyle {
    <#
        .SYNOPSIS
        Detects the casing style of a string

        .DESCRIPTION
        This function detects the casing style of a string.

        .EXAMPLE
        'testtesttest' | Get-StringCasingStyle

        lowercase

        .EXAMPLE
        'TESTTESTTEST' | Get-StringCasingStyle

        UPPERCASE

        .EXAMPLE
        'Testtesttest' | Get-StringCasingStyle

        Sentencecase

        .EXAMPLE
        'TestTestTest' | Get-StringCasingStyle

        PascalCase

        .EXAMPLE
        'testTestTest' | Get-StringCasingStyle

        camelCase

        .EXAMPLE
        'test-test-test' | Get-StringCasingStyle

        kebab-case

        .EXAMPLE
        'TEST-TEST-TEST' | Get-StringCasingStyle

        UPPER-KEBAB-CASE

        .EXAMPLE
        'test_test_test' | Get-StringCasingStyle

        snake_case

        .EXAMPLE
        'TEST_TEST_TEST' | Get-StringCasingStyle

        UPPER_SNAKE_CASE

        .EXAMPLE
        'Test_teSt-Test' | Get-StringCasingStyle

        Unknown
    #>

    [OutputType([string])]
    [CmdletBinding()]
    param (
        # The string to check the casing style of
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [ValidateNotNullOrEmpty()]
        [string] $Text
    )

    $style = if ([regex]::Match($Text, '^[a-z][a-z0-9]*$').Success) {
        'lowercase'
    } elseif ([regex]::Match($Text, '^[A-Z][A-Z0-9]*$').Success) {
        'UPPERCASE'
    } elseif ([regex]::Match($Text, '^[A-Z][a-z0-9]*$').Success) {
        'Sentencecase'
    } elseif ([regex]::Match($Text, '^([A-Z][a-z]*)(\s+[A-Z][a-z]*)+$').Success) {
        'Title Case'
    } elseif ([regex]::Match($Text, '^[A-Z][a-z0-9]*([A-Z][a-z0-9]*)+$').Success) {
        'PascalCase'
    } elseif ([regex]::Match($Text, '^[a-z][a-z0-9]*([A-Z][a-z0-9]*)+$').Success) {
        'camelCase'
    } elseif ([regex]::Match($Text, '^[a-z][a-z0-9]*(-[a-z0-9]+)+$').Success) {
        'kebab-case'
    } elseif ([regex]::Match($Text, '^[A-Z][A-Z0-9]*(-[A-Z0-9]+)+$').Success) {
        'UPPER-KEBAB-CASE'
    } elseif ([regex]::Match($Text, '^[a-z][a-z0-9]*(_[a-z0-9]+)+$').Success) {
        'snake_case'
    } elseif ([regex]::Match($Text, '^[A-Z][A-Z0-9]*(_[A-Z0-9]+)+$').Success) {
        'UPPER_SNAKE_CASE'
    } else {
        'Unknown'
    }

    Write-Verbose "Detected casing style: [$style]"
    $style

}

Write-Verbose "[$scriptName] - [private/Utilities/Casing/Get-StringCasingStyle.ps1] - Done"
#endregion - From private/Utilities/Casing/Get-StringCasingStyle.ps1
#region - From private/Utilities/Casing/Split-StringByCasingStyle.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Casing/Split-StringByCasingStyle.ps1] - Importing"

filter Split-StringByCasingStyle {
    <#
        .SYNOPSIS
        Splits a kebab-case string into an array of words

        .DESCRIPTION
        This function splits a kebab-case string into an array of words.

        .EXAMPLE
        Split-StringByCasingStyle -Text 'this-is-a-kebab-case-string' -By kebab-case

        this
        is
        a
        kebab
        case
        string

        .EXAMPLE
        Split-StringByCasingStyle -Text 'this_is_a_kebab_case_string' -By 'snake_case'

        this
        is
        a
        kebab
        case
        string

        .EXAMPLE
        Split-StringByCasingStyle -Text 'ThisIsAPascalCaseString' -By 'PascalCase'

        This
        Is
        A
        Pascal
        Case
        String

        .EXAMPLE
        Split-StringByCasingStyle -Text 'thisIsACamelCaseString' -By 'camelCase'

        this
        Is
        A
        Camel
        Case
        String

        .EXAMPLE
        Split-StringByCasingStyle -Text 'this_is_a-CamelCaseString' -By kebab-case | Split-StringByCasingStyle -By snake_case

        this_is_a
        camelcasestring


    #>

    [OutputType([string[]])]
    [CmdletBinding()]
    param (
        # The string to split
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [string] $Text,

        # The casing style to split the string by
        [Parameter()]
        [ValidateSet(
            'lowercase',
            'UPPERCASE',
            'Sentencecase',
            'Title Case',
            'PascalCase',
            'camelCase',
            'kebab-case',
            'UPPER-KEBAB-CASE',
            'snake_case',
            'UPPER_SNAKE_CASE'
        )]
        [string] $By
    )

    $styles = $PSBoundParameters | Where-Object { $_.Value -eq $true } | Select-Object -ExpandProperty Name

    Write-Verbose "Splitting string [$Text] by casing style [$($styles -join ', ' )]"
    $splitText = switch ($By) {
        'PascalCase' { [regex]::Matches($Text, '([A-Z][a-z]*)').Value; break }
        'camelCase' { [regex]::Matches($Text, '([A-Z][a-z]*)|^[a-z]+').Value; break }
        'kebab-case' { $Text -split '-'; break }
        'UPPER-KEBAB-CASE' { $Text -split '-'; break }
        'snake_case' { $Text -split '_'; break }
        'UPPER_SNAKE_CASE' { $Text -split '_'; break }
        default {
            $Text -split ' '
        }
    }

    Write-Verbose "Result: [$($splitText -join ', ')]"
    $splitText
}

Write-Verbose "[$scriptName] - [private/Utilities/Casing/Split-StringByCasingStyle.ps1] - Done"
#endregion - From private/Utilities/Casing/Split-StringByCasingStyle.ps1

Write-Verbose "[$scriptName] - [private/Utilities/Casing] - Done"
#endregion - From private/Utilities/Casing

#region - From private/Utilities/Hashtable
Write-Verbose "[$scriptName] - [private/Utilities/Hashtable] - Processing folder"

#region - From private/Utilities/Hashtable/ConvertFrom-HashTable.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/ConvertFrom-HashTable.ps1] - Importing"

filter ConvertFrom-HashTable {
    <#
        .SYNOPSIS
        Converts a hashtable to a pscustomobject

        .DESCRIPTION
        This function converts a hashtable to a pscustomobject.

        .EXAMPLE
        $object = @{a = 1;b = 2;c = 3}
        $object | ConvertFrom-HashTable | Format-Table

        a b c
        - - -
        1 2 3

        Converts the hashtable to a pscustomobject and displays it in a table.

        .EXAMPLE
        $object = @{a = 1;b = 2;c = 3}
        $object | ConvertFrom-Dictionary | ConvertTo-Json

        {
            "a": 1,
            "b": 2,
            "c": 3
        }

        Converts the hashtable to a pscustomobject and then to JSON.
        Using the alias 'ConvertFrom-Dictionary' instead of 'ConvertFrom-HashTable'.
    #>

    [OutputType([pscustomobject])]
    [Alias('ConvertFrom-Dictionary')]
    [CmdletBinding()]
    param (
        # The hashtable to be converted. The input takes any type of dictionary. The original dictionary is not modified.
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [object]$InputObject
    )
    $InputObject | ConvertTo-Json -Depth 100 | ConvertFrom-Json
}

Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/ConvertFrom-HashTable.ps1] - Done"
#endregion - From private/Utilities/Hashtable/ConvertFrom-HashTable.ps1
#region - From private/Utilities/Hashtable/ConvertTo-HashTable.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/ConvertTo-HashTable.ps1] - Importing"

filter ConvertTo-HashTable {
    <#
        .SYNOPSIS
        Converts an object to a hashtable

        .DESCRIPTION
        This function converts an object to a hashtable.

        .EXAMPLE
        $object = [pscustomobject]@{a = 1;b = 2;c = 3}
        $object | ConvertTo-HashTable | Format-Table

        Name Value
        ---- -----
        a 1
        b 2
        c 3

        Converts the object to a hashtable and displays it in a table.

        .EXAMPLE
        $object = [pscustomobject]@{a = 1;b = 2;c = 3}
        $object | ConvertTo-Dictionary | ConvertTo-Json

        {
            "a": 1,
            "b": 2,
            "c": 3
        }

        Converts the object to a hashtable and then to JSON.
        Using the alias 'ConvertTo-Dictionary' instead of 'ConvertTo-HashTable'.
    #>

    [OutputType([hashtable])]
    [Alias('ConvertTo-Dictionary')]
    [CmdletBinding()]
    param (
        # The object to be converted. The input takes any type of object. The original object is not modified.
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [object]$InputObject,

        # The casing style of the hashtable keys.
        [Parameter()]
        [ValidateSet(
            'lowercase',
            'UPPERCASE',
            'Title Case',
            'PascalCase',
            'camelCase',
            'kebab-case',
            'UPPER-KEBAB-CASE',
            'snake_case',
            'UPPER_SNAKE_CASE'
        )]
        [string]$NameCasingStyle
    )
    [hashtable]$hashtable = @{}

    foreach ($item in $InputObject.PSObject.Properties) {
        $name = $NameCasingStyle ? ($item.Name | Convert-StringCasingStyle -To $NameCasingStyle) : $item.Name
        $hashtable[$name] = $item.Value
    }
    $hashtable
}

Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/ConvertTo-HashTable.ps1] - Done"
#endregion - From private/Utilities/Hashtable/ConvertTo-HashTable.ps1
#region - From private/Utilities/Hashtable/Join-Object.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/Join-Object.ps1] - Importing"

filter Join-Object {
    <#
        .SYNOPSIS
        Merges two or more objects into a single object

        .DESCRIPTION
        Merges two or more objects into a single object. The first object is the main object, and the remaining objects are overrides. The overrides are applied in order, so the last object in the list will override any previous values.

        .EXAMPLE
        $main = [pscustomobject]@{a = 1; b = 2; c = 3}
        $overrides = [pscustomobject]@{a = 4; b = 5; d = 6}
        $overrides2 = [pscustomobject]@{a = 7; b = 8; e = 9}
        Join-Object -Main $main -Overrides $overrides, $overrides2

        a b c d e
        - - - - -
        7 8 3 6 9

        Merges the three objects into a single object. The values from the last object override the values from the previous objects.

        .EXAMPLE
        $main = @{a = 1;b = 2}
        $overrides = @{a = 3;c = 4}
        Merge-Object -Main $main -Overrides $overrides -AsHashtable

        Name Value
        ---- -----
        a 3
        b 2
        c 4

        Merges the two hashtables into a single hashtable. The values from the last hashtable override the values from the previous hashtables.
        Using the alias 'Merge-Object' instead of 'Join-Object'.

        .EXAMPLE
        $main = @{a = 1;b = 1;c = 1}
        $overrides = @{b = 2;d = 2}
        $overrides2 = @{c = 3;e = 3}
        $main | Join-Object -Overrides $overrides, $overrides2 | Format-Table

        a b c d e
        - - - - -
        1 2 3 2 3

        Merges the three hashtables into a single hashtable. The values from the last hashtable override the values from the previous hashtables.
        Using the pipeline to pass the main object instead of the -Main parameter.
    #>

    [OutputType([pscustomobject])]
    [OutputType(ParameterSetName = 'AsHashTable', [hashtable])]
    [Alias('Merge-Object')]
    [CmdletBinding(DefaultParameterSetName = '__DefaultSet')]
    param (
        # The main object to merge into. This object will be cloned, so the original object will not be modified.
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [object] $Main,

        # The objects to merge into the main object
        [Parameter(Mandatory)]
        [object[]] $Overrides,

        # Return the result as a hashtable instead of a pscustomobject
        [Parameter(
            Mandatory,
            ParameterSetName = 'AsHashTable'
        )]
        [switch] $AsHashtable
    )

    if ($Main -isnot [hashtable]) {
        $Main = $Main | ConvertTo-HashTable
    }
    $hashtable = $Main.clone()

    foreach ($Override in $Overrides) {
        if ($Override -isnot [hashtable]) {
            $Override = $Override | ConvertTo-HashTable
        }

        $Override.Keys | ForEach-Object {
            $hashtable[$_] = $Override[$_]
        }
    }

    if ($AsHashtable) {
        return $hashtable
    }

    $hashtable | ConvertFrom-HashTable
}

Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/Join-Object.ps1] - Done"
#endregion - From private/Utilities/Hashtable/Join-Object.ps1
#region - From private/Utilities/Hashtable/Remove-HashTableEntries.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/Remove-HashTableEntries.ps1] - Importing"

filter Remove-HashtableEntries {
    [OutputType([void])]
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [hashtable] $Hashtable,

        [Parameter()]
        [switch] $NullOrEmptyValues,

        [Parameter()]
        [string[]] $RemoveTypes,

        [Parameter()]
        [string[]] $RemoveNames,

        [Parameter()]
        [string[]] $KeepTypes,

        [Parameter()]
        [string[]] $KeepNames

    )
    if ($NullOrEmptyValues) {
        Write-Verbose 'Remove keys with null or empty values'
        ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object {
            Write-Verbose " - [$($_.Name)] - Value: [$($_.Value)] - Remove"
            $Hashtable.Remove($_.Name)
        }
    }
    if ($RemoveTypes) {
        Write-Verbose "Remove keys of type: [$RemoveTypes]"
        ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -in $RemoveTypes) }) | ForEach-Object {
            Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove"
            $Hashtable.Remove($_.Name)
        }
    }
    if ($KeepTypes) {
        Write-Verbose "Remove keys NOT of type: [$KeepTypes]"
        ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -notin $KeepTypes) }) | ForEach-Object {
            Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove"
            $Hashtable.Remove($_.Name)
        }
    }
    if ($RemoveNames) {
        Write-Verbose "Remove keys named: [$RemoveNames]"
        ($Hashtable.GetEnumerator() | Where-Object { $_.Name -in $RemoveNames }) | ForEach-Object {
            Write-Verbose " - [$($_.Name)] - Remove"
            $Hashtable.Remove($_.Name)
        }
    }
    if ($KeepNames) {
        Write-Verbose "Remove keys NOT named: [$KeepNames]"
        ($Hashtable.GetEnumerator() | Where-Object { $_.Name -notin $KeepNames }) | ForEach-Object {
            Write-Verbose " - [$($_.Name)] - Remove"
            $Hashtable.Remove($_.Name)
        }
    }
}

Write-Verbose "[$scriptName] - [private/Utilities/Hashtable/Remove-HashTableEntries.ps1] - Done"
#endregion - From private/Utilities/Hashtable/Remove-HashTableEntries.ps1

Write-Verbose "[$scriptName] - [private/Utilities/Hashtable] - Done"
#endregion - From private/Utilities/Hashtable

#region - From private/Utilities/Web
Write-Verbose "[$scriptName] - [private/Utilities/Web] - Processing folder"

#region - From private/Utilities/Web/ConvertTo-QueryString.ps1
Write-Verbose "[$scriptName] - [private/Utilities/Web/ConvertTo-QueryString.ps1] - Importing"

filter ConvertTo-QueryString {
    <#
        .SYNOPSIS
        Convert an object to a query string

        .DESCRIPTION
        Convert an object to a query string

        .EXAMPLE
        ConvertTo-QueryString -InputObject @{a=1;b=2}

        ?a=1&b=2

        .EXAMPLE
        ConvertTo-QueryString -InputObject @{a='this is value of a';b='valueOfB'}

        ?a=this%20is%20value%20of%20a&b=valueOfB

        .EXAMPLE
        ConvertTo-QueryString -InputObject @{a='this is value of a';b='valueOfB'} -AsURLEncoded

        ?a=this+is+value+of+a&b=valueOfB
    #>

    [OutputType([string])]
    [CmdletBinding()]
    param(
        [Parameter(
            Mandatory,
            ValueFromPipeline
        )]
        [object] $InputObject,

        [Parameter()]
        [switch] $AsURLEncoded
    )

    if ($InputObject -isnot [hashtable]) {
        $InputObject = $InputObject | ConvertTo-HashTable
    }

    $parameters = if ($AsURLEncoded) {
        ($InputObject.GetEnumerator() | ForEach-Object { "$([System.Web.HttpUtility]::UrlEncode($_.Key))=$([System.Web.HttpUtility]::UrlEncode($_.Value))" }) -join '&'
    } else {
        ($InputObject.GetEnumerator() | ForEach-Object { "$([System.Uri]::EscapeDataString($_.Key))=$([System.Uri]::EscapeDataString($_.Value))" }) -join '&'
    }

    if ($parameters) {
        '?' + $parameters
    }
}

Write-Verbose "[$scriptName] - [private/Utilities/Web/ConvertTo-QueryString.ps1] - Done"
#endregion - From private/Utilities/Web/ConvertTo-QueryString.ps1

Write-Verbose "[$scriptName] - [private/Utilities/Web] - Done"
#endregion - From private/Utilities/Web


Write-Verbose "[$scriptName] - [private/Utilities] - Done"
#endregion - From private/Utilities


Write-Verbose "[$scriptName] - [private] - Done"
#endregion - From private

#region - From public
Write-Verbose "[$scriptName] - [public] - Processing folder"

#region - From public/Actions
Write-Verbose "[$scriptName] - [public/Actions] - Processing folder"

#region - From public/Actions/Disable-GitHubWorkflow.ps1
Write-Verbose "[$scriptName] - [public/Actions/Disable-GitHubWorkflow.ps1] - Importing"

filter Disable-GitHubWorkflow {
    <#
        .NOTES
        https://docs.github.com/rest/reference/actions#disable-a-workflow
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/disable"
        Method      = 'PUT'
    }

    Invoke-GitHubAPI @inputObject | Out-Null

}

Write-Verbose "[$scriptName] - [public/Actions/Disable-GitHubWorkflow.ps1] - Done"
#endregion - From public/Actions/Disable-GitHubWorkflow.ps1
#region - From public/Actions/Enable-GitHubWorkflow.ps1
Write-Verbose "[$scriptName] - [public/Actions/Enable-GitHubWorkflow.ps1] - Importing"

filter Enable-GitHubWorkflow {
    <#
        .NOTES
        https://docs.github.com/rest/reference/actions#enable-a-workflow
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/enable"
        Method      = 'PUT'
    }

    Invoke-GitHubAPI @inputObject | Out-Null

}

Write-Verbose "[$scriptName] - [public/Actions/Enable-GitHubWorkflow.ps1] - Done"
#endregion - From public/Actions/Enable-GitHubWorkflow.ps1
#region - From public/Actions/Get-GitHubWorkflow.ps1
Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflow.ps1] - Importing"

filter Get-GitHubWorkflow {
    <#
        .SYNOPSIS
        Lists the workflows in a repository.

        .DESCRIPTION
        Anyone with read access to the repository can use this endpoint.
        If the repository is private you must use an access token with the repo scope.
        GitHub Apps must have the actions:read permission to use this endpoint.

        .EXAMPLE
        Get-GitHubWorkflow -Owner 'octocat' -Repo 'hello-world'

        Gets all workflows in the 'octocat/hello-world' repository.

        .EXAMPLE
        Get-GitHubWorkflow -Owner 'octocat' -Repo 'hello-world' -Name 'hello-world.yml'

        Gets the 'hello-world.yml' workflow in the 'octocat/hello-world' repository.

        .NOTES
        https://docs.github.com/rest/actions/workflows?apiVersion=2022-11-28#list-repository-workflows
    #>

    [CmdletBinding(DefaultParameterSetName = 'ByName')]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(ParameterSetName = 'ByName')]
        [string] $Name,

        [Parameter(ParameterSetName = 'ByID')]
        [string] $ID,

        [Parameter()]
        [int] $PerPage = 30
    )


    $body = @{
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/actions/workflows"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response.workflows

}

Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflow.ps1] - Done"
#endregion - From public/Actions/Get-GitHubWorkflow.ps1
#region - From public/Actions/Get-GitHubWorkflowRun.ps1
Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowRun.ps1] - Importing"

filter Get-GitHubWorkflowRun {
    <#
        .NOTES
        https://docs.github.com/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-workflow
        https://docs.github.com/rest/actions/workflow-runs?apiVersion=2022-11-28#list-workflow-runs-for-a-repository
    #>

    [CmdletBinding(DefaultParameterSetName = 'Repo')]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(ParameterSetName = 'ByName')]
        [string] $Name,

        [Parameter(ParameterSetName = 'ByID')]
        [string] $ID,

        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        per_page = $PerPage
    }

    if ($Name) {
        $ID = (Get-GitHubWorkflow -Owner $Owner -Repo $Repo -Name $Name).id
    }

    if ($ID) {
        $Uri = "/repos/$Owner/$Repo/actions/workflows/$ID/runs"
    } else {
        $Uri = "/repos/$Owner/$Repo/actions/runs"
    }

    $inputObject = @{
        APIEndpoint = $Uri
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response.workflow_runs

}

Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowRun.ps1] - Done"
#endregion - From public/Actions/Get-GitHubWorkflowRun.ps1
#region - From public/Actions/Get-GitHubWorkflowUsage.ps1
Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowUsage.ps1] - Importing"

filter Get-GitHubWorkflowUsage {
    <#
        .SYNOPSIS
        Short description

        .DESCRIPTION
        Long description

        .PARAMETER Owner
        Parameter description

        .PARAMETER Repo
        Parameter description

        .PARAMETER ID
        Parameter description

        .EXAMPLE
        An example

        .NOTES
        https://docs.github.com/rest/reference/actions#get-workflow-usage
    #>

    [CmdletBinding(
        DefaultParameterSetName = 'ByName'
    )]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $ID
    )

    $inputObject = @{
        Method      = 'GET'
        APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/timing"
    }

    (Invoke-GitHubAPI @inputObject).Response.billable

}

Write-Verbose "[$scriptName] - [public/Actions/Get-GitHubWorkflowUsage.ps1] - Done"
#endregion - From public/Actions/Get-GitHubWorkflowUsage.ps1
#region - From public/Actions/Remove-GitHubWorkflowRun.ps1
Write-Verbose "[$scriptName] - [public/Actions/Remove-GitHubWorkflowRun.ps1] - Importing"

filter Remove-GitHubWorkflowRun {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )

    $inputObject = @{
        APIEndpoint = "repos/$Owner/$Repo/actions/runs/$ID"
        Method      = 'DELETE'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Actions/Remove-GitHubWorkflowRun.ps1] - Done"
#endregion - From public/Actions/Remove-GitHubWorkflowRun.ps1
#region - From public/Actions/Start-GitHubWorkflow.ps1
Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflow.ps1] - Importing"

filter Start-GitHubWorkflow {
    <#
        .SYNOPSIS
        Start a workflow run using the workflow's ID.

        .DESCRIPTION
        Start a workflow run using the workflow's ID.

        .EXAMPLE
        Get-GitHubWorkflow | Where-Object name -NotLike '.*' | Start-GitHubWorkflow -Inputs @{
            staticValidation = $true
            deploymentValidation = $false
            removeDeployment = $true
            prerelease = $false
        }

        .NOTES
        # API Reference
        # https://docs.github.com/free-pro-team@latest/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID,

        [Parameter(
            ValueFromPipelineByPropertyName
        )]
        [Alias('branch', 'tag')]
        [string] $Ref = 'main',

        [Parameter()]
        [hashtable] $Inputs = @{}
    )

    $body = @{
        ref    = $Ref
        inputs = $Inputs
    }

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/actions/workflows/$ID/dispatches"
        Method      = 'POST'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflow.ps1] - Done"
#endregion - From public/Actions/Start-GitHubWorkflow.ps1
#region - From public/Actions/Start-GitHubWorkflowReRun.ps1
Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflowReRun.ps1] - Importing"

filter Start-GitHubWorkflowReRun {
    <#
        .SYNOPSIS
        Short description

        .DESCRIPTION
        Long description

        .PARAMETER Owner
        Parameter description

        .PARAMETER Repo
        Parameter description

        .PARAMETER ID
        Parameter description

        .EXAMPLE
        An example

        .NOTES
        https://docs.github.com/rest/reference/actions#re-run-a-workflow
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )

    $inputObject = @{
        Method      = 'POST'
        APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/rerun"
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Actions/Start-GitHubWorkflowReRun.ps1] - Done"
#endregion - From public/Actions/Start-GitHubWorkflowReRun.ps1
#region - From public/Actions/Stop-GitHubWorkflowRun.ps1
Write-Verbose "[$scriptName] - [public/Actions/Stop-GitHubWorkflowRun.ps1] - Importing"

filter Stop-GitHubWorkflowRun {
    <#
        .SYNOPSIS
        Short description

        .DESCRIPTION
        Long description

        .PARAMETER Owner
        Parameter description

        .PARAMETER Repo
        Parameter description

        .PARAMETER ID
        Parameter description

        .EXAMPLE
        An example

        .NOTES
        https://docs.github.com/rest/reference/actions#cancel-a-workflow-run
    #>

    [CmdletBinding()]
    [alias('Cancel-GitHubWorkflowRun')]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Alias('workflow_id')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $ID
    )


    $inputObject = @{
        Method      = 'POST'
        APIEndpoint = "/repos/$Owner/$Repo/actions/runs/$ID/cancel"
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Actions/Stop-GitHubWorkflowRun.ps1] - Done"
#endregion - From public/Actions/Stop-GitHubWorkflowRun.ps1

Write-Verbose "[$scriptName] - [public/Actions] - Done"
#endregion - From public/Actions

#region - From public/API
Write-Verbose "[$scriptName] - [public/API] - Processing folder"

#region - From public/API/Invoke-GitHubAPI.ps1
Write-Verbose "[$scriptName] - [public/API/Invoke-GitHubAPI.ps1] - Importing"

filter Invoke-GitHubAPI {
    <#
        .SYNOPSIS
        Calls the GitHub API using the provided parameters.

        .DESCRIPTION
        This function is a wrapper around Invoke-RestMethod tailored for calling GitHub's API.
        It automatically handles the endpoint URI construction, headers, and token authentication.

        .EXAMPLE
        Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET

        Gets all open pull requests for the specified repository.

        .EXAMPLE
        Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' }

        Gets all open pull requests for the specified repository, filtered by the 'state' parameter.

        .EXAMPLE
        Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } -Accept 'application/vnd.github.v3+json'

        Gets all open pull requests for the specified repository, filtered by the 'state' parameter, and using the specified 'Accept' header.
    #>

    [CmdletBinding()]
    param (
        # The HTTP method to be used for the API request. It can be one of the following: GET, POST, PUT, DELETE, or PATCH.
        [Parameter()]
        [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'GET',

        # The base URI for the GitHub API. This is usually 'https://api.github.com', but can be adjusted if necessary.
        [Parameter()]
        [string] $ApiBaseUri = (Get-GitHubConfig -Name ApiBaseUri),

        # The specific endpoint for the API call, e.g., '/repos/user/repo/pulls'.
        [Parameter(Mandatory)]
        [string] $ApiEndpoint,

        # The body of the API request. This can be a hashtable or a string. If a hashtable is provided, it will be converted to JSON.
        [Parameter()]
        [Object] $Body,

        # The 'Accept' header for the API request. If not provided, the default will be used by GitHub's API.
        [Parameter()]
        [string] $Accept = 'application/vnd.github+json; charset=utf-8',

        # Specifies the HTTP version used for the request.
        [Parameter()]
        [version] $HttpVersion = '2.0',

        # Support Pagination Relation Links per RFC5988.
        [Parameter()]
        [bool] $FollowRelLink = $true,

        # The secure token used for authentication in the GitHub API. It should be stored as a SecureString to ensure it's kept safe in memory.
        [Parameter()]
        [SecureString] $AccessToken = (Get-GitHubConfig -Name AccessToken),

        # The 'Content-Type' header for the API request. The default is 'application/vnd.github+json'.
        [Parameter()]
        [string] $ContentType = 'application/vnd.github+json; charset=utf-8',

        # The GitHub API version to be used. By default, it pulls from a configuration script variable.
        [Parameter()]
        [string] $Version = (Get-GitHubConfig -Name ApiVersion)
    )

    if (Test-GitHubAccessTokenRefreshRequired) {
        Connect-GitHubAccount -Silent
        $AccessToken = (Get-GitHubConfig -Name AccessToken)
    }

    $functionName = $MyInvocation.MyCommand.Name

    $headers = @{
        Accept                 = $Accept
        'X-GitHub-Api-Version' = $Version
    }

    Remove-HashTableEntries -Hashtable $headers -NullOrEmptyValues

    $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '')

    # $AccessTokenAsPlainText = ConvertFrom-SecureString $AccessToken -AsPlainText
    # # Swap out this by using the -Authentication Bearer -Token $AccessToken
    # switch -Regex ($AccessTokenAsPlainText) {
    # '^ghp_|^github_pat_' {
    # $headers.authorization = "token $AccessTokenAsPlainText"
    # }
    # '^ghu_|^gho_' {
    # $headers.authorization = "Bearer $AccessTokenAsPlainText"
    # }
    # default {
    # $tokenPrefix = $AccessTokenAsPlainText -replace '_.*$', '_*'
    # $errorMessage = "Unexpected AccessToken format: $tokenPrefix"
    # Write-Error $errorMessage
    # throw $errorMessage
    # }
    # }

    $APICall = @{
        Uri                     = $URI
        Method                  = $Method
        Headers                 = $Headers
        Authentication          = 'Bearer'
        Token                   = $AccessToken
        ContentType             = $ContentType
        HttpVersion             = $HttpVersion
        FollowRelLink           = $FollowRelLink
        StatusCodeVariable      = 'APICallStatusCode'
        ResponseHeadersVariable = 'APICallResponseHeaders'
    }

    $APICall | Remove-HashTableEntries -NullOrEmptyValues

    if ($Body) {

        # Use body to create the query string for GET requests
        if ($Method -eq 'GET') {
            $queryString = $Body | ConvertTo-QueryString
            $APICall.Uri = $APICall.Uri + $queryString
        }

        # Use body to create the form data
        if ($Body -is [string]) {
            $APICall.Body = $Body
        } else {
            $APICall.Body = $Body | ConvertTo-Json -Depth 100
        }
    }

    Invoke-RestMethod @APICall | ForEach-Object {
        $statusCode = $APICallStatusCode | ConvertTo-Json -Depth 100 | ConvertFrom-Json
        $responseHeaders = $APICallResponseHeaders | ConvertTo-Json -Depth 100 | ConvertFrom-Json
        [pscustomobject]@{
            Request         = $APICall
            Response        = $_
            StatusCode      = $statusCode
            ResponseHeaders = $responseHeaders
        }
    }
}

Write-Verbose "[$scriptName] - [public/API/Invoke-GitHubAPI.ps1] - Done"
#endregion - From public/API/Invoke-GitHubAPI.ps1

Write-Verbose "[$scriptName] - [public/API] - Done"
#endregion - From public/API

#region - From public/Auth
Write-Verbose "[$scriptName] - [public/Auth] - Processing folder"

#region - From public/Auth/Connect-GitHubAccount.ps1
Write-Verbose "[$scriptName] - [public/Auth/Connect-GitHubAccount.ps1] - Importing"

function Connect-GitHubAccount {
    <#
        .SYNOPSIS
        Connects to GitHub using a personal access token or device code login.

        .DESCRIPTION
        Connects to GitHub using a personal access token or device code login.

        For device flow / device code login:
        PowerShell requests device and user verification codes and gets the authorization URL where you will enter the user verification code.
        In GitHub you will be asked to enter a user verification code at https://github.com/login/device.
        PowerShell will keep polling GitHub for the user authentication status. Once you have authorized the device,
        the app will be able to make API calls with a new access token.

        .EXAMPLE
        Connect-GitHubAccount

        Connects to GitHub using a device flow login.
        If the user has already logged in, the access token will be refreshed.

        .EXAMPLE
        Connect-GitHubAccount -AccessToken
        ! Enter your personal access token: *************

        User gets prompted for the access token and stores it in the secret store.
        The token is used when connecting to GitHub.

        .EXAMPLE
        Connect-GitHubAccount -Mode 'OAuthApp' -Scope 'gist read:org repo workflow'

        Connects to GitHub using a device flow login and sets the scope of the access token.

        .NOTES
        https://docs.github.com/rest/overview/other-authentication-methods#authenticating-for-saml-sso
    #>

    [Alias('Connect-GHAccount')]
    [Alias('Connect-GitHub')]
    [Alias('Connect-GH')]
    [Alias('Login-GitHubAccount')]
    [Alias('Login-GHAccount')]
    [Alias('Login-GitHub')]
    [Alias('Login-GH')]
    [OutputType([void])]
    [CmdletBinding(DefaultParameterSetName = 'DeviceFlow')]
    param (
        # Choose between authentication methods, either OAuthApp or GitHubApp.
        # For more info about the types of authentication visit:
        # https://docs.github.com/apps/oauth-apps/building-oauth-apps/differences-between-github-apps-and-oauth-apps
        [Parameter(ParameterSetName = 'DeviceFlow')]
        [ValidateSet('OAuthApp', 'GitHubApp')]
        [string] $Mode = 'GitHubApp',

        # The scope of the access token, when using OAuth authentication.
        # Provide the list of scopes as space-separated values.
        # For more information on scopes visit:
        # https://docs.github.com/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
        [Parameter(ParameterSetName = 'DeviceFlow')]
        [string] $Scope = 'gist read:org repo workflow',

        # The personal access token to use for authentication.
        [Parameter(
            Mandatory,
            ParameterSetName = 'PAT'
        )]
        [Alias('Token')]
        [Alias('PAT')]
        [switch] $AccessToken,

        # Set the default owner to use in commands.
        [Parameter()]
        [Alias('Organization')]
        [Alias('Org')]
        [string] $Owner,

        # Set the default repository to use in commands.
        [Parameter()]
        [Alias('Repository')]
        [string] $Repo,

        # Suppresses the output of the function.
        [Parameter()]
        [Alias('Quiet')]
        [Alias('q')]
        [Alias('s')]
        [switch] $Silent
    )

    $envVars = Get-ChildItem -Path 'Env:'
    $systemToken = $envVars | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1
    $systemTokenPresent = $systemToken.count -gt 0
    $AuthType = $systemTokenPresent ? 'sPAT' : $PSCmdlet.ParameterSetName

    switch ($AuthType) {
        'DeviceFlow' {
            Write-Verbose 'Logging in using device flow...'
            $clientID = $script:Auth.$Mode.ClientID
            if ($Mode -ne (Get-GitHubConfig -Name DeviceFlowType -ErrorAction SilentlyContinue)) {
                Write-Verbose "Using $Mode authentication..."
                $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope
            } else {
                $accessTokenValidity = [datetime](Get-GitHubConfig -Name 'AccessTokenExpirationDate') - (Get-Date)
                $accessTokenIsValid = $accessTokenValidity.Seconds -gt 0
                $hours = $accessTokenValidity.Hours.ToString().PadLeft(2, '0')
                $minutes = $accessTokenValidity.Minutes.ToString().PadLeft(2, '0')
                $seconds = $accessTokenValidity.Seconds.ToString().PadLeft(2, '0')
                $accessTokenValidityText = "$hours`:$minutes`:$seconds"
                if ($accessTokenIsValid) {
                    if ($accessTokenValidity.TotalHours -gt $script:Auth.AccessTokenGracePeriodInHours) {
                        if (-not $Silent) {
                            Write-Host '✓ ' -ForegroundColor Green -NoNewline
                            Write-Host "Access token is still valid for $accessTokenValidityText ..."
                        }
                        break
                    } else {
                        if (-not $Silent) {
                            Write-Host 'âš  ' -ForegroundColor Yellow -NoNewline
                            Write-Host "Access token remaining validity $accessTokenValidityText. Refreshing access token..."
                        }
                        $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken)
                    }
                } else {
                    $refreshTokenValidity = [datetime](Get-GitHubConfig -Name 'RefreshTokenExpirationDate') - (Get-Date)
                    $refreshTokenIsValid = $refreshTokenValidity.Seconds -gt 0
                    if ($refreshTokenIsValid) {
                        if (-not $Silent) {
                            Write-Host 'âš  ' -ForegroundColor Yellow -NoNewline
                            Write-Host 'Access token expired. Refreshing access token...'
                        }
                        $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken)
                    } else {
                        Write-Verbose "Using $Mode authentication..."
                        $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope
                    }
                }
            }
            Reset-GitHubConfig -Scope 'Auth'
            switch ($Mode) {
                'GitHubApp' {
                    $settings = @{
                        AccessToken                = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token
                        AccessTokenExpirationDate  = (Get-Date).AddSeconds($tokenResponse.expires_in)
                        AccessTokenType            = $tokenResponse.access_token -replace '_.*$', '_*'
                        ApiBaseUri                 = 'https://api.github.com'
                        ApiVersion                 = '2022-11-28'
                        AuthType                   = $AuthType
                        DeviceFlowType             = $Mode
                        RefreshToken               = ConvertTo-SecureString -AsPlainText $tokenResponse.refresh_token
                        RefreshTokenExpirationDate = (Get-Date).AddSeconds($tokenResponse.refresh_token_expires_in)
                        Scope                      = $tokenResponse.scope
                    }
                }
                'OAuthApp' {
                    $settings = @{
                        AccessToken     = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token
                        AccessTokenType = $tokenResponse.access_token -replace '_.*$', '_*'
                        ApiBaseUri      = 'https://api.github.com'
                        ApiVersion      = '2022-11-28'
                        AuthType        = $AuthType
                        DeviceFlowType  = $Mode
                        Scope           = $tokenResponse.scope
                    }
                }
            }
            Set-GitHubConfig @settings
            break
        }
        'PAT' {
            Write-Verbose 'Logging in using personal access token...'
            Reset-GitHubConfig -Scope 'Auth'
            Write-Host '! ' -ForegroundColor DarkYellow -NoNewline
            Start-Process 'https://github.com/settings/tokens'
            $accessTokenValue = Read-Host -Prompt 'Enter your personal access token' -AsSecureString
            $accessTokenType = (ConvertFrom-SecureString $accessTokenValue -AsPlainText) -replace '_.*$', '_*'
            if ($accessTokenType -notmatch '^ghp_|^github_pat_') {
                Write-Warning 'âš  ' -ForegroundColor Yellow -NoNewline
                Write-Warning "Unexpected access token format: $accessTokenType"
            }
            $settings = @{
                AccessToken     = $accessTokenValue
                AccessTokenType = $accessTokenType
                ApiBaseUri      = 'https://api.github.com'
                ApiVersion      = '2022-11-28'
                AuthType        = $AuthType
            }
            Set-GitHubConfig @settings
            break
        }
        'sPAT' {
            Write-Verbose 'Logging in using system access token...'
            Reset-GitHubConfig -Scope 'Auth'
            $prefix = $systemToken.Value -replace '_.*$', '_*'
            $settings = @{
                AccessToken     = ConvertTo-SecureString -AsPlainText $systemToken.Value
                AccessTokenType = $prefix
                ApiBaseUri      = 'https://api.github.com'
                ApiVersion      = '2022-11-28'
                AuthType        = 'sPAT'
            }
            Set-GitHubConfig @settings
        }
    }

    if ($AuthType -ne 'sPAT') {
        $user = Get-GitHubUser
        $username = $user.login
        Set-GitHubConfig -UserName $username
    } else {
        $username = 'system'
    }

    if (-not $Silent) {
        Write-Host '✓ ' -ForegroundColor Green -NoNewline
        Write-Host "Logged in as $username!"
    }

    $systemRepo = $envVars | Where-Object Name -EQ 'GITHUB_REPOSITORY'
    $systemRepoPresent = $systemRepo.count -gt 0

    if ($Owner) {
        Set-GitHubConfig -Owner $Owner
    } elseif ($systemRepoPresent) {
        $owner = $systemRepo.Value.Split('/')[0]
        Set-GitHubConfig -Owner $owner
    }

    if ($Repo) {
        Set-GitHubConfig -Repo $Repo
    } elseif ($systemRepoPresent) {
        $repo = $systemRepo.Value.Split('/')[-1]
        Set-GitHubConfig -Repo $repo
    }
}

Write-Verbose "[$scriptName] - [public/Auth/Connect-GitHubAccount.ps1] - Done"
#endregion - From public/Auth/Connect-GitHubAccount.ps1
#region - From public/Auth/Disconnect-GitHubAccount.ps1
Write-Verbose "[$scriptName] - [public/Auth/Disconnect-GitHubAccount.ps1] - Importing"

function Disconnect-GitHubAccount {
    <#
        .SYNOPSIS
        Disconnects from GitHub and removes the current GitHub configuration.

        .DESCRIPTION
        Disconnects from GitHub and removes the current GitHub configuration.

        .EXAMPLE
        Disconnect-GitHubAccount

        Disconnects from GitHub and removes the current GitHub configuration.
    #>

    [Alias('Disconnect-GHAccount')]
    [Alias('Disconnect-GitHub')]
    [Alias('Disconnect-GH')]
    [Alias('Logout-GitHubAccount')]
    [Alias('Logout-GHAccount')]
    [Alias('Logout-GitHub')]
    [Alias('Logout-GH')]
    [Alias('Logoff-GitHubAccount')]
    [Alias('Logoff-GHAccount')]
    [Alias('Logoff-GitHub')]
    [Alias('Logoff-GH')]
    [OutputType([void])]
    [CmdletBinding()]
    param ()

    Reset-GitHubConfig -Scope 'All'

    Write-Host '✓ ' -ForegroundColor Green -NoNewline
    Write-Host 'Logged out of GitHub!'
}

Write-Verbose "[$scriptName] - [public/Auth/Disconnect-GitHubAccount.ps1] - Done"
#endregion - From public/Auth/Disconnect-GitHubAccount.ps1

Write-Verbose "[$scriptName] - [public/Auth] - Done"
#endregion - From public/Auth

#region - From public/Branches
Write-Verbose "[$scriptName] - [public/Branches] - Processing folder"

#region - From public/Branches/Get-GitHubRepoBranch.ps1
Write-Verbose "[$scriptName] - [public/Branches/Get-GitHubRepoBranch.ps1] - Importing"

filter Get-GitHubRepoBranch {
    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo)
    )

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/branches"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Branches/Get-GitHubRepoBranch.ps1] - Done"
#endregion - From public/Branches/Get-GitHubRepoBranch.ps1

Write-Verbose "[$scriptName] - [public/Branches] - Done"
#endregion - From public/Branches

#region - From public/Config
Write-Verbose "[$scriptName] - [public/Config] - Processing folder"

#region - From public/Config/Get-GitHubConfig.ps1
Write-Verbose "[$scriptName] - [public/Config/Get-GitHubConfig.ps1] - Importing"

function Get-GitHubConfig {
    <#
        .SYNOPSIS
        Get configuration value.

        .DESCRIPTION
        Get a named configuration value from the GitHub configuration file.

        .EXAMPLE
        Get-GitHubConfig -Name ApiBaseUri

        Get the current GitHub configuration for the ApiBaseUri.
    #>

    [Alias('Get-GHConfig')]
    [Alias('GGHC')]
    [OutputType([object])]
    [CmdletBinding()]
    param (
        # Choose a configuration name to get.
        [Parameter()]
        [ValidateSet(
            'AccessToken',
            'AccessTokenExpirationDate',
            'AccessTokenType',
            'ApiBaseUri',
            'ApiVersion',
            'AuthType',
            'DeviceFlowType',
            'Owner',
            'RefreshToken',
            'RefreshTokenExpirationDate',
            'Repo',
            'Scope',
            'UserName'
        )]
        [string] $Name
    )

    $prefix = $script:SecretVault.Prefix

    $RefreshTokenData = (Get-SecretInfo -Name "$prefix`RefreshToken").Metadata | ConvertFrom-HashTable | ConvertTo-HashTable
    $AccessTokenData = (Get-SecretInfo -Name "$prefix`AccessToken").Metadata | ConvertFrom-HashTable | ConvertTo-HashTable
    $metadata = Join-Object -Main $RefreshTokenData -Overrides $AccessTokenData -AsHashtable

    switch($Name) {
        'AccessToken' {
            Get-Secret -Name "$prefix`AccessToken"
        }
        'RefreshToken' {
            Get-Secret -Name "$prefix`RefreshToken"
        }
        default {
            if ($Name) {
                $metadata.$Name
            } else {
                $metadata.GetEnumerator() | Sort-Object -Property Name
            }
        }
    }
}

Write-Verbose "[$scriptName] - [public/Config/Get-GitHubConfig.ps1] - Done"
#endregion - From public/Config/Get-GitHubConfig.ps1
#region - From public/Config/Set-GitHubConfig.ps1
Write-Verbose "[$scriptName] - [public/Config/Set-GitHubConfig.ps1] - Importing"

function Set-GitHubConfig {
    <#
        .SYNOPSIS
        Set the GitHub configuration.

        .DESCRIPTION
        Set the GitHub configuration. Specific scopes can be set by using the parameters.

        .EXAMPLE
        Set-GitHubConfig -APIBaseURI 'https://api.github.com" -APIVersion '2022-11-28'

        Sets the App.API scope of the GitHub configuration.

        .EXAMPLE
        Set-GitHubConfig -Name "MyFavouriteRepo" -Value 'https://github.com/PSModule/GitHub'

        Sets a item called 'MyFavouriteRepo' in the GitHub configuration.
    #>

    [Alias('Set-GHConfig')]
    [CmdletBinding()]
    param (
        # Set the access token type.
        [Parameter()]
        [string] $AccessTokenType,

        # Set the access token.
        [Parameter()]
        [securestring] $AccessToken,

        # Set the access token expiration date.
        [Parameter()]
        [datetime] $AccessTokenExpirationDate,

        # Set the API Base URI.
        [Parameter()]
        [string] $ApiBaseUri,

        # Set the GitHub API Version.
        [Parameter()]
        [string] $ApiVersion,

        # Set the authentication type.
        [Parameter()]
        [string] $AuthType,

        # Set the device flow type.
        [Parameter()]
        [string] $DeviceFlowType,

        # Set the default for the Owner parameter.
        [Parameter()]
        [string] $Owner,

        # Set the refresh token.
        [Parameter()]
        [securestring] $RefreshToken,

        # Set the refresh token expiration date.
        [Parameter()]
        [datetime] $RefreshTokenExpirationDate,

        # Set the default for the Repo parameter.
        [Parameter()]
        [string] $Repo,

        # Set the scope.
        [Parameter()]
        [string] $Scope,

        # Set the GitHub username.
        [Parameter()]
        [string] $UserName
    )

    $prefix = $script:SecretVault.Prefix

    #region AccessToken
    $secretName = "$prefix`AccessToken"
    $removeKeys = 'AccessToken', 'RefreshToken', 'RefreshTokenExpirationDate'
    $keepTypes = 'String', 'Int', 'DateTime'

    # Get existing metadata if it exists
    $newSecretMetadata = @{}
    if (Get-SecretInfo -Name $secretName) {
        $secretGetInfoParam = @{
            Name  = $secretName
            Vault = $script:SecretVault.Name
        }
        $secretInfo = Get-SecretInfo @secretGetInfoParam
        Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)"
        $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable
        $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $secretMetadata -AsHashtable
    }

    # Get metadata updates from parameters and clean up unwanted data
    $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable
    Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)"
    Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())"
    Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys
    Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)"

    $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $updateSecretMetadata -AsHashtable
    Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)"
    Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())"

    if ($AccessToken) {
        $accessTokenSetParam = @{
            Name               = $secretName
            Vault              = $script:SecretVault.Name
            SecureStringSecret = $AccessToken
        }
        Set-Secret @accessTokenSetParam
    }

    if (Get-SecretInfo -Name $secretName) {
        $secretSetInfoParam = @{
            Name     = $secretName
            Vault    = $script:SecretVault.Name
            Metadata = $newSecretMetadata
        }
        Set-SecretInfo @secretSetInfoParam
    }
    #endregion AccessToken

    #region RefreshToken
    $secretName = "$prefix`RefreshToken"
    $removeKeys = 'AccessToken', 'RefreshToken', 'AccessTokenExpirationDate'

    # Get existing metadata if it exists
    $newSecretMetadata = @{}
    if (Get-SecretInfo -Name $secretName) {
        $secretGetInfoParam = @{
            Name  = $secretName
            Vault = $script:SecretVault.Name
        }
        $secretInfo = Get-SecretInfo @secretGetInfoParam
        Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)"
        $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable
        $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $secretMetadata -AsHashtable
    }

    # Get metadata updates from parameters and clean up unwanted data
    $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable
    Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)"
    Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())"
    Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys
    Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)"

    $newSecretMetadata = Join-Object -Main $newSecretMetadata -Overrides $updateSecretMetadata -AsHashtable
    Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)"
    Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())"

    if ($RefreshToken) {
        $refreshTokenSetParam = @{
            Name               = $secretName
            Vault              = $script:SecretVault.Name
            SecureStringSecret = $RefreshToken
        }
        Set-Secret @refreshTokenSetParam
    }

    if (Get-SecretInfo -Name $secretName) {
        $secretSetInfoParam = @{
            Name     = $secretName
            Vault    = $script:SecretVault.Name
            Metadata = $newSecretMetadata
        }
        Set-SecretInfo @secretSetInfoParam
    }
    #endregion AccessToken
}

Write-Verbose "[$scriptName] - [public/Config/Set-GitHubConfig.ps1] - Done"
#endregion - From public/Config/Set-GitHubConfig.ps1

Write-Verbose "[$scriptName] - [public/Config] - Done"
#endregion - From public/Config

#region - From public/Deployments
Write-Verbose "[$scriptName] - [public/Deployments] - Processing folder"

#region - From public/Deployments/Get-GitHubEnvironment.ps1
Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironment.ps1] - Importing"

filter Get-GitHubEnvironment {
    <#
        .SYNOPSIS
        Get GitHub environment

        .DESCRIPTION
        Long description

        .PARAMETER Owner
        Parameter description

        .PARAMETER Repo
        Parameter description

        .EXAMPLE
        An example

        .NOTES
        https://docs.github.com/rest/reference/repos#get-all-environments
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo)
    )

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/environments"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironment.ps1] - Done"
#endregion - From public/Deployments/Get-GitHubEnvironment.ps1
#region - From public/Deployments/Get-GitHubEnvironmentSecrets.ps1
Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironmentSecrets.ps1] - Importing"

filter Get-GitHubEnvironmentSecrets {
    <#
    .SYNOPSIS
    Get GitHub environment secrets

    .DESCRIPTION
    Long description

    .PARAMETER Owner
    Parameter description

    .PARAMETER Repo
    Parameter description

    .PARAMETER EnvironmentName
    Parameter description

    .EXAMPLE
    An example

    .NOTES
    https://docs.github.com/rest/reference/repos#get-all-environments
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [Alias('name')]
        [string] $EnvironmentName
    )

    $RepoID = (Get-GitHubRepo).id

    $inputObject = @{
        APIEndpoint = "/repositories/$RepoID/environments/$EnvironmentName/secrets"
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Deployments/Get-GitHubEnvironmentSecrets.ps1] - Done"
#endregion - From public/Deployments/Get-GitHubEnvironmentSecrets.ps1
#region - From public/Deployments/Update-GitHubEnvironment.ps1
Write-Verbose "[$scriptName] - [public/Deployments/Update-GitHubEnvironment.ps1] - Importing"

filter Update-GitHubEnvironment {
    <#
        .NOTES
        https://docs.github.com/rest/reference/repos#create-or-update-an-environment
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo),

        [Alias('environment_name')]
        [Parameter(
            Mandatory,
            ValueFromPipelineByPropertyName
        )]
        [string] $Name
    )

    $body = @{
        owner            = $Owner
        repo             = $Repo
        environment_name = $Name
    }

    $inputObject = @{
        APIEndpoint = "/repos/$Owner/$Repo/environments/$Name"
        Method      = 'PUT'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Deployments/Update-GitHubEnvironment.ps1] - Done"
#endregion - From public/Deployments/Update-GitHubEnvironment.ps1

Write-Verbose "[$scriptName] - [public/Deployments] - Done"
#endregion - From public/Deployments

#region - From public/Emojis
Write-Verbose "[$scriptName] - [public/Emojis] - Processing folder"

#region - From public/Emojis/Get-GitHubEmojis.ps1
Write-Verbose "[$scriptName] - [public/Emojis/Get-GitHubEmojis.ps1] - Importing"

filter Get-GitHubEmojis {
    <#
        .NOTES
        https://docs.github.com/rest/reference/emojis#get-emojis
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Destination
    )

    $inputObject = @{
        APIEndpoint = '/emojis'
        Method      = 'GET'
    }

    $response = (Invoke-GitHubAPI @inputObject).Response

    if (Test-Path -Path $Destination) {
        $response.PSObject.Properties | ForEach-Object -Parallel {
            Invoke-WebRequest -Uri $_.Value -OutFile "$using:Destination/$($_.Name).png"
        }
    } else {
        $response
    }
}

Write-Verbose "[$scriptName] - [public/Emojis/Get-GitHubEmojis.ps1] - Done"
#endregion - From public/Emojis/Get-GitHubEmojis.ps1

Write-Verbose "[$scriptName] - [public/Emojis] - Done"
#endregion - From public/Emojis

#region - From public/Markdown
Write-Verbose "[$scriptName] - [public/Markdown] - Processing folder"

#region - From public/Markdown/Get-GitHubMarkdown.ps1
Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdown.ps1] - Importing"

filter Get-GitHubMarkdown {
    <#
        .NOTES
        https://docs.github.com/rest/reference/meta#github-api-root
    #>

    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [switch] $Text,

        [Parameter()]
        [ValidateSet('markdown', 'gfm')]
        [string] $Mode,

        [Parameter()]
        [string] $Context
    )

    $body = @{
        context = $Context
        mode    = $Mode
        text    = $Text
    }

    $inputObject = @{
        APIEndpoint = '/markdown'
        Method      = 'POST'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdown.ps1] - Done"
#endregion - From public/Markdown/Get-GitHubMarkdown.ps1
#region - From public/Markdown/Get-GitHubMarkdownRaw.ps1
Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdownRaw.ps1] - Importing"

filter Get-GitHubMarkdownRaw {
    <#
        .NOTES
        https://docs.github.com/rest/reference/meta#github-api-root
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Text
    )

    $inputObject = @{
        APIEndpoint = '/markdown/raw'
        ContentType = 'text/plain'
        Body        = $Text
        Method      = 'POST'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Markdown/Get-GitHubMarkdownRaw.ps1] - Done"
#endregion - From public/Markdown/Get-GitHubMarkdownRaw.ps1

Write-Verbose "[$scriptName] - [public/Markdown] - Done"
#endregion - From public/Markdown

#region - From public/Meta
Write-Verbose "[$scriptName] - [public/Meta] - Processing folder"

#region - From public/Meta/Get-GitHubApiVersions.ps1
Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubApiVersions.ps1] - Importing"

filter Get-GitHubApiVersions {
    <#
        .SYNOPSIS
        Get all API versions.

        .DESCRIPTION
        Get all supported GitHub API versions.

        .EXAMPLE
        Get-GitHubApiVersions

        Get all supported GitHub API versions.

        .NOTES
        https://docs.github.com/rest/meta/meta#get-all-api-versions
    #>

    [OutputType([string[]])]
    [CmdletBinding()]
    param ()

    $inputObject = @{
        ApiEndpoint = '/versions'
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubApiVersions.ps1] - Done"
#endregion - From public/Meta/Get-GitHubApiVersions.ps1
#region - From public/Meta/Get-GitHubMeta.ps1
Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubMeta.ps1] - Importing"

filter Get-GitHubMeta {
    <#
        .SYNOPSIS
        Get GitHub meta information.

        .DESCRIPTION
        Returns meta information about GitHub, including a list of GitHub's IP addresses. For more information, see "[About GitHub's IP addresses](https://docs.github.com/articles/about-github-s-ip-addresses/)."

        The API's response also includes a list of GitHub's domain names.

        The values shown in the documentation's response are example values. You must always query the API directly to get the latest values.

        **Note:** This endpoint returns both IPv4 and IPv6 addresses. However, not all features support IPv6. You should refer to the specific documentation for each feature to determine if IPv6 is supported.

        .EXAMPLE
        Get-GitHubMeta

        Returns meta information about GitHub, including a list of GitHub's IP addresses.

        .NOTES
        https://docs.github.com/rest/meta/meta#get-apiname-meta-information
    #>

    [OutputType([object])]
    [CmdletBinding()]
    param ()

    $inputObject = @{
        ApiEndpoint = '/meta'
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubMeta.ps1] - Done"
#endregion - From public/Meta/Get-GitHubMeta.ps1
#region - From public/Meta/Get-GitHubOctocat.ps1
Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubOctocat.ps1] - Importing"

filter Get-GitHubOctocat {
    <#
        .SYNOPSIS
        Get Octocat.

        .DESCRIPTION
        Get the octocat as ASCII art.

        .EXAMPLE
        Get-GitHubOctocat

        Get the octocat as ASCII art

        .EXAMPLE
        Get-GitHubOctocat -S "Hello world"

        Get the octocat as ASCII art with a custom saying

        .NOTES
        https://docs.github.com/rest/meta/meta#get-octocat
    #>

    [OutputType([string])]
    [CmdletBinding()]
    param (
        # The words to show in Octocat's speech bubble
        [Parameter()]
        [Alias('Say')]
        [Alias('Saying')]
        [string] $S
    )

    $body = @{
        s = $S
    }

    $inputObject = @{
        APIEndpoint = '/octocat'
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubOctocat.ps1] - Done"
#endregion - From public/Meta/Get-GitHubOctocat.ps1
#region - From public/Meta/Get-GitHubRoot.ps1
Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubRoot.ps1] - Importing"

filter Get-GitHubRoot {
    <#
        .SYNOPSIS
        GitHub API Root.

        .DESCRIPTION
        Get Hypermedia links to resources accessible in GitHub's REST API.

        .EXAMPLE
        Get-GitHubRoot

        Get the root endpoint for the GitHub API.

        .NOTES
        https://docs.github.com/rest/meta/meta#github-api-root
    #>

    [CmdletBinding()]
    param ()

    $inputObject = @{
        APIEndpoint = '/'
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubRoot.ps1] - Done"
#endregion - From public/Meta/Get-GitHubRoot.ps1
#region - From public/Meta/Get-GitHubZen.ps1
Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubZen.ps1] - Importing"

filter Get-GitHubZen {
    <#
    .SYNOPSIS
    Get the Zen of GitHub.

    .DESCRIPTION
    Get a random sentence from the Zen of GitHub.

    .EXAMPLE
    Get-GitHubZen

    Get a random sentence from the Zen of GitHub.

    .NOTES
    https://docs.github.com/rest/meta/meta#get-the-zen-of-github
    #>

    [CmdletBinding()]
    param ()

    $inputObject = @{
        APIEndpoint = '/zen'
        Method      = 'GET'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Meta/Get-GitHubZen.ps1] - Done"
#endregion - From public/Meta/Get-GitHubZen.ps1

Write-Verbose "[$scriptName] - [public/Meta] - Done"
#endregion - From public/Meta

#region - From public/Organization
Write-Verbose "[$scriptName] - [public/Organization] - Processing folder"

#region - From public/Organization/Get-GitHubOrganization.ps1
Write-Verbose "[$scriptName] - [public/Organization/Get-GitHubOrganization.ps1] - Importing"

filter Get-GitHubOrganization {
    <#
        .SYNOPSIS
        List organization

        .DESCRIPTION
        List organizations for the authenticated user - if no parameters are provided.
        List organizations for a user - if a username is provided.
        Lists all organizations, in the order that they were created on GitHub - if '-All' is provided.
        Get an organization - if a organization name is provided.

        .EXAMPLE
        Get-GitHubOrganization

        List organizations for the authenticated user.

        .EXAMPLE
        Get-GitHubOrganization -Username 'octocat'

        List public organizations for the user 'octocat'.

        .EXAMPLE
        Get-GitHubOrganization -All -Since 142951047

        List organizations, starting with PSModule.

        .EXAMPLE
        Get-GitHubOrganization -Name 'PSModule'

        Get the organization 'PSModule'.

        .NOTES
        https://docs.github.com/rest/orgs/orgs
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding(DefaultParameterSetName = '__DefaultSet')]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ParameterSetName = 'NamedOrg',
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [Alias('org')]
        [Alias('owner')]
        [string] $OrganizationName,

        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ParameterSetName = 'NamedUser',
            ValueFromPipelineByPropertyName
        )]
        [string] $Username,

        # List all organizations. Use '-Since' to start at a specific organization id.
        [Parameter(
            Mandatory,
            ParameterSetName = 'AllOrg'
        )]
        [switch] $All,

        # A organization ID. Only return organizations with an ID greater than this ID.
        [Parameter(ParameterSetName = 'AllOrg')]
        [int] $Since = 0,

        # The number of results per page (max 100).
        [Parameter(ParameterSetName = 'AllOrg')]
        [Parameter(ParameterSetName = 'UserOrg')]
        [Parameter(ParameterSetName = '__DefaultSet')]
        [int] $PerPage = 30
    )

    switch ($PSCmdlet.ParameterSetName) {
        '__DefaultSet' {
            Get-GitHubMyOrganization -PerPage $PerPage | Get-GitHubOrganizationByName
        }
        'NamedOrg' {
            Get-GitHubOrganizationByName -OrganizationName $OrganizationName
        }
        'NamedUser' {
            Get-GitHubUserOrganization -Username $Username
        }
        'AllOrg' {
            Get-GitHubAllOrganization -Since $Since -PerPage $PerPage
        }
    }
}

Write-Verbose "[$scriptName] - [public/Organization/Get-GitHubOrganization.ps1] - Done"
#endregion - From public/Organization/Get-GitHubOrganization.ps1
#region - From public/Organization/Get-GitHubOrganizationAppInstallation.ps1
Write-Verbose "[$scriptName] - [public/Organization/Get-GitHubOrganizationAppInstallation.ps1] - Importing"

filter Get-GitHubOrganizationAppInstallation {
    <#
        .SYNOPSIS
        List app installations for an organization

        .DESCRIPTION
        Lists all GitHub Apps in an organization. The installation count includes all GitHub Apps installed on repositories in the organization. You must be an organization owner with `admin:read` scope to use this endpoint.

        .EXAMPLE
        Get-GitHubOrganizationAppInstallation -OrganizationName 'github'

        Gets all GitHub Apps in the organization `github`.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#list-app-installations-for-an-organization

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = @{
        per_page = $PerPage
    }

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName/installations"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response.installations

}

Write-Verbose "[$scriptName] - [public/Organization/Get-GitHubOrganizationAppInstallation.ps1] - Done"
#endregion - From public/Organization/Get-GitHubOrganizationAppInstallation.ps1
#region - From public/Organization/Remove-GitHubOrganization.ps1
Write-Verbose "[$scriptName] - [public/Organization/Remove-GitHubOrganization.ps1] - Importing"

filter Remove-GitHubOrganization {
    <#
        .SYNOPSIS
        Delete an organization

        .DESCRIPTION
        Deletes an organization and all its repositories.
        The organization login will be unavailable for 90 days after deletion.
        Please review the Terms of Service regarding account deletion before using this endpoint:
        https://docs.github.com/site-policy/github-terms/github-terms-of-service

        .EXAMPLE
        Remove-GitHubOrganization -OrganizationName 'github'

        Deletes the organization 'github' and all its repositories.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#delete-an-organization
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName
    )

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName"
        Method      = 'DELETE'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Organization/Remove-GitHubOrganization.ps1] - Done"
#endregion - From public/Organization/Remove-GitHubOrganization.ps1
#region - From public/Organization/Set-GitHubOrganization.ps1
Write-Verbose "[$scriptName] - [public/Organization/Set-GitHubOrganization.ps1] - Importing"

filter Set-GitHubOrganization {
    <#
        .SYNOPSIS
        Update an organization

        .DESCRIPTION
        **Parameter Deprecation Notice:** GitHub will replace and discontinue `members_allowed_repository_creation_type` in favor of more granular permissions. The new input parameters are `members_can_create_public_repositories`, `members_can_create_private_repositories` for all organizations and `members_can_create_internal_repositories` for organizations associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see the [blog post](https://developer.github.com/changes/2019-12-03-internal-visibility-changes).

        Enables an authenticated organization owner with the `admin:org` scope or the `repo` scope to update the organization's profile and member privileges.

        .EXAMPLE
        Set-GitHubOrganization -OrganizationName 'github' -Blog 'https://github.blog'

        Sets the blog URL for the organization 'github' to 'https://github.blog'.

        .EXAMPLE
        $param = @{
            OrganizationName = 'github'
            MembersCanCreatePublicRepositories = $true
            MembersCanCreatePrivateRepositories = $true
            MembersCanCreateInternalRepositories = $true
        }
        Set-GitHubOrganization @param

        Sets the repository creation permissions for the organization 'github' to allow all members to create public, private, and internal repositories.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#update-an-organization

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # Billing email address. This address is not publicized.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('billing_email')]
        [string] $BillingEmail,

        # The company name.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Company,

        # The publicly visible email address.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Email,

        # The Twitter username of the company.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('twitter_username')]
        [string] $TwitterUsername,

        # The location.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Location,

        # The shorthand name of the company.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Name,

        # The description of the company.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Description,

        # Whether an organization can use organization projects.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('has_organization_projects')]
        [bool] $HasOrganizationProjects,

        # Whether repositories that belong to the organization can use repository projects.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('has_repository_projects')]
        [bool] $HasRepositoryProjects,

        # Default permission level members have for organization repositories.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('default_repository_permission')]
        [ValidateSet('read', 'write', 'admin', 'none')]
        [string] $DefaultRepositoryPermission,

        # Whether of non-admin organization members can create repositories. Note: A parameter can override this parameter. See members_allowed_repository_creation_type in this table for details.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_repositories')]
        [bool] $MembersCanCreateRepositories = $true,

        # Whether organization members can create internal repositories, which are visible to all enterprise members. You can only allow members to create internal repositories if your organization is associated with an enterprise account using GitHub Enterprise Cloud or GitHub Enterprise Server 2.20+. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_internal_repositories')]
        [bool] $MembersCanCreateInternalRepositories,

        # Whether organization members can create private repositories, which are visible to organization members with permission. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_private_repositories')]
        [bool] $MembersCanCreatePrivateRepositories,

        # Whether organization members can create public repositories, which are visible to anyone. For more information, see "Restricting repository creation in your organization" in the GitHub Help documentation.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_public_repositories')]
        [bool] $MembersCanCreatePublicRepositories,

        # Specifies which types of repositories non-admin organization members can create. private is only available to repositories that are part of an organization on GitHub Enterprise Cloud. Note: This parameter is deprecated and will be removed in the future. Its return value ignores internal repositories. Using this parameter overrides values set in members_can_create_repositories. See the parameter deprecation notice in the operation description for details.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_allowed_repository_creation_type')]
        [ValidateSet('all', 'private', 'none')]
        [string] $MembersAllowedRepositoryCreationType,

        # Whether organization members can create GitHub Pages sites. Existing published sites will not be impacted.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_pages')]
        [bool] $MembersCanCreatePages = $true,

        # Whether organization members can create public GitHub Pages sites. Existing published sites will not be impacted.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_public_pages')]
        [bool] $MembersCanCreatePublicPages = $true,

        # Whether organization members can create private GitHub Pages sites. Existing published sites will not be impacted.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_create_private_pages')]
        [bool] $MembersCanCreatePrivatePages = $true,

        # Whether organization members can fork private organization repositories.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('members_can_fork_private_repositories')]
        [bool] $MembersCanForkPrivateRepositories = $false,

        # Whether contributors to organization repositories are required to sign off on commits they make through GitHub's web interface.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('web_commit_signoff_required')]
        [bool] $WebCommitSignoffRequired = $false,

        # Path to the organization's blog.
        [Parameter(ValueFromPipelineByPropertyName)]
        [string] $Blog,

        # Whether GitHub Advanced Security is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('advanced_security_enabled_for_new_repositories')]
        [bool] $AdvancedSecurityEnabledForNewRepositories = $false,

        # Whether Dependabot alerts is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('dependabot_alerts_enabled_for_new_repositories')]
        [bool] $DependabotAlertsEnabledForNewRepositories = $false,

        # Whether Dependabot security updates is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('dependabot_security_updates_enabled_for_new_repositories')]
        [bool] $DependabotSecurityUpdatesEnabledForNewRepositories = $false,

        # Whether dependency graph is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('dependency_graph_enabled_for_new_repositories')]
        [bool] $DependencyGraphEnabledForNewRepositories = $false,

        # Whether secret scanning is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('secret_scanning_enabled_for_new_repositories')]
        [bool] $SecretScanningEnabledForNewRepositories = $false,

        # Whether secret scanning push protection is automatically enabled for new repositories.
        # To use this parameter, you must have admin permissions for the repository or be an owner or security manager for the organization that owns the repository. For more information, see "Managing security managers in your organization."
        # You can check which security and analysis features are currently enabled by using a GET /orgs/{org} request.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('secret_scanning_push_protection_enabled_for_new_repositories')]
        [bool] $SecretScanningPushProtectionEnabledForNewRepositories = $false,

        # Whether a custom link is shown to contributors who are blocked from pushing a secret by push protection.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('secret_scanning_push_protection_custom_link_enabled')]
        [bool] $SecretScanningPushProtectionCustomLinkEnabled = $false,

        # If secret_scanning_push_protection_custom_link_enabled is true, the URL that will be displayed to contributors who are blocked from pushing a secret.
        [Parameter(ValueFromPipelineByPropertyName)]
        [Alias('secret_scanning_push_protection_custom_link')]
        [string] $SecretScanningPushProtectionCustomLink
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case
    Remove-HashTableEntries -Hashtable $body -RemoveNames 'organization_name'

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName"
        Method      = 'PATCH'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Organization/Set-GitHubOrganization.ps1] - Done"
#endregion - From public/Organization/Set-GitHubOrganization.ps1
#region - From public/Organization/Set-GitHubOrganizationSecurityFeature.ps1
Write-Verbose "[$scriptName] - [public/Organization/Set-GitHubOrganizationSecurityFeature.ps1] - Importing"

filter Set-GitHubOrganizationSecurityFeature {
    <#
        .SYNOPSIS
        Enable or disable a security feature for an organization

        .DESCRIPTION
        Enables or disables the specified security feature for all eligible repositories in an organization.

        To use this endpoint, you must be an organization owner or be member of a team with the security manager role.
        A token with the 'write:org' scope is also required.

        GitHub Apps must have the `organization_administration:write` permission to use this endpoint.

        For more information, see "[Managing security managers in your organization](https://docs.github.com/organizations/managing-peoples-access-to-your-organization-with-roles/managing-security-managers-in-your-organization)."

        .EXAMPLE
        Set-GitHubOrganizationSecurityFeature -OrganizationName 'github' -SecurityProduct 'dependency_graph' -Enablement 'enable_all'

        Enable the dependency graph for all repositories in the organization `github`.

        .NOTES
        https://docs.github.com/rest/orgs/orgs#enable-or-disable-a-security-feature-for-an-organization
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(Mandatory)]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The security feature to enable or disable.
        [Parameter(Mandatory)]
        [Alias('security_product')]
        [ValidateSet('dependency_graph', 'dependabot_alerts', 'dependabot_security_updates', 'advanced_security', 'code_scanning_default_setup', 'secret_scanning', 'secret_scanning_push_protection')]
        [string] $SecurityProduct,

        # The action to take.
        # enable_all means to enable the specified security feature for all repositories in the organization. disable_all means to disable the specified security feature for all repositories in the organization.
        [Parameter(Mandatory)]
        [ValidateSet('enable_all', 'disable_all')]
        [string] $Enablement,

        # CodeQL query suite to be used. If you specify the query_suite parameter, the default setup will be configured with this query suite only on all repositories that didn't have default setup already configured. It will not change the query suite on repositories that already have default setup configured. If you don't specify any query_suite in your request, the preferred query suite of the organization will be applied.
        [Parameter()]
        [Alias('query_suite')]
        [ValidateSet('default', 'extended')]
        [string] $QuerySuite
    )

    $body = @{
        query_suite = $QuerySuite
    }

    $inputObject = @{
        APIEndpoint = "/orgs/$OrganizationName/$SecurityProduct/$Enablement"
        Method      = 'POST'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Organization/Set-GitHubOrganizationSecurityFeature.ps1] - Done"
#endregion - From public/Organization/Set-GitHubOrganizationSecurityFeature.ps1

Write-Verbose "[$scriptName] - [public/Organization] - Done"
#endregion - From public/Organization

#region - From public/Status
Write-Verbose "[$scriptName] - [public/Status] - Processing folder"

#region - From public/Status/Get-GitHubScheduledMaintenance.ps1
Write-Verbose "[$scriptName] - [public/Status/Get-GitHubScheduledMaintenance.ps1] - Importing"

function Get-GitHubScheduledMaintenance {
    <#
        .SYNOPSIS
        Gets the status of GitHub scheduled maintenance

        .DESCRIPTION
        Scheduled maintenances are planned outages, upgrades, or general notices that you're working
        on infrastructure and disruptions may occurr. A close sibling of Incidents, each usually goes
        through a progression of statuses listed below, with an impact calculated from a blend of
        component statuses (or an optional override).

        Status: Scheduled, In Progress, Verifying, or Completed
        Impact: None (black), Minor (yellow), Major (orange), or Critical (red)

        .EXAMPLE
        Get-GitHubScheduledMaintenance

        Get a list of the 50 most recent scheduled maintenances.
        This includes scheduled maintenances as described in the above two endpoints, as well as those in the Completed state.

        .EXAMPLE
        Get-GitHubScheduledMaintenance -Active

        Get a list of any active maintenances.

        .EXAMPLE
        Get-GitHubScheduledMaintenance -Upcoming

        Get a list of any upcoming maintenances.

        .NOTES
        https://www.githubstatus.com/api#scheduled-maintenances
    #>

    param(
        # Get a list of any active maintenances.
        # This endpoint will only return scheduled maintenances in the In Progress or Verifying state.
        [Parameter()]
        [switch] $Active,

        # Get a list of any upcoming maintenances.
        # This endpoint will only return scheduled maintenances still in the Scheduled state.
        [Parameter()]
        [switch] $Upcoming
    )

    if ($Active) {
        $APIURI = 'https://www.githubstatus.com/api/v2/scheduled-maintenances/active.json'
        $response = Invoke-RestMethod -Uri $APIURI -Method Get
        $response.scheduled_maintenances
        return
    }

    if ($Upcoming) {
        $APIURI = 'https://www.githubstatus.com/api/v2/scheduled-maintenances/upcoming.json'
        $response = Invoke-RestMethod -Uri $APIURI -Method Get
        $response.scheduled_maintenances
        return
    }

    $APIURI = 'https://www.githubstatus.com/api/v2/scheduled-maintenances.json'
    $response = Invoke-RestMethod -Uri $APIURI -Method Get
    $response.scheduled_maintenances

}

Write-Verbose "[$scriptName] - [public/Status/Get-GitHubScheduledMaintenance.ps1] - Done"
#endregion - From public/Status/Get-GitHubScheduledMaintenance.ps1
#region - From public/Status/Get-GitHubStatus.ps1
Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatus.ps1] - Importing"

function Get-GitHubStatus {
    <#
        .SYNOPSIS
        Gets the status of GitHub services

        .DESCRIPTION
        Get a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances.
        Get the status rollup for the whole page. This endpoint includes an indicator - one of none, minor, major, or critical, as well as a human description of the blended component status. Examples of the blended status include "All Systems Operational", "Partial System Outage", and "Major Service Outage".

        .EXAMPLE
        Get-GitHubStatus

        Gets the status of GitHub services

        .EXAMPLE
        Get-GitHubStatus -Summary

        Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances.

        .NOTES
        https://www.githubstatus.com/api#summary
        https://www.githubstatus.com/api#status
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param(
        # Gets a summary of the status page, including a status indicator, component statuses, unresolved incidents, and any upcoming or in-progress scheduled maintenances.
        [Parameter()]
        [switch] $Summary
    )

    if ($Summary) {
        $APIURI = 'https://www.githubstatus.com/api/v2/summary.json'
        $response = Invoke-RestMethod -Uri $APIURI -Method Get
        $response
        return
    }

    $APIURI = 'https://www.githubstatus.com/api/v2/status.json'
    $response = Invoke-RestMethod -Uri $APIURI -Method Get
    $response.status

}

Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatus.ps1] - Done"
#endregion - From public/Status/Get-GitHubStatus.ps1
#region - From public/Status/Get-GitHubStatusComponents.ps1
Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatusComponents.ps1] - Importing"

function Get-GitHubStatusComponents {
    <#
        .SYNOPSIS
        Gets the status of GitHub components

        .DESCRIPTION
        Get the components for the page. Each component is listed along with its status - one of operational, degraded_performance, partial_outage, or major_outage.

        .EXAMPLE
        Get-GitHubStatusComponents

        Gets the status of GitHub components

        .NOTES
        https://www.githubstatus.com/api#components
    #>

    [OutputType([pscustomobject[]])]
    [CmdletBinding()]
    param()

    $APIURI = 'https://www.githubstatus.com/api/v2/components.json'
    $response = Invoke-RestMethod -Uri $APIURI -Method Get
    $response.components
}

Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatusComponents.ps1] - Done"
#endregion - From public/Status/Get-GitHubStatusComponents.ps1
#region - From public/Status/Get-GitHubStatusIncidents.ps1
Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatusIncidents.ps1] - Importing"

function Get-GitHubStatusIncidents {
    <#
        .SYNOPSIS
        Gets the status of GitHub incidents

        .DESCRIPTION
        Incidents are the cornerstone of any status page, being composed of many incident updates.
        Each incident usually goes through a progression of statuses listed below, with an impact
        calculated from a blend of component statuses (or an optional override).

        Status: Investigating, Identified, Monitoring, Resolved, or Postmortem
        Impact: None (black), Minor (yellow), Major (orange), or Critical (red)

        .EXAMPLE
        Get-GitHubStatusIncidents

        Gets the status of GitHub incidents

        .EXAMPLE
        Get-GitHubStatusIncidents -Unresolved

        Gets the status of GitHub incidents that are unresolved

        .NOTES
        https://www.githubstatus.com/api#incidents
    #>

    [OutputType([pscustomobject[]])]
    [CmdletBinding()]
    param(
        # Gets the status of GitHub incidents that are unresolved
        [Parameter()]
        [switch] $Unresolved
    )

    if ($Unresolved) {
        $APIURI = 'https://www.githubstatus.com/api/v2/incidents/unresolved.json'
        $response = Invoke-RestMethod -Uri $APIURI -Method Get
        $response.incidents
        return
    }

    $APIURI = 'https://www.githubstatus.com/api/v2/incidents.json'
    $response = Invoke-RestMethod -Uri $APIURI -Method Get
    $response.incidents

}

Write-Verbose "[$scriptName] - [public/Status/Get-GitHubStatusIncidents.ps1] - Done"
#endregion - From public/Status/Get-GitHubStatusIncidents.ps1

Write-Verbose "[$scriptName] - [public/Status] - Done"
#endregion - From public/Status

#region - From public/Teams
Write-Verbose "[$scriptName] - [public/Teams] - Processing folder"

#region - From public/Teams/Get-GitHubRepoTeam.ps1
Write-Verbose "[$scriptName] - [public/Teams/Get-GitHubRepoTeam.ps1] - Importing"

filter Get-GitHubRepoTeam {
    <#
        .NOTES
        https://docs.github.com/rest/reference/repos#get-a-repository
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [string] $Owner = (Get-GitHubConfig -Name Owner),

        [Parameter()]
        [string] $Repo = (Get-GitHubConfig -Name Repo)
    )

    $inputObject = @{
        Method      = 'Get'
        APIEndpoint = "/repos/$Owner/$Repo/teams"
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Teams/Get-GitHubRepoTeam.ps1] - Done"
#endregion - From public/Teams/Get-GitHubRepoTeam.ps1

Write-Verbose "[$scriptName] - [public/Teams] - Done"
#endregion - From public/Teams

#region - From public/Users
Write-Verbose "[$scriptName] - [public/Users] - Processing folder"

#region - From public/Users/Blocking
Write-Verbose "[$scriptName] - [public/Users/Blocking] - Processing folder"

#region - From public/Users/Blocking/Block-GitHubUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Blocking/Block-GitHubUser.ps1] - Importing"

filter Block-GitHubUser {
    <#
        .SYNOPSIS
        Block a user from user or an organization.

        .DESCRIPTION
        Blocks the given user and returns true.
        If the user cannot be blocked false is returned.

        .EXAMPLE
        Block-GitHubUser -Username 'octocat'

        Blocks the user 'octocat' for the authenticated user.
        Returns $true if successful, $false if not.

        .EXAMPLE
        Block-GitHubUser -OrganizationName 'github' -Username 'octocat'

        Blocks the user 'octocat' from the organization 'github'.
        Returns $true if successful, $false if not.

        .NOTES
        https://docs.github.com/rest/users/blocking#block-a-user
        https://docs.github.com/rest/orgs/blocking#block-a-user-from-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username,

        # The organization name. The name is not case sensitive.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName
    )

    if ($OrganizationName) {
        Block-GitHubUserByOrganization -OrganizationName $OrganizationName -Username $Username
    } else {
        Block-GitHubUserByUser -Username $Username
    }

}

Write-Verbose "[$scriptName] - [public/Users/Blocking/Block-GitHubUser.ps1] - Done"
#endregion - From public/Users/Blocking/Block-GitHubUser.ps1
#region - From public/Users/Blocking/Get-GitHubBlockedUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Blocking/Get-GitHubBlockedUser.ps1] - Importing"

filter Get-GitHubBlockedUser {
    <#
        .SYNOPSIS
        List blocked users.

        .DESCRIPTION
        List the users that are blocked on your personal account or a given organization.

        .EXAMPLE
        Get-GitHubBlockedUser

        Returns a list of users blocked by the authenticated user.

        .EXAMPLE
        Get-GitHubBlockedUser -OrganizationName 'github'

        Lists all users blocked by the organization `github`.

        .NOTES
        https://docs.github.com/rest/users/blocking#list-users-blocked-by-the-authenticated-user
        https://docs.github.com/rest/orgs/blocking#list-users-blocked-by-an-organization
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The organization name. The name is not case sensitive.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    if ($OrganizationName) {
        Get-GitHubBlockedUserByOrganization -OrganizationName $OrganizationName -PerPage $PerPage
    } else {
        Get-GitHubBlockedUserByUser -PerPage $PerPage
    }

}

Write-Verbose "[$scriptName] - [public/Users/Blocking/Get-GitHubBlockedUser.ps1] - Done"
#endregion - From public/Users/Blocking/Get-GitHubBlockedUser.ps1
#region - From public/Users/Blocking/Test-GitHubBlockedUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Blocking/Test-GitHubBlockedUser.ps1] - Importing"

filter Test-GitHubBlockedUser {
    <#
        .SYNOPSIS
        Check if a user is blocked by the authenticated user or an organization.

        .DESCRIPTION
        Returns a 204 if the given user is blocked by the authenticated user or organization.
        Returns a 404 if the given user is not blocked, or if the given user account has been identified as spam by GitHub.

        .EXAMPLE
        Test-GitHubBlockedUser -Username 'octocat'

        Checks if the user `octocat` is blocked by the authenticated user.
        Returns true if the user is blocked, false if not.

        .EXAMPLE
        Test-GitHubBlockedUser -OrganizationName 'github' -Username 'octocat'

        Checks if the user `octocat` is blocked by the organization `github`.
        Returns true if the user is blocked, false if not.

        .NOTES
        https://docs.github.com/rest/users/blocking#check-if-a-user-is-blocked-by-the-authenticated-user
        https://docs.github.com/rest/orgs/blocking#check-if-a-user-is-blocked-by-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username,

        # The organization name. The name is not case sensitive.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName,

        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    if ($OrganizationName) {
        Test-GitHubBlockedUserByOrganization -OrganizationName $OrganizationName -Username $Username -PerPage $PerPage
    } else {
        Test-GitHubBlockedUserByUser -Username $Username -PerPage $PerPage
    }

}

Write-Verbose "[$scriptName] - [public/Users/Blocking/Test-GitHubBlockedUser.ps1] - Done"
#endregion - From public/Users/Blocking/Test-GitHubBlockedUser.ps1
#region - From public/Users/Blocking/Unblock-GitHubUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Blocking/Unblock-GitHubUser.ps1] - Importing"

filter Unblock-GitHubUser {
    <#
        .SYNOPSIS
        Unblock a user

        .DESCRIPTION
        Unblocks the given user and returns true.

        .EXAMPLE
        Unblock-GitHubUser -Username 'octocat'

        Unblocks the user 'octocat' for the authenticated user.
        Returns $true if successful.

        .EXAMPLE
        Unblock-GitHubUser -OrganizationName 'github' -Username 'octocat'

        Unblocks the user 'octocat' from the organization 'github'.
        Returns $true if successful.

        .NOTES
        https://docs.github.com/rest/users/blocking#unblock-a-user
        https://docs.github.com/rest/orgs/blocking#unblock-a-user-from-an-organization
    #>

    [OutputType([bool])]
    [CmdletBinding()]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('login')]
        [string] $Username,

        # The organization name. The name is not case sensitive.
        [Parameter(
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [Alias('org')]
        [Alias('owner')]
        [Alias('login')]
        [string] $OrganizationName
    )

    if ($OrganizationName) {
        Unblock-GitHubUserByOrganization -OrganizationName $OrganizationName -Username $Username
    } else {
        Unblock-GitHubUserByUser -Username $Username
    }
}

Write-Verbose "[$scriptName] - [public/Users/Blocking/Unblock-GitHubUser.ps1] - Done"
#endregion - From public/Users/Blocking/Unblock-GitHubUser.ps1

Write-Verbose "[$scriptName] - [public/Users/Blocking] - Done"
#endregion - From public/Users/Blocking

#region - From public/Users/Emails
Write-Verbose "[$scriptName] - [public/Users/Emails] - Processing folder"

#region - From public/Users/Emails/Add-GitHubUserEmail.ps1
Write-Verbose "[$scriptName] - [public/Users/Emails/Add-GitHubUserEmail.ps1] - Importing"

filter Add-GitHubUserEmail {
    <#
        .SYNOPSIS
        Add an email address for the authenticated user

        .DESCRIPTION
        This endpoint is accessible with the `user` scope.

        .EXAMPLE
        Add-GitHubUserEmail -Emails 'octocat@github.com','firstname.lastname@work.com'

        Adds the email addresses 'octocat@github.com' and 'firstname.lastname@work.com' to the authenticated user's account.

        .NOTES
        https://docs.github.com/rest/users/emails#add-an-email-address-for-the-authenticated-user

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # Adds one or more email addresses to your GitHub account.
        # Must contain at least one email address.
        # Note: Alternatively, you can pass a single email address or an array of emails addresses directly,
        # but we recommend that you pass an object using the emails key.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $Emails
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/user/emails"
        Method      = 'POST'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Emails/Add-GitHubUserEmail.ps1] - Done"
#endregion - From public/Users/Emails/Add-GitHubUserEmail.ps1
#region - From public/Users/Emails/Get-GitHubUserEmail.ps1
Write-Verbose "[$scriptName] - [public/Users/Emails/Get-GitHubUserEmail.ps1] - Importing"

filter Get-GitHubUserEmail {
    <#
        .SYNOPSIS
        List email addresses for the authenticated user

        .DESCRIPTION
        Lists all of your email addresses, and specifies which one is visible to the public. This endpoint is accessible with the `user:email` scope.

        .EXAMPLE
        Get-GitHubUserEmail

        Gets all email addresses for the authenticated user.

        .NOTES
        https://docs.github.com/rest/users/emails#list-email-addresses-for-the-authenticated-user

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # The number of results per page (max 100).
        [Parameter()]
        [int] $PerPage = 30
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/user/emails"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Emails/Get-GitHubUserEmail.ps1] - Done"
#endregion - From public/Users/Emails/Get-GitHubUserEmail.ps1
#region - From public/Users/Emails/Remove-GitHubUserEmail.ps1
Write-Verbose "[$scriptName] - [public/Users/Emails/Remove-GitHubUserEmail.ps1] - Importing"

filter Remove-GitHubUserEmail {
    <#
        .SYNOPSIS
        Delete an email address for the authenticated user

        .DESCRIPTION
        This endpoint is accessible with the `user` scope.

        .EXAMPLE
        Remove-GitHubUserEmail -Emails 'octocat@github.com','firstname.lastname@work.com'

        Removes the email addresses 'octocat@github.com' and 'firstname.lastname@work.com' from the authenticated user's account.

        .NOTES
        https://docs.github.com/rest/users/emails#delete-an-email-address-for-the-authenticated-user

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        # Email addresses associated with the GitHub user account.
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [string[]] $Emails
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = "/user/emails"
        Method      = 'DELETE'
        Body        = $body
    }

    $null = (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Emails/Remove-GitHubUserEmail.ps1] - Done"
#endregion - From public/Users/Emails/Remove-GitHubUserEmail.ps1

Write-Verbose "[$scriptName] - [public/Users/Emails] - Done"
#endregion - From public/Users/Emails

#region - From public/Users/Social-Accounts
Write-Verbose "[$scriptName] - [public/Users/Social-Accounts] - Processing folder"

#region - From public/Users/Social-Accounts/Add-GitHubUserSocials.ps1
Write-Verbose "[$scriptName] - [public/Users/Social-Accounts/Add-GitHubUserSocials.ps1] - Importing"

filter Add-GitHubUserSocials {
    <#
        .SYNOPSIS
        Add social accounts for the authenticated user

        .DESCRIPTION
        Add one or more social accounts to the authenticated user's profile. This endpoint is accessible with the `user` scope.

        .EXAMPLE
        Add-GitHubUserSocials -AccountUrls 'https://twitter.com/MyTwitterAccount', 'https://www.linkedin.com/company/MyCompany'

        Adds the Twitter and LinkedIn accounts to the authenticated user's profile.

        .NOTES
        https://docs.github.com/rest/users/social-accounts#add-social-accounts-for-the-authenticated-user
    #>

    [OutputType([void])]
    [CmdletBinding()]
    param (
        # Full URLs for the social media profiles to add.
        [Parameter(Mandatory)]
        [Alias('account_urls')]
        [string[]] $AccountUrls
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = '/user/social_accounts'
        Body        = $body
        Method      = 'POST'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Social-Accounts/Add-GitHubUserSocials.ps1] - Done"
#endregion - From public/Users/Social-Accounts/Add-GitHubUserSocials.ps1
#region - From public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1
Write-Verbose "[$scriptName] - [public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1] - Importing"

filter Remove-GitHubUserSocials {
    <#
        .SYNOPSIS
        Delete social accounts for the authenticated user

        .DESCRIPTION
        Deletes one or more social accounts from the authenticated user's profile. This endpoint is accessible with the `user` scope.

        .PARAMETER AccountUrls
        Parameter description

        .EXAMPLE
        Remove-GitHubUserSocials -AccountUrls 'https://twitter.com/MyTwitterAccount'

        .NOTES
        https://docs.github.com/rest/users/social-accounts#delete-social-accounts-for-the-authenticated-user
    #>

    [OutputType([void])]
    [CmdletBinding()]
    param (
        # Full URLs for the social media profiles to add.
        [Parameter(Mandatory)]
        [Alias('account_urls')]
        [string[]] $AccountUrls
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = '/user/social_accounts'
        Body        = $body
        Method      = 'DELETE'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1] - Done"
#endregion - From public/Users/Social-Accounts/Remove-GitHubUserSocials.ps1

Write-Verbose "[$scriptName] - [public/Users/Social-Accounts] - Done"
#endregion - From public/Users/Social-Accounts

#region - From public/Users/Get-GitHubUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUser.ps1] - Importing"

filter Get-GitHubUser {
    <#
        .SYNOPSIS
        List user(s)

        .DESCRIPTION
        Get the authenticated user - if no parameters are provided.
        Get a given user - if a username is provided.
        Lists all users, in the order that they signed up on GitHub - if '-All' is provided.

        .EXAMPLE
        Get-GitHubUser

        Get the authenticated user.

        .EXAMPLE
        Get-GitHubUser -Username 'octocat'

        Get the 'octocat' user.

        .EXAMPLE
        Get-GitHubUser -All -Since 17722253

        Get a list of users, starting with the user 'MariusStorhaug'.

        .NOTES
        https://docs.github.com/rest/users/users
    #>

    [OutputType([pscustomobject])]
    [CmdletBinding(DefaultParameterSetName = '__DefaultSet')]
    param (
        # The handle for the GitHub user account.
        [Parameter(
            Mandatory,
            ParameterSetName = 'NamedUser',
            ValueFromPipelineByPropertyName
        )]
        [string] $Username,

        # List all users. Use '-Since' to start at a specific user id.
        [Parameter(
            Mandatory,
            ParameterSetName = 'AllUsers'
        )]
        [switch] $All,

        # A user ID. Only return users with an ID greater than this ID.
        [Parameter(ParameterSetName = 'AllUsers')]
        [int] $Since = 0,

        # The number of results per page (max 100).
        [Parameter(ParameterSetName = 'AllUsers')]
        [int] $PerPage = 30
    )

    switch ($PSCmdlet.ParameterSetName) {
        '__DefaultSet' {
            $user = Get-GitHubMyUser
            $social_accounts = Get-GitHubMyUserSocials
            $user | Add-Member -MemberType NoteProperty -Name 'social_accounts' -Value $social_accounts -Force
            $user
        }
        'NamedUser' {
            $user = Get-GitHubUserByName -Username $Username
            $social_accounts = Get-GitHubUserSocialsByName -Username $Username
            $user | Add-Member -MemberType NoteProperty -Name 'social_accounts' -Value $social_accounts -Force
            $user
        }
        'AllUsers' {
            Get-GitHubAllUsers -Since $Since -PerPage $PerPage
        }
    }
}

Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUser.ps1] - Done"
#endregion - From public/Users/Get-GitHubUser.ps1
#region - From public/Users/Get-GitHubUserCard.ps1
Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserCard.ps1] - Importing"

filter Get-GitHubUserCard {
    <#
        .SYNOPSIS
        Get contextual information for a user

        .DESCRIPTION
        Provides hovercard information when authenticated through basic auth or OAuth with the `repo` scope. You can find out more about someone in relation to their pull requests, issues, repositories, and organizations.

        The `subject_type` and `subject_id` parameters provide context for the person's hovercard, which returns more information than without the parameters. For example, if you wanted to find out more about `octocat` who owns the `Spoon-Knife` repository via cURL, it would look like this:

        ```shell
        curl -u username:token
        https://api.github.com/users/octocat/hovercard?subject_type=repository&subject_id=1300192
        ```

        .EXAMPLE

        .NOTES
        https://docs.github.com/rest/users/users#get-contextual-information-for-a-user

    #>

    [OutputType([pscustomobject])]
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory,
            ValueFromPipeline,
            ValueFromPipelineByPropertyName
        )]
        [string] $Username,
        [Parameter()]
        [ValidateSet('organization', 'repository', 'issue', 'pull_request')]
        [string] $SubjectType,
        [Parameter()]
        [int] $SubjectID = ''
    )

    $body = @{
        subject_type = $SubjectType
        subject_id   = $SubjectID
    }

    $inputObject = @{
        APIEndpoint = "/users/$Username/hovercard"
        Method      = 'GET'
        Body        = $body
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Get-GitHubUserCard.ps1] - Done"
#endregion - From public/Users/Get-GitHubUserCard.ps1
#region - From public/Users/Set-GitHubUser.ps1
Write-Verbose "[$scriptName] - [public/Users/Set-GitHubUser.ps1] - Importing"

filter Set-GitHubUser {
    <#
        .SYNOPSIS
        Update the authenticated user

        .DESCRIPTION
        **Note:** If your email is set to private and you send an `email` parameter as part of this request
        to update your profile, your privacy settings are still enforced: the email address will not be
        displayed on your public profile or via the API.

        .EXAMPLE
        Set-GitHubUser -Name 'octocat'

        Update the authenticated user's name to 'octocat'

        .EXAMPLE
        Set-GitHubUser -Location 'San Francisco'

        Update the authenticated user's location to 'San Francisco'

        .EXAMPLE
        Set-GitHubUser -Hireable $true -Bio 'I love programming'

        Update the authenticated user's hiring availability to 'true' and their biography to 'I love programming'

        .NOTES
        https://docs.github.com/rest/users/users#update-the-authenticated-user
    #>

    [OutputType([void])]
    [Alias('Update-GitHubUser')]
    [CmdletBinding()]
    param (
        # The new name of the user.
        [Parameter()]
        [string] $Name,

        # The publicly visible email address of the user.
        [Parameter()]
        [string] $Email,

        # The new blog URL of the user.
        [Parameter()]
        [string] $Blog,

        # The new Twitter username of the user.
        [Parameter()]
        [string] $TwitterUsername,

        # The new company of the user.
        [Parameter()]
        [string] $Company,

        # The new location of the user.
        [Parameter()]
        [string] $Location,

        # The new hiring availability of the user.
        [Parameter()]
        [boolean] $Hireable,

        # The new short biography of the user.
        [Parameter()]
        [string] $Bio
    )

    $body = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable -NameCasingStyle snake_case

    $inputObject = @{
        APIEndpoint = '/user'
        Body        = $body
        Method      = 'PATCH'
    }

    (Invoke-GitHubAPI @inputObject).Response

}

Write-Verbose "[$scriptName] - [public/Users/Set-GitHubUser.ps1] - Done"
#endregion - From public/Users/Set-GitHubUser.ps1

Write-Verbose "[$scriptName] - [public/Users] - Done"
#endregion - From public/Users


Write-Verbose "[$scriptName] - [public] - Done"
#endregion - From public

#region - From GitHub.ps1
Write-Verbose "[$scriptName] - [GitHub.ps1] - Importing"

$scriptFilePath = $MyInvocation.MyCommand.Path

Write-Verbose "[$scriptFilePath] - Initializing GitHub module..."

Initialize-SecretVault -Name $script:SecretVault.Name -Type $script:SecretVault.Type

# Autologon if a token is present in environment variables
$envVar = Get-ChildItem -Path 'Env:' | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1
$envVarPresent = $envVar.count -gt 0
if ($envVarPresent) {
    Connect-GitHubAccount
}
Write-Verbose "[$scriptName] - [GitHub.ps1] - Done"
#endregion - From GitHub.ps1

Export-ModuleMember -Function 'Disable-GitHubWorkflow','Enable-GitHubWorkflow','Get-GitHubWorkflow','Get-GitHubWorkflowRun','Get-GitHubWorkflowUsage','Remove-GitHubWorkflowRun','Start-GitHubWorkflow','Start-GitHubWorkflowReRun','Stop-GitHubWorkflowRun','Invoke-GitHubAPI','Connect-GitHubAccount','Disconnect-GitHubAccount','Get-GitHubRepoBranch','Get-GitHubConfig','Set-GitHubConfig','Get-GitHubEnvironment','Get-GitHubEnvironmentSecrets','Update-GitHubEnvironment','Get-GitHubEmojis','Get-GitHubMarkdown','Get-GitHubMarkdownRaw','Get-GitHubApiVersions','Get-GitHubMeta','Get-GitHubOctocat','Get-GitHubRoot','Get-GitHubZen','Get-GitHubOrganization','Get-GitHubOrganizationAppInstallation','Remove-GitHubOrganization','Set-GitHubOrganization','Set-GitHubOrganizationSecurityFeature','Get-GitHubScheduledMaintenance','Get-GitHubStatus','Get-GitHubStatusComponents','Get-GitHubStatusIncidents','Get-GitHubRepoTeam','Block-GitHubUser','Get-GitHubBlockedUser','Test-GitHubBlockedUser','Unblock-GitHubUser','Add-GitHubUserEmail','Get-GitHubUserEmail','Remove-GitHubUserEmail','Add-GitHubUserSocials','Remove-GitHubUserSocials','Get-GitHubUser','Get-GitHubUserCard','Set-GitHubUser' -Cmdlet '' -Variable '' -Alias '*'