tmdb.ps1
Write-Verbose "Include script '$PSCommandPath'" ### Includes: . "$PSScriptRoot\network.ps1" . "$PSScriptRoot\text.ps1" ### Types: class FindTmdbResult { [string]$Name [string]$NameTranslit [int]$Year [string[]]$CountriesAny [string]$Type $Result = $null [bool]$Success = $false [string]$Message = "" } ### Variables: ### Functions: function Invoke-TmdbRequest { [CmdletBinding()] param ( [string]$Url, [ValidateSet('JSON', 'Text', IgnoreCase = $true)] [string]$ResponseType = 'JSON', [System.Collections.Specialized.OrderedDictionary]$Query = @{ } ### ordered - обязательно, чтобы был одинаковый порядок параметров ) Write-Verbose "Invoke-TmdbRequest: begin" #Write-Verbose "Invoke-TmdbRequest: ErrorActionPreference: '$ErrorActionPreference'" Write-Verbose "Invoke-TmdbRequest: Url: '$Url'" $config = Get-Config $tmdb_config = $config.Tmdb $api_url = $tmdb_config.ApiUrl if (!$api_url) { throw "TMDB API URL is not set" } Write-Verbose "Invoke-TmdbRequest: api_url: '$api_url'" $access_token = $tmdb_config.AccessToken if (!$access_token) { throw "TMDB access token is not set" } Write-Verbose "Invoke-TmdbRequest: access_token: '$($access_token.Substring(0, 2) + "****")'" $full_url = Combine-Url -Segments $api_url, $Url Write-Verbose "Invoke-TmdbRequest: full_url: '$full_url'" $headers = @{ "Authorization" = "Bearer $access_token" "accept" = "application/json" } Get-UrlContent -Url $full_url -ResponseType $ResponseType -Headers $headers -Query $Query } function Enrich-TmdbResult { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] $Result ) process { if ((!$Result.name) -and $Result.title) { Add-Member -InputObject $Result -MemberType NoteProperty -Name name -Value $Result.title } if ((!$Result.original_name) -and $Result.original_title) { Add-Member -InputObject $Result -MemberType NoteProperty -Name original_name -Value $Result.original_title } if (!$Result.year) { $y = if ($Result.release_date) { (Get-Date $Result.release_date).Year } elseif ($Result.first_air_date) { (Get-Date $Result.first_air_date).Year } else { '' } if ($y) { Write-Verbose "Find-Tmdb: add year $y" Add-Member -InputObject $Result -MemberType NoteProperty -Name year -Value $y } } if ($Result.poster_path) { Add-Member -InputObject $Result -MemberType NoteProperty -Name poster_url -Value "https://image.tmdb.org/t/p/original/$($Result.poster_path)" } if ($Result.backdrop_path) { Add-Member -InputObject $Result -MemberType NoteProperty -Name backdrop_url -Value "https://image.tmdb.org/t/p/original/$($Result.backdrop_path)" } $Result } } ### Поиск по External ID #https://developer.themoviedb.org/reference/find-by-id function Find-TmdbByExternalId { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$ExternalId, [ValidateSet('IMDB', IgnoreCase = $true)] [string]$ExternalSource = 'IMDB', # [string[]]$Languages = @('ru-RU') [string[]]$Languages = @('ru-RU', 'en-US') ) process { Write-Verbose "Find-Tmdb: ExternalId: '$ExternalId', ExternalSource: '$ExternalSource'" #Write-Verbose "Find-Tmdb: ErrorActionPreference: '$ErrorActionPreference'" $url = "find/$ExternalId" $query = [ordered]@{ external_source = $ExternalSource + "_id" } foreach ($lang in $Languages) { $query.language = $lang $results = @(Invoke-TmdbRequest -Url $url -Query $query) if ($results.movie_results) { return $results.movie_results | Enrich-TmdbResult } if ($results.tv_results) { return $results.tv_results | Enrich-TmdbResult } } } } ### Поиск фильма по имени и году: function Find-Tmdb { [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [string]$Name, [Parameter(Mandatory = $true)] [ValidateSet('Movie', 'TVShow')] [string]$ContentType, [int]$Year, [string]$Language = 'ru-RU' ) process { Write-Verbose "Find-Tmdb: Name: '$Name'" #Write-Verbose "Find-Tmdb: ErrorActionPreference: '$ErrorActionPreference'" $url = if ($ContentType -eq 'Movie') { 'search/movie' } else { 'search/tv' } $query = [ordered]@{ page = 1 include_adult = 'true' query = $Name } if ($Year) { $query.year = $Year } if ($Language) { $query.language = $Language } Invoke-TmdbRequest -Url $url -Query $query | select -ExpandProperty results | % { if ((!$_.name) -and $_.title) { Add-Member -InputObject $_ -MemberType NoteProperty -Name name -Value $_.title } if ((!$_.original_name) -and $_.original_title) { Add-Member -InputObject $_ -MemberType NoteProperty -Name original_name -Value $_.original_title } if (!$_.year) { $y = if ($_.release_date) { (Get-Date $_.release_date).Year } elseif ($_.first_air_date) { (Get-Date $_.first_air_date).Year } else { '' } if ($y) { Write-Verbose "Find-Tmdb: add year $y" Add-Member -InputObject $_ -MemberType NoteProperty -Name year -Value $y } } if ($_.poster_path) { Add-Member -InputObject $_ -MemberType NoteProperty -Name poster_url -Value "https://image.tmdb.org/t/p/original/$($_.poster_path)" } if ($_.backdrop_path) { Add-Member -InputObject $_ -MemberType NoteProperty -Name backdrop_url -Value "https://image.tmdb.org/t/p/original/$($_.backdrop_path)" } $_ } } } ### Искать 1 результат function Find-TmdbSingle { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [ValidateSet('Movie', 'TVShow')] [string]$ContentType, [string]$OriginalName, [string]$OriginalLanguage, [int]$Year, [string]$ImdbId ) Write-Verbose "Find-TmdbSingle: Name: '$Name', OriginalName: '$OriginalName', Year: '$Year'" #Write-Verbose "Find-TmdbSingle: ErrorActionPreference: '$ErrorActionPreference'" $result = [FindTmdbResult]@{ Name = $Name Year = $Year # CountriesAny = $CountriesAny Type = $ContentType Success = $false } $find_results = @() # $err = $null try { if ($ImdbId) { $find_results = @(Find-TmdbByExternalId -ExternalId $ImdbId -ExternalSource IMDB) if ($find_results) { $result.Result = $find_results[0] $result.Success = $true $result.Message = if ($find_results.Length -eq 1) { "Found single by IMDB ID" } else { "Found multiple IMDB ID, select 1st" } return $result } } $find_results = @(Find-Tmdb -Name $Name -ContentType $ContentType) #| ? { $_.name } } catch { $err = $_ if ($ErrorActionPreference -eq 'Stop') { throw } elseif ($ErrorActionPreference -ne 'SilentlyContinue') { Write-Host ($_ | fl * -Force | Out-String).Trim() -ForegroundColor 'Red' Write-Host ($_.Exception | fl * -Force | Out-String).Trim() -ForegroundColor 'Red' Write-Host ("Parameters:`r`n" + (New-Object "PSObject" -Property $PSBoundParameters | fl * | Out-String).Trim()) -ForegroundColor 'Cyan' } $result.Message = "Find-TmdbSingle: " + $_.Exception.Message return $result } # Write-Host "[DEBUG #2]" # Write-Host ("`r`n=== err:`r`n" + ($err | fl * -Force | Out-String).Trim()) -ForegroundColor 'Cyan' if (!$find_results) { $result.Message = "Cannot find $ContentType '$($Name)'" # if ($err) { # $result.Message += ": $($err.Exception.Message)" # } Write-Verbose "Find-TmdbSingle: $($result.Message)" return $result } Write-Host "Find-TmdbSingle: Before filtration:`r`n$($find_results | select id, name, original_name, year, original_language | ft -AutoSize | Out-String)" -fo Cyan # if ($ContentType -eq 'Movie') { # Write-Host "Find-TmdbSingle: Before filtration:`r`n$($find_results | select id, title, original_title, year, original_language, release_date | ft -AutoSize | Out-String)" -fo Cyan # } else { # Write-Host "Find-TmdbSingle: Before filtration:`r`n$($find_results | select id, name, original_name, year, original_language, first_air_date, origin_country | ft -AutoSize | Out-String)" -fo Cyan # } ### Ищем по оригинальному имени: if ($OriginalName) { $find_results_or_name = @($find_results | ? { $_.original_title -eq $OriginalName }) if ($find_results_or_name.Length -eq 1) { $result.Result = $find_results_or_name[0] $result.Success = $true $result.Message = "Found by original name '$OriginalName'" return $result } } ### Если указан год, ищем по году +-1: if ($Year) { ### !!! скобки обязательно foreach ($y in @($Year, ($Year - 1), ($Year + 1))) { Write-Host "Find by year $y" -fo Cyan $delta = $y - $Year $delta_msg = if ($delta) { " ($('{0:+#;-#;0}' -f $delta))" } else { '' } $find_results_year = @( $find_results | ? { $_.year -eq $y } ` | ? { if ($OriginalLanguage) { $_.original_language -eq $OriginalLanguage } else { $true } } ) if ($find_results_year) { if ($find_results_year.Length -eq 1) { $result.Result = $find_results_year[0] $result.Success = $true $result.Message = "Found single by year $($y)$delta_msg" if($OriginalLanguage) { $result.Message += " and original language '$OriginalLanguage'" } return $result } else { $result.Result = $find_results_year[0] $result.Success = $true $result.Message = "Found multiple by year $($y)$delta_msg, select 1st" if ($OriginalLanguage) { $result.Message += " and original language '$OriginalLanguage'" } return $result } } } $result.Message = "Cannot find $ContentType '$($Name)' by year $Year" return $result } ### Если результат еще не установлен if ($find_results) { if ($find_results.Length -eq 1) { $result.Result = $find_results[0] $result.Success = $true $result.Message = "Found single after filtration" return $result } else { $result.Result = $find_results | Sort-Object year -Descending | select -First 1 $result.Success = $true $result.Message = "Found multiple after filtration, select 1st" return $result } } $result.Message = "Cannot find $ContentType '$($Name)' after filtering" return $result } ### Поиск трейлеров: function Get-TmdbVideos { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Id, [Parameter(Mandatory = $true)] [ValidateSet('Movie', 'TVShow')] [string]$ContentType, [string[]]$Languages = @('ru-RU', 'en-US'), [string[]]$Types ) Write-Verbose "Get-TmdbVideos: Id: '$Id', Languages: [$Languages], Types: [$Types]" $type_order = @{ 'Trailer' = 10 'Teaser' = 20 'Featurette' = 30 'Behind the Scenes' = 40 } $url = if ($ContentType -eq 'Movie') { "movie/$Id/videos" } else { "tv/$Id/videos" } $Languages | % { Invoke-TmdbRequest -Url $url -Query ([ordered]@{ language = $_ } ) | select -ExpandProperty results | ? { if ($Types) { $_.type -in $Types } else { $true } } | % { Add-Member -InputObject $_ -MemberType NoteProperty -Name Order -Value $type_order[$_.type] if ($_.site -eq "YouTube") { Add-Member -InputObject $_ -MemberType NoteProperty -Name YoutubeId -Value $_.key Add-Member -InputObject $_ -MemberType NoteProperty -Name Url -Value "https://www.youtube.com/watch?v=$($_.key)" ### Не работает в Kodi Add-Member -InputObject $_ -MemberType NoteProperty -Name KodiUrl -Value "plugin://plugin.video.youtube/?action=play_video&videoid=$($_.key)" } $_ } | Sort-Object order, name } } function Get-TmdbTrailers { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Id, [ValidateSet('Movie', 'TVShow')] [string]$ContentType, [string[]]$Languages = @('ru-RU', 'en-US'), [string[]]$Types = @("Trailer", "Teaser") ) Write-Verbose "Get-TmdbTrailers: Id: '$Id', Languages: [$Languages], Types: [$Types]" Get-TmdbVideos -Id $Id -Languages $Languages -Types $Types -ContentType $ContentType } |