Browse Source

add zaptv epg guide data

main
Brett Langdon 2 years ago
parent
commit
ad7ac3341e
No known key found for this signature in database GPG Key ID: 9BAD4322A65AD78B
4 changed files with 163 additions and 18 deletions
  1. +1
    -0
      src/dlhdhr/config.py
  2. +32
    -16
      src/dlhdhr/dlhd/channels.py
  3. +3
    -2
      src/dlhdhr/epg/__init__.py
  4. +127
    -0
      src/dlhdhr/epg/zaptv.py

+ 1
- 0
src/dlhdhr/config.py View File

@ -21,3 +21,4 @@ COUNTRY_EXCLUDE: set[str] | None = _set_or_none("DLHDHR_COUNTRY_EXCLUDE")
COUNTRY_ALLOW: set[str] | None = _set_or_none("DLHDHR_COUNTRY_ALLOW") COUNTRY_ALLOW: set[str] | None = _set_or_none("DLHDHR_COUNTRY_ALLOW")
ZAP2IT_REFRESH_DELAY: int = int(os.getenv("DLHDHR_ZAP2IT_REFRESH_DELAY", "3600")) ZAP2IT_REFRESH_DELAY: int = int(os.getenv("DLHDHR_ZAP2IT_REFRESH_DELAY", "3600"))
ZAPTV_REFRESH_DELAY: int = int(os.getenv("DLHDHR_ZAPTV_REFRESH_DELAY", "3600"))

+ 32
- 16
src/dlhdhr/dlhd/channels.py View File

