GenXdev.Console.Spotify.psm1
############################################################################### <# .SYNOPSIS Performs a Spotify search and plays the first found item .DESCRIPTION Performs a Spotify search and plays the first found item on the active device .PARAMETER Queries The search phrase .PARAMETER SearchType Optionally, the type of item to search for .EXAMPLE PS C:\> Search-SpotifyAndPlay Rage against the machine .EXAMPLE PS C:\> fmp Dire Straits You and your friend #> function Search-SpotifyAndPlay { [Alias("smp", "fmp")] param( [Alias("q", "Value", "Name", "Text", "Query")] [parameter( Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string[]] $Queries, [Alias("t")] [ValidateSet("Album", "Artist", "Playlist", "Track", "Show", "Episode", "All")] [parameter(Mandatory = $false)] [string[]] $SearchType = @("Track") ) begin { $Queries = Build-InvocationArguments $MyInvocation $Queries [int] $SearchTypeTypeId = 0; if ($SearchType -contains "Album") { $SearchTypeTypeId += 1 } if ($SearchType -contains "Artist") { $SearchTypeTypeId += 2 } if ($SearchType -contains "Playlist") { $SearchTypeTypeId += 4 } if ($SearchType -contains "Track") { $SearchTypeTypeId += 8 } if ($SearchType -contains "Show") { $SearchTypeTypeId += 16 } if ($SearchType -contains "Episode") { $SearchTypeTypeId += 32 } if ($SearchType -contains "All") { $SearchTypeTypeId += 63 } } process { foreach ($Query in $Queries) { [GenXdev.Helpers.Spotify]::SearchAndPlay((Get-SpotifyApiToken), $Query, $SearchTypeTypeId) | ForEach-Object { if ($null -ne $PSItem) { $PSItem } } -ErrorAction SilentlyContinue } } } ############################################################################### <# .SYNOPSIS Performs a Spotify search and adds the first item to the queue .DESCRIPTION Performs a Spotify search and adds the first item to the queue .PARAMETER Queries The search phrase .PARAMETER SearchType Optionally, the type of item to search for .EXAMPLE PS C:\> Search-SpotifyAndEnqueue Rage against the machine .EXAMPLE PS C:\> fmq Dire Straits You and your friend #> function Search-SpotifyAndEnqueue { [Alias("smq", "fmq")] param( [Alias("q", "Value", "Name", "Text", "Query")] [parameter( Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string[]] $Queries, [Alias("t")] [ValidateSet("Album", "Artist", "Playlist", "Track", "Show", "Episode", "All")] [parameter(Mandatory = $false)] [string[]] $SearchType = @("Track") ) begin { $Queries = Build-InvocationArguments $MyInvocation $Queries [int] $SearchTypeTypeId = 0; if ($SearchType -contains "Album") { $SearchTypeTypeId += 1 } if ($SearchType -contains "Artist") { $SearchTypeTypeId += 2 } if ($SearchType -contains "Playlist") { $SearchTypeTypeId += 4 } if ($SearchType -contains "Track") { $SearchTypeTypeId += 8 } if ($SearchType -contains "Show") { $SearchTypeTypeId += 16 } if ($SearchType -contains "Episode") { $SearchTypeTypeId += 32 } if ($SearchType -contains "All") { $SearchTypeTypeId += 63 } } process { foreach ($Query in $Queries) { [GenXdev.Helpers.Spotify]::SearchAndAdd((Get-SpotifyApiToken), $Query, $SearchTypeTypeId) | ForEach-Object { if ($null -ne $PSItem) { $PSItem } } -ErrorAction SilentlyContinue } } } ############################################################################### <# .SYNOPSIS Performs a Spotify search and returns the search results .DESCRIPTION Performs a Spotify search and returns the search results .PARAMETER Queries The search phrase .PARAMETER SearchType Optionally, the type of item to search for .EXAMPLE PS C:\> Search-Spotify Rage against the machine .EXAMPLE PS C:\> fm Dire Straits You and your friend #> function Search-Spotify { [Alias("sm", "fm")] param( [Alias("q", "Value", "Name", "Text", "Query")] [parameter( Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string[]] $Queries, [Alias("t")] [ValidateSet("Album", "Artist", "Playlist", "Track", "Show", "Episode", "All")] [parameter(Mandatory = $false)] [string[]] $SearchType = @("Track") ) begin { $Queries = Build-InvocationArguments $MyInvocation $Queries [int] $SearchTypeTypeId = 0; if ($SearchType -contains "Album") { $SearchTypeTypeId += 1 } if ($SearchType -contains "Artist") { $SearchTypeTypeId += 2 } if ($SearchType -contains "Playlist") { $SearchTypeTypeId += 4 } if ($SearchType -contains "Track") { $SearchTypeTypeId += 8 } if ($SearchType -contains "Show") { $SearchTypeTypeId += 16 } if ($SearchType -contains "Episode") { $SearchTypeTypeId += 32 } if ($SearchType -contains "All") { $SearchTypeTypeId += 63 } } process { foreach ($Query in $Queries) { [GenXdev.Helpers.Spotify]::Search((Get-SpotifyApiToken), $Query, $SearchTypeTypeId) | ForEach-Object { $PSItem } -ErrorAction SilentlyContinue } } } ############################################################################### <# .SYNOPSIS Starts Spotify playback .DESCRIPTION Starts playback on the device that is active on Spotify #> function Set-SpotifyStart { [Alias("play", "Start-Music")] param() [GenXdev.Helpers.Spotify]::Start((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Pauses Spotify playback .DESCRIPTION Pauses playback on the device that is active on Spotify #> function Set-SpotifyPause { [Alias("pausemusic", "Resume-Music")] param() [GenXdev.Helpers.Spotify]::Pause((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Stops Spotify playback .DESCRIPTION Stops playback on the device that is active on Spotify #> function Set-SpotifyStop { [Alias("stop", "Stop-Music")] param() [GenXdev.Helpers.Spotify]::Stop((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Skips to previous track on Spotify .DESCRIPTION Skips to previous track on the device that is active on Spotify #> function Set-SpotifyPrevious { [Alias("previous", "prev")] param() [GenXdev.Helpers.Spotify]::Previous((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Skips to next track on Spotify .DESCRIPTION Skips to next track on the device that is active on Spotify #> function Set-SpotifyNext { [Alias("next", "skip")] param() [GenXdev.Helpers.Spotify]::Next((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Enables Spotify song-repeat .DESCRIPTION Enables song-repeat on the device that is active on Spotify #> function Set-SpotifyRepeatSong { [CmdletBinding()] [Alias("repeatsong")] param() [GenXdev.Helpers.Spotify]::RepeatSong((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Enables Spotify playlist-repeat .DESCRIPTION Enables playlist-repeat on the device that is active on Spotify #> function Set-SpotifyRepeatContext { [CmdletBinding()] [Alias("repeat")] param() [GenXdev.Helpers.Spotify]::RepeatContext((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Disables Spotify repeat .DESCRIPTION Disables repeat on the device that is active on Spotify #> function Set-SpotifyRepeatOff { [Alias("norepeat", "repeatoff")] param() [GenXdev.Helpers.Spotify]::RepeatOff((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Enables Spotify song-shuffle .DESCRIPTION Enables song-shuffle on the device that is active on Spotify #> function Set-SpotifyShuffleOn { [Alias("shuffle", "shuffleon")] param() [GenXdev.Helpers.Spotify]::ShuffleOn((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Disables Spotify song-shuffle .DESCRIPTION Disables song-shuffle on the device that is active on Spotify #> function Set-SpotifyShuffleOff { [Alias("noshuffle", "shuffleoff")] param() [GenXdev.Helpers.Spotify]::ShuffleOff((Get-SpotifyApiToken)); } ############################################################################### <# .SYNOPSIS Returns a fully populated collection of Spotify playlists owned by current user .DESCRIPTION Returns a fully populated collection of Spotify playlists owned by current user .EXAMPLE PS C:\> $playLists = Get-SpotifyUserPlaylists; $playLists.Tracks.Items.Track.Name .EXAMPLE PS C:\> (upl).Tracks.Items.Track.Name #> function Get-SpotifyUserPlaylists { [CmdletBinding()] [Alias("gupl")] param( [Alias("Uri", "Id", "Name")] [parameter( Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string[]] $Filter = @("*"), [switch] $Force ) begin { $apiToken = Get-SpotifyApiToken; $Filter = Build-InvocationArguments $MyInvocation $Filter $filePath = Expand-Path "$PSScriptRoot\..\..\GenXdev.Local\Spotify.Playlists.json" } process { [System.Collections.Generic.List[Object]] $SpotifyPlaylistCache = $null; if ($Force -ne $true) { if ($null -eq $Global:SpotifyPlaylistCache) { $filePath = Expand-Path "$PSScriptRoot\..\..\GenXdev.Local\Spotify.Playlists.json" $playlistCache = [System.IO.FileInfo]::new($filePath); if ($playlistCache.Exists -and ([datetime]::Now - $playlistCache.LastWriteTime -lt [timespan]::FromHours(12))) { $SpotifyPlaylistCache = $playlistCache.OpenText().ReadToEnd() | ConvertFrom-Json -Depth 100 Set-Variable -Name SpotifyPlaylistCache -Value $SpotifyPlaylistCache -Scope Global -Force } } } if (($Force -eq $true) -or ($null -eq $Global:SpotifyPlaylistCache) -or ( $Global:SpotifyPlaylistCache.Count -eq 0)) { $SpotifyPlaylistCache = [GenXdev.Helpers.Spotify]::GetUserPlaylists($apiToken, "*"); Set-Variable -Name SpotifyPlaylistCache -Value $SpotifyPlaylistCache -Scope Global -Force $SpotifyPlaylistCache | ConvertTo-Json -Depth 100 | Out-File $filePath -Force } $Global:SpotifyPlaylistCache | ForEach-Object -ErrorAction SilentlyContinue { if ($PSItem.Name -like $Filter) { $PSItem } } } end { } } ############################################################################### <# .SYNOPSIS Adds tracks to a Spotify playlist .DESCRIPTION Adds tracks to a Spotify playlist .PARAMETER PlaylistId The Spotify playlist to add tracks to .PARAMETER Uri The Spotify tracks that should be added to the playlist #> function Add-SpotifyTracksToPlaylist { [CmdletBinding(DefaultParameterSetName = "ByName")] [Alias("addtoplaylist")] param( [Alias("Name")] [parameter( ParameterSetName = "ByName", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to add tracks to" )] [string[]] $PlaylistName, [parameter( ParameterSetName = "ById", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to add tracks to" )] [string[]] $PlaylistId, [parameter( Mandatory = $false, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify tracks that should be added to the playlist" )] [string[]] $Uri = @() ) begin { $apiToken = Get-SpotifyApiToken; if ($PlaylistName.Length -gt 0) { $PlaylistId = @(Get-SpotifyPlaylistIdsByName -PlaylistName @($PlaylistName)) } } process { foreach ($Id in $PlaylistId) { [GenXdev.Helpers.Spotify]::AddToPlaylist($apiToken, $Id, $Uri); } } end { } } ############################################################################### <# .SYNOPSIS Creates a new Spotify playlist .DESCRIPTION Creates a new Spotify playlist .PARAMETER Name The name for the new playlist .PARAMETER Description The description for the new playlist .PARAMETER Public Make this a public playlist .PARAMETER Collabrative Allow others to make changes #> function Add-SpotifyNewPlaylist { [CmdletBinding()] [Alias("newplaylist")] param( [parameter( Mandatory, Position = 0, HelpMessage = "The name for the new playlist" )] [string] $Name, [parameter( Mandatory = $false, Position = 1, HelpMessage = "The description for the new playlist" )] [string] $Description = "", [parameter( Mandatory = $false, HelpMessage = "Make this a public playlist" )] [switch] $Public, [parameter( Mandatory = $false, HelpMessage = "Allow others to make changes" )] [switch] $Collabrative ) begin { $apiToken = Get-SpotifyApiToken; } process { $result = [GenXdev.Helpers.Spotify]::NewPlaylist($apiToken, $Name, $Description, ($Public -eq $true), ($Collabrative -eq $true)); if ($Global:SpotifyPlaylistCache -is [System.Collections.Generic.List[object]]) { $Global:SpotifyPlaylistCache.Insert(0, $result); $filePath = Expand-Path "$PSScriptRoot\..\..\GenXdev.Local\Spotify.Playlists.json" $Global:SpotifyPlaylistCache | ConvertTo-Json -Depth 100 | Out-File $filePath -Force } $result } end { } } ############################################################################### <# .SYNOPSIS Sets the main properties of a Spotify playlist .DESCRIPTION Sets the main properties of a Spotify playlist .PARAMETER PlaylistId The Spotify playlist to set properties for .PARAMETER Name The new name for the playlist .PARAMETER Description The new description for the playlist .PARAMETER Public Make the playlist public .PARAMETER Collabrative Allow others to make changes .PARAMETER Private Make the playlist private .PARAMETER NoCollabrations Disallow others to make changes #> function Set-SpotifyPlaylistDetails { [CmdletBinding()] [Alias("spld")] param( [parameter( Mandatory, Position = 0, HelpMessage = "The Spotify playlist to make changes to" )] [string] $PlaylistId, [parameter( Mandatory, Position = 1, HelpMessage = "The name for the new playlist" )] [string] $Name, [parameter( Mandatory = $false, Position = 2, HelpMessage = "The description for the new playlist" )] [string] $Description = "", [parameter( Mandatory = $false, HelpMessage = "Make this a public playlist" )] [switch] $Public, [parameter( Mandatory = $false, HelpMessage = "Allow others to make changes to this playlist" )] [switch] $Collabrative, [parameter( Mandatory = $false, HelpMessage = "Make the playlist private" )] [switch] $Private, [parameter( Mandatory = $false, HelpMessage = "Disallow others to make changes" )] [switch] $NoCollabrations ) begin { $apiToken = Get-SpotifyApiToken; $P = $null; $C = $null; if ($Public -eq $true) { $P = $true } if ($Collabrative -eq $true) { $C = $true } if ($Private -eq $true) { $P = $false } if ($NoCollabrations -eq $true) { $C = $False } } process { [GenXdev.Helpers.Spotify]::ChangePlaylistDetails($PlaylistId, $apiToken, $Name, $P, $C, $Description); } end { } } ############################################################################### <# .SYNOPSIS Removes tracks from a Spotify playlist .DESCRIPTION Removes tracks from a Spotify playlist .PARAMETER PlaylistId The Spotify playlist to delete tracks from .PARAMETER Uri The Spotify tracks that should be removed from the playlist #> function Remove-SpotifyTracksFromPlaylist { [CmdletBinding(DefaultParameterSetName = "ByName")] [Alias("removefromplaylist")] param( [parameter( ParameterSetName="ByName", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to delete tracks from" )] [string[]] $PlaylistName, [parameter( ParameterSetName="ById", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to delete tracks from" )] [string[]] $PlaylistId, [parameter( Mandatory = $false, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify tracks that should be removed from the playlist" )] [string[]] $Uri = @() ) begin { $apiToken = Get-SpotifyApiToken; if ($PlaylistName.Length -gt 0) { $PlaylistId = @(Get-SpotifyPlaylistIdsByName -PlaylistName $PlaylistName) } } process { foreach ($Id in $PlaylistId) { [GenXdev.Helpers.Spotify]::RemoveFromPlaylist($apiToken, $Id, $Uri); } } end { } } ############################################################################### <# .SYNOPSIS Returns the currently on Spotify playing track .DESCRIPTION Returns the currently on Spotify playing track .EXAMPLE PS C:\> Get-SpotifyCurrentlyPlaying .EXAMPLE PS C:\> (gcp).Item #> function Get-SpotifyCurrentlyPlaying { [CmdletBinding()] [Alias("gcp")] param( ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetCurrentlyPlaying($apiToken); } end { } } ############################################################################### <# .SYNOPSIS Returns Spotify track audio feature information .DESCRIPTION Returns Spotify track audio feature information .PARAMETER Id The Spotify track to return audio features for #> function Get-SpotifyTrackAudioFeatures { [CmdletBinding()] [Alias("audiofeatures")] param( [Alias("Id")] [parameter( Mandatory, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify track to return audio features for" )] [string[]] $TrackId ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetSeveralAudioFeatures($apiToken, $TrackId); } end { } } ############################################################################### <# .SYNOPSIS Returns full Spotify track information by given TrackId .DESCRIPTION Returns full Spotify track information by given TrackId .PARAMETER TrackId The Spotify track id of the track to lookup #> function Get-SpotifyTrackById { [CmdletBinding()] [Alias("gettrack")] param( [Alias("Id")] [parameter( Mandatory, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string] $TrackId ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetTrackById($apiToken, $TrackId); } end { } } ############################################################################### <# .SYNOPSIS Reorders a range of tracks inside a Spotify playlist .DESCRIPTION Reorders a range of tracks inside a Spotify playlist .PARAMETER PlaylistId The Spotify playlist to perform the re-ordering on .PARAMETER RangeStart The position of the first item to be reordered .PARAMETER InsertBefore The position where the items should be inserted. To reorder the items to the end of the playlist, simply set insert_before to the position after the last item. Examples: To reorder the first item to the last position in a playlist with 10 items, set range_start to 0, and insert_before to 10. To reorder the last item in a playlist with 10 items to the start of the playlist, set range_start to 9, and insert_before to 0. .PARAMETER RangeLength The amount of items to be reordered. Defaults to 1 if not set. The range of items to be reordered begins from the range_start position, and includes the range_length subsequent items. Example: To move the items at index 9-10 to the start of the playlist, range_start is set to 9, and range_length is set to 2. #> function Set-SpotifyPlaylistOrder { [CmdletBinding()] [Alias("")] param( [parameter( Mandatory, Position = 0, HelpMessage = "The Spotify playlist to perform the re-ordering on" )] [string] $PlaylistId, [parameter( Mandatory, Position = 0, HelpMessage = "The position of the first item to be reordered" )] [int] $RangeStart, [parameter( Mandatory, Position = 1, HelpMessage = "The position where the items should be inserted. To reorder the items to the end of the playlist, simply set insert_before to the position after the last item. Examples: To reorder the first item to the last position in a playlist with 10 items, set range_start to 0, and insert_before to 10. To reorder the last item in a playlist with 10 items to the start of the playlist, set range_start to 9, and insert_before to 0." )] [int] $InsertBefore, [parameter( Mandatory = $false, Position = 2, HelpMessage = "The amount of items to be reordered. Defaults to 1 if not set. The range of items to be reordered begins from the range_start position, and includes the range_length subsequent items. Example: To move the items at index 9-10 to the start of the playlist, range_start is set to 9, and range_length is set to 2." )] [System.Nullable[int]] $RangeLength = $null ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::ReorderPlaylist($apiToken, $PlaylistId, $RangeStart, $InsertBefore, $RangeLength); } end { } } ############################################################################### <# .SYNOPSIS Returns all tracks of a Spotify playlist .DESCRIPTION Returns all tracks of a Spotify playlist .PARAMETER PlaylistId The Spotify playlist to return tracks for #> function Get-SpotifyPlaylistTracks { [CmdletBinding(DefaultParameterSetName = "ByName")] [Alias("getplaylist")] param( [Alias("Name")] [parameter( ParameterSetName = "ByName", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to return tracks for", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string] $PlaylistName, [Alias("Id")] [parameter( ParameterSetName = "ById", Mandatory, Position = 0, HelpMessage = "The Spotify playlist to return tracks for", ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string] $PlaylistId ) begin { $apiToken = Get-SpotifyApiToken; if ([string]::IsNullOrWhiteSpace($PlaylistName) -eq $false) { $PlaylistId = @(Get-SpotifyPlaylistIdsByName -PlaylistName @($PlaylistName)) | Select-Object -First 1 } } process { [GenXdev.Helpers.Spotify]::GetPlaylistTracks($apiToken, $PlaylistId); } end { } } ############################################################################### <# .SYNOPSIS Returns all tracks saved in users own Spotify Library .DESCRIPTION Returns all tracks saved in users own Spotify Library #> function Get-SpotifyLikedTracks { [CmdletBinding()] [Alias("liked")] param( ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetLibraryTracks($apiToken); } end { } } ############################################################################### <# .SYNOPSIS Adds tracks to the users own Spotify Library .DESCRIPTION Adds tracks to the users own Spotify Library .PARAMETER TrackId The Spotify track Ids of the songs that should be added to liked" #> function Add-SpotifyTracksToLiked { [CmdletBinding()] [Alias("like")] param( [Alias("Id")] [parameter( Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify track Uris of the songs that should be added to the playlist" )] [string[]] $TrackId = @() ) begin { $apiToken = Get-SpotifyApiToken; } process { if ($TrackId.Length -eq 0) { $CurrentlyPlaying = Get-SpotifyCurrentlyPlaying if ($null -eq $CurrentlyPlaying -or $CurrentlyPlaying.CurrentlyPlayingType -ne "track") { Write-Warning "There are no tracks playing at this time" return; } Add-SpotifyTracksToLiked -TrackId ($CurrentlyPlaying.Item.Id) $CurrentlyPlaying.Item } else { [GenXdev.Helpers.Spotify]::AddToLiked($apiToken, $TrackId); } } end { } } ############################################################################### <# .SYNOPSIS Moves all tracks from the users own Spotify Library to specified playlist .DESCRIPTION Moves all tracks from the users own Spotify Library to specified playlist .PARAMETER PlaylistId The Spotify playlist where all liked tracks should move to" #> function Move-SpotifyLikedTracksToPlaylist { [CmdletBinding(DefaultParameterSetName = "ByName")] [Alias("moveliked")] param( [Alias("Name")] [parameter( ParameterSetName = "ByName", Mandatory, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify playlist where all liked tracks should move to" )] [string[]] $PlaylistName, [Alias("Id")] [parameter( ParameterSetName = "ById", Mandatory, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify playlist where all liked tracks should move to" )] [string[]] $PlaylistId ) begin { if ($PlaylistName.Length -gt 0) { $PlaylistId = Get-SpotifyPlaylistIdsByName -PlaylistName $PlaylistName } } process { if ($PlaylistId.Length -eq 0) { return; } $likedTracks = Get-SpotifyLikedTracks [bool] $done = $false foreach ($Id in $PlaylistId) { Add-SpotifyTracksToPlaylist -PlaylistId $Id -Uri @($likedTracks.Track.Uri) $done = $true } if ($done) { Remove-SpotifyTracksFromLiked -TrackId @($likedTracks.Track.Id) $likedTracks } } end { } } ############################################################################### function Get-SpotifyPlaylistIdsByName { [CmdletBinding()] param( [Alias("Name")] [parameter( ParameterSetName = "ByName", Mandatory, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify playlist where all liked tracks should move to" )] [string[]] $PlaylistName = @() ) process { $results = @(Get-SpotifyUserPlaylists -Filter $PlaylistName) if ($results.Length -eq 0) { $filePath = Expand-Path -FilePath "$PSScriptRoot\..\..\GenXdev.Local\Spotify.Playlists.json" -CreateDirectory $playlistCache = [System.IO.FileInfo]::new($filePath); if (!$playlistCache.Exists -or ([datetime]::Now - $playlistCache.LastWriteTime -ge [timespan]::FromHours(12))) { $results = @(Get-SpotifyUserPlaylists -Force -Filter $PlaylistName) } } if ($results.Length -eq 0) { throw "Playlist not found" } $results | ForEach-Object Id } } ############################################################################### <# .SYNOPSIS Removes tracks from the users own Spotify Library .DESCRIPTION Removes tracks from the users own Spotify Library .PARAMETER TrackId The Spotify track Ids of the songs that should be removed from liked" #> function Remove-SpotifyTracksFromLiked { [CmdletBinding()] [Alias("dislike")] param( [Alias("Id")] [parameter( Mandatory = $false, Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify track Uris of the songs that should be added to the playlist" )] [string[]] $TrackId = @() ) begin { $apiToken = Get-SpotifyApiToken; } process { if ($TrackId.Length -eq 0) { $CurrentlyPlaying = Get-SpotifyCurrentlyPlaying if ($null -eq $CurrentlyPlaying -or $CurrentlyPlaying.CurrentlyPlayingType -ne "track") { Write-Warning "There are no tracks playing at this time" return; } Remove-SpotifyTracksFromLiked -TrackId ($CurrentlyPlaying.Item.Id) $CurrentlyPlaying.Item } else { [GenXdev.Helpers.Spotify]::RemoveFromLiked($apiToken, $TrackId); } } end { } } ############################################################################### <# .SYNOPSIS Returns all currently available Spotify devices for current user .DESCRIPTION Returns all currently available Spotify devices for current user #> function Get-SpotifyDevices { [CmdletBinding()] [Alias()] param( ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetDevices($apiToken); } end { } } ############################################################################### <# .SYNOPSIS Returns all currently active Spotify devices for current user .DESCRIPTION Returns all currently active Spotify devices for current user #> function Get-SpotifyActiveDevice { [CmdletBinding()] [Alias()] param( ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::GetDevices($apiToken) | Where-Object { $PSItem.IsActive } } end { } } ############################################################################### <# .SYNOPSIS Transfers playback to provided Spotify device .DESCRIPTION Transfers playback to provided Spotify device .PARAMETER DeviceId The Spotify deviceId to transfer playback to #> function Set-SpotifyActiveDevice { [CmdletBinding()] [Alias()] param( [Alias("Id")] [parameter( Mandatory, Position = 0, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $true, HelpMessage = "The Spotify deviceId to transfer playback to" )] [string] $DeviceId ) begin { $apiToken = Get-SpotifyApiToken; } process { [GenXdev.Helpers.Spotify]::SetActiveDevice($apiToken, $DeviceId); } end { } } ############################################################################### <# .SYNOPSIS Searches for lyrics of a track .DESCRIPTION Searches for lyrics of a track .PARAMETER TrackId Optional: Spotify id of track to lookup lyrics for .PARAMETER Queries Optional: A query to find a track to lookup lyrics for #> function Get-SpotifyLyrics { [CmdLetBinding(DefaultParameterSetName = "")] [Alias("lyrics")] param( [Alias("Id")] [parameter( Mandatory = $false, ValueFromPipelineByPropertyName = $True, ParameterSetName = "" )] [string] $TrackId = $null, [Alias("q", "Value", "Name", "Text", "Query")] [parameter( Mandatory = $false, Position = 0, ValueFromRemainingArguments = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [string[]] $Queries = $null ) begin { if ($null -ne $Queries) { $Queries = Build-InvocationArguments $MyInvocation $Queries } if ($null -ne $Queries) { $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 "Nothing found" } } else { if ([String]::IsNullOrWhiteSpace($TrackId) -eq $false) { $track = Get-SpotifyTrackById -TrackId $TrackId if ($null -ne $track) { $Queries = @("$($track.Artists[0].Name) - $($track.Name)"); } } else { $current = Get-SpotifyCurrentlyPlaying if ($null -ne $current) { $Queries = @("$($current.Item.Artists[0].Name) - $($current.Item.Name)"); } } } if ($null -eq $Queries) { throw "Currently no song playing, please specify search phrase" } } process { foreach ($query in $Queries) { $q = [Uri]::EscapeUriString($query) [string] $html = ""; try { $html = Invoke-WebRequest -Uri "https://www.musixmatch.com/search/$q" -ErrorAction SilentlyContinue } catch { Write-Warning "Nothing found for '$query'" continue; } [int] $idx = $html.IndexOf("Best Result"); if ($idx -lt 0) { Write-Warning "Nothing found for '$query'" continue; } $idx = $html.IndexOf('<a class="title" href="', $idx); if ($idx -lt 0) { Write-Warning "Nothing found for '$query'" continue; } $idx += '<a class="title" href="'.Length; [int] $idx2 = $html.IndexOf('"', $idx); if ($idx2 -lt 0) { Write-Warning "Nothing found for '$query'" continue; } $url = "https://www.musixmatch.com$($html.Substring($idx, $idx2-$idx))" try { $html = Invoke-WebRequest -Uri $url -ErrorAction SilentlyContinue } catch { Write-Warning "Nothing found for '$query'" continue; } $idx = $html.IndexOf('"body":"') if ($idx -lt 0) { Write-Warning "Nothing found for '$query'" continue; } $idx += '"body":"'.Length; $idx2 = $html.IndexOf('","language":', $idx); if ($idx2 -lt 0) { Write-Warning "Nothing found for '$query'" continue; } $result = "`"$($html.Substring($idx, $idx2-$idx))`"" | ConvertFrom-Json; if ([String]::IsNullOrWhiteSpace($result)) { Write-Warning "Nothing found for '$query'" } $result } } } ############################################################################### <# .SYNOPSIS Returns a ApiToken for Spotify .DESCRIPTION Returns a ApiToken for Spotify #> function Get-SpotifyApiToken { [CmdletBinding()] param() $path = "$PSScriptRoot\..\..\GenXdev.Local\Spotify_Auth.json"; if ([IO.File]::Exists($path)) { $ApiToken = [IO.File]::ReadAllText($path); } else { $ApiToken = Connect-SpotifyApiToken Set-SpotifyApiToken $ApiToken | Out-Null } try { [GenXdev.Helpers.Spotify]::GetDevices($ApiToken) | Out-Null } catch { $ApiToken = Connect-SpotifyApiToken Set-SpotifyApiToken $ApiToken | Out-Null } $ApiToken } ############################################################################### <# .SYNOPSIS Caches an Spotify API-token for later use .DESCRIPTION Caches an Spotify API-token for later use .PARAMETER ApiToken The API-token to cache #> function Set-SpotifyApiToken { [CmdletBinding()] param( [parameter( Mandatory = $true, Position = 0 )] [string] $ApiToken ) $dir = "$PSScriptRoot\..\..\GenXdev.Local"; $path = "$dir\Spotify_Auth.json"; if (![IO.Directory]::Exists($dir)) { [IO.Directory]::CreateDirectory($dir); } [IO.File]::WriteAllText($path, $ApiToken.Trim("`r`n`t ")); } ############################################################################### <# .SYNOPSIS Uses Spotify Open-Auth to request an access token .DESCRIPTION Uses Spotify Open-Auth to request an access token #> function Connect-SpotifyApiToken { [CmdletBinding()] param() Write-Warning "Spotify access token expired, requesting new.." $url = [GenXdev.Helpers.Spotify]::RequestAuthenticationUri(5642); [System.Diagnostics.Process] $process = Open-Webbrowser -PassThrough -ApplicationMode -NewWindow -Width 1000 -Height 800 -Centered -Monitor 0 -Url $url [GenXdev.Helpers.Spotify]::RequestAuthenticationTokenUsingOAuth(5642) if ((!!$process -and $process -is [System.Diagnostics.Process]) -and (!$process.HasExited)) { $process.CloseMainWindow() | Out-Null } } |