Nologic 30 Posted September 11, 2015 Posted September 11, 2015 (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: AutoIt Curl (SSL support) FSUM NextPVR Schedules Direct (Account) References: ISO 639-1 Codes 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 October 4, 2015 by Nologic 2
VladTepz 46 Posted September 12, 2015 Posted September 12, 2015 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 1
Nologic 30 Posted September 12, 2015 Author Posted September 12, 2015 (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 September 12, 2015 by Nologic 1
rkulagow 19 Posted September 15, 2015 Posted September 15, 2015 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.
Nologic 30 Posted September 15, 2015 Author Posted September 15, 2015 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 CertificatesIn 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/
Damstas 9 Posted September 22, 2015 Posted September 22, 2015 (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 September 22, 2015 by Damstas
Nologic 30 Posted September 23, 2015 Author Posted September 23, 2015 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.
Nologic 30 Posted October 1, 2015 Author Posted October 1, 2015 (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 October 4, 2015 by Nologic
Nologic 30 Posted October 3, 2015 Author Posted October 3, 2015 (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 October 3, 2015 by Nologic 1
ErikaJ 59 Posted September 6, 2018 Posted September 6, 2018 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!
Luke 38551 Posted September 6, 2018 Posted September 6, 2018 Ok, you know that you can use this directly in Emby without Next PVR, right?
ErikaJ 59 Posted September 6, 2018 Posted September 6, 2018 Wow no I didn't. So will it download all my channel logos and put them in a folder someplace?
ErikaJ 59 Posted September 6, 2018 Posted September 6, 2018 (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. Edited September 6, 2018 by snaitaz@aol.com
PenkethBoy 2066 Posted September 6, 2018 Posted September 6, 2018 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
ErikaJ 59 Posted September 6, 2018 Posted September 6, 2018 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 2066 Posted September 6, 2018 Posted September 6, 2018 i think they come from SD - you can replace the images on the channel tab of LiveTV if you want different ones
ErikaJ 59 Posted September 6, 2018 Posted September 6, 2018 (edited) Thanks. So basically the logos are in the metadata and not in .png or similar format in a folder. Edited September 6, 2018 by snaitaz@aol.com
PenkethBoy 2066 Posted September 6, 2018 Posted September 6, 2018 they are but finding them would take time - just replace them with what you like
ErikaJ 59 Posted September 7, 2018 Posted September 7, 2018 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... An here is what I have for now...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now