diff --git a/.gitignore b/.gitignore index 12ab2e10..3b95b10c 100755 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ home-assistant.log ui-experimental.yaml __pycache__ *.pyc +token* diff --git a/configuration.yaml b/configuration.yaml index 6bb054e3..90886dec 100755 --- a/configuration.yaml +++ b/configuration.yaml @@ -26,16 +26,15 @@ lovelace: {url: /hacsfiles/light-entity-card/light-entity-card.js, type: js}, {url: /hacsfiles/light-popup-card/light-popup-card.js, type: module}, {url: /hacsfiles/lovelace-card-mod/card-mod.js, type: module}, - {url: /hacsfiles/lovelace-card-preloader/lovelace-card-preloader.js, type: module}, {url: /hacsfiles/lovelace-hui-element/hui-element.js, type: module}, {url: /hacsfiles/lovelace-layout-card/layout-card.js, type: module}, {url: /hacsfiles/lovelace-slider-entity-row/slider-entity-row.js, type: module}, {url: /hacsfiles/mini-graph-card/mini-graph-card-bundle.js, type: module}, {url: /hacsfiles/mini-media-player/mini-media-player-bundle.js, type: module}, - {url: /hacsfiles/stack-in-card/stack-in-card.js, type: module}, {url: /hacsfiles/swipe-card/swipe-card.js, type: module}, {url: '/local/calendar-card.js?v=31091', type: module}, + {url: '/local/stack-in-card.js?v=101', type: module}, {url: '/local/valetudo-map-card.js?v=42dbceb', type: js}, {url: '/local/custom_icons.js?v=25052001', type: module}, {url: /local/font.css, type: css} ] @@ -52,6 +51,7 @@ logger: homeassistant.components.media_player: error homeassistant.helpers.entity: error homeassistant.helpers.event: fatal + homeassistant.components.ipp: fatal recorder: purge_keep_days: 2 @@ -89,8 +89,10 @@ wemo: cast: -samsungtv: - - host: !secret samsungtv_host +media_player: + - platform: samsungtv_tizen + host: !secret samsungtv_host + mac: !secret samsungtv_mac hacs: token: !secret hacs_token @@ -123,7 +125,7 @@ mqtt: browser_mod: devices: - 918296e3-e2a54976: + 94414206-952e1e9a: name: imac_chrome c2080cea-6627150a: name: tablet @@ -206,7 +208,7 @@ homekit: filter: include_entities: &include_entities ['fan.studio_wemo', 'switch.wemo_monitors', 'switch.computer_imac', 'media_player.sony_bravia', 'switch.air_purifier', 'lock.dator', - 'media_player.samsung', 'switch.playstation_4', 'input_boolean.motion_hall', 'fan.sovrum_anslut', 'script.samsung_tv_energy_saving', + 'media_player.samsung_tv_remote', 'switch.playstation_4', 'input_boolean.motion_hall', 'fan.sovrum_anslut', 'script.samsung_tv_energy_saving', 'input_boolean.motion_garderob', 'input_boolean.motion_badrum', 'script.home_arrive', 'script.home_leave', 'vacuum.xiaomi_vacuum_cleaner', 'person.mattias', 'person.sanja'] entity_config: @@ -227,7 +229,7 @@ homekit: name: Tv feature_list: - feature: on_off - media_player.samsung: + media_player.samsung_tv_remote: name: Samsung Tv feature_list: - feature: on_off @@ -273,7 +275,7 @@ cloud: ['Tv', 'Sony Tv', 'Sony Bravia Tv', 'Bravia Tv', 'Vardagsrums Tv', 'Vardagsrums Teven', 'Tv Vardagsrum'] room: Vardagsrum - media_player.samsung: + media_player.samsung_tv_remote: name: Samsung Tv aliases: ['Samsung Tv', 'Sovrums Tv', 'Sovrums Teven', 'Tv Sovrum'] room: Sovrum diff --git a/custom_components/samsungtv_tizen/__init__.py b/custom_components/samsungtv_tizen/__init__.py new file mode 100644 index 00000000..e43ea1ba --- /dev/null +++ b/custom_components/samsungtv_tizen/__init__.py @@ -0,0 +1 @@ +"""The samsungtv component.""" diff --git a/custom_components/samsungtv_tizen/exceptions.py b/custom_components/samsungtv_tizen/exceptions.py new file mode 100644 index 00000000..897a3f08 --- /dev/null +++ b/custom_components/samsungtv_tizen/exceptions.py @@ -0,0 +1,13 @@ +class ConnectionFailure(Exception): + """Error during connection.""" + pass + + +class ResponseError(Exception): + """Error in response.""" + pass + + +class HttpApiError(Exception): + """Error using HTTP API.""" + pass diff --git a/custom_components/samsungtv_tizen/logo_paths.json b/custom_components/samsungtv_tizen/logo_paths.json new file mode 100644 index 00000000..867fffeb --- /dev/null +++ b/custom_components/samsungtv_tizen/logo_paths.json @@ -0,0 +1 @@ +{"fuji tv":"/yS5UJjsSdZXML0YikWTYYHLPKhQ.png","abc":"/an88sKsFz0KX5CQngAM95WkncX4.png","bbc three":"/ex369Frq6w0PaQsVofp21C6tbuC.png","bbc one":"/8UNCAmEJGuwKhgEPfqwymVF3xRn.png","bell tv":"/5hksRDWDoqYYkq0q7KWk4MkMCoZ.png","nbc":"/4tg60YhOwXieVhGwuGxefGWbJr6.png","māori television":"/bwO92lNZstiQHtM7CSD7YNPGYM.png","itv":"/j3KAlTmxGDCHQZqs1A2hagzjYqu.png","discovery health channel":"/yiBepnHS6gdzlT6ZIehYnNl0nEG.png","cctv":"/ufmYwN934igUGuPaorjcfsg57IU.png","htb":"/eJSYeF1YIyQbZdTRNxuvVKaZOIK.png","nickelodeon":"/aYkLXz4dxHgOrFNH7Jv7Cpy56Ms.png","pbs":"/d4OH7tMO4ece61s4j7mJWqQejv.png","cbbc":"/rKm8M7QhQg1OkNFHyIoi9sE9UeZ.png","cbs":"/wWA5mILSAyahtdNQh1WiADi6PRI.png","mtv2":"/6o7HFq6Sm6mOt5Kh5iL6VzqJ4No.png","fox":"/1DSpHrWyOORkL9N2QHX7Adt31mQ.png","abs-cbn":"/ulpsCGEVv18h9AUCQP5ungP3R6o.png","the wb":"/9GlDHjQj9c2dkfARCR3zlH87R66.png","discovery kids":"/opuyeVwROh4w7lm3DPQux8SKs4I.png","cbc television":"/cw5WW6cc9UANam4A6o1BDua9njN.png","bet":"/pejxmP1m6GiUZj01jhDN4a2tHKq.png","televisión nacional de chile":"/qTSv2HzTql23V14ww521kU2CZFn.png","channel 4":"/hbifXPpM55B1fL5wPo7t72vzN78.png","univision":"/8JwhJGdxpSsiuPiFDGslBH1cr7t.png","espn":"/w9le4FUeXVlKLfnlkuk1djRrena.png","usa network":"/g1e0H0Ka97IG5SyInMXdJkHGKiH.png","zdf":"/sfZaVx3svlzIoNoerdgb840TPD9.png","mtv":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","lifetime":"/kU18GafTybg4uMhkj3wvsGBgn8s.png","nick jr.":"/zmXCDvQt7AUf5ci1ldjFfccsmJc.png","atv":"/qCnMXkdER5FYvmy2AGSMnAFH9ue.png","msnbc":"/eV4rShI9xT9tzziSFFqGvVbNtza.png","network ten":"/bgoa1MRBnps2JTJPrxmziG3nS0t.png","irib tv5":"/r5hZ043QIKBhvIGVOcwN5FVn5Me.png","upn":"/333LtWX9Z7H9uRrNcCl1JcTvdpR.png","tnt":"/6ISsKwa2XUhSC6oBtHZjYf6xFqv.png","tv5":"/gVinXXdpdbLHuXTUUfx4R9PyuPB.png","national geographic":"/5UtQpFierweXjriDoRf3LUVDjce.png","disney xd":"/nKM9EnV7jTpt3MKRbhBusJ03lAY.png","fox news channel":"/zYjYOy304S4JPXWncHS6D5K0mdi.png","ytv":"/nXrfHqHOtLcrSKPz2do1duM3cwT.png","comedy central":"/EQ7BIt2cb1Zayf8hSvtJN1aRYj.png","tvb jade":"/8QQTIU1Rd0Stw2jmlSi4emv6PkK.png","hbo":"/tuomPhY2UtuPTqqFnKMVHvSb724.png","gma network":"/ftB1h0NyMIeu1H1AtZ8BXtsYIiA.png","the comedy network":"/zWANL77d5GiGouIaL5o8a2hErRv.png","telecinco":"/3q9Kob7joLOHrsJPXQ9clhsF4az.png","disney channel":"/rxhJszKVAvAZYTmF0vfRHfyo4Fb.png","spike":"/82MKSH7iM5LAGXFb0PDOclTWn5u.png","cartoon network":"/c5OC6oVCg6QP4eqzW6XIq17CQjI.png","ntv":"/uxaXSoT8K0S2NE5PWsBpHUl3GGU.png","televisa":"/3vFK8I1mW11dBfUcCopWd5rWDBH.png","cnn":"/2EIKV6SomKx8L52HoSViKyJO87m.png","rede globo":"/qFNe75EkUaIdNlTqadArD00a62m.png","outtv":"/rJI8nxnuiSB4O0roWpAAB7BEcqv.png","logo":"/ztSNqnJ8W1GOYfa3525xFBDb3NY.png","game show network":"/er3Bx1TMCviOUvhIXyOtFhL9f8w.png","discovery":"/8qkdZlbrTSVfkJ73DjOBrwYtMSC.png","history":"/i1EWv4eUVKRGAiMRE5ZQKzzWgej.png","nine network":"/pXibAQSgIIanNkSg68dUooI7IGU.png","showtime":"/Allse9kbjiP6ExaQrnSpIhkurEi.png","tbs":"/65r0kR6MfOBYF0gEQsJGM6v5fEG.png","q":"/alf22ocIIX03AfHLBa5E2xgZRKl.png","espn2":"/iWq7EXFKUO7FYPH6umvE6mB99Ta.png","the cw":"/ge9hzeaU7nMtQ4PjkFlc68dGAJ9.png","musiqueplus":"/vsDEmpE3Wmol7W1LlNso8lidsQg.png","bravo":"/wX5HsfS47u6UUCSpYXqaQ1x2qdu.png","abc family":"/p57JGkSUBdXbOtqkEKeTnfHn7kd.png","e!":"/ptpx2Ag52sYJG6LiX9zBlnKsQOS.png","syfy":"/iYfrkobwDhTOFJ4AXYPSLIEeaAT.png","adult swim":"/v9ma1uXIjIR8D2LG3y5UaUKrgTz.png","espnu":"/oByKzXnqvTqCD9ctG0sFMm5Mn4E.png","teletoon":"/pDIiwRTwheBQ0UY6TZZIW8I8MEB.png","tlc":"/6GRfZSrYh9D6C88n9kWlyrySB2l.png","cmt":"/lSwwz91j5O3CLDypFZgiFYZOjp8.png","fox sports detroit":"/jySh2X4wkO8jQRSSqfx09joD0Nn.png","fx":"/aexGjtcs42DgRtZh7zOxayiry4J.png","cbc news network":"/9hqzoCyMCZEXi2Iiz9P4ivmoRQf.png","animal planet":"/xQ25rzpv83d74V1zpOzSHbYlwJq.png","city":"/eZipPYKRhkp9Hg1Kujyba3oghM7.png","mbs":"/7RNXnyiMbjgqtPAjja13wchcrGI.png","mediacorp channel 5":"/idQWLSFyRqV3mBsMPDLrvfAP59M.png","telefe":"/fzb6OmfOHrautcnTBcyo8mig5vp.png","mbc":"/pOSCKaZhndUFYtxHXjQOV6xJi1s.png","tv tokyo":"/kGRavMqgyx4p2X4C96bjRCj50oI.png","channel 5":"/bMuKs6xuhI0GHSsq4WWd9FsntUN.png","bbc four":"/cJlMCKsILwSK5OzinIsUKo7Ewug.png","tv 2 zulu":"/sa7WIkkl34Hh8xj8hFRfrZNaLis.png","tv asahi":"/usmwgnOfBWuzet8vdWe3dfxXlNc.png","showcase":"/hdbp4Un78kOw9E5U3B1GQyIYqzM.png","sky sports":"/4Zb6JGtAT7IWLEAdOdkJ59VMRmY.png","espnews":"/1bRRzGqexnzn5BodK4X4L2SmVia.png","ctv":"/uPoKSf3GtME7IZz4alnoWvc0nWx.png","citv":"/rwuEsuBDb200skfrDTvBiJihMLd.png","fuse":"/vkxW1Up7dls1AZIsIjpkNutdxcU.png","three":"/45DWFxTFn4BCe1cNmIWK12nqnEx.png","sky living":"/k7EOxG3Ul7JWaRq2MzxWM04Gxc6.png","challenge":"/qsEPXw9Yp4KIWz5T5HrGBeO5BFl.png","associated television":"/hEdI56n4EHSP6kto7BUPEOb6bqo.png","seven network":"/83L2wF8tM76nUQHzOBOBAGlPQVP.png","national educational television":"/pjQ7a6Pplwm6KmR4kunOwoiqYaO.png","pbs kids":"/uthoU85XHVBs3PTRoRgii0wMppo.png","tvnz 2":"/wGMxGK0IlrDER4GqWKqr3wzOj1v.png","ifc":"/jZYZjulF2FTaAHo5TKBHBC4ihS1.png","tv 2":"/fft3jrctrZNcgAxgN1w5Givtzip.png","bbc choice":"/lBk6aoAEPdbtnhR4H3eouQVq9Dp.png","london weekend television":"/iGAUX15FMJDjOwUfRG3Nmm8C1yL.png","sistema brasileiro de televisão (sbt)":"/jQ6pbmLCO2mheofZJPPByy7Wozq.png","a&e":"/ptSTdU4GPNJ1M8UVEOtA0KgtuNk.png","oxygen":"/acDtMnoo5byrtFLEJa6J5BYfgBW.png","venevisión":"/vJf1d51q3nOyYDwrtNfnPxBiwmw.png","ktla":"/bK3L5F30rnZcit3AefcHpUlpqVp.png","slice":"/uSmL90amaWU7yGAaZuhyJipuT6l.png","e4":"/fJPM9Rj12us4HF03N3qvakz7WuZ.png","much ":"/yKnRDHAQ0lDt38GS62imutKRzMp.png","s4c":"/GOTWuhzHulAcXJMETunP2Wy8No.png","ici radio-canada télé":"/32OnRA75a9xn30N2fC44IcCzHkC.png","toon disney":"/7ahoCR2iIFYd0p2xbbrhQgnClJC.png","food network":"/aKkZnTIGTn92sUODLxqP8ZmgyIA.png","stv":"/ntnvyI2vhcEzEv8IHzm2CweEfJ5.png","itv2":"/wbGo5nGjF0nFxTajmY5WOZVAEQM.png","tv one":"/tVTnNvyGqOmerZtHVoofisDTZhN.png","utv":"/6PFI9tl5Glq7NLOCqsQXwr4rnlU.png","rté one":"/2kjTvhfxtXLnHspCUZQ9cv9gToV.png","sbs":"/uHQFPvRTlpgaIFQVN8eKWEnFOll.png","tvnorge":"/v25T1fvtINzeQMC1AdwFPwOL1no.png","vh1":"/2IUI7PwPokLMbXwwJndNH4sqEFn.png","starplus":"/ldd8BuRLIhjhhpKa1Bqi6Bs4sTE.png","dumont television network":"/csmISkmy8gil9Vp0pnQlNZbLdjU.png","sat.1":"/x8Hyu8Y3RUA47sZjslz4vt4PPjH.png","g4":"/apAZlt5T2uvebXaEN4f5Zw4C1pK.png","cbeebies":"/h05xw1JP88QtiOtvFw8HENlFafx.png","sportsnet new york":"/bSXHwrwZ0WknsA56lCynzvZ8cpI.png","channel 2":"/goKg57ALHXJnoMBNyKazKOlSNPU.png","space":"/cS39ZxQO8OVmtROHvH2LjQsJo1L.png","animax":"/5S9xrNouNbaYlhDkaZopIpcmbp2.png","wowow prime":"/dCN47YS5lugkwts5ellpW51cBzL.png","at-x":"/fERjndErEpveJmQZccJbJDi93rj.png","amc":"/pmvRmATOCaDykE6JrVoeYxlFHw3.png","cnbc":"/2spn0ROdbTtg3Ob8TTk2g48LQRy.png","tvb":"/u6ij3DirPrXgbvMllZFGdFwyx8I.png","dd national":"/mXNmU8Ya7ljkap8P9F5wm717CvS.png","rcti":"/qML2Ii1tKVCjLw4n84iWsojuBlq.png","soapnet":"/uf48VYnrrEaHBSNLxJbbaaEuugv.png","channel 7":"/ibIbm8NsXYrrPLRmSG74hfsVMnR.png","hln":"/cl9kFya9Ux8xj8sT0gzPEHc8lhL.png","rcn":"/46LNdPSG2gBxy3s3G9csA8vLH8l.png","gtv":"/gnuvnhctu0v29jgab3IW8Q9ob0p.png","cnbc europe":"/fVspXHRXTD2mLc1YFzp0zdWCYsl.png","tvbs":"/lSdTUbOqNyvGHwiypMJVm0ZqTb1.png","noggin":"/jQmuRRuydB4XPm6yTv6Src7LPZa.png","orf":"/3Yu4dZFU9eaavEj9U5s5ptl4fHj.png","tvontario":"/hDshGefbigrvUnGeRlqSQzUtsJB.png","m-net":"/dJ9KWprPx7AXMOxBrGJoadLhhZQ.png","telemundo":"/mieMBXx82qgY8nmnyaH0rY2D943.png","cnn-news18":"/vyRTawSUJVJpRQbm8LKsYQkNSDp.png","dr2":"/hvXnIfzUJwwNryDZxWfKGRR1flc.png","family channel":"/sLuWrN9nntgkRF18bQprUndxrvq.png","mynetworktv":"/90qPHtj2iZXLwq5nMS1xDtVm2YZ.png","people's television network":"/yr4HMPCZfulgTrqWqLldnWpoVer.png","cbc":"/qNooLje0YQh1y3y9LUM2Y5QCtiF.png","wgn america":"/kCNFRiqVRMgNWKSWu0LzAIpy9um.png","tg4":"/3gyjl5W69islPd2OZipKM3H8QKb.png","movie central":"/tSIeioQXU8kPnaMleoaCSrdfEHt.png","axs tv":"/m4db3aJTfBhgpgXoiqQRRS2znXe.png","rtl":"/ttANGe4D31vZoMmtmolsHSlZUAy.png","travel channel":"/zXcqp8e0W9YYKvwJpj9m67V7g25.png","hgtv":"/tzTtKdQ7vC2FkBvJDUErOhBPdKJ.png","netflix":"/wwemzKWzjKYJFfCeiB57q3r4Bcm.png","sky one":"/5tiClNENtZ0hdVupYGviUciIa8L.png","treehouse tv":"/q0I6cg9HiMt7Jpvpi69cj8t5vOC.png","global tv":"/lpB2tPkovzbAbYfyBjJjbptygfV.png","nhk bs1":"/hX0BGE9ZWkb3rVAVknHwGbE1MxV.png","intercontinental broadcasting corporation":"/jpWs4vSQgf5AeG2zMPDySKgoZx8.png","nicktoons":"/xlUUkgMevNvnKXcZ5z7F6R2CaGw.png","playboy tv":"/7iOalmkph7r4IxZ4hhOP41LCI4E.png","science":"/orcpefChr3hPSipPcoYa9gSq7ev.png","msg":"/w3lRAzzr0AZfHlDICAAPZRn0uVX.png","rté2":"/DmMVVZOtZ6p7Fkpa4S4XNKT5Y3.png","irib tv3":"/vRLKJDsQPgA8BfBG0pCporH7EZF.png","kabillion":"/4R1535w4NgBHAwqUYK7Y2F75rMH.png","here tv":"/cageYPqxfcJkH6DIvd2g6juzzVV.png","rfd-tv":"/aq8hpQPfhUSEwohm27RAhYLnKZn.png","teennick":"/h04Po2f2Uqq19xYHB4mbkjC7njG.png","rai 2":"/ar0fBQkxzbBYe4S8zEGnrfZNBnm.png","visiontv":"/dtnGkrdsbMsTRDBIxGbciiqWgwO.png","kika":"/1dtumlarEVXeYX1BrUFS9qLoG2Z.png","fox reality channel":"/xlybmiKc9R93u1xBzgRBVHh1wAD.png","investigation discovery":"/yfkdPLHjsed7vwUNuh20eMuDiDO.png","the movie network":"/7UcTAnlDj25ro8LQZJSFfyx4MXT.png","youtube":"/9Ga8A5QegQmiSVHp4hyusfMfpVk.png","france 3":"/2Lf7Sax0ycRzPAFy2MWM8ueLO7h.png","audience":"/tmhbFiRpgJFSmza9GTQam8ICyHp.png","tv aichi":"/zFZ5KCuvx7K0vP9XgGcidfXjuUd.png","chch-dt":"/ea7lVHA90j9UVg5EAEriWkBY6Y5.png","france 5":"/8xK6AdNT6PfRyygRvb2MKCoqrv2.png","the filipino channel":"/A2ZQ14XP6dm8dfSZiKR6gwUSPFB.png","speed":"/kZBWkOGlWsDzcmWBwtRCL3nZERs.png","svt2":"/2XpT6uiGyZH6tXbYATb8mTdThSc.png","nick at nite":"/oiybiBcUD3kG1XGQd27oWxF3zvF.png","itv4":"/9jZyZWsW7ZBY0RfvANDFj18Lq6l.png","soho":"/w3WfrSFdWiEr5dJMC3dDMrIyzpp.png","rúv":"/r4KMDmIFmjf1xhE3OmbSgaGNxt6.png","sundancetv":"/xhTdszjVRy1tABMix2dffBcdDJ1.png","télétoon":"/d7roMuKFcpBtQFteOuce4HjQbFV.png","mega tv":"/9BWPicebrzShoc8uJFxHLugjc5K.png","rtl 4":"/llVa87a3nemOfjSTp8yTR4xQCUa.png","stöð 2":"/iSwAMV35QvYvtjEd6Mds945DXQt.png","abc me":"/urZw0SJAesGIybpA9dRT8npuSEf.png","disney junior":"/gcKywHY6hQ9ZO8x1R6rSUNQ8P8L.png","w network":"/6dO7ncorVUIbVQDuj28loEVUWvy.png","canal+":"/9aotxauvc9685tq9pTcRJszuT06.png","cnbc asia":"/44H155I10tsBBvJ67gO91N5BH3l.png","eleven":"/aWWP8dpuGhK3W6NduSkGlo3JbPn.png","rctv":"/eFSACJaHlGL4X9UwimqWs2n0URg.png","tf1":"/fqsd09CrijoGu6qfoNIdgUQmVGO.png","win television":"/su4QkMUe6HngIPIDHZV5WrDSvpk.png","ion television":"/eYUrZKBbpdNX4xfqrYYtGXjqo6A.png","mtv3":"/u9LyIrxe50xzah32svsarAiYwDd.png","espn classic":"/lv2pOqUDdHYjwKD90EV3muMWwST.png","more4":"/jLd2mCUf1J1sab6NoJaeVa6Wcfi.png","8tv":"/maA70URks6mR45DatydS3UuEmlp.png","nba tv":"/bqrgXjfeWqTc9oTUgCcT4wTTQwq.png","tva":"/21BfveCN5mODgltQyZdB4UuELbS.png","mtv australia":"/l98wmIRlhjGZN1nR9YMXi8oQSae.png","the weather channel":"/y53akJvADKuINKDfyrbnxk3AUmD.png","ard":"/n8OnhOKcr9buScZzEvfJKO6d6gz.png","ntv7":"/bYgylwAxgdBaBjVYHgFDrTkXhlW.png","československá televize":"/usWXQzUqjcRQ2fZYaKae5G0941M.png","bnn":"/2RG1bG0viFfNR5K6IzacRgccKXf.png","nfl network":"/bbczSB2PKAbypWMcYxWpNaSjQcD.png","polsat":"/wY4JejqerW2SLtbI5poStyHyXNn.png","trouble":"/5BYWSGLMj5aG0w7A2UtUjboVRU9.png","bbc world news":"/k7mbvioXIHBZqg5nWlLCHzq2OEH.png","starz":"/8GJjw3HHsAJYwIWKIPBPfqMxlEa.png","canal sony":"/jGGIaOA4YmFeFi1S5krXZ2zaS8J.png","abc comedy":"/yoWi43bVJiBKolwn4zvq6omZl3o.png","c-span":"/fbDHCA8G5SviMKRvz1W6W0DRgLA.png","rtl televizija":"/AlVhoGZIyM56mL07y82SnqAookp.png","kron-tv":"/5SgFklnDuIIYNtD8gjCP8IiBcE1.png","oln":"/zS4kwaXhwNhMhoT55yOPtQqHxhX.png","fox8":"/84wCbPq14btKqZ60shwkf78viMA.png","bbc two":"/bfAVKGrJGcKTAndYktB7cf8UlBO.png","free speech tv":"/gcLVgJnxsOi41pf1EG3n5cc05zF.png","prosieben":"/hComKsCkgZRMWQQnNWu92p3ndSR.png","mtv canada":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","fox sports":"/3sFV9ixObo5To5GoGyEWg0U1qHU.png","kbs2":"/gKJIHWyoPKEu6AEKK4Mw9TY8kaq.png","channel 3":"/jjndRHOq412g8D6Hjm63rZMxAnO.png","access 31":"/vCHdWATtpBx9HYqKvxCvZr6xhlR.png","vrak":"/jbVGAEHzFWfEGvP2SEJHw3TWqV3.png","tv4":"/9zmhGgy7jANwrQduB16IubC10KM.png","studio 23":"/1PRHnwFCZGuPH4nNSTCZY8A1b6a.png","unimás":"/96qnI7mFiTafCgcBY4yh0m25G0Y.png","cnbc world":"/hfmJTKDzTNlV9jYRROE3eaqF3VI.png","svt1":"/zFb3TsNzVC8STlkSzbnF1FTHXTA.png","cinemax":"/6mSHSquNpfLgDdv6VnOOvC5Uz2h.png","fox sports networks":"/cjf6hfzFj7SPhJZAvLHP4Th69OP.png","france 2":"/aXcxzEpApUkAeJaIgA51imxuIcp.png","sky angel":"/eQYAmq3kPDMh3xCxJDncZrhsiaD.png","hot3":"/6GFmliU9Dv6pgSPfhMra6a89HA6.png","trutv":"/c48pVcWAEYhEFXrWFsYxx343mjx.png","reelz":"/ngpAA1R1mOkiwC7RAxTbgbip6DZ.png","eltrece":"/qa8pAOkCgETeqZUjGk3wWY3vvGr.png","trinity broadcasting network":"/rYyfBLqn23ZeWkrjlCoxZQONcXf.png","play uk":"/59bzfm3ea1STcL3pSmKwxWBsG4u.png","military channel":"/7J1OGBuET20pHmy0fZyHXaqBu1z.png","cnn international":"/syr5vSPmTOcNGsQ4d8H3tYBY8pg.png","tv3":"/8tHNliWyaw7WC4q1P6R2K2i6GRF.png","bbc news":"/hmOvRkVWqP0vpFXwks8krePxdKu.png","sub":"/pjxwmLHvlQ658M2I6NOe9FwaPln.png","cuatro":"/pZtmQfr0z82ODDxZsqGzORZJJux.png","nrk1":"/4TTFfXnGIEosh3EPYX25ERWp1XG.png","mtv base":"/lj484gn1gauJ84vZLTlwxVC3gjb.png","gold":"/koB7D1eoGWaKvyKQtYsiLeXlSm.png","hallmark channel":"/9JTL7HcaiVxq7M6eu5m7giFqaxR.png","dave":"/5pS7SazUfbPHBlYy8pnt1y0TgFV.png","dr1":"/swq3ovsx3N3hUmqODqIAU8BSdos.png","canal 13":"/5ZRqE0cyc3QZV73Q47KG9OfqUW6.png","tv land":"/lOCn3EqluXoP8olsZsJHoWITwQJ.png","tiny pop":"/5EduZEQmHFuJ7IN0vD0ASzEdzOH.png","antena 3":"/l7MngINTyv0O6mNlwNsUlhQ9iwZ.png","cts":"/vYmVFpUIzodAYpVyUzkW62n9Dz.png","italia 1":"/2cXinuyZFHdOT0hZW9ZSZpcQOe.png","sky two":"/lJMJ2ZIy7paWGAHArgAgVdP3Wlg.png","turner classic movies":"/bSp7U5Ok8JVsmnIVYBcKWx2QIsJ.png","wpvi-tv":"/vkZSDeY15RRknUSfi4NFRP6RPXj.png","mtv italy":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","rtl ii":"/vUNEwV13X4VWEhhfehsCzdLkLD.png","russia-1":"/t96cnWLH1OivW91EXygZDNSmhAK.png","nbcsn":"/42DK95aYJKNUHECYorwF9Y4pEWD.png","bbc kids":"/jQTIHNpmVPlxJSW2AFGxCalBGQs.png","fox soccer":"/bd3HqAbKmzHlEikgaVaS117ONOS.png","royal thai army radio and television channel 5":"/yzOyN0ZWBCYYKGJn1T8B7AnP7Qv.png","rtl 5":"/nxk9R0L3hJLlrG6unfZepCE3Hy0.png","golf channel":"/qeAzttzlfeWS0j2bJZ4EmZshRIR.png","galavisión":"/hm51VPYcKMALCh6bXbIXN6gfUyB.png","bio.":"/uWzrgtgTm0StkbazCqnD4YmjPR0.png","bbc red button":"/woHKsYIoXVKQkTnCdHnr6QSu1fD.png","revver":"/i7kP2gmsRljZpJbFrGFdiPy1ntD.png","bitetv":"/jlDSWBmrNUGzPagojwxSzfUAQkN.png","familynet":"/ajOiVQbESqoIli1a7Ecy7LvpvQd.png","pro tv":"/eMJ75CQIE9q7LBE3SWsMtxUlP30.png","velocity":"/pwozKkEio5Nh1UvffRGL6rP73Ml.png","kanal 5":"/dZMFAq8ypCTiG0XrU7YGJV5VTym.png","retro television network":"/kxjWiSSpQ6NLQV6lgR4jnxdrPaW.png","kanal d":"/qJXllHIGCEUF0MJUUnAMErglUjF.png","irib tv1":"/iFfnecuKaF8i5MewrOvTyXfgR1W.png","américa televisión":"/u5PIQvo5rpgb97FfhYAYFURKSjK.png","das erste":"/nGl2dDGonksWY4fTzPPdkK3oNyq.png","la 1":"/cXE4tgQ5hcvqSTwrlbGYVt7prHu.png","channel 1":"/7Xot603KMbXkbW4JOwyH2HCBsai.png","collegehumor":"/qtOgRuzVgP8skW96UmIYSIj61f4.png","we tv":"/gWllamFWxBczPiFxQzHZd2IAY9W.png","wttw":"/jj3MBZpVZOLyJSj1eTmNtjNwHGS.png","palladia":"/hP68W3FIJAyd4bv8UPgmbUPL2R5.png","arena":"/ccn7eromR1KWcv5xefUw9rGAVld.png","hulu":"/4giYeGORZzztkAAd1HOzrQ4iaLW.png","mtv europe":"/eQrvQf4A4P6iaTw2JTpzz1XVHCJ.png","beijing television":"/5LU9zEP1SredmscM25lv7Z1xW3y.png","c more":"/V6q6F7OvgZz4Ai6fBCOYxAhZBo.png","asia television limited":"/94NJxCdLsn1tMd4EHiJPv2iUODt.png","pop tv":"/uHBySX5Mfre9yK5cjstlxvZIZqt.png","yes network":"/3frmQPITaRTkeHW77wZUYUOPSGl.png","btv":"/vaSNnTr6c3HfXUhq5p7YlKZ2sSc.png","tvp2":"/ke3GCMWqnxUBS3TBWOZOfmoH1uq.png","nhk g\t":"/bH9mwMa64tQeVhmTmkC8Qn9Eoe.png","aboriginal peoples television network":"/qqTeEEAdCEfvYlTFXll8uu8Ld8K.png","ttv main channel":"/2HVxTrTSKWoFsYB7KxxwMMP1LBt.png","sky news":"/9YoK4mgfqsvxqWMNHQcwfWxKxaT.png","fox footy channel":"/2dMiTtgbRffsskfaGOejD4TO6Ff.png","tvp1":"/nSCivqAKH8fjMMBVt0DHI0FXEC5.png","truevisions":"/vckXfsEJ2Co45VjsosM7mk20cqn.png","kcet":"/r3yany6hVMVFJ9N6gsKhEWFdi13.png","las estrellas":"/TY6ks3vyDrb0iyw0ga2xTCVO2W.png","latina televisión":"/pJz1mGZl0xKchDHZkuV9XDLW4Go.png","bbc america":"/8Js4sUaxjE3RSxJcOCDjfXvhZqz.png","ctv two":"/s6BePy1BOPH3199Wkaf6WVnunpi.png","channel one":"/ffWS9AzEM2FTNLpe6mKt3bzx4WA.png","caracol tv":"/6lbu3Xq8ZsTMrS0AnPfMtPhjxQk.png","star vijay":"/jNnu8sUvVmv7Xbr058DciEzHF8P.png","séries+":"/qQxJNlfXVhNe98sOLUZqiDcZZYw.png","tvn":"/cvpDEjkTD4zar67EKtkHc3jzE4F.png","max":"/p68i7UhUANShAvfk6G4md5NUJEr.png","canal 5":"/kaxn1QFpkkcgacw5DL5lKarz7HA.png","5star":"/pkvQvUAnAKn9BLyoWSk7l7cm7cp.png","setanta sports usa":"/8koUXsbccaeo14v9bfrPJkjXat3.png","israeli educational television":"/3k0mzFUKPNY70aZdiWID4GFhQEo.png","france 4":"/4uNCyAdb8R0jhoIOObHhlUWaBrF.png","rede manchete":"/5PyrCDbFSf3rVa3WyyfstEPQHS3.png","channel 9 mcot hd":"/fBUJZboOehTu3izEeECjocUIJyS.png","pop":"/m5bolPhhZJ2SZS4XEo8ZCdluCds.png","nova tv":"/iBibvLYwkZuYc8lawEgGoY9GyNn.png","hub network":"/tL3aAxpgiKdCbSEbmfLKv08jXdl.png","channel eser":"/kMtmqoi9pLlWNMZy2qis0er2qBS.png","cctv-8":"/vvLZmx02cxpws9IX5P8se3ARBDG.png","super rtl":"/nDiZSdUQvqiAUROq6DubHA5pLDd.png","boomerang":"/lkMfZclFXosrByxWf459NrXBiRY.png","colors":"/kZRp9PV8qwGsLFkwEV7d7P04k5n.png","nrk2":"/uyuXWEhdRer47riC1lwpUHYI9sZ.png","zee tv":"/a9g7n8Frkiaaf5olShkyhHTk6bC.png","telehit":"/AveWW2HBYyYaowzgHmzZNiUtjP5.png","destination america":"/wEIVk7jOJnEwtKhrS5lNW7WPd4L.png","tv+":"/kFWoj3vcB9l91Hz9hWtTwDBcB27.png","esquire network":"/czsUqezqDyLlRnI3dUwytoOApp5.png","rai 1":"/pLsnP0qF90P4QAXTKGPgDsftKDl.png","recordtv":"/3N2U3nGeRFYGcwPLnGqqKaFeX6h.png","canale 5":"/5nhlFNs8ASHZij5ZNvF8sXwpLAL.png","star one":"/yqrTS5shXIjd8iAbUKUTqImgPQi.png","sctv":"/3Zs6z9zA8mELGA04fnFfy2zM3lm.png","tv9":"/d32YycZbbedFEIH1n0c9mkxcwew.png","dubai tv":"/pBS3SKvsoXDL1SEGjkseZ0vtwqn.png","rai 3":"/eRLfW6GOHrV9rOE0YnUIYzIUjyz.png","rustavi 2":"/h0HAku8p8oV4X3eN7SRbideIrYv.png","markíza":"/iCe2CgmhAi2ZyJwtQg3rz4LMcux.png","tv puls":"/dxBoW24EUtMh5MWdcTCjO3op0iJ.png","sky arts":"/ylgVrMSjD8vCPXuzkLeDfipmE2b.png","rtp1":"/iJBaPuHCVjROCUXZzGuon3oDqMC.png","tvp":"/AqrV3Nzf7Ofja9asZpkUxkBeOlC.png","vtm":"/5qL5JMrIzn6oCcKTITr3CdVnP02.png","rts 1":"/7MHxcb0oaOEEerv1TAKMwJNS8Pn.png","link tv":"/zhlDTzQIJri9kvJbO1xyUuIZwZe.png","onstyle":"/iOxSRZyRJ4W1eFxE4KjEAIzvgEQ.png","sahara one":"/qsm88BnftOCFmNa2NJFpmHpV5Pj.png","azn television":"/y0nd8l1EWIqttcOlgrobC4GrzMD.png","mtv pakistan":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","srf 1":"/txYJaM2VKunNRk3JooH1mnsVSOg.png","ant1":"/yepAYSCsRS9G4WF9Gt47GSuRjCz.png","mētele":"/kW9bMQqnMFtPHvdoyCDpRqh7Gxt.png","ndr fernsehen":"/ycqsY7zsvi2EkLAdAKn4rozvOpf.png","asn":"/cTgn4vc0AOHeEzL9ozg8vNmmrP7.png","wnbc":"/7OE3m5MRyJqBygASzLJ93TvvSUK.png","v":"/l3TVdYRGHqcDWMXxHdofswgynW9.png","the nashville network":"/9otXwFJUXTRyEY9jMSoGVhZXF5d.png","itv3":"/n4a1RiUD4F9lr31WLAEg8oHnci2.png","tele 5":"/2T0uzcONwa6w34MWdlN2QzJ08sr.png","tolo ":"/qsjFn5sFnqbIEgzqJapYRjvZ0i8.png","pax tv":"/tNnUEFZV7RmtUsHxVG3RmQn2WUn.png","abc news":"/sUZ0N10Qbg8zbZ1IIgyUTfhY6Ds.png","cp24":"/1o1hmmTRejn8gUH6IsvLFwm2f6S.png","astro ria":"/eD4l5QOBKFGojiWgXlQ3qQE7ntO.png","rush hd":"/oxLhbVU6SrEBB6CGK1lw6oyVLEp.png","televen":"/f0Ylm2274535HSBgicsuVpdnx9Y.png","ntr":"/a3DUk1Tpaubu4vGUITUa4NQSlGZ.png","kids station":"/7V7vR2yOXblLOZH0qa1Zcqs5BRs.png","tokyo mx":"/3qFArHw6nrFIdkH2tPht701sNhs.png","yle":"/9KQP9AEEqOpSVYgih9tqJKCkA1w.png","nyc tv":"/9eeH7SsakrYk1QC4KsUEug324ZK.png","dtour":"/fRv3FaOynrlFKmgNKxloMCH6BjD.png","new england sports network":"/tilq1nUQUDb7LNh5hcHyI5Laj0N.png","nhk educational tv":"/1N9ItImbsdy4AZcfs0kUlyYxQKV.png","diy network":"/bg1njNAqzcSefrDF9e64hQvRMbG.png","discovery real time":"/qaOBgzNyO8imgMFCuvMW1jtmM3d.png","ocn":"/x1PpeMBZ1bJzitJyPuuUMRN8u2z.png","nikkei cnbc":"/uZ5iuDKHe5N0LMXsGfe3UCvkeqQ.png","yle tv1":"/5WItBySbMUAklcJMVv6k4GEOR6a.png","čt1":"/z9TW8kib9BIuAWnP0hNhYpNcsim.png","nbn television":"/hl7xdx55m7dySt6sElrKZBOBp3p.png","fearnet on demand":"/uEbZJTy9migMWBlIeAQ6sHq30om.png","avro":"/lSjeePNTWHqXdwx8DvzuvHQwWVZ.png","future television":"/6JuHPsBeKOV5uU0LAUQJEBjCjvZ.png","super deluxe":"/1r6pLSTR1h7DQTXa87UXoiIi3Er.png","tvr 2":"/AaJV5H4lZ9pMXBHyyimUU4OrgfS.png","the sports network":"/eEtN7vNV9ISMft8TYUVvWfq95OK.png","sic radical":"/zo5Fh88xy3wjk6HqiDVilStaTnh.png","yes":"/9yWETECjfnsxZ9UtviBZXaZ087k.png","mega":"/kZtuBCs839orkhvhPq9w4EQRnKt.png","latv":"/n5a1CuFl9aD5cPNC68NUrBEG4Dv.png","vpro":"/96hCWEsfmTZQsoUap0CcG21qaA.png","good food":"/zPoHdGnUH4MpIeS6SFqr0tr0wzw.png","the movie channel":"/psTUtm3E7tIZ3D8IDOtfaRxYvix.png","arutz hayeladim":"/oAvXUCqp03ZYqfwokrCbce2EG2F.png","my damn channel":"/cpVjXtmCE1zUrbim16qOsypLsBL.png","trans tv":"/7k6LEMLTtmiMfSqZ8Ai7DMpl2W3.png","smithsonian channel":"/ksVbshmQi14s6WCeaWHmTkTk1a.png","daystar":"/5y8rXfTAWTU3WYy6DSbLWZGiYcw.png","indosiar":"/rINnk0IoS0jd4gMHCOsmRTD9iJB.png","arte":"/4MEB2DgVrZFPal9gfeFEs8GCF9u.png","chiba tv":"/8XNtModCxAwtvLy86b3phkE1jge.png","vh1 classic":"/nXv4IJqVHwFcAnDyJMv4P8UbrwS.png","nasa tv":"/uy6hjTBQa1qK5iP9aiJJGXKb4wj.png","bloomberg television":"/njT7K8UuwxAmS3ZgS48n79OJcWX.png","telesur":"/2ygPNCW0f24ACFG52nfvtOCKcZK.png","discovery life":"/q0s7tkK10OiIYM5eHO1dLRpOem9.png","aurora community channel":"/rTdsdWYeHNrXvYlOejMYgJlm8cK.png","ctv news channel":"/xKNDsdbwuS4CSzPodoz81TX00RR.png","tr3s":"/ngZZzCoTP6eFJjeu3S0fZ5iV5Dq.png","eurosport":"/AfhbW2Y6X9uwoZAgoP0cOfSPoH7.png","sony entertainment television":"/64r15LN2A5QKLIJ5lZ1xQitjeiL.png","ztv":"/rvg8MLiM3Lzzwi7CTd02Wh0kUP4.png","christian broadcasting network":"/oscTUqzDq0xgrACJOuOlUy2WSyD.png","ren tv":"/mh5PeHiXKewYD8UYSKao5c7GFW9.png","canal j":"/8yYcABkUdlDWGeY6gtH6xUVMR7N.png","lifestyle":"/9MBltiYrqFNgMSecwmFPrf1UAfS.png","bold ":"/ryeIUr3wnwUGnKZ8egBDN7bKgn4.png","home":"/rh6xH8UIqx4o3Jb0lMZArcsTurq.png","tv cultura":"/zfSn03BXad9VadOBPe5HcGrMoZW.png","al jazeera":"/lXoPBYZ40AjCPL8OgOuCFO6KHA4.png","tmf":"/zmukzR1VC0ee3sAYwE0kKUUDaoP.png","kqed":"/wARyrEcUQko2AzJ2JepJOr2s4fd.png","kqeh":"/gnRkWdoYbBSTssZzgVYsMPDcs59.png","one":"/dpgEQOqag77UYovQLM1GXNWywnH.png","cctv-2":"/kTWfqWGvWDzMTkmVGVEc363DjrC.png","venezolana de televisión":"/bwfWL9rt7QPvOXlflLFKG82RmoF.png","yesterday":"/gWBrjMLsPypHyQqin4cXz7i7v7.png","tv nova":"/twuMX6vryssdv8oY01ZD5eNTKLt.png","m6":"/4iYtRK67O8oiY3PqY7W1V5wLAYr.png","panamericana televisión":"/a4MhsRdI14SBcQYXioukdJTNw7R.png","teletama":"/yhFNPfWqQTOj8olwR4Gk2H5397X.png","tvp polonia":"/gzGa9mzkSuHjgynb0oZnvEicym8.png","jnn":"/3nGVNDvVqavpmlVk6jXDPtP4JSy.png","tv 2 zebra":"/kcMwQNXs2AQsQIrKy8CS3hRha2l.png","funimation channel":"/a5oMoSOlNaH6AydiqLm6Gf5dnAx.png","tros":"/vVmQTR6osEsk7bfsKKPQEVTejIG.png","kcts-tv":"/pkbYCkZql1GlrEwubaoSWBbOBpb.png","teleg":"/6chdmJlRJQ2LgsGbUuUsIQG9fXy.png","kgw":"/oEn2me5z7dMiuiyb5Fhq0NthIc2.png","mlb network":"/rN8HUqQIGsHQwTMamuQmeAZdqY7.png","great american country":"/oPiqGNF9lEOuyZVRfkph9YY2dEB.png","show tv":"/8kD8Spe7RlZOqNV54bIvLuAtprO.png","geo tv":"/5lRMiLqqjuuBFOfYi9Z0m0pCOKS.png","outdoor channel":"/iRg8Zh8V4EB3KvWFDrAfuwmHfS0.png","star world":"/cGR5NFbkIsJayT8lcvJyiQmZq3a.png","veronica":"/qmnO61PjyHfi2HqsAQszL20GLpx.png","starz encore":"/iV3yGuHerGb6yjtNgGlCabTARse.png","vara":"/el8phAL6Xa6vXvvaQNiELmEOgx8.png","kro":"/b0egFPlnPdqnhhWywwKwpdl4GXJ.png","alpha tv":"/jaY3I8qSvcymAOMsafafhFatC80.png","rtp2":"/xQEn9jUjxou6R1Ef2pjBQt887Jd.png","nova":"/cXH7lEOGhaNHWTHcTMKbeFMk9Lr.png","muchmore":"/ukImteHLH8BfaRwKH0zQG0yUPV6.png","w9":"/e5TTp11V850EmQjoeoTd93NyDHS.png","star tv":"/dEXIDBT111hJgZjKKHKB1o7jhQQ.png","rete 4":"/fWh7OAc6hGan6h7gYiPu6ARdAdN.png","national indigenous television":"/oTYxKyXcetIc1LXmvPHI60kXrYz.png","vox":"/tfrd4tN4KOr9cWmMBI1xdhWc6v6.png","super channel":"/rqGf031msXZRkHeoRu0nRlI8vW8.png","nbc weather plus":"/kOouDwONltKwZ7LACyEe3E6MP7d.png","star chinese channel":"/vdDLFYlbeQmrQpvxbIroRyYuIrJ.png","tvk":"/onniCKpgZl8VEVSS8oa08Oas9jT.png","nuvotv":"/zHWUAxaRHLGdjPp9OOIAU3wjDBh.png","mavtv":"/l8PRX4B4OVVZvpIv1WspN3ZS43i.png","national geographic channel":"/5UtQpFierweXjriDoRf3LUVDjce.png","kfve":"/izJGbSnzWPJgA7OgoaOUzW1fbON.png","american forces network":"/rqa28aS9PAUfBsRYqYRQGIqYTqP.png","cooking channel":"/uquJYxCMkKMUsXatUMLbiUAb0d8.png","4music":"/zVmoePlyh7CyDS5lRPBvtwSR0mp.png","viva germany":"/3DTdPqvewDwM6SXOW7Ca45EX2HX.png","chilevisión":"/xU0AW8Lf6mwRGiOAwzUPM5XNbHT.png","sts":"/7746GOkRkVW8UviV1OqDNAzdpgE.png","mnet":"/8R0iHi9qYaEvWWv9XH5XoGpuRJk.png","azteca américa":"/f7ff3vL4zYHHqZD9OhhI7SoWB6M.png","cctv news":"/K9ZzEc7RdUaVzUnaAiYT2QIvkL.png","ary digital":"/eX0FNufESHTD8lFBwP31DcieOCe.png","tvm":"/bpMDF5niZ0OBMsclu9vJ7JOjnIh.png","sun tv":"/5g8LER5X7tvziu3We71m9HnBmy6.png","sic":"/lgc1ScGTjapJJZOZezszceuxRyR.png","fashiontv":"/hjznlXXosdr5bOJ9G0yU0rTgHRX.png","tvq":"/koirj3XCAq3J6OK3YpNepJIq7lO.png","tv osaka":"/6foQmoPac7WCDnDuDbuCZklmDuA.png","antena 1":"/rXFw15vvldWBxZuJOy0kmrkGFfO.png","own":"/pPdXGF9RKhb2R3SUMO2EH90ehJT.png","planet green":"/aYCHvH2wTWT930WChun3xJhj79e.png","kbs1":"/2XQNaYF5fQWbPkX9J9Sat3WiVHU.png","polsat news":"/eokeifaZXb84ScRE59fciPmjEsI.png","magyar televízió":"/f5Sn7vW86OR8wsoLmc0qPi34hXB.png","rtl klub":"/fGmCnh6tmQlCllhaFaHbKf6dSL.png","zdtv":"/46lTha6b37IjPBYl0Fp2lSSuDP2.png","disney channel latin america":"/3DKY9AYDEWnDNYcOcx6iFVTLpg4.png","pts":"/qEQ4L4VyAUM4Ea1x1CMrS5JaPOt.png","comcast sportsnet":"/l7UYVQv4kzjEqFwVjpJspvZeoE7.png","rt":"/1Jaw3XrH1YIljfYKzreC5vccham.png","tv 2 charlie":"/gMiW0s4TcDsd890J4R0wKUGkxPQ.png","canal d":"/nxwhjDnPOJxtcfvfz0RaM8fSloN.png","5usa":"/aiNDCNGIJagS5D1lzgyheQYdkya.png","nrk3":"/sW3AjUOXSsmsmzZJl9M9vHEGqKd.png","tv3+":"/1a9ziVZr8ICI6dIQSjfqRMoT9g6.png","muz-tv":"/2OyKNnKFFViTCfpW6eMEHyoYSj7.png","h2":"/bd6vDgU9S8RHZQhjACj007vSnR6.png","the pet network":"/yCcrTmJqJv5tN7sBwsLUuBGvKmz.png","antv":"/jtNG2wwB894Sq6zgqMWtcTjFIsp.png","viasat film":"/gNycHYrLZc1QEcUadiVsTVfi74x.png","sjuan":"/A5MluV2bOnC6X5pZbEQ5KJR6doV.png","sbs 2":"/hDsDVGDpMAF4RYDuLReoCiuy98k.png","life ok":"/hYLoiHpf64G0PY0m7b6LevhCMpf.png","2×2":"/k8iLqMFhoJLznlycK54q63faZY2.png","ctv main channel":"/zqFRxhKTBqiQ1GLghwJUG5ftBJr.png","bs11":"/JQ5bx6n7Qmdmyqz6sqjo5Fz2iR.png","action":"/gtVM4iIAgwwoGrrpoB00JhgLO8M.png","trans7":"/w31NBcd9jhVFCp6BFzhhTpFyGSL.png","mtv brasil":"/tPc6YzgcCoIwfWoILOmj0kMwBHe.png","west tv":"/Yp60FMzSW5tXpLEDQoBs7AF7Aw.png","trt 1":"/kifpl4V64lK6PlRk0bRM4k64oCN.png","formosa tv":"/qSdro8ifVBU5wcLg3T2tdT6u694.png","br fernsehen":"/aaKRK0QfSGvQYgpCQXLmn0L6mwR.png","direct 8":"/4Dn5JdscAUXQQqVCZ6lDk8IVUVg.png","fox sports 2":"/inrSGtPRteNjHWKgmv0cJrWaPIt.png","sky cinema":"/tRhoV4iavui4O4w3c2BX5yNTJEm.png","tōkai television broadcasting":"/pX3gDCsG8WcQvQbCNJ37t5w0HyG.png","tvg network":"/sdi800YFyFgxuW4cuhefD2X59yp.png","bs-tbs":"/zcWERoR0KacvffK7PBeAdQfcfmI.png","jtbc":"/44I4aVlasm8Blb8WPGXTkMYuZJF.png","channel 7 ":"/dY1LkDiKcZGs0F66K5BRtyzsXpO.png","band":"/1bpeEUnCwQUrU5XQLP0msaIwv4e.png","bandai channel":"/xGS6thPrtg4hA4bvjyKuWcpPSrk.png","tulip television":"/qfUzYnpnN5bnd2bqGUH0OlAMell.png","cnbc tv18":"/sAz1kkzKmYNjTAYXVnYCzkHBITQ.png","armenia tv":"/4Qe34F4EZ2H6s9MTKKNjvFNtq6z.png","tv chosun":"/cdLZORDaBfQEDaHFIJyhpGqlGXk.png","tnt serie":"/oPPsO7TGHwxVW7h8gsi6BP6sHYs.png","nhl network":"/7T2utseIB8pm6YNJTDRBmsNTLto.png","byu television":"/6SS8KHz1KH594IG5hom9bL3DQI5.png","big ten network":"/4KrfOZXvC3AGcKuAI3Xm07xvnwo.png","nebraska educational telecommunications":"/4u8WeGjfq1Hox7SiGAm5e9urYX8.png","epix":"/jGPp0XFofiNt1kXIqu8GYZ0KhXv.png","all-nippon news network":"/mlcZ8Y4Q71rKTMhH7ItHH2ZrCVo.png","mtv germany":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","central television ussr":"/eMCbJfoNCBZlbDKQO6NrfFyfYng.png","crackle":"/bR8S6Fjv3VGtEKyKF5lvvRJ5xfw.png","mbn":"/7XKVnL4rDYZNBcTfalthDYsnYzs.png","mtv asia":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","sbs plus":"/90qhJ7ek7FmvhxGciWqZIi5R3Ed.png","ocn movies":"/uabddxuKhIPCQhr0QsnbATDqVWa.png","tv joj":"/uTNAiA16CZpw9IqlvizCswtXV2m.png","trt çocuk":"/plxq6VJWQkcJLiB3hXhGbyBosvQ.png","tvh":"/vEUZNYjuSn0iTQyZ3SLNfVgI9Z8.png","theblaze":"/6hv8xCPpFAWuRBwcc17yPgfBEc6.png","xtv":"/joesfMvq4jbfQQzYSKBl9y0qhXi.png","la7":"/682kUhTAnoqLnjVrVCCDNWhd78f.png","kino polska":"/bKJKrhuxL7C7PcLzRZ2LIt8lxi6.png","canal+ poland":"/snQBlVJrlLu8mgvvNf7cn6NUP9g.png","hunan television":"/6WVfgvW4r3jiw6v80jflHSQr41j.png","domo+":"/hf9ytYXqJD3nltQmLIjfxm4HAQd.png","mtv poland":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","samanyolu tv":"/ocg7ggjBkHjBoWsivNoLfcepQHi.png","mbc 1":"/wpmtil822d31Hv74wMb9UNrpPZr.png","mnctv":"/iocCLzVdgFJnrY6jgBcG7t0T1XO.png","kompas tv":"/4ub8nWvuGWTImEZ1iA577gDouJn.png","rotana khalijia":"/pLBBENYny3IzqLdIj1cqVj4cRDx.png","acasă":"/p7iv8u65nbOCdS3RlMUnJKDVhUY.png","prima":"/rkXrvlCHvu9kholozdXInpFIcD4.png","powned":"/nmLUhNof9VsJrBfxWLjGVQpZWiQ.png","tv6":"/dQjXZCl4bbXkYjVcXsfLKlWXRDA.png","tv2":"/ze9D9aLekVWZqLdrD1YeBKBgwz8.png","mtv denmark":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","turkmax":"/904DQtkXsaJgda0Bd0lUJ6cqWgn.png","asian food channel":"/bInMzS40CwuFe5VshmnjJllxPnQ.png","astro aruna":"/uMUHnF7I3MdlqAY0aGNCanlzdZ.png","music 24":"/u0KvrWrvKdXOn5WW0Mx9CNINkS1.png","antenna tv":"/jjvypoVqza69K2KOoiXAAwWvIqB.png","abu dhabi tv":"/xkgPOy6LEhz6sxS9JUZi2SuZJA0.png","zhejiang television":"/jXR61DUeQu4jdryz85cjnCFXNNv.png","etv":"/zsAoHKZoisS3UkGVE1ypc00610B.png","bnt 1":"/3yGshVnJkeBZebtnAO2D6NMadK3.png","liv":"/gkbzGqaC61olfJUxGQpQNVzPNO4.png","yle tv2":"/pbnLDOMP0nFRgyXMehuAzxh4Y5w.png","quest":"/9pZ9FYfofnkNz3YvAgUfTAxrLf2.png","channel [v]":"/343n8epNQbuZzOvafIvan1WJNzA.png","bbc uktv":"/rVzjodqFFtiltpYXyXqNfdXJ8te.png","fuel tv":"/owTQrkg5emUr1bUwpPOOfdyW1vv.png","espn australia":"/h0cjpCMfeX9irSu3g6aLLniKP7E.png","nelonen":"/laL9hs5dAbGVG3SZA4y139b5dOX.png","mtv russia":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","plus":"/vkrkqstsMEqFRoux9ivPHKeFQ4m.png","eden":"/4KwxxBQ1d0sJCXRbG7tLX0ORk8T.png","el 33":"/e3wM62UyjolroXeYPxfiay1WVFe.png","ltv1":"/2QYKk9W10eTizbGlkhFwVmpJM4N.png","ichannel":"/b4SB7k3AzNR0rbwZYDHgJEixXkY.png","lasexta":"/pQK2RR4b8Dzr1XP6LEKOe57gb6I.png","manoto":"/nsSvyXHfEIrZEnWo0lzFICq9QET.png","thai public broadcasting service":"/s5BTEEGw6NyRd0RiJlzbK8ofdnT.png","sportsnet":"/e5EpXQONx9dHwohXfEurZJEZgqR.png","whyy-tv":"/6atmMY5TxsEpGJJjAeJNnfn1Kwn.png","prime7":"/5tA0UNpqiAb8RhZ0lGJMXoMgK4a.png","amazon":"/h80ZoKsOPXKG7tgsMhm0znzJAkT.png","wwe network":"/iTD3AB16Bp9NK7HEVr2wOw43MPJ.png","één":"/cJL7S48csOFFRC3FHdFV44T4xjU.png","playstation network":"/oLrbwkpqM9ShxO67b0HQTgT3tkW.png","w":"/Pp7UfEzEkXo1blroQ7PpcVQBqw.png","hr-fernsehen":"/rOebGShjIWMSBYOihHDSVdV3q5a.png","sbs6":"/e3jBhigg6nvPkjdee8E7mdwNlim.png","fxx":"/hDLXRZMBOCbpVYpkBbIlLvMXgdX.png","sky perfectv!":"/o4LTo79SR55GEYQKFZjq2MUDb7n.png","vgtv":"/ngr0Gjq1Ct6YJVYfmIcmi0FzmNg.png","vier":"/ttsSlZKl2MIZuen6NfFpC89xJD1.png","nat geo wild":"/esXeePrsUGpF6mGQXs3jImz9QoN.png","al jazeera america":"/yTwWYAAwL2Ag4wxHVzOnhwkjwUQ.png","star channel":"/4FdEFkYde4AyjOoRTGw0gL9DREW.png","cw seed":"/wwo3PZyBpHL3Wz8eg4cr3kqVZQY.png","aol":"/i6qYMS1mYYQQh0INmAQPz20wzdu.png","bbc first":"/gLNh4QYTeYCKJzhZwzzwgMEqI3n.png","mbc masr":"/gdNW3Sdhx4tMhOhp4rr3Ok1iJqq.png","jiangsu television":"/lVrjBzC9COqah57JSkjx6pjOXtd.png","dragon tv":"/neufSFU0ZrXxA3c0JRNpuNXzLdx.png","duna tv":"/bPTVfSbxQsQJucD6ev7eF1c5n6j.png","yahoo! screen":"/wHzuLEPQSkQeFFPNy3qx5XsLMxo.png","hbo nordic":"/sFWkLyP2ps3yUOajuqaUEWxpSWP.png","sky atlantic":"/iVij5p9Mxfoj7mOmcLvVlKgIx9p.png","rmc découverte":"/xU5g31CXgsP7BhcDtXx9yW0Emrj.png","vimeo":"/lYL7PahejU2LKpMVixqksxnQ448.png","fox premium action":"/jjXxcZ0wMkQcvwocDkl4Y9jOQ7f.png","ocs city":"/6toCBtsVvbItflTy1gg8qhLwx2v.png","lifetime movies":"/dNUQ8xO2D13KfAke4lmT0a6JYHH.png","canvas":"/i5MdIv07gHYRPhYlQ6mm3RrATXd.png","sky uno":"/NN6klPGA1vVxbldSGZIllYIeK9.png","fyi":"/2svUcQHkz1Cz9afvBJQHfatjpow.png","olive":"/4zo7YRkORjKD7vRVBdCEDHPTqId.png","niconico":"/rU3iJ1dHKneqKLqZ1H1lc7eNy4T.png","net5":"/7Gq1M8lgHL0KyZ5htehDZ8A90aO.png","hbo latin america":"/xiKKr4gL7TM7Q5Rn79LrYFeRjV3.png","multishow":"/5Ane2hnYZCjfVHV0OsHyzdtTtSg.png","contv":"/4RcQmKjjI1dwfQLpbaszYuTdDTC.png","gaia":"/kym0UnNZNRxGHdZsFBUQNCCRrcb.png","google play":"/wc4mcODIyf07UEnqEMusJS009v0.png","kabel eins":"/kTU5bdSiPMxHkOvQsTWQSZeOy2e.png","crunchyroll":"/81QfupgVijSH5v1H3VUbdlPm2r8.png","dmax":"/sekWRXrSt31ZKIlE5tRwY8GA0YU.png","sky italia":"/dNuhKIiAChEJdGA7TXQgwqbFU6y.png","foxlife":"/fLvIov11xLjV93nK92D9NQ33l7B.png","mdr fernsehen":"/m3LuGFHHjhsFgdAkYhdXxL1yeKN.png","el rey network":"/9z6vxDNyom1T9WSDd9rCwaVLQLs.png","hbo europe":"/tyoN6zoxMJ71GBddxVkk4dpaeze.png","antenne 2":"/1JnQqStddzcIoa6XYB7LqJbLx01.png","télé-québec":"/2U9tjiHqLUsXnpeBI8fNxEX7CJB.png","3sat":"/bwqI45tuLt3qygttnZUz4Imh1dC.png","tmc":"/mG8AujLo1qacorLWNXqHqMCxlPM.png","wdr fernsehen":"/xtK4PjzICkOEB2JSD9hgeQLow9K.png","bs fuji":"/6y8C9KrIkfstbIkMX3kxdOjimJt.png","kbs kyoto":"/j12pSWPsDBxE1mmIpB7M8VRzk78.png","gnt":"/ykNd5NwABd2hmcwvOrTrneIPz2G.png","tv8":"/4xyjzCRkpueVLcTxvFapZZPNUJg.png","tvfplay ":"/x8wUwvtwsrlyl3pjMvdhZYpwuZN.png","naver tv":"/zt8MWI6nc20BCTViJPrtFPJFAY3.png","ketnet":"/3IdQwXxK3WlYfc0wUumwBIcN43K.png","bbc iplayer":"/zg70HfOG0FHyKEvTGp7RIP4z94A.png","itvbe":"/cKcGa9lsFn0mSY6TDcskNJ0wDAh.png","swr fernsehen":"/f3WRCoSDZyXYmG6mcg3adgSAnfe.png","kansai telecasting corporation\t":"/1J33ZvSff1VOEt3aC8CyKmj9GEy.png","ictv":"/sSlI7H7o85Lixv3Lq5hYUeBGjHr.png","stream.cz":"/w1dYHHZ7E01XThKEFxzGC7SrnEm.png","tlc uk":"/nDCnUdHNseEmnVaek4u3bPl0bZR.png","mtv lebanon":"/26t1txCTRfGjN2qW5WZegWuTiF1.png","toons.tv":"/est3feuwDI2L6VxvJoDIa33PzJi.png","gbs":"/wi1TlXf4tnnnEA5m3DkbH1X7iC9.png","mie tv":"/iJZZIOdaKz7aYK01BTUo001ooPc.png","up tv":"/6lijJgGj3wKZMKPuMUyh8wpUMtx.png","nt1":"/7Cpds3V9PLm104O3iyjg0jrTatz.png","travel channel united kingdom":"/pGzkI87fhsp8w7Xi4uPhwMVvyJh.png","duna world":"/yEp1BDU3rbvF4IvZ6mzHaJ6LhN4.png","npo 3":"/wVbxJBRSvSdGeLTm4z7WOBgTD1B.png","ortf télévision":"/oRNBLezTiOW3WMly2rOqXoG5a5H.png","russia-2":"/liqQQATn4eTB72ZK4dFYfTv0F4x.png","ntv ":"/brhoCkVqDnV6Hhw34w0QCLrxAJe.png","das vierte":"/bcWqbhaBEdcUGdoJymCo6S0dBMe.png","hum tv":"/xcQRcWC6mfhpSMvb47Vkr1uqvpc.png","stb":"/8VidRVpoPUAtOCWfqgtq5bMnyD0.png","sat.1 comedy":"/r2SY6PDU4wZQYdqffPrygomz1O1.png","yle fem":"/A8L0PEH6QEMB1SszGWuBaRdOghT.png","servus tv":"/9KwJgZRZazjR7iTDPQAKpyfuJP3.png","rtl telekids":"/qhLwkbUoGnSYSH1OBIFpREgDckA.png","rbb fernsehen":"/cqkLRyzEMuvaUYWWZGVCdZWwdVz.png","gemini tv":"/J8ukrtA7oCTidkE8tqJfl3vDeb.png","avrotros":"/naqjpD7duqbwGkzDwmf1o00wD9P.png","eo":"/9xXq6b03qFEoB0C0z7p2K5vCcEo.png","twitch":"/9zEimOdB52l4V4zUa8cQ1pp9fxm.png","divinity":"/ylVTWpC2Tsyyy5aPFXwcC8NlOZe.png","mbc every1":"/3p143jGfJyaYvjHoM4nViY9uTff.png","facebook":"/6LEYZhup5GJmUyTgXTk8q44F0nJ.png","historia":"/tBLu0d0gheCMFpVPbbQOlvh8BAN.png","z":"/lumkoDUOMH2CtfbI8TAJdHIv1ku.png","movie extra":"/5CcSuKdeR3Z1MCQmEVlCZq5mE34.png","1+1":"/xctncKucNjPJW800COSuGF8J1MC.png","stan":"/7xkrqChYGiXQYfcxKTNKmPRH8Xs.png","redetv!":"/3eAsZvWd1bZF35edX61xDhFPsTh.png","tv-3":"/1U8FtJNwKMiUITng9A6pOY6jnt7.png","sohu":"/2Ew6jjFlEPxeubJEijHZY14Z27p.png","cartoonito":"/q7mFfgYZU6FK45npeHgXux4bHKK.png","canal brasil":"/xrNYfnO8sop22tP2R75g4JzRC3c.png","freeform":"/rsz16keQ0hiBWYpaKIFspsMwuqj.png","zdfneo":"/5xti6WP3i8AoI9o4Wl813JA98CF.png","rtvs":"/nDx34bjfT01XwaY3WC3ASOYxS8T.png","kyushu asahi broadcasting":"/zph6Ed1k57GnwNkwjKSLo6wh3uk.png","addiktv":"/ymw9354i1x27T6s9QaIqo7ReAOd.png","sixx":"/xSfWRN9kd5mUp65JEKRD5IVmgcB.png","discovery family":"/zza75igMo6rkTC3IV8gT6TwXMNl.png","hdnet":"/4uR2HZZyKf0jikSAAGnY4TYYDIq.png","jim":"/hfFPMSsWBn9gFBQKSNnIohMo8Es.png","club illico":"/sqJrxmxTASr5HaDGfARp2Mv1Cm0.png","canal once":"/tTviRhCAJzidTyGT0AT0kIXXtRe.png","moi & cie":"/aTKxGzJVvzUbuZYohxwBC01vhWZ.png","go90":"/tF8iyBRDO0DAyBbhrRhT5ZSbBf5.png","atreseries":"/8eVtnRtNna32iu2iMgxY1IWo5Jf.png","discovery asia":"/vWHt63dgArLtqnsSTu744G6g3sS.png","hbo asia":"/e0TPhobVyxQ09bu9r5qj3rQLxkj.png","pure flix":"/lnKHz9ppcvIiBJkG9m2hVehDpFC.png","telemadrid":"/3BrhXENv3fNvyGHsB9xNCat2BuS.png","prva":"/kcf1jXy3LI49k1tBB0qskDczkip.png","ovation":"/taRXRfIg76AzEGYMorSzB30Cpse.png","ici tou.tv":"/eSiNfjTIaEWJ8zF6cLagHAEzj4P.png","televisión de galicia":"/xFCWp2bNmwQFG6QAF4Pij7TqAiZ.png","television maldives":"/1rLr1aixQ3Eu55neO1hYprwXbpK.png","timvision":"/6TbgPzmPzCnJ69fxSicj76d9io7.png","repubblica tv":"/cOwQwxIKPJTuvwsxDOboCC6gRF8.png","domashniy":"/pgxodwZf8IyWo65M89wcbZouM1N.png","tet ":"/uJtL9RshoQjvDWy7vqJI4UuUwvA.png","abc iview":"/yQrlu1TLTWLc4QSCsC1N7M7lGoz.png","iqiyi":"/t2HmORL2WgZdUUWyK2QOVIU6lwv.png","videoland":"/iUw1KzetjpvsQnz18iZSywTGwxp.png","viceland":"/qatKbG5JUVlG3TXyTSQmakI3Pdt.png","chiller":"/n3uRSQoUznYxEHoedb3TMqJyKwU.png","crave":"/7tpqd3YYEChpmsxefEoOt4GPUW.png","abc spark":"/ofTYpgSeD9g1ngurAigv2GwesDT.png","la 2":"/htHYdnx8pGORO8fXZX5xNNL9CX0.png","zdfinfo":"/dQPFVeKoJHy27pF18gqpT9xzIm.png","bounce tv":"/tWSCLKFpIiV5Ss1uipUaKnd1jM.png","history channel italia":"/aeariwRHHb23lyOr3AczHz5aIhb.png","rooster teeth":"/dMmhDfPq3Ulz6AIJ9G2ymeTKwUh.png","la 5":"/fBvBN22sqohV1yqsbOY0YqUvt4d.png","stream tv":"/tteR5Nu42tXwynoir9Tqnl5nMlM.png","mediaset premium":"/mKI1LBsgZPPKSmy4kq4hXTZI7Dg.png","cctv-1":"/x0f4gH2NOQpE77XF4E8IrrwfoKU.png","cielo":"/dMBZYliXeBx3LWWLaa3no5qbUD7.png","rtf télévision":"/h6JrmEHzmsNEaOo16N3YHP2GHHl.png","reshet 13":"/tyzqjTqeUob43G4h5RorVftFQOt.png","tvnz 1":"/tRUJaANZCvxWQbQfdWcP8UvOjTG.png","itunes store":"/jSixO9O2oYjNgBQQRlPED993naB.png","zoom":"/e88FdLtfoPvIWgECmjO3EbqgKgL.png","dr3":"/8tkTPwcCC6wRctDgT53Q67KIFIT.png","la une":"/kR47hzfGe3zFsFipHTuC123qyCe.png","telemundo puerto rico":"/5X2cgXYnWHLyNAMjwdr8csWn0E1.png","viki":"/elFTTrZr1Q2jnI1j0mHh0h7B9B1.png","kanal 2":"/vfrFks7wIMo61gkDTgHuXhfebcY.png","cadenatres":"/eylWpcQpVqVeNfMQz2afE4sSmgI.png","ava":"/kHJSF8VxsrQmhh85LGXoYXBVC1K.png","m1":"/kn04GbAmCv95bMiUaIQG7q4BH1n.png","crime+investigation":"/vitUTPUae38gzMRl8aMVecN0Cme.png","nitro":"/yce3GSxIR0USFkq2qA2ZTUqaJWr.png","asahi broadcasting corporation":"/ca3Qw7exc3RPSd0CQFOZuSNbGjF.png","fox crime":"/9Jvtpn5dHx3GwkLZFF3Uu7Qxt2X.png","tv wau":"/4F4WYqokszsuLaWXPKdlzAES8xX.png","youku":"/jGumA5iP8eXdQ22EOFY6kWrBzza.png","rai gulp":"/nzYlSSVEia1cj51VU28MNZt70IO.png","ahc":"/6raSjDirX1vidlYindgj300ORyC.png","sky 1":"/wKPXzKFHqn7YIiOK6iuRwGn2uAX.png","npo 1":"/eDObRs53SyWCHlnFoKTTnwZGPpB.png","youtube premium":"/rzx2W2juybm6jbDljxTNhLk0LDN.png","ami-télé":"/n9Ew7VScCbnPccoArCHgTFnohOo.png","pogo":"/qAhtyf2OX0bowig8g8CgG9iViRb.png","flooxer":"/vTpEiwbk7a9qi63xCwlTxhJ5k4W.png","cartoon network latin america":"/nDFWFbAHEZ8Towq7fsVCgv4U245.png","tvp kultura":"/8N2gw2i6CvoJgHQisNnfYESGKrU.png","btv cinema":"/j2Sk7rRQ8Q1J48OnoRrXGP3XbOj.png","pptv":"/oISsIyupFNddsKTsvL9sdBpJnyz.png","ncrv":"/fNRriPhwrnqLLTtus56ZVMrTUta.png","family chrgd":"/bvD5SchGvYFLyZlsvaPryPDTjl4.png","minimax":"/9COoUNYnEb6o8oGkVOrxEq90Ovq.png","axn asia":"/3Xls5ATyPM60HWKiDuVSErnQdzk.png","sabc 2":"/t1OEW9w4G6X4yXVn4Wd6dBXeAWm.png","abematv":"/esNzq1wc1ZciitHPusIIHhTPQwg.png","infinity":"/8a4NMo0A1PYOeLv4v7dOazarcZj.png","seeso":"/7LtW83ODEmIxDDwGBTVo22A0vcV.png","epic":"/aA1J3TjNvUCs1zEssJpwbDeNF9T.png","televisión pública argentina":"/3jB8XdFxuxgmY6O9db5I1vyvoOC.png","tnt latin america":"/nLB04d4R5UrlH3AsYDRAcgAbtq7.png","tv5 québec canada":"/5KU8oRvXX9I1bWdiATsSlYqx6em.png","discovery world":"/qNNNVIAnREE8m12VmuXd20OGqby.png","wapa-tv":"/olygrPxYGt9otF7BuYOCAWuUsBA.png","el nueve":"/iStQ8BYrxNlP9RICqPFHCcVAfN4.png","7two":"/7JvANenUas1w596l5ikfSBksDN6.png","sbc":"/artkCykJgOAh6lAjfrNNgANasgk.png","&tv":"/qmI9f9HOyY3L9ZGMgFfUExBJ9yf.png","prime":"/uHro7KWaW6h2Dj4ILFKYC1UJbd2.png","tv brasil":"/q6CBUNLpUaqvkI4ukrcmHdlIHn7.png","spektrum":"/4j1soX8JkM0W2nrlkrO15ir5Gy7.png","viaplay":"/zs2yhnfMzRLoRtZgGRf41mqrLL0.png","al saudiya":"/zIGFsV7DK4A5fnxBEmkrIlS2MGK.png","hbo canada":"/o3E090mK4GIg5He1KUnJX5HGLij.png","now tv":"/kwHeVfONZfDBfBwToWGYcYkW1U3.png","cctv-9":"/dU67Pko8o057r6mea8kAHEO2Gyp.png","cnc":"/nmrpwndiC6uTS4uksPwk4O75y4U.png","tnu":"/egMex7hlhlrCFbt0xB3H8PaBisv.png","c8":"/sxXmhPMQeGeYwbh7RKMqUztnHGY.png","trt haber":"/qrT9NQAHrs1wZHOKMtyURld4mcJ.png","bilibili":"/uA84wxiVlJJRbBkymIdKTw42zk8.png","carousel":"/mC98ktCFvsDb5vrAOOhLozTVn71.png","mult":"/dY0PUuBx2KXhXl95DzDY5ZLMylr.png","tlum hd":"/sGROKSsIbgWOThPbFaxsjGr6eER.png","canal sur":"/yI3v9EhMP2Mt3tdIXuz6E8t1YN2.png","tvr 1 ":"/axE7fqLKR0oN9pC9HwrtcrTbjcm.png","ukraine ":"/jLFuGLkwOQHAekvU7CmXaBBj4JA.png","arte ":"/6UIpEURdjnmcJPwgTDRzVRuwADr.png","mango tv":"/lr8L36trGOi8iKYOQOhVtJ2uOKg.png","rt uk":"/eMZoX8lgiMv5kbxnRbnaeJ1rPg9.png","inter":"/fTwKj4hZMMGCFLHSglJOAKnvNH.png","star world india":"/cGR5NFbkIsJayT8lcvJyiQmZq3a.png","fox premium series":"/drQKL4J2mjlXFdYkky4NT9jzsFO.png","fx brasil":"/sFK0I7f90UY5o6BDC1CLhJXKs6R.png","zvezda ":"/3nVHeDt2xktjuqyIC7VXWOEOOgH.png","kanal 4":"/iCTD7rkLiUlDhSdT0W56LxtWY3o.png","fox latin america":"/mGIwo5uKaPMK4sRNwSwRl9nmRtd.png","fdf":"/p9guqIXM0MWzk2F7uGPvJU12ase.png","canal+ family":"/slQe62dRo5kCuiwz7oLVQAHN1hi.png","dplay":"/cllBOlqfzv9t6KpOmMcpanhxBLI.png","funk":"/9MozrFdzzDNo9AcpkN4cz3TkGrF.png","nolife":"/55cfTZPHKBf1pReaVG07kLsfnXn.png","be mad":"/wulMNvZi2CrdUx2USpfJNt7y7qW.png","line tv":"/eBK2WsrRlpmLpyoeR09I6fDRJie.png","hgtv canada":"/iQgW9a6kOgMbxCVYB97643ICVDn.png","osn":"/3SjwBFCLTOAlPmkp9lHbGaVLWfL.png","studio+":"/oRlKS6G0JJ7LLQUDfVgM7x1YCxk.png","fullscreen":"/9u8319x0HeSCxWyzko8KjNFgNhZ.png","facebook live":"/ausOAbylt6Id43JF1q3rfeYw2ao.png","nick pakistan":"/ikZXxg6GnwpzqiZbRPhJGaZapqB.png","sab tv":"/3hNAuxQ7LWXfbkTlMptD7shp7UE.png","cbs all access":"/7d02Rw9EDMWba5yeM6EZqPydmCn.png","al-nahar one":"/j2DofV0EVjP2TWC8aGqPAAcBsnD.png","super écran":"/2y9dB6N3pq5efMRdtEDtSrUwcSY.png","rtl2":"/oG6mx3igu1POada9WinACUpN02o.png","tvi":"/sn36BiLSsKi3QcWvGQUn8KVfl0P.png","7mate":"/8AjZwKDE88I37Wf6OoOPJVsTPoP.png","lifestyle food":"/rww2vgf35bZ9a90GVCljJo8JUoh.png","astro warna":"/tQlbwFAnTwGuHR7pz9iS1rikKcp.png","astro prima":"/s2AFSINUQDX5NIKYkuUJhQ6Uaru.png","astro maya":"/hOC8CA7WyCDg0xvI1JqhAxbi9pb.png","blutv":"/aY0a4ZsUyG0zYKDE9H9I1eT4qdq.png","globonews":"/xlJCivVutt9N3GiXGVIMFTGUxGz.png","rts un":"/nJzBHOK2WkMlaEWz7vhE3lpDCW3.png","rtéjr":"/tk5BBwAt7oJrlZCNhXYAXooWt8.png","maxdome":"/W6znAbTNCBQUwyCwwxuqZUeAcz.png","al jazeera english":"/9nAXtejiDQYqkeIWWk5eulSo2c.png","bs asahi":"/9nilrJJG8NlmKykGZL6qbE1BBvK.png","hot8":"/j4twJk4F0EmQVzNa3KbgX4NPB5o.png","manhattan neighborhood network":"/hOg1wHvttsEOT8v7DxmA6nkzfw.png","fusion":"/q0OTdtI98gljdgwHHIdNW2aaJZz.png","crime & investigation network":"/vitUTPUae38gzMRl8aMVecN0Cme.png","hulu japan":"/5EbNwVlVEHGOkSJFw9cjhaHJOhY.png","ici artv":"/u6n4LTVDa19B73PZcEQAiLqL6CG.png","vrv":"/fe6aKemBSA4knkxTxPIxO8UAOhl.png","one 31":"/cxBpog9yHJTIclmGsojZC7tqwlH.png","évasion":"/rJ6xicSW61rop8ChUgI7r8vp52M.png","astro shuang xing":"/spr25hXf651DaXjTHoynIO4plMz.png","mediacorp channel 8":"/mgbUgCcgbpxzXD928ELSymL5JzO.png","sony pal":"/fOGv0UuTWkLxp4aOTw3s9C7T2Rs.png","suomitv":"/q78UuMAjpSIZnYMWo72KYJHbFm9.png","orf iii":"/alCTY3pXKHFPoPLgMaJrFirkhsu.png","ebs 1":"/vM4FN2WU2JU1mCiZw2BtqJ27zxR.png","dptv":"/8J6u2IEM9gPQrYhLfq9GGfXpswY.png","obbod":"/gEnWY6u3CxtY0HxecNK77Pi6vBz.png","hot vod young":"/g9I9S69LEwTOFJeSRF6NlF01Lt7.png","video pass":"/zSqGTh3kRtv3yeHRPJOk4BvBQew.png","rtv 1":"/z2rWC9f1T8J9O1MEHNXWmncCYFL.png","npr":"/jc6Wxu2us3rgsmbCJRLvfS1n53Y.png","hd1":"/sZvjj48224okQHs7HduRsNpikAx.png","nove":"/97Ztf6tKA78wgg5yZPnr1zrE7Bn.png","elisa viihde":"/oPC1XYp7nHUxEzJ5r7i1hdk6n8t.png","kyknet":"/vZOtg2kWd8s4v5vt2iqCExXQK9o.png","13th street":"/o9bWCO9zWVv9hBXTFmyOVFMyLU5.png","dsf":"/p5UKCbb0k7PNkD3nuOoKQiS11Sk.png","comédie+":"/qtIj2PTkOImRGPu7k2NdDKtTiKp.png","einsfestival":"/70h76nG3qP34HRKbvJyKM62tK2A.png","rtltvi":"/oyOihoeQw7wcMx59hNhVwOI0wyR.png","family jr.":"/zJn9ypM6cfI5APVVnpl0a8Bp4BU.png","sky sports f1":"/2Vd7UkFp6EEyLJFSMUqIsqQhJ0t.png","rajawali televisi":"/vxzYcVxYGgHdWMVrZTewxxcrntO.png","kidz":"/lHspOb8qSkK7P8UN02oOgXtSG6I.png","dove channel":"/vfTImdo7SUW6yJRM8XiKiNeajyx.png","ap1":"/dzfymvDFyoCfLE6Ot0I2YVAToa5.png","yle teema":"/lt1agd2pOlDmhaSmwSAklOxNZq4.png","mbc drama":"/zTxqKder2IIIUzAnYDmGqi8VJil.png","really":"/eNQpKWZ9fmN6YIuQTObFfbFIWVy.png","tagesschau24":"/7XPIFSf35QHP4TMEtNXtjVLTpJf.png","ewtn televisión":"/7rbRK6vILJFsQIIQGRNEFvNsv3y.png","fbs":"/suqJy99xiGr8PV7eQovUFRgquYT.png","ocs max":"/hqYpZX7DKht3HTXbdi5SSCNEPxF.png","odisea":"/lp1kyWPAjJTgUdqVKMaMWuzTE0I.png","blim":"/zavliTuAnVSaip9OxbsXTs1v8uN.png","real madrid tv":"/puHOYN9L20sxZXaifbQQJ0mgIOS.png","true4u":"/cGSND9e3N4A2LE1DMdMTUwCLoLA.png","kbs joy":"/8YOK3T6YmCcHi0rhb7nmBkUMJrq.png","jtbc2":"/bYcQHaavcJQV5XXc5LmiH5e4iSy.png","puhutv":"/q10rgiHNUffVdAs3neLZZmXUsca.png","on e":"/bMjDKMox1AgY8byELQIgrMdw4r9.png","alhayah ":"/eacM4a8Soc2FdgkBkmzH3j4au3u.png","apple music":"/nrHnK81jlSAA530PfZlU7t3p9wv.png","corrieredellosport.it":"/mZd26t06bKCSn7LZ05ezTanhqxc.png","tuttosport.com":"/gIhV1CB1aGQb32LNESiSQ27ehqS.png","nrk super":"/7wYa0aLdSPtTloukX4uyXKpsIVE.png","channel a":"/yZiuYgxiBGJAucKmcBIy7TnVkSv.png","al-nahar drama":"/sJwKdmChunUfVweZHYRqmAcCRrL.png","a plus":"/akshdZKWozy4kAgHLfdJMhg9gz4.png","gmm 25":"/ggKRyZIgrGhVM0fszfYWwzJIuio.png","kktv":"/a8E9RFxhWBDGfwPBKiyjDe8ZrXt.png","vrt nu":"/kMrSGkH1NbpfuRdADlOIXhVnUo4.png","rtl plus":"/ibXEpM48lnjfz6HNLtuAgyrXjNC.png","all 4":"/1yd6L2IUvuNmzvYYtd19rm9l7H0.png","ici explora":"/lRhRKVFzRQGeESBAETOZLcghtuM.png","erf 1":"/plqklbW4UTMcGBHEBKEP0oVCGDW.png","rtl gold":"/zuBvtzbEUWXRx19rZjQSonYO0pt.png","kabel 1 doku":"/o7zjpTAiTwvYSXeVpCjLPLlQ0IH.png","axn":"/AjR6Ug74xJYMhtpxGFusVGAHfWd.png","ufc fight pass":"/mDWJAHRHefTi5BQnq9EbvGsYQkM.png","tencent video":"/6Lfll43wYG2eyereOBjpYFRSGs4.png","stargate command":"/fPXvpCLOBpAkhjjsyXQLFazuAqL.png","ozonetv":"/dvRKuaOBydS9P73UqdEBhfX9L9L.png","canal viva":"/kWvptNESFDqic8JITEsmfhiajuE.png","planète+":"/7wJmmffmEUVrvypzWI3AfL5xuro.png","star maa":"/qszJZrnbUPtPPTeUSadt81cE1E7.png","red bull tv":"/oxpqVDcgjgyzuUlskVGtDjD7Sw8.png","arirangtv":"/z075mUlUUMe5WcEDA5wU09mtRsi.png","vtmkzoom":"/fHqpMM2uYdN5wg8ZCR43XXK1CwC.png","13e rue":"/e28DXTUjaK6SKCpJpmICQXllswx.png","myspace":"/fweyuLaPpCgJQIHd0XcMEsoQ2u9.png","canal vie":"/5QdYa6SxoITRGp4UtUzLtJc1VqH.png","tv setouchi":"/qi4L1ffRabF5LJqVimCaaUYpeSj.png","la red":"/qTgh2i6MbhUpzVvcEpaZWOn6dKU.png","tv 2 fri":"/otdpdzEUOp6WPo46TSfuJuRgD9t.png","paramount network":"/4knr4ozp2IQrA3SMQlLSYKcM3ML.png","viafree":"/e6QNxf1eUhD1V2IRXOAMbG2dDfH.png","discovery channel":"/8qkdZlbrTSVfkJ73DjOBrwYtMSC.png","unis.tv":"/dWmz39wEMoREif2ncajtcukKUQ7.png","plug rtl":"/r8Meoc299hN06gDaplv1aJWzJkn.png","blackpills":"/aXVvr4Aw9JBj2SWrEjb1tJaHYPC.png","tv vest":"/8ZzYfUSyC6O5S4p1qG1Ha5fG9wS.png","techtv":"/pNE1La0x9MZJAFe8Z2QTEMG1wmq.png","g4techtv":"/fmHYPuOlLRah8sp7ZYUNg2LqsMF.png","the new tnn":"/g3qXB4IDKL8sIk9yDVeKlsfLeFT.png","casa":"/a0ByNgmzVO3NpC0P7gY5xntZo3J.png","dekkoo":"/qD8575BVoagIUosW3JQo25HYShP.png","altbalaji":"/zZ8gquIrrBvDGyMMcsSgArRuzyh.png","mtv latin america":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","orf 2":"/yMnlNdwOHo3YrqPFXVYgvz3pimN.png","the great courses":"/p8bhSRCzDu60XrsQXjWfoArbgqn.png","canal algérie":"/ed0NjMKYAG3SPGdNJjaJEBmFqs7.png","etb2":"/u2g0SE1ZpEzrJv9wueKAHEbfrTt.png","universal kids":"/p7CrTUDgneTfikaSP6hAlFcbmqF.png","dtv":"/4pgrhONIKQAu0V11Mt4qECC3NO3.png","la sept":"/7LE9NhjHzyQ4tOjgdKAn5eBZerk.png","hoichoi":"/qVqRSAy79VGjfN4qyeypuS5vLX1.png","#0":"/7odcr2uwJNhanhEaFOnITogxmRX.png","rtp play":"/mB5QFbQhbJh4haHFP50TaDjhbQ1.png","fox españa":"/mGIwo5uKaPMK4sRNwSwRl9nmRtd.png","viutv":"/mmQOH5hoPd9ZieQPr5FFsjAMgD8.png","ard-alpha":"/plZ5IdyUmR4130lzno1D71NtwLt.png","dr ultra":"/udkodZN7FY6iXsYQjPDJwj3ex7H.png","bnnvara":"/tiBiiquRvGhxXteossLAWQkaFA1.png","tlc go":"/wjQaV8ijywhBHMjjNTTiwUBtw52.png","wpix":"/uTdbKD11HIWuUv7chni1TGiebEk.png","télétoon+":"/nLFQkHAhQXlhLGRXJTbuULYJWuv.png","yorin":"/vTPFIDfCy9dO0j0nORq8g2Qv08W.png","channel nine":"/azP1gQxvW4ssDevqHgCvN6mCeaH.png","irib tv2":"/uMqUppxmwSGDnOS8PROETr8wNcE.png","4fun.tv":"/kB3LXsRMnzy2CDg3TzXA753Uhxj.png","ortf télévision 2":"/nYx1n3XorcxbzSdhFc81pC64lQT.png","bangladesh television":"/lI6c4QsJrfqFA1wTIrQtigM7jF.png","pick":"/sVVgQc89KYaDkFbewtpxg0uiiZk.png","t+e":"/opfqVBIJvLWy3QHog2wo3MKWqpS.png","iflix":"/ysdz7EX24pmSFlLzF224rvBVhrz.png","astro oasis":"/nkObiKyTKiQV1SbIw7AGTAL3vUR.png","6ter":"/oKO8f2L6QRNu7HpeyDr0SfgabfK.png","mtv japan":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","kanal 1":"/ovdg7mo5neFJK4bTkh4Q0JFfd5X.png","universal channel":"/hbi1JluYG87C0oSAvIYxSgl1YlN.png","dc universe":"/eOL4PkiC0zkDpxKFQhBnmCtwx5p.png","dom kino":"/wOuhUtvKkyDxzFWPFfLdPsdoM0B.png","tv centre":"/gOua3AtNAQg4PWbTRKTpwWLfeIN.png","talpa":"/kejyjdzZg04SMRkRT6w8piOmXOd.png","xtvn":"/hcXvuYIsKJHhqd7Wzh4rmOBNyDk.png","fearless":"/ogaCadUI1W8kItFpjaN6tvtnZj.png","showmax":"/72uE6rBXSuth2k36cGsvIYxm5sp.png","o channel":"/u0605fwa355v0MaeyP0HgvXIdNI.png","toute l'histoire":"/mVOvssvqKTATcfiW2dkHAcMASsA.png","vidi space":"/dM96XxgerPiGJHlhnXi9pprnSU9.png","tv2000":"/tbEkWpDqFqHGlu7CYyfbjomskMn.png","ici rdi":"/wUMDQIp1KlyiFwKk7gXlw8uMJw6.png","mtv nederland":"/e9GMyvaguUc36ktS7iSFYP0WLKa.png","rsi la1":"/biCq8cxwDErIA6of5Mi1DHRv9U7.png","hallmark movies & mysteries":"/kWQZeBIXk9tPoct8PiBrUsWZdYx.png","dk4":"/eSMIKk4bpKR4g2BobUmnzHT80GS.png","nhk bs premium":"/jP2RyVsBTv9mEMGjVEWlY72dJha.png","canal famille":"/2UbgDDv9cHAdGrznUWEi62M3RTi.png","tqs":"/xJpMfVYkLh9SfduR6r5cWWDSBrj.png","razer":"/eEJhNL65DYewmplr4LWHhaiCqYw.png","nickelodeon india":"/ikZXxg6GnwpzqiZbRPhJGaZapqB.png","fox footy":"/ydzHHnyZsC60RViiNAvMe3v5la4.png","fox sports 1":"/xAih9wNDjqvDmX9O9BA1bekRHQr.png","country music channel":"/reGaYh8WHArHeTndzA4ikkkNByt.png","fox brasil":"/mGIwo5uKaPMK4sRNwSwRl9nmRtd.png","fox business network":"/7llt1tSy6CNazFNUuWSNvssfWI4.png","rtm2":"/jlBKRggeBhdxvVW39g0iCqRxdOH.png","nou":"/vqA3Tlc2rjS4ZnpllDYt9XpN5Mj.png","nhk":"/14FlBTfMQNlHJDKEdjxfUyn6PrR.png","curiositystream":"/pO2jjhCt7UeCSqDJJ4O1AtunmxE.png","pbs digital studios":"/ah3lNfMwcr1YOV9NZuCFEhwdrLf.png","astro vaanavil":"/zSoyLUFwe5n13qG3aIphWEnKXaG.png","htv9":"/9nWl4V9190sE76KwIR5BpHIikHb.png","sundance now":"/tKitog3eIbbdLMnWNZg75ErhJr9.png","facebook watch":"/rtn9QlZo54aW04pBVbtDqNfO0Iq.png","atv home":"/toGJnf4MniOfRwl8ki6nGm5U9ov.png","sbs fune":"/ue22MrGpagp8u0dQ1bRemFSCI0e.png","rts deux":"/8G3g6cWhxdqCQeyvJHpUVZrZtqh.png","čt2":"/mSGMeLPTTCKKB9DVMJoFFzWNUqd.png","rtbf.be":"/rWYlPrkpIK1ZvDhpYTc03umbZYb.png","la deux":"/tSheAzX1u6cVVvzxaObx8gyblHV.png","jednotka":"/6bqAV4y12zSroTITdmPO0vYCpda.png","crime + investigation":"/vitUTPUae38gzMRl8aMVecN0Cme.png","tv rain ":"/dEv6BcTZWHCBXCJZiVTBQQGUM2E.png","brazzers tv":"/axTJr1j7O9xV8RhqeCM8ESPNJTI.png","noovo.ca":"/b1cd3PHzrtwrXEvkOZoHtqvji7L.png","npo 2":"/4GaXwPcTDWaZ83a9hOt2fTgh1kQ.png","tf6":"/hKHAEkO7gW3UA9VSVI7z13eN6Yn.png","lotus play":"/uaNCh8fyN14DsYYGBTkAjz6ZgQ5.png","w.":"/eIWj7cmwJf41P8lIbqZY4sfZiGr.png","v live":"/xlc6O9RcjItzvzYtxl6tCYMol1t.png","keshet 12":"/guJs28rlEaZTKllD5J1qD7WRQWP.png","paramount comedy 1":"/KbcFmyKSpMDMIsswtQzi7aVNZt.png","shanghai television":"/mutdWEoQEtand10DBc19dbI6hWG.png","motortrend":"/9JkfbzNXtoXPQkVaZf0LqHPatle.png","jetix":"/et3ZqCUvzqGVFIs6OiPlw2rxRbc.png","fox kids":"/6SGZqBYHU6zpY3UfDvD09prOmM4.png","tfx":"/mTljUaXNXAlVSD8aGcrlQPpmdF3.png","brat":"/8zD7H0aJH9YEISk1OyFuLPpFu91.png","viasat3":"/w6MMMIa10yZowA18lLMKMfMZ5d4.png","kbs drama":"/dMqfeM6UTlgXoMcOAxnneZruCDe.png","bsn":"/34sNEcsgcTAuDidRMrgxdfNyVjL.png","tys":"/b4Ivxqz6UY0EogjYc09Y22ctC6F.png","hot entertainment":"/crZefYhlhwf4q1bp6qzDUPlotIi.png","cctv-14":"/pb8Fon4VjQ7BpGcthzjOqBIzyfW.png","hrt 1":"/i1rGoIBvxpP9wNYrjsELctDfCib.png","hrt 2":"/yToiGhuIZfIbcnrgxFBjSFTiYpZ.png","uktv style":"/5pm09nDmkt0Yv2eIJJIHaKUJnW0.png","goltv":"/2yFWfYPux3l6WdDDvqNuo4cBzo1.png","ecuavisa":"/5Bts3XGqQkibLfFv26TqeDBSahq.png","etb 1":"/vVZ6oBrw4cxGEBv6pmKnwVPcpt.png","ert1":"/NYry3kLLITgJptE1pkeU52jRZl.png","tochigi tv":"/2v82HpzoKRveJEJcGHkeTcktMRM.png","tvtropolis":"/hZ4UqGsabYK356avLp8rrvRxny5.png","discovery home":"/nVAkhCXG3I4W4Nk5kGhA57BFSWa.png","uktv history":"/1oGs72mYB4gp10gmIMZeG3Sb5Fd.png","américa tv":"/rLnMBF8MVSeQr975Btb5zLQjP4a.png","universo":"/e2uRuY5VobEg67VLfow0Cq765o5.png","jtbc4":"/8ik7JYVYjKH6ybX0DGKB9Gbj9j6.png","abc nyheter":"/oCxb2Gwu3niYnbc5hNiaTtwg72c.png","canal q":"/bXJlpIwmXjWmTFDmQKWKFZpOyXm.png","start":"/oOin3L9AhYzQzKL1qDrYNbePzKE.png","3net":"/3NWCn4m29tjInw1QcwiJaI8b3XX.png","belgische radio en televisie":"/lpjHtqZkBZflKjCe33nHXKF7YNV.png","milkshake!":"/wsFJkUNuvuxd8s3XYDSDxh4HDOw.png","mbc m":"/5u9vcoUlsBo2M3rxjOnfNhXXB2E.png","fifth channel":"/sWLhRZyDAcaFlrNY8QKHJT0MRac.png","perets":"/xelYsoekbDNZ8Bh6VEWwzSa6cXj.png","che":"/Ls0C5phLTXp1dYpHlXRm9gRiRE.png","360°":"/bca3aMuF0v3hgRFKWhZ3qcsDUsM.png","directv now":"/6Gsz4JrWMVvx5OPepEO4Bc5zPsn.png","tiji":"/bSSdpKi6hPwf06pNu5TIUymope0.png","3+":"/lCkMbSafIjIAj4FYGilRLM765Li.png","cbs reality":"/nXC4er1ccpuWVrI2cQNHjuQqAF2.png","voot":"/l6RWXnmlxVgMsu2G3Y938DQszee.png","foxtelecolombia":"/qQGutAt6YQYRAwWc9ZxHQe3b00e.png","russian detective":"/kXb9FRf9pRInsyFCuXSeeQk8pfk.png","infomix":"/jhWfbeJtP992xsG5MbeBigXtDpL.png","art hekayat":"/9fH1kXMwRhXciiEyF7fFGX7o2cf.png","art hekayat kaman":"/At6Y06E0eKvIsMACfuGZVuy0c9J.png","apple tv+":"/4KAy34EHvRM25Ih8wb82AuGU7zJ.png","mbc 4":"/zT01qgrQAqmLRjyPZ3otBhaYNMQ.png","dazn":"/kGipWQCpZcafdYmF0NICQmKw0uQ.png","srf zwei":"/3OcAkffT1ZJAkWPQZKTDdKp8wmC.png","super3":"/43vUOZkb5nBAYvYPj7haOeczoqU.png","genius kitchen":"/2kPJ4CjpyZqDvZYwYnb3lrb0etz.png","be tv":"/fAZfGwB4j4fTxZu44XvxUEDcwmU.png","smithsonian earth":"/9dgMIZKjZWCWxDkqj3KX8KFxRoq.png","asianet":"/5tYd7YS72hn3urGQ51WfSiLjRTA.png","neox":"/2OOKfHMOMqN4l2QU5WLRjwp47iz.png","colors kannada":"/bt7SKpvQmDxnqKnJIhPhxOCPUCf.png","colors super":"/lU82n8N9gwTc3AhPOpXrssvzODu.png","colors marathi":"/wjGZg6wjVs2XIz6b0ihbai9yM3d.png","colors bangla":"/5Bj8Mtk5rQnBwcKKb1lWSkeqzTd.png","tv-6":"/6ErJUdDHOHD0AE8Ae2tdmPkOhTO.png","oksusu":"/xIHkp7frQMMTlXKEAUtDQUZgDa1.png","teletica":"/rd6CM8f887MW9MMkRyuuKIpMH6K.png","odyssey network":"/wyfqylHYxhnTMXVZTcpdZrvtpL8.png","zee5":"/cakduIXxOWnOasbKSMZ6Xvw5REG.png","hbo family":"/asKFyxwgYp8WluQkWhGFYj6IYYd.png","yle areena":"/vxp8LTTXwGFrzNM7zSgzl4DfSad.png","rivit tv":"/cCyMbuRim1x6WmnbYgCFn2AVm7i.png","energy":"/rTqQRXaYFtJRnRetbswziCvmn8M.png","azteca 7":"/hRxYQTVSCRh4uCs3Wk4AisHOKUI.png","anime zone":"/vmlXZtGw76HkFrXR5UqvEklpCy4.png","česká televize":"/qnFEMaWjBM3kC9JmRWEhQf5W6EX.png","ntv mir":"/oPqmdzTb2VmZdpjit8HV4bvbIT7.png","7tv":"/7FgVHt1k6lEQDMkvrCVvDbswjqn.png","cbs.com":"/fpkDVuVhNCDDh1JX5ikWGcyBx9Y.png","passionflix":"/zXeUVqLEoCFeiUHb3cDSrNWz0a.png","vt4":"/fueFFOI4BXl1OMiISPMRLxcdbn8.png","q2":"/rUFW6o9HHbi8la6s1MPEEKpVS87.png","crypt tv":"/xFpavPCmIe8pe41cSbIpxNtbQj8.png","discovery kids (br)":"/8woBOtitimA6diobq7sxCIwj37G.png","omni":"/lGE7lnRo1zmxbdo8hCFxhr5WuJU.png","joodse omroep":"/qN0PALF8sXGHS42dhTmr2BS1oHb.png","gulli":"/4b8ZM73YKqFCJLbQB70Pyw5wQCK.png","onf/nfb":"/dPdaLDtWPiuJzXP1CuNUxxV0DSU.png","sony liv":"/gDmNY44E7NhRqJ9sosYf17oAC8X.png","fox action movies":"/zltsrFgk824Oe4oWNmvKyya2EtB.png","jewelry television":"/e9JDcchf0AKjBOXnkClvizhm8Ba.png","fight network":"/7Ht7PCwpRkYyoOOxVlQPJUa0QFl.png","hkstv":"/Ar1dX8uhWORSAV6vkKVQM1EoaLb.png","rmc sport":"/q38SfscVUlRaXW1l6w0G7vkdBlG.png","cctv-5":"/zYZ87Aa4549mSAzanVZqgcmgVOU.png","mono29":"/43zGTXOvLAIqIfuJYHhMUFxG7i8.png","n24":"/1dmD88GE8Y5YRtVdhy9yI3pxovK.png","massengeschmack.tv":"/wTYO3w8PawspS95VYwsHcajmI0t.png","sky atlantic ":"/iVij5p9Mxfoj7mOmcLvVlKgIx9p.png","hello sunshine":"/b94sYzp4YUqi3DqIUnWnfrmxlN.png","contar":"/bLcnvFY4lGJYoWWEc2qpAAkgewp.png","canal 22":"/hrTqBjGeXnoAyPh1HUbaUc60Raw.png","ondirecttv":"/uPNX6Cikdj4ES3TkyOKA9yedDxP.png","canal fox":"/1DSpHrWyOORkL9N2QHX7Adt31mQ.png","sky witness":"/bsGPlGAxaDUas40y52i5IsWMOPV.png","discovery channel ":"/vWHt63dgArLtqnsSTu744G6g3sS.png","kvcw":"/6NO3G5vuhkewHTuUAoZpjTxcPFh.png","hooq":"/s8QZ9FywliUa3FQdjDGU2hopcfi.png","acorn tv":"/zwiN71q3FqfVGdCfgDwESUBIfmO.png","umc":"/4nGQWWLyDbQpJvUbXYlZKHFjUFP.png","spiegel geschichte":"/3Urhc0dBh4jKL8InhwsjY2xRL3E.png","studio 4":"/eUwMEnQJlXBNBXydcsBUJSqKVuN.png","yes tv":"/o36tNm5Scu1mOltjUxUdSbKmNCl.png","ruutu":"/ieV9u8Q0WqTvlRcR3TTceA1X2r5.png","style network":"/hmm0xFl7nydC8VR7YdTQ0TXowQ6.png","eros now":"/9JQSlUKzAu1nQzCnCDWz5x9dw4R.png","aj+ arabi":"/qatnFtgbatXo5TqY2P7Sx5y6wvK.png","rds info":"/dqHb8f2Fdi5fpzysHIKh5SCRiw9.png","chukyo tv":"/KaIK93kJFD8WKH451owMdmNOSz.png","rnb":"/kwC7bfbGknKuL7uxKahk6paamlp.png","ustream":"/pRc6dPI8TIaZ61bF24bh6Zwk6QS.png","qatar tv":"/5SM3cwPsh5uqb3YKAQWVzn2FGcz.png","sat.1 gold":"/wYrKXhcChgIqfDRONnANmOoFBm.png","nps":"/bbHC6qV98IoKn3veSx8wDiOjtCi.png","nos":"/982W7v4h7zS9yO4VZIjHw1ORCl.png","disney+":"/PQxvkeK8cTtD7vjataBsNpjbJ5.png","focus":"/zO8gBLL20TbV0Jd86K7WrMQOGLf.png","rang":"/A04tNYZI1mi0jxFCsSlKrUPmGeQ.png","kakao tv":"/uZpVywEEp1FaMAWZKQD0ZSa9nel.png","freesports":"/1xCjgcYsJ4DaD3NHzDl5bNuay05.png","sky travel":"/m0oaYs13Y3K2vsqoxcWYjBBpDyM.png","tro":"/4sPm8L8wX1gp3iBXqU5bhGqdYvQ.png","fod":"/rD6NQ5JxOxFG6533TAONS2ZwxUi.png","gusto":"/xhoPVvSmHRm1984Sd8GWmEQ6YQa.png","kbs w":"/ouocJy6EukDqdAIS5tqER5uzmIX.png","man-ga":"/v8WRVyDAQ7xA7Lt7jTaz5AFpH3z.png","tvn 7":"/yaevuAiWmYoYyoa9N2uYyDVRPtz.png","love nature":"/sQzxQ1GOyNyxyaznugkicB1JNDO.png","n-tv":"/aW9VAddPX7Z1GNCOAXzXtaFsYSa.png","abcd":"/qFL0BoydPB60mO22edlV3RfhLUT.png","deejay tv":"/xkRLUdy3thCCST8gkVwdJnP4Cfm.png","snapchat":"/yQcvQqcOWxprmIuzjnQEZfKjj0G.png","rocket beans tv":"/iH3nusZNkYn8lXPCZHKCS4pXrlc.png","canal savoir":"/z3JFzSXjwgzGuCCynk2nifjQ5qQ.png","dkiss":"/70ezozaVCQmchziAM8HgBFmT9Qp.png","wow presents plus":"/fw3Qk2pTRhkCSrIBq4i1q6xI8Ae.png","rocketjump":"/7w2U3oxMYybsd6lBtcJEiT3zcII.png","eurêka !":"/uoYFG9jVdyA7OctqW1WZdSE3pnX.png","netvideo":"/kNTluzyx84RrGizI5zh03lwADmD.png","gyao!":"/e4Zb74V62MpQRgtgZnBeGEt4UE9.png","hungama":"/znFJryX0SQflQHmJcgbWkuvWN5N.png","tlc (hu)":"/i3Qh6pjy2DZqxAXcuOGXNTyHl2v.png","toei tokusatsu fan club":"/8jJMPoqXIBdcWKlGFTrkGi0Zyj2.png","rtl+":"/2joN5UqxLRyrE8JJJUnbcvqU4hm.png","squat":"/1Cb4mAfBLfacI1aaraod1PGS2fm.png","kanal 6":"/2IbmlZYWPDCAvSXLrYxKsFfMwwx.png","hallmark movies now":"/zjgwf8ZDrMf7zxhe8WdwzPFKnjc.png","abc kids":"/efIOJEqy89zWpK4fDlOXwXtTbkE.png","sjónvarp símans":"/dhHde76oIEfmqjAuvlkxlGKWYGK.png","tnt comedy":"/w0ZtygaHGHBxLmdS2ZqNDDYyb0w.png","premier":"/xmp2uRpL7Us327irpYhkPtHhLLK.png","hub vv drama":"/dlSncZ9PmlvCTGOC56hX05LdQ8G.png","gyeongin tv":"/bjdegNjZyWFcCIAxyA13o2FkrzL.png","vtv ":"/rqLpVk7zzDFUT0BFOIEVbC6XvEP.png","tv3 latvia":"/uxOAZGDIoP5ZRGSw9QX9TxNpLgk.png","pursuit channel":"/gD9Q0OkWa2R9fc559JNCLIy0R8f.png","spectrum":"/ta0tkJ6VUugXwQzdea6T7jzUYkI.png","the fantasy network":"/xlRy985kuvtyLXurGkudazmgYYw.png","safari tv":"/1qRHeqcNJQzvzdaeAh2NBahs0zk.png","yoopa":"/5TMxGA733YHkPFXIA8uxs5VxN2Z.png","makeful":"/44K8Iq6d382bQvP15bgGoRZ3bjO.png","top channel ":"/8V28tzPL9o6w1cc98IuFKhFezZ3.png","food network polska":"/jhxxYJx97vqPiGL6rZHDVixJpfN.png","ullu":"/plFwH8j6fGrDE2wJ5rYyqJ2046N.png","zeste":"/OyDOzuN9GIlPfCZmcVQA9Kka3L.png","open beyond tv":"/qH5M9dRWAwpPJ34PehcOudqh2hq.png","family gekijo":"/uYiTfGXmZnCzGNCB59QcaZmnffT.png","imdb freedive":"/AqLQUhGYbgIalivsos4IeM3RIPR.png","télésud":"/2YD9FBzTO62sc0ev9ESPBJV59R7.png","tv5monde":"/b6KDy3HbsO4RpnDPtHDSfsRq90c.png","russia-kultura":"/jN9V5mPoi7nXNr2y97v9vJXLIj.png","tvnow":"/fXCqxsW0QhZTTfL5YxDuDeKNvxJ.png","nrk p3":"/3bgRacRlAN0S6xUihXVzpwsVvNe.png","teleuv":"/zxwuX0eT489Od5KkPGIV9nScR6g.png","now 26":"/zYJkN0FO4WclBYu6GWWB9fgeHJm.png","workpoint tv":"/luK3LME1iDphfp4r7Te00PIi2AH.png","super tv2":"/9Z6XVfyFRFneRhrIPUfX9QZjGHz.png","shudder":"/Ap2jtXPy3QlLMi1GYLtasq7VoN3.png","matv":"/iZepWlKX8Pj0MYjfxyF4EHQcLez.png","tvi24":"/p0LHKVYtJaPi0SyAS34ubx0eTtC.png","mx player":"/xKMlXKggJ1mTsfC5OSnlBKuFccO.png","bon appétit":"/8crroBYIfllpwrM2Fsuce8XZe2k.png","kan 11":"/hcG3NWwfOP7lW9tgxcWwDovEdT1.png","mtmad":"/zH1XEtQleT7o6cnfBmePj0xiJBY.png","animax korea":"/aA74agiTaAoFrGmOfSDyBlpZocE.png","aniplus":"/36j1vbkw3OvemkkXaOmlKzoXvbu.png","viu":"/yEv7NZDYYxWak9cytEKzjO4Te1L.png","cbc gem":"/m4nAbyBNzPHitupGll2n9WR5kp8.png","france tv slash":"/6MNsYgexPfbWm7pxfosNqltwVDa.png","france ô":"/y6b6Vc4Jwn4zHrwyYa99I4ODUCc.png","comedy central (au)":"/waWpWvfVRCCFUt295SEMkebc0ai.png","playhouse disney":"/4v1r0aXZkoTTIi8MJcNrvTaIG0g.png","machinima":"/as9uQ9NyarUFgrM3NdoYrg40ZOI.png","clan":"/lVYNNXEJhUAoCxBl0cJ9KvsIjRs.png","mall.tv":"/6YxXJOhFnPkzSDDpJBR7UdQ452A.png","imdb":"/pN6bGlicIXxGhnBF3SLFpVpmcFs.png","azərbaycan televiziyası":"/6Fq1RN4322VfSLrVRZqbt80jp9i.png","mewatch":"/p0kcc0CINYJIKD3hDkaW1vejCAg.png","idnes.tv":"/buZupHGVRcmtpa5j6mvnJKzOhhj.png","iwant":"/C9LDkqA2vosa6ibxue9gZrCaQr.png","claro video":"/wDW3ph5cEpQSNpcVZAx5EZm81wf.png","friday!":"/bFrRqO2SCc8UXXpraOfqSgsbVQk.png","metv":"/qrqFyJGAxOJvKXP2y2dQss5XDkW.png","mbc 2":"/dTnrqi9U571MDkN5PQB1KW3em10.png","otv":"/qQGOqPmNuhKUgWHsVulcvU1rP2z.png","env":"/8XxETYoMnfidCmegobHPvKV8xD.png","planète+ a&e":"/h8WAnO9OIO0k2hLyKxTbXplYFUz.png","metro":"/mfeKu8D3mrR5efzkZ0Hq70ww5kO.png","bell fibe tv1":"/xJuu166ou5sK95UK2zzMkTkN6Jf.png","estrella tv":"/iGw7s1jiRcWggyURxSHfv2DgIIE.png","tvn style":"/bd7eZpipCRGTjLtbQeYzlo93h4s.png","canal+ discovery":"/uAfVBVVmDQIEVRGZQGzb0X3X5hX.png","polsat play":"/6hJkIbD5xRfNMvHbluo4zKmVUJR.png","drink tv":"/mU3bZsaS8bX08azWJJIQFCDRcch.png","ttv":"/jyl5bWGbhSJ3ZnMcvZAJwUs5chp.png","señal colombia":"/w0rERIXkvfI01ey6kDv0H3QQTWt.png","rai yoyo":"/6tIBzDghJkH9hFntmMKYevW04cK.png","quibi":"/vgrbe5rHvK28Crzb5Djl2KbdogK.png","kanal 7":"/j5sCHmg2vY1sUmgOftAVr7HsuHa.png","bioscope":"/jy8ZINiQHxbLCHatbnxxmD23L5T.png","amrita tv":"/6dhn5HQprA0S3xDvXZWW1MPCOBU.png","lcn":"/6Oz6gcki6qtF9ZzhkBHTpdaS0M6.png","nippon news network":"/m8ABeozh6TciFlSLpYOaK0vZlWs.png","sari-sari channel":"/wKwaz7ToYijKepNGUl7SlQ6bnYt.png","cctv-10":"/ytV0qzKx3o5sdtM0tqLXBWEugEb.png","canal 1":"/dVoNhpCtTKW1Tr7sxngUx9bshys.png","o tvn":"/9amnWEOzoOXVe0CBw1Yz0M7CFOL.png","zeus network":"/8BVAYP3Y61LvjNZr9mcIr1IBSoH.png","joyn":"/2OWbACUYTojW3CSzbEuPicnAabp.png","sony espn":"/4JjhUXUKpnk7ALQJe5nPbFdn5Tf.png","hum sitaray":"/cqqwSxneFMDBcqjBnJ3OfKstvNH.png","xee":"/2LUK4SQdjmQ6rTnQyQzbhT9evh3.png","trece":"/fh32Yocc1650C20U9KNudtxIssj.png","trt 2":"/axA7x7TBJgN5WHjmGoEmQorOq8u.png","hbo max":"/xbYyhmzn6oq3RoV6MT03ZUMMo7L.png","itv encore":"/ucMo8oAZCwmn5IFjUV9yDnWpC2O.png","100 tv":"/xWb0SVMUndHG3UQCrMOFt3aTiG1.png","foro tv":"/oX35kX14EpjkEluiYE28FF3drE0.png","tv hokkaido":"/g1jerEP7O2rIYd83AaLKXeZlbpI.png","build series":"/ZJ7pobVIemTKkpRPgDJDLBGCau.png","zee zindagi":"/8DNSIug88tDYzxWuNBQwbAt6Sw8.png","viva":"/mNbbxQWaf78nVPPXiAOzf5MuJfo.png","bs4":"/naTpOY8AjRtgBw0JXafrhAD8ZBT.png","azul televisión":"/f9LUy0pcsI3DfEWc28wgHs7NBEv.png","pluto tv":"/6xI75dFULiEks0Dqm3Uag7CiC29.png","namava":"/uLOLNOsN5xMvbB6ppk4Dax7uzhS.png","gagaoolala":"/7pXbP8D3T3BfXKyJpbalc96lFll.png","animax asia":"/gNsvkmJY7QzRQ7AZ0QK9PeONIm2.png","canalplay":"/ij9WCzOHq8oPo1nHnIISqdkFcPo.png","la cinq":"/vZDDmxWjogmw3sdpiTQhaiZdOmW.png","ab1":"/9uwYyKu45dv5DyZEuEp2JXzy6Cx.png","ab4":"/kB986fmXXXfNtpxJ7fbIfd5JmKs.png","bbc scotland":"/pkei1FCLR4Eox16BrN6sGL5FEfL.png","dr ramasjang":"/umufIzcQu8rOaxtPfCNEAyhFsTg.png","amarin tv":"/x7mp7VgOFS1LqFvwZJ5OXcB8xLe.png","prosieben maxx":"/eQPoTcjYtZocXyv1RFFWZJ3JKZ9.png","pantaya":"/ytTHs0Mw26jCFQtRUqdajqR5F13.png","globoplay":"/v4ihAGQyPCteVnLVrY3QuS0Gij5.png","cine.ar":"/cLd8MF4WjSNENPYVHTPbfEfWRXH.png","investigation":"/ewPhtyNWEN4Jl6kgp42knjAxRxK.png","azteca uno":"/yJyGhrAaFdmOHjiSjinNjIcErHs.png","ami-tv":"/hEdPOGY7TwSRZqvsEswM6BzhzfS.png","funnyordie.com":"/sBzU4PjJ8vH9YGUbfFnXs0sDHuM.png","astro ceria":"/iY099ZpmP1j5t9QkE2Q3bbBcsHT.png","jstv":"/nhVwbUQM3WIbZdf2Px6AjN1m981.png","tps jeunesse":"/8XnIxN8hFMCjfwssg6HM88Wh1g9.png","vudu":"/xsiFrVU7PirDYY0av8SiyswYzLf.png","toonami":"/5BHAWTdsmpCcgNQxUkOATOn6iNV.png","bet+":"/vEBCYgIAVklR4lg0ev9bASLzE6h.png","redlight tv":"/mnXLCetNP9oEZx1KnvkL7etj0o0.png","peacock":"/gIAcGTjKKr0KOHL5s4O36roJ8p7.png","wavve":"/5x28VbYCOuLfMRePMDOcax94SD9.png","pts taigi":"/3mRQw6lQrZIaOu8aYR1VAUMjULk.png","stuff.co.nz":"/qx7huXKL5kYg1dXuDxcOA7BXFZO.png","svt play":"/xtXMBjBC6YhQzODw0XWERsHvhdz.png","insight tv":"/cysCdp10yByvUrvRoJxNUtdMFhr.png","čt art":"/pbZg2N5BVb2Hc5cpJIYjbuqWCDj.png","čt :d":"/jr6QJwDKiEV2flOJnv2bkyfIhdn.png","televize seznam":"/ePO2Wcv5B3zw5eJgUxNp0CJHpIf.png","čt24":"/27GU3PdUPXwsX5TqoGKCraPJj6T.png","hakka tv":"/lanjDqaaJhNFjHLLqBb691P6taR.png","prima zoom":"/gW4dPB7TFHP1AGnL9bvhQnRWaj5.png","universal tv":"/bKzvRKx4kTWdJLl3trEc3p7cldt.png","hikari tv":"/1hWkGw1Srw74dFzIYDgssn6OoR6.png","hikari tv channel+":"/9Dn3FlAlZooCFRk9Fi4ErgGJqxU.png","سورية دراما":"/iTTCHsQr9flXKcvyDTxZ4cbHept.png","prima cool":"/erohPAehVomIV3pglLuDquAQsCo.png","prima love":"/753SEOKvGzRE18mfuCz0cr8LStW.png","çufo (al)":"/4EvKLwhdagu2KfhicZt2KbkOpu.png","הופ!":"/a1TGWWQUFBNdqTV1XKpa6GGkJJO.png","first channel":"/uGVAdCWl1nOustsOVGxNBBJZJHz.png","腾讯视频":"/kiDJEB9eyV0syoyF51zjM4ySjpI.png","hallmark drama":"/m9mXUR2XTFp4jTbkQNAQTUnbmKG.png","tfo":"/8FWZNgPWEazdwA54aul7bKOvFnq.png","الشرقية":"/rSiJGtW34JFVrXLgI8zAJRR5zCa.png","rai storia":"/7ypIuH80IDEZwScONIjrBqihXVU.png","bayam":"/nykmIgHsU6aQrmuNJc0lSxzz2qz.png","virgin media one":"/pPfZlk1P3zfNyIMginkstYPn9wC.png","raiplay":"/xuijJ556OSE9xqw9C6Y8nf3liKP.png","comic-con hq":"/5AbiaYEKlsY0qFjWsdC7qxdSsFQ.png"," 10 play":"/4Z1e4FlcFhak6BoKE13EckL8fmF.png","bs tv tokyo":"/k7YLyfQSI9cnspw5zBsAsrppUjb.png","dumpert":"/mglYZoTvCPemKgrpRtJXney78x0.png","junior tv":"/pZ22U6rIUivAlqPEWr8kcij70BG.png","rds":"/fvLrKSvF9uhQeCFKJKhUCkyPXmU.png","tnt españa":"/kCM7MNC49D5Z0BVaT9FfnGDyUvi.png","latvijas televizija":"/4cAeVQcPBxttZC9Y9FQItgFKBXU.png","novyi kanal":"/5YOCVGFdB48wS47TFB5HhFEKTwA.png","la trois":"/dRvulHecDfIgJNBA4Dyltcpaqm5.png","svt barn":"/ck9dgW7WZTTYmcTsXuR2MIzihtv.png","alibi":"/2rYX5QwGnFDJtkLoDwn1bAJNLsV.png","diyanet tv":"/ir108f6LYvYMaEfGJqVVva0xbiR.png","cottage life":"/dfZGwt6pF1IczG4nWIOM3jXB5Ga.png","la5":"/ifDMYB7mJ0VkbvNaP2SW7mIbtzD.png","arte creative":"/80vsDtw538sEbfeMZayWqxzbB9D.png","ici tou.tv extra":"/lGynoY0Hnn5TSEVqwKAQb5vVGl9.png","tello":"/97OWtUjBFLxtztMrplqrOhYtMzD.png","2stv":"/azCNFEbDIIIeJ8yM5hDKQtTKH6X.png","sen tv":"/sUisp9lJUDI7dA7SP0X7wdJYsZX.png","wido":"/vwm0z2FK2A0tLjvSRjiyvR7yWpV.png","club rtl":"/7tjZK7sd7P7zz6fthAl2ELN93vU.png","jtbc3 fox sports":"/15puhQImE5hGj1lxXG4IUdN64im.png","comedy central netherlands":"/6ooPjtXufjsoskdJqj6pxuvHEno.png","vidio.com":"/eYdP5Uikvq9K2x0KK1emIx2WJdJ.png","kan educational":"/3R5OK6NxfFUnumjCkDCs5yxc4EV.png","à punt":"/iKEJEInEYPYDfQIZVGfEFVterDJ.png","5-tv":"/nIey7JqAgMmH0UC1ZXuTawGdAHL.png","discovery science":"/afxnsEk7jsfQlVbK0scU6gcuUeu.png","tv barrandov":"/vQde5X0ChsnMA0jNenBgtj2gTwW.png","nrj 12":"/uC0JP1tx3FPNTb8B0prVgRCscdf.png","rtv slovenija":"/yD8yjPqs10C0ayb38hKMXpQonJ3.png","wakanim":"/mBVrs71WfQiivUPrRQKvzAaXlb6.png","tvnz duke":"/tzwUoHIMWKhQzBw6sytWK6faCjv.png","net tv":"/yBzinXzZCmHWmK233JEX54xPdL5.png","hbo brasil":"/tuomPhY2UtuPTqqFnKMVHvSb724.png","tvn movies":"/kIxFo8qXuqVEVra2EKeuJGlPGBO.png","nagoya tv":"/6NBvugZ46HATVS6nXmWaLBHAtE8.png","hidive":"/rTjC2AeaaSTPjIh9YIqkPzVWpUw.png","puls 4":"/fs3NkllP0yllYAOOFcIBWKxLmtx.png","fct":"/1UBs9MeAJZyt8LzHowk25cXP7Ez.png","sky crime":"/sjBtLb4AiJX1pg4jUgBeNCgK7VO.png","gunma tv":"/oe9SS3K7nqf4s1VJpbqWx6wlxBb.png","hbc":"/n77lM12X5dhGHb0I57RmbtqxFsd.png","ktv":"/kkRV4tioxhTByglS1dVtgdpR1nB.png","tv5unis.ca":"/6Q0QyebAHKzDLHqW3xzajNYnVPA.png","aptn":"/d5oq1JLxnwRJ8YWCmOnr12iLIqA.png","rmc story":"/uKuCdsGlB3QETtIqoReAkEFS8am.png","d anime store":"/cCbMTimZb14Bk4KL6yHCVJl0ANC.png","sapporo television broadcasting":"/qV2FvarOatWAtBGk7tLe2KuQMyn.png","weverse":"/cIpoMkLXqYUPQgyESTbVcnPivh5.png","rkk kumamoto broadcasting":"/vSn3Au44pqNvrRAtOE7CjBWOOdz.png","vice tv":"/iA3HkJ8eNQZngQAjETO24YV8p1n.png","hokkaido cultural broadcasting":"/uKTzwez1p8tB4dnHMCeDjdN7xlR.png","ab3":"/yZdt7s80AWA1aqM8OsP6rD4CfMA.png","wetv":"/lf9ih4TfFC845idJHjuggJhQNL.png","television nishinippon corporation":"/6HPq1wlbqjCDa93OgaYp7E0ANIM.png","kitanihon broadcasting":"/kGUilAgTPGgaALslFvjyGvn4TKj.png","tps star":"/d7mFDlWCM6dvNah1Dn5q3haTq8k.png","atresplayer premium":"/pwqShp6HwtoMUpOubetuNnGeqwi.png","yomiuri telecasting corporation":"/wWiz0zwFX6WOXQSwsPyTCKITNQK.png","rakuten tv":"/4OMk9wkAMwjcVM905BDyDC3iIgC.png","anime houdai":"/zQbXySts9Nz2wus72JOqUPWG3Qt.png","anitele":"/6DTnriulEzrdURGjPV4QbY7WPuJ.png","video market":"/gx4yubRa2NkJ2Amia2kiNeQ2cja.png","omroep max":"/9kyApMSkL89Dtmidc3r9IRtSfBT.png","nagasaki culture telecasting corporation":"/qEIIHhehdHtTQ4fhuXrA29mbzmo.png","aha":"/whVDNlpH9Z9gqU3v6m4o4stnjgX.png","imago tv":"/hO0Oy9Jk9CEgKzNvZO7ERGPIuPQ.png","dailymotion":"/sjaEKT3ynyGDpOODdpLqsqJuy16.png","rtl-tvi":"/1a0bsGJysuLK6iH0OaBnAfxeEB7.png","kbs n sports":"/cfocxbV1M6E0NGEAhpLPhlio9g4.png","rtl9":"/umOhb2Hp2MrBL4rYbYALlsdBY7j.png","la sexta":"/2TtvRCBuH7OTK1vaKjtrWjepMLk.png","chubu-nippon broadcasting":"/gM0yhHNZxgJUUjb1o4abliDf0qN.png","fem":"/bvjpiZxP8cCU8HYcHnC0wvCvs7x.png","myvideo":"/q2n52WeF8xiBIA8efwtPXOyPT4V.png","vijf":"/AgdI3DKRqx8wrXkPQAExHQSwmfh.png","deutsche welle":"/wiZ9S6UFFGro47TnzgAR13IhneP.png","distrito comedia (mx)":"/9qOOQy1cVCs84SE18ivIWpL8Mqc.png","aragón tv":"/22uvDUdf6WfQr7jpSs34iKIUkUx.png","kinopoisk hd":"/4XvTKPCb8jpCpwkvYLjYxnjJhqH.png","rai play":"/3EOt7Yoe23FBVVAKbUPjMzxkzRD.png","canal+ (telenor)":"/5rTyarrnWBpX1lOInrVRM4zXr5r.png","téva":"/81QFkWQND1V5DQou9d65025qBTf.png","el toro tv":"/ZYHWzIaxCjtzogQz2PYddxwXEv.png","gemplex":"/m7Np4sh424iI6ApJrpb0tl49vc.png","rti1":"/el1B87vLnyEbkjTxuyxjOpi8dkw.png","france.tv":"/ugeH4bNdkJtBK0p30WlsFdtdx6d.png","filimo":"/5bajjCwynBYseyzOUxOfbqpQy3t.png","el terrat tv":"/th0Y7HsUwXvFOH8seRIzWk83OWe.png","ひかりtv":"/4iCrWtLJbSHABWZX022VEjvftmb.png","u-next":"/ydvZrfyYbBVXPDT1Tv2P6EmRmDZ.png","okko":"/pMy0zJmwHTsmR2mxLd4ifkOSq6h.png","čt sport":"/qB4QfmivJzhX6JLTfbB8BjuOD0K.png","disney channel ":"/3DKY9AYDEWnDNYcOcx6iFVTLpg4.png","revry":"/dXmPubyyiZtgHXU5bSbSQNnZq6v.png","snackabletv":"/mDiDmKmP4cWTfjuTSaHfVkOnOT4.png","hbo españa":"/z59yULluBjVC1NzIGzxSPBEjr2K.png","sama dubai tv":"/kbZ37FNUSIVFYhhMjGJV7X7AlJ0.png","paravi":"/xD3w4RZFoI78h1yiW7oslFixkJj.png","more.tv":"/mrv0nhpnFIqc3ouMtHzSkH6lBn1.png","el sótano":"/nJcGLqbapXY2dfLVbhfqB6LCLUf.png","čt3":"/wCn4ZTUgH6Di5NXmpJ7dQNWhM09.png","mbc 5":"/6y1eVaiCffvH7HOKSdEIJfIh8xq.png","laugh out loud":"/9LiLRKyEokkUQPQTAKRv2wGezLc.png","nippon television":"/bWiM2iY82B32NGmPCOFatgfekIR.png","movistar+":"/8DdXvwYKBnLU4ZV9bOTOBAn7Zci.png","6play":"/rPMeCuFqgCj4gNVLX75uEcFApHQ.png","boing":"/iTubxZz2a5zjePACJYEJoQkIrJp.png","disney+ hotstar":"/sFfLNkL0DZPbYlgmxu9aXp7TiHZ.png","kapamilya channel":"/xal22lPb7A1c1FQoYdHzpOm37Kf.png","ivi":"/iiw2u46efdRXsnPMMh9C0na67oN.png","tvnz kidzone":"/tvnhZ9VlSoIpgps2wqLmPUVwV7p.png","tvnz6":"/gm9eU2DrGROjAkIoODCjnAHkOO2.png","rai 5":"/mvh2XSuVFwksHTwaYNSr3umfAIR.png","ten":"/8OeBWslnqoiEfBR9XpIOQrNgwI5.png","ifilm":"/3hchCBmgzMuMbWoElH7y7YtCBUD.png","friday影音":"/kP69k9W9KSCbtA4SRI3x2LmByAD.png","nara television":"/9M08u5EOibJxZCWPG2kasrLrKAR.png","channel 20":"/6QAPdSM1oyNwdXil345sGshUjVv.png","i-television":"/3t75XJS7vO7Ih6rJkIqUuZkePDp.png","shizuoka broadcasting system":"/coXc7bJqUEik68t3AzjjGzUQ7zJ.png","iwate broadcasting":"/zoFgqDe0v8svSA01yExlhcG1Bss.png","broadcasting system of san-in":"/cQWQ5UZqFviyJNqvbuvgZUyly5b.png","hokuriku broadcasting":"/wvBiZKeuACCz8kxeUJ8obHfHnqZ.png","oita broadcasting system":"/iRxliwAcihUyTIjJbpxQ9zMGbEj.png","tv-u fukushima":"/7jZrfXteN6dWampK5E6qJSScuZm.png","tv-u yamagata":"/zOz9LK6WWLUWGuG0fthzDzCIXlA.png","tohoku broadcasting":"/6oIE2LmtONObnw5wtFO4IIXwgkb.png","mitele":"/t8uzAgIZTWU0MkhPSlqhIQNJ8H4.png","wakayama telecasting":"/qBhdAhitNODSGDEmeK8p0XZ0JAG.png","arre":"/6915j5uXxekwxJO6RFnqJMlMFc1.png","bindass":"/ivTJSsZ8qLOkrEFebBMB1d8Y56A.png","nrt2":"/mZABPzdCUaHtd1P6cwQEfle2Bie.png","jiocinema":"/yXrkdA9NlUfX2mRDhPgk0ye9frq.png","britbox":"/n8YeTJow7qmgfjgoQ51Xi2MQezB.png","shant tv":"/sTexVkysmuo2hjHzBG5YHn4TMCY.png","azteca trece":"/tP07zSQEFmN84mfdYrPqdyxGDO0.png","óčko":"/hvp4sRYLwe18yWagNcBkSVwnzwd.png","13c":"/fWv4H0txKqviTx4aq5HxSFJ7j7J.png","imdb tv":"/vizcQUuniStEN7Xm9IminQbuisT.png","ct-1 (ussr)":"/usMoGOAxJ1YfYkPTwPTsDeVIvEJ.png","nova s":"/ljhUSTgggthaCgI1q7gYoVvU2Fd.png","20th television":"/2xv5kBgBdH91xtkm7SwPCd17nir.png","steam":"/wWvkikegnLxnBEkVTVmjRSlUpwH.png","tchelet tv":"/2O5ZRXQgH8yRvFCAXFyY2mw3OzP.png","hero tv":"/uF8cYTk1EOlFO003DX4LVSQHVbp.png","anime network":"/5Jc6AwN606Yg3efvFTQddaHrdFg.png","rtk":"/5eolJ0d90bDHlgx0PTBIu2klH1I.png","vizion plus":"/o5oZOnIRbV3jxZusMOWkQLcnriK.png","tva sports":"/a2hV9XrqawPM4fsg9CWoeTzW3Mc.png","voyagevoyage.ca":"/pFzYb9kpO100rhN5kdx2zwT9sLk.png","ctc media":"/8Sko4MFVPiwWInOuV1CsjHz0In1.png","children channel":"/9XSgTaER2dC4CVQJ759SCazA2vf.png","la fabrique culturelle":"/yq4KcjrdazO6YJhxuaS43iA7ltL.png","تطبيق أكوام | لمشاهدة الافلام والمسلسلات مجانًا":"/bxUTlwXm2v1PDnVIkQj79Ewtdx5.png","xbox live":"/4yYlTy9YoiJdSbxpsTJSKrLrSiU.png","super":"/yVgt27IiNXdelp7B1BHj5IAWFfe.png","streamz":"/mwVrzJ290lzATbpMg22Fk4MVBcs.png","disney.com":"/7Lpp3EiQyEWnHWUlDIBtr2Jzp92.png","espn+":"/mnrrbM7g7gvthN6iyYZ8ndrGKix.png","court tv":"/uZHvgQG1ThBWbmDH6Os3YL6sA9J.png","hbo go":"/3UnuWwVr6PCtXyGzZZqgYQTZhCq.png","sky documentaries":"/3bNL6ulQf7SInQiOEwJKeClMvrX.png","commercial television":"/d8K1SKholLjEPHaY5evDwRR7wgj.png","noovo":"/5dvZFVBad4gj3vdCFY3kBHlIwg3.png","shanxi television":"/7SfN4GyCU58ijp0DQJpKdGJURHV.png","rthk":"/szBBidFy2MHGUejAtu4EjaiS3Mt.png","a+":"/9xCEeQAKtyH54sY3c0TxY6X7Scn.png","astro aec":"/7AvGS1q9vYjUs2GkVKnoypLC0nv.png","f1 tv":"/eGPTbt05LYgBniGaj8NFusMzRWm.png","tl streaming":"/bwjj3k5haH2cXpONzngRlt1QO3o.png"} \ No newline at end of file diff --git a/custom_components/samsungtv_tizen/manifest.json b/custom_components/samsungtv_tizen/manifest.json new file mode 100644 index 00000000..62889989 --- /dev/null +++ b/custom_components/samsungtv_tizen/manifest.json @@ -0,0 +1,13 @@ +{ + "domain": "samsungtv_tizen", + "name": "SamsungTV Tizen", + "documentation": "https://github.com/jaruba/ha-samsungtv-tizen", + "requirements": [ + "websocket-client==0.56.0", + "wakeonlan==1.1.6", + "numpy==1.19.2" + ], + "dependencies": [], + "codeowners": ["@jaruba"], + "homeassistant": "0.99.3" +} diff --git a/custom_components/samsungtv_tizen/media_player.py b/custom_components/samsungtv_tizen/media_player.py new file mode 100644 index 00000000..eacc2d50 --- /dev/null +++ b/custom_components/samsungtv_tizen/media_player.py @@ -0,0 +1,983 @@ +"""Support for interface with an Samsung TV.""" +import asyncio +from datetime import timedelta, datetime +import logging +import socket +import json +import voluptuous as vol +import os +import wakeonlan +import websocket +import requests +import time +import numpy as np + +from .websockets import SamsungTVWS +from . import exceptions + +from .smartthings import smartthingstv as smartthings + +from .upnp import upnp + +from homeassistant import util +try: + from homeassistant.components.media_player import MediaPlayerEntity, PLATFORM_SCHEMA, DEVICE_CLASS_TV +except ImportError: + from homeassistant.components.media_player import MediaPlayerDevice as MediaPlayerEntity, PLATFORM_SCHEMA, DEVICE_CLASS_TV + +from homeassistant.components.media_player.const import ( + MEDIA_TYPE_CHANNEL, + SUPPORT_NEXT_TRACK, + SUPPORT_PAUSE, + SUPPORT_PLAY, + SUPPORT_PLAY_MEDIA, + SUPPORT_PREVIOUS_TRACK, + SUPPORT_SELECT_SOURCE, + SUPPORT_TURN_OFF, + SUPPORT_TURN_ON, + SUPPORT_VOLUME_MUTE, + SUPPORT_VOLUME_STEP, + SUPPORT_VOLUME_SET, + MEDIA_TYPE_APP, + MEDIA_TYPE_URL, +) + +from homeassistant.const import ( + CONF_BROADCAST_ADDRESS, + CONF_HOST, + CONF_MAC, + CONF_NAME, + CONF_PORT, + CONF_TIMEOUT, + CONF_API_KEY, + CONF_DEVICE_ID, + STATE_OFF, + STATE_ON, +) +import homeassistant.helpers.config_validation as cv +from homeassistant.util import dt as dt_util + +_LOGGER = logging.getLogger(__name__) + +CONF_SHOW_CHANNEL_NR = "show_channel_number" + +DEFAULT_NAME = "Samsung TV Remote" +DEFAULT_PORT = 8002 +DEFAULT_TIMEOUT = 3 +DEFAULT_KEY_CHAIN_DELAY = 1.25 +DEFAULT_UPDATE_METHOD = "ping" +DEFAULT_SOURCE_LIST = '{"TV": "KEY_TV", "HDMI": "KEY_HDMI"}' +CONF_UPDATE_METHOD = "update_method" +CONF_UPDATE_CUSTOM_PING_URL = "update_custom_ping_url" +CONF_SOURCE_LIST = "source_list" +CONF_APP_LIST = "app_list" +CONF_CHANNEL_LIST = "channel_list" +CONF_SCAN_APP_HTTP = "scan_app_http" +CONF_IS_FRAME_TV = "is_frame_tv" +CONF_SHOW_LOGOS = "show_logos" + +KNOWN_DEVICES_KEY = "samsungtv_known_devices" +MEDIA_TYPE_KEY = "send_key" +MEDIA_TYPE_BROWSER = "browser" + +SCAN_INTERVAL = timedelta(seconds=15) + +MIN_TIME_BETWEEN_FORCED_SCANS = timedelta(milliseconds=100) +MIN_TIME_BETWEEN_SCANS = SCAN_INTERVAL + +KEYHOLD_MAX_DELAY = 5.0 +KEY_PRESS_TIMEOUT = 0.5 +UPDATE_PING_TIMEOUT = 1.0 +UPDATE_STATUS_DELAY = 1 +UPDATE_SOURCE_INTERVAL = 5 +WS_CONN_TIMEOUT = 10 +POWER_OFF_DELAY = timedelta(seconds=20) + +SUPPORT_SAMSUNGTV = ( + SUPPORT_PAUSE + | SUPPORT_VOLUME_STEP + | SUPPORT_VOLUME_MUTE + | SUPPORT_VOLUME_SET + | SUPPORT_PREVIOUS_TRACK + | SUPPORT_SELECT_SOURCE + | SUPPORT_NEXT_TRACK + | SUPPORT_TURN_OFF + | SUPPORT_PLAY + | SUPPORT_PLAY_MEDIA +) + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( + { + vol.Required(CONF_HOST): cv.string, + vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, + vol.Optional(CONF_MAC): cv.string, + vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int, + vol.Optional(CONF_UPDATE_METHOD, default=DEFAULT_UPDATE_METHOD): cv.string, + vol.Optional(CONF_UPDATE_CUSTOM_PING_URL): cv.string, + vol.Optional(CONF_SOURCE_LIST, default=DEFAULT_SOURCE_LIST): cv.string, + vol.Optional(CONF_APP_LIST): cv.string, + vol.Optional(CONF_CHANNEL_LIST): cv.string, + vol.Optional(CONF_DEVICE_ID): cv.string, + vol.Optional(CONF_API_KEY): cv.string, + vol.Optional(CONF_SHOW_CHANNEL_NR, default=False): cv.boolean, + vol.Optional(CONF_BROADCAST_ADDRESS): cv.string, + vol.Optional(CONF_SCAN_APP_HTTP, default=True): cv.boolean, + vol.Optional(CONF_IS_FRAME_TV, default=False): cv.boolean, + vol.Optional(CONF_SHOW_LOGOS, default="white-color"): cv.string + } +) + +MEDIA_IMAGE_OPTIONS = {'none': 'none', 'blue-color': '05a9f4-color', 'blue-white': '05a9f4-white', 'dark-white': '282c34-white', 'darkblue-white': '212c39-white', 'white-color': 'fff-color', 'transparent-color': 'transparent-color', 'transparent-white': 'transparent-white'} +MEDIA_FILE_IMAGE_TO_PATH = os.path.dirname(os.path.realpath(__file__)) + '/logo_paths.json' +MEDIA_IMAGE_MIN_SCORE_REQUIRED = 80 +MEDIA_TITLE_KEYWORD_REMOVAL = ['HD'] + +def setup_platform(hass, config, add_entities, discovery_info=None): + """Set up the Samsung TV platform.""" + known_devices = hass.data.get(KNOWN_DEVICES_KEY) + if known_devices is None: + known_devices = set() + hass.data[KNOWN_DEVICES_KEY] = known_devices + + uuid = None + + # Is this a manual configuration? + if config.get(CONF_HOST) is not None: + host = config.get(CONF_HOST) + port = config.get(CONF_PORT) + name = config.get(CONF_NAME) + mac = config.get(CONF_MAC) + broadcast = config.get(CONF_BROADCAST_ADDRESS) + timeout = config.get(CONF_TIMEOUT) + update_method = config.get(CONF_UPDATE_METHOD) + update_custom_ping_url = config.get(CONF_UPDATE_CUSTOM_PING_URL) + source_list = config.get(CONF_SOURCE_LIST) + app_list = config.get(CONF_APP_LIST) + channel_list = config.get(CONF_CHANNEL_LIST) + api_key = config.get(CONF_API_KEY) + device_id = config.get(CONF_DEVICE_ID) + show_channel_number = config.get(CONF_SHOW_CHANNEL_NR) + scan_app_http = config.get(CONF_SCAN_APP_HTTP) + is_frame_tv = config.get(CONF_IS_FRAME_TV) + show_logos = config.get(CONF_SHOW_LOGOS) + elif discovery_info is not None: + tv_name = discovery_info.get("name") + model = discovery_info.get("model_name") + host = discovery_info.get("host") + name = f"{tv_name} ({model})" + port = DEFAULT_PORT + timeout = DEFAULT_TIMEOUT + update_method = DEFAULT_UPDATE_METHOD + update_custom_ping_url = None + source_list = DEFAULT_SOURCE_LIST + app_list = None + mac = None + udn = discovery_info.get("udn") + if udn and udn.startswith("uuid:"): + uuid = udn[len("uuid:") :] + else: + _LOGGER.warning("Cannot determine device") + return + + # Only add a device once, so discovered devices do not override manual + # config. + ip_addr = socket.gethostbyname(host) + if ip_addr not in known_devices: + known_devices.add(ip_addr) + add_entities([SamsungTVDevice(host, port, name, timeout, mac, uuid, update_method, update_custom_ping_url, source_list, app_list, channel_list, api_key, device_id, show_channel_number, broadcast, scan_app_http, is_frame_tv, show_logos)]) + _LOGGER.info("Samsung TV %s:%d added as '%s'", host, port, name) + else: + _LOGGER.info("Ignoring duplicate Samsung TV %s:%d", host, port) + + +class SamsungTVDevice(MediaPlayerEntity): + """Representation of a Samsung TV.""" + + def __init__(self, host, port, name, timeout, mac, uuid, update_method, update_custom_ping_url, source_list, app_list, channel_list, api_key, device_id, show_channel_number, broadcast, scan_app_http, is_frame_tv, show_logos): + """Initialize the Samsung device.""" + + # Save a reference to the imported classes + self._host = host + self._name = name + self._api_key = api_key + self._device_id = device_id + self._show_channel_number = show_channel_number + self._timeout = timeout + self._mac = mac + self._update_method = update_method + self._update_custom_ping_url = update_custom_ping_url + self._broadcast = broadcast + self._scan_app_http = scan_app_http + self._is_frame_tv = is_frame_tv + + self._source = None + self._source_list = json.loads(source_list) + + self._running_app = None + if app_list is not None: + self._auto_gen_installed_app_list = False + dlist = self._split_app_list(json.loads(app_list), "/") + self._app_list = dlist["app"] + self._app_list_ST = dlist["appST"] + else: + self._auto_gen_installed_app_list = True + self._app_list = None + self._app_list_ST = None + + self._channel = None + if channel_list is not None: + self._channel_list = json.loads(channel_list) + else: + self._channel_list = None + + self._uuid = uuid + self._is_ws_connection = True if port in (8001, 8002) else False + # Assume that the TV is not muted and volume is 0 + self._muted = False + self._volume = 0 + # Assume that the TV is in Play mode + self._playing = True + self._state = None + # Mark the end of a shutdown command (need to wait 15 seconds before + # sending the next command to avoid turning the TV back ON). + self._end_of_power_off = None + self._token_file = None + + self._last_command_time = datetime.now() + self._last_source_time = None + + # Generate token file only for WS + SSL + Token connection + if port == 8002: + self._gen_token_file() + + self._ws = SamsungTVWS( + name=name, + host=host, + port=port, + timeout=self._timeout, + key_press_delay=KEY_PRESS_TIMEOUT, + token_file=self._token_file, + app_list=self._app_list + ) + + self._upnp = upnp( + host=host + ) + + self._media_title = None + self._media_image_url = None + self._media_image_base_url = None + + if show_logos in MEDIA_IMAGE_OPTIONS: + if MEDIA_IMAGE_OPTIONS[show_logos] == "none": + self._media_image_base_url = None + else: + self._media_image_base_url = "https://jaruba.github.io/channel-logos/export/{}".format(MEDIA_IMAGE_OPTIONS[show_logos]) + else: + _LOGGER.warning("Unrecognized value '%s' for 'show_logos' option (%s). Using default value.",show_logos,self._name) + self._media_image_base_url = "https://jaruba.github.io/channel-logos/export/fff-color" + + def _split_app_list(self, app_list, sep = "/"): + retval = {"app": {}, "appST": {}} + + for attr, value in app_list.items(): + value_split = value.split(sep, 1) + idx = 1 if len(value_split) > 1 else 0 + retval["app"].update({attr: value_split[0]}) + retval["appST"].update({attr: value_split[idx]}) + + return retval + + def _gen_token_file(self): + self._token_file = os.path.dirname(os.path.realpath(__file__)) + '/token-' + self._host + '.txt' + + if os.path.isfile(self._token_file) is False: + # For correct auth + self._timeout = 45 + + # Create token file for catch possible errors + try: + handle = open(self._token_file, "w+") + handle.close() + except: + _LOGGER.error("Samsung TV - Error creating token file: %s", self._token_file) + + def _power_off_in_progress(self): + return ( + self._end_of_power_off is not None + and self._end_of_power_off > dt_util.utcnow() + ) + + def _ping_device(self): + _LOGGER.debug("Updating SamsungTV %s, With Method: %s", self._name,self._update_method) + # Smartthings Update + if self._update_method == "smartthings" and self._api_key and self._device_id: + if hasattr(self, '_cloud_state'): + self._state = self._cloud_state + else: + self._state = STATE_OFF + # HTTP ping + elif self._is_ws_connection and self._update_method == "ping": + try: + ping_url = "http://{}:8001/api/v2/".format(self._host) + if self._update_custom_ping_url is not None: + ping_url = self._update_custom_ping_url + requests.get(ping_url,timeout=UPDATE_PING_TIMEOUT) + self._state = STATE_ON + tmp_muted=self._upnp.get_mute() + if tmp_muted is not None: + self._muted = tmp_muted + tmp_vol=self._upnp.get_volume() + if tmp_vol is not None: + self._volume = int(self._upnp.get_volume()) / 100 + if self._app_list is None: + self.hass.async_create_task(self._gen_installed_app_list()) + except: + self._state = STATE_OFF + # WS ping + elif self._is_ws_connection and self._update_method == "websockets": + if self.send_command("KEY", "send_key", 1, 0,bForceUpdate=False): + tmp_muted=self._upnp.get_mute() + if tmp_muted is not None: + self._muted = tmp_muted + tmp_vol=self._upnp.get_volume() + if tmp_vol is not None: + self._volume = int(self._upnp.get_volume()) / 100 + if self._app_list is None: + self.hass.async_create_task(self._gen_installed_app_list()) + else: + _LOGGER.debug("SamsungTV %s, Update Error, assuming state: %s", self._name, self._state) + else: + _LOGGER.error("SamsungTV %s, Unknown Update Method: %s", self._name,self._update_method) + + def _get_running_app(self): + if self._app_list is not None: + if hasattr(self, '_cloud_state') and self._cloud_channel_name != "": + for attr, value in self._app_list_ST.items(): + if value == self._cloud_channel_name: + self._running_app = attr + return + if self._scan_app_http: + for app in self._app_list: + r = None + try: + r = requests.get('http://{host}:8001/api/v2/applications/{value}'.format(host=self._host, value=self._app_list[app]), timeout=0.5) + except requests.exceptions.RequestException as e: + pass + try: + if r is not None: + data = r.text + if data is not None: + root = json.loads(data.encode('UTF-8')) + if 'visible' in root: + if root['visible']: + self._running_app = app + return + except Exception as ex: + _LOGGER.debug("Samsung TV %s, _get_running_app Failed - %s......",self._name,ex) + self._running_app = 'TV/HDMI' + + + async def _gen_installed_app_list(self): + if self._app_list is not None: + _LOGGER.debug("SamsungTV %s, Manual set applist or already got, _gen_installed_app_list not executed", self._name) + return + _LOGGER.debug("Samsung TV %, Self Applist %s",self._app_list) + if self._state == STATE_OFF or self._state == None: + _LOGGER.debug("Samsung TV %s, is OFF, _gen_installed_app_list not executed...%s",self._name) + return + _LOGGER.debug("Samsung TV %s, _gen_installed_app_list executed......",self._name) + try: + app_list = self._ws.app_list() + except Exception as ex: + _LOGGER.debug("Samsung TV %s, _gen_installed_app_list Failed - %s......",self._name,ex) + self._ws.close() + return + # app_list is a list of dict + clean_app_list = {} + for i in range(len(app_list)): + try: + app = app_list[i] + clean_app_list[ app.get('name') ] = app.get('appId') + except Exception: + pass + self._app_list_ST = self._app_list = clean_app_list + _LOGGER.debug("Gen installed app_list %s", clean_app_list) + + + @util.Throttle(MIN_TIME_BETWEEN_SCANS, MIN_TIME_BETWEEN_FORCED_SCANS) + def update(self): + """Update state of device.""" + if self._update_method == "smartthings" and self._api_key and self._device_id: + smartthings.device_update(self) + self._ping_device() + else: + self._ping_device() + """Still required to get source and media title""" + if self._api_key and self._device_id: + smartthings.device_update(self) + if self._state == STATE_ON and not self._power_off_in_progress(): + self._get_running_app() + + if self._state == STATE_OFF: + self._end_of_power_off = None + + self.hass.async_add_job(self._update_media_data) + + def _get_source(self): + """Return the current input source.""" + if self._state != STATE_OFF: + # we throttle the method for 5 seconds when we change the source from the UI + # this is done to give the required time to update the real status and provide correct feedback + # self._last_source_time is set in async_select_source method + call_time = datetime.now() + if self._last_source_time is not None: + difference = (call_time - self._last_source_time).total_seconds() + if difference < UPDATE_SOURCE_INTERVAL: #update source every 5 seconds + return self._source + self._last_source_time = call_time + if hasattr(self, '_cloud_state'): + if self._cloud_state == STATE_OFF: + self._source = None + else: + if self._running_app == "TV/HDMI": + cloud_key = "" + if self._cloud_source in ["DigitalTv", "digitalTv", "TV"]: + cloud_key = "ST_TV" + else: + cloud_key = "ST_" + self._cloud_source + found_source = "" + for attr, value in self._source_list.items(): + if value == cloud_key: + found_source = attr + if found_source != "": + self._source = found_source + else: + self._source = self._running_app + else: + self._source = self._running_app + else: + self._source = self._running_app + else: + self._source = None + self._last_source_time = None + + return self._source + + def _smartthings_keys(self, source_key): + if source_key.startswith("ST_HDMI"): + smartthings.send_command(self, source_key.replace("ST_", ""), "selectsource") + elif source_key == "ST_TV": + smartthings.send_command(self, "digitalTv", "selectsource") + elif source_key == "ST_CHUP": + smartthings.send_command(self, "up", "stepchannel") + elif source_key == "ST_CHDOWN": + smartthings.send_command(self, "down", "stepchannel") + elif source_key.startswith("ST_CH"): + ch_num = source_key.replace("ST_CH", "") + if ch_num.isdigit(): + smartthings.send_command(self, ch_num, "selectchannel") + elif source_key == "ST_MUTE": + smartthings.send_command(self, "off" if self._muted else "on", "audiomute") + elif source_key == "ST_VOLUP": + smartthings.send_command(self, "up", "stepvolume") + elif source_key == "ST_VOLDOWN": + smartthings.send_command(self, "down", "stepvolume") + elif source_key.startswith("ST_VOL"): + vol_lev = source_key.replace("ST_VOL", "") + if vol_lev.isdigit(): + smartthings.send_command(self, vol_lev, "setvolume") + + def send_command(self, payload, command_type = "send_key", retry_count = 1, key_press_delay=None,bForceUpdate=True): + """Send a key to the tv and handles exceptions.""" + bReturn = True + call_time = datetime.now() + difference = (call_time - self._last_command_time).total_seconds() + if difference > WS_CONN_TIMEOUT: #always close connection after WS_CONN_TIMEOUT (10 seconds) + self._ws.close() + self._last_command_time = call_time + try: + # recreate connection if connection was dead + for _ in range(retry_count + 1): + try: + if command_type == "run_app": + #run_app(self, app_id, app_type='DEEP_LINK', meta_tag='') + self._ws.run_app(payload) + else: + hold_delay = 0 + source_keys = payload.split(",") + key_code = source_keys[0] + if len(source_keys) > 1: + + def get_hold_time(): + hold_time = source_keys[1].replace(" ", "") + if not hold_time: + return 0 + if not hold_time.isdigit(): + return 0 + hold_time = int(hold_time)/1000 + return min(hold_time, KEYHOLD_MAX_DELAY) + + hold_delay = get_hold_time() + + if hold_delay > 0: + self._ws.hold_key(key_code, hold_delay) + else: + self._ws.send_key(payload, key_press_delay) + break + except (ConnectionResetError, AttributeError, BrokenPipeError) as ex: + self._ws.close() + _LOGGER.debug("Samsung TV %s, Error in send_command() -> %s......",self._name,ex) + self._state = STATE_ON + except (websocket._exceptions.WebSocketTimeoutException,exceptions.ConnectionFailure) as ex: + # We got a response so it's on. + self._ws.close() + self._state = STATE_ON + _LOGGER.debug("Samsung TV %s, Failed sending payload %s command_type %s",self._name,payload, command_type,ex) + bReturn = False + except OSError: + self._ws.close() + self._state = STATE_OFF + _LOGGER.debug("Error in send_command() -> OSError") + bReturn = False + if bForceUpdate: + self.update(no_throttle=True) + self.schedule_update_ha_state(True) + else: + self.update() + self.schedule_update_ha_state() + return bReturn + + @property + def unique_id(self) -> str: + """Return the unique ID of the device.""" + return self._uuid + + @property + def name(self): + """Return the name of the device.""" + return self._name + + @property + def media_title(self): + """Title of current playing media.""" + return self._media_title + + @property + def media_image_url(self): + """Return the media image URL.""" + return self._media_image_url + + async def _update_media_data(self): + if self._state == STATE_OFF and self._update_method != "smartthings": + self._media_title = None + if self._api_key and self._device_id and hasattr(self, '_cloud_state'): + if self._cloud_state == STATE_OFF: + self._state = STATE_OFF + self._media_title = None + elif self._running_app == "TV/HDMI" and self._cloud_source in ["DigitalTv", "digitalTv", "TV"] and self._cloud_channel_name == "" and self._cloud_channel != "": + self._media_title = self._cloud_channel + self._media_image_url = None + else: + if self._running_app == "TV/HDMI" and self._cloud_source in ["DigitalTv", "digitalTv", "TV"] and self._cloud_channel_name != "": + new_media_title = search_media_title = self._cloud_channel_name + if self._show_channel_number and self._cloud_channel != "": + new_media_title = new_media_title + " (" + self._cloud_channel + ")" + else: + new_media_title = search_media_title = self._get_source() + #only match new image if title actually changed and logos are enabled + if self._media_title != new_media_title and self._media_image_base_url is not None: + if new_media_title not in ["TV","HDMI","TV/HDMI"]: + _LOGGER.debug("Matching title to image %s",search_media_title) + await self._match_title_to_image(search_media_title) + else: + self._media_image_url = None + self._media_title = new_media_title + else: + new_media_title = self._get_source() + #only match new image if title actually changed and logos are enabled + if self._media_title != new_media_title and self._media_image_base_url is not None: + if new_media_title not in ["TV","HDMI","TV/HDMI"] and new_media_title is not None: + _LOGGER.debug("Matching title to image %s",new_media_title) + await self._match_title_to_image(new_media_title) + else: + self._media_image_url = None + self._media_title = new_media_title + + async def _match_title_to_image(self, media_title): + if media_title is not None: + for word in MEDIA_TITLE_KEYWORD_REMOVAL: + media_title = media_title.lower().replace(word.lower(),'') + media_title = media_title.lower().strip() + try: + with open(MEDIA_FILE_IMAGE_TO_PATH, 'r') as f: + image_paths = iter(json.load(f).items()) + except: + self._media_image_url = None + + best_match = {"ratio": None, "title": None, "path": None} + while True: + try: + image_path = next(image_paths) + ratio = levenshtein_ratio_and_distance(media_title,image_path[0].lower(),ratio_calc = True) + if best_match["ratio"] is None or ratio > best_match["ratio"]: + best_match = {"ratio":ratio,"title":image_path[0],"path":image_path[1]} + except StopIteration: + break + + if best_match["ratio"] > MEDIA_IMAGE_MIN_SCORE_REQUIRED/100: + _LOGGER.debug("Match found for %s: %s (%f) %s", media_title, best_match["title"], best_match["ratio"], self._media_image_base_url+best_match["path"]) + self._media_image_url = self._media_image_base_url+best_match["path"] + else: + _LOGGER.debug("No match found for %s: best candidate was %s (%f) %s", media_title, best_match["title"], best_match["ratio"], self._media_image_base_url+best_match["path"]) + self._media_image_url = None + else: + _LOGGER.debug("No media title right now!") + self._media_image_url = None + + @property + def state(self): + """Return the state of the device.""" + + # Warning: we assume that after a sending a power off command, the command is successful + # so for 20 seconds (defined in POWER_OFF_DELAY) the state will be off regardless of the actual state. + # This is to have better feedback to the command in the UI, but the logic might cause other issues in the future + if self._power_off_in_progress(): + return STATE_OFF + return self._state + + + @property + def is_volume_muted(self): + """Boolean if volume is currently muted.""" + return self._muted + + + @property + def source_list(self): + """List of available input sources.""" + if self._app_list is None: + self._gen_installed_app_list() + source_list = [] + source_list.extend(list(self._source_list)) + if self._app_list is not None: + source_list.extend(list(self._app_list)) + if self._channel_list is not None: + source_list.extend(list(self._channel_list)) + return source_list + + @property + def channel_list(self): + """List of available channels.""" + if self._channel_list is None: + return None + else: + return list(self._channel_list) + + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + return self._volume + + + @property + def source(self): + """Return the current input source.""" + return self._get_source() + + + @property + def supported_features(self): + """Flag media player features that are supported.""" + return SUPPORT_SAMSUNGTV | SUPPORT_TURN_ON + + @property + def device_class(self): + """Set the device class to TV.""" + return DEVICE_CLASS_TV + + def turn_on(self): + """Turn the media player on.""" + if self._power_off_in_progress(): + self._end_of_power_off = None + if self._is_ws_connection: + self.hass.async_add_job(self.send_command, "KEY_POWER") + else: + self.hass.async_add_job(self.send_command, "KEY_POWEROFF") + elif self._state == STATE_OFF: + if self._mac: + if self._broadcast: + for i in range(20): + wakeonlan.send_magic_packet(self._mac, ip_address=self._broadcast) + time.sleep(0.25) + else: + for i in range(20): + wakeonlan.send_magic_packet(self._mac) + time.sleep(0.25) + #Force Update as send command not called + self.update(no_throttle=True) + self.schedule_update_ha_state(True) + else: + self.hass.async_add_job(self.send_command, "KEY_POWERON") + #Assume optomistic ON + self._state = STATE_ON + + def turn_off(self): + """Turn off media player.""" + if (not self._power_off_in_progress()) and self._state != STATE_OFF: + self._end_of_power_off = dt_util.utcnow() + POWER_OFF_DELAY + if self._is_ws_connection: + if self._is_frame_tv == False: + self.hass.async_add_job(self.send_command, "KEY_POWER") + else: + self.hass.async_add_job(self.send_command, "KEY_POWER,3000") + else: + self.hass.async_add_job(self.send_command, "KEY_POWEROFF") + # Force closing of remote session to provide instant UI feedback + try: + self._ws.close() + except OSError: + _LOGGER.debug("Could not establish connection.") + #Empty Applist if autogenerated + if self._auto_gen_installed_app_list == True: + self._app_list = None + self._app_list_ST = None + #Assume optomistic OFF + self._state = STATE_OFF + + + + def volume_up(self): + """Volume up the media player.""" + self._volume = self._volume + 0.1 + if self._volume>1: + self._volume = 1 + self.hass.async_add_job(self.send_command, "KEY_VOLUP") + + + def volume_down(self): + """Volume down media player.""" + self._volume = self._volume - 0.1 + if self._volume<0: + self._volume = 0 + self.hass.async_add_job(self.send_command, "KEY_VOLDOWN") + + + def mute_volume(self, mute): + """Send mute command.""" + self._muted = not self._muted + self.hass.async_add_job(self.send_command, "KEY_MUTE") + + + def set_volume_level(self, volume): + """Set volume level, range 0..1.""" + self._volume = volume + self.hass.async_add_job(self._upnp.set_volume, int(volume*100)) + + + def media_play_pause(self): + """Simulate play pause media player.""" + if self._playing: + self.media_pause() + else: + self.media_play() + + + def media_play(self): + """Send play command.""" + self._playing = True + self.hass.async_add_job(self.send_command, "KEY_PLAY") + + + def media_pause(self): + """Send media pause command to media player.""" + self._playing = False + self.hass.async_add_job(self.send_command, "KEY_PAUSE") + + + def media_next_track(self): + """Send next track command.""" + if self.source == "TV": + self.hass.async_add_job(self.send_command, "KEY_CHUP") + else: + self.hass.async_add_job(self.send_command, "KEY_FF") + + + def media_previous_track(self): + """Send the previous track command.""" + if self.source == "TV": + self.hass.async_add_job(self.send_command, "KEY_CHDOWN") + else: + self.hass.async_add_job(self.send_command, "KEY_REWIND") + + + async def async_play_media(self, media_type, media_id, **kwargs): + # Type channel + if media_type == MEDIA_TYPE_CHANNEL: + """Support changing a channel.""" + _LOGGER.debug("Trying to change %s to %s",media_type,media_id) + try: + cv.positive_int(media_id) + except vol.Invalid: + _LOGGER.error("Media ID must be positive integer") + return + if self._api_key and self._device_id: + if self._running_app == 'TV/HDMI' and self._cloud_source in ["DigitalTv", "digitalTv", "TV"]: + #In TV mode, change channel + if self._cloud_channel != media_id: + await self.hass.async_add_job(self._smartthings_keys, f"ST_CH{media_id}") + else: + #Change to TV source before changing channel + self.hass.async_add_job(self._smartthings_keys, "ST_TV") + time.sleep(5) + smartthings.device_update(self) + if self._cloud_channel != media_id: + await self.hass.async_add_job(self._smartthings_keys, f"ST_CH{media_id}") + else: + keychain = "" + for digit in media_id: + keychain += "KEY_{}+".format(digit) + keychain += "KEY_ENTER" + if self._running_app == 'TV/HDMI': + self.hass.async_add_job(self.async_play_media, MEDIA_TYPE_KEY, keychain) + else: + found_source = False + for source in self._source_list: + if source.lower() in ["tv", "live tv", "livetv"]: + found_source = True + await self.hass.async_add_job(self.async_select_source, source) + time.sleep(2) + break + if found_source == False: + keychain = "KEY_EXIT+KEY_EXIT+{}".format(keychain) + self.hass.async_add_job(self.async_play_media, MEDIA_TYPE_KEY, keychain) + # Launch an app + elif media_type == MEDIA_TYPE_APP: + await self.hass.async_add_job(self.send_command, media_id, "run_app") + # Send custom key + elif media_type == MEDIA_TYPE_KEY: + try: + cv.string(media_id) + except vol.Invalid: + _LOGGER.error('Media ID must be a string (ex: "KEY_HOME"') + return + source_key = media_id + if "+" in source_key: + all_source_keys = source_key.split("+") + last_was_delay = True + for this_key in all_source_keys: + if this_key.isdigit(): + last_was_delay = True + time.sleep(int(this_key)/1000) + else: + if this_key.startswith("ST_"): + await self.hass.async_add_job(self._smartthings_keys, this_key) + else: + if last_was_delay == False: + time.sleep(DEFAULT_KEY_CHAIN_DELAY) + last_was_delay = False + self.hass.async_add_job(self.send_command, this_key) + elif source_key.startswith("ST_"): + await self.hass.async_add_job(self._smartthings_keys, source_key) + else: + await self.hass.async_add_job(self.send_command, source_key) + # Play media + elif media_type == MEDIA_TYPE_URL: + try: + cv.url(media_id) + except vol.Invalid: + _LOGGER.error('Media ID must be an url (ex: "http://"') + return + await self.hass.async_add_job(self._upnp.set_current_media, media_id) + self._playing = True + # Trying to make stream component work on TV + elif media_type == "application/vnd.apple.mpegurl": + await self.hass.async_add_job(self._upnp.set_current_media, media_id) + self._playing = True + elif media_type == MEDIA_TYPE_BROWSER: + try: + await self.hass.async_add_job(self._ws.open_browser, media_id) + except (ConnectionResetError, AttributeError, BrokenPipeError,websocket._exceptions.WebSocketTimeoutException): + self._ws.close() + else: + _LOGGER.error("Unsupported media type") + return + + async def async_select_source(self, source): + """Select input source.""" + _LOGGER.debug('SamsungTV Trying source:%s',source) + if source in self._source_list: + source_key = self._source_list[ source ] + if "+" in source_key: + all_source_keys = source_key.split("+") + for this_key in all_source_keys: + if this_key.isdigit(): + time.sleep(int(this_key)/1000) + else: + if this_key.startswith("ST_"): + await self.hass.async_add_job(self._smartthings_keys, this_key) + else: + await self.hass.async_add_job(self.send_command, this_key) + elif source_key.startswith("ST_"): + await self.hass.async_add_job(self._smartthings_keys, source_key) + else: + await self.hass.async_add_job(self.send_command, self._source_list[ source ]) + elif source in self._app_list: + source_key = self._app_list[ source ] + await self.hass.async_add_job(self.send_command, source_key, "run_app") + elif source in self._channel_list: + source_key = self._channel_list[ source ] + ch_media_type = MEDIA_TYPE_CHANNEL + if source_key.startswith("http"): ch_media_type = MEDIA_TYPE_URL + await self.hass.async_add_job(self.async_play_media,ch_media_type, source_key) + else: + _LOGGER.error("Unsupported source") + return + self._last_source_time = datetime.now() + self._source = source + +def levenshtein_ratio_and_distance(s, t, ratio_calc = False): + """ levenshtein_ratio_and_distance: + Calculates levenshtein distance between two strings. + If ratio_calc = True, the function computes the + levenshtein distance ratio of similarity between two strings + For all i and j, distance[i,j] will contain the Levenshtein + distance between the first i characters of s and the + first j characters of t + """ + # Initialize matrix of zeros + rows = len(s)+1 + cols = len(t)+1 + distance = np.zeros((rows,cols),dtype = int) + + # Populate matrix of zeros with the indeces of each character of both strings + for i in range(1, rows): + for k in range(1,cols): + distance[i][0] = i + distance[0][k] = k + + # Iterate over the matrix to compute the cost of deletions,insertions and/or substitutions + for col in range(1, cols): + for row in range(1, rows): + if s[row-1] == t[col-1]: + cost = 0 # If the characters are the same in the two strings in a given position [i,j] then the cost is 0 + else: + # In order to align the results with those of the Python Levenshtein package, if we choose to calculate the ratio + # the cost of a substitution is 2. If we calculate just distance, then the cost of a substitution is 1. + if ratio_calc == True: + cost = 2 + else: + cost = 1 + distance[row][col] = min(distance[row-1][col] + 1, # Cost of deletions + distance[row][col-1] + 1, # Cost of insertions + distance[row-1][col-1] + cost) # Cost of substitutions + if ratio_calc == True: + # Computation of the Levenshtein Distance Ratio + Ratio = ((len(s)+len(t)) - distance[row][col]) / (len(s)+len(t)) + return Ratio + else: + # print(distance) # Uncomment if you want to see the matrix showing how the algorithm computes the cost of deletions, + # insertions and/or substitutions + # This is the minimum number of edits needed to convert string a to string b + return "The strings are {} edits away".format(distance[row][col]) diff --git a/custom_components/samsungtv_tizen/shortcuts.py b/custom_components/samsungtv_tizen/shortcuts.py new file mode 100644 index 00000000..91cec215 --- /dev/null +++ b/custom_components/samsungtv_tizen/shortcuts.py @@ -0,0 +1,110 @@ +""" +SamsungTVWS - Samsung Smart TV WS API wrapper + +Copyright (C) 2019 Xchwarze + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1335 USA + +""" + + +class SamsungTVShortcuts: + def __init__(self, remote): + self.remote = remote + + # power + def power(self): + self.remote.send_key('KEY_POWER') + + # menu + def home(self): + self.remote.send_key('KEY_HOME') + + def menu(self): + self.remote.send_key('KEY_MENU') + + def source(self): + self.remote.send_key('KEY_SOURCE') + + def guide(self): + self.remote.send_key('KEY_GUIDE') + + def tools(self): + self.remote.send_key('KEY_TOOLS') + + def info(self): + self.remote.send_key('KEY_INFO') + + # navigation + def up(self): + self.remote.send_key('KEY_UP') + + def down(self): + self.remote.send_key('KEY_DOWN') + + def left(self): + self.remote.send_key('KEY_LEFT') + + def right(self): + self.remote.send_key('KEY_RIGHT') + + def enter(self, count=1): + self.remote.send_key('KEY_ENTER') + + def back(self): + self.remote.send_key('KEY_RETURN') + + # channel + def channel_list(self): + self.remote.send_key('KEY_CH_LIST') + + def channel(self, ch): + for c in str(ch): + self.digit(c) + + self.enter() + + def digit(self, d): + self.remote.send_key('KEY_' + d) + + def channel_up(self): + self.remote.send_key('KEY_CHUP') + + def channel_down(self): + self.remote.send_key('KEY_CHDOWN') + + # volume + def volume_up(self): + self.remote.send_key('KEY_VOLUP') + + def volume_down(self): + self.remote.send_key('KEY_VOLDOWN') + + def mute(self): + self.remote.send_key('KEY_MUTE') + + # extra + def red(self): + self.remote.send_key('KEY_RED') + + def green(self): + self.remote.send_key('KEY_GREEN') + + def yellow(self): + self.remote.send_key('KEY_YELLOW') + + def blue(self): + self.remote.send_key('KEY_BLUE') diff --git a/custom_components/samsungtv_tizen/smartthings.py b/custom_components/samsungtv_tizen/smartthings.py new file mode 100644 index 00000000..97126eb3 --- /dev/null +++ b/custom_components/samsungtv_tizen/smartthings.py @@ -0,0 +1,109 @@ +#Smartthings TV integration# +import requests +from requests import ReadTimeout, ConnectTimeout, HTTPError, Timeout, ConnectionError +import json +import os +from homeassistant.const import ( + STATE_OFF, + STATE_ON, +) +API_BASEURL = "https://api.smartthings.com/v1" +API_DEVICES = API_BASEURL + "/devices/" +COMMAND_POWER_OFF = "{'commands': [{'component': 'main','capability': 'switch','command': 'off'}]}" +COMMAND_POWER_ON = "{'commands': [{'component': 'main','capability': 'switch','command': 'on'}]}" +COMMAND_REFRESH = "{'commands':[{'component': 'main','capability': 'refresh','command': 'refresh'}]}" +COMMAND_PAUSE = "{'commands':[{'component': 'main','capability': 'mediaPlayback','command': 'pause'}]}" +COMMAND_MUTE = "{'commands':[{'component': 'main','capability': 'audioMute','command': 'mute'}]}" +COMMAND_UNMUTE = "{'commands':[{'component': 'main','capability': 'audioMute','command': 'unmute'}]}" +COMMAND_PLAY = "{'commands':[{'component': 'main','capability': 'mediaPlayback','command': 'play'}]}" +COMMAND_STOP = "{'commands':[{'component': 'main','capability': 'mediaPlayback','command': 'stop'}]}" +COMMAND_REWIND = "{'commands':[{'component': 'main','capability': 'mediaPlayback','command': 'rewind'}]}" +COMMAND_FAST_FORWARD = "{'commands':[{'component': 'main','capability': 'mediaPlayback','command': 'fastForward'}]}" + +class smartthingstv: + + def __init__(self): + self._cloud_state = STATE_OFF + self._cloud_muted = False + self._cloud_volume = 10 + + + def device_update(self): + API_KEY = self._api_key + REQUEST_HEADERS = {"Authorization": "Bearer " + API_KEY} + DEVICE_ID = self._device_id + API_DEVICE = API_DEVICES + DEVICE_ID + API_DEVICE_STATUS = API_DEVICE + "/states" + API_COMMAND = API_DEVICE + "/commands" + cmdurl = requests.post(API_COMMAND,data=COMMAND_REFRESH ,headers=REQUEST_HEADERS) + resp = requests.get(API_DEVICE_STATUS,headers=REQUEST_HEADERS) + data = resp.json() + device_volume = data['main']['volume']['value'] + device_volume = int(device_volume) / 100 + device_state = data['main']['switch']['value'] + device_source = data['main']['inputSource']['value'] + device_all_sources = json.loads(data['main']['supportedInputSources']['value']) + device_tv_chan = data['main']['tvChannel']['value'] + device_tv_chan_name = data['main']['tvChannelName']['value'] + device_muted = data['main']['mute']['value'] + self._cloud_state = device_state + if device_state == "off": + self._cloud_state = STATE_OFF + else: + self._cloud_state = STATE_ON + self._cloud_volume = device_volume + self._cloud_source_list = device_all_sources + if device_muted == "mute": + self._cloud_muted = True + else: + self._cloud_muted = False + self._cloud_source = device_source + self._cloud_channel = device_tv_chan + self._cloud_channel_name = device_tv_chan_name + + def send_command(self, command, cmdtype): + API_KEY = self._api_key + REQUEST_HEADERS = {"Authorization": "Bearer " + API_KEY} + DEVICE_ID = self._device_id + API_DEVICES = API_BASEURL + "/devices/" + API_DEVICE = API_DEVICES + DEVICE_ID + API_COMMAND = API_DEVICE + "/commands" + + if cmdtype == "setvolume": # sets volume + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'audioVolume','command': 'setVolume','arguments': " + API_COMMAND_ARG = "[{}]}}]}}".format(command) + API_FULL = API_COMMAND_DATA + API_COMMAND_ARG + cmdurl = requests.post(API_COMMAND,data=API_FULL ,headers=REQUEST_HEADERS) + elif cmdtype == "stepvolume": # steps volume up or down + if command == "up": + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'audioVolume','command': 'volumeUp'}]}" + cmdurl = requests.post(API_COMMAND,data=API_COMMAND_DATA ,headers=REQUEST_HEADERS) + else: + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'audioVolume','command': 'volumeDown'}]}" + cmdurl = requests.post(API_COMMAND,data=API_COMMAND_DATA ,headers=REQUEST_HEADERS) + elif cmdtype == "audiomute": # mutes audio + if command == "on": + cmdurl = requests.post(API_COMMAND,data=COMMAND_MUTE ,headers=REQUEST_HEADERS) + elif command == "off": + cmdurl = requests.post(API_COMMAND,data=COMMAND_UNMUTE ,headers=REQUEST_HEADERS) + elif cmdtype == "turn_off": # turns off + cmdurl = requests.post(API_COMMAND,data=COMMAND_POWER_OFF ,headers=REQUEST_HEADERS) + elif cmdtype == "turn_on": # turns on + cmdurl = requests.post(API_COMMAND,data=COMMAND_POWER_ON ,headers=REQUEST_HEADERS) + elif cmdtype == "selectsource": #changes source + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'mediaInputSource','command': 'setInputSource', 'arguments': " + API_COMMAND_ARG = "['{}']}}]}}".format(command) + API_FULL = API_COMMAND_DATA + API_COMMAND_ARG + cmdurl = requests.post(API_COMMAND,data=API_FULL ,headers=REQUEST_HEADERS) + elif cmdtype == "selectchannel": #changes channel + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'tvChannel','command': 'setTvChannel', 'arguments': " + API_COMMAND_ARG = "['{}']}}]}}".format(command) + API_FULL = API_COMMAND_DATA + API_COMMAND_ARG + cmdurl = requests.post(API_COMMAND,data=API_FULL ,headers=REQUEST_HEADERS) + elif cmdtype == "stepchannel": # steps channel up or down + if command == "up": + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'tvChannel','command': 'channelUp'}]}" + cmdurl = requests.post(API_COMMAND,data=API_COMMAND_DATA ,headers=REQUEST_HEADERS) + else: + API_COMMAND_DATA = "{'commands':[{'component': 'main','capability': 'tvChannel','command': 'channelDown'}]}" + cmdurl = requests.post(API_COMMAND,data=API_COMMAND_DATA ,headers=REQUEST_HEADERS) diff --git a/custom_components/samsungtv_tizen/upnp.py b/custom_components/samsungtv_tizen/upnp.py new file mode 100644 index 00000000..1a27ca64 --- /dev/null +++ b/custom_components/samsungtv_tizen/upnp.py @@ -0,0 +1,74 @@ +#Smartthings TV integration# +import requests +import xml.etree.ElementTree as ET + +class upnp: + + def __init__(self, host): + self.host = host + self.mute = False + self.volume = 0 + + def __enter__(self): + return self + + def SOAPrequest(self, action, arguments, protocole): + headers = {'SOAPAction': '"urn:schemas-upnp-org:service:{protocole}:1#{action}"'.format(action=action, protocole=protocole), 'content-type': 'text/xml'} + body = """ + + + + 0 + {arguments} + + + """.format(action=action, arguments=arguments, protocole=protocole) + response = None + try: + response = requests.post("http://{host}:9197/upnp/control/{protocole}1".format(host=self.host, protocole=protocole), data=body, headers=headers, timeout=0.1) + response = response.content + except: + pass + return response + + def get_volume(self): + response = self.SOAPrequest('GetVolume', "Master", 'RenderingControl') + if response is not None: + volume_xml = response.decode('utf8') + tree = ET.fromstring(volume_xml) + for elem in tree.iter(tag='CurrentVolume'): + self.volume = elem.text + return self.volume + + def set_volume(self, volume): + self.SOAPrequest('SetVolume', "Master{}".format(volume), 'RenderingControl') + + def get_mute(self): + response = self.SOAPrequest('GetMute', "Master", 'RenderingControl') + if response is not None: + # mute_xml = response.decode('utf8') + tree = ET.fromstring(response.decode('utf8')) + mute = 0 + for elem in tree.iter(tag='CurrentMute'): + mute = elem.text + if (int(mute) == 0): + self.mute = False + else: + self.mute = True + return self.mute + + def set_current_media(self, url): + """ Set media to playback and play it.""" + try: + self.SOAPrequest('SetAVTransportURI', "{url}".format(url=url), 'AVTransport') + self.SOAPrequest('Play', "1", 'AVTransport') + except Exception: + pass + + def play(self): + """ Play media that was already set as current.""" + try: + self.SOAPrequest('Play', "1", 'AVTransport') + except Exception: + pass + diff --git a/custom_components/samsungtv_tizen/websockets.py b/custom_components/samsungtv_tizen/websockets.py new file mode 100644 index 00000000..072590c7 --- /dev/null +++ b/custom_components/samsungtv_tizen/websockets.py @@ -0,0 +1,284 @@ +""" +SamsungTVWS - Samsung Smart TV WS API wrapper + +Copyright (C) 2019 Xchwarze + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1335 USA + +""" +import base64 +import json +import logging +import time +import ssl +import websocket +import requests +from . import exceptions +from . import shortcuts + +_LOGGING = logging.getLogger(__name__) + + +class SamsungTVWS: + _URL_FORMAT = 'ws://{host}:{port}/api/v2/channels/samsung.remote.control?name={name}' + _SSL_URL_FORMAT = 'wss://{host}:{port}/api/v2/channels/samsung.remote.control?name={name}&token={token}' + _REST_URL_FORMAT = 'http://{host}:8001/api/v2/{append}' + + def __init__(self, host, token=None, token_file=None, port=8001, timeout=None, key_press_delay=1, + name='SamsungTvRemote', app_list=None): + self.host = host + self.token = token + self.token_file = token_file + self._app_list = app_list + self.port = port + self.timeout = None if timeout == 0 else timeout + self.key_press_delay = key_press_delay + self.name = name + self.connection = None + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def _serialize_string(self, string): + if isinstance(string, str): + string = str.encode(string) + + return base64.b64encode(string).decode('utf-8') + + def _is_ssl_connection(self): + return self.port == 8002 + + def _format_websocket_url(self, is_ssl=False): + params = { + 'host': self.host, + 'port': self.port, + 'name': self._serialize_string(self.name), + 'token': self._get_token(), + } + + if is_ssl: + return self._SSL_URL_FORMAT.format(**params) + else: + return self._URL_FORMAT.format(**params) + + def _format_rest_url(self, append=''): + params = { + 'host': self.host, + 'append': append, + } + + return self._REST_URL_FORMAT.format(**params) + + def _get_token(self): + if self.token_file is not None: + try: + with open(self.token_file, 'r') as token_file: + return token_file.readline() + except: + return '' + else: + return self.token + + def _set_token(self, token): + _LOGGING.info('New token %s', token) + if self.token_file is not None: + _LOGGING.debug('Save token to file', token) + with open(self.token_file, 'w') as token_file: + token_file.write(token) + else: + self.token = token + + def _ws_send(self, command, key_press_delay=None): + if self.connection is None: + self.open() + + payload = json.dumps(command) + self.connection.send(payload) + + if key_press_delay is None: + time.sleep(self.key_press_delay) + else: + time.sleep(key_press_delay) + + def _rest_request(self, target, method='GET'): + url = self._format_rest_url(target) + try: + if method == 'POST': + return requests.post(url, timeout=self.timeout) + elif method == 'PUT': + return requests.put(url, timeout=self.timeout) + elif method == 'DELETE': + return requests.delete(url, timeout=self.timeout) + else: + return requests.get(url, timeout=self.timeout) + except requests.ConnectionError: + raise exceptions.HttpApiError('TV unreachable or feature not supported on this model.') + + def _process_api_response(self, response): + try: + return json.loads(response) + except json.JSONDecodeError: + _LOGGING.debug('Failed to parse response from TV. response text: %s', response) + raise exceptions.ResponseError('Failed to parse response from TV. Maybe feature not supported on this model') + + def open(self): + is_ssl = self._is_ssl_connection() + url = self._format_websocket_url(is_ssl) + sslopt = {'cert_reqs': ssl.CERT_NONE} if is_ssl else {} + + _LOGGING.debug('WS url %s', url) + self.connection = websocket.create_connection( + url, + self.timeout, + sslopt=sslopt + ) + + completed = False + + try: + response = self._process_api_response(self.connection.recv()) + except: + response = False + + if response and response.get("event", "") == "ms.channel.connect": + conn_data = response.get("data") + completed = True + token = conn_data.get("token") + if token: + _LOGGING.debug("Got token %s", token) + self._set_token(token) + + if not completed: + # For correct auth + self.timeout = 45 + self.close() + raise exceptions.ConnectionFailure(response) + + def close(self): + if self.connection: + self.connection.close() + + self.connection = None + _LOGGING.debug('Connection closed.') + + def send_key(self, key, key_press_delay=None, cmd='Click'): + _LOGGING.debug('Sending key %s', key) + self._ws_send( + { + 'method': 'ms.remote.control', + 'params': { + 'Cmd': cmd, + 'DataOfCmd': key, + 'Option': 'false', + 'TypeOfRemote': 'SendRemoteKey' + } + }, + key_press_delay + ) + + def hold_key(self, key, seconds): + self.send_key(key, cmd='Press') + time.sleep(seconds) + self.send_key(key, cmd='Release') + + def move_cursor(self, x, y, duration=0): + self._ws_send( + { + 'method': 'ms.remote.control', + 'params': { + 'Cmd': 'Move', + 'Position': { + 'x': x, + 'y': y, + 'Time': str(duration) + }, + 'TypeOfRemote': 'ProcessMouseDevice' + } + }, + key_press_delay=0 + ) + + def run_app(self, app_id, app_type='DEEP_LINK', meta_tag=''): + _LOGGING.debug('Sending run app app_id: %s app_type: %s meta_tag: %s', app_id, app_type, meta_tag) + self._ws_send({ + 'method': 'ms.channel.emit', + 'params': { + 'event': 'ed.apps.launch', + 'to': 'host', + 'data': { + # action_type: NATIVE_LAUNCH / DEEP_LINK + # app_type == 2 ? 'DEEP_LINK' : 'NATIVE_LAUNCH', + 'action_type': app_type, + 'appId': app_id, + 'metaTag': meta_tag + } + } + }) + + def open_browser(self, url): + _LOGGING.debug('Opening url in browser %s', url) + self.run_app( + 'org.tizen.browser', + 'NATIVE_LAUNCH', + url + ) + + def app_list(self): + _LOGGING.debug('Get app list') + self._ws_send({ + 'method': 'ms.channel.emit', + 'params': { + 'event': 'ed.installedApp.get', + 'to': 'host' + } + }) + + response = self._process_api_response(self.connection.recv()) + if response.get('data') and response.get('data').get('data'): + return response.get('data').get('data') + else: + return response + + def rest_device_info(self): + _LOGGING.debug('Get device info via rest api') + response = self._rest_request('') + return self._process_api_response(response.text) + + def rest_app_status(self, app_id): + _LOGGING.debug('Get app %s status via rest api', app_id) + response = self._rest_request('applications/' + app_id) + return self._process_api_response(response.text) + + def rest_app_run(self, app_id): + _LOGGING.debug('Run app %s via rest api', app_id) + response = self._rest_request('applications/' + app_id, 'POST') + return self._process_api_response(response.text) + + def rest_app_close(self, app_id): + _LOGGING.debug('Close app %s via rest api', app_id) + response = self._rest_request('applications/' + app_id, 'DELETE') + return self._process_api_response(response.text) + + def rest_app_install(self, app_id): + _LOGGING.debug('Install app %s via rest api', app_id) + response = self._rest_request('applications/' + app_id, 'PUT') + return self._process_api_response(response.text) + + def shortcuts(self): + return shortcuts.SamsungTVShortcuts(self) diff --git a/include/automation.yaml b/include/automation.yaml index f5de5a21..647e319a 100644 --- a/include/automation.yaml +++ b/include/automation.yaml @@ -28,7 +28,7 @@ automation: - conditions: - condition: state entity_id: - ['media_player.sony_bravia', 'media_player.samsung', + ['media_player.sony_bravia', 'media_player.samsung_tv_remote', 'media_player.google_nest_mini'] state: 'off' sequence: @@ -550,7 +550,7 @@ automation: trigger: - platform: state entity_id: - ['media_player.sony_bravia', 'media_player.samsung', 'switch.computer_imac', + ['media_player.sony_bravia', 'media_player.samsung_tv_remote', 'switch.computer_imac', 'switch.playstation_4', 'fan.sovrum_anslut', 'switch.air_purifier'] action: - service: input_boolean.turn_off @@ -563,7 +563,7 @@ automation: trigger: - platform: state entity_id: - ['input_boolean.sony_bravia', 'input_boolean.samsung', 'input_boolean.computer_imac', + ['input_boolean.sony_bravia', 'input_boolean.samsung_tv_remote', 'input_boolean.computer_imac', 'input_boolean.playstation_4', 'input_boolean.sovrum_anslut', 'input_boolean.air_purifier'] to: 'on' for: @@ -600,7 +600,7 @@ automation: action: - service: media_player.select_source data: - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote source: > {{ states(trigger.entity_id) }} @@ -634,7 +634,7 @@ automation: domain: media_player service: turn_on service_data: - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote action: - service: media_player.turn_on data: @@ -806,7 +806,7 @@ automation: is_state('media_player.google_nest_mini', 'off') or is_state('media_player.sony_bravia', 'off') and - is_state('media_player.samsung', 'off') and + is_state('media_player.samsung_tv_remote', 'off') and is_state('media_player.google_nest_mini', 'off') }} action: - service: input_select.select_option diff --git a/include/customize.yaml b/include/customize.yaml index fe949153..1f37889c 100644 --- a/include/customize.yaml +++ b/include/customize.yaml @@ -87,7 +87,7 @@ homeassistant: device_class: tv source_list: ['HDMI 1', 'HDMI 2/MHL', 'HDMI 3', 'HDMI 4'] - media_player.samsung: + media_player.samsung_tv_remote: friendly_name: "Tv\u00B2" device_class: tv source_list: ['TV', 'HDMI'] diff --git a/include/input.yaml b/include/input.yaml index 382c7801..eccf7614 100644 --- a/include/input.yaml +++ b/include/input.yaml @@ -11,7 +11,7 @@ input_boolean: initial: off sony_bravia: initial: off - samsung: + samsung_tv_remote: initial: off playstation_4: initial: off diff --git a/include/script.yaml b/include/script.yaml index b2b606b3..ad2d9b55 100644 --- a/include/script.yaml +++ b/include/script.yaml @@ -194,7 +194,7 @@ script: - choose: - conditions: - condition: state - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote state: 'on' sequence: - service: switch.turn_off diff --git a/include/switch.yaml b/include/switch.yaml index a40e3c94..d9489888 100644 --- a/include/switch.yaml +++ b/include/switch.yaml @@ -108,19 +108,19 @@ switch: tv_samsung: friendly_name: "Tv\u00B2" icon_template: custom:tv - value_template: "{{ is_state('media_player.samsung', 'on') }}" + value_template: "{{ is_state('media_player.samsung_tv_remote', 'on') }}" turn_on: - service: input_boolean.turn_on - entity_id: input_boolean.samsung + entity_id: input_boolean.samsung_tv_remote - service: remote.send_command data: entity_id: remote.sovrum command: menu turn_off: - service: input_boolean.turn_on - entity_id: input_boolean.samsung + entity_id: input_boolean.samsung_tv_remote - service: media_player.turn_off - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote playstation_4: friendly_name: Playstation diff --git a/popup/sovrum_tv2.yaml b/popup/sovrum_tv2.yaml index 3d2a3d7c..26198c4d 100644 --- a/popup/sovrum_tv2.yaml +++ b/popup/sovrum_tv2.yaml @@ -27,7 +27,7 @@ cards: - type: custom:button-card - entity: media_player.samsung + entity: media_player.samsung_tv_remote icon: mdi:volume-mute show_name: false tap_action: @@ -47,7 +47,7 @@ action: call-service service: media_player.volume_down service_data: - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote template: icon_action - type: custom:button-card @@ -56,6 +56,6 @@ action: call-service service: media_player.volume_up service_data: - entity_id: media_player.samsung + entity_id: media_player.samsung_tv_remote template: icon_action diff --git a/ui-lovelace.yaml b/ui-lovelace.yaml index 63516aea..3acfffe8 100755 --- a/ui-lovelace.yaml +++ b/ui-lovelace.yaml @@ -5,11 +5,6 @@ # # ########################################################################## -preload_cards: - [map, iframe, markdown] -preload_rows: - [input-select-entity] - anchors: ⚓₁: &title entity: sensor.placeholder @@ -86,7 +81,7 @@ views: hold_action: action: none style: - {top: 50%, left: 10.6%, width: 21.5%, pointer-events: none, border-right: '1.5px solid rgba(58,69,73,0.2)'} + {top: 49.24%, left: 10.6%, width: 21.5%, pointer-events: none, border-right: '1.5px solid rgba(58,69,73,0.2)'} ################################################# # # @@ -359,7 +354,7 @@ views: if (entity.state === 'on') { hass.callService('input_boolean', 'turn_on', {entity_id: entity.entity_id.replace(entity.entity_id.split('.')[0], 'input_boolean')}); hass.callService('media_player', 'turn_off', {entity_id: entity.entity_id}); - hass.callService('media_player', 'turn_off', {entity_id: entity.entity_id.replace('sony_bravia', 'vardagsrum').replace('samsung', 'sovrum')}); } ]]] + hass.callService('media_player', 'turn_off', {entity_id: entity.entity_id.replace('sony_bravia', 'vardagsrum').replace('samsung_tv_remote', 'sovrum')}); } ]]] hold_action: !include popup/vardagsrum_tv.yaml custom_fields: icon_tv: &icon_tv > @@ -640,9 +635,9 @@ views: ################################################# - type: custom:button-card - entity: media_player.samsung + entity: media_player.samsung_tv_remote triggers_update: - ['media_player.samsung', 'input_boolean.samsung'] + ['media_player.samsung_tv_remote', 'input_boolean.samsung_tv_remote'] style: top: 37.9% left: 91.05%