mirror of
https://github.com/fHDHR/fHDHR_NextPVR.git
synced 2025-12-06 08:46:58 -05:00
EPG Enhancements
This commit is contained in:
parent
55ca03b389
commit
7f6d80fd3e
@ -63,9 +63,12 @@ class tvtvEPG():
|
|||||||
"name": chan_item["channel"]["name"],
|
"name": chan_item["channel"]["name"],
|
||||||
"number": channel_number,
|
"number": channel_number,
|
||||||
"id": str(chan_item["channel"]["stationID"]),
|
"id": str(chan_item["channel"]["stationID"]),
|
||||||
"thumbnail": "https://cdn.tvpassport.com/image/station/100x100/%s" % chan_item["channel"]["logoFilename"],
|
"thumbnail": None,
|
||||||
"listing": [],
|
"listing": [],
|
||||||
}
|
}
|
||||||
|
if chan_item["channel"]["logoFilename"]:
|
||||||
|
programguide[channel_number]["thumbnail"] = "https://cdn.tvpassport.com/image/station/100x100/%s" % chan_item["channel"]["logoFilename"]
|
||||||
|
|
||||||
for listing in chan_item["listings"]:
|
for listing in chan_item["listings"]:
|
||||||
|
|
||||||
timestamp = self.tvtv_timestamps(listing["listDateTime"], listing["duration"])
|
timestamp = self.tvtv_timestamps(listing["listDateTime"], listing["duration"])
|
||||||
@ -74,7 +77,7 @@ class tvtvEPG():
|
|||||||
"time_start": timestamp['time_start'],
|
"time_start": timestamp['time_start'],
|
||||||
"time_end": timestamp['time_end'],
|
"time_end": timestamp['time_end'],
|
||||||
"duration_minutes": listing["duration"],
|
"duration_minutes": listing["duration"],
|
||||||
"thumbnail": "https://cdn.tvpassport.com/image/show/480x720/%s" % listing["artwork"]["poster"],
|
"thumbnail": None,
|
||||||
"title": listing["showName"],
|
"title": listing["showName"],
|
||||||
"sub-title": listing["episodeTitle"],
|
"sub-title": listing["episodeTitle"],
|
||||||
"description": listing["description"],
|
"description": listing["description"],
|
||||||
@ -88,19 +91,19 @@ class tvtvEPG():
|
|||||||
"id": listing["listingID"],
|
"id": listing["listingID"],
|
||||||
}
|
}
|
||||||
|
|
||||||
if not any(d['id'] == clean_prog_dict['id'] for d in programguide[channel_number]["listing"]):
|
if listing["artwork"]["poster"]:
|
||||||
|
listing["artwork"]["poster"] = "https://cdn.tvpassport.com/image/show/480x720/%s" % listing["artwork"]["poster"]
|
||||||
|
|
||||||
|
if not any((d['time_start'] == clean_prog_dict['time_start'] and d['id'] == clean_prog_dict['id']) for d in programguide[channel_number]["listing"]):
|
||||||
programguide[channel_number]["listing"].append(clean_prog_dict)
|
programguide[channel_number]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
return programguide
|
return programguide
|
||||||
|
|
||||||
def tvtv_timestamps(self, starttime, duration):
|
def tvtv_timestamps(self, starttime, duration):
|
||||||
start_time = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M:%S')
|
start_time = datetime.datetime.strptime(starttime, '%Y-%m-%d %H:%M:%S').timestamp()
|
||||||
end_time = start_time + datetime.timedelta(minutes=duration)
|
|
||||||
start_time = start_time.strftime('%Y%m%d%H%M%S +0000')
|
|
||||||
end_time = end_time.strftime('%Y%m%d%H%M%S +0000')
|
|
||||||
timestamp = {
|
timestamp = {
|
||||||
"time_start": start_time,
|
"time_start": start_time,
|
||||||
"time_end": end_time
|
"time_end": start_time + (duration * 60)
|
||||||
}
|
}
|
||||||
return timestamp
|
return timestamp
|
||||||
|
|
||||||
@ -110,11 +113,11 @@ class tvtvEPG():
|
|||||||
stoptime = str(datesdict["stop"]) + "T00%3A00%3A00.000Z"
|
stoptime = str(datesdict["stop"]) + "T00%3A00%3A00.000Z"
|
||||||
url = "https://www.tvtv.us/tvm/t/tv/v4/lineups/%s/listings/grid?start=%s&end=%s" % (self.lineup_id, starttime, stoptime)
|
url = "https://www.tvtv.us/tvm/t/tv/v4/lineups/%s/listings/grid?start=%s&end=%s" % (self.lineup_id, starttime, stoptime)
|
||||||
self.get_cached_item(str(datesdict["start"]), url)
|
self.get_cached_item(str(datesdict["start"]), url)
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "tvtv") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "tvtv") or []
|
||||||
return [self.fhdhr.db.get_cacheitem_value(x, "offline_cache", "tvtv") for x in cache_list]
|
return [self.fhdhr.db.get_cacheitem_value(x, "epg_cache", "tvtv") for x in cache_list]
|
||||||
|
|
||||||
def get_cached_item(self, cache_key, url):
|
def get_cached_item(self, cache_key, url):
|
||||||
cacheitem = self.fhdhr.db.get_cacheitem_value(cache_key, "offline_cache", "tvtv")
|
cacheitem = self.fhdhr.db.get_cacheitem_value(cache_key, "epg_cache", "tvtv")
|
||||||
if cacheitem:
|
if cacheitem:
|
||||||
self.fhdhr.logger.info('FROM CACHE: ' + str(cache_key))
|
self.fhdhr.logger.info('FROM CACHE: ' + str(cache_key))
|
||||||
return cacheitem
|
return cacheitem
|
||||||
@ -127,26 +130,26 @@ class tvtvEPG():
|
|||||||
return
|
return
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
|
|
||||||
self.fhdhr.db.set_cacheitem_value(cache_key, "offline_cache", result, "tvtv")
|
self.fhdhr.db.set_cacheitem_value(cache_key, "epg_cache", result, "tvtv")
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "tvtv") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "tvtv") or []
|
||||||
cache_list.append(cache_key)
|
cache_list.append(cache_key)
|
||||||
self.fhdhr.db.set_cacheitem_value("cache_list", "offline_cache", cache_list, "tvtv")
|
self.fhdhr.db.set_cacheitem_value("cache_list", "epg_cache", cache_list, "tvtv")
|
||||||
|
|
||||||
def remove_stale_cache(self, todaydate):
|
def remove_stale_cache(self, todaydate):
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "tvtv") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "tvtv") or []
|
||||||
cache_to_kill = []
|
cache_to_kill = []
|
||||||
for cacheitem in cache_list:
|
for cacheitem in cache_list:
|
||||||
cachedate = datetime.datetime.strptime(str(cacheitem), "%Y-%m-%d")
|
cachedate = datetime.datetime.strptime(str(cacheitem), "%Y-%m-%d")
|
||||||
todaysdate = datetime.datetime.strptime(str(todaydate), "%Y-%m-%d")
|
todaysdate = datetime.datetime.strptime(str(todaydate), "%Y-%m-%d")
|
||||||
if cachedate < todaysdate:
|
if cachedate < todaysdate:
|
||||||
cache_to_kill.append(cacheitem)
|
cache_to_kill.append(cacheitem)
|
||||||
self.fhdhr.db.delete_cacheitem_value(cacheitem, "offline_cache", "tvtv")
|
self.fhdhr.db.delete_cacheitem_value(cacheitem, "epg_cache", "tvtv")
|
||||||
self.fhdhr.logger.info('Removing stale cache: ' + str(cacheitem))
|
self.fhdhr.logger.info('Removing stale cache: ' + str(cacheitem))
|
||||||
self.fhdhr.db.set_cacheitem_value("cache_list", "offline_cache", [x for x in cache_list if x not in cache_to_kill], "tvtv")
|
self.fhdhr.db.set_cacheitem_value("cache_list", "epg_cache", [x for x in cache_list if x not in cache_to_kill], "tvtv")
|
||||||
|
|
||||||
def clear_cache(self):
|
def clear_cache(self):
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "tvtv") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "tvtv") or []
|
||||||
for cacheitem in cache_list:
|
for cacheitem in cache_list:
|
||||||
self.fhdhr.db.delete_cacheitem_value(cacheitem, "offline_cache", "tvtv")
|
self.fhdhr.db.delete_cacheitem_value(cacheitem, "epg_cache", "tvtv")
|
||||||
self.fhdhr.logger.info('Removing cache: ' + str(cacheitem))
|
self.fhdhr.logger.info('Removing cache: ' + str(cacheitem))
|
||||||
self.fhdhr.db.delete_cacheitem_value("cache_list", "offline_cache", "tvtv")
|
self.fhdhr.db.delete_cacheitem_value("cache_list", "epg_cache", "tvtv")
|
||||||
|
|||||||
@ -63,9 +63,11 @@ class zap2itEPG():
|
|||||||
eventdict = xmldictmaker(event, ["startTime", "endTime", "duration", "rating", "flag"], list_items=["filter", "flag"])
|
eventdict = xmldictmaker(event, ["startTime", "endTime", "duration", "rating", "flag"], list_items=["filter", "flag"])
|
||||||
progdict = xmldictmaker(event['program'], ["title", "sub-title", "releaseYear", "episodeTitle", "shortDesc", "season", "episode", "id"])
|
progdict = xmldictmaker(event['program'], ["title", "sub-title", "releaseYear", "episodeTitle", "shortDesc", "season", "episode", "id"])
|
||||||
|
|
||||||
|
timestamp = self.zap2it_timestamps(eventdict['startTime'], eventdict['endTime'])
|
||||||
|
|
||||||
clean_prog_dict = {
|
clean_prog_dict = {
|
||||||
"time_start": self.xmltimestamp_zap(eventdict['startTime']),
|
"time_start": timestamp['time_start'],
|
||||||
"time_end": self.xmltimestamp_zap(eventdict['endTime']),
|
"time_end": timestamp['time_end'],
|
||||||
"duration_minutes": eventdict['duration'],
|
"duration_minutes": eventdict['duration'],
|
||||||
"thumbnail": str("https://zap2it.tmsimg.com/assets/" + str(eventdict['thumbnail']) + ".jpg"),
|
"thumbnail": str("https://zap2it.tmsimg.com/assets/" + str(eventdict['thumbnail']) + ".jpg"),
|
||||||
"title": progdict['title'] or "Unavailable",
|
"title": progdict['title'] or "Unavailable",
|
||||||
@ -78,7 +80,7 @@ class zap2itEPG():
|
|||||||
"seasonnumber": progdict['season'],
|
"seasonnumber": progdict['season'],
|
||||||
"episodenumber": progdict['episode'],
|
"episodenumber": progdict['episode'],
|
||||||
"isnew": False,
|
"isnew": False,
|
||||||
"id": str(progdict['id'] or self.xmltimestamp_zap(eventdict['startTime'])),
|
"id": str(progdict['id'] or "%s_%s" % (cdict["channelId"], timestamp['time_start'])),
|
||||||
}
|
}
|
||||||
|
|
||||||
for f in eventdict['filter']:
|
for f in eventdict['filter']:
|
||||||
@ -92,16 +94,16 @@ class zap2itEPG():
|
|||||||
if 'New' in eventdict['flag'] and 'live' not in eventdict['flag']:
|
if 'New' in eventdict['flag'] and 'live' not in eventdict['flag']:
|
||||||
clean_prog_dict["isnew"] = True
|
clean_prog_dict["isnew"] = True
|
||||||
|
|
||||||
if not any(d['id'] == clean_prog_dict['id'] for d in programguide[str(cdict["channelNo"])]["listing"]):
|
if not any((d['time_start'] == clean_prog_dict['time_start'] and d['id'] == clean_prog_dict['id']) for d in programguide[str(cdict["channelNo"])]["listing"]):
|
||||||
programguide[str(cdict["channelNo"])]["listing"].append(clean_prog_dict)
|
programguide[str(cdict["channelNo"])]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
return programguide
|
return programguide
|
||||||
|
|
||||||
def xmltimestamp_zap(self, inputtime):
|
def zap2it_timestamps(self, starttime, endtime):
|
||||||
xmltime = inputtime.replace('Z', '+00:00')
|
timestamp = {}
|
||||||
xmltime = datetime.datetime.fromisoformat(xmltime)
|
for time_item, time_value in zip(["time_start", "time_end"], [starttime, endtime]):
|
||||||
xmltime = xmltime.strftime('%Y%m%d%H%M%S %z')
|
timestamp[time_item] = datetime.datetime.fromisoformat(time_value.replace('Z', '+00:00')).timestamp()
|
||||||
return xmltime
|
return timestamp
|
||||||
|
|
||||||
def get_cached(self, i_times):
|
def get_cached(self, i_times):
|
||||||
|
|
||||||
@ -129,11 +131,11 @@ class zap2itEPG():
|
|||||||
url = 'https://tvlistings.zap2it.com/api/grid?'
|
url = 'https://tvlistings.zap2it.com/api/grid?'
|
||||||
url += urllib.parse.urlencode(parameters)
|
url += urllib.parse.urlencode(parameters)
|
||||||
self.get_cached_item(str(i_time), url)
|
self.get_cached_item(str(i_time), url)
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "zap2it") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "zap2it") or []
|
||||||
return [self.fhdhr.db.get_cacheitem_value(x, "offline_cache", "zap2it") for x in cache_list]
|
return [self.fhdhr.db.get_cacheitem_value(x, "epg_cache", "zap2it") for x in cache_list]
|
||||||
|
|
||||||
def get_cached_item(self, cache_key, url):
|
def get_cached_item(self, cache_key, url):
|
||||||
cacheitem = self.fhdhr.db.get_cacheitem_value(cache_key, "offline_cache", "zap2it")
|
cacheitem = self.fhdhr.db.get_cacheitem_value(cache_key, "epg_cache", "zap2it")
|
||||||
if cacheitem:
|
if cacheitem:
|
||||||
self.fhdhr.logger.info('FROM CACHE: ' + str(cache_key))
|
self.fhdhr.logger.info('FROM CACHE: ' + str(cache_key))
|
||||||
return cacheitem
|
return cacheitem
|
||||||
@ -146,26 +148,26 @@ class zap2itEPG():
|
|||||||
return
|
return
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
|
|
||||||
self.fhdhr.db.set_cacheitem_value(cache_key, "offline_cache", result, "zap2it")
|
self.fhdhr.db.set_cacheitem_value(cache_key, "epg_cache", result, "zap2it")
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "zap2it") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "zap2it") or []
|
||||||
cache_list.append(cache_key)
|
cache_list.append(cache_key)
|
||||||
self.fhdhr.db.set_cacheitem_value("cache_list", "offline_cache", cache_list, "zap2it")
|
self.fhdhr.db.set_cacheitem_value("cache_list", "epg_cache", cache_list, "zap2it")
|
||||||
|
|
||||||
def remove_stale_cache(self, zap_time):
|
def remove_stale_cache(self, zap_time):
|
||||||
|
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "zap2it") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "zap2it") or []
|
||||||
cache_to_kill = []
|
cache_to_kill = []
|
||||||
for cacheitem in cache_list:
|
for cacheitem in cache_list:
|
||||||
cachedate = int(cacheitem)
|
cachedate = int(cacheitem)
|
||||||
if cachedate < zap_time:
|
if cachedate < zap_time:
|
||||||
cache_to_kill.append(cacheitem)
|
cache_to_kill.append(cacheitem)
|
||||||
self.fhdhr.db.delete_cacheitem_value(cacheitem, "offline_cache", "zap2it")
|
self.fhdhr.db.delete_cacheitem_value(cacheitem, "epg_cache", "zap2it")
|
||||||
self.fhdhr.logger.info('Removing stale cache: ' + str(cacheitem))
|
self.fhdhr.logger.info('Removing stale cache: ' + str(cacheitem))
|
||||||
self.fhdhr.db.set_cacheitem_value("cache_list", "offline_cache", [x for x in cache_list if x not in cache_to_kill], "zap2it")
|
self.fhdhr.db.set_cacheitem_value("cache_list", "epg_cache", [x for x in cache_list if x not in cache_to_kill], "zap2it")
|
||||||
|
|
||||||
def clear_cache(self):
|
def clear_cache(self):
|
||||||
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "offline_cache", "zap2it") or []
|
cache_list = self.fhdhr.db.get_cacheitem_value("cache_list", "epg_cache", "zap2it") or []
|
||||||
for cacheitem in cache_list:
|
for cacheitem in cache_list:
|
||||||
self.fhdhr.db.delete_cacheitem_value(cacheitem, "offline_cache", "zap2it")
|
self.fhdhr.db.delete_cacheitem_value(cacheitem, "epg_cache", "zap2it")
|
||||||
self.fhdhr.logger.info('Removing cache: ' + str(cacheitem))
|
self.fhdhr.logger.info('Removing cache: ' + str(cacheitem))
|
||||||
self.fhdhr.db.delete_cacheitem_value("cache_list", "offline_cache", "zap2it")
|
self.fhdhr.db.delete_cacheitem_value("cache_list", "epg_cache", "zap2it")
|
||||||
|
|||||||
@ -19,6 +19,21 @@
|
|||||||
"value": "None,blocks",
|
"value": "None,blocks",
|
||||||
"config_file": false,
|
"config_file": false,
|
||||||
"config_web": false
|
"config_web": false
|
||||||
|
},
|
||||||
|
"reverse_days": {
|
||||||
|
"value": -1,
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"forward_days": {
|
||||||
|
"value": 7,
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"block_size": {
|
||||||
|
"value": 1800,
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,14 @@ class Channel_IDs():
|
|||||||
if cnumber:
|
if cnumber:
|
||||||
return cnumber
|
return cnumber
|
||||||
|
|
||||||
used_numbers = [existing_channel["number"] for existing_channel in existing_channel_info]
|
used_numbers = []
|
||||||
|
for existing_channel in existing_channel_info:
|
||||||
|
if existing_channel["subnumber"]:
|
||||||
|
number = "%s.%s" % (existing_channel["number"], existing_channel["subnumber"])
|
||||||
|
else:
|
||||||
|
number = existing_channel["number"]
|
||||||
|
used_numbers.append(number)
|
||||||
|
|
||||||
for i in range(1000, 2000):
|
for i in range(1000, 2000):
|
||||||
if str(float(i)) not in used_numbers:
|
if str(float(i)) not in used_numbers:
|
||||||
break
|
break
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
from .blocks import blocksEPG
|
from .blocks import blocksEPG
|
||||||
|
|
||||||
@ -29,12 +28,8 @@ class EPG():
|
|||||||
|
|
||||||
self.def_method = self.fhdhr.config.dict["epg"]["def_method"]
|
self.def_method = self.fhdhr.config.dict["epg"]["def_method"]
|
||||||
self.sleeptime = {}
|
self.sleeptime = {}
|
||||||
for epg_method in self.epg_methods:
|
for epg_method in list(self.epg_handling.keys()):
|
||||||
if epg_method in list(self.fhdhr.config.dict.keys()):
|
self.sleeptime[epg_method] = self.fhdhr.config.dict["epg"]["update_frequency"]
|
||||||
if "update_frequency" in list(self.fhdhr.config.dict[epg_method].keys()):
|
|
||||||
self.sleeptime[epg_method] = self.fhdhr.config.dict[epg_method]["update_frequency"]
|
|
||||||
if epg_method not in list(self.sleeptime.keys()):
|
|
||||||
self.sleeptime[epg_method] = self.fhdhr.config.dict["epg"]["update_frequency"]
|
|
||||||
|
|
||||||
self.epg_update_url = "%s/api/epg?method=update" % (self.fhdhr.api.base)
|
self.epg_update_url = "%s/api/epg?method=update" % (self.fhdhr.api.base)
|
||||||
|
|
||||||
@ -60,38 +55,28 @@ class EPG():
|
|||||||
|
|
||||||
self.fhdhr.db.delete_fhdhr_value("epg_dict", method)
|
self.fhdhr.db.delete_fhdhr_value("epg_dict", method)
|
||||||
|
|
||||||
def whats_on_now(self, channel_number, method=None):
|
def whats_on_now(self, channel_number, method=None, chan_obj=None, chan_dict=None):
|
||||||
nowtime = datetime.datetime.utcnow()
|
nowtime = time.time()
|
||||||
epgdict = self.get_epg(method)
|
epgdict = self.get_epg(method)
|
||||||
try:
|
try:
|
||||||
listings = epgdict[channel_number]["listing"]
|
listings = epgdict[channel_number]["listing"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
listings = []
|
listings = []
|
||||||
for listing in listings:
|
for listing in listings:
|
||||||
start_time = datetime.datetime.strptime(listing["time_start"], '%Y%m%d%H%M%S +0000')
|
for time_item in ["time_start", "time_end"]:
|
||||||
end_time = datetime.datetime.strptime(listing["time_end"], '%Y%m%d%H%M%S +0000')
|
time_value = listing[time_item]
|
||||||
if start_time <= nowtime <= end_time:
|
if str(time_value).endswith("+00:00"):
|
||||||
|
listing[time_item] = datetime.datetime.strptime(time_value, '%Y%m%d%H%M%S +00:00').timestamp()
|
||||||
|
elif str(time_value).endswith("+0000"):
|
||||||
|
listing[time_item] = datetime.datetime.strptime(time_value, '%Y%m%d%H%M%S +0000').timestamp()
|
||||||
|
else:
|
||||||
|
listing[time_item] = int(time_value)
|
||||||
|
if int(listing["time_start"]) <= nowtime <= int(listing["time_end"]):
|
||||||
epgitem = epgdict[channel_number].copy()
|
epgitem = epgdict[channel_number].copy()
|
||||||
epgitem["listing"] = [listing]
|
epgitem["listing"] = [listing]
|
||||||
return epgitem
|
return epgitem
|
||||||
epgitem = epgdict[channel_number].copy()
|
epgitem = epgdict[channel_number].copy()
|
||||||
epgitem["listing"] = [{
|
epgitem["listing"] = [self.blocks.empty_listing(chan_obj=None, chan_dict=None)]
|
||||||
"time_start": None,
|
|
||||||
"time_end": None,
|
|
||||||
"duration_minutes": None,
|
|
||||||
"thumbnail": None,
|
|
||||||
"title": "Unavailable",
|
|
||||||
"sub-title": "Unavailable",
|
|
||||||
"description": "Unavailable",
|
|
||||||
"rating": "N/A",
|
|
||||||
"episodetitle": None,
|
|
||||||
"releaseyear": None,
|
|
||||||
"genres": [],
|
|
||||||
"seasonnumber": None,
|
|
||||||
"episodenumber": None,
|
|
||||||
"isnew": False,
|
|
||||||
"id": None,
|
|
||||||
}]
|
|
||||||
return epgitem
|
return epgitem
|
||||||
|
|
||||||
def whats_on_allchans(self, method=None):
|
def whats_on_allchans(self, method=None):
|
||||||
@ -102,23 +87,26 @@ class EPG():
|
|||||||
method not in self.fhdhr.config.dict["epg"]["valid_epg_methods"]):
|
method not in self.fhdhr.config.dict["epg"]["valid_epg_methods"]):
|
||||||
method = "origin"
|
method = "origin"
|
||||||
|
|
||||||
channel_guide_list = []
|
channel_guide_dict = {}
|
||||||
epgdict = self.get_epg(method)
|
epgdict = self.get_epg(method)
|
||||||
if method in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
epgdict = epgdict.copy()
|
||||||
epgdict = epgdict.copy()
|
for c in list(epgdict.keys()):
|
||||||
for c in list(epgdict.keys()):
|
if method in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
||||||
chan_obj = self.channels.get_channel_obj("origin_id", epgdict[c]["id"])
|
chan_obj = self.channels.get_channel_obj("origin_id", epgdict[c]["id"])
|
||||||
epgdict[chan_obj.number] = epgdict.pop(c)
|
channel_number = chan_obj.number
|
||||||
epgdict[chan_obj.number]["name"] = chan_obj.dict["name"]
|
epgdict[channel_number] = epgdict.pop(c)
|
||||||
epgdict[chan_obj.number]["callsign"] = chan_obj.dict["callsign"]
|
epgdict[channel_number]["name"] = chan_obj.dict["name"]
|
||||||
epgdict[chan_obj.number]["number"] = chan_obj.number
|
epgdict[channel_number]["callsign"] = chan_obj.dict["callsign"]
|
||||||
epgdict[chan_obj.number]["id"] = chan_obj.dict["origin_id"]
|
epgdict[channel_number]["number"] = chan_obj.number
|
||||||
epgdict[chan_obj.number]["thumbnail"] = chan_obj.thumbnail
|
epgdict[channel_number]["id"] = chan_obj.dict["origin_id"]
|
||||||
for channel_number in list(epgdict.keys()):
|
epgdict[channel_number]["thumbnail"] = chan_obj.thumbnail
|
||||||
whatson = self.whats_on_now(channel_number, method)
|
else:
|
||||||
|
chan_obj = None
|
||||||
|
channel_number = c
|
||||||
|
whatson = self.whats_on_now(channel_number, method, chan_dict=epgdict, chan_obj=chan_obj)
|
||||||
if whatson:
|
if whatson:
|
||||||
channel_guide_list.append(whatson)
|
channel_guide_dict[channel_number] = whatson
|
||||||
return channel_guide_list
|
return channel_guide_dict
|
||||||
|
|
||||||
def get_epg(self, method=None):
|
def get_epg(self, method=None):
|
||||||
|
|
||||||
@ -194,18 +182,108 @@ class EPG():
|
|||||||
else:
|
else:
|
||||||
programguide = self.epg_handling[method].update_epg()
|
programguide = self.epg_handling[method].update_epg()
|
||||||
|
|
||||||
programguide = OrderedDict(sorted(programguide.items()))
|
# Sort the channels
|
||||||
|
clean_prog_guide = {}
|
||||||
|
sorted_chan_list = sorted(list(programguide.keys()))
|
||||||
|
for cnum in sorted_chan_list:
|
||||||
|
if cnum not in list(clean_prog_guide.keys()):
|
||||||
|
clean_prog_guide[cnum] = programguide[cnum].copy()
|
||||||
|
programguide = clean_prog_guide.copy()
|
||||||
|
|
||||||
for cnum in programguide:
|
# sort the channel listings by time stamp
|
||||||
|
for cnum in list(programguide.keys()):
|
||||||
programguide[cnum]["listing"] = sorted(programguide[cnum]["listing"], key=lambda i: i['time_start'])
|
programguide[cnum]["listing"] = sorted(programguide[cnum]["listing"], key=lambda i: i['time_start'])
|
||||||
|
|
||||||
if method in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
# Gernate Block periods for between EPG data, if missing
|
||||||
|
clean_prog_guide = {}
|
||||||
|
desired_start_time = (datetime.datetime.today() + datetime.timedelta(days=self.fhdhr.config.dict["epg"]["reverse_days"])).timestamp()
|
||||||
|
desired_end_time = (datetime.datetime.today() + datetime.timedelta(days=self.fhdhr.config.dict["epg"]["forward_days"])).timestamp()
|
||||||
|
for cnum in list(programguide.keys()):
|
||||||
|
|
||||||
|
if cnum not in list(clean_prog_guide.keys()):
|
||||||
|
clean_prog_guide[cnum] = programguide[cnum].copy()
|
||||||
|
clean_prog_guide[cnum]["listing"] = []
|
||||||
|
|
||||||
|
if method in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
||||||
|
chan_obj = self.channels.get_channel_obj("origin_id", programguide[cnum]["id"])
|
||||||
|
else:
|
||||||
|
chan_obj = None
|
||||||
|
|
||||||
|
# Generate Blocks for Channels containing No Lisiings
|
||||||
|
if not len(programguide[cnum]["listing"]):
|
||||||
|
timestamps = self.blocks.timestamps_between(desired_start_time, desired_end_time)
|
||||||
|
clean_prog_dicts = self.blocks.empty_channel_epg(timestamps, chan_dict=programguide[cnum], chan_obj=chan_obj)
|
||||||
|
clean_prog_guide[cnum]["listing"].extend(clean_prog_dicts)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# Clean Timetamps from old xmltv method to timestamps
|
||||||
|
progindex = 0
|
||||||
|
for program_item in programguide[cnum]["listing"]:
|
||||||
|
for time_item in ["time_start", "time_end"]:
|
||||||
|
time_value = programguide[cnum]["listing"][progindex][time_item]
|
||||||
|
if str(time_value).endswith("+00:00"):
|
||||||
|
programguide[cnum]["listing"][progindex][time_item] = datetime.datetime.strptime(time_value, '%Y%m%d%H%M%S +00:00').timestamp()
|
||||||
|
elif str(time_value).endswith("+0000"):
|
||||||
|
programguide[cnum]["listing"][progindex][time_item] = datetime.datetime.strptime(time_value, '%Y%m%d%H%M%S +0000').timestamp()
|
||||||
|
else:
|
||||||
|
programguide[cnum]["listing"][progindex][time_item] = int(time_value)
|
||||||
|
progindex += 1
|
||||||
|
|
||||||
|
# Generate time before the listing actually starts
|
||||||
|
first_prog_time = programguide[cnum]["listing"][0]['time_start']
|
||||||
|
if desired_start_time < first_prog_time:
|
||||||
|
timestamps = self.blocks.timestamps_between(desired_start_time, first_prog_time)
|
||||||
|
clean_prog_dicts = self.blocks.empty_channel_epg(timestamps, chan_dict=programguide[cnum], chan_obj=chan_obj)
|
||||||
|
clean_prog_guide[cnum]["listing"].extend(clean_prog_dicts)
|
||||||
|
|
||||||
|
# Generate time blocks between events if chunks of time are missing
|
||||||
|
progindex = 0
|
||||||
|
for program_item in programguide[cnum]["listing"]:
|
||||||
|
try:
|
||||||
|
nextprog_dict = programguide[cnum]["listing"][progindex + 1]
|
||||||
|
except IndexError:
|
||||||
|
nextprog_dict = None
|
||||||
|
if not nextprog_dict:
|
||||||
|
clean_prog_guide[cnum]["listing"].append(program_item)
|
||||||
|
else:
|
||||||
|
if nextprog_dict['time_start'] > program_item['time_end']:
|
||||||
|
timestamps = self.blocks.timestamps_between(program_item['time_end'], nextprog_dict['time_start'])
|
||||||
|
clean_prog_dicts = self.blocks.empty_channel_epg(timestamps, chan_dict=programguide[cnum], chan_obj=chan_obj)
|
||||||
|
clean_prog_guide[cnum]["listing"].extend(clean_prog_dicts)
|
||||||
|
else:
|
||||||
|
clean_prog_guide[cnum]["listing"].append(program_item)
|
||||||
|
progindex += 1
|
||||||
|
|
||||||
|
# Generate time after the listing actually ends
|
||||||
|
end_prog_time = programguide[cnum]["listing"][progindex]['time_end']
|
||||||
|
if desired_end_time > end_prog_time:
|
||||||
|
timestamps = self.blocks.timestamps_between(end_prog_time, desired_end_time)
|
||||||
|
clean_prog_dicts = self.blocks.empty_channel_epg(timestamps, chan_dict=programguide[cnum], chan_obj=chan_obj)
|
||||||
|
clean_prog_guide[cnum]["listing"].extend(clean_prog_dicts)
|
||||||
|
|
||||||
|
programguide = clean_prog_guide.copy()
|
||||||
|
|
||||||
|
# if a stock method, generate Blocks EPG for missing channels
|
||||||
|
if method in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
||||||
|
timestamps = self.blocks.timestamps
|
||||||
for fhdhr_id in list(self.channels.list.keys()):
|
for fhdhr_id in list(self.channels.list.keys()):
|
||||||
chan_obj = self.channels.list[fhdhr_id]
|
chan_obj = self.channels.list[fhdhr_id]
|
||||||
|
|
||||||
if str(chan_obj.number) not in list(programguide.keys()):
|
if str(chan_obj.number) not in list(programguide.keys()):
|
||||||
programguide[str(chan_obj.number)] = chan_obj.epgdict
|
programguide[str(chan_obj.number)] = chan_obj.epgdict
|
||||||
|
clean_prog_dicts = self.blocks.empty_channel_epg(timestamps, chan_obj=chan_obj)
|
||||||
|
programguide[str(chan_obj.number)]["listing"].extend(clean_prog_dicts)
|
||||||
|
|
||||||
|
# Make Thumbnails for missing thumbnails
|
||||||
|
for cnum in list(programguide.keys()):
|
||||||
|
if not programguide[cnum]["thumbnail"]:
|
||||||
|
programguide[cnum]["thumbnail"] = "/api/images?method=generate&type=channel&message=%s" % programguide[cnum]["number"]
|
||||||
|
programguide[cnum]["listing"] = sorted(programguide[cnum]["listing"], key=lambda i: i['time_start'])
|
||||||
|
prog_index = 0
|
||||||
|
for program_item in programguide[cnum]["listing"]:
|
||||||
|
if not programguide[cnum]["listing"][prog_index]["thumbnail"]:
|
||||||
|
programguide[cnum]["listing"][prog_index]["thumbnail"] = programguide[cnum]["thumbnail"]
|
||||||
|
prog_index += 1
|
||||||
|
|
||||||
self.epgdict = programguide
|
self.epgdict = programguide
|
||||||
self.fhdhr.db.set_fhdhr_value("epg_dict", method, programguide)
|
self.fhdhr.db.set_fhdhr_value("epg_dict", method, programguide)
|
||||||
@ -218,7 +296,10 @@ class EPG():
|
|||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
for epg_method in self.epg_methods:
|
for epg_method in self.epg_methods:
|
||||||
if time.time() >= (self.fhdhr.db.get_fhdhr_value("update_time", epg_method) + self.sleeptime[epg_method]):
|
last_update_time = self.fhdhr.db.get_fhdhr_value("update_time", epg_method)
|
||||||
|
if not last_update_time:
|
||||||
|
self.fhdhr.web.session.get(self.epg_update_url)
|
||||||
|
elif time.time() >= (last_update_time + self.sleeptime[epg_method]):
|
||||||
self.fhdhr.web.session.get(self.epg_update_url)
|
self.fhdhr.web.session.get(self.epg_update_url)
|
||||||
time.sleep(360)
|
time.sleep(360)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|||||||
@ -19,56 +19,99 @@ class blocksEPG():
|
|||||||
if str(chan_obj.number) not in list(programguide.keys()):
|
if str(chan_obj.number) not in list(programguide.keys()):
|
||||||
programguide[str(chan_obj.number)] = chan_obj.epgdict
|
programguide[str(chan_obj.number)] = chan_obj.epgdict
|
||||||
|
|
||||||
clean_prog_dicts = self.empty_channel_epg(timestamps, chan_obj)
|
clean_prog_dicts = self.empty_channel_epg(timestamps, chan_obj=chan_obj)
|
||||||
for clean_prog_dict in clean_prog_dicts:
|
for clean_prog_dict in clean_prog_dicts:
|
||||||
programguide[str(chan_obj.number)]["listing"].append(clean_prog_dict)
|
programguide[str(chan_obj.number)]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
return programguide
|
return programguide
|
||||||
|
|
||||||
def get_content_thumbnail(self, content_id):
|
|
||||||
return "/api/images?method=generate&type=content&message=%s" % content_id
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def timestamps(self):
|
def timestamps(self):
|
||||||
timestamps = []
|
desired_start_time = (datetime.datetime.today() + datetime.timedelta(days=self.fhdhr.config.dict["epg"]["reverse_days"])).timestamp()
|
||||||
todaydate = datetime.date.today()
|
desired_end_time = (datetime.datetime.today() + datetime.timedelta(days=self.fhdhr.config.dict["epg"]["forward_days"])).timestamp()
|
||||||
for x in range(0, 6):
|
return self.timestamps_between(desired_start_time, desired_end_time)
|
||||||
xdate = todaydate + datetime.timedelta(days=x)
|
|
||||||
xtdate = xdate + datetime.timedelta(days=1)
|
|
||||||
|
|
||||||
for hour in range(0, 24):
|
def timestamps_between(self, starttime, endtime):
|
||||||
time_start = datetime.datetime.combine(xdate, datetime.time(hour, 0))
|
timestamps = []
|
||||||
if hour + 1 < 24:
|
desired_blocksize = self.fhdhr.config.dict["epg"]["block_size"]
|
||||||
time_end = datetime.datetime.combine(xdate, datetime.time(hour + 1, 0))
|
current_time = starttime
|
||||||
else:
|
while (current_time + desired_blocksize) <= endtime:
|
||||||
time_end = datetime.datetime.combine(xtdate, datetime.time(0, 0))
|
timestampdict = {
|
||||||
timestampdict = {
|
"time_start": current_time,
|
||||||
"time_start": str(time_start.strftime('%Y%m%d%H%M%S')) + " +0000",
|
"time_end": current_time + desired_blocksize,
|
||||||
"time_end": str(time_end.strftime('%Y%m%d%H%M%S')) + " +0000",
|
}
|
||||||
}
|
timestamps.append(timestampdict)
|
||||||
timestamps.append(timestampdict)
|
current_time += desired_blocksize
|
||||||
|
if current_time < endtime:
|
||||||
|
timestampdict = {
|
||||||
|
"time_start": current_time,
|
||||||
|
"time_end": endtime
|
||||||
|
}
|
||||||
|
timestamps.append(timestampdict)
|
||||||
return timestamps
|
return timestamps
|
||||||
|
|
||||||
def empty_channel_epg(self, timestamps, chan_obj):
|
def single_channel_epg(self, timestampdict, chan_obj=None, chan_dict=None):
|
||||||
|
|
||||||
|
if chan_obj:
|
||||||
|
content_id = "%s_%s" % (chan_obj.dict["origin_id"], timestampdict['time_start'])
|
||||||
|
elif chan_dict:
|
||||||
|
content_id = "%s_%s" % (chan_dict["id"], timestampdict['time_start'])
|
||||||
|
|
||||||
|
clean_prog_dict = {
|
||||||
|
"time_start": timestampdict['time_start'],
|
||||||
|
"time_end": timestampdict['time_end'],
|
||||||
|
"duration_minutes": (timestampdict['time_end'] - timestampdict['time_start']) / 60,
|
||||||
|
"title": "Unavailable",
|
||||||
|
"sub-title": "Unavailable",
|
||||||
|
"description": "Unavailable",
|
||||||
|
"rating": "N/A",
|
||||||
|
"episodetitle": None,
|
||||||
|
"releaseyear": None,
|
||||||
|
"genres": [],
|
||||||
|
"seasonnumber": None,
|
||||||
|
"episodenumber": None,
|
||||||
|
"isnew": False,
|
||||||
|
"id": content_id,
|
||||||
|
}
|
||||||
|
if chan_obj:
|
||||||
|
clean_prog_dict["thumbnail"] = chan_obj.thumbnail
|
||||||
|
elif chan_dict:
|
||||||
|
clean_prog_dict["thumbnail"] = chan_dict["thumbnail"]
|
||||||
|
if not clean_prog_dict["thumbnail"]:
|
||||||
|
clean_prog_dict["thumbnail"] = "/api/images?method=generate&type=content&message=%s" % content_id
|
||||||
|
|
||||||
|
return clean_prog_dict
|
||||||
|
|
||||||
|
def empty_channel_epg(self, timestamps, chan_obj=None, chan_dict=None):
|
||||||
clean_prog_dicts = []
|
clean_prog_dicts = []
|
||||||
for timestamp in timestamps:
|
for timestampdict in timestamps:
|
||||||
content_id = "%s_%s" % (chan_obj.dict["origin_id"], str(timestamp['time_start']).split(" ")[0])
|
clean_prog_dict = self.single_channel_epg(timestampdict, chan_obj=chan_obj, chan_dict=chan_dict)
|
||||||
clean_prog_dict = {
|
|
||||||
"time_start": timestamp['time_start'],
|
|
||||||
"time_end": timestamp['time_end'],
|
|
||||||
"duration_minutes": 60,
|
|
||||||
"thumbnail": chan_obj.dict["thumbnail"] or self.get_content_thumbnail(content_id),
|
|
||||||
"title": "Unavailable",
|
|
||||||
"sub-title": "Unavailable",
|
|
||||||
"description": "Unavailable",
|
|
||||||
"rating": "N/A",
|
|
||||||
"episodetitle": None,
|
|
||||||
"releaseyear": None,
|
|
||||||
"genres": [],
|
|
||||||
"seasonnumber": None,
|
|
||||||
"episodenumber": None,
|
|
||||||
"isnew": False,
|
|
||||||
"id": content_id,
|
|
||||||
}
|
|
||||||
clean_prog_dicts.append(clean_prog_dict)
|
clean_prog_dicts.append(clean_prog_dict)
|
||||||
return clean_prog_dicts
|
return clean_prog_dicts
|
||||||
|
|
||||||
|
def empty_listing(self, chan_obj=None, chan_dict=None):
|
||||||
|
clean_prog_dict = {
|
||||||
|
"time_start": None,
|
||||||
|
"time_end": None,
|
||||||
|
"duration_minutes": None,
|
||||||
|
"title": "Unavailable",
|
||||||
|
"sub-title": "Unavailable",
|
||||||
|
"description": "Unavailable",
|
||||||
|
"rating": "N/A",
|
||||||
|
"episodetitle": None,
|
||||||
|
"releaseyear": None,
|
||||||
|
"genres": [],
|
||||||
|
"seasonnumber": None,
|
||||||
|
"episodenumber": None,
|
||||||
|
"isnew": False,
|
||||||
|
"id": "Unavailable",
|
||||||
|
}
|
||||||
|
|
||||||
|
if chan_obj:
|
||||||
|
clean_prog_dict["thumbnail"] = chan_obj.thumbnail
|
||||||
|
elif chan_dict:
|
||||||
|
clean_prog_dict["thumbnail"] = chan_dict["thumbnail"]
|
||||||
|
if not clean_prog_dict["thumbnail"]:
|
||||||
|
clean_prog_dict["thumbnail"] = "/api/images?method=generate&type=content&message=Unavailable"
|
||||||
|
|
||||||
|
return clean_prog_dict
|
||||||
|
|||||||
@ -2,6 +2,7 @@ from flask import Response, request, redirect
|
|||||||
import xml.etree.ElementTree
|
import xml.etree.ElementTree
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import datetime
|
||||||
|
|
||||||
from fHDHR.tools import sub_el
|
from fHDHR.tools import sub_el
|
||||||
|
|
||||||
@ -90,6 +91,18 @@ class xmlTV():
|
|||||||
"""This method is called when creation of a full xmltv is not possible"""
|
"""This method is called when creation of a full xmltv is not possible"""
|
||||||
return self.xmltv_file(self.xmltv_headers())
|
return self.xmltv_file(self.xmltv_headers())
|
||||||
|
|
||||||
|
def timestamp_to_datetime(self, time_start, time_end):
|
||||||
|
xmltvtimetamps = {}
|
||||||
|
|
||||||
|
for time_item, time_value in zip(["time_start", "time_end"], [time_start, time_end]):
|
||||||
|
|
||||||
|
if str(time_value).endswith(tuple(["+0000", "+00:00"])):
|
||||||
|
xmltvtimetamps[time_item] = str(time_value)
|
||||||
|
else:
|
||||||
|
xmltvtimetamps[time_item] = str(datetime.datetime.fromtimestamp(time_value)) + " +0000"
|
||||||
|
|
||||||
|
return xmltvtimetamps
|
||||||
|
|
||||||
def create_xmltv(self, base_url, epgdict, source):
|
def create_xmltv(self, base_url, epgdict, source):
|
||||||
if not epgdict:
|
if not epgdict:
|
||||||
return self.xmltv_empty()
|
return self.xmltv_empty()
|
||||||
@ -129,9 +142,11 @@ class xmlTV():
|
|||||||
|
|
||||||
for program in channel_listing:
|
for program in channel_listing:
|
||||||
|
|
||||||
|
xmltvtimetamps = self.timestamp_to_datetime(program['time_start'], program['time_end'])
|
||||||
|
|
||||||
prog_out = sub_el(out, 'programme',
|
prog_out = sub_el(out, 'programme',
|
||||||
start=program['time_start'],
|
start=xmltvtimetamps['time_start'],
|
||||||
stop=program['time_end'],
|
stop=xmltvtimetamps['time_end'],
|
||||||
channel=str(channelnum))
|
channel=str(channelnum))
|
||||||
|
|
||||||
sub_el(prog_out, 'title', lang='en', text=program['title'])
|
sub_el(prog_out, 'title', lang='en', text=program['title'])
|
||||||
|
|||||||
@ -24,4 +24,6 @@ class Channels_Editor_HTML():
|
|||||||
|
|
||||||
channelslist.append(channel_dict)
|
channelslist.append(channel_dict)
|
||||||
|
|
||||||
|
channelslist = sorted(channelslist, key=lambda i: i['number'])
|
||||||
|
|
||||||
return render_template('channels_editor.html', request=request, fhdhr=self.fhdhr, channelslist=channelslist)
|
return render_template('channels_editor.html', request=request, fhdhr=self.fhdhr, channelslist=channelslist)
|
||||||
|
|||||||
@ -31,4 +31,6 @@ class Channels_HTML():
|
|||||||
if channel_dict["enabled"]:
|
if channel_dict["enabled"]:
|
||||||
channels_dict["Enabled"] += 1
|
channels_dict["Enabled"] += 1
|
||||||
|
|
||||||
|
channelslist = sorted(channelslist, key=lambda i: i['number'])
|
||||||
|
|
||||||
return render_template('channels.html', request=request, fhdhr=self.fhdhr, channelslist=channelslist, channels_dict=channels_dict, list=list)
|
return render_template('channels.html', request=request, fhdhr=self.fhdhr, channelslist=channelslist, channels_dict=channels_dict, list=list)
|
||||||
|
|||||||
@ -14,9 +14,28 @@ class Guide_HTML():
|
|||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
return self.get(*args)
|
return self.get(*args)
|
||||||
|
|
||||||
|
def number_sort(self, chan_dict):
|
||||||
|
for channel in list(chan_dict.keys()):
|
||||||
|
number = chan_dict[channel]["number"]
|
||||||
|
chan_dict[channel]["number"] = number.split(".")[0]
|
||||||
|
try:
|
||||||
|
chan_dict[channel]["subnumber"] = number.split(".")[1]
|
||||||
|
except IndexError:
|
||||||
|
chan_dict[channel]["subnumber"] = None
|
||||||
|
sorted_chan_list = sorted(list(chan_dict.keys()), key=lambda i: (int(chan_dict[i]['number']), int(chan_dict[i]['subnumber'] or 0)))
|
||||||
|
sorted_chan_dict = {}
|
||||||
|
for cnum in sorted_chan_list:
|
||||||
|
if cnum not in list(sorted_chan_dict.keys()):
|
||||||
|
sorted_chan_dict[cnum] = chan_dict[cnum].copy()
|
||||||
|
if sorted_chan_dict[cnum]["subnumber"]:
|
||||||
|
sorted_chan_dict[cnum]["number"] = "%s.%s" % (sorted_chan_dict[cnum]["number"], sorted_chan_dict[cnum]["subnumber"])
|
||||||
|
del sorted_chan_dict[cnum]["subnumber"]
|
||||||
|
chan_dict = sorted_chan_dict.copy()
|
||||||
|
return chan_dict
|
||||||
|
|
||||||
def get(self, *args):
|
def get(self, *args):
|
||||||
|
|
||||||
nowtime = datetime.datetime.utcnow()
|
nowtime = datetime.datetime.utcnow().timestamp()
|
||||||
|
|
||||||
chan_guide_list = []
|
chan_guide_list = []
|
||||||
|
|
||||||
@ -25,24 +44,38 @@ class Guide_HTML():
|
|||||||
if source not in epg_methods:
|
if source not in epg_methods:
|
||||||
source = self.fhdhr.device.epg.def_method
|
source = self.fhdhr.device.epg.def_method
|
||||||
|
|
||||||
for channel in self.fhdhr.device.epg.whats_on_allchans(source):
|
whatson = self.fhdhr.device.epg.whats_on_allchans(source)
|
||||||
if channel["listing"][0]["time_end"]:
|
|
||||||
end_time = datetime.datetime.strptime(channel["listing"][0]["time_end"], '%Y%m%d%H%M%S +0000')
|
# Sort the channels
|
||||||
remaining_time = humanized_time(int((end_time - nowtime).total_seconds()))
|
sorted_chan_guide = self.number_sort(whatson)
|
||||||
|
|
||||||
|
for channel in list(sorted_chan_guide.keys()):
|
||||||
|
if sorted_chan_guide[channel]["listing"][0]["time_end"]:
|
||||||
|
remaining_time = humanized_time(sorted_chan_guide[channel]["listing"][0]["time_end"] - nowtime)
|
||||||
else:
|
else:
|
||||||
remaining_time = "N/A"
|
remaining_time = "N/A"
|
||||||
|
|
||||||
chan_dict = {
|
chan_dict = {
|
||||||
"name": channel["name"],
|
"name": sorted_chan_guide[channel]["name"],
|
||||||
"number": channel["number"],
|
"number": sorted_chan_guide[channel]["number"],
|
||||||
"chan_thumbnail": channel["thumbnail"],
|
"chan_thumbnail": sorted_chan_guide[channel]["thumbnail"],
|
||||||
"listing_title": channel["listing"][0]["title"],
|
"listing_title": sorted_chan_guide[channel]["listing"][0]["title"],
|
||||||
"listing_thumbnail": channel["listing"][0]["thumbnail"],
|
"listing_thumbnail": sorted_chan_guide[channel]["listing"][0]["thumbnail"],
|
||||||
"listing_description": channel["listing"][0]["description"],
|
"listing_description": sorted_chan_guide[channel]["listing"][0]["description"],
|
||||||
"remaining_time": str(remaining_time)
|
"listing_remaining_time": str(remaining_time)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for time_item in ["time_start", "time_end"]:
|
||||||
|
|
||||||
|
if not sorted_chan_guide[channel]["listing"][0][time_item]:
|
||||||
|
chan_dict["listing_%s" % time_item] = "N/A"
|
||||||
|
elif str(sorted_chan_guide[channel]["listing"][0][time_item]).endswith(tuple(["+0000", "+00:00"])):
|
||||||
|
chan_dict["listing_%s" % time_item] = str(sorted_chan_guide[channel]["listing"][0][time_item])
|
||||||
|
else:
|
||||||
|
chan_dict["listing_%s" % time_item] = str(datetime.datetime.fromtimestamp(sorted_chan_guide[channel]["listing"][0][time_item]))
|
||||||
|
|
||||||
if source in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
if source in ["blocks", "origin", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
||||||
chan_obj = self.fhdhr.device.channels.get_channel_obj("origin_id", channel["id"])
|
chan_obj = self.fhdhr.device.channels.get_channel_obj("origin_id", sorted_chan_guide[channel]["id"])
|
||||||
|
|
||||||
chan_dict["name"] = chan_obj.dict["name"]
|
chan_dict["name"] = chan_obj.dict["name"]
|
||||||
chan_dict["number"] = chan_obj.number
|
chan_dict["number"] = chan_obj.number
|
||||||
@ -50,6 +83,13 @@ class Guide_HTML():
|
|||||||
chan_dict["enabled"] = chan_obj.dict["enabled"]
|
chan_dict["enabled"] = chan_obj.dict["enabled"]
|
||||||
chan_dict["play_url"] = chan_obj.play_url
|
chan_dict["play_url"] = chan_obj.play_url
|
||||||
|
|
||||||
|
chan_dict["listing_thumbnail"] = chan_dict["listing_thumbnail"] or chan_obj.thumbnail
|
||||||
|
else:
|
||||||
|
if not chan_dict["listing_thumbnail"]:
|
||||||
|
chan_dict["listing_thumbnail"] = chan_dict["chan_thumbnail"]
|
||||||
|
if not chan_dict["listing_thumbnail"]:
|
||||||
|
chan_dict["listing_thumbnail"] = "/api/images?method=generate&type=channel&message=%s" % chan_dict["number"]
|
||||||
|
|
||||||
chan_guide_list.append(chan_dict)
|
chan_guide_list.append(chan_dict)
|
||||||
|
|
||||||
return render_template('guide.html', request=request, fhdhr=self.fhdhr, chan_guide_list=chan_guide_list, epg_methods=epg_methods, source=source)
|
return render_template('guide.html', request=request, fhdhr=self.fhdhr, chan_guide_list=chan_guide_list, epg_methods=epg_methods, source=source)
|
||||||
|
|||||||
@ -21,6 +21,8 @@
|
|||||||
<th>Content Title</th>
|
<th>Content Title</th>
|
||||||
<th>Content Thumbnail</th>
|
<th>Content Thumbnail</th>
|
||||||
<th>Content Description</th>
|
<th>Content Description</th>
|
||||||
|
<th>Start Time (UTC)</th>
|
||||||
|
<th>End Time (UTC)</th>
|
||||||
<th>Content Remaining Time</th>
|
<th>Content Remaining Time</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@ -39,7 +41,9 @@
|
|||||||
<td>{{ chan_dict["listing_title"] }}</td>
|
<td>{{ chan_dict["listing_title"] }}</td>
|
||||||
<td><img src="{{ chan_dict["listing_thumbnail"] }}" alt="{{ chan_dict["listing_title"] }}" width="100" height="100"></td>
|
<td><img src="{{ chan_dict["listing_thumbnail"] }}" alt="{{ chan_dict["listing_title"] }}" width="100" height="100"></td>
|
||||||
<td>{{ chan_dict["listing_description"] }}</td>
|
<td>{{ chan_dict["listing_description"] }}</td>
|
||||||
<td>{{ chan_dict["remaining_time"] }}</td>
|
<td>{{ chan_dict["listing_time_start"] }}</td>
|
||||||
|
<td>{{ chan_dict["listing_time_end"] }}</td>
|
||||||
|
<td>{{ chan_dict["listing_remaining_time"] }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import datetime
|
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
import fHDHR.tools
|
import fHDHR.tools
|
||||||
@ -19,11 +18,6 @@ class OriginEPG():
|
|||||||
))
|
))
|
||||||
return item_thumb_url
|
return item_thumb_url
|
||||||
|
|
||||||
def xmltimestamp_nextpvr(self, epochtime):
|
|
||||||
xmltime = datetime.datetime.fromtimestamp(int(epochtime)/1000)
|
|
||||||
xmltime = str(xmltime.strftime('%Y%m%d%H%M%S')) + " +0000"
|
|
||||||
return xmltime
|
|
||||||
|
|
||||||
def duration_nextpvr_minutes(self, starttime, endtime):
|
def duration_nextpvr_minutes(self, starttime, endtime):
|
||||||
return ((int(endtime) - int(starttime))/1000/60)
|
return ((int(endtime) - int(starttime))/1000/60)
|
||||||
|
|
||||||
@ -33,9 +27,9 @@ class OriginEPG():
|
|||||||
for fhdhr_id in list(fhdhr_channels.list.keys()):
|
for fhdhr_id in list(fhdhr_channels.list.keys()):
|
||||||
chan_obj = fhdhr_channels.list[fhdhr_id]
|
chan_obj = fhdhr_channels.list[fhdhr_id]
|
||||||
|
|
||||||
if str(chan_obj.dict['number']) not in list(programguide.keys()):
|
if str(chan_obj.number) not in list(programguide.keys()):
|
||||||
|
|
||||||
programguide[str(chan_obj.dict["number"])] = chan_obj.epgdict
|
programguide[str(chan_obj.number)] = chan_obj.epgdict
|
||||||
|
|
||||||
epg_url = ('%s%s:%s/service?method=channel.listings&channel_id=%s' %
|
epg_url = ('%s%s:%s/service?method=channel.listings&channel_id=%s' %
|
||||||
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
||||||
@ -53,8 +47,8 @@ class OriginEPG():
|
|||||||
progdict = fHDHR.tools.xmldictmaker(program_item, ["start", "end", "title", "name", "subtitle", "rating", "description", "season", "episode", "id", "episodeTitle"])
|
progdict = fHDHR.tools.xmldictmaker(program_item, ["start", "end", "title", "name", "subtitle", "rating", "description", "season", "episode", "id", "episodeTitle"])
|
||||||
|
|
||||||
clean_prog_dict = {
|
clean_prog_dict = {
|
||||||
"time_start": self.xmltimestamp_nextpvr(progdict["start"]),
|
"time_start": (int(progdict["start"]) / 1000),
|
||||||
"time_end": self.xmltimestamp_nextpvr(progdict["end"]),
|
"time_end": (int(progdict["end"]) / 1000),
|
||||||
"duration_minutes": self.duration_nextpvr_minutes(progdict["start"], progdict["end"]),
|
"duration_minutes": self.duration_nextpvr_minutes(progdict["start"], progdict["end"]),
|
||||||
"thumbnail": self.get_content_thumbnail(progdict['id']),
|
"thumbnail": self.get_content_thumbnail(progdict['id']),
|
||||||
"title": progdict['name'] or "Unavailable",
|
"title": progdict['name'] or "Unavailable",
|
||||||
@ -67,7 +61,7 @@ class OriginEPG():
|
|||||||
"seasonnumber": progdict['season'],
|
"seasonnumber": progdict['season'],
|
||||||
"episodenumber": progdict['episode'],
|
"episodenumber": progdict['episode'],
|
||||||
"isnew": False,
|
"isnew": False,
|
||||||
"id": str(progdict['id'] or self.xmltimestamp_nextpvr(progdict["start"])),
|
"id": str(progdict['id'] or "%s_%s" % (chan_obj.dict['origin_id'], progdict["start"])),
|
||||||
}
|
}
|
||||||
|
|
||||||
if 'genre' in list(progdict.keys()):
|
if 'genre' in list(progdict.keys()):
|
||||||
@ -80,7 +74,7 @@ class OriginEPG():
|
|||||||
|
|
||||||
# TODO isNEW
|
# TODO isNEW
|
||||||
|
|
||||||
if not any(d['id'] == clean_prog_dict['id'] for d in programguide[str(chan_obj.dict["number"])]["listing"]):
|
if not any((d['time_start'] == clean_prog_dict['time_start'] and d['id'] == clean_prog_dict['id']) for d in programguide[chan_obj.number]["listing"]):
|
||||||
programguide[str(chan_obj.dict["number"])]["listing"].append(clean_prog_dict)
|
programguide[str(chan_obj.number)]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
return programguide
|
return programguide
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user