Compare commits

..

No commits in common. "eda2f9e73d6d3615849c2eb9a00a6612346481a2" and "7081c424f41664bceac311951e58655f6a3e2015" have entirely different histories.

7 changed files with 6006 additions and 6498 deletions

9059
EPG/TV.xml

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -12,7 +12,7 @@ from scrapers import (
shark,
sport9,
streambtw,
streamcenter,
streameast,
streamfree,
strmd,
tvpass,
@ -53,7 +53,7 @@ async def main() -> None:
asyncio.create_task(shark.scrape(network.client)),
asyncio.create_task(sport9.scrape(network.client)),
asyncio.create_task(streambtw.scrape(network.client)),
asyncio.create_task(streamcenter.scrape(network.client)),
#asyncio.create_task(streameast.scrape(network.client)),
asyncio.create_task(streamfree.scrape(network.client)),
asyncio.create_task(strmd.scrape(network.client)),
asyncio.create_task(tvpass.scrape(network.client)),
@ -71,7 +71,7 @@ async def main() -> None:
| shark.urls
| sport9.urls
| streambtw.urls
| streamcenter.urls
| streameast.urls
| strmd.urls
| streamfree.urls
| tvpass.urls

View file

@ -1,174 +0,0 @@
from functools import partial
import httpx
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]] = {}
CACHE_FILE = Cache("streamcenter.json", exp=10_800)
API_FILE = Cache("streamcenter-api.json", exp=28_800)
BASE_URL = "https://backendstreamcenter.youshop.pro:488/api/Parties"
TAG = "STRMCNTR"
categories = {
4: "Basketball",
9: "Football",
13: "Baseball",
14: "American Football",
15: "Motor Sport",
16: "Hockey",
17: "Fight MMA",
18: "Boxing",
19: "NCAA Sports",
20: "WWE",
21: "Tennis",
}
async def refresh_api_cache(
client: httpx.AsyncClient,
url: str,
now_ts: float,
) -> list[dict[str, str | int]]:
log.info("Refreshing API cache")
try:
r = await client.get(url, params={"pageNumber": 1, "pageSize": 500})
r.raise_for_status()
except Exception as e:
log.error(f'Failed to fetch "{url}": {e}')
return {}
data = r.json()
data[-1]["timestamp"] = now_ts
return data
async def get_events(
client: httpx.AsyncClient,
cached_keys: set[str],
) -> list[dict[str, str]]:
now = Time.clean(Time.now())
if not (api_data := API_FILE.load(per_entry=False, index=-1)):
api_data = await refresh_api_cache(
client,
BASE_URL,
now.timestamp(),
)
API_FILE.write(api_data)
events = []
start_dt = now.delta(minutes=-30)
end_dt = now.delta(minutes=30)
for stream_group in api_data:
category_id: int = stream_group.get("categoryId")
name: str = stream_group.get("gameName")
iframe: str = stream_group.get("videoUrl")
event_time: str = stream_group.get("beginPartie")
if not (name and category_id and iframe and event_time):
continue
event_dt = Time.from_str(event_time, timezone="UTC")
if not start_dt <= event_dt <= end_dt:
continue
if not (sport := categories.get(category_id)):
continue
key = f"[{sport}] {name} ({TAG})"
if cached_keys & {key}:
continue
events.append(
{
"sport": sport,
"event": name,
"link": iframe.split("<")[0],
"timestamp": event_dt.timestamp(),
}
)
return events
async def scrape(client: httpx.AsyncClient) -> 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(client, set(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)
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 = (
ev["sport"],
ev["event"],
ev["timestamp"],
)
key = f"[{sport}] {event} ({TAG})"
tvg_id, logo = leagues.get_tvg_info(sport, event)
entry = {
"url": url,
"logo": logo,
"base": "https://streamcenter.xyz",
"timestamp": ts,
"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

@ -1,17 +1,14 @@
## Base Log @ 2025-12-05 08:48 UTC
## Base Log @ 2025-12-05 03:38 UTC
### ✅ Working Streams: 139<br>❌ Dead Streams: 8
### ✅ Working Streams: 142<br>❌ Dead Streams: 5
| Channel | Error (Code) | Link |
| ------- | ------------ | ---- |
| Comedy Central | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/7466` |
| Disney XD | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/75621` |
| FDSN Southwest | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/21843` |
| Fox Sports 2 | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/1847` |
| Freeform TV | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/13370` |
| HBO Comedy | HTTP Error (404) | `http://fl1.moveonjoy.com/HBO_COMEDY/index.m3u8` |
| History Channel | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/15017` |
| SportsNet New York | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/20938` |
| Comet TV | HTTP Error (502) | `http://nocable.cc:8080/91161088/91161088/125831` |
| FDSN Florida | HTTP Error (403) | `http://nocable.cc:8080/91161088/91161088/46794` |
| HBO Family | HTTP Error (404) | `https://fl1.moveonjoy.com/HBO_FAMILY/index.m3u8` |
| Premier Sports 2 | HTTP Error (403) | `http://109.61.81.147:1935/cdn7/1275/mpegts?token=0abb07758b53c286d3b6b7943b7c5405` |
| SportsNet New York | HTTP Error (502) | `http://nocable.cc:8080/91161088/91161088/20938` |
---
#### Base Channels URL
```