Functions/GenXdev.Console.Spotify/Get-SpotifyLyrics.ps1
################################################################################ <# .SYNOPSIS Retrieves lyrics for Spotify tracks from Musixmatch.com .DESCRIPTION Searches for and displays song lyrics by either: - Using a Spotify track ID - Searching for tracks by name/artist - Getting lyrics for currently playing track If lyrics aren't found on Musixmatch, opens a Google search as fallback. .PARAMETER TrackId The Spotify track ID to look up lyrics for. If omitted, uses currently playing track or allows searching by name. .PARAMETER Queries Search terms to find a track. Can include artist name and/or song title. Results will be shown for selection. .EXAMPLE Get-SpotifyLyrics -TrackId "1301WleyT98MSxVHPZCA6M" .EXAMPLE lyrics "bohemian rhapsody queen" #> function Get-SpotifyLyrics { [CmdLetBinding(DefaultParameterSetName = "")] [Alias("lyrics")] param( ######################################################################## [parameter( Mandatory = $false, ValueFromPipelineByPropertyName, ParameterSetName = "", HelpMessage = "Spotify track ID to lookup lyrics for" )] [Alias("Id")] [string] $TrackId = $null, ######################################################################## [parameter( Mandatory = $false, Position = 0, ValueFromRemainingArguments, ValueFromPipeline, ValueFromPipelineByPropertyName, HelpMessage = "Search terms to find a track" )] [Alias("q", "Value", "Name", "Text", "Query")] [string[]] $Queries = $null ######################################################################## ) begin { # handle track search if queries provided if ($null -ne $Queries) { Write-Verbose "Searching Spotify for tracks matching query: $Queries" # search spotify and build list of track names with artists $results = Search-Spotify -SearchType Track -Queries $Queries $new = [System.Collections.Generic.List[string]]::new() foreach ($track in $results.Tracks.Items) { $new.Add("$($track.Artists[0].Name) - $($track.Name)") } $Queries = $new if ($new.Count -eq 0) { Write-Warning "No tracks found matching search terms" } } else { # use track ID if provided if ([String]::IsNullOrWhiteSpace($TrackId) -eq $false) { Write-Verbose "Looking up track by ID: $TrackId" $track = Get-SpotifyTrackById -TrackId $TrackId if ($null -ne $track) { $Queries = @("$($track.Artists[0].Name) - $($track.Name)") } } else { # get currently playing track Write-Verbose "Getting currently playing track" $current = Get-SpotifyCurrentlyPlaying if ($null -ne $current) { $Queries = @("$($current.Item.Artists[0].Name) - " + ` "$($current.Item.Name)") } } } if ($null -eq $Queries) { throw "No song playing and no search terms provided" } } process { foreach ($query in $Queries) { Write-Verbose "Searching Musixmatch for lyrics: $query" # encode query for URL $q = [Uri]::EscapeUriString($query) [string] $html = "" # attempt to get search results page try { $html = Invoke-WebRequest ` -Uri "https://www.musixmatch.com/search/$q" ` -ErrorAction SilentlyContinue } catch { Write-Warning "No results found for '$query'" Open-GoogleQuery "lyrics $query" continue } # extract best match URL from search results [int] $idx = $html.IndexOf("Best Result") if ($idx -lt 0) { Write-Warning "No results found for '$query'" Open-GoogleQuery "lyrics $query" continue } $idx = $html.IndexOf('<a class="title" href="', $idx) if ($idx -lt 0) { Write-Warning "No results found for '$query'" Open-GoogleQuery "lyrics $query" continue } $idx += '<a class="title" href="'.Length [int] $idx2 = $html.IndexOf('"', $idx) if ($idx2 -lt 0) { Write-Warning "No results found for '$query'" Open-GoogleQuery "lyrics $query" continue } # get lyrics page $url = "https://www.musixmatch.com$($html.Substring($idx, $idx2-$idx))" Write-Verbose "Fetching lyrics from: $url" try { $html = Invoke-WebRequest -Uri $url -ErrorAction SilentlyContinue } catch { Write-Warning "Failed to get lyrics for '$query'" Open-GoogleQuery "lyrics $query" continue } # extract lyrics from page $idx = $html.IndexOf('"body":"') if ($idx -lt 0) { Write-Warning "No lyrics found for '$query'" Open-GoogleQuery "lyrics $query" continue } $idx += '"body":"'.Length $idx2 = $html.IndexOf('","language":', $idx) if ($idx2 -lt 0) { Write-Warning "No lyrics found for '$query'" Open-GoogleQuery "lyrics $query" continue } # parse and clean up lyrics $result = "`"$($html.Substring($idx, $idx2-$idx))`"" | ConvertFrom-Json if ([String]::IsNullOrWhiteSpace($result)) { Write-Warning "Empty lyrics found for '$query'" Open-GoogleQuery "lyrics $query" } $result.Replace("???", "'") } } } ################################################################################ |