5 Commits

6 changed files with 45 additions and 19 deletions
Split View
  1. +18
    -5
      src/dlhdhr/dlhd/__init__.py
  2. +1
    -1
      src/dlhdhr/dlhd/channels.py
  3. +0
    -1
      src/dlhdhr/epg/__init__.py
  4. +8
    -4
      src/dlhdhr/epg/program.py
  5. +6
    -3
      src/dlhdhr/epg/zap2it.py
  6. +12
    -5
      src/dlhdhr/epg/zaptv.py

+ 18
- 5
src/dlhdhr/dlhd/__init__.py View File

@ -20,11 +20,13 @@ class DLHDClient:
_channels: dict[str, DLHDChannel]
_channels_last_fetch: float = 0
_base_urls: dict[DLHDChannel, (float, str)]
_referers: dict[DLHDChannel, str]
_cookies: dict[str, str]
def __init__(self):
self._channels = {}
self._base_urls = {}
self._referers = {}
self._cookies = {}
async def _log_request(self, request):
@ -40,7 +42,7 @@ class DLHDClient:
def _get_client(self, referer: str = ""):
headers = {
"User-Agent": "",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:122.0) Gecko/20100101 Firefox/122.0",
"Referer": referer,
}
return httpx.AsyncClient(
@ -62,11 +64,22 @@ class DLHDClient:
return channel
return None
async def get_channel_referer(self, channel: DLHDChannel) -> str:
if channel not in self._referers:
base_url = f"https://weblivehdplay.ru/premiumtv/daddyhd.php?id={channel.number}"
referer = f"https://dlhd.sx/stream/stream-{channel.number}.php"
async with self._get_client(referer=referer) as client:
res = await client.get(base_url, follow_redirects=True)
res.raise_for_status()
self._referers[channel] = str(res.request.url)
return self._referers[channel]
async def get_channel_playlist(self, channel: DLHDChannel) -> m3u8.M3U8:
base_url = f"https://weblivehdplay.ru/premiumtv/daddyhd.php?id={channel.number}"
referer = base_url
referer = f"https://dlhd.sx/stream/stream-{channel.number}.php"
async with self._get_client(referer=referer) as client:
res = await client.get(referer, follow_redirects=True)
res = await client.get(base_url, follow_redirects=True)
res.raise_for_status()
referer = str(res.request.url)
@ -126,7 +139,7 @@ class DLHDClient:
return mono_playlist
async def get_channel_key(self, channel: DLHDChannel, proxy_url: str) -> bytes:
referer = f"https://weblivehdplay.ru/premiumtv/daddyhd.php?id={channel.number}"
referer = await self.get_channel_referer(channel)
async with self._get_client(referer=referer) as client:
res = await client.get(proxy_url)
res.raise_for_status()
@ -147,7 +160,7 @@ class DLHDClient:
return base_url
async def stream_segment(self, channel: DLHDChannel, segment_path: str):
referer = "https://claplivehdplay.ru/"
referer = await self.get_channel_referer(channel)
base_url = await self.get_channel_base_url(channel)
segment_url = urllib.parse.urljoin(base_url, segment_path)


+ 1
- 1
src/dlhdhr/dlhd/channels.py View File

@ -23,7 +23,7 @@ class DLHDChannel:
return f"/channel/{self.number}"
def to_xmltv(self) -> Element:
node = Element("channel", attrib={"id": self.xmltv_id})
node = Element("channel", attrib={"id": str(self.number)})
SubElement(node, "display-name", attrib={"lang": "en"}).text = self.name
SubElement(node, "lcn").text = self.number
return node


+ 0
- 1
src/dlhdhr/epg/__init__.py View File

@ -30,7 +30,6 @@ class EPG:
for channel in channels:
tv.append(channel.to_xmltv())
for channel in channels:
programs = await self.get_channel_programs(channel)
# Note: The order of the elements in the <programme /> matters


+ 8
- 4
src/dlhdhr/epg/program.py View File

@ -18,6 +18,7 @@ class Program:
title: str
description: str
tags: list[str]
subtitle: str | None
thumbnail: str | None
season: int | None
episode: int | None
@ -25,15 +26,14 @@ class Program:
release_year: str | None
def to_xmltv(self, channel: DLHDChannel) -> Element | None:
if not channel.xmltv_id:
return None
start_time = self.start_time.strftime("%Y%m%d%H%M%S %z")
end_time = self.start_time.strftime("%Y%m%d%H%M%S %z")
programme = Element("programme", attrib={"start": start_time, "stop": end_time, "channel": channel.xmltv_id})
programme = Element("programme", attrib={"start": start_time, "stop": end_time, "channel": str(channel.number)})
if self.title:
SubElement(programme, "title", attrib={"lang": "en"}).text = self.title
if self.subtitle:
SubElement(programme, "sub-title", attrib={"lang": "en"}).text = self.subtitle
if self.description:
SubElement(programme, "desc", attrib={"lang": "en"}).text = self.description
@ -50,6 +50,10 @@ class Program:
season_id = self.season or ""
episode_id = self.episode or ""
SubElement(programme, "episode-num", attrib={"system": "xmltv_ns"}).text = f"{season_id}.{episode_id}."
if self.season and self.episode:
SubElement(
programme, "episode-num", attrib={"system": "onscreen"}
).text = f"S{self.season} E{self.episode}"
if self.rating:
rating = SubElement(programme, "rating", attrib={"system": self.rating.system})


+ 6
- 3
src/dlhdhr/epg/zap2it.py View File

@ -31,10 +31,11 @@ class Zap2it:
def _cleanup_listings(self) -> None:
now = datetime.datetime.now(datetime.UTC)
cutoff = now - datetime.timedelta(hours=3)
updated: dict[str, list[Program]] = {}
for call_sign, programs in self._listings.items():
updated_programs = [p for p in programs if p.end_time > now]
updated_programs = [p for p in programs if p.end_time > cutoff]
if updated_programs:
updated[call_sign] = updated_programs
self._listings = updated
@ -58,6 +59,7 @@ class Zap2it:
listings: dict[str, list[Program]] = {}
now = datetime.datetime.now(datetime.UTC)
cutoff = now - datetime.timedelta(hours=3)
async with self._get_client() as client:
channels = set()
events = {}
@ -84,7 +86,7 @@ class Zap2it:
programs = []
for evt_data in events[call_sign].values():
end_time = datetime.datetime.fromisoformat(evt_data["endTime"])
if end_time < now:
if end_time < cutoff:
continue
rating = None
@ -96,6 +98,7 @@ class Zap2it:
start_time=datetime.datetime.fromisoformat(evt_data["startTime"]),
end_time=end_time,
title=evt_data["program"]["title"],
subtitle=evt_data["program"].get("episodeTitle") or None,
description=evt_data["program"]["shortDesc"],
season=evt_data["program"]["season"],
episode=evt_data["program"]["episode"],
@ -106,7 +109,7 @@ class Zap2it:
)
)
listings[call_sign] = sorted(programs, key=lambda p: p.start_time, reverse=True)
listings[call_sign] = sorted(programs, key=lambda p: p.start_time)
return listings


