Open victarmas opened 7 years ago
I run into the same problem. The nice solution would be a "-username" parameter to the script, and then getting prompted for the password. The second best would be variables to set at the top of the script.
You just need to edit the powershell script and add in your token. If you're a plex pass subscriber, I believe this is easy to get. If you don't, the easiest way I've found is to go to any item in your library, look at its info and click "view XML". The end of that string in your address bar will be your token "X-Plex-Token=****"
Take that token, and append it to the 3 times you see "$plex" string
line 8 and line 10:
$plex+"/library/sections/{0}/all?X-Plex-Token=xxxxxxxx"
line 15:
$doc.Load($plex+$_.key+"?X-Plex-Token=xxxxxx"
This should take care of authorization. If I was any better at Git, I'd upload the fixed file here. Maybe tonight :)
TylerAlmeida,
Thank you for your work on this! However, I am unable to get the script working even after fixing the token piece. Do you have an updated script? currently, I am getting the following errors:
The code I am using is:
param([String[]] $extras, [String[]] $libraries, [String] $plex="http://localhost:32400", [Int] $max=0)
Function Remove-InvalidFileNameChars { param([Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][String]$Name) $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''; $re = "[{0}]" -f [RegEx]::Escape($invalidChars); return ($Name -replace $re)}
$web=New-Object System.Net.WebCLient
$doc=New-Object System.Xml.XmlDocument
#imdb video types to plex extra content type mapping
$map=@{"Clip"="Scene";"Featurette"="Featurette";"Interview"="Interview";"Promo"="Short";"Trailer"="Trailer";"Video"="BehindTheScenes"}
#get all the library and filter them if $libraries is defined
$dirs=([xml]$web.DownloadString($plex+"/library/sections/{0}/all?X-Plex-Token=MYTOKEN")).MediaContainer.Directory | where {$libraries -eq $Null -or $libraries -contains $_.title }
#get all the movies of the libraries, select only the needed data and esclude all the already processed movies, which have the imdb_extras.xml file in their folder
$movies=$dirs | foreach{([xml]$web.DownloadString(($plex+"/library/sections/{0}/all?X-Plex-Token=MYTOKEN") -F $_.key)).MediaContainer.Video | where {$_.type -eq "movie"} | select -p key, title, year, @{Name="path"; Expression={(split-path -Path ([System.Uri]::UnescapeDataString($_.Media.Part.file)))}}, @{Name="imdb"; Expression={}} | where {!(test-path -LiteralPath ($_.path+"\imdb_extras.xml"))}} | sort -p title
if ($movies -eq $Null) { write-host (get-date) "All the movies have already been processed" }
else
{
#get imdb id from the movie details
$movies | foreach { $doc.Load($plex+$_.key+"?X-Plex-Token=MYTOKEN"); $_.imdb=[regex]::match($doc.MediaContainer.Video.guid,"imdb://(.*)\?").Groups[1].Value}
#search imdb id of unmatched movies with ombd with movie title and year
$movies | where { [System.String]::IsNullOrEmpty($_.imdb) } | foreach { $doc.Load(("http://www.omdbapi.com/?t={0}&y={1}&plot=short&r=xml" -F [System.Uri]::EscapeDataString($_.title), $_.year)); $_.imdb=$doc.root.movie.imdbID}
#get titles of unmatched movies
$nomatches=$movies | where { [System.String]::IsNullOrEmpty($_.imdb) } | foreach {$_.title}
if ($nomatches -ne $Null) { write-host (get-date) "There are unmached movies: " ($nomatches -join ", ") }
#removing movies without imdb key, which aren't yet identified by plex or with omdb
$movies=$movies | where { ![System.String]::IsNullOrEmpty($_.imdb) }
if ($movies -eq $Null) { write-host (get-date) "All other movies have already been processed" }
else
{
#if $max is defined processing only $max movies (it was a debugging feature, but it could be useful)
if ($max -gt 0) { $movies=$movies | select -first $max }
#get videos on imdb, max 60 videos (2 pages) per movie, the download url is missing here
$movies=$movies | select *,@{Name="videos"; Expression={$path=$_.path; $page=$web.DownloadString("http://www.imdb.com/title/{0}/videogallery?ref_=tt_ov_vi_sm" -F $_.imdb)+$web.DownloadString("http://www.imdb.com/title/{0}/videogallery?ref_=tt_ov_vi_sm&page=2" -F $_.imdb); [regex]::matches($page,',-1_ZA(.*?),.*?<a href="/video/imdb/(.*?)"[.|\s|\n|\r]*?>(.*?)</a>') | select @{Name="id"; Expression={$_.Groups[2].Value}},@{Name="type"; Expression={$map[$_.Groups[1].Value]}},@{Name="file"; Expression={(Remove-InvalidFileNameChars($_.Groups[3].Value))+".mp4"}},@{Name="url"; Expression={}} | where {$extras -eq $Null -or $extras -contains $_.type} }}
#get the download url of the videos, some videos require the age verification and thus an account and to login, skip those videos
$movies | foreach { write-host (get-date) "Processing" $_.title; if ($_.videos -eq $Null) { $_.videos = @() } else { $_.videos | foreach { $page=$web.DownloadString("http://www.imdb.com/video/imdb/{0}/imdb/single?vPage=1" -F $_.id); $_.url=[regex]::Match($page,'"videoMimeType":"video/mp4","videoUrl":"(.*?)"').Groups[1].Value } } }
#download videos and creating the imdb_extras.xml file, to avoid to process the movies again
$movies | foreach { $path=$_.path; $_.videos | foreach { $dir=$path+"\"+$_.type; if (!(test-path -LiteralPath $dir)) {New-Item -ItemType directory -Path $dir}; while(test-path -LiteralPath ($dir+"\"+$_.file)) {$_.file=$_.file.Replace(".mp4"," .mp4")}; if (!([System.String]::IsNullOrEmpty($_.url))) {$web.DownloadFile($_.url,$dir+"\"+$_.file)} }; [System.IO.File]::WriteAllText(($path+"\imdb_extras.xml"),($_ | ConvertTo-XML -Depth 2).OuterXML); }
}
}
I ended up shelling out for a plex membership, which includes this feature :) So I haven't messed with this in a while, but feel free compare to what I have: (note I've added the "$token" parameter to make it a bit simpler)
param([String[]] $extras, [String[]] $libraries, [String] $plex="http://localhost:32400", [Int] $max=0, [String] $token)
Function Remove-InvalidFileNameChars { param([Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][String]$Name) $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''; $re = "[{0}]" -f [RegEx]::Escape($invalidChars); return ($Name -replace $re)}
$web=New-Object System.Net.WebCLient
$doc=New-Object System.Xml.XmlDocument
#imdb video types to plex extra content type mapping
$map=@{"Clip"="Scene";"Featurette"="Featurette";"Interview"="Interview";"Promo"="Short";"Trailer"="Trailer";"Video"="BehindTheScenes"}
#get all the library and filter them if $libraries is defined
$dirs=([xml]$web.DownloadString($plex+"/library/sections?X-Plex-Token="+$token)).MediaContainer.Directory | where {$libraries -eq $Null -or $libraries -contains $_.title }
#get all the movies of the libraries, select only the needed data and esclude all the already processed movies, which have the imdb_extras.xml file in their folder
$movies=$dirs | foreach{([xml]$web.DownloadString(($plex+"/library/sections/{0}/all?X-Plex-Token="+$token) -F $_.key)).MediaContainer.Video | where {$_.type -eq "movie"} | select -p key, title, year, @{Name="path"; Expression={(split-path -Path ([System.Uri]::UnescapeDataString($_.Media.Part.file)))}}, @{Name="imdb"; Expression={}} | where {!(test-path -LiteralPath ($_.path+"\imdb_extras.xml"))}} | sort -p title
if ($movies -eq $Null) { write-host (get-date) "All the movies have already been processed" }
else
{
#get imdb id from the movie details
$movies | foreach { $doc.Load($plex+$_.key+"?X-Plex-Token="+$token); $_.imdb=[regex]::match($doc.MediaContainer.Video.guid,"imdb://(.*)\?").Groups[1].Value}
#search imdb id of unmatched movies with ombd with movie title and year
$movies | where { [System.String]::IsNullOrEmpty($_.imdb) } | foreach { $doc.Load(("http://www.omdbapi.com/?t={0}&y={1}&plot=short&r=xml" -F [System.Uri]::EscapeDataString($_.title), $_.year)); $_.imdb=$doc.root.movie.imdbID}
#get titles of unmatched movies
$nomatches=$movies | where { [System.String]::IsNullOrEmpty($_.imdb) } | foreach {$_.title}
if ($nomatches -ne $Null) { write-host (get-date) "There are unmached movies: " ($nomatches -join ", ") }
#removing movies without imdb key, which aren't yet identified by plex or with omdb
$movies=$movies | where { ![System.String]::IsNullOrEmpty($_.imdb) }
if ($movies -eq $Null) { write-host (get-date) "All other movies have already been processed" }
else
{
#if $max is defined processing only $max movies (it was a debugging feature, but it could be useful)
if ($max -gt 0) { $movies=$movies | select -first $max }
#get videos on imdb, max 60 videos (2 pages) per movie, the download url is missing here
$movies=$movies | select *,@{Name="videos"; Expression={$path=$_.path; $page=$web.DownloadString("http://www.imdb.com/title/{0}/videogallery?ref_=tt_ov_vi_sm" -F $_.imdb)+$web.DownloadString("http://www.imdb.com/title/{0}/videogallery?ref_=tt_ov_vi_sm&page=2" -F $_.imdb); [regex]::matches($page,',-1_ZA(.*?),.*?<a href="/video/imdb/(.*?)"[.|\s|\n|\r]*?>(.*?)</a>') | select @{Name="id"; Expression={$_.Groups[2].Value}},@{Name="type"; Expression={$map[$_.Groups[1].Value]}},@{Name="file"; Expression={(Remove-InvalidFileNameChars($_.Groups[3].Value))+".mp4"}},@{Name="url"; Expression={}} | where {$extras -eq $Null -or $extras -contains $_.type} }}
#get the download url of the videos, some videos require the age verification and thus an account and to login, skip those videos
$movies | foreach { write-host (get-date) "Processing" $_.title; if ($_.videos -eq $Null) { $_.videos = @() } else { $_.videos | foreach { $page=$web.DownloadString("http://www.imdb.com/video/imdb/{0}/imdb/single?vPage=1" -F $_.id); $_.url=[regex]::Match($page,'"videoMimeType":"video/mp4","videoUrl":"(.*?)"').Groups[1].Value } } }
#download videos and creating the imdb_extras.xml file, to avoid to process the movies again
$movies | foreach { $path=$_.path; $_.videos | foreach { $dir=$path+"\"+$_.type; if (!(test-path -LiteralPath $dir)) {New-Item -ItemType directory -Path $dir}; while(test-path -LiteralPath ($dir+"\"+$_.file)) {$_.file=$_.file.Replace(".mp4"," .mp4")}; if (!([System.String]::IsNullOrEmpty($_.url))) {$web.DownloadFile($_.url,$dir+"\"+$_.file)} }; [System.IO.File]::WriteAllText(($path+"\imdb_extras.xml"),($_ | ConvertTo-XML -Depth 2).OuterXML); }
}
}
I've had the Plex Pass for a long time, however, it doesn't seem to always be on-point for downloading trailers, this why I was looking for an alternate route. I also checked into Media Center Master. It does an 'OK' job, but it also sometimes has issues searching YouTube for trailers. So do I need to assign the $token variable my actual token to make things work?
Correct, pass the argument -token MYTOKEN when calling the script.
When trying to run the script, I get a 401 Unauthorized error. Should I be passing a token somehow?