Generic/Github.ps1

<#
.SYNOPSIS
    Gets the download URL of an artifact from the latest GitHub release.
.PARAMETER Owner
    The repository owner (e.g., SagerNet).
.PARAMETER Repo
    The repository name (e.g., sing-box).
.PARAMETER AssetNamePattern
    The wildcard pattern for the artifact name (e.g., '*windows-amd64.zip').
.OUTPUTS
    A string with the download URL.
#>

function Get-GitHubLatestReleaseAssetUrl {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string] $Owner,
        
        [Parameter(Mandatory)]
        [string] $Repo,
        
        [Parameter(Mandatory)]
        [string] $AssetNamePattern
    )

    $apiUrl = "https://api.github.com/repos/$Owner/$Repo/releases/latest"

    try {
        $release = Invoke-RestMethod -Uri $apiUrl -UseBasicParsing -ErrorAction Stop
    }
    catch {
        throw "Failed to get release data: $_"
    }

    $asset = $release.assets | Where-Object { $_.name -like $AssetNamePattern } | Select-Object -First 1

    if (-not $asset) {
        throw "Asset with pattern '$AssetNamePattern' not found in the latest release."
    }

    return $asset.browser_download_url
}

function Get-GithubReleaseVersions {
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory, Position = 0)]
        [string] $OwnerRepo,        # Format "owner/repo", e.g. "PowerShell/PowerShell"

        [Parameter(Position = 1)]
        [switch] $IncludePrerelease, # If set, includes prereleases; otherwise only full releases

        [Parameter()]
        [string] $GitHubToken       # (Optional) Personal token to avoid anonymous rate limits
    )

    Begin {
        # Base API URL for releases
        $apiUrl = "https://api.github.com/repos/$OwnerRepo/releases"

        # Prepare request headers
        $headers = @{
            'User-Agent'    = 'PowerShell'
            'Accept'        = 'application/vnd.github.v3+json'
        }
        if ($GitHubToken) {
            $headers['Authorization'] = "token $GitHubToken"
        }
    }

    Process {
        try {
            # Fetch all releases from GitHub API
            $releases = Invoke-RestMethod -Uri $apiUrl -Headers $headers -ErrorAction Stop

            # Filter out prereleases unless requested
            if (-not $IncludePrerelease) {
                $releases = $releases | Where-Object { -not $_.prerelease }
            }

            # Select and sort the relevant properties
            $releases |
                Select-Object `
                    @{Name='Tag';         Expression = { $_.tag_name }}, `
                    @{Name='Prerelease';  Expression = { $_.prerelease }}, `
                    @{Name='Name';        Expression = { $_.name }}, `
                    @{Name='PublishedAt'; Expression = { [DateTime]$_.published_at } } `
                | Sort-Object PublishedAt -Descending
        }
        catch {
            Write-Error "Failed to retrieve releases from https://github.com/{$OwnerRepo}: $_"
        }
    }
}