@ -39,10 +39,18 @@ _CHANNELS = [
), ),
DLHDChannel(number="36", name="Sky Sports Arena UK", country_code="uk", xmltv_id="SkySportsArena.uk", call_sign=""), DLHDChannel(number="36", name="Sky Sports Arena UK", country_code="uk", xmltv_id="SkySportsArena.uk", call_sign=""),
DLHDChannel( DLHDChannel(
number="37", name="Sky Sports Action UK", country_code="uk", xmltv_id="SkySportsAction.uk", call_sign=""
number="37",
name="Sky Sports Action UK",
country_code="uk",
xmltv_id="SkySportsAction.uk",
call_sign="sky-action",
), ),
DLHDChannel( DLHDChannel(
number="38", name="Sky Sports Main Event", country_code="uk", xmltv_id="SkySportsMainEvent.uk", call_sign=""
number="38",
name="Sky Sports Main Event",
country_code="uk",
xmltv_id="SkySportsMainEvent.uk",
call_sign="sky-sports-main-event",
), ),
DLHDChannel(number="39", name="Fox Sports 1 USA", country_code="us", xmltv_id="FoxSports1.us", call_sign=""), DLHDChannel(number="39", name="Fox Sports 1 USA", country_code="us", xmltv_id="FoxSports1.us", call_sign=""),
DLHDChannel(number="40", name="Tennis Channel", country_code="us", xmltv_id="TennisChannel.us", call_sign="TENNIS"), DLHDChannel(number="40", name="Tennis Channel", country_code="us", xmltv_id="TennisChannel.us", call_sign="TENNIS"),
@ -67,7 +75,9 @@ _CHANNELS = [
), ),
DLHDChannel(number="57", name="EuroSport 1 Poland", country_code="pl", xmltv_id="", call_sign=""), DLHDChannel(number="57", name="EuroSport 1 Poland", country_code="pl", xmltv_id="", call_sign=""),
DLHDChannel(number="58", name="EuroSport 2 Poland", country_code="pl", xmltv_id="Eurosport2.pl", call_sign=""), DLHDChannel(number="58", name="EuroSport 2 Poland", country_code="pl", xmltv_id="Eurosport2.pl", call_sign=""),
DLHDChannel(number="60", name="Sky Sports F1 UK", country_code="uk", xmltv_id="SkySportsF1.uk", call_sign=""),
DLHDChannel(
number="60", name="Sky Sports F1 UK", country_code="uk", xmltv_id="SkySportsF1.uk", call_sign="sky-sports-f1"
),
DLHDChannel(number="61", name="beIN Sports MENA English 1", country_code="", xmltv_id="", call_sign=""), DLHDChannel(number="61", name="beIN Sports MENA English 1", country_code="", xmltv_id="", call_sign=""),
DLHDChannel(number="62", name="beIN SPORTS 1 Turkey", country_code="tr", xmltv_id="beINSports1.tr", call_sign=""), DLHDChannel(number="62", name="beIN SPORTS 1 Turkey", country_code="tr", xmltv_id="beINSports1.tr", call_sign=""),
DLHDChannel(number="63", name="beIN SPORTS 2 Turkey", country_code="tr", xmltv_id="beINSports2.tr", call_sign=""), DLHDChannel(number="63", name="beIN SPORTS 2 Turkey", country_code="tr", xmltv_id="beINSports2.tr", call_sign=""),
@ -77,7 +87,13 @@ _CHANNELS = [
), ),
DLHDChannel(number="66", name="TUDN USA", country_code="us", xmltv_id="TUDN.us", call_sign="TUDN"), DLHDChannel(number="66", name="TUDN USA", country_code="us", xmltv_id="TUDN.us", call_sign="TUDN"),
DLHDChannel(number="67", name="beIN SPORTS 4 Turkey", country_code="tr", xmltv_id="beINSports4.tr", call_sign=""), DLHDChannel(number="67", name="beIN SPORTS 4 Turkey", country_code="tr", xmltv_id="beINSports4.tr", call_sign=""),
DLHDChannel(number="70", name="Sky Sports Golf UK", country_code="uk", xmltv_id="SkySportsGolf.uk", call_sign=""),
DLHDChannel(
number="70",
name="Sky Sports Golf UK",
country_code="uk",
xmltv_id="SkySportsGolf.uk",
call_sign="sky-sports-golf",
),
DLHDChannel( DLHDChannel(
number="71", name="Eleven Sports 1 Poland", country_code="pl", xmltv_id="ElevenSport1.pl", call_sign="" number="71", name="Eleven Sports 1 Poland", country_code="pl", xmltv_id="ElevenSport1.pl", call_sign=""
), ),
@ -151,7 +167,7 @@ _CHANNELS = [
name="Sky sports Premier League", name="Sky sports Premier League",
country_code="uk", country_code="uk",
xmltv_id="SkySportsPremiereLeague.uk", xmltv_id="SkySportsPremiereLeague.uk",
call_sign="",
call_sign="sky-sports-premier-league",
), ),
DLHDChannel(number="131", name="Telemundo", country_code="us", xmltv_id="WKAQ.us", call_sign="WNJU"), DLHDChannel(number="131", name="Telemundo", country_code="us", xmltv_id="WKAQ.us", call_sign="WNJU"),
DLHDChannel(number="132", name="Univision", country_code="ca", xmltv_id="UnivisionCanada.ca", call_sign=""), DLHDChannel(number="132", name="Univision", country_code="ca", xmltv_id="UnivisionCanada.ca", call_sign=""),
@ -276,16 +292,16 @@ _CHANNELS = [
DLHDChannel(number="345", name="CNN USA", country_code="us", xmltv_id="CNN.us", call_sign="CNN"), DLHDChannel(number="345", name="CNN USA", country_code="us", xmltv_id="CNN.us", call_sign="CNN"),
DLHDChannel(number="346", name="Willow Cricket", country_code="", xmltv_id="WillowCricket.us", call_sign=""), DLHDChannel(number="346", name="Willow Cricket", country_code="", xmltv_id="WillowCricket.us", call_sign=""),
DLHDChannel(number="347", name="Fox News", country_code="us", xmltv_id="FoxNews.us", call_sign=""), DLHDChannel(number="347", name="Fox News", country_code="us", xmltv_id="FoxNews.us", call_sign=""),
DLHDChannel(number="348", name="Dave", country_code="uk", xmltv_id="Dave.uk", call_sign=""),
DLHDChannel(number="349", name="BBC News Channel HD", country_code="uk", xmltv_id="", call_sign=""),
DLHDChannel(number="350", name="ITV 1 UK", country_code="uk", xmltv_id="ITV1.uk", call_sign=""),
DLHDChannel(number="351", name="ITV 2 UK", country_code="uk", xmltv_id="ITV2.uk", call_sign=""),
DLHDChannel(number="352", name="ITV 3 UK", country_code="uk", xmltv_id="ITV3.uk", call_sign=""),
DLHDChannel(number="353", name="ITV 4 UK", country_code="uk", xmltv_id="ITV4.uk", call_sign=""),
DLHDChannel(number="354", name="Channel 4 UK", country_code="uk", xmltv_id="Channel4.uk", call_sign=""),
DLHDChannel(number="355", name="Channel 5 UK", country_code="uk", xmltv_id="Channel5.uk", call_sign=""),
DLHDChannel(number="356", name="BBC One UK", country_code="uk", xmltv_id="BBC1.uk", call_sign=""),
DLHDChannel(number="357", name="BBC Two UK", country_code="uk", xmltv_id="BBC2.uk", call_sign=""),
DLHDChannel(number="348", name="Dave", country_code="uk", xmltv_id="Dave.uk", call_sign="dave"),
DLHDChannel(number="349", name="BBC News Channel HD", country_code="uk", xmltv_id="", call_sign="bbc-news-channel"),
DLHDChannel(number="350", name="ITV 1 UK", country_code="uk", xmltv_id="ITV1.uk", call_sign="itv1"),
DLHDChannel(number="351", name="ITV 2 UK", country_code="uk", xmltv_id="ITV2.uk", call_sign="itv2"),
DLHDChannel(number="352", name="ITV 3 UK", country_code="uk", xmltv_id="ITV3.uk", call_sign="itv3"),
DLHDChannel(number="353", name="ITV 4 UK", country_code="uk", xmltv_id="ITV4.uk", call_sign="itv4"),
DLHDChannel(number="354", name="Channel 4 UK", country_code="uk", xmltv_id="Channel4.uk", call_sign="channel-4"),
DLHDChannel(number="355", name="Channel 5 UK", country_code="uk", xmltv_id="Channel5.uk", call_sign="channel-5"),
DLHDChannel(number="356", name="BBC One UK", country_code="uk", xmltv_id="BBC1.uk", call_sign="bbc-one"),
DLHDChannel(number="357", name="BBC Two UK", country_code="uk", xmltv_id="BBC2.uk", call_sign="bbc-two"),
DLHDChannel(number="358", name="BBC Three UK", country_code="uk", xmltv_id="BBC3.uk", call_sign=""), DLHDChannel(number="358", name="BBC Three UK", country_code="uk", xmltv_id="BBC3.uk", call_sign=""),
DLHDChannel(number="359", name="BBC Four UK", country_code="uk", xmltv_id="BBC4.uk", call_sign=""), DLHDChannel(number="359", name="BBC Four UK", country_code="uk", xmltv_id="BBC4.uk", call_sign=""),
DLHDChannel(number="360", name="5 USA", country_code="us", xmltv_id="", call_sign=""), DLHDChannel(number="360", name="5 USA", country_code="us", xmltv_id="", call_sign=""),
@ -791,7 +807,7 @@ _CHANNELS = [
), ),
DLHDChannel(number="682", name="Sky Showcase UK", country_code="uk", xmltv_id="SkyShowcase.uk", call_sign=""), DLHDChannel(number="682", name="Sky Showcase UK", country_code="uk", xmltv_id="SkyShowcase.uk", call_sign=""),
DLHDChannel(number="683", name="Sky Arts UK", country_code="uk", xmltv_id="SkyArts.uk", call_sign=""), DLHDChannel(number="683", name="Sky Arts UK", country_code="uk", xmltv_id="SkyArts.uk", call_sign=""),
DLHDChannel(number="684", name="Sky Comedy UK", country_code="uk", xmltv_id="SkyComedy.uk", call_sign=""),
DLHDChannel(number="684", name="Sky Comedy UK", country_code="uk", xmltv_id="SkyComedy.uk", call_sign="sky-comedy"),
DLHDChannel(number="685", name="Showtime SHOxBET USA", country_code="us", xmltv_id="ShowtimeXBet.us", call_sign=""), DLHDChannel(number="685", name="Showtime SHOxBET USA", country_code="us", xmltv_id="ShowtimeXBet.us", call_sign=""),
DLHDChannel(number="686", name="Sky History", country_code="gb", xmltv_id="HistoryChannel.uk", call_sign=""), DLHDChannel(number="686", name="Sky History", country_code="gb", xmltv_id="HistoryChannel.uk", call_sign=""),
DLHDChannel(number="687", name="Gold UK", country_code="gb", xmltv_id="StarGold.uk", call_sign=""), DLHDChannel(number="687", name="Gold UK", country_code="gb", xmltv_id="StarGold.uk", call_sign=""),


