diff --git a/MyPersonalConfig.json b/MyPersonalConfig.json index 47bb307..b06163a 100644 --- a/MyPersonalConfig.json +++ b/MyPersonalConfig.json @@ -5,6 +5,7 @@ "FanartTvAPIKey": "xxxxxxxxxxxxx", "PlexToken": "xxxxxxxxxxxxx", "JellyfinAPIKey": "xxxxxxxxxxxxx", + "EmbyAPIKey": "xxxxxxxxxxxxx", "FavProvider": "tmdb", "WidthHeightFilter": "false", "PosterMinWidth": "2000", @@ -45,6 +46,17 @@ "JellyfinUrl": "http://jellyfin:8096", "UseJellyfin": "false" }, + "EmbyPart": { + "LibstoExclude": [ + "Youtube", + "Audiobooks", + "KidsAudiobooks", + "TechTrainings", + "KidsMusic" + ], + "EmbyUrl": "http://192.168.1.20:8096/emby", + "UseEmby": "false" + }, "Notification": { "SendNotification": "True", "AppriseUrl": "discord://xxxxxxxxxx/xxxxxxxxxxxxx", diff --git a/Posterizarr.ps1 b/Posterizarr.ps1 index 720eb5a..b43663c 100644 --- a/Posterizarr.ps1 +++ b/Posterizarr.ps1 @@ -8,7 +8,7 @@ [string]$mediatype ) -$CurrentScriptVersion = "1.6.3" +$CurrentScriptVersion = "1.7.0" $global:HeaderWritten = $false $ProgressPreference = 'SilentlyContinue' @@ -3341,6 +3341,11 @@ function LogConfigSettings { Write-Entry -Subtext "| Excluded Libs: $($LibstoExclude -join ',')" -Path $configLogging -Color White -log Info Write-Entry -Subtext "| Jellyfin Url: $($JellyfinUrl[0..10] -join '')****" -Path $configLogging -Color White -log Info } + if ($UseEmby -eq 'true') { + Write-Entry -Subtext "Emby Part" -Path $configLogging -Color Cyan -log Info + Write-Entry -Subtext "| Excluded Libs: $($LibstoExclude -join ',')" -Path $configLogging -Color White -log Info + Write-Entry -Subtext "| Emby Url: $($EmbyUrl[0..10] -join '')****" -Path $configLogging -Color White -log Info + } Write-Entry -Subtext "Prerequisites Part" -Path $configLogging -Color Cyan -log Info Write-Entry -Subtext "| Asset Path: $AssetPath" -Path $configLogging -Color White -log Info Write-Entry -Subtext "| Upload to Plex: $Upload2Plex" -Path $configLogging -Color White -log Info @@ -3730,7 +3735,35 @@ function CheckJellyfinAccess { } } } -function UploadJellyfinArtwork { +function CheckEmbyAccess { + param ( + [string]$EmbyUrl, + [string]$EmbyAPI + ) + + if ($EmbyAPI) { + Write-Entry -Message "Checking Emby access now..." -Path $configLogging -Color White -log Info + try { + $response = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/System/Info?api_key=$OtherMediaServerApiKey" -ErrorAction Stop + if ($response.version) { + Write-Entry -Subtext "Emby access is working..." -Path $configLogging -Color Green -log Info + } + else { + Write-Entry -Message "Could not access Emby" -Path $configLogging -Color Red -Log Error + Write-Entry -Subtext "Please check token and url..." -Path $configLogging -Color Red -log Error + Write-Entry -Subtext "[ERROR-HERE] See above. ^^^" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Red -log Error + $errorCount++ + Exit + } + } + catch { + Write-Entry -Subtext "Could not access Emby" -Path $configLogging -Color Red -Log Error + Write-Entry -Subtext "Error occurred while accessing Emby server: $($_.Exception.Message)" -Path $configLogging -Color Red -log Error + Exit + } + } +} +function UploadOtherMediaServerArtwork { param ( [string]$itemId, [string]$imageType, @@ -3738,15 +3771,15 @@ function UploadJellyfinArtwork { ) # Check if current image already has exif data - $Imageinfo = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/items/$itemId/images/?api_key=$JellyfinAPIKey" + $Imageinfo = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/items/$itemId/images/?api_key=$OtherMediaServerApiKey" $Imageinfotemp = $Imageinfo | Where-Object imagetype -eq $imageType | Select-Object Height, Width, Path if ($Imageinfotemp) { $Imageinfotemp = $imageinfotemp[0] } # Set the API endpoint URL for magick exif check if (($imageinfotemp.Height) -and ($imageinfotemp.width)) { - $JellyfinImageUrl = "$JellyfinUrl/items/$itemId/images/$imageType/?api_key=$JellyfinAPIKey&width=$($imageinfotemp.width)&height=$($imageinfotemp.Height)" - $magickcommand = "& `"$magick`" identify -verbose `"$JellyfinImageUrl`"" + $ImageUrl = "$OtherMediaServerUrl/items/$itemId/images/$imageType/?api_key=$OtherMediaServerApiKey&width=$($imageinfotemp.width)&height=$($imageinfotemp.Height)" + $magickcommand = "& `"$magick`" identify -verbose `"$ImageUrl`"" $magickcommand | Out-File $global:ScriptRoot\Logs\ImageMagickCommands.log -Append # Execute command and get exif data @@ -3780,7 +3813,7 @@ function UploadJellyfinArtwork { } # Set the API endpoint URL - $apiUrl = "$JellyfinUrl/items/$itemId/images/$imageType/?api_key=$JellyfinAPIKey" + $apiUrl = "$OtherMediaServerUrl/items/$itemId/images/$imageType/?api_key=$OtherMediaServerApiKey" # Make the API request to upload the image try { @@ -3899,6 +3932,7 @@ $global:tmdbtoken = $config.ApiPart.tmdbtoken $FanartTvAPIKey = $config.ApiPart.FanartTvAPIKey $PlexToken = $config.ApiPart.PlexToken $JellyfinAPIKey = $config.ApiPart.JellyfinAPIKey +$EmbyAPIKey = $config.ApiPart.EmbyAPIKey $global:WidthHeightFilter = $config.ApiPart.WidthHeightFilter.tolower() $global:PosterMinWidth = $config.ApiPart.PosterMinWidth $global:PosterMinHeight = $config.ApiPart.PosterMinHeight @@ -3999,6 +4033,19 @@ $JellyfinUrl = $config.JellyfinPart.JellyfinUrl $UseJellyfin = $config.JellyfinPart.UseJellyfin.tolower() if ($UseJellyfin -eq 'true') { $LibstoExclude = $config.JellyfinPart.LibstoExclude + $OtherMediaServerUrl = $JellyfinUrl + $UseOtherMediaServer = $UseJellyfin + $OtherMediaServerApiKey = $JellyfinAPIKey +} + +# Emby Part +$EmbyUrl = $config.EmbyPart.EmbyUrl +$UseEmby = $config.EmbyPart.UseEmby.tolower() +if ($UseEmby -eq 'true') { + $LibstoExclude = $config.EmbyPart.LibstoExclude + $OtherMediaServerUrl = $EmbyUrl + $UseOtherMediaServer = $UseEmby + $OtherMediaServerApiKey = $EmbyAPIKey } # Prerequisites Part @@ -4380,6 +4427,10 @@ if ($UseJellyfin -eq 'true') { # Check Jellyfin now: CheckJellyfinAccess -JellyfinUrl $JellyfinUrl -JellyfinApi $JellyfinAPIKey } +if ($UseEmby -eq 'true') { + # Check Emby now: + CheckEmbyAccess -EmbyUrl $EmbyUrl -EmbyAPI $EmbyAPIKey +} # Check overlay artwork for poster, background, and titlecard dimensions Write-Entry -Message "Checking size of overlay files..." -Path $configLogging -Color White -log Info @@ -9051,24 +9102,24 @@ Elseif ($Tautulli) { Remove-Item -LiteralPath $CurrentlyRunning | out-null } } -Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { - Write-Entry -Message "Query Jellyfin..." -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info +Elseif ($OtherMediaServerUrl -and $OtherMediaServerApiKey -and $UseOtherMediaServer -eq 'true') { + Write-Entry -Message "Query Jellyfin/Emby..." -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info Write-Entry -Message "Query all items from all Libs, this can take a while..." -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info - $PreferredMetadataLanguage = (Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/System/Configuration?api_key=$JellyfinAPIKey").PreferredMetadataLanguage - $allShowsquery = "$JellyfinUrl/Items?api_key=$JellyfinAPIKey&Recursive=true&Fields=ProviderIds,SeasonUserData,OriginalTitle,Path,Overview&IncludeItemTypes=Series" - $allMoviesquery = "$JellyfinUrl/Items?api_key=$JellyfinAPIKey&Recursive=true&Fields=ProviderIds,OriginalTitle,Settings,Path,Overview&IncludeItemTypes=Movie" + $PreferredMetadataLanguage = (Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/System/Configuration?api_key=$OtherMediaServerApiKey").PreferredMetadataLanguage + $allShowsquery = "$OtherMediaServerUrl/Items?api_key=$OtherMediaServerApiKey&Recursive=true&Fields=ProviderIds,SeasonUserData,OriginalTitle,Path,Overview&IncludeItemTypes=Series" + $allMoviesquery = "$OtherMediaServerUrl/Items?api_key=$OtherMediaServerApiKey&Recursive=true&Fields=ProviderIds,OriginalTitle,Settings,Path,Overview&IncludeItemTypes=Movie" $AllShows = Invoke-RestMethod -Method Get -Uri $allShowsquery $AllMovies = Invoke-RestMethod -Method Get -Uri $allMoviesquery $Libraries = @() foreach ($Movie in $AllMovies.Items) { - $Libtemp = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/Items/$($Movie.Id)/Ancestors?api_key=$JellyfinAPIKey" - $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, Path - if ($lib.name -notin $LibstoExclude) { - if ($Movie.Path -like "$($lib.Path)/*" -or $Movie.Path -like "$($lib.Path)\*") { + if ($UseEmby -eq 'true'){ + $Libtemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/Items/$($Movie.Id)/Ancestors?api_key=$OtherMediaServerApiKey" + $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, Path + if ($lib.name -notin $LibstoExclude) { Write-Entry -Subtext "Location: $($Movie.Path)" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug - Write-Entry -Subtext "Libpath: $($lib.Path)" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug - $Matchedpath = AddTrailingSlash $($lib.Path) + Write-Entry -Subtext "Libpath: $($lib.Path[1])" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + $Matchedpath = AddTrailingSlash $($lib.Path[1]) $libpath = $Matchedpath $extractedFolder = $Movie.Path.Substring($libpath.Length) if ($extractedFolder -like '*\*') { @@ -9079,30 +9130,68 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { } Write-Entry -Subtext "Matchedpath: $Matchedpath" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug Write-Entry -Subtext "ExtractedFolder: $extractedFolder" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + $temp = New-Object psobject + $temp | Add-Member -MemberType NoteProperty -Name "Library Name" -Value $lib.name[1] + $temp | Add-Member -MemberType NoteProperty -Name "Library Type" -Value $Movie.Type + $temp | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage + $temp | Add-Member -MemberType NoteProperty -Name "Id" -Value $Movie.Id + $temp | Add-Member -MemberType NoteProperty -Name "title" -Value $Movie.Name + $temp | Add-Member -MemberType NoteProperty -Name "originalTitle" -Value $Movie.OriginalTitle + $temp | Add-Member -MemberType NoteProperty -Name "year" -Value $Movie.ProductionYear + $temp | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $Movie.ProviderIds.Imdb + $temp | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $Movie.ProviderIds.Tmdb + $temp | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $Movie.ProviderIds.Tvdb + $temp | Add-Member -MemberType NoteProperty -Name "Path" -Value $lib.Path[1] + $temp | Add-Member -MemberType NoteProperty -Name "RootFoldername" -Value $extractedFolder + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerPosterUrl" -Value $Movie.ImageTags.Primary + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerBackgroundUrl" -Value $($Movie.BackdropImageTags -join ",") + $Libraries += $temp + Write-Entry -Subtext "Found [$($temp.title)] of type $($temp.{Library Type}) in [$($temp.{Library Name})]" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + } + } + Else { + $Libtemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/Items/$($Movie.Id)/Ancestors?api_key=$OtherMediaServerApiKey" + $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, Path + if ($lib.name -notin $LibstoExclude) { + if ($Movie.Path -like "$($lib.Path)/*" -or $Movie.Path -like "$($lib.Path)\*") { + Write-Entry -Subtext "Location: $($Movie.Path)" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + Write-Entry -Subtext "Libpath: $($lib.Path)" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + $Matchedpath = AddTrailingSlash $($lib.Path) + $libpath = $Matchedpath + $extractedFolder = $Movie.Path.Substring($libpath.Length) + if ($extractedFolder -like '*\*') { + $extractedFolder = $extractedFolder.split('\')[0] + } + if ($extractedFolder -like '*/*') { + $extractedFolder = $extractedFolder.split('/')[0] + } + Write-Entry -Subtext "Matchedpath: $Matchedpath" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + Write-Entry -Subtext "ExtractedFolder: $extractedFolder" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + } + $temp = New-Object psobject + $temp | Add-Member -MemberType NoteProperty -Name "Library Name" -Value $lib.name + $temp | Add-Member -MemberType NoteProperty -Name "Library Type" -Value $Movie.Type + $temp | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage + $temp | Add-Member -MemberType NoteProperty -Name "Id" -Value $Movie.Id + $temp | Add-Member -MemberType NoteProperty -Name "title" -Value $Movie.Name + $temp | Add-Member -MemberType NoteProperty -Name "originalTitle" -Value $Movie.OriginalTitle + $temp | Add-Member -MemberType NoteProperty -Name "year" -Value $Movie.ProductionYear + $temp | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $Movie.ProviderIds.Imdb + $temp | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $Movie.ProviderIds.Tmdb + $temp | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $Movie.ProviderIds.Tvdb + $temp | Add-Member -MemberType NoteProperty -Name "Path" -Value $lib.Path + $temp | Add-Member -MemberType NoteProperty -Name "RootFoldername" -Value $extractedFolder + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerPosterUrl" -Value $Movie.ImageTags.Primary + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerBackgroundUrl" -Value $($Movie.BackdropImageTags -join ",") + $Libraries += $temp + Write-Entry -Subtext "Found [$($temp.title)] of type $($temp.{Library Type}) in [$($temp.{Library Name})]" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug } - $temp = New-Object psobject - $temp | Add-Member -MemberType NoteProperty -Name "Library Name" -Value $lib.name - $temp | Add-Member -MemberType NoteProperty -Name "Library Type" -Value $Movie.Type - $temp | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage - $temp | Add-Member -MemberType NoteProperty -Name "Id" -Value $Movie.Id - $temp | Add-Member -MemberType NoteProperty -Name "title" -Value $Movie.Name - $temp | Add-Member -MemberType NoteProperty -Name "originalTitle" -Value $Movie.OriginalTitle - $temp | Add-Member -MemberType NoteProperty -Name "year" -Value $Movie.ProductionYear - $temp | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $Movie.ProviderIds.Imdb - $temp | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $Movie.ProviderIds.Tmdb - $temp | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $Movie.ProviderIds.Tvdb - $temp | Add-Member -MemberType NoteProperty -Name "Path" -Value $lib.Path - $temp | Add-Member -MemberType NoteProperty -Name "RootFoldername" -Value $extractedFolder - $temp | Add-Member -MemberType NoteProperty -Name "JellyfinPosterUrl" -Value $Movie.ImageTags.Primary - $temp | Add-Member -MemberType NoteProperty -Name "JellyfinBackgroundUrl" -Value $($Movie.BackdropImageTags -join ",") - $Libraries += $temp - Write-Entry -Subtext "Found [$($temp.title)] of type $($temp.{Library Type}) in [$($temp.{Library Name})]" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug - Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug } } - foreach ($Show in $AllShows.Items) { - $Libtemp = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/Items/$($Show.Id)/Ancestors?api_key=$JellyfinAPIKey" + $Libtemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/Items/$($Show.Id)/Ancestors?api_key=$OtherMediaServerApiKey" $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, path if ($lib.name -notin $LibstoExclude) { if ($Show.Path -like "$($lib.Path)/*" -or $Show.Path -like "$($lib.Path)\*") { @@ -9133,51 +9222,86 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { $temp | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $Show.ProviderIds.Tvdb $temp | Add-Member -MemberType NoteProperty -Name "Path" -Value $lib.Path $temp | Add-Member -MemberType NoteProperty -Name "RootFoldername" -Value $extractedFolder - $temp | Add-Member -MemberType NoteProperty -Name "JellyfinPosterUrl" -Value $Show.ImageTags.Primary - $temp | Add-Member -MemberType NoteProperty -Name "JellyfinBackgroundUrl" -Value $($Show.BackdropImageTags -join ",") + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerPosterUrl" -Value $Show.ImageTags.Primary + $temp | Add-Member -MemberType NoteProperty -Name "OtherMediaServerBackgroundUrl" -Value $($Show.BackdropImageTags -join ",") $Libraries += $temp Write-Entry -Subtext "Found [$($temp.title)] of type $($temp.{Library Type}) in [$($temp.{Library Name})]" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug } } Write-Entry -Subtext "Found '$($Libraries.count)' Items..." -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Info - $Libraries | Select-Object * | Export-Csv -Path "$global:ScriptRoot\Logs\JellyfinLibExport.csv" -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force - Write-Entry -Message "Export everything to a csv: $global:ScriptRoot\Logs\JellyfinLibExport.csv" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info + $Libraries | Select-Object * | Export-Csv -Path "$global:ScriptRoot\Logs\OtherMediaServerLibExport.csv" -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force + Write-Entry -Message "Export everything to a csv: $global:ScriptRoot\Logs\OtherMediaServerLibExport.csv" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info $Episodedata = @() foreach ($show in $AllShows.Items) { - $Libtemp = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/Items/$($Show.Id)/Ancestors?api_key=$JellyfinAPIKey" - $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, path - if ($lib.name -notin $LibstoExclude) { - # extract seasons - $Seasonstemp = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/shows/$($show.id)/Episodes?api_key=$JellyfinAPIKey" - $seasons = $Seasonstemp.Items | Where-Object { $_.LocationType -eq 'FileSystem' } | Select-Object ParentIndexNumber, SeasonId, ImageTags -Unique - - foreach ($Season in $Seasons) { - $SeasonEpisodestemp = Invoke-RestMethod -Method Get -Uri "$JellyfinUrl/shows/$($show.id)/Episodes?seasonid=$($Season.SeasonId)&api_key=$JellyfinAPIKey" - $SeasonEpisodes = $SeasonEpisodestemp.Items | Where-Object { $_.LocationType -eq 'FileSystem' } | Select-Object indexnumber, SeriesId, SeasonId, ImageTags, Id, Name -Unique - $tempseasondata = New-Object psobject - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Name" -Value $show.Name - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Original Name" -Value $show.OriginalTitle - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage - $tempseasondata | Add-Member -MemberType NoteProperty -Name "ShowID" -Value $($SeasonEpisodes.SeriesId[0] -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonId" -Value $($SeasonEpisodes.SeasonId[0] -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "EpisodeIds" -Value $($SeasonEpisodes.id -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $show.ProviderIds.tvdb - $tempseasondata | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $show.ProviderIds.imdb - $tempseasondata | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $show.ProviderIds.tmdb - $tempseasondata | Add-Member -MemberType NoteProperty -Name "type" -Value 'Episode' - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Season Number" -Value $Season.ParentIndexNumber - $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonName" -Value $($Season.SeasonName -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Episodes" -Value $($SeasonEpisodes.indexnumber -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "Title" -Value $($SeasonEpisodes.Name -join ';') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "JellyfinTitleCardTag" -Value $($SeasonEpisodes.ImageTags.Primary -join ',') - $tempseasondata | Add-Member -MemberType NoteProperty -Name "JellyfinSeasonTag" -Value $($Season.ImageTags.Primary -join ',') - $Episodedata += $tempseasondata - Write-Entry -Subtext "Found [$($tempseasondata.{Show Name})] of type $($tempseasondata.Type) for season $($tempseasondata.{Season Number})" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + if ($UseEmby -eq 'true'){ + $Libtemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/Items/$($Show.Id)/Ancestors?api_key=$OtherMediaServerApiKey" + $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, path + if ($lib.name -notin $LibstoExclude) { + # extract seasons + $Seasonstemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/shows/$($show.id)/Episodes?api_key=$OtherMediaServerApiKey" + $seasons = $Seasonstemp.Items | Where-Object { $_.Type -eq 'Episode' } | Select-Object ParentIndexNumber, SeasonId, ImageTags -Unique + + foreach ($Season in $Seasons) { + $SeasonEpisodestemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/shows/$($show.id)/Episodes?seasonid=$($Season.SeasonId)&api_key=$OtherMediaServerApiKey" + $SeasonEpisodes = $SeasonEpisodestemp.Items | Where-Object { $_.Type -eq 'Episode' } | Select-Object indexnumber, SeriesId, SeasonId, ImageTags, Id, Name -Unique + $tempseasondata = New-Object psobject + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Name" -Value $show.Name + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Original Name" -Value $show.OriginalTitle + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage + $tempseasondata | Add-Member -MemberType NoteProperty -Name "ShowID" -Value $($SeasonEpisodes.SeriesId[0] -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonId" -Value $($SeasonEpisodes.SeasonId[0] -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "EpisodeIds" -Value $($SeasonEpisodes.id -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $show.ProviderIds.tvdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $show.ProviderIds.imdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $show.ProviderIds.tmdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "type" -Value 'Episode' + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Season Number" -Value $Season.ParentIndexNumber + $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonName" -Value $($Season.SeasonName -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Episodes" -Value $($SeasonEpisodes.indexnumber -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Title" -Value $($SeasonEpisodes.Name -join ';') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "OtherMediaServerTitleCardTag" -Value $($SeasonEpisodes.ImageTags.Primary -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "OtherMediaServerSeasonTag" -Value $($Season.ImageTags.Primary -join ',') + $Episodedata += $tempseasondata + Write-Entry -Subtext "Found [$($tempseasondata.{Show Name})] of type $($tempseasondata.Type) for season $($tempseasondata.{Season Number})" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + } } } - } - $Episodedata | Select-Object * | Export-Csv -Path "$global:ScriptRoot\Logs\JellyfinEpisodeExport.csv" -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force + Else { + $Libtemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/Items/$($Show.Id)/Ancestors?api_key=$OtherMediaServerApiKey" + $lib = $Libtemp | Where-Object { $_.Type -eq 'Folder' } | Select-Object Name, path + if ($lib.name -notin $LibstoExclude) { + # extract seasons + $Seasonstemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/shows/$($show.id)/Episodes?api_key=$OtherMediaServerApiKey" + $seasons = $Seasonstemp.Items | Where-Object { $_.LocationType -eq 'FileSystem' } | Select-Object ParentIndexNumber, SeasonId, ImageTags -Unique + + foreach ($Season in $Seasons) { + $SeasonEpisodestemp = Invoke-RestMethod -Method Get -Uri "$OtherMediaServerUrl/shows/$($show.id)/Episodes?seasonid=$($Season.SeasonId)&api_key=$OtherMediaServerApiKey" + $SeasonEpisodes = $SeasonEpisodestemp.Items | Where-Object { $_.LocationType -eq 'FileSystem' } | Select-Object indexnumber, SeriesId, SeasonId, ImageTags, Id, Name -Unique + $tempseasondata = New-Object psobject + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Name" -Value $show.Name + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Show Original Name" -Value $show.OriginalTitle + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Library Language" -Value $PreferredMetadataLanguage + $tempseasondata | Add-Member -MemberType NoteProperty -Name "ShowID" -Value $($SeasonEpisodes.SeriesId[0] -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonId" -Value $($SeasonEpisodes.SeasonId[0] -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "EpisodeIds" -Value $($SeasonEpisodes.id -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "tvdbid" -Value $show.ProviderIds.tvdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "imdbid" -Value $show.ProviderIds.imdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "tmdbid" -Value $show.ProviderIds.tmdb + $tempseasondata | Add-Member -MemberType NoteProperty -Name "type" -Value 'Episode' + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Season Number" -Value $Season.ParentIndexNumber + $tempseasondata | Add-Member -MemberType NoteProperty -Name "SeasonName" -Value $($Season.SeasonName -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Episodes" -Value $($SeasonEpisodes.indexnumber -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "Title" -Value $($SeasonEpisodes.Name -join ';') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "OtherMediaServerTitleCardTag" -Value $($SeasonEpisodes.ImageTags.Primary -join ',') + $tempseasondata | Add-Member -MemberType NoteProperty -Name "OtherMediaServerSeasonTag" -Value $($Season.ImageTags.Primary -join ',') + $Episodedata += $tempseasondata + Write-Entry -Subtext "Found [$($tempseasondata.{Show Name})] of type $($tempseasondata.Type) for season $($tempseasondata.{Season Number})" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Debug + } + } + } + } + $Episodedata | Select-Object * | Export-Csv -Path "$global:ScriptRoot\Logs\OtherMediaServerEpisodeExport.csv" -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force if ($Episodedata) { Write-Entry -Subtext "Found '$($Episodedata.Episodes.split(',').count)' Episodes..." -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Cyan -log Info } @@ -9489,8 +9613,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { if (!$global:ImageMagickError -eq 'True') { if (Get-ChildItem -LiteralPath $PosterImage -ErrorAction SilentlyContinue) { if (!$global:IsTruncated) { - # Uploading Poster to Jellyfin - UploadJellyfinArtwork -itemId $entry.id -imageType "Primary" -imagePath $PosterImage + UploadOtherMediaServerArtwork -itemId $entry.id -imageType "Primary" -imagePath $PosterImage Move-Item -LiteralPath $PosterImage $PosterImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $PosterImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info @@ -9776,7 +9899,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { # Move file back to original naming with Brackets. if (Get-ChildItem -LiteralPath $backgroundImage -ErrorAction SilentlyContinue) { if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $entry.id -imageType "Backdrop" -imagePath $backgroundImage + UploadOtherMediaServerArtwork -itemId $entry.id -imageType "Backdrop" -imagePath $backgroundImage Move-Item -LiteralPath $backgroundImage $backgroundImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $backgroundImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info @@ -10126,7 +10249,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { if (Get-ChildItem -LiteralPath $PosterImage -ErrorAction SilentlyContinue) { # Move file back to original naming with Brackets. if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $entry.Id -imageType "Primary" -imagePath $PosterImage + UploadOtherMediaServerArtwork -itemId $entry.Id -imageType "Primary" -imagePath $PosterImage Move-Item -LiteralPath $PosterImage $PosterImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $PosterImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info @@ -10420,7 +10543,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { # Move file back to original naming with Brackets. if (Get-ChildItem -LiteralPath $backgroundImage -ErrorAction SilentlyContinue) { if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $entry.id -imageType "Backdrop" -imagePath $backgroundImage + UploadOtherMediaServerArtwork -itemId $entry.id -imageType "Backdrop" -imagePath $backgroundImage Move-Item -LiteralPath $backgroundImage $backgroundImageoriginal -Force -ErrorAction SilentlyContinue $BackgroundCount++ Write-Entry -Subtext "Added: $backgroundImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info @@ -10771,7 +10894,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { if (Get-ChildItem -LiteralPath $SeasonImage -ErrorAction SilentlyContinue) { # Move file back to original naming with Brackets. if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $global:seasonId -imageType "Primary" -imagePath $SeasonImage + UploadOtherMediaServerArtwork -itemId $global:seasonId -imageType "Primary" -imagePath $SeasonImage Move-Item -LiteralPath $SeasonImage -destination $SeasonImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $SeasonImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info @@ -11141,7 +11264,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { if (Get-ChildItem -LiteralPath $EpisodeImage -ErrorAction SilentlyContinue) { # Move file back to original naming with Brackets. if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $global:episodeid -imageType "Primary" -imagePath $EpisodeImage + UploadOtherMediaServerArtwork -itemId $global:episodeid -imageType "Primary" -imagePath $EpisodeImage Move-Item -LiteralPath $EpisodeImage -destination $EpisodeImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $EpisodeImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info @@ -11503,7 +11626,7 @@ Elseif ($JellyfinUrl -and $JellyfinAPIKey -and $UseJellyfin -eq 'true') { if (Get-ChildItem -LiteralPath $EpisodeImage -ErrorAction SilentlyContinue) { # Move file back to original naming with Brackets. if (!$global:IsTruncated) { - UploadJellyfinArtwork -itemId $global:episodeid -imageType "Primary" -imagePath $EpisodeImage + UploadOtherMediaServerArtwork -itemId $global:episodeid -imageType "Primary" -imagePath $EpisodeImage Move-Item -LiteralPath $EpisodeImage -destination $EpisodeImageoriginal -Force -ErrorAction SilentlyContinue Write-Entry -Subtext "Added: $EpisodeImageoriginal" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color Green -log Info Write-Entry -Subtext "--------------------------------------------------------------------------------" -Path $global:ScriptRoot\Logs\Scriptlog.log -Color White -log Info diff --git a/README.md b/README.md index 6c49f08..14ab72f 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ [![ARM](https://img.shields.io/static/v1?style=for-the-badge&logo=raspberrypi&logoColor=FFFFFF&message=ARM&color=A22846&label=)](walkthrough.md#arm-prerequisites) ## Introduction -This PowerShell script automates the process of generating images for your Plex/Jellyfin media library. Leveraging information from your Plex/Jellyfin library, such as movie or show titles, season and episode data, it fetches relevant artwork from Fanart.tv, TMDB, TVDB, Plex and IMDB. The script is able to focus on artwork with specific languages to grab. By default, textless artwork `xx` is retrieved and will fall back to `en` if textless is not found. This is a setting a user can decide on, either to focus on textless or on text posters. It also offers both automatic and manual modes for generating posters. The manual mode can accommodate custom creations that cannot be bulk retrieved. +This PowerShell script automates the process of generating images for your Plex/Jellyfin/Emby media library. Leveraging information from your Plex/Jellyfin/Emby library, such as movie or show titles, season and episode data, it fetches relevant artwork from Fanart.tv, TMDB, TVDB, Plex and IMDB. The script is able to focus on artwork with specific languages to grab. By default, textless artwork `xx` is retrieved and will fall back to `en` if textless is not found. This is a setting a user can decide on, either to focus on textless or on text posters. It also offers both automatic and manual modes for generating posters. The manual mode can accommodate custom creations that cannot be bulk retrieved. > [!NOTE] Posterizarr is cross-platform ready, meaning it can run on Linux (also arm), [Docker (Ubuntu 22.04 Base Image) does not work on ARM](#docker), [unRAID](#unraid) and on Windows operating systems. @@ -50,7 +50,7 @@ Posterizarr is cross-platform ready, meaning it can run on Linux (also arm), [Do > [!IMPORTANT] > You do not have to redeploy the container if the script version changes because it is not part of the container. > Container rebuilds only happen when there are changes to the ImageMagick, PowerShell, or other prerequisite versions. -> +> > If you want to install it on ARM please follow this carefully [ARM prerequisites](walkthrough.md#arm-prerequisites) @@ -67,18 +67,19 @@ Posterizarr is cross-platform ready, meaning it can run on Linux (also arm), [Do > You can find an example config for the Assets on my [Kometa-Configs repo](https://github.com/Kometa-Team/Community-Configs/blob/master/fscorrupt/config.yml) - **Upload to Plex**: If you do not have Kometa, posterizarr can directly Upload that Artwork to Plex. - **Upload to Jellyfin**: Posterizarr can directly upload the artwork to Jellyfin. +- **Upload to Emby**: Posterizarr can directly upload the artwork to Emby. - **Resizing**: It automatically resizes every poster to 2000x3000. - **Overlays**: If you choose to, downloaded images will automatically have borders, text, and a gradient overlay applied. - Here are some gradient overlays that you can use instead of the default one [gradient-zip](gradient_background_poster_overlays.zip) -- **Automatic Library Search**: The script autonomously searches for libraries within your Plex/Jellyfin server, enhancing its usability. +- **Automatic Library Search**: The script autonomously searches for libraries within your Plex/Jellyfin/Emby server, enhancing its usability. - **Handling Multiple Versions**: It adeptly manages multiple versions of a movie/show, ensuring comprehensive coverage. -- **CSV Export**: Produces an impressive CSV file containing all queried movie/show information during the script's runtime in `$ScriptRoot\logs\PlexLibexport.csv` or `$ScriptRoot\logs\JellyfinLibexport.csv` +- **CSV Export**: Produces an impressive CSV file containing all queried movie/show information during the script's runtime in `$ScriptRoot\logs\PlexLibexport.csv` or `$ScriptRoot\logs\OtherMediaServerLibExport.csv` - **Logging Capabilities**: Records valuable information to a file in `$ScriptRoot\logs\Scriptlog.log`, facilitating troubleshooting and analysis. - It also generates a log with the output of every imagemagick command `$ScriptRoot\logs\ImageMagickCommands.log`. - Additionally, an `ImageChoices.csv` file is generated to store all the selected download options and essential information. - Send notification via apprise or discord [Click here for Example pictures.](#webhook). -- **Cross-platform Compatibility**: Ensures seamless operation across Linux, Docker, and Windows Plex/Jellyfin servers, enhancing versatility. +- **Cross-platform Compatibility**: Ensures seamless operation across Linux, Docker, and Windows Plex/Jellyfin/Emby servers, enhancing versatility. - **Poster/Background/TitleCard Creation**: It searches fanart/tmdb/tvdb/Plex for posters/backgrounds/titlecards and resizes the downloaded image to 3840x2160 (for titlecards and backgrounds) or 2000x3000 (for posters), fallback is grabbing artwork from imdb. > [!NOTE] @@ -112,6 +113,7 @@ Posterizarr is cross-platform ready, meaning it can run on Linux (also arm), [Do - `FanartTvAPIKey`: Your Fanart personal API key. - `PlexToken`: Your Plex token (Leave empty if not applicable). - `JellyfinAPIKey`: Your Jellyfin API key. (You can create an API key from inside Jellyfin at Settings > Advanced > Api Keys.) + - `EmbyAPIKey`: Your Emby API key. (You can create an API key from inside Emby at Settings > Advanced > Api Keys.) - `FavProvider`: Set your preferred provider (default is `tmdb`). - possible values are: - `tmdb` (recommended) @@ -152,6 +154,14 @@ Posterizarr is cross-platform ready, meaning it can run on Linux (also arm), [Do - Also have a look at the hint: [Jellyfin CSS](#Jellyfin)
+ EmbyPart: +
+ + - `LibstoExclude`: Libraries, by local folder name, to exclude from processing. + - `EmbyUrl`: Plex server URL (i.e. "http://192.168.1.1:8096" or "http://myplexserver.com:8096"). + - `UseEmby`: If set to `true`, you tell the script to use a Emby Server (Default value is: `false`) +
+
Notification:
diff --git a/Release.txt b/Release.txt index f5d2a58..9dbb0c0 100644 --- a/Release.txt +++ b/Release.txt @@ -1 +1 @@ -1.6.3 \ No newline at end of file +1.7.0 \ No newline at end of file diff --git a/config.example.json b/config.example.json index 55f9296..fcdb22e 100644 --- a/config.example.json +++ b/config.example.json @@ -5,6 +5,7 @@ "FanartTvAPIKey": "FANARTAPIKEY", "PlexToken": "", "JellyfinAPIKey": "JELLYFINAPIKEY", + "EmbyAPIKey": "EMBYAPIKEY", "FavProvider": "tmdb", "WidthHeightFilter": "false", "PosterMinWidth": "2000", @@ -21,9 +22,14 @@ "UsePlex": "true" }, "JellyfinPart": { - "LibstoExclude": ["Youtube", "Audiobooks", "KidsAudiobooks", "TechTrainings"], - "JellyfinUrl": "http://192.168.1.93:8096", - "UseJellyfin": "false" + "LibstoExclude": ["Youtube", "Audiobooks", "KidsAudiobooks", "TechTrainings"], + "JellyfinUrl": "http://192.168.1.93:8096", + "UseJellyfin": "false" + }, + "EmbyPart": { + "LibstoExclude": ["Youtube", "Audiobooks", "KidsAudiobooks", "TechTrainings"], + "EmbyUrl": "http://192.168.1.93:8096/emby", + "UseEmby": "false" }, "Notification":{ "SendNotification":"False",