Compare commits

..

No commits in common. "41bf21c3628d716e941c7cfdc1df512846beb8b2" and "b9b5681a28dce278062fb308eb098bd13d1db494" have entirely different histories.

8 changed files with 86602 additions and 88495 deletions

167880
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

@ -64,7 +64,7 @@ async def main() -> None:
asyncio.create_task(roxie.scrape()), asyncio.create_task(roxie.scrape()),
asyncio.create_task(shark.scrape()), asyncio.create_task(shark.scrape()),
asyncio.create_task(sport9.scrape()), asyncio.create_task(sport9.scrape()),
# asyncio.create_task(streambtw.scrape()), asyncio.create_task(streambtw.scrape()),
asyncio.create_task(streamcenter.scrape()), asyncio.create_task(streamcenter.scrape()),
asyncio.create_task(streamfree.scrape()), asyncio.create_task(streamfree.scrape()),
asyncio.create_task(streamhub.scrape()), asyncio.create_task(streamhub.scrape()),

View file

@ -18,7 +18,7 @@ API_FILE = Cache(f"{TAG.lower()}-api.json", exp=28_800)
MIRRORS = [ MIRRORS = [
"https://streami.su", "https://streami.su",
# "https://streamed.st", "https://streamed.st",
"https://streamed.pk", "https://streamed.pk",
] ]

View file

@ -1,6 +1,6 @@
import re import re
from functools import partial from functools import partial
from urllib.parse import urljoin, urlparse from urllib.parse import urljoin
from selectolax.parser import HTMLParser from selectolax.parser import HTMLParser
@ -26,9 +26,7 @@ MIRRORS = [
] ]
def fix_txt(s: str) -> str: def fix_league(s: str) -> str:
s = " ".join(s.split())
return s.upper() if s.islower() else s return s.upper() if s.islower() else s
@ -36,9 +34,9 @@ async def process_event(href: str, url_num: int) -> tuple[str | None, str | None
valid_m3u8 = re.compile(r'var\s+(\w+)\s*=\s*"([^"]*)"', re.IGNORECASE) valid_m3u8 = re.compile(r'var\s+(\w+)\s*=\s*"([^"]*)"', re.IGNORECASE)
for x, mirror in enumerate(MIRRORS, start=1): for x, mirror in enumerate(MIRRORS, start=1):
base: str = mirror["base"] base = mirror["base"]
hex_decode: bool = mirror["hex_decode"] hex_decode = mirror["hex_decode"]
url = urljoin(base, href) url = urljoin(base, href)
@ -63,10 +61,11 @@ async def process_event(href: str, url_num: int) -> tuple[str | None, str | None
log.warning(f"M{x} | URL {url_num}) No Clappr source found.") log.warning(f"M{x} | URL {url_num}) No Clappr source found.")
continue continue
raw: str = match[2] raw = match[2]
try: try:
m3u8_url = bytes.fromhex(raw).decode("utf-8") if hex_decode else raw m3u8_url = bytes.fromhex(raw).decode("utf-8") if hex_decode else raw
except Exception as e: except Exception as e:
log.warning(f"M{x} | URL {url_num}) Decoding failed: {e}") log.warning(f"M{x} | URL {url_num}) Decoding failed: {e}")
continue continue
@ -76,7 +75,10 @@ async def process_event(href: str, url_num: int) -> tuple[str | None, str | None
return m3u8_url, iframe_src return m3u8_url, iframe_src
log.warning(f"M{x} | URL {url_num}) No M3U8 found") else:
log.warning(f"M{x} | URL {url_num}) No M3U8 found")
return None, None
return None, None return None, None
@ -91,42 +93,41 @@ async def get_events(url: str, cached_keys: list[str]) -> list[dict[str, str]]:
sport = "Live Event" sport = "Live Event"
for node in soup.css("a"): for box in soup.css(".div-main-box"):
if not node.attributes.get("class"): for node in box.iter():
continue if not (node_class := node.attributes.get("class")):
continue
if (parent := node.parent) and "my-1" in parent.attributes.get("class", ""): if "my-1" in node_class:
if span := node.css_first("span"): if span := node.css_first("span"):
sport = span.text(strip=True) sport = span.text(strip=True)
sport = fix_txt(sport) if node.tag == "a" and "nav-link2" in node_class:
if not (time_node := node.css_first(".col-3")):
continue
if not (teams := [t.text(strip=True) for t in node.css(".col-7 .col-12")]): if time_node.text(strip=True) != "MatchStarted":
continue continue
if not (href := node.attributes.get("href")): if not (href := node.attributes.get("href")) or href.startswith("http"):
continue continue
href = urlparse(href).path if href.startswith("http") else href sport = fix_league(sport)
if not (time_node := node.css_first(".col-3 span")): teams = [t.text(strip=True) for t in node.css(".col-7 .col-12")]
continue
if time_node.text(strip=True) != "MatchStarted": event_name = " vs ".join(teams)
continue
event_name = fix_txt(" vs ".join(teams)) if f"[{sport}] {event_name} ({TAG})" in cached_keys:
continue
if f"[{sport}] {event_name} ({TAG})" in cached_keys: events.append(
continue {
"sport": sport,
events.append( "event": event_name,
{ "href": href,
"sport": sport, }
"event": event_name, )
"href": href,
}
)
return events return events

View file

@ -216,7 +216,6 @@
"CHAMPIONSHIP": { "CHAMPIONSHIP": {
"logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/24.png", "logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/24.png",
"names": [ "names": [
"ENGLAND CHAMPIONSHIP",
"ENGLISH CHAMPIONSHIP", "ENGLISH CHAMPIONSHIP",
"ENGLISH FOOTBALL LEAGUE CHAMPIONSHIP", "ENGLISH FOOTBALL LEAGUE CHAMPIONSHIP",
"ENGLISH LEAGUE CHAMPIONSHIP", "ENGLISH LEAGUE CHAMPIONSHIP",
@ -325,7 +324,6 @@
"logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/25.png", "logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/25.png",
"names": [ "names": [
"ENGLISH FOOTBALL LEAGUE ONE", "ENGLISH FOOTBALL LEAGUE ONE",
"ENGLISH LEAGUE ONE",
"LEAGUE ONE", "LEAGUE ONE",
"SKY BET LEAGUE ONE" "SKY BET LEAGUE ONE"
] ]
@ -336,7 +334,6 @@
"logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/26.png", "logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/26.png",
"names": [ "names": [
"ENGLISH FOOTBALL LEAGUE TWO", "ENGLISH FOOTBALL LEAGUE TWO",
"ENGLISH LEAGUE TWO",
"LEAGUE TWO", "LEAGUE TWO",
"SKY BET LEAGUE TWO" "SKY BET LEAGUE TWO"
] ]
@ -683,7 +680,7 @@
{ {
"UEFA CHAMPIONS LEAGUE": { "UEFA CHAMPIONS LEAGUE": {
"logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/2.png", "logo": "https://a.espncdn.com/combiner/i?img=/i/leaguelogos/soccer/500/2.png",
"names": ["CHAMPIONS LEAGUE", "EUROPE UEFA CHAMPIONS LEAGUE", "UCL"] "names": ["CHAMPIONS LEAGUE", "UCL"]
} }
}, },
{ {

View file

@ -1,13 +1,10 @@
## Base Log @ 2026-01-20 22:40 UTC ## Base Log @ 2026-01-19 20:43 UTC
### ✅ Working Streams: 141<br>❌ Dead Streams: 4 ### ✅ Working Streams: 144<br>❌ Dead Streams: 1
| Channel | Error (Code) | Link | | Channel | Error (Code) | Link |
| ------- | ------------ | ---- | | ------- | ------------ | ---- |
| ESPN | HTTP Error (404) | `http://41.205.93.154/ESPN/index.m3u8` | | Premier Sports 2 | Unknown status (302) | `http://hardcoremedia.xyz:80/NW3Vk7xXwW/8375773282/117038` |
| FDSN Florida | HTTP Error (403) | `http://mytvstream.net:8080/live/A1Jay5/362586/46794.m3u8` |
| NBC Sports Bay Area | Unknown status (302) | `http://hardcoremedia.xyz:80/NW3Vk7xXwW/8375773282/257216` |
| Premier Sports 2 | HTTP Error (502) | `http://hardcoremedia.xyz:80/NW3Vk7xXwW/8375773282/117038` |
--- ---
#### Base Channels URL #### Base Channels URL
``` ```