+ 3
- 2
src/dlhdhr/epg/__init__.py View File

@ -6,18 +6,19 @@ from xml.etree.ElementTree import Element, tostring
from dlhdhr.dlhd import DLHDChannel from dlhdhr.dlhd import DLHDChannel
from dlhdhr.epg.zap2it import Zap2it from dlhdhr.epg.zap2it import Zap2it
from dlhdhr.epg.program import Program from dlhdhr.epg.program import Program
from dlhdhr.epg.zaptv import ZapTV
@dataclass() @dataclass()
class EPG: class EPG:
zap2it: Zap2it = field(default_factory=Zap2it) zap2it: Zap2it = field(default_factory=Zap2it)
zaptv: ZapTV = field(default_factory=ZapTV)
async def get_channel_programs(self, channel: DLHDChannel) -> list[Program]: async def get_channel_programs(self, channel: DLHDChannel) -> list[Program]:
if channel.country_code == "us": if channel.country_code == "us":
return await self.zap2it.get_channel_programs(channel) return await self.zap2it.get_channel_programs(channel)
elif channel.country_code == "uk": elif channel.country_code == "uk":
# TODO: TV24? TV Guide?
return []
return await self.zaptv.get_channel_programs(channel)
return [] return []


+ 127
- 0
src/dlhdhr/epg/zaptv.py View File