+ 12
- 5
src/dlhdhr/epg/zaptv.py View File

@ -31,10 +31,11 @@ class ZapTV:
def _cleanup_listings(self) -> None:
now = datetime.datetime.now(datetime.UTC)
cutoff = now - datetime.timedelta(hours=3)
updated: dict[str, list[Program]] = {}
for call_sign, programs in self._listings.items():
updated_programs = [p for p in programs if p.end_time > now]
updated_programs = [p for p in programs if p.end_time > cutoff]
if updated_programs:
updated[call_sign] = updated_programs
self._listings = updated
@ -42,6 +43,7 @@ class ZapTV:
async def _fetch_listings(self) -> dict[str, list[Program]]:
listings: dict[str, list[Program]] = {}
now = datetime.datetime.now(datetime.UTC)
cutoff = now - datetime.timedelta(hours=3)
async with self._get_client() as client:
channels = set()
events = {}
@ -66,17 +68,21 @@ class ZapTV:
programs = []
for evt_data in events[code].values():
end_time = datetime.datetime.fromisoformat(evt_data["endsAt"])
if end_time < now:
if end_time < cutoff:
continue
ep_data = evt_data["metadata"].get("episode") or {}
season = ep_data.get("season") or None
season: str | None = ep_data.get("season") or None
if season is not None:
season = str(season)
episode = ep_data.get("number") or None
episode: str | None = ep_data.get("number") or None
if episode is not None:
episode = str(episode)
episode_title: str | None = ep_data.get("title") or None
if episode_title is not None:
episode_title = str(episode_title)
release_year = evt_data["metadata"].get("year")
if release_year is not None:
release_year = str(release_year)
@ -87,6 +93,7 @@ class ZapTV:
end_time=end_time,
title=evt_data["title"],
description="",
subtitle=episode_title,
season=season,
episode=episode,
tags=[],
@ -96,7 +103,7 @@ class ZapTV:
)
)
listings[code] = sorted(programs, key=lambda p: p.start_time, reverse=True)
listings[code] = sorted(programs, key=lambda p: p.start_time)
return listings


Loading…
Cancel
Save