Jump to content

Recommended Posts

Posted (edited)

What this solves:

  • Adding Channel Schedules in bulk to NextPVR
  • User Friendly Channel Names
  • Cleans up Channel Names
  • Prune Channels by Language
  • Download Channel Icons/Logos

Requirements:

References:

 

Notes:

I wrote this against two HDHomeRun Primes (Comcast Cable), so not sure how it will fair with OTA & Satellite. One might also be able to alter this script to work with other services, but since I don't have access to others, I can't add support for them.

 

How:

This is made up of two scripts, one will download & prep 1 or more JSON Channel lineups that you created on your Schedules Direct Account. The other will import information from one of the Lineups, into the data scrapped from a fresh Channel listing XML made by NextPVR, and output a new XML along with downloading all the Icon's\Logo's that Schedules Direct has to offer.

 

Instructions:

Install AutoIt and set it to execute scripts when double clicked.

 

Now Right Click on desktop and select "New\Folder" from the context menu, and Rename it "NextPVR Stuff"

 

Now download & extract Curl and FSUM into "NextPVR Stuff"

 

Now in "NextPVR Stuff" Right Click on the background and select "New\AutoIt v3 Script" from the context menu, and Rename it "Schedules Direct LineUp's.au3"

 

Now Right Click "Schedules Direct LineUp's.au3" & select "Edit Script" from the context menu.

 

Now paste the following code into:

 

 

 


$sUserName     = 'MyUserName'
$sUserPassword = 'MyUserPassword'


; Hash Password
FileWrite(  @ScriptDir & '\Password.txt' , $sUserPassword )
RunWait( @ComSpec & ' /c fsum.exe -sha1 -jnc "Password.txt">"' & @ScriptDir & '\EncryptedPassword.txt"' , @ScriptDir , @SW_HIDE )
$sUserPassword = StringLower( FileRead( @ScriptDir & '\EncryptedPassword.txt' , 40 ))
FileDelete( @ScriptDir & '\Password.txt' )
FileDelete( @ScriptDir & '\EncryptedPassword.txt' )

; Get Schedules Direct Token
RunWait( @ComSpec & ' /c curl.exe -X POST -H "Content-Type: application/json" -d "{\"username\":\"' & $sUserName & '\",\"password\":\"' & $sUserPassword & '\"}" https://json.schedulesdirect.org/20141201/token >"' & @ScriptDir & '\Token.txt"' , @ScriptDir , @SW_HIDE )

; Set Schedules Direct Token
$sBuffer = FileRead( @ScriptDir & '\Token.txt' )
$iBufferFind = StringInStr( $sBuffer , '"token":"' )
$sToken = StringTrimRight( StringTrimLeft( $sBuffer , $iBufferFind + 8 ) , 2 )
FileDelete( @ScriptDir & '\Token.txt' )

; Get Schedules Direct LineUps
RunWait( @ComSpec & ' /c curl.exe -v -H "token:' & $sToken & '" https://json.schedulesdirect.org/20141201/lineups >"' & @ScriptDir & '\LineUp.txt"' , @ScriptDir , @SW_HIDE )

