mirror of
https://github.com/doms9/iptv.git
synced 2026-04-21 19:46:59 +02:00
Compare commits
37 commits
8df77c1f13
...
17c574615d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17c574615d | ||
|
|
6116ed0f04 | ||
|
|
0dc119558d | ||
|
|
47ac7989de | ||
|
|
d9b784bf22 | ||
|
|
a211e316da | ||
|
|
8b08ab5a5e | ||
|
|
670134ba65 | ||
|
|
c5af8e7b39 | ||
|
|
3d893c1c0a | ||
|
|
00000d9604 | ||
|
|
00000d9ab1 | ||
|
|
b896a22a29 | ||
|
|
a481b75f71 | ||
|
|
b0fd09ff50 | ||
|
|
2d1c3afc35 | ||
|
|
8d38c43997 | ||
|
|
5d8611ce56 | ||
|
|
ee7dafc20a | ||
|
|
e0ad692ae1 | ||
|
|
983266181e | ||
|
|
85d1b9c6b7 | ||
|
|
9bad373127 | ||
|
|
91039fa206 | ||
|
|
5c462dc9ac | ||
|
|
2dff4cc5a5 | ||
|
|
59bd648dab | ||
|
|
5d7deb4d19 | ||
|
|
6e1099f059 | ||
|
|
952076d914 | ||
|
|
c0b45e4643 | ||
|
|
c6f2240099 | ||
|
|
c0f8ae9aca | ||
|
|
872acdf18c | ||
|
|
672dc56a6c | ||
|
|
c7985450b2 | ||
|
|
b1278d35b8 |
11 changed files with 101441 additions and 103662 deletions
2302
M3U8/TV.m3u8
2302
M3U8/TV.m3u8
File diff suppressed because it is too large
Load diff
200406
M3U8/TV.xml
200406
M3U8/TV.xml
File diff suppressed because one or more lines are too long
|
|
@ -4,7 +4,7 @@
|
||||||
http://41.205.93.154/AandE/index.m3u8
|
http://41.205.93.154/AandE/index.m3u8
|
||||||
|
|
||||||
#EXTINF:-1 tvg-chno="2" tvg-id="ABC.National.Feed.us2" 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
|
#EXTINF:-1 tvg-chno="2" tvg-id="ABC.National.Feed.us2" 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://stream.cammonitorplus.net/1790/index.m3u8?token=MnE3ZWg1YkgxdFdWZlo2c2hLMkltWnJhcFo1OHhxcXVyb2pKazZXaWxZRERxNEduaVp1UnBxU2VlWmF0ZnRlRGxaMm1zNStDbnJOOXFZMlhtcStybmc9PQ==
|
http://stream.cammonitorplus.net/1762/index.m3u8?token=MnE3ZWg1YkgxdFdWZlo2c2hLMkltWnJhcFo1OHhxcXVyb2pKazZXaWxZRERxNEduaVp1UnBxU2VlWmF0ZnRlRGxaMm1zNStDbnJOOXFZMlhtcStybmc9PQ==
|
||||||
|
|
||||||
#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
|
#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://23.239.31.26:8989/accnetwork/index.m3u8
|
http://23.239.31.26:8989/accnetwork/index.m3u8
|
||||||
|
|
|
||||||
2300
M3U8/events.m3u8
2300
M3U8/events.m3u8
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,9 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import re
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
import feedparser
|
import feedparser
|
||||||
from playwright.async_api import Browser, Page
|
from playwright.async_api import Browser, Page, TimeoutError
|
||||||
|
|
||||||
from .utils import Cache, Time, get_logger, leagues, network
|
from .utils import Cache, Time, get_logger, leagues, network
|
||||||
|
|
||||||
|
|
@ -24,15 +25,30 @@ VALID_SPORTS = [
|
||||||
"Basketball",
|
"Basketball",
|
||||||
"Football",
|
"Football",
|
||||||
"Ice Hockey",
|
"Ice Hockey",
|
||||||
|
"Wrestling",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def fix_url(s: str) -> str | None:
|
||||||
|
pattern = re.compile(r"eventinfo\/(\d*)", re.I)
|
||||||
|
|
||||||
|
if not (match := pattern.search(s)):
|
||||||
|
return
|
||||||
|
|
||||||
|
elif not (event_id := match[1]).isalnum():
|
||||||
|
return
|
||||||
|
|
||||||
|
return f"https://cdn.livetv872.me/cache/links/en.{event_id}.html"
|
||||||
|
|
||||||
|
|
||||||
async def process_event(
|
async def process_event(
|
||||||
url: str,
|
url: str,
|
||||||
url_num: int,
|
url_num: int,
|
||||||
page: Page,
|
page: Page,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
|
|
||||||
|
event_id_pattern = re.compile(r"&c=(\d*)", re.I)
|
||||||
|
|
||||||
captured: list[str] = []
|
captured: list[str] = []
|
||||||
|
|
||||||
got_one = asyncio.Event()
|
got_one = asyncio.Event()
|
||||||
|
|
@ -46,40 +62,33 @@ async def process_event(
|
||||||
page.on("request", handler)
|
page.on("request", handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await page.goto(
|
resp = await page.goto(
|
||||||
url,
|
url,
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=10_000,
|
timeout=10_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
await page.wait_for_timeout(1_500)
|
if resp.status != 200:
|
||||||
|
log.warning(f"URL {url_num}) Status Code: {resp.status}")
|
||||||
|
return
|
||||||
|
|
||||||
buttons = await page.query_selector_all(".lnktbj a[href*='webplayer']")
|
try:
|
||||||
|
event_a = page.locator('a[title*="Aliez"]').first
|
||||||
|
|
||||||
labels = await page.eval_on_selector_all(
|
href = await event_a.get_attribute("href", timeout=1_250)
|
||||||
".lnktyt span",
|
except TimeoutError:
|
||||||
"elements => elements.map(el => el.textContent.trim().toLowerCase())",
|
|
||||||
)
|
|
||||||
|
|
||||||
for btn, label in zip(buttons, labels):
|
|
||||||
if label in ["web", "youtube"]:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if not (href := await btn.get_attribute("href")):
|
|
||||||
continue
|
|
||||||
|
|
||||||
break
|
|
||||||
|
|
||||||
else:
|
|
||||||
log.warning(f"URL {url_num}) No valid sources found.")
|
log.warning(f"URL {url_num}) No valid sources found.")
|
||||||
return
|
return
|
||||||
|
|
||||||
href = href if href.startswith("http") else f"https:{href}"
|
if (match := event_id_pattern.search(href)) and (
|
||||||
|
event_id := match[1]
|
||||||
href.replace("livetv.sx", "livetv873.me")
|
).isalnum():
|
||||||
|
event_url = f"https://emb.apl392.me/player/live.php?id={event_id}"
|
||||||
|
else:
|
||||||
|
event_url = href if href.startswith("http") else f"https:{href}"
|
||||||
|
|
||||||
await page.goto(
|
await page.goto(
|
||||||
href,
|
event_url,
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=5_000,
|
timeout=5_000,
|
||||||
)
|
)
|
||||||
|
|
@ -130,7 +139,7 @@ async def refresh_xml_cache(now_ts: float) -> dict[str, dict[str, str | float]]:
|
||||||
if not (date := entry.get("published")):
|
if not (date := entry.get("published")):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not (link := entry.get("link")):
|
if (not (link := entry.get("link"))) or (not (fixed_link := fix_url(link))):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not (title := entry.get("title")):
|
if not (title := entry.get("title")):
|
||||||
|
|
@ -151,7 +160,7 @@ async def refresh_xml_cache(now_ts: float) -> dict[str, dict[str, str | float]]:
|
||||||
"sport": sport,
|
"sport": sport,
|
||||||
"league": league,
|
"league": league,
|
||||||
"event": title,
|
"event": title,
|
||||||
"link": link.replace("livetv.sx", "livetv873.me"),
|
"link": fixed_link,
|
||||||
"event_ts": event_dt.timestamp(),
|
"event_ts": event_dt.timestamp(),
|
||||||
"timestamp": now_ts,
|
"timestamp": now_ts,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,17 @@ BASE_URL = "https://pixelsport.tv"
|
||||||
|
|
||||||
async def get_api_data(page: Page) -> dict[str, list[dict, str, str]]:
|
async def get_api_data(page: Page) -> dict[str, list[dict, str, str]]:
|
||||||
try:
|
try:
|
||||||
await page.goto(
|
resp = await page.goto(
|
||||||
url := urljoin(BASE_URL, "backend/livetv/events"),
|
url := urljoin(BASE_URL, "backend/livetv/events"),
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=6_000,
|
timeout=6_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if resp.status != 200:
|
||||||
|
log.warning(f"{url} Status Code: {resp.status}")
|
||||||
|
|
||||||
|
return {}
|
||||||
|
|
||||||
raw_json = await page.locator("pre").inner_text(timeout=5_000)
|
raw_json = await page.locator("pre").inner_text(timeout=5_000)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f'Failed to fetch "{url}": {e}')
|
log.error(f'Failed to fetch "{url}": {e}')
|
||||||
|
|
|
||||||
|
|
@ -93,12 +93,16 @@ async def process_event(
|
||||||
page.on("request", handler)
|
page.on("request", handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await page.goto(
|
resp = await page.goto(
|
||||||
url,
|
url,
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=6_000,
|
timeout=6_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if resp.status != 200:
|
||||||
|
log.warning(f"URL {url_num}) Status Code: {resp.status}")
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if btn := await page.wait_for_selector(
|
if btn := await page.wait_for_selector(
|
||||||
"button.streambutton:nth-of-type(1)",
|
"button.streambutton:nth-of-type(1)",
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ def get_logger(name: str | None = None) -> logging.Logger:
|
||||||
LOG_DIR / "fetch.log",
|
LOG_DIR / "fetch.log",
|
||||||
when="midnight",
|
when="midnight",
|
||||||
interval=1,
|
interval=1,
|
||||||
backupCount=3,
|
backupCount=1,
|
||||||
encoding="utf-8",
|
encoding="utf-8",
|
||||||
utc=False,
|
utc=False,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -250,12 +250,17 @@ class Network:
|
||||||
page.on("request", handler)
|
page.on("request", handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await page.goto(
|
resp = await page.goto(
|
||||||
url,
|
url,
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=6_000,
|
timeout=6_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if resp.status != 200:
|
||||||
|
log.warning(f"URL {url_num}) Status Code: {resp.status}")
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
wait_task = asyncio.create_task(got_one.wait())
|
wait_task = asyncio.create_task(got_one.wait())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,16 @@ async def process_event(
|
||||||
page.on("request", handler)
|
page.on("request", handler)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
await page.goto(
|
resp = await page.goto(
|
||||||
url,
|
url,
|
||||||
wait_until="domcontentloaded",
|
wait_until="domcontentloaded",
|
||||||
timeout=8_000,
|
timeout=8_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if resp.status != 200:
|
||||||
|
log.warning(f"URL {url_num}) Status Code: {resp.status}")
|
||||||
|
return
|
||||||
|
|
||||||
await page.wait_for_timeout(2_000)
|
await page.wait_for_timeout(2_000)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
## Base Log @ 2026-03-02 09:06 UTC
|
## Base Log @ 2026-03-03 09:07 UTC
|
||||||
|
|
||||||
### ✅ Working Streams: 158<br>❌ Dead Streams: 3
|
### ✅ Working Streams: 160<br>❌ Dead Streams: 1
|
||||||
|
|
||||||
| Channel | Error (Code) | Link |
|
| Channel | Error (Code) | Link |
|
||||||
| ------- | ------------ | ---- |
|
| ------- | ------------ | ---- |
|
||||||
| CMT | HTTP Error (404) | `http://23.237.104.106:8080/USA_CMT/index.m3u8` |
|
|
||||||
| Golf Channel | HTTP Error (000) | `http://hardcoremedia.xyz/live/rabdsbmz/3731346838/258721.ts` |
|
| Golf Channel | HTTP Error (000) | `http://hardcoremedia.xyz/live/rabdsbmz/3731346838/258721.ts` |
|
||||||
| NBC Sports California | HTTP Error (403) | `http://hardcoremedia.xyz/live/rabdsbmz/3731346838/136474.ts` |
|
|
||||||
---
|
---
|
||||||
#### Base Channels URL
|
#### Base Channels URL
|
||||||
```
|
```
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue