init
This commit is contained in:
commit
6e1c25caa4
16 changed files with 80378 additions and 0 deletions
48
.github/workflows/epg.yml
vendored
Normal file
48
.github/workflows/epg.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: fetch epg
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 2,10,18 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
epg-fetcher:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache venv
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .venv
|
||||
key: shared-venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
shared-venv-${{ runner.os }}-
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
version: "latest"
|
||||
enable-cache: true
|
||||
ignore-nothing-to-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: "pyproject.toml"
|
||||
|
||||
- name: Fetch EPG
|
||||
run: uv run EPG/fetch.py
|
||||
|
||||
- name: Push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v6
|
||||
with:
|
||||
commit_message: "update EPG"
|
||||
file_pattern: "EPG/TV.xml"
|
||||
commit_author: "GitHub Actions Bot <actions@github.com>"
|
||||
commit_user_name: "GitHub Actions Bot"
|
||||
commit_user_email: "actions@github.com"
|
||||
27
.github/workflows/health.yml
vendored
Normal file
27
.github/workflows/health.yml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
name: health check
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2,8,14,20 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
health-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run health.sh
|
||||
run: bash health.sh
|
||||
|
||||
- name: Update log
|
||||
uses: stefanzweifel/git-auto-commit-action@v6
|
||||
with:
|
||||
commit_message: "health log"
|
||||
file_pattern: "readme.md"
|
||||
commit_author: "GitHub Actions Bot <actions@github.com>"
|
||||
commit_user_name: "GitHub Actions Bot"
|
||||
commit_user_email: "actions@github.com"
|
||||
56
.github/workflows/m3u8.yml
vendored
Normal file
56
.github/workflows/m3u8.yml
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
name: fetch m3u8
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 * * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
m3u8-fetcher:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check time
|
||||
run: |
|
||||
hour=$(TZ=America/New_York date +%-H)
|
||||
|
||||
if [ "$hour" -lt 8 ] || [ "$hour" -gt 23 ]; then
|
||||
exit 78
|
||||
fi
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache venv
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .venv
|
||||
key: shared-venv-${{ runner.os }}-${{ hashFiles('uv.lock') }}
|
||||
restore-keys: |
|
||||
shared-venv-${{ runner.os }}-
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v6
|
||||
with:
|
||||
version: "latest"
|
||||
enable-cache: true
|
||||
ignore-nothing-to-cache: true
|
||||
cache-dependency-glob: "uv.lock"
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version-file: "pyproject.toml"
|
||||
|
||||
- name: Fetch M3U8
|
||||
run: uv run M3U8/fetch.py
|
||||
|
||||
- name: Push changes
|
||||
uses: stefanzweifel/git-auto-commit-action@v6
|
||||
with:
|
||||
commit_message: "update M3U8"
|
||||
file_pattern: "M3U8/TV.m3u8 M3U8/scrape/tvpass.json"
|
||||
commit_author: "GitHub Actions Bot <actions@github.com>"
|
||||
commit_user_name: "GitHub Actions Bot"
|
||||
commit_user_email: "actions@github.com"
|
||||
14
.gitignore
vendored
Normal file
14
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Python-generated files
|
||||
__pycache__/
|
||||
*.py[oc]
|
||||
build/
|
||||
dist/
|
||||
wheels/
|
||||
*.egg-info
|
||||
|
||||
# Virtual environments
|
||||
.venv
|
||||
|
||||
# Misc
|
||||
.python-version
|
||||
stuff/
|
||||
79271
EPG/TV.xml
Normal file
79271
EPG/TV.xml
Normal file
File diff suppressed because it is too large
Load diff
95
EPG/fetch.py
Normal file
95
EPG/fetch.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
#!/usr/bin/env python3
|
||||
import gzip
|
||||
from pathlib import Path
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import httpx
|
||||
|
||||
epg_file = Path(__file__).parent / "TV.xml"
|
||||
epg_urls = [
|
||||
"https://epgshare01.online/epgshare01/epg_ripper_US1.xml.gz",
|
||||
"https://epgshare01.online/epgshare01/epg_ripper_US_LOCALS2.xml.gz",
|
||||
"https://epgshare01.online/epgshare01/epg_ripper_FANDUEL1.xml.gz",
|
||||
"https://epgshare01.online/epgshare01/epg_ripper_CA1.xml.gz",
|
||||
]
|
||||
|
||||
|
||||
def fetch_tvg_ids() -> dict[str, str]:
|
||||
try:
|
||||
r = httpx.get(
|
||||
"https://spoo.me/mvrlVh",
|
||||
follow_redirects=True,
|
||||
timeout=5,
|
||||
headers={
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36 Edg/134.0.0.0"
|
||||
},
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
except Exception as e:
|
||||
raise SystemExit(f"Failed to fetch TVG IDs\n{e}") from e
|
||||
|
||||
return r.json()
|
||||
|
||||
|
||||
def fetch_xml(url: str) -> ET.Element:
|
||||
try:
|
||||
r = httpx.get(
|
||||
url,
|
||||
follow_redirects=True,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
except Exception as e:
|
||||
raise SystemExit(f'Failed to fetch "{url}"\n{e}') from e
|
||||
|
||||
try:
|
||||
decompressed_data = gzip.decompress(r.content)
|
||||
|
||||
return ET.fromstring(decompressed_data)
|
||||
|
||||
except Exception as e:
|
||||
raise SystemExit(f'Failed to decompress and parse XML from "{url}"\n{e}') from e
|
||||
|
||||
|
||||
def main() -> None:
|
||||
tvg_ids = fetch_tvg_ids()
|
||||
|
||||
root = ET.Element("tv")
|
||||
|
||||
for url in epg_urls:
|
||||
epg_data = fetch_xml(url)
|
||||
|
||||
for channel in epg_data.findall("channel"):
|
||||
if (channel_id := channel.get("id")) in tvg_ids:
|
||||
for icon_tag in channel.findall("icon"):
|
||||
icon_tag.set("src", tvg_ids[channel_id])
|
||||
|
||||
if (url_tag := channel.find("url")) is not None:
|
||||
channel.remove(url_tag)
|
||||
|
||||
root.append(channel)
|
||||
|
||||
for program in epg_data.findall("programme"):
|
||||
tvg_id = program.get("channel")
|
||||
|
||||
if tvg_id in tvg_ids:
|
||||
if (title_text := program.find("title").text) in [
|
||||
"NHL Hockey",
|
||||
"Live: NFL Football",
|
||||
] and (subtitle := program.find("sub-title")) is not None:
|
||||
|
||||
program.find("title").text = f"{title_text} {subtitle.text}"
|
||||
|
||||
root.append(program)
|
||||
|
||||
tree = ET.ElementTree(root)
|
||||
|
||||
tree.write(epg_file, encoding="utf-8", xml_declaration=True)
|
||||
|
||||
print(f"EPG saved to {epg_file.name}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
24
LICENSE
Normal file
24
LICENSE
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
227
M3U8/TV.m3u8
Normal file
227
M3U8/TV.m3u8
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
#EXTM3U url-tvg="https://raw.githubusercontent.com/doms9/iptv/refs/heads/default/EPG/TV.xml"
|
||||
#EXTINF:-1 tvg-chno="1" tvg-id="ABC.(WABC).New.York,.NY.us" tvg-name="ABC" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10003_dark_360w_270h.png" group-title="TV",ABC
|
||||
http://fl1.moveonjoy.com/ABC_EAST/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="2" tvg-id="ACC.Network.us" tvg-name="ACC Network" tvg-logo="http://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s111871_dark_360w_270h.png" group-title="TV",ACC Network
|
||||
http://fl3.moveonjoy.com/ACC_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="3" tvg-id="AMC.-.Eastern.Feed.us" 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://fl5.moveonjoy.com/AMC_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="4" tvg-id="ASPiRE.TV.us" tvg-name="Aspire" tvg-logo="https://i.gyazo.com/0dec42cc5ef48c489cc10db906dc5b9b.png" group-title="TV",Aspire
|
||||
http://fl3.moveonjoy.com/Aspire/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="5" tvg-id="BET.-.Eastern.Feed.us" 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://fl3.moveonjoy.com/BET_EAST/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="6" tvg-id="Big.Ten.Network.us" 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://fl3.moveonjoy.com/BIG_TEN_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="7" tvg-id="Boomerang.us" 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://fl3.moveonjoy.com/BOOMERANG/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="8" tvg-id="Cartoon.Network.USA.-.Eastern.Feed.us" tvg-name="Cartoon Network" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12131_dark_360w_270h.png" group-title="TV",Cartoon Network
|
||||
http://fl3.moveonjoy.com/CARTOON_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="9" tvg-id="CBS.(WCBS).New.York,.NY.us" tvg-name="CBS" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10098_dark_360w_270h.png" group-title="TV",CBS
|
||||
http://fl1.moveonjoy.com/CBSEAST/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="10" tvg-id="CBS.Sports.Network.USA.us" tvg-name="CBS Sports Network" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16365_dark_360w_270h.png" group-title="TV",CBS Sports Network
|
||||
http://fl3.moveonjoy.com/CBS_SPORTS_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="11" tvg-id="CNBC.USA.us" tvg-name="CNBC" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10139_dark_360w_270h.png" group-title="TV",CNBC
|
||||
https://fl5.moveonjoy.com/CNBC/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="12" tvg-id="CNN.us" tvg-name="CNN" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s58646_dark_360w_270h.png" group-title="TV",CNN
|
||||
https://turnerlive.warnermediacdn.com/hls/live/586495/cnngo/cnn_slate/VIDEO_0_3564000.m3u8
|
||||
#EXTINF:-1 tvg-chno="13" tvg-id="Comedy.Central.(US).-.Eastern.Feed.us" tvg-name="Comedy Central" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10149_dark_360w_270h.png" group-title="TV",Comedy Central
|
||||
http://fl3.moveonjoy.com/Comedy_Central/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="14" tvg-id="WPIX.New.York.(SUPERSTATION).us" tvg-name="CW" tvg-logo="https://i.gyazo.com/afd5b481b327d204087dfde6a7741f9d.png" group-title="TV",CW
|
||||
http://user.scalecdn.co:8080/live/26725074/92867131/93093.m3u8
|
||||
#EXTINF:-1 tvg-chno="15" tvg-id="Discovery.Channel.(US).-.Eastern.Feed.us" tvg-name="Discovery Channel" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11150_dark_360w_270h.png" group-title="TV",Discovery Channel
|
||||
http://fl3.moveonjoy.com/Discovery_Channel/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="16" tvg-id="Disney.-.Eastern.Feed.us" tvg-name="Disney" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10171_dark_360w_270h.png" group-title="TV",Disney
|
||||
http://fl5.moveonjoy.com/DISNEY/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="17" tvg-id="Disney.XD.USA.-.Eastern.Feed.us" tvg-name="Disney XD" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s18279_dark_360w_270h.png" group-title="TV",Disney XD
|
||||
http://fl3.moveonjoy.com/DISNEY_XD/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="18" tvg-id="E!.Entertainment.USA.-.Eastern.Feed.us" tvg-name="E!" tvg-logo="https://i.gyazo.com/f73b80e3eb56cec06df6705d00e2f422.png" group-title="TV",E!
|
||||
http://fl3.moveonjoy.com/E_ENTERTAINMENT_TELEVISION/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="19" tvg-id="ESPN.us" tvg-name="ESPN" tvg-logo="https://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/25464931/30585186/14197
|
||||
#EXTINF:-1 tvg-chno="20" tvg-id="ESPN.News.us" tvg-name="ESPN News" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16485_dark_360w_270h.png" group-title="TV",ESPN News
|
||||
http://fl1.moveonjoy.com/ESPN_NEWS/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="21" tvg-id="ESPN.U.us" tvg-name="ESPN U" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s45654_dark_360w_270h.png" group-title="TV",ESPN U
|
||||
http://fl1.moveonjoy.com/ESPN_U/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="22" tvg-id="ESPN2.us" tvg-name="ESPN2" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s12444_dark_360w_270h.png" group-title="TV",ESPN2
|
||||
http://fl1.moveonjoy.com/ESPN_2/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="23" tvg-id="FanDuel.Sports.Network.Detroit.HD.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/25464931/30585186/20936
|
||||
#EXTINF:-1 tvg-chno="24" tvg-id="FanDuel.Sports.Network.North.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/25464931/30585186/58827
|
||||
#EXTINF:-1 tvg-chno="25" tvg-id="FanDuel.Sports.Network.Oklahoma.us" tvg-name="FDSN Oklahoma" tvg-logo="https://i.gyazo.com/80ad6fd142cd67f06eef58d9ce5aa72b.png" group-title="TV",FDSN Oklahoma
|
||||
http://cord-cutter.net:8080/25464931/30585186/20934
|
||||
#EXTINF:-1 tvg-chno="26" tvg-id="FanDuel.Sports.Network.Southwest.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/25464931/30585186/21843
|
||||
#EXTINF:-1 tvg-chno="27" tvg-id="FanDuel.Sports.Network.West.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/25464931/30585186/20932
|
||||
#EXTINF:-1 tvg-chno="28" tvg-id="FOX.(WNYW).New.York,.NY.us" tvg-name="Fox" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s28719_dark_360w_270h.png" group-title="TV",Fox
|
||||
http://fl1.moveonjoy.com/FOX_EAST/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="29" tvg-id="Fox.News.us" tvg-name="Fox News" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16374_dark_360w_270h.png" group-title="TV",Fox News
|
||||
https://stream.livenewsplay.com:9443/hls/foxnews/foxsd.m3u8
|
||||
#EXTINF:-1 tvg-chno="30" tvg-id="Fox.Sports.1.us" tvg-name="Fox Sports 1" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s82541_dark_360w_270h.png" group-title="TV",Fox Sports 1
|
||||
http://23.237.104.106:8080/USA_FS1/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="31" tvg-id="Fox.Sports.2.us" tvg-name="Fox Sports 2" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s33178_dark_360w_270h.png" group-title="TV",Fox Sports 2
|
||||
http://23.237.104.106:8080/USA_FS2/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="32" tvg-id="FUSE.TV.-.Eastern.feed.us" tvg-name="FUSE" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14929_dark_360w_270h.png" group-title="TV",FUSE
|
||||
http://fl3.moveonjoy.com/FUSE/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="33" tvg-id="FX.Networks.East.Coast.us" tvg-name="FX" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s14321_dark_360w_270h.png" group-title="TV",FX
|
||||
http://fl5.moveonjoy.com/FX/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="34" tvg-id="FX.Movie.Channel.us" tvg-name="FX Movie Channel" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s70253_dark_360w_270h.png" group-title="TV",FX Movie Channel
|
||||
http://fl3.moveonjoy.com/FX_MOVIE/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="35" tvg-id="FXX.USA.-.Eastern.us" 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://fl3.moveonjoy.com/FXX/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="36" tvg-id="Game.Show.Network.-.East.us" tvg-name="Game Show Network" tvg-logo="https://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/25464931/30585186/120633
|
||||
#EXTINF:-1 tvg-chno="37" tvg-id="HBO.-.Eastern.Feed.us" tvg-name="HBO" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10240_dark_360w_270h.png" group-title="TV",HBO
|
||||
http://fl3.moveonjoy.com/HBO/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="38" tvg-id="ION..-.Eastern.Feed.us" 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://fl3.moveonjoy.com/ION_TV/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="39" tvg-id="Marquee.Sports.Network.us" 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/25464931/30585186/13379
|
||||
#EXTINF:-1 tvg-chno="40" tvg-id="MLB.Network.us" 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
|
||||
http://fl5.moveonjoy.com/MLB_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="41" tvg-id="MSG.(Madison.Square.Gardens).us" 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
|
||||
https://fl3.moveonjoy.com/MSG/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="42" tvg-id="MSNBC.USA.us" tvg-name="MSNBC" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s16300_dark_360w_270h.png" group-title="TV",MSNBC
|
||||
https://fl5.moveonjoy.com/MSNBC/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="43" tvg-id="NBA.TV.USA.us" tvg-name="NBA TV" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s32281_dark_360w_270h.png" group-title="TV",NBA TV
|
||||
http://fl3.moveonjoy.com/NBA_TV/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="44" tvg-id="NBC.(WNBC).New.York,.NY.us" tvg-name="NBC" tvg-logo="https://i.gyazo.com/39d42952500205d04e448247b7889256.png" group-title="TV",NBC
|
||||
http://fl1.moveonjoy.com/NBC_EAST/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="45" tvg-id="NBC.Sports.Boston.us" tvg-name="NBC Sports Boston" tvg-logo="https://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/25464931/30585186/20939
|
||||
#EXTINF:-1 tvg-chno="46" tvg-id="NBC.Sports.Philadelphia.HDTV.(NBCSPAHD).us" tvg-name="NBC Sports Philadelphia" tvg-logo="https://i.gyazo.com/c5204722cef60da756f1b994d6d71c28.png" group-title="TV",NBC Sports Philadelphia
|
||||
http://cord-cutter.net:8080/25464931/30585186/20943
|
||||
#EXTINF:-1 tvg-chno="47" tvg-id="NFL.Network.us" 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://fl5.moveonjoy.com/NFL_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="48" tvg-id="NFL.RedZone.us" 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://fl1.moveonjoy.com/NFL_RedZone/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="49" tvg-id="NHL.Network.USA.us" 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://fl1.moveonjoy.com/NHL_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="50" tvg-id="Nickelodeon.USA.-.East.Feed.us" tvg-name="Nickelodeon" tvg-logo="https://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/25464931/30585186/38
|
||||
#EXTINF:-1 tvg-chno="51" tvg-id="Nicktoons.-.East.us" tvg-name="Nicktoons" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s30420_dark_360w_270h.png" group-title="TV",Nicktoons
|
||||
http://fl1.moveonjoy.com/NICKTOONS/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="52" tvg-id="Root.Sports.Northwest.us" 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/25464931/30585186/85232
|
||||
#EXTINF:-1 tvg-chno="53" tvg-id="SEC.Network.us" 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://fl1.moveonjoy.com/SEC_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="54" tvg-id="Paramount+.with.Showtime.-.Eastern.Feed.us" 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://fl3.moveonjoy.com/SHOWTIME/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="55" tvg-id="SNY:.SportsNet.New.York.(Comcast).us" 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
|
||||
https://fl3.moveonjoy.com/SNY/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="56" tvg-id="Sportsnet.One.ca" 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/25464931/30585186/10247
|
||||
#EXTINF:-1 tvg-chno="57" tvg-id="SportsNet.Pittsburgh.us" 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/25464931/30585186/108178
|
||||
#EXTINF:-1 tvg-chno="58" tvg-id="Starz.-.Eastern.us" 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
|
||||
https://fl3.moveonjoy.com/STARZ/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="59" tvg-id="TBS.-.East.us" tvg-name="TBS" tvg-logo="https://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
|
||||
#EXTINF:-1 tvg-chno="60" tvg-id="TLC.USA.-.Eastern.us" tvg-name="TLC" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11158_dark_360w_270h.png" group-title="TV",TLC
|
||||
http://fl1.moveonjoy.com/TLC/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="61" tvg-id="TNT.-.Eastern.Feed.us" tvg-name="TNT" tvg-logo="https://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
|
||||
#EXTINF:-1 tvg-chno="62" tvg-id="truTV.USA.-.Eastern.us" tvg-name="truTV" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s10153_dark_360w_270h.png" group-title="TV",truTV
|
||||
https://turnerlive.warnermediacdn.com/hls/live/2023176/trueast/slate/VIDEO_0_3564000.m3u8
|
||||
#EXTINF:-1 tvg-chno="63" tvg-id="TSN1.ca" 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/25464931/30585186/57292
|
||||
#EXTINF:-1 tvg-chno="64" tvg-id="TSN2.ca" 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://fl5.moveonjoy.com/TSN_2/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="65" tvg-id="USA.Network.-.East.Feed.us" tvg-name="USA East" tvg-logo="https://schedulesdirect-api20141201-logos.s3.dualstack.us-east-1.amazonaws.com/stationLogos/s11207_dark_360w_270h.png" group-title="TV",USA East
|
||||
http://4c66041f.tvclub.xyz/iptv/E3TZUWKUS8PTA7/31124/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="66" tvg-id="YES.Network.us" 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://fl5.moveonjoy.com/YES_NETWORK/index.m3u8
|
||||
#EXTINF:-1 tvg-chno="67" tvg-id="(N/A)" tvg-name="[MLB] Philadelphia Phillies @ Washington Nationals" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Philadelphia Phillies @ Washington Nationals
|
||||
https://tvpass.org/live/mlb-01/sd
|
||||
#EXTINF:-1 tvg-chno="68" tvg-id="(N/A)" tvg-name="[WNBA] Indiana Fever @ Connecticut Sun" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[WNBA] Indiana Fever @ Connecticut Sun
|
||||
https://tvpass.org/live/WNBA01/sd
|
||||
#EXTINF:-1 tvg-chno="69" tvg-id="(N/A)" tvg-name="[NFL] Jacksonville Jaguars @ New Orleans Saints" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[NFL] Jacksonville Jaguars @ New Orleans Saints
|
||||
https://tvpass.org/live/NFL23/sd
|
||||
#EXTINF:-1 tvg-chno="70" tvg-id="(N/A)" tvg-name="[MLB] Miami Marlins @ Boston Red Sox" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Miami Marlins @ Boston Red Sox
|
||||
https://tvpass.org/live/mlb-22/sd
|
||||
#EXTINF:-1 tvg-chno="71" tvg-id="(N/A)" tvg-name="[MLB] Texas Rangers @ Toronto Blue Jays" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Texas Rangers @ Toronto Blue Jays
|
||||
https://tvpass.org/live/mlb-12/sd
|
||||
#EXTINF:-1 tvg-chno="72" tvg-id="(N/A)" tvg-name="[MLB] Atlanta Braves @ Cleveland Guardians" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Atlanta Braves @ Cleveland Guardians
|
||||
https://tvpass.org/live/mlb-30/sd
|
||||
#EXTINF:-1 tvg-chno="73" tvg-id="(N/A)" tvg-name="[MLB] Milwaukee Brewers @ Cincinnati Reds" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Milwaukee Brewers @ Cincinnati Reds
|
||||
https://tvpass.org/live/mlb-04/sd
|
||||
#EXTINF:-1 tvg-chno="74" tvg-id="(N/A)" tvg-name="[MLB] Baltimore Orioles @ Houston Astros" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Baltimore Orioles @ Houston Astros
|
||||
https://tvpass.org/live/mlb-06/sd
|
||||
#EXTINF:-1 tvg-chno="75" tvg-id="(N/A)" tvg-name="[MLB] Chicago White Sox @ Kansas City Royals" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Chicago White Sox @ Kansas City Royals
|
||||
https://tvpass.org/live/mlb-05/sd
|
||||
#EXTINF:-1 tvg-chno="76" tvg-id="(N/A)" tvg-name="[MLB] Detroit Tigers @ Minnesota Twins" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Detroit Tigers @ Minnesota Twins
|
||||
https://tvpass.org/live/mlb-20/sd
|
||||
#EXTINF:-1 tvg-chno="77" tvg-id="(N/A)" tvg-name="[MLB] New York Yankees @ St. Louis Cardinals" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] New York Yankees @ St. Louis Cardinals
|
||||
https://tvpass.org/live/mlb-08/sd
|
||||
#EXTINF:-1 tvg-chno="78" tvg-id="(N/A)" tvg-name="[MLB] Pittsburgh Pirates @ Chicago Cubs" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Pittsburgh Pirates @ Chicago Cubs
|
||||
https://tvpass.org/live/mlb-23/sd
|
||||
#EXTINF:-1 tvg-chno="79" tvg-id="(N/A)" tvg-name="[WNBA] Los Angeles Sparks @ Washington Mystics" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[WNBA] Los Angeles Sparks @ Washington Mystics
|
||||
https://tvpass.org/live/WNBA02/sd
|
||||
#EXTINF:-1 tvg-chno="80" tvg-id="(N/A)" tvg-name="[MLB] Arizona Diamondbacks @ Colorado Rockies" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Arizona Diamondbacks @ Colorado Rockies
|
||||
https://tvpass.org/live/mlb-25/sd
|
||||
#EXTINF:-1 tvg-chno="81" tvg-id="(N/A)" tvg-name="[WNBA] Dallas Wings @ Las Vegas Aces" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[WNBA] Dallas Wings @ Las Vegas Aces
|
||||
https://tvpass.org/live/WNBA03/sd
|
||||
#EXTINF:-1 tvg-chno="82" tvg-id="(N/A)" tvg-name="[MLB] Los Angeles Angels @ Oakland Athletics" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Los Angeles Angels @ Oakland Athletics
|
||||
https://tvpass.org/live/mlb-19/sd
|
||||
#EXTINF:-1 tvg-chno="83" tvg-id="(N/A)" tvg-name="[MLB] Tampa Bay Rays @ San Francisco Giants" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Tampa Bay Rays @ San Francisco Giants
|
||||
https://tvpass.org/live/mlb-27/sd
|
||||
#EXTINF:-1 tvg-chno="84" tvg-id="(N/A)" tvg-name="[MLB] San Diego Padres @ Los Angeles Dodgers" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] San Diego Padres @ Los Angeles Dodgers
|
||||
https://tvpass.org/live/mlb-14/sd
|
||||
#EXTINF:-1 tvg-chno="85" tvg-id="(N/A)" tvg-name="[WNBA] Phoenix Mercury @ Seattle Storm" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[WNBA] Phoenix Mercury @ Seattle Storm
|
||||
https://tvpass.org/live/WNBA04/sd
|
||||
#EXTINF:-1 tvg-chno="86" tvg-id="(N/A)" tvg-name="[MLB] Seattle Mariners @ New York Mets" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[MLB] Seattle Mariners @ New York Mets
|
||||
https://tvpass.org/live/mlb-24/sd
|
||||
#EXTINF:-1 tvg-chno="87" tvg-id="(N/A)" tvg-name="[NFL] Buffalo Bills @ Chicago Bears" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[NFL] Buffalo Bills @ Chicago Bears
|
||||
https://tvpass.org/live/NFL11/sd
|
||||
#EXTINF:-1 tvg-chno="88" tvg-id="(N/A)" tvg-name="[WNBA] Atlanta Dream @ Golden State Valkyries" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[WNBA] Atlanta Dream @ Golden State Valkyries
|
||||
https://tvpass.org/live/WNBA05/sd
|
||||
#EXTINF:-1 tvg-chno="89" tvg-id="(N/A)" tvg-name="[Premier League] Nottingham Forest vs Brentford (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Premier League] Nottingham Forest vs Brentford (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NTMwMTUyNDhlM2ExLTAwMGItNjE3NC02OGM0LThjZDU4YmQy/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="90" tvg-id="(N/A)" tvg-name="[Premier League] Nottingham Forest vs Brentford (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Premier League] Nottingham Forest vs Brentford (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/variant/VE1AO1NTbu8mbv12LxEWM21ycrNWYyR3LhdTO3kTZwcDZyczYtMWYmFWL3UGZ00CZ4MDZtQTN3czY4M2M/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="91" tvg-id="(N/A)" tvg-name="[Premier League] Nottingham Forest vs Brentford (S3)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Premier League] Nottingham Forest vs Brentford (S3)
|
||||
https://subrugopuciblchlvl6uqa666p23rig.happy-ending.site/fishy-smell/ed4bbd1554e94cc86f65e40166b1fec4.m3u8?auth=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdHJlYW1JZCI6ImVkNGJiZDE1NTRlOTRjYzg2ZjY1ZTQwMTY2YjFmZWM0IiwidHlwZSI6InBsYXlsaXN0X2FjY2VzcyIsImlhdCI6MTc1NTQzNjY4MSwiZXhwIjoxNzU1NDQ3NDgxfQ.dCRhM3JFUGE0VDZZbGt1dHVDJG8
|
||||
#EXTINF:-1 tvg-chno="92" tvg-id="(N/A)" tvg-name="[Championship] Hull City vs Oxford United (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Championship] Hull City vs Oxford United (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NjU5NGU0NzYwMGEwLTIwZmItMWNiNC1iMDI4LTYzZmM5NjU3/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="93" tvg-id="(N/A)" tvg-name="[Championship] Hull City vs Oxford United (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Championship] Hull City vs Oxford United (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1YzU2MjI0ZGQ0MTBhLTllNzgtMGEzNC0yNDg3LTUyMjFjZDUw/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="94" tvg-id="(N/A)" tvg-name="[DFB Pokal] Lokomotive Leipzig vs FC Schalke 04 (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[DFB Pokal] Lokomotive Leipzig vs FC Schalke 04 (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NWZjYWY1ZGRjOTljLWQzMjktMWZlNC1iYmZjLTM5YzY2ODFh/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="95" tvg-id="(N/A)" tvg-name="[Ligue 1] Stade Brestois 29 vs Lille (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Ligue 1] Stade Brestois 29 vs Lille (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NzdiN2IwMTM2MzRmLTAwNmItNjM3NC05ZWJmLWFmZmYxNzU2/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="96" tvg-id="(N/A)" tvg-name="[Ligue 1] Stade Brestois 29 vs Lille (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Ligue 1] Stade Brestois 29 vs Lille (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MWZlMDAwZTlmM2QyLWUzMGItYjVmNC0zMDhjLTViNGQ3YTRl/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="97" tvg-id="(N/A)" tvg-name="[Moto GP] MotoGP | Round 13 | Austria 🏍 (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Moto GP] MotoGP | Round 13 | Austria 🏍 (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NGY2YTlkMjFlMzNiLTNlN2ItZTQ4NC1jMWVjLWY5ZjU0Mzg5/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="98" tvg-id="(N/A)" tvg-name="[Moto GP] MotoGP | Round 13 | Austria 🏍 (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Moto GP] MotoGP | Round 13 | Austria 🏍 (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1ZmI4NzhmOGI3ZGUwLTU4Y2ItNjJhNC1iYjlmLTYyNGM4ZGZm/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="99" tvg-id="(N/A)" tvg-name="[Racing] Sweden | MX2 | Race 1 & 2 (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Racing] Sweden | MX2 | Race 1 & 2 (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MzMyYzk1MGY3ZWIyLWM3NzgtNjNkNC1jODNhLWZmYjRjYzg1/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="100" tvg-id="(N/A)" tvg-name="[Racing] Sweden | MX2 | Race 1 & 2 (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Racing] Sweden | MX2 | Race 1 & 2 (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MDJhM2Q4MmIzYTc3LWJhMjgtMGM2NC0yN2IwLTA4M2Q2NDkz/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="101" tvg-id="(N/A)" tvg-name="[Eredivisie] Twente vs PSV Eindhoven (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Eredivisie] Twente vs PSV Eindhoven (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MmUzYTQyNGU1ODZjLWE1OTgtYTE5NC1lYzcwLWEyZmVjOTk1/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="102" tvg-id="(N/A)" tvg-name="[Eredivisie] Twente vs PSV Eindhoven (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Eredivisie] Twente vs PSV Eindhoven (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1YzRkNjI0OWU1Nzc5LTMyM2EtZWE5NC1lYTZhLWViODNhMTA0/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="103" tvg-id="(N/A)" tvg-name="[Eredivisie] Twente vs PSV Eindhoven (S3)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Eredivisie] Twente vs PSV Eindhoven (S3)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1OWQ3NWJhMGY1Zjk0LTU3OTgtNmUwNC05YTkyLWM1M2IyNzA0/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="104" tvg-id="(N/A)" tvg-name="[Superliga] Vejle vs FC Midtjylland (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Superliga] Vejle vs FC Midtjylland (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1ZTkwZTUzMTE3MjEwLWYyM2ItNjE4NC04ZjVkLWNlY2ZiOWI2/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="105" tvg-id="(N/A)" tvg-name="[African Nations Championship] Congo DR vs Morocco (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[African Nations Championship] Congo DR vs Morocco (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1YWYzMWU2OTM4MGUwLWNjYTgtMjMxNC05YWMzLTNjYzFkMmI0/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="106" tvg-id="(N/A)" tvg-name="[Betfred Super League] St Helens vs Huddersfield (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Betfred Super League] St Helens vs Huddersfield (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NTVkYzFhNDNkNGI2LWUwMWItNDBmNC1jZDQwLTdhZmIxYWNl/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="107" tvg-id="(N/A)" tvg-name="[Segunda Liga] Penafiel vs Oliveirense (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Segunda Liga] Penafiel vs Oliveirense (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1Yjc3YTEzYzkzODQ4LWJmMDktZjVhNC1jOWMzLWJkMzQ5ZTRi/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="108" tvg-id="(N/A)" tvg-name="[CYCLING] Czech Tour | Stage 4 - Men | Kroměříž - Pustevny (179km) (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[CYCLING] Czech Tour | Stage 4 - Men | Kroměříž - Pustevny (179km) (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NTE5MmVjYzhmYTE3LWZkMDgtZDQ2NC0xMzU3LWE5MmE0Mzk3/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="109" tvg-id="(N/A)" tvg-name="[Allsvenskan] IFK Goteborg vs AIK Stockholm (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Allsvenskan] IFK Goteborg vs AIK Stockholm (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MTgwODFiMzBlYjNjLTcyMzktZTUwNC0wOWRkLTY3NzE3NWUy/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="110" tvg-id="(N/A)" tvg-name="[League Cup] Kilmarnock vs Dundee Utd (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[League Cup] Kilmarnock vs Dundee Utd (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1MmE1YzBjODczNmVhLTlmNjktYjQ5NC0xYWRhLWUzMThiMDQw/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="111" tvg-id="(N/A)" tvg-name="[Liga I] Csikszereda vs Universitatea Craiova (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Liga I] Csikszereda vs Universitatea Craiova (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1ZmMxMGExZmZhMGU3LTg0ZmItNWVjNC1kZTg2LWU5ODZhYmQ2/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="112" tvg-id="(N/A)" tvg-name="[Golf] Danish Golf Championship, Final Round - European PGA Tour Golf (S1)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Golf] Danish Golf Championship, Final Round - European PGA Tour Golf (S1)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1ZTg2ZTEzZTk2ZTQzLThiMmEtYzkxNC04ODNhLTM5MThlZGQz/master.m3u8
|
||||
#EXTINF:-1 tvg-chno="113" tvg-id="(N/A)" tvg-name="[Golf] Danish Golf Championship, Final Round - European PGA Tour Golf (S2)" tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png" group-title="Live Events",[Golf] Danish Golf Championship, Final Round - European PGA Tour Golf (S2)
|
||||
https://5nhp186eg31fofnc.chinese-restaurant-api.site/v3/director/VE1NmNmOTRlN2Q4ZDg2LTlhNTktYjEyNC1iZGVkLWEzNjI5NzBh/master.m3u8
|
||||
78
M3U8/fetch.py
Normal file
78
M3U8/fetch.py
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#!/usr/bin/env python3
|
||||
import json
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
import pytz
|
||||
from scrape import fstv, tvpass
|
||||
|
||||
m3u8_file = Path(__file__).parent / "TV.m3u8"
|
||||
|
||||
base = "http://m3u4u.com/m3u/d5k2nvp8w2t3w2k1n984"
|
||||
|
||||
current_hour = datetime.now(pytz.timezone("America/New_York")).hour
|
||||
|
||||
|
||||
def vanilla_fetch() -> tuple[list[str], int]:
|
||||
print("Fetching base M3U8")
|
||||
|
||||
try:
|
||||
r = httpx.get(
|
||||
base,
|
||||
follow_redirects=True,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
except Exception as e:
|
||||
raise SystemExit(f'Failed to fetch "{base}"\n{e}') from e
|
||||
|
||||
d = r.text.splitlines()
|
||||
|
||||
d.pop(0)
|
||||
|
||||
last_chnl_number = int(r.text.split("tvg-chno=")[-1].split('"')[1])
|
||||
|
||||
return d, last_chnl_number
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if current_hour <= 11:
|
||||
tvpass.main()
|
||||
else:
|
||||
try:
|
||||
tvpass.urls = json.loads(tvpass.base_file.read_text(encoding="utf-8"))
|
||||
except (FileNotFoundError, json.JSONDecodeError):
|
||||
pass
|
||||
|
||||
fstv.main()
|
||||
|
||||
base_m3u8, chnl_number = vanilla_fetch()
|
||||
|
||||
m3u8_file.write_text(
|
||||
'#EXTM3U url-tvg="https://raw.githubusercontent.com/doms9/iptv/refs/heads/default/EPG/TV.xml"\n'
|
||||
+ "\n".join(base_m3u8)
|
||||
+ "\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
additions = tvpass.urls | fstv.urls
|
||||
|
||||
for event, url in additions.items():
|
||||
chnl_number += 1
|
||||
|
||||
with m3u8_file.open("a", encoding="utf-8") as f:
|
||||
f.write(f'#EXTINF:-1 tvg-chno="{chnl_number}"')
|
||||
f.write(f' tvg-id="(N/A)" tvg-name="{event}"')
|
||||
f.write(
|
||||
' tvg-logo="https://i.gyazo.com/ec27417a9644ae517196494afa72d2b9.png"'
|
||||
)
|
||||
f.write(' group-title="Live Events"')
|
||||
f.write(f",{event}\n{url}\n")
|
||||
|
||||
print(f"M3U8 saved to {m3u8_file.name}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
118
M3U8/scrape/fstv.py
Normal file
118
M3U8/scrape/fstv.py
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
from urllib.parse import urljoin
|
||||
|
||||
import httpx
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
urls: dict[str, str] = {}
|
||||
|
||||
mirrors = {"https://fstv.online", "https://fstv.space", "https://fstv.zip"}
|
||||
|
||||
|
||||
def check_status(l: str) -> bool:
|
||||
try:
|
||||
r = httpx.get(l)
|
||||
r.raise_for_status()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
return r.status_code == 200
|
||||
|
||||
|
||||
def get_base() -> str:
|
||||
for url in filter(check_status, mirrors):
|
||||
return url
|
||||
|
||||
|
||||
def get_hrefs(base_url: str) -> list[tuple[str, str]] | tuple[None, None]:
|
||||
print(f'Scraping from "{base_url}"')
|
||||
|
||||
try:
|
||||
r = httpx.get(
|
||||
base_url,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
except Exception as e:
|
||||
print(f'Failed to fetch "{base_url}"\n{e}')
|
||||
|
||||
return None, None
|
||||
|
||||
soup = BeautifulSoup(r.text, "lxml")
|
||||
|
||||
events = {}
|
||||
|
||||
for wrpr in soup.find_all("div", class_="fixtures-live-wrapper"):
|
||||
for games in wrpr.select(".match-table-item"):
|
||||
|
||||
league_name = games.select_one(".league-info a.league-name")
|
||||
|
||||
league_match = games.select_one(".common-table-row a[href*='/match/']")
|
||||
|
||||
if league_name and league_match:
|
||||
full_text = league_name.get_text(strip=True)
|
||||
|
||||
if "]" in full_text:
|
||||
event_name = full_text.split("]", 1)[1].strip()
|
||||
else:
|
||||
event_name = full_text
|
||||
|
||||
events[event_name] = urljoin(base_url, league_match["href"])
|
||||
|
||||
return events.items()
|
||||
|
||||
|
||||
def fetch_m3u8(url: str) -> tuple[str, list[str]] | tuple[None, None]:
|
||||
try:
|
||||
r = httpx.get(
|
||||
url,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
except Exception as e:
|
||||
print(f'Failed to fetch "{url}"\n{e}')
|
||||
|
||||
return None, None
|
||||
|
||||
soup = BeautifulSoup(r.text, "lxml")
|
||||
|
||||
if category_links := soup.select(".common-list-category .category-item a"):
|
||||
match_name = category_links[-1].get_text(strip=True)
|
||||
else:
|
||||
match_name = None
|
||||
|
||||
if not match_name or match_name.lower() == "vs":
|
||||
if og_title := soup.find("meta", property="og:title"):
|
||||
match_name = og_title["content"].split(" start on")[0].strip()
|
||||
|
||||
btns = soup.select("button.btn-server")
|
||||
|
||||
return match_name, [btn["data-link"] for btn in btns if btn.has_attr("data-link")]
|
||||
|
||||
|
||||
def main() -> None:
|
||||
for event, href in get_hrefs(get_base()):
|
||||
|
||||
if not href:
|
||||
return
|
||||
|
||||
match_name, m3u8_urls = fetch_m3u8(href)
|
||||
|
||||
if not m3u8_urls:
|
||||
return
|
||||
|
||||
for i, link in enumerate(m3u8_urls, start=1):
|
||||
key = (
|
||||
f"[{event}] (S{i})"
|
||||
if not match_name
|
||||
else f"[{event}] {match_name} (S{i})"
|
||||
)
|
||||
|
||||
urls[key] = link
|
||||
|
||||
print(f"Collected {len(urls)} live events")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
24
M3U8/scrape/tvpass.json
Normal file
24
M3U8/scrape/tvpass.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"[MLB] Philadelphia Phillies @ Washington Nationals": "https://tvpass.org/live/mlb-01/sd",
|
||||
"[WNBA] Indiana Fever @ Connecticut Sun": "https://tvpass.org/live/WNBA01/sd",
|
||||
"[NFL] Jacksonville Jaguars @ New Orleans Saints": "https://tvpass.org/live/NFL23/sd",
|
||||
"[MLB] Miami Marlins @ Boston Red Sox": "https://tvpass.org/live/mlb-22/sd",
|
||||
"[MLB] Texas Rangers @ Toronto Blue Jays": "https://tvpass.org/live/mlb-12/sd",
|
||||
"[MLB] Atlanta Braves @ Cleveland Guardians": "https://tvpass.org/live/mlb-30/sd",
|
||||
"[MLB] Milwaukee Brewers @ Cincinnati Reds": "https://tvpass.org/live/mlb-04/sd",
|
||||
"[MLB] Baltimore Orioles @ Houston Astros": "https://tvpass.org/live/mlb-06/sd",
|
||||
"[MLB] Chicago White Sox @ Kansas City Royals": "https://tvpass.org/live/mlb-05/sd",
|
||||
"[MLB] Detroit Tigers @ Minnesota Twins": "https://tvpass.org/live/mlb-20/sd",
|
||||
"[MLB] New York Yankees @ St. Louis Cardinals": "https://tvpass.org/live/mlb-08/sd",
|
||||
"[MLB] Pittsburgh Pirates @ Chicago Cubs": "https://tvpass.org/live/mlb-23/sd",
|
||||
"[WNBA] Los Angeles Sparks @ Washington Mystics": "https://tvpass.org/live/WNBA02/sd",
|
||||
"[MLB] Arizona Diamondbacks @ Colorado Rockies": "https://tvpass.org/live/mlb-25/sd",
|
||||
"[WNBA] Dallas Wings @ Las Vegas Aces": "https://tvpass.org/live/WNBA03/sd",
|
||||
"[MLB] Los Angeles Angels @ Oakland Athletics": "https://tvpass.org/live/mlb-19/sd",
|
||||
"[MLB] Tampa Bay Rays @ San Francisco Giants": "https://tvpass.org/live/mlb-27/sd",
|
||||
"[MLB] San Diego Padres @ Los Angeles Dodgers": "https://tvpass.org/live/mlb-14/sd",
|
||||
"[WNBA] Phoenix Mercury @ Seattle Storm": "https://tvpass.org/live/WNBA04/sd",
|
||||
"[MLB] Seattle Mariners @ New York Mets": "https://tvpass.org/live/mlb-24/sd",
|
||||
"[NFL] Buffalo Bills @ Chicago Bears": "https://tvpass.org/live/NFL11/sd",
|
||||
"[WNBA] Atlanta Dream @ Golden State Valkyries": "https://tvpass.org/live/WNBA05/sd"
|
||||
}
|
||||
69
M3U8/scrape/tvpass.py
Normal file
69
M3U8/scrape/tvpass.py
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import httpx
|
||||
|
||||
base_url = "https://tvpass.org/playlist/m3u"
|
||||
base_file = Path(__file__).parent / "tvpass.json"
|
||||
|
||||
urls: dict[str, str] = {}
|
||||
|
||||
|
||||
def fetch_m3u8() -> list[str] | None:
|
||||
try:
|
||||
r = httpx.get(
|
||||
base_url,
|
||||
follow_redirects=True,
|
||||
timeout=5,
|
||||
)
|
||||
|
||||
r.raise_for_status()
|
||||
|
||||
except Exception as e:
|
||||
print(f'Failed to fetch "{base_url}"\n{e}')
|
||||
|
||||
return
|
||||
|
||||
return r.text.splitlines()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
print(f'Scraping from "{base_url}"')
|
||||
|
||||
if not (data := fetch_m3u8()):
|
||||
return
|
||||
|
||||
for i in range(len(data) - 1):
|
||||
if data[i].startswith("#EXTINF"):
|
||||
tvg_id_match = re.search(r'tvg-id="([^"]*)"', data[i])
|
||||
tvg_name_match = re.search(r'tvg-name="([^"]*)"', data[i])
|
||||
|
||||
tvg_id = tvg_id_match[1] if tvg_id_match else None
|
||||
tvg_name = tvg_name_match[1]
|
||||
|
||||
if tvg_id == "":
|
||||
url = data[i + 1]
|
||||
|
||||
tvg_name = tvg_name.split("(")[0].strip()
|
||||
|
||||
if url.endswith("/sd"):
|
||||
|
||||
path_parts = urlparse(url).path.strip("/").split("/")
|
||||
|
||||
if len(path_parts) >= 2 and path_parts[-1] == "sd":
|
||||
sport = "".join(x for x in path_parts[1] if x.isalpha()).upper()
|
||||
else:
|
||||
sport = "UNKNWN"
|
||||
|
||||
urls[f"[{sport}] {tvg_name}"] = url
|
||||
|
||||
print(f"Collected {len(urls)} live events")
|
||||
|
||||
if urls:
|
||||
base_file.write_text(json.dumps(urls, indent=2), encoding="utf-8")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
130
health.sh
Normal file
130
health.sh
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
#!/bin/bash
|
||||
main="http://m3u4u.com/m3u/d5k2nvp8w2t3w2k1n984"
|
||||
MAX_JOBS=10
|
||||
RETRY_COUNT=3
|
||||
README="./readme.md"
|
||||
STATUSLOG=$(mktemp)
|
||||
PASSED=0
|
||||
FAILED=0
|
||||
REDIRECTED=0
|
||||
EMPTY=0
|
||||
|
||||
get_status() {
|
||||
local url="$1"
|
||||
local channel="$2"
|
||||
local attempt response status_code
|
||||
|
||||
[[ "$url" != http* ]] && return
|
||||
|
||||
for attempt in $(seq 1 "$RETRY_COUNT"); do
|
||||
response=$(curl -sL -o /dev/null --max-time 10 -w "%{http_code}" "$url" 2>&1)
|
||||
[[ "$response" =~ ^[0-9]+$ ]] && break
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [[ ! "$response" =~ ^[0-9]+$ ]]; then
|
||||
if [[ "$response" == *"timed out"* ]]; then
|
||||
echo "| $channel | Connection timed out | \`$url\` |" >>"$STATUSLOG"
|
||||
else
|
||||
echo "| $channel | Curl error | \`$url\` |" >>"$STATUSLOG"
|
||||
fi
|
||||
echo "FAIL" >>"$STATUSLOG"
|
||||
return
|
||||
fi
|
||||
|
||||
status_code="$response"
|
||||
|
||||
case "$status_code" in
|
||||
200)
|
||||
if ! curl -sL --max-time 5 "$url" | head -c 1 | grep -q '.'; then
|
||||
echo "| $channel | Empty body (404) | \`$url\` |" >>"$STATUSLOG"
|
||||
echo "EMPTY" >>"$STATUSLOG"
|
||||
else
|
||||
echo "PASS" >>"$STATUSLOG"
|
||||
fi
|
||||
;;
|
||||
301 | 302 | 307 | 308)
|
||||
redirect_url=$(curl -sI --max-time 5 "$url" | grep -i '^Location:' | sed 's/Location: //I' | tr -d '\r\n')
|
||||
echo "| $channel | Redirect ($status_code) | \`$url → $redirect_url\` |" >>"$STATUSLOG"
|
||||
echo "REDIRECT" >>"$STATUSLOG"
|
||||
;;
|
||||
4* | 5*)
|
||||
echo "| $channel | HTTP Error ($status_code) | \`$url\` |" >>"$STATUSLOG"
|
||||
echo "FAIL" >>"$STATUSLOG"
|
||||
;;
|
||||
*)
|
||||
if [[ "$status_code" == "000" ]]; then
|
||||
echo "| $channel | Connection timed out (000) | \`$url\` |" >>"$STATUSLOG"
|
||||
else
|
||||
echo "| $channel | Unknown status ($status_code) | \`$url\` |" >>"$STATUSLOG"
|
||||
fi
|
||||
echo "FAIL" >>"$STATUSLOG"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
check_links() {
|
||||
echo "Checking links from: $main"
|
||||
channel_num=0
|
||||
name=""
|
||||
jobs_running=0
|
||||
|
||||
echo "| Channel | Error (Code) | Link |" >"$STATUSLOG"
|
||||
echo "| ------- | ------------ | ---- |" >>"$STATUSLOG"
|
||||
|
||||
while IFS= read -r line; do
|
||||
line=$(echo "$line" | tr -d '\r\n')
|
||||
|
||||
if [[ "$line" == \#EXTINF* ]]; then
|
||||
name=$(echo "$line" | sed -n 's/.*tvg-name="\([^"]*\)".*/\1/p')
|
||||
[[ -z "$name" ]] && name="Channel $channel_num"
|
||||
elif [[ "$line" =~ ^https?:// ]]; then
|
||||
while (($(jobs -r | wc -l) >= MAX_JOBS)); do sleep 0.2; done
|
||||
get_status "$line" "$name" &
|
||||
((channel_num++))
|
||||
fi
|
||||
done < <(curl -sL "$main")
|
||||
|
||||
wait
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
write_readme() {
|
||||
local passed redirected empty failed
|
||||
passed=$(grep -c '^PASS$' "$STATUSLOG")
|
||||
redirected=$(grep -c '^REDIRECT$' "$STATUSLOG")
|
||||
empty=$(grep -c '^EMPTY$' "$STATUSLOG")
|
||||
failed=$(grep -c '^FAIL$' "$STATUSLOG")
|
||||
|
||||
{
|
||||
echo "## Log @ $(date '+%Y-%m-%d %H:%M:%S UTC')"
|
||||
echo
|
||||
echo "### ✅ Working Streams: $passed<br>🔁 Redirected Links: $redirected<br>➖ Empty Streams: $empty<br>❌ Dead Streams: $failed"
|
||||
echo
|
||||
|
||||
if [ $failed -gt 0 ] || [ $empty -gt 0 ] || [ $redirected -gt 0 ]; then
|
||||
head -n 1 "$STATUSLOG"
|
||||
grep -v -e '^PASS$' -e '^FAIL$' -e '^EMPTY$' -e '^REDIRECT$' -e '^---' "$STATUSLOG" |
|
||||
grep -v '^| Channel' | sort -u
|
||||
fi
|
||||
|
||||
echo "---"
|
||||
echo "#### M3U8 URL"
|
||||
printf "\`\`\`\nhttps://raw.githubusercontent.com/doms9/iptv/refs/heads/default/M3U8/TV.m3u8\n\`\`\`\n"
|
||||
echo "#### EPG URL"
|
||||
printf "\`\`\`\nhttps://raw.githubusercontent.com/doms9/iptv/refs/heads/default/EPG/TV.xml\n\`\`\`\n"
|
||||
echo "---"
|
||||
echo "#### Legal Disclaimer"
|
||||
echo "This repository lists publicly accessible IPTV streams as found on the internet at the time of checking."
|
||||
echo "No video or audio content is hosted in this repository. These links may point to copyrighted material owned by third parties;"
|
||||
echo "they are provided **solely for educational and research purposes.**"
|
||||
echo "The author does not endorse, promote, or encourage illegal streaming or copyright infringement."
|
||||
echo "End users are solely responsible for ensuring they comply with all applicable laws in their jurisdiction before using any link in this repository."
|
||||
echo "If you are a rights holder and wish for a link to be removed, please open an issue."
|
||||
|
||||
} >"$README"
|
||||
}
|
||||
|
||||
check_links
|
||||
write_readme
|
||||
rm "$STATUSLOG"
|
||||
10
pyproject.toml
Normal file
10
pyproject.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[project]
|
||||
name = "iptv"
|
||||
version = "0.0.2"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"beautifulsoup4>=4.13.4",
|
||||
"httpx>=0.28.1",
|
||||
"lxml>=6.0.0",
|
||||
"pytz>=2025.2",
|
||||
]
|
||||
24
readme.md
Normal file
24
readme.md
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
## Log @ 2025-08-17 08:33:49 UTC
|
||||
|
||||
### ✅ Working Streams: 65<br>🔁 Redirected Links: 0<br>➖ Empty Streams: 0<br>❌ Dead Streams: 1
|
||||
|
||||
| Channel | Error (Code) | Link |
|
||||
| ------- | ------------ | ---- |
|
||||
| CW | HTTP Error (401) | `http://user.scalecdn.co:8080/live/26725074/92867131/93093.m3u8` |
|
||||
---
|
||||
#### M3U8 URL
|
||||
```
|
||||
https://raw.githubusercontent.com/doms9/iptv/refs/heads/default/M3U8/TV.m3u8
|
||||
```
|
||||
#### EPG URL
|
||||
```
|
||||
https://raw.githubusercontent.com/doms9/iptv/refs/heads/default/EPG/TV.xml
|
||||
```
|
||||
---
|
||||
#### Legal Disclaimer
|
||||
This repository lists publicly accessible IPTV streams as found on the internet at the time of checking.
|
||||
No video or audio content is hosted in this repository. These links may point to copyrighted material owned by third parties;
|
||||
they are provided **solely for educational and research purposes.**
|
||||
The author does not endorse, promote, or encourage illegal streaming or copyright infringement.
|
||||
End users are solely responsible for ensuring they comply with all applicable laws in their jurisdiction before using any link in this repository.
|
||||
If you are a rights holder and wish for a link to be removed, please open an issue.
|
||||
163
uv.lock
generated
Normal file
163
uv.lock
generated
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
version = 1
|
||||
revision = 2
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
name = "anyio"
|
||||
version = "4.10.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "idna" },
|
||||
{ name = "sniffio" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/b4/636b3b65173d3ce9a38ef5f0522789614e590dab6a8d505340a4efe4c567/anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6", size = 213252, upload-time = "2025-08-04T08:54:26.451Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6f/12/e5e0282d673bb9746bacfb6e2dba8719989d3660cdb2ea79aee9a9651afb/anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1", size = 107213, upload-time = "2025-08-04T08:54:24.882Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "beautifulsoup4"
|
||||
version = "4.13.4"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "soupsieve" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d8/e4/0c4c39e18fd76d6a628d4dd8da40543d136ce2d1752bd6eeeab0791f4d6b/beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195", size = 621067, upload-time = "2025-04-15T17:05:13.836Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/50/cd/30110dc0ffcf3b131156077b90e9f60ed75711223f306da4db08eff8403b/beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", size = 187285, upload-time = "2025-04-15T17:05:12.221Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2025.8.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "h11"
|
||||
version = "0.16.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "1.0.9"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "h11" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.28.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "anyio" },
|
||||
{ name = "certifi" },
|
||||
{ name = "httpcore" },
|
||||
{ name = "idna" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.10"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iptv"
|
||||
version = "0.0.2"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "beautifulsoup4" },
|
||||
{ name = "httpx" },
|
||||
{ name = "lxml" },
|
||||
{ name = "pytz" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "beautifulsoup4", specifier = ">=4.13.4" },
|
||||
{ name = "httpx", specifier = ">=0.28.1" },
|
||||
{ name = "lxml", specifier = ">=6.0.0" },
|
||||
{ name = "pytz", specifier = ">=2025.2" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "6.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c5/ed/60eb6fa2923602fba988d9ca7c5cdbd7cf25faa795162ed538b527a35411/lxml-6.0.0.tar.gz", hash = "sha256:032e65120339d44cdc3efc326c9f660f5f7205f3a535c1fdbf898b29ea01fb72", size = 4096938, upload-time = "2025-06-26T16:28:19.373Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/79/21/6e7c060822a3c954ff085e5e1b94b4a25757c06529eac91e550f3f5cd8b8/lxml-6.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6da7cd4f405fd7db56e51e96bff0865b9853ae70df0e6720624049da76bde2da", size = 8414372, upload-time = "2025-06-26T16:26:39.079Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a4/f6/051b1607a459db670fc3a244fa4f06f101a8adf86cda263d1a56b3a4f9d5/lxml-6.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b34339898bb556a2351a1830f88f751679f343eabf9cf05841c95b165152c9e7", size = 4593940, upload-time = "2025-06-26T16:26:41.891Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8e/74/dd595d92a40bda3c687d70d4487b2c7eff93fd63b568acd64fedd2ba00fe/lxml-6.0.0-cp313-cp313-manylinux2010_i686.manylinux2014_i686.manylinux_2_12_i686.manylinux_2_17_i686.whl", hash = "sha256:51a5e4c61a4541bd1cd3ba74766d0c9b6c12d6a1a4964ef60026832aac8e79b3", size = 5214329, upload-time = "2025-06-26T16:26:44.669Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/46/3572761efc1bd45fcafb44a63b3b0feeb5b3f0066886821e94b0254f9253/lxml-6.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d18a25b19ca7307045581b18b3ec9ead2b1db5ccd8719c291f0cd0a5cec6cb81", size = 4947559, upload-time = "2025-06-28T18:47:31.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/94/8a/5e40de920e67c4f2eef9151097deb9b52d86c95762d8ee238134aff2125d/lxml-6.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d4f0c66df4386b75d2ab1e20a489f30dc7fd9a06a896d64980541506086be1f1", size = 5102143, upload-time = "2025-06-28T18:47:33.612Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/4b/20555bdd75d57945bdabfbc45fdb1a36a1a0ff9eae4653e951b2b79c9209/lxml-6.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f4b481b6cc3a897adb4279216695150bbe7a44c03daba3c894f49d2037e0a24", size = 5021931, upload-time = "2025-06-26T16:26:47.503Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/6e/cf03b412f3763d4ca23b25e70c96a74cfece64cec3addf1c4ec639586b13/lxml-6.0.0-cp313-cp313-manylinux_2_27_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8a78d6c9168f5bcb20971bf3329c2b83078611fbe1f807baadc64afc70523b3a", size = 5645469, upload-time = "2025-07-03T19:19:13.32Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/dd/39c8507c16db6031f8c1ddf70ed95dbb0a6d466a40002a3522c128aba472/lxml-6.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae06fbab4f1bb7db4f7c8ca9897dc8db4447d1a2b9bee78474ad403437bcc29", size = 5247467, upload-time = "2025-06-26T16:26:49.998Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4d/56/732d49def0631ad633844cfb2664563c830173a98d5efd9b172e89a4800d/lxml-6.0.0-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:1fa377b827ca2023244a06554c6e7dc6828a10aaf74ca41965c5d8a4925aebb4", size = 4720601, upload-time = "2025-06-26T16:26:52.564Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8f/7f/6b956fab95fa73462bca25d1ea7fc8274ddf68fb8e60b78d56c03b65278e/lxml-6.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1676b56d48048a62ef77a250428d1f31f610763636e0784ba67a9740823988ca", size = 5060227, upload-time = "2025-06-26T16:26:55.054Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/06/e851ac2924447e8b15a294855caf3d543424364a143c001014d22c8ca94c/lxml-6.0.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:0e32698462aacc5c1cf6bdfebc9c781821b7e74c79f13e5ffc8bfe27c42b1abf", size = 4790637, upload-time = "2025-06-26T16:26:57.384Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/d4/fd216f3cd6625022c25b336c7570d11f4a43adbaf0a56106d3d496f727a7/lxml-6.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4d6036c3a296707357efb375cfc24bb64cd955b9ec731abf11ebb1e40063949f", size = 5662049, upload-time = "2025-07-03T19:19:16.409Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/52/03/0e764ce00b95e008d76b99d432f1807f3574fb2945b496a17807a1645dbd/lxml-6.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7488a43033c958637b1a08cddc9188eb06d3ad36582cebc7d4815980b47e27ef", size = 5272430, upload-time = "2025-06-26T16:27:00.031Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5f/01/d48cc141bc47bc1644d20fe97bbd5e8afb30415ec94f146f2f76d0d9d098/lxml-6.0.0-cp313-cp313-win32.whl", hash = "sha256:5fcd7d3b1d8ecb91445bd71b9c88bdbeae528fefee4f379895becfc72298d181", size = 3612896, upload-time = "2025-06-26T16:27:04.251Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f4/87/6456b9541d186ee7d4cb53bf1b9a0d7f3b1068532676940fdd594ac90865/lxml-6.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:2f34687222b78fff795feeb799a7d44eca2477c3d9d3a46ce17d51a4f383e32e", size = 4013132, upload-time = "2025-06-26T16:27:06.415Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/42/85b3aa8f06ca0d24962f8100f001828e1f1f1a38c954c16e71154ed7d53a/lxml-6.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:21db1ec5525780fd07251636eb5f7acb84003e9382c72c18c542a87c416ade03", size = 3672642, upload-time = "2025-06-26T16:27:09.888Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2025.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sniffio"
|
||||
version = "1.3.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372, upload-time = "2024-02-25T23:20:04.057Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235, upload-time = "2024-02-25T23:20:01.196Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.7"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/3f/f4/4a80cd6ef364b2e8b65b15816a843c0980f7a5a2b4dc701fc574952aa19f/soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a", size = 103418, upload-time = "2025-04-20T18:50:08.518Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/9c/0e6afc12c269578be5c0c1c9f4b49a8d32770a080260c333ac04cc1c832d/soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", size = 36677, upload-time = "2025-04-20T18:50:07.196Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.14.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/98/5a/da40306b885cc8c09109dc2e1abd358d5684b1425678151cdaed4731c822/typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36", size = 107673, upload-time = "2025-07-04T13:28:34.16Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/00/d631e67a838026495268c2f6884f3711a15a9a2a96cd244fdaea53b823fb/typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76", size = 43906, upload-time = "2025-07-04T13:28:32.743Z" },
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue