Compare commits

..

No commits in common. "f12ef19d514c7b7c3274933f13942d4396a602f1" and "00000d98382cdaaf49e488aab892b786bb970dcc" have entirely different histories.

28 changed files with 87747 additions and 83165 deletions

166199
EPG/TV.xml

File diff suppressed because one or more lines are too long

View file

@ -22,7 +22,7 @@ epg_urls = [
]
client = httpx.AsyncClient(
timeout=httpx.Timeout(5.0),
timeout=5,
follow_redirects=True,
http2=True,
headers={

File diff suppressed because it is too large Load diff

View file

@ -7,16 +7,16 @@ http://fl1.moveonjoy.com/ANE/index.m3u8
https://fl1.moveonjoy.com/FL_Tampa_ABC/index.m3u8
#EXTINF:-1 tvg-chno="3" tvg-id="ACC.Network.us2" tvg-name="ACC Network" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s111871_dark_360w_270h.png" group-title="TV",ACC Network
http://cord-cutter.net:8080/k4Svp2/645504/9273
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/9273
#EXTINF:-1 tvg-chno="4" tvg-id="AdultSwim.com.Cartoon.Network.us2" tvg-name="Adult Swim" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16496_dark_360w_270h.png" group-title="TV",Adult Swim
https://turnerlive.warnermediacdn.com/hls/live/2023183/aseast/noslate/VIDEO_1_5128000.m3u8
#EXTINF:-1 tvg-chno="5" tvg-id="Altitude.Sports.us2" tvg-name="Altitude Sports" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s44263_dark_360w_270h.png" group-title="TV",Altitude Sports
http://cord-cutter.net:8080/k4Svp2/645504/79545
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/79545
#EXTINF:-1 tvg-chno="6" tvg-id="AMC.HD.us2" tvg-name="AMC" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10021_dark_360w_270h.png" group-title="TV",AMC
http://cord-cutter.net:8080/k4Svp2/645504/18925
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/18925
#EXTINF:-1 tvg-chno="7" tvg-id="Animal.Planet.HD.us2" tvg-name="Animal Planet" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16331_dark_360w_270h.png" group-title="TV",Animal Planet
http://fl1.moveonjoy.com/Animal_Planet/index.m3u8
@ -28,25 +28,25 @@ http://fl1.moveonjoy.com/Aspire/index.m3u8
http://stalker.klma2023.net/play/live.php?mac=00:1B:79:F8:59:0E&stream=1163984&extension=ts
#EXTINF:-1 tvg-chno="10" tvg-id="BBC.America.HD.us2" tvg-name="BBC America" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s64492_dark_360w_270h.png" group-title="TV",BBC America
http://cord-cutter.net:8080/k4Svp2/645504/20194
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20194
#EXTINF:-1 tvg-chno="11" tvg-id="BBC.News.(North.America).HD.us2" tvg-name="BBC World News" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s89542_dark_360w_270h.png" group-title="TV",BBC World News
http://cord-cutter.net:8080/k4Svp2/645504/139752
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/139752
#EXTINF:-1 tvg-chno="12" tvg-id="BET.HD.us2" tvg-name="BET" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10051_dark_360w_270h.png" group-title="TV",BET
http://fl1.moveonjoy.com/BET_EAST/index.m3u8
#EXTINF:-1 tvg-chno="13" tvg-id="Big.Ten.Network.HD.us2" tvg-name="Big Ten Network" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s56783_dark_360w_270h.png" group-title="TV",Big Ten Network
http://cord-cutter.net:8080/k4Svp2/645504/9828
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/9828
#EXTINF:-1 tvg-chno="14" tvg-id="Bloomberg.HD.us2" tvg-name="Bloomberg TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s71799_dark_360w_270h.png" group-title="TV",Bloomberg TV
http://cord-cutter.net:8080/k4Svp2/645504/15158
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/15158
#EXTINF:-1 tvg-chno="15" tvg-id="Boomerang.us2" tvg-name="Boomerang" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s21883_dark_360w_270h.png" group-title="TV",Boomerang
http://cord-cutter.net:8080/k4Svp2/645504/14741
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/14741
#EXTINF:-1 tvg-chno="16" tvg-id="Bounce.TV.us2" tvg-name="Bounce TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s73067_dark_360w_270h.png" group-title="TV",Bounce TV
http://cord-cutter.net:8080/k4Svp2/645504/48323
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/48323
#EXTINF:-1 tvg-chno="17" tvg-id="Bravo.HD.us2" tvg-name="Bravo TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10057_dark_360w_270h.png" group-title="TV",Bravo TV
http://fl1.moveonjoy.com/BRAVO/index.m3u8
@ -58,16 +58,16 @@ https://buzzrota-web.amagi.tv/playlist.m3u8
http://fl1.moveonjoy.com/C-SPAN/index.m3u8
#EXTINF:-1 tvg-chno="20" tvg-id="Cartoon.Network.HD.us2" tvg-name="Cartoon Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12131_dark_360w_270h.png" group-title="TV",Cartoon Network
http://cord-cutter.net:8080/k4Svp2/645504/46708
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46708
#EXTINF:-1 tvg-chno="21" tvg-id="WCBS-DT.us_locals1" tvg-name="CBS" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10098_dark_360w_270h.png" group-title="TV",CBS
http://cord-cutter.net:8080/k4Svp2/645504/120749
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/120749
#EXTINF:-1 tvg-chno="22" tvg-id="plex.tv.CBS.Sports.Golazo.Network.plex" tvg-name="CBS Sports Golazo Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s133691_dark_360w_270h.png" group-title="TV",CBS Sports Golazo Network
https://dai.google.com/linear/hls/event/GxrCGmwST0ixsrc_QgB6qw/master.m3u8
#EXTINF:-1 tvg-chno="23" tvg-id="CBS.Sports.Network.HD.us2" tvg-name="CBS Sports Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16365_dark_360w_270h.png" group-title="TV",CBS Sports Network
http://cord-cutter.net:8080/k4Svp2/645504/10454
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10454
#EXTINF:-1 tvg-chno="24" tvg-id="CMT.HD.us2" tvg-name="CMT" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10138_dark_360w_270h.png" group-title="TV",CMT
https://fl1.moveonjoy.com/CMT/index.m3u8
@ -79,34 +79,34 @@ https://fl1.moveonjoy.com/CNBC/index.m3u8
https://turnerlive.warnermediacdn.com/hls/live/586495/cnngo/cnn_slate/VIDEO_0_3564000.m3u8
#EXTINF:-1 tvg-chno="27" tvg-id="Comedy.Central.HD.us2" tvg-name="Comedy Central" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10149_dark_360w_270h.png" group-title="TV",Comedy Central
http://cord-cutter.net:8080/k4Svp2/645504/7466
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/7466
#EXTINF:-1 tvg-chno="28" tvg-id="Comedy.TV.HD.us2" tvg-name="Comedy TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s82470_dark_360w_270h.png" group-title="TV",Comedy TV
https://fl1.moveonjoy.com/Comedy_TV/index.m3u8
#EXTINF:-1 tvg-chno="29" tvg-id="Comet.us2" tvg-name="Comet TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s97051_dark_360w_270h.png" group-title="TV",Comet TV
http://cord-cutter.net:8080/k4Svp2/645504/125831
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/125831
#EXTINF:-1 tvg-chno="30" tvg-id="Cooking.Channel.HD.us2" tvg-name="Cooking Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s30156_dark_360w_270h.png" group-title="TV",Cooking Channel
https://fl1.moveonjoy.com/COOKING_CHANNEL/index.m3u8
#EXTINF:-1 tvg-chno="31" tvg-id="Court.TV.us2" tvg-name="Court TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s117160_dark_360w_270h.png" group-title="TV",Court TV
http://cord-cutter.net:8080/k4Svp2/645504/21092
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/21092
#EXTINF:-1 tvg-chno="32" tvg-id="COZI.TV.us2" tvg-name="Cozi TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s78851_dark_360w_270h.png" group-title="TV",Cozi TV
http://cord-cutter.net:8080/k4Svp2/645504/11868
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/11868
#EXTINF:-1 tvg-chno="33" tvg-id="Crime.and.Investigation.Network.HD.us2" tvg-name="Crime & Investigation Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s61469_dark_360w_270h.png" group-title="TV",Crime & Investigation Network
https://fl1.moveonjoy.com/Crime_and_Investigation_Network/index.m3u8
#EXTINF:-1 tvg-chno="34" tvg-id="WKCF-DT.us_locals1" tvg-name="CW" tvg-logo="https://i.gyazo.com/afd5b481b327d204087dfde6a7741f9d.png" group-title="TV",CW
http://cord-cutter.net:8080/k4Svp2/645504/120893
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/120893
#EXTINF:-1 tvg-chno="35" tvg-id="Discovery.Channel.HD.us2" tvg-name="Discovery Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11150_dark_360w_270h.png" group-title="TV",Discovery Channel
http://cord-cutter.net:8080/k4Svp2/645504/46720
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46720
#EXTINF:-1 tvg-chno="36" tvg-id="Discovery.Family.Channel.HD.us2" tvg-name="Discovery Family Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16618_dark_360w_270h.png" group-title="TV",Discovery Family Channel
http://cord-cutter.net:8080/k4Svp2/645504/10538
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10538
#EXTINF:-1 tvg-chno="37" tvg-id="Discovery.Life.Channel.us2" tvg-name="Discovery Life" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16125_dark_360w_270h.png" group-title="TV",Discovery Life
https://fl1.moveonjoy.com/DISCOVERY_LIFE/index.m3u8
@ -115,106 +115,106 @@ https://fl1.moveonjoy.com/DISCOVERY_LIFE/index.m3u8
https://fl1.moveonjoy.com/Discovery_Science/index.m3u8
#EXTINF:-1 tvg-chno="39" tvg-id="Disney.Channel.HD.us2" tvg-name="Disney" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10171_dark_360w_270h.png" group-title="TV",Disney
http://cord-cutter.net:8080/k4Svp2/645504/2206
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/2206
#EXTINF:-1 tvg-chno="40" tvg-id="Disney.XD.HD.us2" tvg-name="Disney XD" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s18279_dark_360w_270h.png" group-title="TV",Disney XD
http://cord-cutter.net:8080/k4Svp2/645504/75621
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/75621
#EXTINF:-1 tvg-chno="41" tvg-id="E!.Entertainment.Television.HD.us2" tvg-name="E! Entertainment" tvg-logo="https://i.gyazo.com/f73b80e3eb56cec06df6705d00e2f422.png" group-title="TV",E! Entertainment
http://fl1.moveonjoy.com/E_ENTERTAINMENT_TELEVISION/index.m3u8
#EXTINF:-1 tvg-chno="42" tvg-id="ESPN.HD.us2" tvg-name="ESPN" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10179_dark_360w_270h.png" group-title="TV",ESPN
http://cord-cutter.net:8080/k4Svp2/645504/14197
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/14197
#EXTINF:-1 tvg-chno="43" tvg-id="ESPNEWS.HD.us2" tvg-name="ESPN News" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16485_dark_360w_270h.png" group-title="TV",ESPN News
http://cord-cutter.net:8080/k4Svp2/645504/17707
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/17707
#EXTINF:-1 tvg-chno="44" tvg-id="ESPNU.HD.us2" tvg-name="ESPN U" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s45654_dark_360w_270h.png" group-title="TV",ESPN U
http://cord-cutter.net:8080/k4Svp2/645504/10255
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10255
#EXTINF:-1 tvg-chno="45" tvg-id="ESPN2.HD.us2" tvg-name="ESPN2" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12444_dark_360w_270h.png" group-title="TV",ESPN2
http://cord-cutter.net:8080/k4Svp2/645504/2210
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/2210
#EXTINF:-1 tvg-chno="46" tvg-id="FanDuel.Sports.Network.Detroit.24/7.HDTV.us" tvg-name="FDSN Detroit" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s54286_dark_360w_270h.png" group-title="TV",FDSN Detroit
http://cord-cutter.net:8080/k4Svp2/645504/20936
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20936
#EXTINF:-1 tvg-chno="47" tvg-id="FanDuel.Sports.Network.Florida.HDTV.(Out.of.Market).us" tvg-name="FDSN Florida" tvg-logo="https://i.gyazo.com/fad701fbaaafe161b13b23ed9b50179b.png" group-title="TV",FDSN Florida
http://cord-cutter.net:8080/k4Svp2/645504/46794
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46794
#EXTINF:-1 tvg-chno="48" tvg-id="FanDuel.Sports.Network.Midwest.24/7.HDTV.us" tvg-name="FDSN Midwest" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11058_dark_360w_270h.png" group-title="TV",FDSN Midwest
http://cord-cutter.net:8080/k4Svp2/645504/66795
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/66795
#EXTINF:-1 tvg-chno="49" tvg-id="FanDuel.Sports.Network.North.HDTV.us" tvg-name="FDSN North" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10977_dark_360w_270h.png" group-title="TV",FDSN North
http://cord-cutter.net:8080/k4Svp2/645504/58827
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/58827
#EXTINF:-1 tvg-chno="50" tvg-id="FanDuel.Sports.Network.Ohio.(Cleveland).HDTV.us" tvg-name="FDSN Ohio" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s49691_dark_360w_270h.png" group-title="TV",FDSN Ohio
http://cord-cutter.net:8080/k4Svp2/645504/17752
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/17752
#EXTINF:-1 tvg-chno="51" tvg-id="FanDuel.Sports.Network.Oklahoma.24/7.HDTV.(Tulsa).us" tvg-name="FDSN Oklahoma" tvg-logo="https://i.gyazo.com/80ad6fd142cd67f06eef58d9ce5aa72b.png" group-title="TV",FDSN Oklahoma
http://cord-cutter.net:8080/k4Svp2/645504/20934
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20934
#EXTINF:-1 tvg-chno="52" tvg-id="FanDuel.Sports.Network.SoCal.HDTV.us" tvg-name="FDSN SoCal" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16743_dark_360w_270h.png" group-title="TV",FDSN SoCal
http://cord-cutter.net:8080/k4Svp2/645504/221151
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/221151
#EXTINF:-1 tvg-chno="53" tvg-id="FanDuel.Sports.Network.Southeast.HDTV.(Mont./Birm./Dothan/Mobile.AL).us" tvg-name="FDSN Southeast" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s20789_dark_360w_270h.png" group-title="TV",FDSN Southeast
http://cord-cutter.net:8080/k4Svp2/645504/81111
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/81111
#EXTINF:-1 tvg-chno="54" tvg-id="FanDuel.Sports.Network.Southwest.HDTV.24/7.(Main).us" tvg-name="FDSN Southwest" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s59629_dark_360w_270h.png" group-title="TV",FDSN Southwest
http://cord-cutter.net:8080/k4Svp2/645504/21843
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/21843
#EXTINF:-1 tvg-chno="55" tvg-id="FanDuel.Sports.Network.Sun.South.24/7.HDTV.(South.Marlins,.Rays,.Heat).us" tvg-name="FDSN Sun" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s61084_dark_360w_270h.png" group-title="TV",FDSN Sun
http://cord-cutter.net:8080/k4Svp2/645504/104917
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/104917
#EXTINF:-1 tvg-chno="56" tvg-id="FanDuel.Sports.Network.West.HDTV.us" tvg-name="FDSN West" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s59627_dark_360w_270h.png" group-title="TV",FDSN West
http://cord-cutter.net:8080/k4Svp2/645504/20932
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20932
#EXTINF:-1 tvg-chno="57" tvg-id="FanDuel.Sports.Network.Wisconsin.24/7.HDTV.us" tvg-name="FDSN Wisconsin" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16348_dark_360w_270h.png" group-title="TV",FDSN Wisconsin
http://cord-cutter.net:8080/k4Svp2/645504/78599
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/78599
#EXTINF:-1 tvg-chno="58" tvg-id="plex.tv.FIFA+.plex" tvg-name="FIFA+ TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s136235_dark_360w_270h.png" group-title="TV",FIFA+ TV
https://jmp2.uk/stvp-IN270000230
#EXTINF:-1 tvg-chno="59" tvg-id="Food.Network.HD.us2" tvg-name="Food Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s44718_dark_360w_270h.png" group-title="TV",Food Network
http://cord-cutter.net:8080/k4Svp2/645504/7323
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/7323
#EXTINF:-1 tvg-chno="60" tvg-id="WFLX-DT.us_locals1" tvg-name="Fox" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s28719_dark_360w_270h.png" group-title="TV",Fox
http://cord-cutter.net:8080/k4Svp2/645504/121595
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/121595
#EXTINF:-1 tvg-chno="61" tvg-id="Fox.Business.HD.us2" tvg-name="Fox Business" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s58649_dark_360w_270h.png" group-title="TV",Fox Business
http://cord-cutter.net:8080/k4Svp2/645504/17639
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/17639
#EXTINF:-1 tvg-chno="62" tvg-id="Fox.News.Channel.HD.us2" tvg-name="Fox News" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16374_dark_360w_270h.png" group-title="TV",Fox News
http://cord-cutter.net:8080/k4Svp2/645504/1818
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/1818
#EXTINF:-1 tvg-chno="63" tvg-id="FS1.Fox.Sports.1.HD.us2" tvg-name="Fox Sports 1" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s82541_dark_360w_270h.png" group-title="TV",Fox Sports 1
http://cord-cutter.net:8080/k4Svp2/645504/1846
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/1846
#EXTINF:-1 tvg-chno="64" tvg-id="FS2.Fox.Sports.2.HD.us2" tvg-name="Fox Sports 2" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s33178_dark_360w_270h.png" group-title="TV",Fox Sports 2
http://cord-cutter.net:8080/k4Svp2/645504/1847
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/1847
#EXTINF:-1 tvg-chno="65" tvg-id="Freeform.HD.us2" tvg-name="Freeform TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10093_dark_360w_270h.png" group-title="TV",Freeform TV
http://cord-cutter.net:8080/k4Svp2/645504/13370
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/13370
#EXTINF:-1 tvg-chno="66" tvg-id="Fuse.HD.us2" tvg-name="FUSE" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14929_dark_360w_270h.png" group-title="TV",FUSE
http://fl1.moveonjoy.com/FUSE/index.m3u8
#EXTINF:-1 tvg-chno="67" tvg-id="FX.HD.us2" tvg-name="FX" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14321_dark_360w_270h.png" group-title="TV",FX
http://cord-cutter.net:8080/k4Svp2/645504/46690
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46690
#EXTINF:-1 tvg-chno="68" tvg-id="FX.Movie.Channel.HD.us2" tvg-name="FX Movie Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s70253_dark_360w_270h.png" group-title="TV",FX Movie Channel
http://fl1.moveonjoy.com/FX_MOVIE/index.m3u8
#EXTINF:-1 tvg-chno="69" tvg-id="FXX.HD.us2" tvg-name="FXX" tvg-logo="https://raw.githubusercontent.com/tv-logo/tv-logos/refs/heads/main/countries/united-states/fxx-us.png" group-title="TV",FXX
http://cord-cutter.net:8080/k4Svp2/645504/46699
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46699
#EXTINF:-1 tvg-chno="70" tvg-id="FYI.Channel.HD.us2" tvg-name="FYI TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16834_dark_360w_270h.png" group-title="TV",FYI TV
http://fl1.moveonjoy.com/FYI/index.m3u8
#EXTINF:-1 tvg-chno="71" tvg-id="Game.Show.Network.HD.us2" tvg-name="Game Show Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14909_dark_360w_270h.png" group-title="TV",Game Show Network
http://cord-cutter.net:8080/k4Svp2/645504/120633
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/120633
#EXTINF:-1 tvg-chno="72" tvg-id="get.us2" tvg-name="getTV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s82563_dark_360w_270h.png" group-title="TV",getTV
http://cord-cutter.net:8080/k4Svp2/645504/18366
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/18366
#EXTINF:-1 tvg-chno="73" tvg-id="Golf.Channel.HD.us2" tvg-name="Golf Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14899_dark_360w_270h.png" group-title="TV",Golf Channel
https://fl1.moveonjoy.com/GOLF/index.m3u8
@ -232,7 +232,7 @@ https://fl1.moveonjoy.com/HALLMARK_DRAMA/index.m3u8
https://fl1.moveonjoy.com/HALLMARK_MOVIES_MYSTERIES/index.m3u8
#EXTINF:-1 tvg-chno="78" tvg-id="HBO.East.us2" tvg-name="HBO" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10240_dark_360w_270h.png" group-title="TV",HBO
http://cord-cutter.net:8080/k4Svp2/645504/46713
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46713
#EXTINF:-1 tvg-chno="79" tvg-id="HBO2.HD.us2" tvg-name="HBO 2" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s68140_dark_360w_270h.png" group-title="TV",HBO 2
http://fl1.moveonjoy.com/HBO_2/index.m3u8
@ -247,7 +247,7 @@ https://fl1.moveonjoy.com/HBO_FAMILY/index.m3u8
https://fl1.moveonjoy.com/HBO_ZONE/index.m3u8
#EXTINF:-1 tvg-chno="83" tvg-id="History.HD.us2" tvg-name="History Channel" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s87679_dark_360w_270h.png" group-title="TV",History Channel
http://cord-cutter.net:8080/k4Svp2/645504/15017
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/15017
#EXTINF:-1 tvg-chno="84" tvg-id="HLN.HD.us2" tvg-name="HLN TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10145_dark_360w_270h.png" group-title="TV",HLN TV
https://turnerlive.warnermediacdn.com/hls/live/586496/cnngo/hln/VIDEO_0_3564000.m3u8
@ -256,7 +256,7 @@ https://turnerlive.warnermediacdn.com/hls/live/586496/cnngo/hln/VIDEO_0_3564000.
https://fl1.moveonjoy.com/INVESTIGATION_DISCOVERY/index.m3u8
#EXTINF:-1 tvg-chno="86" tvg-id="ION.Television.HD.us2" tvg-name="ION TV" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s18633_dark_360w_270h.png" group-title="TV",ION TV
http://cord-cutter.net:8080/k4Svp2/645504/9297
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/9297
#EXTINF:-1 tvg-chno="87" tvg-id="Lifetime.HD.us2" tvg-name="Lifetime" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10918_dark_360w_270h.png" group-title="TV",Lifetime
http://fl1.moveonjoy.com/LIFETIME/index.m3u8
@ -265,16 +265,16 @@ http://fl1.moveonjoy.com/LIFETIME/index.m3u8
https://fl1.moveonjoy.com/LIFETIME_MOVIE_NETWORK/index.m3u8
#EXTINF:-1 tvg-chno="89" tvg-id="Marquee.Sports.Network.HD.us2" tvg-name="Marquee Sports Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s113768_dark_360w_270h.png" group-title="TV",Marquee Sports Network
http://cord-cutter.net:8080/k4Svp2/645504/13379
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/13379
#EXTINF:-1 tvg-chno="90" tvg-id="MLB.Network.HD.us2" tvg-name="MLB Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s62081_dark_360w_270h.png" group-title="TV",MLB Network
https://fl1.moveonjoy.com/MLB_NETWORK/index.m3u8
#EXTINF:-1 tvg-chno="91" tvg-id="MOTORTREND.HD.us2" tvg-name="MotorTrend TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s31046_dark_360w_270h.png" group-title="TV",MotorTrend TV
http://cord-cutter.net:8080/k4Svp2/645504/10399
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10399
#EXTINF:-1 tvg-chno="92" tvg-id="MSG.National.us2" tvg-name="MSG" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10979_dark_360w_270h.png" group-title="TV",MSG
http://cord-cutter.net:8080/k4Svp2/645504/21090
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/21090
#EXTINF:-1 tvg-chno="93" tvg-id="MSNBC.HD.us2" tvg-name="MSNBC" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16300_dark_360w_270h.png" group-title="TV",MSNBC
https://fl1.moveonjoy.com/MSNBC/index.m3u8
@ -292,40 +292,40 @@ http://fl1.moveonjoy.com/NBA_TV/index.m3u8
https://fl1.moveonjoy.com/FL_Tampa_NBC/index.m3u8
#EXTINF:-1 tvg-chno="98" tvg-id="NBC.Sports.Bay.Area.HD.us2" tvg-name="NBC Sports Bay Area" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s63138_dark_360w_270h.png" group-title="TV",NBC Sports Bay Area
http://cord-cutter.net:8080/k4Svp2/645504/9900
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/9900
#EXTINF:-1 tvg-chno="99" tvg-id="NBC.Sports.Boston.HD.us2" tvg-name="NBC Sports Boston" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s49198_dark_360w_270h.png" group-title="TV",NBC Sports Boston
http://cord-cutter.net:8080/k4Svp2/645504/20939
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20939
#EXTINF:-1 tvg-chno="100" tvg-id="NBC.Sports.California.SAT.us2" tvg-name="NBC Sports California" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s45540_dark_360w_270h.png" group-title="TV",NBC Sports California
http://cord-cutter.net:8080/k4Svp2/645504/20940
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20940
#EXTINF:-1 tvg-chno="101" tvg-id="a90a91570ce0536cbb22b591ad7e0da2" tvg-name="NBC Sports NOW" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s114140_dark_360w_270h.png" group-title="TV",NBC Sports NOW
https://jmp2.uk/plu-6549306c83595c000815a696.m3u8
#EXTINF:-1 tvg-chno="102" tvg-id="NBC.Sports.Philadelphia.HD.us2" tvg-name="NBC Sports Philadelphia" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s32571_dark_360w_270h.png" group-title="TV",NBC Sports Philadelphia
http://cord-cutter.net:8080/k4Svp2/645504/20943
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20943
#EXTINF:-1 tvg-chno="103" tvg-id="New.England.Sports.Network.HD.us2" tvg-name="NESN" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s35038_dark_360w_270h.png" group-title="TV",NESN
http://cord-cutter.net:8080/k4Svp2/645504/31637
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/31637
#EXTINF:-1 tvg-chno="104" tvg-id="NewsNation.us2" tvg-name="NewsNation" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s91096_dark_360w_270h.png" group-title="TV",NewsNation
http://cord-cutter.net:8080/k4Svp2/645504/161450
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/161450
#EXTINF:-1 tvg-chno="105" tvg-id="NFL.Network.HD.us2" tvg-name="NFL Network" tvg-logo="https://raw.githubusercontent.com/tv-logo/tv-logos/refs/heads/main/countries/united-states/nfl-network-hz-us.png" group-title="TV",NFL Network
http://cord-cutter.net:8080/k4Svp2/645504/159117
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/159117
#EXTINF:-1 tvg-chno="106" tvg-id="NFL.RedZone.HD.us2" tvg-name="NFL RedZone" tvg-logo="https://raw.githubusercontent.com/tv-logo/tv-logos/refs/heads/main/countries/united-states/nfl-red-zone-hz-us.png" group-title="TV",NFL RedZone
http://cord-cutter.net:8080/k4Svp2/645504/208830
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/208830
#EXTINF:-1 tvg-chno="107" tvg-id="NHL.Network.HD.us2" tvg-name="NHL Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s58570_dark_360w_270h.png" group-title="TV",NHL Network
http://23.237.104.106:8080/USA_NHL_NETWORK/index.m3u8
#EXTINF:-1 tvg-chno="108" tvg-id="Nickelodeon.HD.us2" tvg-name="Nickelodeon" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11006_dark_360w_270h.png" group-title="TV",Nickelodeon
http://cord-cutter.net:8080/k4Svp2/645504/38
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/38
#EXTINF:-1 tvg-chno="109" tvg-id="Nicktoons.us2" tvg-name="Nicktoons" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s30420_dark_360w_270h.png" group-title="TV",Nicktoons
http://cord-cutter.net:8080/k4Svp2/645504/36
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/36
#EXTINF:-1 tvg-chno="110" tvg-id="Outdoor.Channel.HD.us2" tvg-name="Outdoor Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14776_dark_360w_270h.png" group-title="TV",Outdoor Channel
http://fl1.moveonjoy.com/OUTDOOR_CHANNEL/index.m3u8
@ -346,13 +346,13 @@ https://fl1.moveonjoy.com/Pop_TV/index.m3u8
http://c3921155.edmonst.net/iptv/ZQHGFQ9PRYN859UHYGWY674B/2160/index.m3u8
#EXTINF:-1 tvg-chno="116" tvg-id="ReelzChannel.HD.us2" tvg-name="Reelz Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s68385_dark_360w_270h.png" group-title="TV",Reelz Channel
http://cord-cutter.net:8080/k4Svp2/645504/10526
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10526
#EXTINF:-1 tvg-chno="117" tvg-id="ROOT.Sports.Northwest.HD.us2" tvg-name="Root Sports" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11062_dark_360w_270h.png" group-title="TV",Root Sports
http://cord-cutter.net:8080/k4Svp2/645504/85232
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/85232
#EXTINF:-1 tvg-chno="118" tvg-id="SEC.Network.HD.us2" tvg-name="SEC Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s89535_dark_360w_270h.png" group-title="TV",SEC Network
http://cord-cutter.net:8080/k4Svp2/645504/17608
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/17608
#EXTINF:-1 tvg-chno="119" tvg-id="Paramount+.with.Showtime.HD.us2" tvg-name="Showtime" tvg-logo="https://raw.githubusercontent.com/tv-logo/tv-logos/refs/heads/main/countries/united-states/showtime-us.png" group-title="TV",Showtime
http://fl1.moveonjoy.com/SHOWTIME/index.m3u8
@ -364,37 +364,37 @@ http://fl1.moveonjoy.com/SMITHSONIAN_CHANNEL/index.m3u8
http://fl1.moveonjoy.com/Sony_Movie_Channel/index.m3u8
#EXTINF:-1 tvg-chno="122" tvg-id="Space.City.Home.Network.HD.us2" tvg-name="Space City Home Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s77744_dark_360w_270h.png" group-title="TV",Space City Home Network
http://cord-cutter.net:8080/k4Svp2/645504/213668
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/213668
#EXTINF:-1 tvg-chno="123" tvg-id="Spectrum.SportsNet.LA.Dodgers.HD.us2" tvg-name="Spectrum SportsNet LA Dodgers" tvg-logo="https://i.gyazo.com/765cce528ddda366695bb178d9dee6da.png" group-title="TV",Spectrum SportsNet LA Dodgers
http://cord-cutter.net:8080/k4Svp2/645504/31636
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/31636
#EXTINF:-1 tvg-chno="124" tvg-id="Spectrum.SportsNet.Lakers.HD.us2" tvg-name="Spectrum SportsNet Lakers" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s77422_dark_360w_270h.png" group-title="TV",Spectrum SportsNet Lakers
http://cord-cutter.net:8080/k4Svp2/645504/20946
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20946
#EXTINF:-1 tvg-chno="125" tvg-id="Sportsnet.360.HD.ca2" tvg-name="Sportsnet 360" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s49952_dark_360w_270h.png" group-title="TV",Sportsnet 360
http://cord-cutter.net:8080/k4Svp2/645504/57299
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/57299
#EXTINF:-1 tvg-chno="126" tvg-id="Sportsnet.East.ca2" tvg-name="Sportsnet East" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s62109_dark_360w_270h.png" group-title="TV",Sportsnet East
http://cord-cutter.net:8080/k4Svp2/645504/57298
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/57298
#EXTINF:-1 tvg-chno="127" tvg-id="SNY.SportsNet.New.York.HD.us2" tvg-name="SportsNet New York" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s50038_dark_360w_270h.png" group-title="TV",SportsNet New York
http://cord-cutter.net:8080/k4Svp2/645504/20938
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/20938
#EXTINF:-1 tvg-chno="128" tvg-id="Sportsnet.One.ca2" tvg-name="Sportsnet One" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s68859_dark_360w_270h.png" group-title="TV",Sportsnet One
http://cord-cutter.net:8080/k4Svp2/645504/10247
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10247
#EXTINF:-1 tvg-chno="129" tvg-id="Sportsnet.Ontario.HD.ca2" tvg-name="Sportsnet Ontario" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s62111_dark_360w_270h.png" group-title="TV",Sportsnet Ontario
http://cord-cutter.net:8080/k4Svp2/645504/11649
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/11649
#EXTINF:-1 tvg-chno="130" tvg-id="SportsNet.Pittsburgh.HD.us2" tvg-name="SportsNet Pittsburgh" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s26028_dark_360w_270h.png" group-title="TV",SportsNet Pittsburgh
http://cord-cutter.net:8080/k4Svp2/645504/108178
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/108178
#EXTINF:-1 tvg-chno="131" tvg-id="Starz.HD.us2" tvg-name="Starz" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12719_dark_360w_270h.png" group-title="TV",Starz
http://cord-cutter.net:8080/k4Svp2/645504/9299
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/9299
#EXTINF:-1 tvg-chno="132" tvg-id="Syfy.HD.us2" tvg-name="Syfy" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11097_dark_360w_270h.png" group-title="TV",Syfy
http://cord-cutter.net:8080/k4Svp2/645504/46685
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46685
#EXTINF:-1 tvg-chno="133" tvg-id="TBS.HD.us2" tvg-name="TBS" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11867_dark_360w_270h.png" group-title="TV",TBS
https://turnerlive.warnermediacdn.com/hls/live/2023172/tbseast/slate/VIDEO_0_3564000.m3u8
@ -403,10 +403,10 @@ https://turnerlive.warnermediacdn.com/hls/live/2023172/tbseast/slate/VIDEO_0_356
https://fl1.moveonjoy.com/TENNIS_CHANNEL/index.m3u8
#EXTINF:-1 tvg-chno="135" tvg-id="The.Weather.Channel.HD.us2" tvg-name="The Weather Channel" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s58812_dark_360w_270h.png" group-title="TV",The Weather Channel
http://cord-cutter.net:8080/k4Svp2/645504/18926
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/18926
#EXTINF:-1 tvg-chno="136" tvg-id="TLC.HD.(US).us2" tvg-name="TLC" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11158_dark_360w_270h.png" group-title="TV",TLC
http://cord-cutter.net:8080/k4Svp2/645504/12734
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/12734
#EXTINF:-1 tvg-chno="137" tvg-id="TNT.HD.us2" tvg-name="TNT" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11164_dark_360w_270h.png" group-title="TV",TNT
https://turnerlive.warnermediacdn.com/hls/live/2023168/tnteast/slate/VIDEO_0_3564000.m3u8
@ -415,10 +415,10 @@ https://turnerlive.warnermediacdn.com/hls/live/2023168/tnteast/slate/VIDEO_0_356
https://turnerlive.warnermediacdn.com/hls/live/2023176/trueast/slate/VIDEO_0_3564000.m3u8
#EXTINF:-1 tvg-chno="139" tvg-id="TSN.1.ca2" tvg-name="TSN1" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11182_dark_360w_270h.png" group-title="TV",TSN1
http://cord-cutter.net:8080/k4Svp2/645504/57292
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/57292
#EXTINF:-1 tvg-chno="140" tvg-id="TSN.2.ca2" tvg-name="TSN2" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s61474_dark_360w_270h.png" group-title="TV",TSN2
http://cord-cutter.net:8080/k4Svp2/645504/47442
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/47442
#EXTINF:-1 tvg-chno="141" tvg-id="Turner.Classic.Movies.HD.us2" tvg-name="Turner Classic Movies" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12852_dark_360w_270h.png" group-title="TV",Turner Classic Movies
https://turnerlive.warnermediacdn.com/hls/live/2023186/tcmeast/noslate/VIDEO_1_5128000.m3u8
@ -430,13 +430,13 @@ https://fl1.moveonjoy.com/TV_LAND/index.m3u8
https://fl1.moveonjoy.com/TV_ONE/index.m3u8
#EXTINF:-1 tvg-chno="144" tvg-id="USA.Network.HD.us2" tvg-name="USA East" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11207_dark_360w_270h.png" group-title="TV",USA East
http://cord-cutter.net:8080/k4Svp2/645504/10252
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/10252
#EXTINF:-1 tvg-chno="145" tvg-id="Vice.HD.us2" tvg-name="Vice TV" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s18822_dark_360w_270h.png" group-title="TV",Vice TV
http://cord-cutter.net:8080/k4Svp2/645504/46697
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46697
#EXTINF:-1 tvg-chno="146" tvg-id="Willow.Cricket.HD.us2" tvg-name="Willow Cricket" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s68605_dark_360w_270h.png" group-title="TV",Willow Cricket
http://cord-cutter.net:8080/k4Svp2/645504/41979
http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/41979
#EXTINF:-1 tvg-chno="147" tvg-id="Yes.Network.us2" tvg-name="YES Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s30017_dark_360w_270h.png" group-title="TV",YES Network
https://fl1.moveonjoy.com/YES_NETWORK/index.m3u8

File diff suppressed because it is too large Load diff

View file

@ -4,7 +4,6 @@ import re
from pathlib import Path
from scrapers import (
embedhd,
fawa,
istreameast,
pixel,
@ -12,12 +11,12 @@ from scrapers import (
roxie,
shark,
sport9,
streambtw,
streamcenter,
streamfree,
streamhub,
streamsgate,
strmd,
time4tv,
tvpass,
watchfooty,
webcast,
@ -49,7 +48,6 @@ async def main() -> None:
base_m3u8, tvg_chno = load_base()
tasks = [
asyncio.create_task(embedhd.scrape()),
asyncio.create_task(fawa.scrape()),
asyncio.create_task(istreameast.scrape()),
asyncio.create_task(pixel.scrape()),
@ -57,35 +55,33 @@ async def main() -> None:
asyncio.create_task(roxie.scrape()),
asyncio.create_task(shark.scrape()),
asyncio.create_task(sport9.scrape()),
asyncio.create_task(streambtw.scrape()),
asyncio.create_task(streamcenter.scrape()),
asyncio.create_task(streamfree.scrape()),
asyncio.create_task(streamhub.scrape()),
asyncio.create_task(streamsgate.scrape()),
asyncio.create_task(strmd.scrape()),
asyncio.create_task(time4tv.scrape()),
asyncio.create_task(tvpass.scrape()),
asyncio.create_task(watchfooty.scrape()),
asyncio.create_task(webcast.scrape()),
]
await asyncio.gather(*tasks)
await watchfooty.scrape()
additions = (
embedhd.urls
| fawa.urls
fawa.urls
| istreameast.urls
| pixel.urls
| ppv.urls
| roxie.urls
| shark.urls
| sport9.urls
| streambtw.urls
| streamcenter.urls
| strmd.urls
| streamfree.urls
| streamhub.urls
| streamsgate.urls
| time4tv.urls
| tvpass.urls
| watchfooty.urls
| webcast.urls

View file

@ -1,141 +0,0 @@
from functools import partial
from playwright.async_api import async_playwright
from .utils import Cache, Time, get_logger, leagues, network
log = get_logger(__name__)
urls: dict[str, dict[str, str | float]] = {}
TAG = "EMBEDHD"
CACHE_FILE = Cache(f"{TAG.lower()}.json", exp=5_400)
API_CACHE = Cache(f"{TAG.lower()}-api.json", exp=28_800)
BASE_URL = "https://embedhd.org/api-event.php"
def fix_league(s: str) -> str:
return " ".join(x.capitalize() for x in s.split()) if len(s) > 5 else s.upper()
async def get_events(cached_keys: list[str]) -> list[dict[str, str]]:
now = Time.clean(Time.now())
if not (api_data := API_CACHE.load(per_entry=False)):
api_data = {}
if r := await network.request(BASE_URL, log=log):
api_data: dict = r.json()
api_data["timestamp"] = now.timestamp()
API_CACHE.write(api_data)
events = []
for info in api_data.get("days", []):
event_dt = Time.from_str(info["day_et"], timezone="ET")
if now.date() != event_dt.date():
continue
for event in info["items"]:
if (event_league := event["league"]) == "channel tv":
continue
sport = fix_league(event_league)
event_name = event["title"]
if f"[{sport}] {event_name} ({TAG})" in cached_keys:
continue
event_streams: list[dict[str, str]] = event["streams"]
if not (event_link := event_streams[0].get("link")):
continue
events.append(
{
"sport": sport,
"event": event_name,
"link": event_link,
"timestamp": now.timestamp(),
}
)
return events
async def scrape() -> None:
cached_urls = CACHE_FILE.load()
cached_count = len(cached_urls)
urls.update(cached_urls)
log.info(f"Loaded {cached_count} event(s) from cache")
log.info(f'Scraping from "{BASE_URL}"')
events = await get_events(cached_urls.keys())
log.info(f"Processing {len(events)} new URL(s)")
if events:
async with async_playwright() as p:
browser, context = await network.browser(p)
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
if url:
sport, event, link, ts = (
ev["sport"],
ev["event"],
ev["link"],
ev["timestamp"],
)
tvg_id, logo = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": "https://vividmosaica.com/",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")
else:
log.info("No new events found")
CACHE_FILE.write(cached_urls)

View file

@ -114,8 +114,8 @@ async def scrape() -> None:
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.HTTP_S,
log=log,
timeout=10,
)
if url:

View file

@ -1,6 +1,5 @@
import base64
import re
from functools import partial
from selectolax.parser import HTMLParser
@ -10,7 +9,7 @@ log = get_logger(__name__)
urls: dict[str, dict[str, str | float]] = {}
TAG = "iSTRMEST"
TAG = "ISTRMEST"
CACHE_FILE = Cache(f"{TAG.lower()}.json", exp=3_600)
@ -122,20 +121,7 @@ async def scrape() -> None:
now = Time.clean(Time.now()).timestamp()
for i, ev in enumerate(events, start=1):
handler = partial(
process_event,
url=ev["link"],
url_num=i,
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.HTTP_S,
log=log,
)
if url:
if url := await process_event(ev["link"], i):
sport, event, link = (
ev["sport"],
ev["event"],

View file

@ -1,7 +1,6 @@
import json
from functools import partial
from playwright.async_api import BrowserContext, async_playwright
from playwright.async_api import async_playwright
from .utils import Cache, Time, get_logger, leagues, network
@ -16,29 +15,36 @@ CACHE_FILE = Cache(f"{TAG.lower()}.json", exp=19_800)
BASE_URL = "https://pixelsport.tv/backend/livetv/events"
async def get_api_data(context: BrowserContext) -> dict[str, list[dict, str, str]]:
try:
page = await context.new_page()
async def get_api_data() -> dict[str, list[dict, str, str]]:
async with async_playwright() as p:
try:
browser, context = await network.browser(p)
await page.goto(
BASE_URL,
wait_until="domcontentloaded",
timeout=10_000,
)
page = await context.new_page()
raw_json = await page.locator("pre").inner_text(timeout=5_000)
except Exception as e:
log.error(f'Failed to fetch "{BASE_URL}": {e}')
await page.goto(
BASE_URL,
wait_until="domcontentloaded",
timeout=10_000,
)
return {}
raw_json = await page.locator("pre").inner_text(timeout=5_000)
except Exception as e:
log.error(f'Failed to fetch "{BASE_URL}": {e}')
return {}
finally:
await browser.close()
return json.loads(raw_json)
async def get_events(context: BrowserContext) -> dict[str, dict[str, str | float]]:
async def get_events() -> dict[str, dict[str, str | float]]:
now = Time.clean(Time.now())
api_data = await get_api_data(context)
api_data = await get_api_data()
events = {}
@ -85,23 +91,9 @@ async def scrape() -> None:
log.info(f'Scraping from "{BASE_URL}"')
async with async_playwright() as p:
browser, context = await network.browser(p)
events = await get_events()
try:
handler = partial(get_events, context=context)
events = await network.safe_process(
handler,
url_num=1,
semaphore=network.PW_S,
log=log,
)
finally:
await browser.close()
urls.update(events or {})
urls.update(events)
CACHE_FILE.write(urls)

View file

@ -110,50 +110,47 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
timeout=6,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
timeout=6,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
tvg_id, pic = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo or pic,
"base": base_url,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, pic = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo or pic,
"base": base_url,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -159,7 +159,6 @@ async def scrape() -> None:
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.HTTP_S,
log=log,
)

View file

@ -137,7 +137,6 @@ async def scrape() -> None:
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.HTTP_S,
log=log,
)

View file

@ -109,47 +109,44 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, link = (
ev["sport"],
ev["event"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, link = (
ev["sport"],
ev["event"],
ev["link"],
)
tvg_id, logo = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": "https://vividmosaica.com/",
"timestamp": now,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, logo = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo,
"base": "https://vividmosaica.com/",
"timestamp": now,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -1,137 +0,0 @@
import base64
import re
from functools import partial
from urllib.parse import urljoin
from selectolax.parser import HTMLParser
from .utils import Cache, Time, get_logger, leagues, network
log = get_logger(__name__)
urls: dict[str, dict[str, str | float]] = {}
TAG = "STRMBTW"
CACHE_FILE = Cache(f"{TAG.lower()}.json", exp=3_600)
BASE_URL = "https://streambtw.com"
def fix_league(s: str) -> str:
pattern = re.compile(r"^\w*-\w*", re.IGNORECASE)
return " ".join(s.split("-")) if pattern.search(s) else s
async def process_event(url: str, url_num: int) -> str | None:
if not (html_data := await network.request(url, log=log)):
return
valid_m3u8 = re.compile(r'var\s+(\w+)\s*=\s*"([^"]*)"', re.IGNORECASE)
if not (match := valid_m3u8.search(html_data.text)):
log.info(f"URL {url_num}) No M3U8 found")
return
stream_link: str = match[2]
if not stream_link.startswith("http"):
stream_link = base64.b64decode(stream_link).decode("utf-8")
log.info(f"URL {url_num}) Captured M3U8")
return stream_link
async def get_events() -> list[dict[str, str]]:
events = []
if not (html_data := await network.request(BASE_URL, log=log)):
return events
soup = HTMLParser(html_data.content)
for card in soup.css(".league"):
if not (league_elem := card.css_first(".league-header h4")):
continue
for event in card.css(".match"):
if not (event_elem := event.css_first(".match-title")):
continue
if not (watch_btn := event.css_first(".watch-btn")) or not (
href := watch_btn.attributes.get("href")
):
continue
league, name = league_elem.text(strip=True), event_elem.text(strip=True)
events.append(
{
"sport": fix_league(league),
"event": name,
"link": urljoin(BASE_URL, href),
}
)
return events
async def scrape() -> None:
if cached := CACHE_FILE.load():
urls.update(cached)
log.info(f"Loaded {len(urls)} event(s) from cache")
return
log.info(f'Scraping from "{BASE_URL}"')
events = await get_events()
log.info(f"Processing {len(events)} new URL(s)")
if events:
now = Time.clean(Time.now())
for i, ev in enumerate(events, start=1):
handler = partial(
process_event,
url=ev["link"],
url_num=i,
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.HTTP_S,
log=log,
)
if url:
sport, event, link = (
ev["sport"],
ev["event"],
ev["link"],
)
key = f"[{sport}] {event} ({TAG})"
tvg_id, logo = leagues.get_tvg_info(sport, event)
entry = {
"url": url,
"logo": logo,
"base": link,
"timestamp": now.timestamp(),
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = entry
log.info(f"Collected {len(urls)} event(s)")
CACHE_FILE.write(urls)

View file

@ -107,48 +107,45 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["timestamp"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["timestamp"],
ev["link"],
)
tvg_id, logo = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": "https://streamcenter.xyz",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, logo = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo,
"base": "https://streamcenter.xyz",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -77,14 +77,7 @@ async def scrape() -> None:
log.info(f'Scraping from "{BASE_URL}"')
events = await network.safe_process(
get_events,
url_num=1,
semaphore=network.HTTP_S,
log=log,
)
urls.update(events or {})
urls.update(await get_events())
CACHE_FILE.write(urls)

View file

@ -151,50 +151,47 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
timeout=5,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
timeout=5,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, logo, link, ts = (
ev["sport"],
ev["event"],
ev["logo"],
ev["link"],
ev["event_ts"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, logo, link, ts = (
ev["sport"],
ev["event"],
ev["logo"],
ev["link"],
ev["event_ts"],
)
tvg_id, pic = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo or pic,
"base": "https://storytrench.net/",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, pic = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo or pic,
"base": "https://storytrench.net/",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -139,48 +139,45 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["timestamp"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["timestamp"],
ev["link"],
)
tvg_id, logo = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": BASE_URL,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, logo = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo,
"base": BASE_URL,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -139,49 +139,46 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
tvg_id, pic = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo or pic,
"base": "https://embedsports.top/",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, pic = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo or pic,
"base": "https://embedsports.top/",
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

138
M3U8/scrapers/time4tv.py Normal file
View file

@ -0,0 +1,138 @@
import re
from functools import partial
from urllib.parse import urljoin
from playwright.async_api import async_playwright
from selectolax.parser import HTMLParser
from .utils import Cache, Time, get_logger, leagues, network
log = get_logger(__name__)
urls: dict[str, dict[str, str | float]] = {}
TAG = "TIME4TV"
CACHE_FILE = Cache(f"{TAG.lower()}.json", exp=5_400)
BASE_URL = "https://time4tv.icu/"
def fix_league(s: str) -> str:
return " ".join(x.capitalize() for x in s.split()) if len(s) > 5 else s.upper()
async def get_events(cached_keys: list[str], now: Time) -> dict[dict[str, str]]:
events = []
if not (html_data := await network.request(BASE_URL, log=log)):
return events
pattern = re.compile(r"openPlayerPopup\(\s*(\d+)\s*\)", re.IGNORECASE)
soup = HTMLParser(html_data.content)
for row in soup.css(".wrap .row"):
if not (date := row.css_first(".date")):
continue
event_date = date.text(strip=True).replace("\t", " ")
try:
event_dt = Time.from_str(event_date, fmt="%m/%d/%Y %I:%M %p")
except ValueError:
continue
if event_dt.date() != now.date():
continue
league = row.css_first(".league")
title = row.css_first(".title")
hds_a = row.css_first(".hds a")
if not (league and title and hds_a):
continue
sport, event = fix_league(league.text(strip=True)), title.text(strip=True)
if f"[{sport}] {event} ({TAG})" in cached_keys:
continue
onclick = hds_a.attributes.get("onclick", "")
if not (match := pattern.search(onclick)):
continue
events.append(
{
"sport": sport,
"event": event,
"link": urljoin(BASE_URL, f"player1.php?{match[1]}"),
}
)
return events
async def scrape() -> None:
cached_urls = CACHE_FILE.load()
cached_count = len(cached_urls)
urls.update(cached_urls)
log.info(f"Loaded {cached_count} event(s) from cache")
log.info(f'Scraping from "{BASE_URL}"')
now = Time.clean(Time.now())
events = await get_events(cached_urls.keys(), now)
log.info(f"Processing {len(events)} new URL(s)")
async with async_playwright() as p:
browser, context = await network.browser(p)
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event = ev["sport"], ev["event"]
tvg_id, logo = leagues.info(sport)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": "https://vividmosaica.com/",
"timestamp": now.timestamp(),
"id": tvg_id or "Live.Event.us",
}
urls[key] = cached_urls[key] = entry
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")
else:
log.info("No new events found")
CACHE_FILE.write(cached_urls)

View file

@ -66,14 +66,7 @@ async def scrape() -> None:
log.info(f'Scraping from "{BASE_URL}"')
events = await network.safe_process(
get_events,
url_num=1,
semaphore=network.HTTP_S,
log=log,
)
urls.update(events or {})
urls.update(await get_events())
CACHE_FILE.write(urls)

View file

@ -5,13 +5,13 @@ from .config import Time
class Cache:
now_ts: float = Time.now().timestamp()
def __init__(self, file: str, exp: int | float) -> None:
self.file = Path(__file__).parent.parent / "caches" / file
self.exp = exp
self.now_ts = Time.now().timestamp()
def is_fresh(self, entry: dict) -> bool:
ts: float | int = entry.get("timestamp", Time.default_8())

View file

@ -130,7 +130,7 @@ class Time(datetime):
class Leagues:
live_img = "https://i.gyazo.com/4a5e9fa2525808ee4b65002b56d3450e.png"
live_img = "https://i.gyazo.com/978f2eb4a199ca5b56b447aded0cb9e3.png"
def __init__(self) -> None:
self.data = json.loads(
@ -165,7 +165,7 @@ class Leagues:
league: str,
) -> bool:
pattern = re.compile(r"\s+(?:-|vs\.?|at|@)\s+", re.IGNORECASE)
pattern = re.compile(r"\s+(?:-|vs\.?|at|@)\s+", flags=re.IGNORECASE)
if pattern.search(event):
t1, t2 = re.split(pattern, event)

View file

@ -24,15 +24,11 @@ class Network:
"Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
)
HTTP_S = asyncio.Semaphore(10)
PW_S = asyncio.Semaphore(3)
proxy_base = "https://stream.nvrmind.xyz"
def __init__(self) -> None:
self.client = httpx.AsyncClient(
timeout=httpx.Timeout(5.0),
timeout=5,
follow_redirects=True,
headers={"User-Agent": Network.UA},
http2=True,
@ -89,39 +85,34 @@ class Network:
async def safe_process(
fn: Callable[[], Awaitable[T]],
url_num: int,
semaphore: asyncio.Semaphore,
timeout: int | float = 10,
timeout: int | float = 15,
log: logging.Logger | None = None,
) -> T | None:
log = log or logger
async with semaphore:
task = asyncio.create_task(fn())
task = asyncio.create_task(fn())
try:
return await asyncio.wait_for(task, timeout=timeout)
except asyncio.TimeoutError:
log.warning(f"URL {url_num}) Timed out after {timeout}s, skipping event")
task.cancel()
try:
return await asyncio.wait_for(task, timeout=timeout)
await task
except asyncio.CancelledError:
pass
except asyncio.TimeoutError:
log.warning(
f"URL {url_num}) Timed out after {timeout}s, skipping event"
)
task.cancel()
try:
await task
except asyncio.CancelledError:
pass
except Exception as e:
log.debug(f"URL {url_num}) Ignore exception after timeout: {e}")
return
except Exception as e:
log.error(f"URL {url_num}) Unexpected error: {e}")
log.debug(f"URL {url_num}) Ignore exception after timeout: {e}")
return
return
except Exception as e:
log.error(f"URL {url_num}) Unexpected error: {e}")
return
@staticmethod
def capture_req(

View file

@ -78,12 +78,12 @@ async def process_event(
pattern = re.compile(r"\((\d+)\)")
page = await context.new_page()
captured: list[str] = []
got_one = asyncio.Event()
page = await context.new_page()
handler = partial(
network.capture_req,
captured=captured,
@ -102,7 +102,10 @@ async def process_event(
await page.wait_for_timeout(2_000)
try:
header = await page.wait_for_selector("text=/Stream Links/i", timeout=5_000)
header = await page.wait_for_selector(
"text=/Stream Links/i",
timeout=5_000,
)
text = await header.inner_text()
except TimeoutError:
@ -117,7 +120,8 @@ async def process_event(
try:
first_available = await page.wait_for_selector(
'a[href*="/stream/"]', timeout=3_000
'a[href*="/stream/"]',
timeout=3_000,
)
except TimeoutError:
log.warning(f"URL {url_num}) No available stream links.")
@ -129,18 +133,22 @@ async def process_event(
return None, None
embed = re.sub(
pattern=r"^.*\/stream",
repl="https://spiderembed.top/embed",
string=href,
)
await page.goto(
embed,
href,
wait_until="domcontentloaded",
timeout=5_000,
)
if not (iframe := await page.query_selector("iframe")):
log.warning(f"URL {url_num}) No iframe found.")
return None, None
if not (iframe_src := await iframe.get_attribute("src")):
log.warning(f"URL {url_num}) No iframe source found.")
return None, None
wait_task = asyncio.create_task(got_one.wait())
try:
@ -162,7 +170,7 @@ async def process_event(
if captured:
log.info(f"URL {url_num}) Captured M3U8")
return captured[0], embed
return captured[-1], iframe_src
log.warning(f"URL {url_num}) No M3U8 captured after waiting.")
@ -263,51 +271,48 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p, browser="external")
try:
for i, ev in enumerate(events, start=1):
handler = partial(
process_event,
url=ev["link"],
url_num=i,
context=context,
)
for i, ev in enumerate(events, start=1):
handler = partial(
process_event,
url=ev["link"],
url_num=i,
context=context,
)
url, iframe = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
url, iframe = await network.safe_process(
handler,
url_num=i,
log=log,
)
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
sport, event, logo, ts, link = (
ev["sport"],
ev["event"],
ev["logo"],
ev["timestamp"],
ev["link"],
)
key = f"[{sport}] {event} ({TAG})"
key = f"[{sport}] {event} ({TAG})"
tvg_id, pic = leagues.get_tvg_info(sport, event)
tvg_id, pic = leagues.get_tvg_info(sport, event)
entry = {
"url": url,
"logo": logo or pic,
"base": iframe,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
entry = {
"url": url,
"logo": logo or pic,
"base": iframe,
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
cached_urls[key] = entry
cached_urls[key] = entry
if url:
valid_count += 1
urls[key] = entry
if url:
valid_count += 1
urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := valid_count - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -129,48 +129,45 @@ async def scrape() -> None:
async with async_playwright() as p:
browser, context = await network.browser(p)
try:
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
for i, ev in enumerate(events, start=1):
handler = partial(
network.process_event,
url=ev["link"],
url_num=i,
context=context,
log=log,
)
url = await network.safe_process(
handler,
url_num=i,
log=log,
)
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["event_ts"],
ev["link"],
)
url = await network.safe_process(
handler,
url_num=i,
semaphore=network.PW_S,
log=log,
)
key = f"[{sport}] {event} ({TAG})"
if url:
sport, event, ts, link = (
ev["sport"],
ev["event"],
ev["event_ts"],
ev["link"],
)
tvg_id, logo = leagues.get_tvg_info(sport, event)
key = f"[{sport}] {event} ({TAG})"
entry = {
"url": url,
"logo": logo,
"base": BASE_URLS[sport],
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
tvg_id, logo = leagues.get_tvg_info(sport, event)
urls[key] = cached_urls[key] = entry
entry = {
"url": url,
"logo": logo,
"base": BASE_URLS[sport],
"timestamp": ts,
"id": tvg_id or "Live.Event.us",
"link": link,
}
urls[key] = cached_urls[key] = entry
finally:
await browser.close()
await browser.close()
if new_count := len(cached_urls) - cached_count:
log.info(f"Collected and cached {new_count} new event(s)")

View file

@ -1,10 +1,10 @@
## Base Log @ 2025-12-23 20:41 UTC
## Base Log @ 2025-12-22 21:06 UTC
### ✅ Working Streams: 145<br>❌ Dead Streams: 1
| Channel | Error (Code) | Link |
| ------- | ------------ | ---- |
| FDSN Florida | HTTP Error (403) | `http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/46794` |
| FDSN Southeast | HTTP Error (502) | `http://1tv41.icu:8080/8434692955/judgen64@yahoo.com/81111` |
---
#### Base Channels URL
```