@ -0,0 +1,127 @@
import datetime
from dataclasses import dataclass, field
import time
import httpx
from dlhdhr import config
from dlhdhr.dlhd.channels import DLHDChannel
from dlhdhr.epg.program import Program
from dlhdhr.epg.program import Rating
@dataclass()
class ZapTV:
_BASE_URL = "https://www.zaptv.co.uk/api/"
_listings: dict[str, Program] = field(default_factory=dict)
_last_fetch: float = 0
def _get_client(self) -> httpx.AsyncClient:
return httpx.AsyncClient(
base_url=self._BASE_URL,
timeout=2.0,
verify=True,
max_redirects=1,
headers={
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:120.0) Gecko/20100101 Firefox/120.0",
"Referer": "https://www.zaptv.co.uk/",
"Accept": "application/json",
},
)
def _cleanup_listings(self) -> None:
now = datetime.datetime.now(datetime.UTC)
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]
if updated_programs:
updated[call_sign] = updated_programs
self._listings = updated
async def _fetch_listings(self) -> dict[str, list[Program]]:
listings: dict[str, list[Program]] = {}
now = datetime.datetime.now(datetime.UTC)
async with self._get_client() as client:
channels = set()
events = {}
# TODO: Can we fetch tomorrows data as well?
res = await client.get(f"/schedules/today")
res.raise_for_status()
data = res.json()
for d in data:
channel = d["channel"]
code = channel["code"]
channels.add(code)
if code not in events:
events[code] = {}
for broadcast in d["broadcasts"]:
events[code][broadcast["uid"]] = broadcast
for code in channels:
programs = []
for evt_data in events[code].values():
end_time = datetime.datetime.fromisoformat(evt_data["endsAt"])
if end_time < now:
continue
ep_data = evt_data["metadata"].get("episode") or {}
season = ep_data.get("season") or None
if season is not None:
season = str(season)
episode = ep_data.get("number") or None
if episode is not None:
episode = str(episode)
release_year = evt_data["metadata"].get("year")
if release_year is not None:
release_year = str(release_year)
programs.append(
Program(
start_time=datetime.datetime.fromisoformat(evt_data["startsAt"]),
end_time=end_time,
title=evt_data["title"],
description="",
season=season,
episode=episode,
tags=[],
release_year=release_year,
thumbnail=evt_data["image"] or None,
rating=None,
)
)
listings[code] = sorted(programs, key=lambda p: p.start_time, reverse=True)
return listings
async def _refresh_listings(self) -> dict[str, list[Program]]:
self._cleanup_listings()
now = time.time()
if self._listings and now - self._last_fetch > config.ZAPTV_REFRESH_DELAY:
return self._listings
programs = await self._fetch_listings()
for code, programs in programs.items():
if code in self._listings:
self._listings[code].extend(programs)
else:
self._listings[code] = programs
return self._listings
async def get_channel_programs(self, channel: DLHDChannel) -> list[Program]:
if not channel.call_sign:
return []
await self._refresh_listings()
if channel.call_sign not in self._listings:
return []
return self._listings[channel.call_sign]

Loading…
Cancel
Save