Public/Get-ShellPhishSongFrequency.ps1

function Get-ShellPhishSongFrequency {
    <#
    .SYNOPSIS
        Counts how many times each song was played in a given year or all-time.
    .PARAMETER Year
        Four-digit year to analyze. Omit for all-time.
    .PARAMETER Top
        Show only the top N songs. Default: all.
    .PARAMETER ExportPath
        Optional file path (.csv or .json) to export results.
    .PARAMETER DelayMs
        Delay in milliseconds between API calls. Default 500.
    .EXAMPLE
        PS C:\> Get-ShellPhishSongFrequency -Year 1997 -Top 20
    .EXAMPLE
        PS C:\> Get-ShellPhishSongFrequency -Year 2024 -ExportPath ./freq-2024.csv
    #>

    [CmdletBinding()]
    param (
        [Parameter()]
        [ValidatePattern('^\d{4}$')]
        [string]$Year,

        [Parameter()]
        [int]$Top,

        [Parameter()]
        [string]$ExportPath,

        [Parameter()]
        [int]$DelayMs = 500
    )

    if ($Year) {
        Write-Verbose "Fetching shows for $Year..."
        $shows = (Get-ShellPhishShows -Year $Year -OrderBy showdate -Direction asc).data
    }
    else {
        Write-Verbose "Fetching all Phish shows..."
        $shows = (Get-ShellPhishShows -Artist phish -OrderBy showdate -Direction asc).data
    }

    if (-not $shows) {
        Write-Warning "No shows found"
        return
    }

    Write-Verbose "Found $($shows.Count) show(s). Fetching setlists..."
    $allSongs = @()
    foreach ($show in $shows) {
        Start-Sleep -Milliseconds $DelayMs
        $setlist = (Get-ShellPhishSetlists -ShowDate $show.showdate).data
        if ($setlist) {
            foreach ($entry in $setlist) {
                $allSongs += [PSCustomObject]@{
                    Song     = $entry.song
                    Slug     = $entry.slug
                    ShowDate = $show.showdate
                }
            }
        }
    }

    $grouped = $allSongs | Group-Object -Property Song | ForEach-Object {
        [PSCustomObject]@{
            Song       = $_.Name
            TimePlayed = $_.Count
        }
    } | Sort-Object TimePlayed -Descending

    if ($Top) {
        $grouped = $grouped | Select-Object -First $Top
    }

    Export-ShellPhishData -Data $grouped -ExportPath $ExportPath
}