Public/Add-SpotifyTracks.ps1

<#
.SYNOPSIS
Adds songs to your Spotify liked tracks

.DESCRIPTION
Accepts a list of tracks from a CSV or from another cmdlet in this module,
searches for those songs on Spotify, and adds them to your Spotify liked tracks
if found.

.PARAMETER Tracks
Mutually exclusive with InputFile. An array of SpotifyTracks, as generated by
another cmdlet in this module, such as Get-TracksFromFolder or
Get-SpotifyTracks.

.PARAMETER InputFile
Mutually exclusive with Tracks. The Path to a CSV file containing a list of
tracks, where each track has values for three columns: name (song name), artists
(a comma-separated list of artist names), and album (album name).

.PARAMETER ClientId
Optional. The ClientId of the app you registered in the Spotify developer
portal. See the 'Authentication' section at
https://github.com/niwamo/SpotifyUtils

.PARAMETER RedirectURI
Optional. The redirect URI used for OAuth authentication. Must match what is
configured in the Spotify developer protal. See the 'Authentication' section at
https://github.com/niwamo/SpotifyUtils

.PARAMETER ConfigFile
Optional. The path to a JSON configuration file containing 'ClientId' and
'RedirectURI' properties. See the 'Authentication' section at
https://github.com/niwamo/SpotifyUtils

.EXAMPLE
Add-SpotifyTracks -Tracks $(Get-TracksFromFolder -Path ~\Songs)
#>

function Add-SpotifyTracks {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$false, ValueFromPipeline=$true)]
        [Object[]] $Tracks,

        [ValidateScript({ Test-Path $_ })]
        [Parameter(Mandatory=$false)]
        [string] $InputFile,

        [Parameter(Mandatory=$false)]
        [string] $ClientId,

        [Parameter(Mandatory=$false)]
        [string] $RedirectURI,

        [ValidateScript({Test-Path $_})]
        [Parameter(Mandatory=$false)]
        [string] $ConfigFile
    )
    
    begin {
        Set-StrictMode -Version 1.0
        $ErrorActionPreference = 'Stop'
        $inputData = [System.Collections.ArrayList]::new()
    }

    process {
        if (!$Tracks -and !$InputFile) {
            throw "Either 'Tracks' or 'InputFile' required"
        }
        elseif ($Tracks) {
            $inputData.AddRange([array] $Tracks) | Out-Null
        }
        elseif ($InputFile.Substring($InputFile.Length-3, 3) -ne 'csv') {
            throw 'Only CSV files are supported for InputFile'
        }
        else {
            Write-Debug "Importing tracks from CSV"
            $inputData = Import-Csv -Path $InputFile
        }
    }
  
    end {
        Write-Debug (
            "Received $($inputData.Count) tracks to add"
        )
        $tracks = ConvertTo-SpotifyTrack -Tracks $inputData
        return
        
        # authorization
        $TokenParams = @{
            Scopes      = @('user-library-modify')
        }
        foreach ($param in @('ClientId', 'RedirectURI', 'ConfigFile')) {
            if ($PSBoundParameters.ContainsKey($param)) {
                $TokenParams.Add($param, $PSBoundParameters.TryGetValue($param))
            }
        }
        try {
            $token = Get-SpotifyToken @TokenParams
        }
        catch {
            Write-Error (
                "There was a problem authenticating to the Spotify API.`n" +
                "Please review the Authentication section at https://github.com/niwamo/SpotifyUtils.`n" +
                "Error message: " + $_.Exception.Message
            )
        }
        $headers = @{ Authorization = "Bearer $token" }

        ##########################
        # Region: Add Tracks #
        ##########################

        $missing = [System.Collections.ArrayList]::new()
        foreach ($song in $tracks) {
            Write-Debug "Trying to add $($song.name) by $($song.artists[0])"
            # https://stackoverflow.com/questions/73680222
            $uri = "$($script:SEARCH_URI)?type=track&q=artist:""$($song.artists[0])"" track:""$($song.name)"""
            $results = (Invoke-WebRequest -Uri $uri -Headers $headers).Content | ConvertFrom-Json
            $top = $results.tracks.items[0]

            Write-Debug "top: $($top | ConvertTo-Json -Depth 5)"

            if ($top.name -eq $song.name -and $top.artists[0].name -eq $song.artists[0]) {
                $params = @{
                    URI         = "$script:MYTRACKS_URI"
                    Method      = 'Put'
                    ContentType = 'application/json'
                    #Body = @{ids=@($top.id)}
                    Body        = "{""ids"":[""$($top.id)""]}"
                    Headers     = $headers
                }

                Write-Debug "params: $($params | ConvertTo-Json -Depth 5)"

                Invoke-WebRequest @params | Out-Null
                Write-Debug "Added $($song.name)"
            }
            else {
                Write-Debug "Could not find $($song.name)"
                $missing.Add($song) | Out-Null
            }

            [System.Threading.Thread]::Sleep($script:API_DELAY)
        }

        if ($missing.Count) {
            Write-Warning "Failed to add $($missing.Count) tracks, returning them in an array"
            return $missing
        }
    }
}