Public/Find-PlexItem.ps1
function Find-PlexItem { <# .SYNOPSIS This function uses the search ability of Plex find items on your Plex server. .DESCRIPTION This function uses the search ability of Plex find items on your Plex server. As objects returned have different properties depending on the type, there is an option to refine this by type. .PARAMETER ItemName Name of what you wish to find. .PARAMETER ItemType Refines the output by type. .PARAMETER Year Refine by year. .PARAMETER ExactNameMatch Return only items matching exactly what is specified as ItemName. .EXAMPLE # Find only 'movies' from the Plex server that (fuzzy)match 'The Dark Knight'. Find-PlexItem -ItemName 'The Dark Knight' -ItemType 'movie' .EXAMPLE # Find items that match exactly 'The Dark Knight' from the library 'Films'. Find-PlexItem -ItemName 'The Dark Knight' -ExactNameMatch -LibraryTitle 'Films' .EXAMPLE # Find items that (fuzzy)match 'Spider' from the library 'TV'. Find-PlexItem -ItemName 'spider' -LibraryTitle 'TV' #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory = $true)] [String] $ItemName, [Parameter(Mandatory = $false)] [ValidateSet('movie', 'episode', 'album')] [String] $ItemType, [Parameter(Mandatory = $false)] [String] $LibraryTitle, [Parameter(Mandatory = $false)] [Int] $Year, [Parameter(Mandatory = $false)] [Switch] $ExactNameMatch ) ############################################################################# #Region Import Plex Configuration if(!$script:PlexConfigData) { try { Import-PlexConfiguration -WhatIf:$False } catch { throw $_ } } #EndRegion ############################################################################# #Region Construct Uri try { $RestEndpoint = "hubs/search" # URLEncode the title, otherwise we'll get '400 bad request' errors when searching for things like: Bill and Ted's ... $ItemNameEncoded = [System.Web.HttpUtility]::UrlEncode($ItemName) $Params = [Ordered]@{ 'includeCollections' = 0 'sectionId' = '' 'query' = $ItemNameEncoded 'limit' = 50 } $DataUri = Get-PlexAPIUri -RestEndpoint $RestEndpoint -Params $Params } catch { throw $_ } #EndRegion ############################################################################# #Region Make request Write-Verbose -Message "Function: $($MyInvocation.MyCommand): Searching for $ItemName." try { [Array]$Data = Invoke-RestMethod -Uri $DataUri -Method GET } catch { throw $_ } #EndRegion ############################################################################# # Refine by type: if($ItemType) { $Results = ($Data.MediaContainer.Hub | Where-Object { $_.type -eq $ItemType -and $_.Size -gt 0 }).Metadata } else { $Results = ($Data.MediaContainer.Hub | Where-Object { $_.Size -gt 0 }).Metadata } if($Results.Count -gt 0) { # Refine by the ItemName to attempt an exact match: if($ExactNameMatch) { [Array]$Results = $Results | Where-Object { $_.title -eq $ItemName } # There could still be more than one result with an exact title match due to the same item being in multiple libraries # or even in the same library! if($Results.count -gt 1) { Write-Warning -Message "Exact match was specified but there was more than 1 result for $ItemName." } } # Refine by library name: if($LibraryTitle) { # Sometimes they come back with 'reasonTitle'. Makes sense, not. Write-Verbose "Refining multiple results by library" [Array]$Results = $Results | Where-Object { $_.librarySectionTitle -eq $LibraryTitle -or $_.reasonTitle -eq $LibraryTitle } } if($Year) { #[Array]$Results = $Results | Where-Object { ($_.originallyAvailableAt.split('-')[0]) -match $Year } Write-Verbose "Refining results by Year: $Year" [Array]$Results = $Results | Where-Object { $_.year -eq $Year } } # Add datetime objects so we don't have to work with unixtimes... $Results | ForEach-Object { if($Null -ne $_.lastViewedAt) { $_ | Add-Member -NotePropertyName 'lastViewedAtDateTime' -NotePropertyValue (ConvertFrom-UnixTime $_.lastViewedAt) -Force } if($Null -ne $_.addedAt) { $_ | Add-Member -NotePropertyName 'addedAtDateTime' -NotePropertyValue (ConvertFrom-UnixTime $_.addedAt) -Force } if($Null -ne $_.updatedAt) { $_ | Add-Member -NotePropertyName 'updatedAtDateTime' -NotePropertyValue (ConvertFrom-UnixTime $_.updatedAt) -Force } } return $Results } else { Write-Verbose -Message "Function: $($MyInvocation.MyCommand): No result found." return } } |