First Commit
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
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
|
||||
Reference in New Issue
Block a user