; Set Schedules Direct LineUps
$sBuffer = FileRead( @ScriptDir & '\LineUp.txt' )
$aLineUp = StringRegExp( $sBuffer, '"name":"([^"]+)".+"uri":"([^"]+)"' , 3 )
For $ii = 0 To UBound( $aLineUp ) - 1 Step 2
	$aLineUp[$ii + 1] = 'https://json.schedulesdirect.org' & StringReplace( $aLineUp[$ii + 1] , '\' , '' )
	FileDelete( @ScriptDir & '\[LineUp] ' & $aLineUp[$ii] & '.txt' )
	RunWait( @ComSpec & ' /c curl.exe -v -H "token:' & $sToken & '" ' & $aLineUp[$ii + 1] & ' >"' & @ScriptDir & '\[LineUp] ' & $aLineUp[$ii] & '.txt"' , @ScriptDir , @SW_HIDE )
Next
FileDelete( @ScriptDir & '\LineUp.txt' )

MsgBox( 0 , 'Finsihed:' , "Station LineUp's Downloaded." )

 

 

 

Be sure to edit the values of $sUserName  and $sUserPassword to match what is used for your Schedules Direct account.

 

Now save the script & execute it by double clicking it and if all went well...then you should now see one or more txt files that are prefixed with "[LineUp]", these are the lineups you setup on your account.

 

Okay at this point one needs to fire up NextPVR.

 

Now with NextPVR open, Right Click on the background and select "Settings" from the context menu.

 

With the Settings Dialog open, Click Devices on the ListView on the left side of the dialog.

 

Select one of your Devices from the ListView on the right, it should be marked as Present & Enabled, (if it doesn't list any Channels, please Click the "Device Setup" Button, then perform a scan by Clicking the "Scan" button, then Click the "OK" button) with the device selected Click the "Export Channels" Button, when the Export Dialog comes up save the file to the location you have "NextPVR Stuff" which according to the instructions I've been giving should be on your Desktop.

 

Once you saved off the file and are back to the Settings dialog, Click the Channels item in the ListView on the left side.

 

With the Channels ListView now shown on the right, select one of the channels and Click the "Details" Button.

 

When the "Channel Details" Dialog pops up, in the EPG Source Group control, select "Schedules Direct"  from the Source comboBox...this should if I recall prompt you for your Schedules Direct account information...when it's done for the first time. After that set things to whatever...as it doesn't really matter...the main purpose is to have your Account info added to NextPVR's config...which I currently don't know the type of encryption used...so I can't automatically add it for you...via a script. Hence...doing this manually now.

 

So Click all the "OK" buttons till you are back to the main NextPVR form...now close NextPVR...as we are done with it for now.

 

Now in "NextPVR Stuff" Right Click on the background and select "New\AutoIt v3 Script" from the context menu, and Rename it "Merge Schedules Direct.au3"

 

Now Right Click "Merge Schedules Direct.au3" & select "Edit Script" from the context menu.

 

Now paste the following code into:

 

 

 

#include <Array.au3>

$sArtPath = 'C:\Users\Public\NPVR\Media\Channels\'
$sBuffer1 = FileRead( @ScriptDir & '\[LineUp] Comcast King County South - Digital.txt' )
$sBuffer2 = FileRead( @ScriptDir & '\channels-New.xml' )

$sLangsOnly = 'en'

$bRemoveParentheses = True
$bSplitOnDash       = True



If StringRight( $sArtPath , 1 ) <> '\' Then $sArtPath &= '\'


$sChannels = StringLeft(      $sBuffer1 , StringInStr( $sBuffer1  , 'stations' ))
$sChannels = StringTrimLeft( $sChannels , StringInStr( $sChannels , '[' ))
$sChannels = StringLeft(     $sChannels , StringInStr( $sChannels , ']' , 0 , -1 ) - 1 )

$aChannels = StringRegExp( $sChannels , '{([^}]+)}' , 3 )
Dim $aChannelIDs[UBound(   $aChannels ) + 1][2] = [[UBound( $aChannels )]]
For $ii = 0 To UBound( $aChannels ) - 1
	$aSegment = StringSplit( $aChannels[$ii] , ',' )
	$aID      = StringSplit( $aSegment[1]    , ':' )
	$aNumber  = StringSplit( $aSegment[2]    , ':' )
	$aChannelIDs[$ii + 1][0] = StringReplace( $aID[2]     , '"' , '' )
	$aChannelIDs[$ii + 1][1] = StringReplace( $aNumber[2] , '"' , '' )
	While StringLeft( $aChannelIDs[$ii + 1][1] , 1 ) = 0
		$aChannelIDs[$ii + 1][1] = StringTrimLeft( $aChannelIDs[$ii + 1][1] , 1 )
	WEnd
Next
;_ArrayDisplay( $aChannelIDs )


$sStations = StringTrimLeft( $sBuffer1  , StringInStr( $sBuffer1  , 'stations' ))
$sStations = StringTrimLeft( $sStations , StringInStr( $sStations , '{' ))
$sStations = StringLeft(     $sStations , StringInStr( $sStations , 'metadata' , -1 ))
$sStations = StringLeft(     $sStations , StringInStr( $sStations , '}' , 0 , -1 ) - 1 )

$aStations = StringSplit( $sStations , '},{' , 1 )
Dim $aStationInfo[$aStations[0] + 1][15] = [[$aStations[0]]]
For $ii = 1 To $aStations[0]
	If StringInStr( $aStations[$ii] , '"logo"' ) > 0 Then
		$sCurrentBuffer = StringTrimLeft( $aStations[$ii] , StringInStr( $aStations[$ii] , '"logo"' ) - 1 )
		$sCurrentBuffer = StringTrimLeft( $sCurrentBuffer , StringInStr( $sCurrentBuffer , '{' ))
		$sCurrentBuffer = StringLeft(     $sCurrentBuffer , StringInStr( $sCurrentBuffer , '}' , 0  , -1 ) - 1 )
		$aStations[$ii] = StringLeft(     $aStations[$ii] , StringInStr( $aStations[$ii] , '"logo"' , -1 ) - 2 )

		$aStationInfo[$ii][11] = _ArrayToString( StringRegExp( $sCurrentBuffer , '"URL":"([^"]+)"' , 1 ))
		$aStationInfo[$ii][12] = _ArrayToString( StringRegExp( $sCurrentBuffer , '"height":(\d+)'  , 1 ))
		$aStationInfo[$ii][13] = _ArrayToString( StringRegExp( $sCurrentBuffer , '"width":(\d+)'   , 1 ))
		$aStationInfo[$ii][14] = _ArrayToString( StringRegExp( $sCurrentBuffer , '"md5":"([^"]+)"' , 1 ))

		$aStationInfo[$ii][11] = StringReplace( $aStationInfo[$ii][11] , '\' , '' )
	EndIf
	If StringInStr( $aStations[$ii] , '"broadcaster"' ) > 0 Then
		$sCurrentBuffer = StringTrimLeft( $aStations[$ii] , StringInStr( $aStations[$ii] , '"broadcaster"' ) - 1 )
		$sCurrentBuffer = StringTrimLeft( $sCurrentBuffer , StringInStr( $sCurrentBuffer , '{' ))
		$sCurrentBuffer = StringLeft(     $sCurrentBuffer , StringInStr( $sCurrentBuffer , '}' , 0 , -1 ) - 1 )
		$aStations[$ii] = StringLeft(     $aStations[$ii] , StringInStr( $aStations[$ii] , '"broadcaster"' , -1  ) - 2 )

		$aStationInfo[$ii][7]  = _ArrayToString( StringRegExp( $sCurrentBuffer , '"city":"([^"]+)"'       , 1 ))
		$aStationInfo[$ii][8]  = _ArrayToString( StringRegExp( $sCurrentBuffer , '"state":"([^"]+)"'      , 1 ))
		$aStationInfo[$ii][9]  = _ArrayToString( StringRegExp( $sCurrentBuffer , '"postalcode":"([^"]+)"' , 1 ))
		$aStationInfo[$ii][10] = _ArrayToString( StringRegExp( $sCurrentBuffer , '"country":"([^"]+)"'    , 1 ))
	EndIf
	$aStationInfo[$ii][1] = _ArrayToString( StringRegExp( $aStations[$ii] , '"stationID":"(\d+)"'                 , 1 ))
	$aStationInfo[$ii][2] = _ArrayToString( StringRegExp( $aStations[$ii] , '"name":"([^"]+)"'                    , 1 ))
	$aStationInfo[$ii][3] = _ArrayToString( StringRegExp( $aStations[$ii] , '"callsign":"([^"]+)"'                , 1 ))
	$aStationInfo[$ii][4] = _ArrayToString( StringRegExp( $aStations[$ii] , '"affiliate":"([^"]+)"'               , 1 ))
	$aStationInfo[$ii][5] = _ArrayToString( StringRegExp( $aStations[$ii] , '"broadcastLanguage":\["([^"]+)"\]'   , 1 ))
	$aStationInfo[$ii][6] = _ArrayToString( StringRegExp( $aStations[$ii] , '"descriptionLanguage":\["([^"]+)"\]' , 1 ))
	For $jj = 1 To 14
		If $aStationInfo[$ii][$jj] = '-1' Then $aStationInfo[$ii][$jj] = ''
	Next
Next
For $ii = 1 To $aChannelIDs[0][0]
	$iIndex = _ArraySearch( $aStationInfo , $aChannelIDs[$ii][0] , 1 , 0 , 0 , 0 , 1 , 1 )
	If NOT @Error Then $aStationInfo[$iIndex][0] = $aChannelIDs[$ii][1]
Next
;_ArrayDisplay( $aStationInfo )


$aXMLList = StringRegExp( $sBuffer2 , '(?s)<Channel>(.+?)</Channel>' , 3 )
Dim $aNextPVR[UBound(  $aXMLList ) + 1][10] = [[UBound( $aXMLList )]]
For $ii = 0 To UBound( $aXMLList ) - 1
	$aNextPVR[$ii + 1][0] = _ArrayToString( StringRegExp( $aXMLList[$ii] , '<Name>(.+?)</Name>'               , 1 ))
	$aNextPVR[$ii + 1][1] = _ArrayToString( StringRegExp( $aXMLList[$ii] , '<Number>(.+?)</Number>'           , 1 ))
	$aNextPVR[$ii + 1][2] = _ArrayToString( StringRegExp( $aXMLList[$ii] , '<ServiceType>(.+?)</ServiceType>' , 1 ))
	$aNextPVR[$ii + 1][3] = _ArrayToString( StringRegExp( $aXMLList[$ii] , '<type>(.+?)</type>'               , 1 ))
	$aNextPVR[$ii + 1][4] = _ArrayToString( StringRegExp( $aXMLList[$ii] , '<service_id>(.+?)</service_id>'   , 1 ))

	$sCurrentBuffer = _ArrayToString( StringRegExp( $aXMLList[$ii] , '(?s)<locator>(.+?)</locator>' , 1 ))

	$aNextPVR[$ii + 1][5] = _ArrayToString( StringRegExp( $sCurrentBuffer , '<sid>(.+?)</sid>'   , 1 ))
	$aNextPVR[$ii + 1][6] = _ArrayToString( StringRegExp( $sCurrentBuffer , '<tsid>(.+?)</tsid>' , 1 ))
	$aNextPVR[$ii + 1][7] = _ArrayToString( StringRegExp( $sCurrentBuffer , '<map>(.+?)</map>'   , 1 ))
	$aNextPVR[$ii + 1][8] = _ArrayToString( StringRegExp( $sCurrentBuffer , '<chan>(.+?)</chan>' , 1 ))
	$aNextPVR[$ii + 1][9] = _ArrayToString( StringRegExp( $sCurrentBuffer , '<name>(.+?)</name>' , 1 ))
Next
;_ArrayDisplay( $aNextPVR )


$sString = '<Channels Type="Other">' & @CRLF
For $ii = 1 To $aNextPVR[0][0]
	$iIndex = _ArraySearch( $aStationInfo , $aNextPVR[$ii][1] , 1 , 0 , 0 , 0 , 1 , 0 )
	If NOT @Error Then
		$aStationInfo[$iIndex][0] = $aChannelIDs[$ii][1]
		If $sLangsOnly <> '' Then
			If StringInStr( $sLangsOnly , $aStationInfo[$iIndex][5] ) = 0 Then ContinueLoop
		EndIf
		If $bRemoveParentheses = True Then
			If StringInStr( $aStationInfo[$iIndex][2] , ' (' ) > 0 Then $aStationInfo[$iIndex][2] = StringLeft( $aStationInfo[$iIndex][2] , StringInStr( $aStationInfo[$iIndex][2] , ' (' ) - 1 )
			If StringInStr( $aStationInfo[$iIndex][4] , ' (' ) > 0 Then $aStationInfo[$iIndex][4] = StringLeft( $aStationInfo[$iIndex][4] , StringInStr( $aStationInfo[$iIndex][4] , ' (' ) - 1 )
		EndIf
		If $bSplitOnDash = True Then
			If StringInStr( $aStationInfo[$iIndex][2] , ' - ' ) > 0 Then
				$aSplit = StringSplit( $aStationInfo[$iIndex][2] , ' - ' , 1 )
				If StringInStr( $aSplit[2] , ' HD' ) > 0 AND StringInStr( $aSplit[1] , ' HD' ) = 0 Then $aSplit[1] &= ' HD'
				$aStationInfo[$iIndex][2] = $aSplit[1]
			EndIf

			If StringInStr( $aStationInfo[$iIndex][4] , ' - ' ) > 0 Then
				$aSplit = StringSplit( $aStationInfo[$iIndex][4] , ' - ' , 1 )
				If StringInStr( $aSplit[2] , ' HD' ) > 0 AND StringInStr( $aSplit[1] , ' HD' ) = 0 Then $aSplit[1] &= ' HD'
				$aStationInfo[$iIndex][4] = $aSplit[1]
			EndIf
		EndIf
		$sString &= '  <Channel>'        & @CRLF
		If $aStationInfo[$iIndex][4] <> '' Then
			$sString &= '    <Name>'      & _Markup_Normal_To_Special( $aStationInfo[$iIndex][4] ) & '</Name>' & @CRLF
		Else
			$sString &= '    <Name>'      & _Markup_Normal_To_Special( $aStationInfo[$iIndex][2] ) & '</Name>' & @CRLF
		EndIf
		$sString &= '    <Number>'       & $aNextPVR[$ii][1] & '</Number>'      & @CRLF
		$sString &= '    <ServiceType>'  & $aNextPVR[$ii][2] & '</ServiceType>' & @CRLF
		$sString &= '    <tuning>'       & @CRLF
		$sString &= '      <type>'       & $aNextPVR[$ii][3] & '</type>'       & @CRLF
		$sString &= '      <service_id>' & $aNextPVR[$ii][4] & '</service_id>' & @CRLF
		$sString &= '      <locator>'    & @CRLF
		$sString &= '        <sid>'      & $aNextPVR[$ii][5] & '</sid>'  & @CRLF
		$sString &= '        <tsid>'     & $aNextPVR[$ii][6] & '</tsid>' & @CRLF
		$sString &= '        <map>'      & $aNextPVR[$ii][7] & '</map>'  & @CRLF
		$sString &= '        <chan>'     & $aNextPVR[$ii][8] & '</chan>' & @CRLF
		If $aStationInfo[$iIndex][4] <> '' Then
			$sString &= '        <name>'  & _Markup_Normal_To_Special( $aStationInfo[$iIndex][4] ) & '</name>' & @CRLF
		Else
			$sString &= '        <name>'  & _Markup_Normal_To_Special( $aStationInfo[$iIndex][2] ) & '</name>' & @CRLF
		EndIf
		$sString &= '      </locator>'   & @CRLF
		$sString &= '    </tuning>'      & @CRLF
		$sString &= '    <EPGSource>Schedules Direct</EPGSource>' & @CRLF
		$sString &= '    <epg>' & @CRLF
		$sString &= '      <source>Schedules Direct</source>' & @CRLF
		$sString &= '      <station>' & $aStationInfo[$iIndex][1] & '</station>' & @CRLF
		$sString &= '    </epg>' & @CRLF
		$sString &= '  </Channel>' & @CRLF

		If $aStationInfo[$iIndex][11] <> '' Then
			$sFileExt = StringTrimLeft( $aStationInfo[$iIndex][11] , StringInStr( $aStationInfo[$iIndex][11] , '.' , 0 , -1 ) - 1 )
			If $aStationInfo[$iIndex][4] <> '' Then
				InetGet( $aStationInfo[$iIndex][11] , $sArtPath & $aStationInfo[$iIndex][4] & $sFileExt )
			Else
				InetGet( $aStationInfo[$iIndex][11] , $sArtPath & $aStationInfo[$iIndex][2] & $sFileExt )
			EndIf
		EndIf
	EndIf
Next
$sString &= '</Channels>' & @CRLF

FileDelete( @ScriptDir & '\New.xml' )
FileWrite(  @ScriptDir & '\New.xml' , $sString )

MsgBox( 0 , 'Finsihed:' , "Merge Completed." )



; Markup Normal to Special
Func _Markup_Normal_To_Special( $String )
	$String = StringReplace( $String , Chr( 38  ) , "&"		, 0 , 1 ) ; & ampersand
	$String = StringReplace( $String , Chr( 34  ) , """	, 0 , 1 ) ; " quotation mark
	$String = StringReplace( $String , Chr( 39  ) , "'"	, 0 , 1 ) ; ' apostrophe
	$String = StringReplace( $String , Chr( 60  ) , "<"		, 0 , 1 ) ; < less-than
	$String = StringReplace( $String , Chr( 62  ) , ">"		, 0 , 1 ) ; > greater-than
	$String = StringReplace( $String , Chr( 161 ) , "¡"	, 0 , 1 ) ; ¡ inverted exclamation mark
	$String = StringReplace( $String , Chr( 162 ) , "¢"	, 0 , 1 ) ; ¢ cent
	$String = StringReplace( $String , Chr( 163 ) , "£"	, 0 , 1 ) ; £ pound
	$String = StringReplace( $String , Chr( 164 ) , "¤"	, 0 , 1 ) ; ¤ currency
	$String = StringReplace( $String , Chr( 165 ) , "¥"		, 0 , 1 ) ; ¥ yen
	$String = StringReplace( $String , Chr( 166 ) , "¦"	, 0 , 1 ) ; ¦ broken vertical bar
	$String = StringReplace( $String , Chr( 167 ) , "§"	, 0 , 1 ) ; § section
	$String = StringReplace( $String , Chr( 168 ) , "¨"		, 0 , 1 ) ; ¨ spacing diaeresis
	$String = StringReplace( $String , Chr( 169 ) , "©"	, 0 , 1 ) ; © copyright
	$String = StringReplace( $String , Chr( 170 ) , "ª"	, 0 , 1 ) ; ª feminine ordinal indicator
	$String = StringReplace( $String , Chr( 171 ) , "«"	, 0 , 1 ) ; « angle quotation mark (left)
	$String = StringReplace( $String , Chr( 172 ) , "¬"		, 0 , 1 ) ; ¬ negation
	$String = StringReplace( $String , Chr( 173 ) , "­"		, 0 , 1 ) ; ­ soft hyphen
	$String = StringReplace( $String , Chr( 174 ) , "®"		, 0 , 1 ) ; ® registered trademark
	$String = StringReplace( $String , Chr( 175 ) , "¯"	, 0 , 1 ) ; ¯ spacing macron
	$String = StringReplace( $String , Chr( 176 ) , "°"		, 0 , 1 ) ; ° degree
	$String = StringReplace( $String , Chr( 177 ) , "±"	, 0 , 1 ) ; ± plus-or-minus
	$String = StringReplace( $String , Chr( 178 ) , "²"	, 0 , 1 ) ; ² superscript 2
	$String = StringReplace( $String , Chr( 179 ) , "³"	, 0 , 1 ) ; ³ superscript 3
	$String = StringReplace( $String , Chr( 180 ) , "´"	, 0 , 1 ) ; ´ spacing acute
	$String = StringReplace( $String , Chr( 181 ) , "µ"	, 0 , 1 ) ; µ micro
	$String = StringReplace( $String , Chr( 182 ) , "¶"	, 0 , 1 ) ; ¶ paragraph
	$String = StringReplace( $String , Chr( 183 ) , "·"	, 0 , 1 ) ; · middle dot
	$String = StringReplace( $String , Chr( 184 ) , "¸"	, 0 , 1 ) ; ¸ spacing cedilla
	$String = StringReplace( $String , Chr( 185 ) , "¹"	, 0 , 1 ) ; ¹ superscript 1
	$String = StringReplace( $String , Chr( 186 ) , "º"	, 0 , 1 ) ; º masculine ordinal indicator
	$String = StringReplace( $String , Chr( 187 ) , "»"	, 0 , 1 ) ; » angle quotation mark (right)
	$String = StringReplace( $String , Chr( 188 ) , "¼"	, 0 , 1 ) ; ¼ fraction 1/4
	$String = StringReplace( $String , Chr( 189 ) , "½"	, 0 , 1 ) ; ½ fraction 1/2
	$String = StringReplace( $String , Chr( 190 ) , "¾"	, 0 , 1 ) ; ¾ fraction 3/4
	$String = StringReplace( $String , Chr( 191 ) , "¿"	, 0 , 1 ) ; ¿ inverted question mark
	$String = StringReplace( $String , Chr( 215 ) , "×"	, 0 , 1 ) ; × multiplication
	$String = StringReplace( $String , Chr( 247 ) , "÷"	, 0 , 1 ) ; ÷ division
	$String = StringReplace( $String , Chr( 192 ) , "À"	, 0 , 1 ) ; À capital a, grave accent
	$String = StringReplace( $String , Chr( 193 ) , "Á"	, 0 , 1 ) ; Á capital a, acute accent
	$String = StringReplace( $String , Chr( 194 ) , "Â"	, 0 , 1 ) ; Â capital a, circumflex accent
	$String = StringReplace( $String , Chr( 195 ) , "Ã"	, 0 , 1 ) ; Ã capital a, tilde
	$String = StringReplace( $String , Chr( 196 ) , "Ä"	, 0 , 1 ) ; Ä capital a, umlaut mark
	$String = StringReplace( $String , Chr( 197 ) , "Å"	, 0 , 1 ) ; Å capital a, ring
	$String = StringReplace( $String , Chr( 198 ) , "Æ"	, 0 , 1 ) ; Æ capital ae
	$String = StringReplace( $String , Chr( 199 ) , "Ç"	, 0 , 1 ) ; Ç capital c, cedilla
	$String = StringReplace( $String , Chr( 200 ) , "È"	, 0 , 1 ) ; È capital e, grave accent
	$String = StringReplace( $String , Chr( 201 ) , "É"	, 0 , 1 ) ; É capital e, acute accent
	$String = StringReplace( $String , Chr( 202 ) , "Ê"	, 0 , 1 ) ; Ê capital e, circumflex accent
	$String = StringReplace( $String , Chr( 203 ) , "Ë"	, 0 , 1 ) ; Ë capital e, umlaut mark
	$String = StringReplace( $String , Chr( 204 ) , "Ì"	, 0 , 1 ) ; Ì capital i, grave accent
	$String = StringReplace( $String , Chr( 205 ) , "Í"	, 0 , 1 ) ; Í capital i, acute accent
	$String = StringReplace( $String , Chr( 206 ) , "Î"	, 0 , 1 ) ; Î capital i, circumflex accent
	$String = StringReplace( $String , Chr( 207 ) , "Ï"	, 0 , 1 ) ; Ï capital i, umlaut mark
	$String = StringReplace( $String , Chr( 208 ) , "Ð"		, 0 , 1 ) ; Ð capital eth, Icelandic
	$String = StringReplace( $String , Chr( 209 ) , "Ñ"	, 0 , 1 ) ; Ñ capital n, tilde
	$String = StringReplace( $String , Chr( 210 ) , "Ò"	, 0 , 1 ) ; Ò capital o, grave accent
	$String = StringReplace( $String , Chr( 211 ) , "Ó"	, 0 , 1 ) ; Ó capital o, acute accent
	$String = StringReplace( $String , Chr( 212 ) , "Ô"	, 0 , 1 ) ; Ô capital o, circumflex accent
	$String = StringReplace( $String , Chr( 213 ) , "Õ"	, 0 , 1 ) ; Õ capital o, tilde
	$String = StringReplace( $String , Chr( 214 ) , "Ö"	, 0 , 1 ) ; Ö capital o, umlaut mark
	$String = StringReplace( $String , Chr( 216 ) , "Ø"	, 0 , 1 ) ; Ø capital o, slash
	$String = StringReplace( $String , Chr( 217 ) , "Ù"	, 0 , 1 ) ; Ù capital u, grave accent
	$String = StringReplace( $String , Chr( 218 ) , "Ú"	, 0 , 1 ) ; Ú capital u, acute accent
	$String = StringReplace( $String , Chr( 219 ) , "Û"	, 0 , 1 ) ; Û capital u, circumflex accent
	$String = StringReplace( $String , Chr( 220 ) , "Ü"	, 0 , 1 ) ; Ü capital u, umlaut mark
	$String = StringReplace( $String , Chr( 221 ) , "Ý"	, 0 , 1 ) ; Ý capital y, acute accent
	$String = StringReplace( $String , Chr( 222 ) , "Þ"	, 0 , 1 ) ; Þ capital THORN, Icelandic
	$String = StringReplace( $String , Chr( 223 ) , "ß"	, 0 , 1 ) ; ß small sharp s, German
	$String = StringReplace( $String , Chr( 224 ) , "à"	, 0 , 1 ) ; à small a, grave accent
	$String = StringReplace( $String , Chr( 225 ) , "á"	, 0 , 1 ) ; á small a, acute accent
	$String = StringReplace( $String , Chr( 226 ) , "â"	, 0 , 1 ) ; â small a, circumflex accent
	$String = StringReplace( $String , Chr( 227 ) , "ã"	, 0 , 1 ) ; ã small a, tilde
	$String = StringReplace( $String , Chr( 228 ) , "ä"	, 0 , 1 ) ; ä small a, umlaut mark
	$String = StringReplace( $String , Chr( 229 ) , "å"	, 0 , 1 ) ; å small a, ring
	$String = StringReplace( $String , Chr( 230 ) , "æ"	, 0 , 1 ) ; æ small ae
	$String = StringReplace( $String , Chr( 231 ) , "ç"	, 0 , 1 ) ; ç small c, cedilla
	$String = StringReplace( $String , Chr( 232 ) , "è"	, 0 , 1 ) ; è small e, grave accent
	$String = StringReplace( $String , Chr( 233 ) , "é"	, 0 , 1 ) ; é small e, acute accent
	$String = StringReplace( $String , Chr( 234 ) , "ê"	, 0 , 1 ) ; ê small e, circumflex accent
	$String = StringReplace( $String , Chr( 235 ) , "ë"	, 0 , 1 ) ; ë small e, umlaut mark
	$String = StringReplace( $String , Chr( 236 ) , "ì"	, 0 , 1 ) ; ì small i, grave accent
	$String = StringReplace( $String , Chr( 237 ) , "í"	, 0 , 1 ) ; í small i, acute accent
	$String = StringReplace( $String , Chr( 238 ) , "î"	, 0 , 1 ) ; î small i, circumflex accent
	$String = StringReplace( $String , Chr( 239 ) , "ï"	, 0 , 1 ) ; ï small i, umlaut mark
	$String = StringReplace( $String , Chr( 240 ) , "ð"		, 0 , 1 ) ; ð small eth, Icelandic
	$String = StringReplace( $String , Chr( 241 ) , "ñ"	, 0 , 1 ) ; ñ small n, tilde
	$String = StringReplace( $String , Chr( 242 ) , "ò"	, 0 , 1 ) ; ò small o, grave accent
	$String = StringReplace( $String , Chr( 243 ) , "ó"	, 0 , 1 ) ; ó small o, acute accent
	$String = StringReplace( $String , Chr( 244 ) , "ô"	, 0 , 1 ) ; ô small o, circumflex accent
	$String = StringReplace( $String , Chr( 245 ) , "õ"	, 0 , 1 ) ; õ small o, tilde
	$String = StringReplace( $String , Chr( 246 ) , "ö"	, 0 , 1 ) ; ö small o, umlaut mark
	$String = StringReplace( $String , Chr( 248 ) , "ø"	, 0 , 1 ) ; ø small o, slash
	$String = StringReplace( $String , Chr( 249 ) , "ù"	, 0 , 1 ) ; ù small u, grave accent
	$String = StringReplace( $String , Chr( 250 ) , "ú"	, 0 , 1 ) ; ú small u, acute accent
	$String = StringReplace( $String , Chr( 251 ) , "û"	, 0 , 1 ) ; û small u, circumflex accent
	$String = StringReplace( $String , Chr( 252 ) , "ü"	, 0 , 1 ) ; ü small u, umlaut mark
	$String = StringReplace( $String , Chr( 253 ) , "ý"	, 0 , 1 ) ; ý small y, acute accent
	$String = StringReplace( $String , Chr( 254 ) , "þ"	, 0 , 1 ) ; þ small thorn, Icelandic
	$String = StringReplace( $String , Chr( 255 ) , "ÿ"	, 0 , 1 ) ; ÿ small y, umlaut mark
	Return $String
EndFunc

 

 

 

You will now need to edit some of the variables, at the top of the script, to match what you have or want:

 

$sArtPath

  • this is where your logo's are for NextPVR to make use of them

$sBuffer1

  • this is your Schedules Direct Lineup that you intend to use

$sBuffer2

  • this is the xml with the list of channels detected by NextPVR

$sLangsOnly

  • leave this empty if you do not wish to prune any langs...if you do however wish to remove other langs, add all the langs you wish to keep, but split them with a comma

$bRemoveParentheses

  • this will remove anything in paren's...review your Schedules Direct file to help decide if you wish to prune these or not

$bSplitOnDash

  • this will remove the dash and anything on the right side of it, note that a space must be both before and after the dash, for a split to occure

 

Now save the script & execute it by double clicking it and if all went well...then you should see a bunch of images in the path you set for $sArtPath, and a new file called "New.xml" that is ready to be imported into NextPVR.

 

Alright time to fire up NextPVR once again.

 

Now with NextPVR open, Right Click on the background and select "Settings" from the context menu.

 

With the Settings Dialog open, Click Devices on the ListView on the left side of the dialog.

 

Select one of your Devices from the ListView on the right, (it should be marked as Present & Enabled) now Click "Device Setup" Button, and wait for the new dialog to open, once open Click on the first channel in the ListView, then scroll down to the last and SHIFT + Click on it, then Click on the "Delete" Button followed by the "OK" Button. Once the dialog closes repeat this for every Device you intend to apply a new Channel List to.

 

Select one of your Devices from the ListView on the right, now Click the "Import Channels" Button and navigate to the "NextPVR Stuff" folder, and select "New.xml", then Click the "Open" Button. Repeat this for every device this channel list applies to.

 

Once done with that, Click the Channels item in the ListView on the left side.

 

With the Channels ListView now shown on the right, Click the "Update EPG" Button, then wait till the update is complete, and Click the "OK" Button to close out the Settings dialog.

 

Now when you select the "TV Guide" on the main NextPVR form...you should be greated with all your show info, pretty names...and hopefully a bunch of icons. :)

Edited by Nologic
  • Like 2
Posted

Nice :)

Tried it out yesterday & it worked pretty well.

 

A Few Notes:

  • I needed to use Curl with SSL
  • I needed to add the -k switch to all the curl commands in "Schedules Direct LineUp's.au3" to allow "insecure" SSL connections because Schedules Direct was failing on the certificate check.
    RunWait( @ComSpec & ' /c curl.exe -k ...

     

  • Before importing the "New.xml", I needed to remove all existing channels.

 

Other than that, worked well...Thanks :)

  • Like 1
Posted (edited)

Doh! I completely forgot about removing the channels. The issues with Curl I wasn't aware of because of the build I grabbed had SSL & came with a Cert.

 

Many thanks for a very complete bug report, and sorry you had to trouble shoot things to get it to work correctly.

Edited by Nologic
  • Like 1
Posted

The Schedules Direct certificate should be valid; it was generated / authenticated by a valid issuer. If you can let me know what's failing with curl then I can try to see what's happening.

Posted

Howdy, it has more to do with Curl being able to validate a websites Cert.

 

The build I used came with a file to validate web certs.

 

Here is the head of the file, along with one cert...from a collection of many in the file:

##
## Bundle of CA Root Certificates
##
## Certificate data from Mozilla as of: Sat Jun 20 20:21:50 2015
##
## This is a bundle of X.509 certificates of public Certificate Authorities
## (CA). These were automatically extracted from Mozilla's root certificates
## file (certdata.txt).  This file can be found in the mozilla source tree:
## http://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
##
## It contains the certificates in PEM format and therefore
## can be directly used with curl / libcurl / php_curl, or with
## an Apache+mod_ssl webserver for SSL client authentication.
## Just configure this file as the SSLCACertificateFile.
##
## Conversion done with mk-ca-bundle.pl version 1.25.
## SHA1: ed3c0bbfb7912bcc00cd2033b0cb85c98d10559c
##


Equifax Secure CA
=================
-----BEGIN CERTIFICATE-----
MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
70+sB3c4
-----END CERTIFICATE-----

So since I had such a file, and I didn't run into the error like VladTepz did, you can safely deduce that your Cert is indeed valid.

 

You can find out more about this file from here and here.

 

Oh and a quote from here.

 

10.2 Certificates

In the HTTPS world, you use certificates to validate that you are the one you claim to be, as an addition to normal passwords. Curl supports client- side certificates. All certificates are locked with a pass phrase, which you need to enter before the certificate can be used by curl. The pass phrase can be specified on the command line or if not, entered interactively when curl queries for it. Use a certificate with curl on a HTTPS server like:

 curl --cert mycert.pem https://secure.example.com

curl also tries to verify that the server is who it claims to be, by verifying the server's certificate against a locally stored CA cert bundle. Failing the verification will cause curl to deny the connection. You must then use --insecure (-k) in case you want to tell curl to ignore that the server can't be verified.

More about server certificate verification and ca cert bundles can be read in the SSLCERTS document, available online here:

 http://curl.haxx.se/docs/sslcerts.html

At times you may end up with your own CA cert store and then you can tell curl to use that to verify the server's certificate:

 curl --cacert ca-bundle.pem https://example.com/
Posted (edited)

"Now save the script & execute it by double clicking it and if all went well...then you should now see one or more txt files that are prefixed with "[LineUp]", these are the lineups you setup on your account."

This seems to only work for North America, since you can't configure lineups in the Schedules Direct site outside NA. It should be done in an app.

Edited by Damstas
Posted

You are correct, the original script only works for North America...I'm looking into making an alternate version that should ideally work for everyone supported by Schedules Direct.

 

Keep in mind my use of Curl is novice level at best...so might fail. Given the API only has examples for Postman...which is honestly better than nothing. :)

 

By app I'm assuming you mean a GUI based one...not sure that is required...but I'm sure a lot of users would feel far more comfortable with controls to interact with...rather than editing variables...for some programming lang they likely know little about. So we'll see how smoothly things go and if I feel up to or feel its worth doing a full blown GUI...right now just need to see if I can make something work.

Posted (edited)

Okay I started this a little while ago...but had to spend a little time in the hospital so...kind of delayed getting this out the door.
 
So below is the code for a rough GUI to handle all the regions and countries that Schedules Direct supports. This basically replaces the first script at the top of the thread.
 
At present the code doesn't do a good job of try\catch for errors...just gives a weak reason why things went wrong & bails...I'll likely fix this later on.
 
Also when you press a button, I don't give decent feedback at present that the app\script is waiting on a reply from Schedules Direct...so give things a few seconds after clicking.
 
Anyways so it's rough...but works generally.

 

 

 

#include <Array.au3>

#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <EditConstants.au3>
#include <GuiComboBox.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Opt( 'GUIOnEventMode' , 1 )

Global $sMyToken , $aCountries , $aRegions , $aLineUps
Global $aMyLineUps , $sMyToken


#Region ### START Koda GUI section ### Form=C:\Program Files (x86)\AutoIt3\SciTE\Koda\Forms\SchedulesDirectFE.kxf
$SchedulesDirectFE = GUICreate("Schedules Direct FE", 638, 409, 192, 124)
	$lbl_Region  = GUICtrlCreateLabel("Region:", 9, 13, 41, 17)
	$cbo_Region  = GUICtrlCreateCombo("", 55, 10, 114, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
	$lbl_Country = GUICtrlCreateLabel("Country:", 184, 13, 43, 17)
	$cbo_Country = GUICtrlCreateCombo("", 232, 10, 169, 25, BitOR($CBS_DROPDOWN,$CBS_AUTOHSCROLL))
	$lbl_ZipCode = GUICtrlCreateLabel("Zip Code:", 416, 13, 50, 17)
	$inp_ZipCode = GUICtrlCreateInput("", 471, 10, 74, 21)
	$btn_Update  = GUICtrlCreateButton("UpDate", 554, 8, 75, 25)

	$grp_Available = GUICtrlCreateGroup(" Available LineUps ", 10, 39, 304, 360)
		$lst_Available = GUICtrlCreateList("", 22, 62, 280, 292)
		$lbl_WebSite   = GUICtrlCreateLabel("Schedules Direct", 22, 369, 120, 17)
		$btn_Add       = GUICtrlCreateButton("Add", 228, 363, 75, 25)
	GUICtrlCreateGroup("", -99, -99, 1, 1)

	$grp_Active = GUICtrlCreateGroup(" Active LineUps ", 324, 39, 304, 360)
		$lst_Active = GUICtrlCreateList("", 336, 62, 280, 292)
		$btn_Remove = GUICtrlCreateButton("Remove", 335, 363, 75, 25)
		$btn_Export = GUICtrlCreateButton("Export", 542, 363, 75, 25)
	GUICtrlCreateGroup("", -99, -99, 1, 1)

	GUISetOnEvent( $GUI_EVENT_CLOSE , "_btn_Exit" , $SchedulesDirectFE )
	GUICtrlSetOnEvent( $cbo_Region  , "_cbo_Region"  )
	GUICtrlSetOnEvent( $cbo_Country , "_cbo_Country" )
	GUICtrlSetOnEvent( $btn_Update  , "_btn_Update"  )
	GUICtrlSetOnEvent( $lbl_WebSite , "_lbl_WebSite" )
	GUICtrlSetOnEvent( $btn_Add     , "_btn_Add"     )
	GUICtrlSetOnEvent( $btn_Remove  , "_btn_Remove"  )
	GUICtrlSetOnEvent( $btn_Export  , "_btn_Export"  )
	
	GUICtrlSetFont(  $lbl_WebSite , 8, 800, 0, "MS Sans Serif")
	GUICtrlSetColor( $lbl_WebSite , 0x3B97D3)
	GUICtrlSetTip(   $lbl_WebSite , "Click to visit SchedulesDirect.org")
	GUICtrlSetCursor($lbl_WebSite , 0)

;GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

#Region ### START Koda GUI section ### Form=C:\Program Files (x86)\AutoIt3\SciTE\Koda\Forms\SchedulesDirectLogin.kxf
$SchedulesDirectLogin = GUICreate("Schedules Direct Login", 274, 105, 192, 124)
	$lbl_Name     = GUICtrlCreateLabel("User Name:", 9, 14, 60, 17)
	$inp_Name     = GUICtrlCreateInput("", 74, 10, 190, 21)
	$lbl_Password = GUICtrlCreateLabel("Password:", 16, 45, 53, 17)
	$inp_Password = GUICtrlCreateInput("", 74, 41, 190, 21)
	$btn_Login    = GUICtrlCreateButton("Login", 190, 71, 75, 25)

	GUISetOnEvent( $GUI_EVENT_CLOSE , "_btn_Exit" , $SchedulesDirectLogin )
	GUICtrlSetOnEvent( $btn_Login   , "_btn_Login" )

;GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

$sSetttingFile = @ScriptDir & '\Settings.ini'
If FileExists( $sSetttingFile ) = 0 Then _CreateSettings()

; Load Settings
Global $sMyUserName = IniRead( $sSetttingFile , 'Login'    , 'Name'     , '' )
Global $sMyPassword = IniRead( $sSetttingFile , 'Login'    , 'Password' , '' )
Global $sMyRegion   = IniRead( $sSetttingFile , 'Settings' , 'Region'   , '' )
Global $sMyCountry  = IniRead( $sSetttingFile , 'Settings' , 'Country'  , '' )
Global $sMyZipCode  = IniRead( $sSetttingFile , 'Settings' , 'ZipCode'  , '' )

; Basic Setup
If $sMyUserName = '' OR $sMyPassword = '' Then
	GUISetState( @SW_SHOW , $SchedulesDirectLogin )
Else
	$sMyToken = _GetToken( $sMyUserName , $sMyPassword )
	If $sMyToken = -1 Then _ReportError( 'Failed to Login' )
	$aRegions = _GetRegions()
	If $aRegions = -1 Then _ReportError( 'Failed to Get Regions' )
	$iFindRegion = _ArraySearch( $aRegions , $sMyRegion , 1 , 0 , 0 , 0 , 1 , 0 )
	If $iFindRegion = -1 Then _ReportError( 'Failed to Find User Region' )
	$aCountries   = $aRegions[$iFindRegion][1]
	$iFindCountry = _ArraySearch( $aCountries , $sMyCountry , 1 , 0 , 0 , 0 , 1 , 0 )
	If $iFindCountry = -1 Then _ReportError( 'Failed to Find User Country' )
	If $aCountries[$iFindCountry][4] = 'True' Then
		GUICtrlSetState( $inp_ZipCode , $GUI_DISABLE )
	Else
		GUICtrlSetState( $inp_ZipCode , $GUI_ENABLE )
	EndIf
	$aLineUps = _GetAreaLineups( $sMyToken , $aCountries[$iFindCountry][1] , $sMyZipCode )
	If $aLineUps = -1 Then _ReportError( 'Failed to Find Area Lineups' )
	$aMyLineUps = _GetAccountLineups( $sMyToken )
	GUICtrlSetData( $cbo_Region    , _ArrayColumnToString( $aRegions   , 1 , -1 , 0 , '|' ) , $aRegions[$iFindRegion][0] )
	GUICtrlSetData( $cbo_Country   , _ArrayColumnToString( $aCountries , 1 , -1 , 0 , '|' ) , $aCountries[$iFindCountry][0] )
	GUICtrlSetData( $inp_ZipCode   , $sMyZipCode )
	GUICtrlSetData( $lst_Available , _ArrayColumnToString( $aLineUps   , 1 , -1 , 0 , '|' ) , $aLineUps[1][0] )
	GUICtrlSetData( $lst_Active    , _ArrayColumnToString( $aMyLineUps , 1 , -1 , 1 , '|' ) , $aMyLineUps[1][1] )
	GUISetState( @SW_SHOW , $SchedulesDirectFE )
EndIf



While 1
	Sleep( 100 )
WEnd



Func _ReportError( $sError )
	GUISetState( @SW_HIDE , $SchedulesDirectFE )
	GUISetState( @SW_HIDE , $SchedulesDirectLogin )
	MsgBox( 16 , 'Error:' , $sError )
	Exit
EndFunc

Func _btn_Exit()
	IniWrite( $sSetttingFile , 'Login'    , 'Name'     , $sMyUserName )
	IniWrite( $sSetttingFile , 'Login'    , 'Password' , $sMyPassword )
	IniWrite( $sSetttingFile , 'Settings' , 'Region'   , GUICtrlRead( $cbo_Region  ))
	IniWrite( $sSetttingFile , 'Settings' , 'Country'  , GUICtrlRead( $cbo_Country ))
	IniWrite( $sSetttingFile , 'Settings' , 'ZipCode'  , GUICtrlRead( $inp_ZipCode ))

	Exit
EndFunc

Func _lbl_WebSite()
	ShellExecute( "http://www.SchedulesDirect.org/" )
EndFunc

Func _btn_Export()
	$sIndexText = _GUICtrlListBox_GetText( $lst_Active , _GUICtrlListBox_GetCurSel( $lst_Active ))
	$iFindLineUp = _ArraySearch( $aMyLineUps , $sIndexText , 1 , 0 , 0 , 0 , 1 , 1 )
	If $iFindLineUp = -1 Then _ReportError( 'Failed to Export Area Lineup' )
	; Schedules Direct Account LineUp Remove
	RunWait( @ComSpec & ' /c curl.exe -H "Token: ' & $sMyToken & '" -H "Accept: application/json" -X GET "https://json.schedulesdirect.org' & $aMyLineUps[$iFindLineUp][4] & '" >"' & @ScriptDir & '\[LineUp] ' & $sIndexText & '.txt"' , @ScriptDir , @SW_HIDE )
EndFunc

Func _btn_Add()
	$sIndexText = _GUICtrlListBox_GetText( $lst_Available , _GUICtrlListBox_GetCurSel( $lst_Available ))
	$iFindLineUp = _ArraySearch( $aLineUps , $sIndexText , 1 , 0 , 0 , 0 , 1 , 0 )
	If $iFindLineUp = -1 Then _ReportError( 'Failed to Add Area Lineup' )
	; Schedules Direct Account LineUp Add
	RunWait( @ComSpec & ' /c curl.exe -H "Token: ' & $sMyToken & '" -H "Accept: application/json" -X PUT "https://json.schedulesdirect.org' & $aLineUps[$iFindLineUp][2] & '"' , @ScriptDir , @SW_HIDE )
	$aMyLineUps = _GetAccountLineups( $sMyToken )
	_GUICtrlListBox_ResetContent( $lst_Active )
	GUICtrlSetData( $lst_Active , _ArrayColumnToString( $aMyLineUps , 1 , -1 , 1 , '|' ) , $aMyLineUps[1][1] )
EndFunc

Func _btn_Remove()
	$sIndexText = _GUICtrlListBox_GetText( $lst_Active , _GUICtrlListBox_GetCurSel( $lst_Active ))
	$iFindLineUp = _ArraySearch( $aMyLineUps , $sIndexText , 1 , 0 , 0 , 0 , 1 , 1 )
	If $iFindLineUp = -1 Then _ReportError( 'Failed to Remove Area Lineup' )
	; Schedules Direct Account LineUp Remove
	RunWait( @ComSpec & ' /c curl.exe -H "Token: ' & $sMyToken & '" -H "Accept: application/json" -X DELETE "https://json.schedulesdirect.org' & $aMyLineUps[$iFindLineUp][4] & '"' , @ScriptDir , @SW_HIDE )
	$aMyLineUps = _GetAccountLineups( $sMyToken )
	_GUICtrlListBox_ResetContent( $lst_Active )
	GUICtrlSetData( $lst_Active , _ArrayColumnToString( $aMyLineUps , 1 , -1 , 1 , '|' ) , $aMyLineUps[1][1] )
EndFunc

Func _btn_Login()
	GUISetState( @SW_HIDE , $SchedulesDirectLogin )
	$sMyUserName = GUICtrlRead( $inp_Name )
	$sMyPassword = GUICtrlRead( $inp_Password )
	$sMyToken = _GetToken( $sMyUserName , $sMyPassword )
	If $sMyToken = -1 Then _ReportError( 'Failed to Login' )
	$aRegions = _GetRegions()
	If $aRegions = -1 Then _ReportError( 'Failed to Get Regions' )
	$aCountries = $aRegions[1][1]
	$sMyRegion  = $aRegions[1][0]
	$sMyCountry = $aCountries[1][0]
	$aLineUps   = _GetAreaLineups( $sMyToken , 'USA' , '98056' )
	If $aLineUps = -1 Then _ReportError( 'Failed to Find Area Lineups' )
	$aMyLineUps = _GetAccountLineups( $sMyToken )
	GUICtrlSetData( $cbo_Region    , _ArrayColumnToString( $aRegions   , 1 , -1 , 0 , '|' ) , $sMyRegion  )
	GUICtrlSetData( $cbo_Country   , _ArrayColumnToString( $aCountries , 1 , -1 , 0 , '|' ) , $sMyCountry )
	GUICtrlSetData( $inp_ZipCode   , '98056' )
	GUICtrlSetData( $lst_Available , _ArrayColumnToString( $aLineUps   , 1 , -1 , 0 , '|' ) , $aLineUps[1][0] )
	GUICtrlSetData( $lst_Active    , _ArrayColumnToString( $aMyLineUps , 1 , -1 , 1 , '|' ) , $aMyLineUps[1][1] )
	GUISetState( @SW_SHOW , $SchedulesDirectFE )
EndFunc

Func _cbo_Region()
	Local $iFindRegion

	_GUICtrlComboBox_ResetContent( $cbo_Country )
	$iFindRegion = _ArraySearch( $aRegions , GUICtrlRead( $cbo_Region ) , 1 , 0 , 0 , 0 , 1 , 0 )
	If $iFindRegion = -1 Then _ReportError( 'Failed to Find Region' )
	$aCountries  = $aRegions[$iFindRegion][1]
	GUICtrlSetData( $cbo_Country , _ArrayColumnToString( $aCountries , 1 , -1 , 0 , '|' ) , $aCountries[1][0] )
	_cbo_Country()
EndFunc

Func _cbo_Country()
	Local $iFindCountry

	$iFindCountry = _ArraySearch( $aCountries , GUICtrlRead( $cbo_Country ) , 1 , 0 , 0 , 0 , 1 , 0 )
	If $iFindCountry = -1 Then _ReportError( 'Failed to Find Country' )
	If $aCountries[$iFindCountry][4] = 'True' Then
		GUICtrlSetData( $inp_ZipCode , $aCountries[$iFindCountry][2] )
	Else
		GUICtrlSetData( $inp_ZipCode , '' )
	EndIf
EndFunc

Func _btn_Update()
	Local $iFindCountry

	$iFindCountry = _ArraySearch( $aCountries  , GUICtrlRead( $cbo_Country ) , 1 , 0 , 0 , 0 , 1 , 0 )
	$aLineUps     = _GetAreaLineups( $sMyToken , $aCountries[$iFindCountry][1] , GUICtrlRead( $inp_ZipCode ))
	_GUICtrlListBox_ResetContent( $lst_Available )
	GUICtrlSetData( $lst_Available , _ArrayColumnToString( $aLineUps , 1 , -1 , 0 , '|' ) , $aLineUps[1][0] )
EndFunc

Func _ArrayColumnToString( Const ByRef $aArray , $iRowStart = 0 , $iRowEnd = -1 , $iColumn = 0 , $sDelimiter = '|' )
	Local $ii , $sString

	If $iRowEnd < $iRowStart Then $iRowEnd = UBound( $aArray ) - 1
	For $ii = $iRowStart To $iRowEnd
		$sString &= $aArray[$ii][$iColumn]
		If $ii <> $iRowEnd Then $sString &= $sDelimiter
	Next

	Return $sString
EndFunc

Func _CreateSettings()
	Local $sString

	$sString &= '[Login]'   & @CRLF
	$sString &= 'Name='     & @CRLF
	$sString &= 'Password=' & @CRLF
	$sString &= @CRLF
	$sString &= '[Settings]' & @CRLF
	$sString &= 'Region='    & @CRLF
	$sString &= 'Country='   & @CRLF
	$sString &= 'ZipCode='   & @CRLF

	FileWrite( @ScriptDir & '\Settings.ini' , $sString )
EndFunc

Func _GetToken( $sUserName , $sUserPassword )
	Local $sBuffer , $iBufferFind , $sToken

	; Hash Password
	FileWrite(  @ScriptDir & '\Password.txt' , $sUserPassword )
	RunWait( @ComSpec & ' /c fsum.exe -sha1 -jnc "Password.txt">"' & @ScriptDir & '\PasswordHash.txt"' , @ScriptDir , @SW_HIDE )
	$sUserPassword = StringLower( FileRead( @ScriptDir & '\PasswordHash.txt' , 40 ))
	FileDelete( @ScriptDir & '\Password.txt' )
	FileDelete( @ScriptDir & '\PasswordHash.txt' )

	; Get Schedules Direct Token
	RunWait( @ComSpec & ' /c curl.exe -H "Accept: application/json" -X POST -d "{\"username\":\"' & $sUserName & '\",\"password\":\"' & $sUserPassword & '\"}" "https://json.schedulesdirect.org/20141201/token" >"' & @ScriptDir & '\Token.txt"' , @ScriptDir , @SW_HIDE )

	; Set Schedules Direct Token
	$sBuffer = FileRead( @ScriptDir & '\Token.txt' )
	$iBufferFind = StringInStr( $sBuffer , '"token":"' )
	$sToken = StringTrimRight( StringTrimLeft( $sBuffer , $iBufferFind + 8 ) , 2 )
	FileDelete( @ScriptDir & '\Token.txt' )

	Return $sToken
EndFunc

Func _GetRegions()
	Local $ii , $jj , $kk , $ll , $aCountries , $aRegions , $aTemp , $sBuffer , $sCountryBuffer , $sRegionBuffer

	; Schedules Direct List Regions & Countries
	RunWait( @ComSpec & ' /c curl.exe -H "Accept: application/json" -X GET "https://json.schedulesdirect.org/20141201/available/countries" >"' & @ScriptDir & '\Countries.txt"' , @ScriptDir , @SW_HIDE )
	$sBuffer = FileRead( @ScriptDir & '\Countries.txt' )
	FileDelete( @ScriptDir & '\Countries.txt' )

	$ii = 0
	$jj = 0
	While StringInStr( $sBuffer , '":[{' , 0 , 1 , $jj + 1 ) <> 0
		$jj = StringInStr( $sBuffer , '":[{' , 0 , 1 , $jj + 1 )
		$ii += 1
	WEnd
	Dim $aRegions[$ii][2] = [[$ii - 1]]
	For $kk = 1 To $ii - 1
		$sRegionBuffer = StringLeft(      $sBuffer        , StringInStr( $sBuffer        , '":[{' , 0 , $kk ) - 1 )
		$sRegionBuffer = StringTrimLeft(  $sRegionBuffer  , StringInStr( $sRegionBuffer  , '"'    , 0 , -1 ))
		$sCountryBuffer = StringLeft(     $sBuffer        , StringInStr( $sBuffer        , '":[{' , 0 , $kk + 1 ) - 1 )
		If $kk > 1 Then $sCountryBuffer = StringTrimLeft( $sCountryBuffer , StringInStr( $sCountryBuffer , '":[{' , 0 , $kk ) - 1 )
		$sCountryBuffer = StringLeft(     $sCountryBuffer , StringInStr( $sCountryBuffer , ']'    , 0 , -1 ) - 2 )
		$sCountryBuffer = StringTrimLeft( $sCountryBuffer , StringInStr( $sCountryBuffer , '['    , 0 ,  1 ) + 1 )
		$aCountries = StringSplit( $sCountryBuffer , '},{' , 1 )
		Dim $aTemp[$aCountries[0] + 1][5] = [[$aCountries[0]]]
		For $ll = 1 To $aCountries[0]
			$aTemp[$ll][0] = _ArrayToString( StringRegExp( $aCountries[$ll] , '"fullName":"([^"]+)"'   , 1 ))        ; United States
			$aTemp[$ll][1] = _ArrayToString( StringRegExp( $aCountries[$ll] , '"shortName":"([^"]+)"'  , 1 ))        ; USA
			$aTemp[$ll][2] = _ArrayToString( StringRegExp( $aCountries[$ll] , '"postalCodeExample":"([^"]+)"' , 1 )) ; 12345
			$aTemp[$ll][3] = _ArrayToString( StringRegExp( $aCountries[$ll] , '"postalCode":"([^"]+)"' , 1 ))        ; \/\\d{5}\/
			$aTemp[$ll][4] = _ArrayToString( StringRegExp( $aCountries[$ll] , '"onePostalCode":(.+)'   , 1 ))        ; -1 or True
			$aTemp[$ll][0] = StringReplace( $aTemp[$ll][0] , '\/'  , '/' )                                           ; Antigua/Barbuda
			$aTemp[$ll][0] = _UTF8( $aTemp[$ll][0] )
			$aTemp[$ll][1] = _UTF8( $aTemp[$ll][1] )
		Next
		$aRegions[$kk][0] = $sRegionBuffer                                                                          ; North America
		$aRegions[$kk][1] = $aTemp
	Next

	Return $aRegions
EndFunc

Func _GetAccountLineups( $sToken )
	Local $kk , $ll , $sBuffer , $aLineUp , $aLineUpList

	; Schedules Direct Account LineUp List
	RunWait( @ComSpec & ' /c curl.exe -H "Token: ' & $sToken & '" -H "Accept: application/json" -X GET "https://json.schedulesdirect.org/20141201/lineups" >"' & @ScriptDir & '\Account Lineups.txt"' , @ScriptDir , @SW_HIDE )
	$sBuffer = FileRead( @ScriptDir & '\Account Lineups.txt' )
	FileDelete( @ScriptDir & '\Account Lineups.txt' )
	$aBuffer = StringRegExp( $sBuffer , '"lineups":\[([^\]]+)\]' , 3 )

	Dim $aLineUpList[1][5] = [[0]]
	For $kk = 0 To UBound( $aBuffer ) - 1
		$aLineUp = StringSplit( $aBuffer[$kk] , '},{' , 1 )
		For $ll = 1 To $aLineUp[0]
			ReDim $aLineUpList[UBound( $aLineUpList ) + 1][5]
			$aLineUpList[0][0] += 1
			$aLineUpList[$aLineUpList[0][0]][0] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"lineup":"([^"]+)"'   , 1 )) ; USA-OTA-98056
			$aLineUpList[$aLineUpList[0][0]][1] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"name":"([^"]+)"'     , 1 )) ; Local Over the Air Broadcast
			$aLineUpList[$aLineUpList[0][0]][2] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"transport":"([^"]+)"', 1 )) ; Antenna
			$aLineUpList[$aLineUpList[0][0]][3] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"location":"([^"]+)"' , 1 )) ; 98056
			$aLineUpList[$aLineUpList[0][0]][4] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"uri":"([^"]+)"'      , 1 )) ; \/20141201\/lineups\/USA-OTA-98056
			$aLineUpList[$aLineUpList[0][0]][4] = StringReplace( $aLineUpList[$aLineUpList[0][0]][4] , '\' , '' )             ; /20141201/lineups/USA-OTA-98056
			$aLineUpList[$aLineUpList[0][0]][0] = _UTF8( $aLineUpList[$aLineUpList[0][0]][0] )
			$aLineUpList[$aLineUpList[0][0]][1] = _UTF8( $aLineUpList[$aLineUpList[0][0]][1] )
			$aLineUpList[$aLineUpList[0][0]][2] = _UTF8( $aLineUpList[$aLineUpList[0][0]][2] )
		Next
	Next

	Return $aLineUpList
EndFunc

Func _GetAreaLineups( $sToken , $sCountryShort , $sZipCode )
	Local $kk , $ll , $sBuffer , $aHeadend , $aLineUp , $aLineUps

	; Schedules Direct List LineUps Area
	RunWait( @ComSpec & ' /c curl.exe -H "Token: ' & $sToken & '" -H "Accept: application/json" -X GET "https://json.schedulesdirect.org/20141201/headends?country=' & $sCountryShort & '&postalcode=' & $sZipCode & '" >"' & @ScriptDir & '\Headends.txt"' , @ScriptDir , @SW_HIDE )
	$sBuffer = FileRead( @ScriptDir & '\Headends.txt' )
	FileDelete( @ScriptDir & '\Headends.txt' )
	$sBuffer = StringLeft(     $sBuffer , StringInStr( $sBuffer , ']' , 0 , -1 ) - 1 )
	$sBuffer = StringTrimLeft( $sBuffer , StringInStr( $sBuffer , '[' , 0 ,  1 ))
	$aHeadend = StringRegExp(  $sBuffer , '"lineups":\[([^\]]+)\]' , 3 )

	Dim $aLineUps[1][3] = [[0]]
	For $kk = 0 To UBound( $aHeadend ) - 1
		$aLineUp = StringSplit( $aHeadend[$kk] , '},{' , 1 )
		For $ll = 1 To $aLineUp[0]
			ReDim $aLineUps[UBound( $aLineUps ) + 1][3]
			$aLineUps[0][0] += 1
			$aLineUps[$aLineUps[0][0]][0] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"name":"([^"]+)"'   , 1 )) ; Antenna
			$aLineUps[$aLineUps[0][0]][1] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"lineup":"([^"]+)"' , 1 )) ; USA-OTA-98056
			$aLineUps[$aLineUps[0][0]][2] = _ArrayToString( StringRegExp( $aLineUp[$ll] , '"uri":"([^"]+)"'    , 1 )) ; \/20141201\/lineups\/USA-OTA-98056
			$aLineUps[$aLineUps[0][0]][2] = StringReplace( $aLineUps[$aLineUps[0][0]][2], '\' , '' )                  ; /20141201/lineups/USA-OTA-98056
		Next
	Next

	Return $aLineUps
EndFunc

Func _UTF8( $sString )
	Local $iStart , $sValue , $sChr

	If StringInStr( $sString , '\u' ) > 0 Then
		$iStart  = StringInStr( $sString , '\u' )
		$sValue  = StringMid( $sString , $iStart + 2 , 4 )
		$sChr    = Chr( Dec( $sValue ))
		$sString = StringReplace( $sString , '\u' & $sValue , $sChr )
	EndIf

	Return $sString
EndFunc

 

 

 

*Update 1*

Fixed UTF-8 issue as remarked upon by rkulagow

Edited by Nologic
Posted (edited)

Note if you are not interested in icons and the other odd ball options my scripts offer...but just want to bulk assign Schedules Direct to all the channels you have in NextPVR, checkout this video that sub pointed out to me.

 

 

Please note that sub has downloading icons lined up for a future release of NextPVR yay! After that a few more options and we can toss my scripts in the trash bin. :)

Edited by Nologic
  • Like 1
  • 2 years later...
Posted

G'day...I just came accross this thread but noticed that it is 2 years old. Any way I was wondering if you have done any more work on this project because this is just what I have been looking for. I would like to have a way to download all the icons instead of hunting them down individually. I tried out your setup but it failed to write the text file. If this proggy is no longer valid can you direct me to another program which would accomplish the same thing? I have scoured the Internet and have found some possibilities but they turned out to be of no use to me. Thanks in advance...Cheers!

Posted

What kind of tuner do you have?

Posted

Ok, you know that you can use this directly in Emby without Next PVR, right?

Posted

Wow no I didn't. So will it download all my channel logos and put them in a folder someplace?

Posted (edited)

Okay, I am going to assume tat it does since that was my main bjective. I will give that a go in a minute and see if it does. I remember using Emby a while back but couldn't recall if the channel logos were in a seperate file. Thanks. Cheers!

 

Just to be clear, tis is what I am after, nice colorful logos.

 

5b918cc3b326d_EmbyEPG.png

 

Edited by snaitaz@aol.com
PenkethBoy
Posted

yes

 

make sure you have wintv installed and upto date etc and things setup in wintv correctly

 

then add your tuner and epg provider to emby

 

and you should be good to go

Posted

Got it. So are the logos based on what the provider has since I have noticed that SD does not have coloful ones just mainly blackground logos.

PenkethBoy
Posted

i think they come from SD - you can replace the images on the channel tab of LiveTV if you want different ones

Posted (edited)

Thanks. So basically the logos are in the metadata and not in .png or similar format in a folder.

Edited by snaitaz@aol.com
PenkethBoy
Posted

they are but finding them would take time - just replace them with what you like

Posted

G'day, well I decided to maake my own, like my dad always said, "if you can't find what you want them make the damn thing". So I did and I am. Im' starting out with the channel logos I need for now then going to make as many as possible. Here is what I started out with...

5b928833a1173_TVGuideNestBlue1IPTVChanne

 

An here is what I have for now...

 

5b9288b385f87_ChannelsNow.png

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...