2025-01-20 12:04:20 +09:00

115 lines
4.0 KiB
Python

import logging
from datetime import date, datetime, timedelta
from typing import List
from epg2xml.providers import EPGProgram, EPGProvider
log = logging.getLogger(__name__.rsplit(".", maxsplit=1)[-1].upper())
class SPOTV(EPGProvider):
"""EPGProvider for SPOTV
데이터: jsonapi
요청수: #days
특이사항:
- 5일치만 제공
"""
referer = "https://www.spotvnow.co.kr/channel"
title_regex = r"\s?(?:\[(.*?)\])?\s?(.*?)\s?(?:[\(<](.*)[\)>])?\s?(?:-(\d+))?\s?(?:<?([\d,]+)회>?)?\s?$"
def get_svc_channels(self) -> List[dict]:
url = "https://www.spotvnow.co.kr/api/v3/channel"
return [
{
"Name": ch["name"],
"ServiceId": ch["id"],
"Icon_url": ch["logo"],
}
for ch in self.request(url)
]
def __dt(self, dt: str) -> datetime:
if not dt:
return None
if dt.endswith("24:00"):
return datetime.strptime(dt.replace("24:00", "00:00"), "%Y-%m-%d %H:%M") + timedelta(days=1)
return datetime.strptime(dt, "%Y-%m-%d %H:%M")
def get_programs(self) -> None:
max_ndays = 5
if int(self.cfg["FETCH_LIMIT"]) > max_ndays:
log.warning(
"""
***********************************************************************
%s는 당일포함 %d일치만 EPG를 제공하고 있습니다.
***********************************************************************
""",
self.provider_name,
max_ndays,
)
data = []
for nd in range(min(int(self.cfg["FETCH_LIMIT"]), max_ndays)):
day = date.today() + timedelta(days=nd)
url = "https://www.spotvnow.co.kr/api/v3/program/" + day.strftime("%Y-%m-%d")
try:
data.extend(self.request(url))
except Exception:
log.exception("데이터 가져오는 중 에러:")
continue
# 날짜의 경계에서 발생할 수 있는 중복 제거
_data = []
for _d in data:
_d.pop("date", None)
if _d not in _data:
_data.append(_d)
for idx, _ch in enumerate(self.req_channels):
log.info("%03d/%03d %s", idx + 1, len(self.req_channels), _ch)
try:
_epgs = self.__epgs_of_channel(_ch.id, _data, _ch.svcid)
except AssertionError as e:
log.warning("%s: %s", e, _ch)
except Exception:
log.exception("프로그램 파싱 중 예외: %s", _ch)
else:
_ch.programs.extend(_epgs)
def __epgs_of_channel(self, channelid: str, data: dict, svcid: str) -> List[EPGProgram]:
programs = [x for x in data if x["channelId"] == svcid]
assert programs, "EPG 정보가 없거나 없는 채널입니다"
_epgs = []
for p in programs:
_epg = EPGProgram(channelid)
_epg.title = p["title"]
_epg.stime = self.__dt(p["startTime"])
# 끝나는 시간이 없으면 해당일 자정으로 강제
_epg.etime = self.__dt(p["endTime"]) or (_epg.stime.replace(hour=0, minute=0) + timedelta(days=1))
if _epg.stime == _epg.etime:
continue
if m := self.title_regex.match(_epg.title):
_epg.title = m.group(2)
subs = []
if prefix := m.group(1):
subs.append(prefix)
if sub := m.group(3):
subs += [sub.replace(")(", ", ").replace(") (", ", ")]
title_sub = ", ".join(subs)
if num := m.group(4):
title_sub += f"-{num}"
if title_sub:
_epg.title_sub = title_sub
_epg.ep_num = m.group(5)
if p["type"] == 300:
# 100: live, 200: 본방송
_epg.rebroadcast = True
_epgs.append(_epg)
return _epgs