Skip to content

Instantly share code, notes, and snippets.

@sytone
Last active July 30, 2016 01:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sytone/637a14253dac119c41f7e2c1589dd614 to your computer and use it in GitHub Desktop.
Save sytone/637a14253dac119c41f7e2c1589dd614 to your computer and use it in GitHub Desktop.
Used to schedule recordings in Next PVR to fill missing items in EMBY.
<#
Set these values and uncomment.
$embyServerUrl = "http://localhost:8096"
$embyUsername = "user"
$embyPassword = "password"
$npvrServerUrl = "http://localhost:8866"
#>
$embyClientName = "PowerShellScript"
$embyDeviceName = "PowerShellScriptEpisodeFiller"
$embyDeviceId = "1"
$embyApplicationVersion = "1.0.0";
Function Get-StringHash([String] $String,$HashName = "MD5")
{
$StringBuilder = New-Object System.Text.StringBuilder
[System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{
[Void]$StringBuilder.Append($_.ToString("x2"))
}
$StringBuilder.ToString()
}
 
function Get-EmbyAccessToken {
[CmdletBinding()]
param ($Username, $Password)
$authUrl = "{0}/Users/AuthenticateByName?format=json" -f $embyServerUrl
$sha1Pass = Get-StringHash -String $password -HashName "SHA1"
$md5Pass = Get-StringHash -String $password
$postParams = (@{Username="$username";password="$sha1Pass";passwordMd5="$md5Pass"} | ConvertTo-Json)
$headers = @{"Authorization"="MediaBrowser Client=`"$embyClientName`", Device=`"$embyDeviceName`", DeviceId=`"$embyDeviceId`", Version=`"$embyApplicationVersion`""}
Write-Verbose ("authUrl={0},Username={1},sha1Pass={2},md5Pass={3},params={4}" -f $authUrl, $Username,$sha1Pass,$md5Pass,$postParams)
return (Invoke-WebRequest -Uri $authUrl -Method POST -Body $postParams -ContentType "application/json" -Headers $headers)
}
function Get-EmbyEpisodesMissingItems {
[CmdletBinding()]
param ($AccessToken)
$url = "{0}/Items?format=json&recursive=true&IncludeItemTypes=Episode&IsMissing=true" -f $embyServerUrl
$embyHeaderWithAccessToken = @{"X-MediaBrowser-Token"=$user.AccessToken}
Write-Verbose ("authUrl={0},Header={1}" -f $url, $embyHeaderWithAccessToken)
return (Invoke-WebRequest -Uri $url -Method GET -ContentType "application/json" -Headers $embyHeaderWithAccessToken)
}
function Get-NpvrAccessSid {
[CmdletBinding()]
param ($Pin)
$InstantiateUrl = "{0}/public/Util/NPVR/Client/Instantiate" -f $npvrServerUrl
$InitializeUrl = "{0}/public/Util/NPVR/Client/Initialize" -f $npvrServerUrl
$pinHash = Get-StringHash $Pin
$keys = Invoke-WebRequest -Uri $InstantiateUrl -Method Get
$clientKeys = $keys.Content | ConvertFrom-Json
$authString = ':'+ $pinHash + ':' + $clientKeys.clientKeys.salt
$authHash = Get-StringHash $authString
$sid = $clientKeys.clientKeys.sid
$authUrl = "{0}/{1}?sid={2}" -f $InitializeUrl,$authHash,$sid
$finalAuth = Invoke-WebRequest -Uri "$authUrl" -Method Get
return $sid
}
function Get-NpvrSearchResult {
[CmdletBinding()]
param ($Sid, $SearchTerm)
$SearchUrl = "{0}/public/SearchService/Search" -f $npvrServerUrl
$searchBody = @"
{
"searchName": "$searchTerm",
"autoShowSearch": true,
"autoRecordSearch": false,
"searchTitle": true,
"searchSubTitle": true,
"searchDescription": false,
"matchTitle": false,
"matchSubTitle": false,
"matchDescription": false,
"startTitle": false,
"startSubTitle": false,
"startDescription": false,
"searchPhrase": "$searchTerm",
"searchCaseSensitive": false,
}
"@
$fullSearchUrl = ("{0}?sid={1}" -f $SearchUrl, $sid)
$searchResults = Invoke-WebRequest -Uri $fullSearchUrl -Method Post -Body $searchBody -ContentType "application/json"
return $searchResults
}
function Get-NpvrScheduleServiceDefaults {
[CmdletBinding()]
param ($Sid)
$SearchUrl = "{0}/public/ScheduleService/Get/SchedSettingsObj" -f $npvrServerUrl
$fullSearchUrl = ("{0}?sid={1}" -f $SearchUrl, $sid)
$searchResults = Invoke-WebRequest -Uri $fullSearchUrl -Method Get -ContentType "application/json"
return ($searchResults.Content | ConvertFrom-Json)
}
function Get-NpvrScheduleServiceRecord {
[CmdletBinding()]
param ($Sid, $ChannelOid, $EpgEventOid, $start, $end)
$recordUrl = "{0}/public/ScheduleService/Record" -f $npvrServerUrl
$defaultSchedule = Get-NpvrScheduleServiceDefaults -Sid $Sid
$defaultSchedule.allChannels = $false
$defaultSchedule.ChannelOID = $ChannelOid
$defaultSchedule.epgeventOID = $EpgEventOid
$defaultSchedule.qualityDefault = $true
$defaultSchedule.recordOnce = $true
$defaultSchedule.startDate = $start
$defaultSchedule.endDate = $end
$fullRecordUrl = ("{0}?sid={1}" -f $recordUrl, $sid)
$recordResults = Invoke-WebRequest -Uri $fullRecordUrl -Method POST -ContentType "application/json" -Body ($defaultSchedule | ConvertTo-Json)
return ($recordResults.Content | ConvertFrom-Json)
}
function Get-NpvrManageServiceRecordingsSortFilterObj {
[CmdletBinding()]
param ($Sid)
$SearchUrl = "{0}/public/ManageService/Get/RecordingsSortFilterObj" -f $npvrServerUrl
$fullSearchUrl = ("{0}?sid={1}" -f $SearchUrl, $sid)
$searchResults = Invoke-WebRequest -Uri $fullSearchUrl -Method Get -ContentType "application/json"
return ($searchResults.Content | ConvertFrom-Json)
}
function Get-NpvrManageServiceRecordingsSummary {
[CmdletBinding()]
param ($Sid)
$recordingsSummaryUrl = "{0}/public/ManageService/Get/SortedFilteredList" -f $npvrServerUrl
$defaultSchedule = Get-NpvrManageServiceRecordingsSortFilterObj -Sid $Sid
$defaultSchedule.Pending = $true
$defaultSchedule.InProgress = $true
$fullRecordingsSummaryUrl = ("{0}?sid={1}" -f $recordingsSummaryUrl, $sid)
$recordResults = Invoke-WebRequest -Uri $fullRecordingsSummaryUrl -Method POST -ContentType "application/json" -Body ($defaultSchedule | ConvertTo-Json)
return ($recordResults.Content | ConvertFrom-Json)
}
$accessSid = Get-NpvrAccessSid -Pin "0000"
#$schedule = Get-NpvrScheduleService -Sid $accessSid
#$schedule.Content | ConvertFrom-Json
$recordings = Get-NpvrManageServiceRecordingsSummary -Sid $accessSid
$scheduled = @()
foreach($rec in $recordings.ManageResults.EPGEvents.epgEventJSONObject.epgEvent) {
$scheduled += "{0} - {1}" -f $rec.Title,$rec.Subtitle
}
$authResult = Get-EmbyAccessToken -Username $embyUsername -Password $embyPassword
$user = $authResult.Content | ConvertFrom-Json
$items = Get-EmbyEpisodesMissingItems -AccessToken $user.AccessToken -Verbose
$missingContent = $items.Content | ConvertFrom-Json
$missingContent.Items | % {
$seriesName = $_.SeriesName
$episodeName = $_.Name
$searchResults = Get-NpvrSearchResult -Sid $accessSid -SearchTerm $seriesName
$found = $searchResults.Content | ConvertFrom-Json
Write-Host ("Searching for: {0} - {1}" -f $seriesName,$episodeName)
#$found.SearchResults.EPGEvents[0]
$showsToRecord = $found.SearchResults.EPGEvents | ? {$_.epgEventJSONObject.epgEvent.Subtitle -eq $episodeName -and $_.epgEventJSONObject.epgEvent.StartTime -gt (Get-Date)}
if($showsToRecord.Count -gt 0) {
$showsToRecord[0] | % {
$found = "{0}: {1} - {2}`n {3} " -f $_.epgEventJSONObject.epgEvent.ChannelName,$_.epgEventJSONObject.epgEvent.Title,$_.epgEventJSONObject.epgEvent.Subtitle,$_.epgEventJSONObject.epgEvent.Desc
Write-Host ("Missing {0} from {1}" -f $episodeName, $seriesName)
Write-Host $found
$scheduleMatch = "{0} - {1}" -f $_.epgEventJSONObject.epgEvent.Title,$_.epgEventJSONObject.epgEvent.Subtitle
if($scheduled -contains $scheduleMatch) {
Write-Host "Already Scheduled"
} else {
$record = Get-NpvrScheduleServiceRecord -Sid $accessSid -ChannelOid ($_.epgEventJSONObject.epgEvent.ChannelOid) -EpgEventOid ($_.epgEventJSONObject.epgEvent.OID) `
-start $_.epgEventJSONObject.epgEvent.StartTime -end $_.epgEventJSONObject.epgEvent.EndTime
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment