mirror of
https://github.com/fHDHR/fHDHR_NextPVR.git
synced 2025-12-06 16:16:58 -05:00
commit
1b7e5cd2ba
2
alternative_epg/__init__.py
Normal file
2
alternative_epg/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# pylama:ignore=W0401,W0611
|
||||||
|
from .zap2it import *
|
||||||
@ -4,6 +4,16 @@
|
|||||||
"value": "pass",
|
"value": "pass",
|
||||||
"config_file": true,
|
"config_file": true,
|
||||||
"config_web": true
|
"config_web": true
|
||||||
|
},
|
||||||
|
"method":{
|
||||||
|
"value": "blocks",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
|
},
|
||||||
|
"update_frequency":{
|
||||||
|
"value": 14400,
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,13 +49,26 @@
|
|||||||
"value": true,
|
"value": true,
|
||||||
"config_file": true,
|
"config_file": true,
|
||||||
"config_web": true
|
"config_web": true
|
||||||
}
|
},
|
||||||
},
|
"friendlyname":{
|
||||||
"web_ui":{
|
"value": "fHDHR",
|
||||||
"theme":{
|
"config_file": true,
|
||||||
"value": "none",
|
"config_web": true
|
||||||
"config_file": true,
|
},
|
||||||
"config_web": true
|
"stream_type":{
|
||||||
}
|
"value": "direct",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
|
},
|
||||||
|
"tuner_count":{
|
||||||
|
"value": 4,
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
|
},
|
||||||
|
"reporting_firmware_name":{
|
||||||
|
"value": "fHDHR",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,31 @@
|
|||||||
"value": "multiprocessing",
|
"value": "multiprocessing",
|
||||||
"config_file": true,
|
"config_file": true,
|
||||||
"config_web": true
|
"config_web": true
|
||||||
|
},
|
||||||
|
"servicename":{
|
||||||
|
"value": "fHDHR",
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"dictpopname":{
|
||||||
|
"value": "fHDHR",
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"reponame":{
|
||||||
|
"value": "fHDHR",
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"valid_epg_methods":{
|
||||||
|
"value": "None,blocks",
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
|
},
|
||||||
|
"required":{
|
||||||
|
"value": "none",
|
||||||
|
"config_file": false,
|
||||||
|
"config_web": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
data/internal_config/web_ui.json
Normal file
9
data/internal_config/web_ui.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"web_ui":{
|
||||||
|
"theme":{
|
||||||
|
"value": "none",
|
||||||
|
"config_file": true,
|
||||||
|
"config_web": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
|
|
||||||
from .origin import OriginServiceWrapper
|
from .originwrapper import OriginServiceWrapper
|
||||||
from .device import fHDHR_Device
|
from .device import fHDHR_Device
|
||||||
|
|
||||||
import fHDHR.tools
|
import fHDHR.tools
|
||||||
@ -21,12 +21,12 @@ class fHDHR_INT_OBJ():
|
|||||||
|
|
||||||
class fHDHR_OBJ():
|
class fHDHR_OBJ():
|
||||||
|
|
||||||
def __init__(self, settings, logger, db):
|
def __init__(self, settings, logger, db, alternative_epg, origin):
|
||||||
self.fhdhr = fHDHR_INT_OBJ(settings, logger, db)
|
self.fhdhr = fHDHR_INT_OBJ(settings, logger, db)
|
||||||
|
|
||||||
self.origin = OriginServiceWrapper(self.fhdhr)
|
self.originwrapper = OriginServiceWrapper(self.fhdhr, origin)
|
||||||
|
|
||||||
self.device = fHDHR_Device(self.fhdhr, self.origin)
|
self.device = fHDHR_Device(self.fhdhr, self.originwrapper, alternative_epg)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
''' will only get called for undefined attributes '''
|
''' will only get called for undefined attributes '''
|
||||||
|
|||||||
@ -38,9 +38,9 @@ def get_configuration(args, script_dir):
|
|||||||
return fHDHR.config.Config(args.cfg, script_dir)
|
return fHDHR.config.Config(args.cfg, script_dir)
|
||||||
|
|
||||||
|
|
||||||
def run(settings, logger, db):
|
def run(settings, logger, db, alternative_epg, origin):
|
||||||
|
|
||||||
fhdhr = fHDHR_OBJ(settings, logger, db)
|
fhdhr = fHDHR_OBJ(settings, logger, db, alternative_epg, origin)
|
||||||
fhdhrweb = fHDHR_HTTP_Server(fhdhr)
|
fhdhrweb = fHDHR_HTTP_Server(fhdhr)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -81,7 +81,7 @@ def run(settings, logger, db):
|
|||||||
return ERR_CODE
|
return ERR_CODE
|
||||||
|
|
||||||
|
|
||||||
def start(args, script_dir):
|
def start(args, script_dir, alternative_epg, origin):
|
||||||
"""Get Configuration for fHDHR and start"""
|
"""Get Configuration for fHDHR and start"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -94,17 +94,17 @@ def start(args, script_dir):
|
|||||||
|
|
||||||
db = fHDHRdb(settings)
|
db = fHDHRdb(settings)
|
||||||
|
|
||||||
return run(settings, logger, db)
|
return run(settings, logger, db, alternative_epg, origin)
|
||||||
|
|
||||||
|
|
||||||
def main(script_dir):
|
def main(script_dir, alternative_epg, origin):
|
||||||
"""fHDHR run script entry point"""
|
"""fHDHR run script entry point"""
|
||||||
|
|
||||||
print("Loading fHDHR " + fHDHR_VERSION)
|
print("Loading fHDHR " + fHDHR_VERSION)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
args = build_args_parser()
|
args = build_args_parser()
|
||||||
return start(args, script_dir)
|
return start(args, script_dir, alternative_epg, origin)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("\n\nInterrupted")
|
print("\n\nInterrupted")
|
||||||
return ERR_CODE
|
return ERR_CODE
|
||||||
|
|||||||
@ -32,6 +32,8 @@ class Config():
|
|||||||
self.internal["paths"] = {
|
self.internal["paths"] = {
|
||||||
"script_dir": script_dir,
|
"script_dir": script_dir,
|
||||||
"data_dir": data_dir,
|
"data_dir": data_dir,
|
||||||
|
"alternative_epg": pathlib.Path(script_dir).joinpath('alternative_epg'),
|
||||||
|
"origin": pathlib.Path(script_dir).joinpath('origin'),
|
||||||
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
|
"cache_dir": pathlib.Path(data_dir).joinpath('cache'),
|
||||||
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
|
"internal_config": pathlib.Path(data_dir).joinpath('internal_config'),
|
||||||
"www_dir": www_dir,
|
"www_dir": www_dir,
|
||||||
@ -44,6 +46,13 @@ class Config():
|
|||||||
if str(conffilepath).endswith(".json"):
|
if str(conffilepath).endswith(".json"):
|
||||||
self.read_json_config(conffilepath)
|
self.read_json_config(conffilepath)
|
||||||
|
|
||||||
|
for dir_type in ["alternative_epg", "origin"]:
|
||||||
|
|
||||||
|
for file_item in os.listdir(self.internal["paths"][dir_type]):
|
||||||
|
file_item_path = os.path.join(self.internal["paths"][dir_type], file_item)
|
||||||
|
if str(file_item_path).endswith("_conf.json"):
|
||||||
|
self.read_json_config(file_item_path)
|
||||||
|
|
||||||
print("Loading Configuration File: " + str(self.config_file))
|
print("Loading Configuration File: " + str(self.config_file))
|
||||||
self.read_ini_config(self.config_file)
|
self.read_ini_config(self.config_file)
|
||||||
|
|
||||||
|
|||||||
@ -8,11 +8,11 @@ from .cluster import fHDHR_Cluster
|
|||||||
|
|
||||||
class fHDHR_Device():
|
class fHDHR_Device():
|
||||||
|
|
||||||
def __init__(self, fhdhr, origin):
|
def __init__(self, fhdhr, originwrapper, alternative_epg):
|
||||||
|
|
||||||
self.channels = Channels(fhdhr, origin)
|
self.channels = Channels(fhdhr, originwrapper)
|
||||||
|
|
||||||
self.epg = EPG(fhdhr, self.channels, origin)
|
self.epg = EPG(fhdhr, self.channels, originwrapper, alternative_epg)
|
||||||
|
|
||||||
self.tuners = Tuners(fhdhr, self.epg, self.channels)
|
self.tuners = Tuners(fhdhr, self.epg, self.channels)
|
||||||
|
|
||||||
|
|||||||
@ -9,10 +9,10 @@ from .chan_ident import Channel_IDs
|
|||||||
|
|
||||||
class Channels():
|
class Channels():
|
||||||
|
|
||||||
def __init__(self, fhdhr, origin):
|
def __init__(self, fhdhr, originwrapper):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
self.origin = origin
|
self.origin = originwrapper
|
||||||
|
|
||||||
self.id_system = Channel_IDs(fhdhr)
|
self.id_system = Channel_IDs(fhdhr)
|
||||||
|
|
||||||
|
|||||||
@ -12,15 +12,38 @@ class Channel():
|
|||||||
channel_id = id_system.get(origin_id)
|
channel_id = id_system.get(origin_id)
|
||||||
else:
|
else:
|
||||||
channel_id = id_system.assign()
|
channel_id = id_system.assign()
|
||||||
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "dict") or self.default_dict(channel_id)
|
self.channel_id = channel_id
|
||||||
|
self.dict = self.fhdhr.db.get_channel_value(str(channel_id), "dict") or self.default_dict
|
||||||
self.verify_dict()
|
self.verify_dict()
|
||||||
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def thumbnail(self):
|
||||||
|
if str(self.dict["thumbnail"]).lower() in ["none"]:
|
||||||
|
return self.generic_image_url
|
||||||
|
elif self.dict["thumbnail"]:
|
||||||
|
return self.dict["thumbnail"]
|
||||||
|
elif self.dict["origin_thumbnail"]:
|
||||||
|
return self.dict["origin_thumbnail"]
|
||||||
|
else:
|
||||||
|
return self.generic_image_url
|
||||||
|
|
||||||
|
@property
|
||||||
|
def epgdict(self):
|
||||||
|
return {
|
||||||
|
"callsign": self.dict["callsign"],
|
||||||
|
"name": self.dict["name"],
|
||||||
|
"number": self.dict["number"],
|
||||||
|
"id": self.dict["origin_id"],
|
||||||
|
"thumbnail": self.dict["thumbnail"],
|
||||||
|
"listing": [],
|
||||||
|
}
|
||||||
|
|
||||||
def verify_dict(self):
|
def verify_dict(self):
|
||||||
"""Development Purposes
|
"""Development Purposes
|
||||||
Add new Channel dict keys
|
Add new Channel dict keys
|
||||||
"""
|
"""
|
||||||
default_dict = self.default_dict(self.dict["id"])
|
default_dict = self.default_dict
|
||||||
for key in list(default_dict.keys()):
|
for key in list(default_dict.keys()):
|
||||||
if key not in list(self.dict.keys()):
|
if key not in list(self.dict.keys()):
|
||||||
self.dict[key] = default_dict[key]
|
self.dict[key] = default_dict[key]
|
||||||
@ -68,9 +91,10 @@ class Channel():
|
|||||||
|
|
||||||
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
||||||
|
|
||||||
def default_dict(self, channel_id):
|
@property
|
||||||
|
def default_dict(self):
|
||||||
return {
|
return {
|
||||||
"id": str(channel_id), "origin_id": None,
|
"id": str(self.channel_id), "origin_id": None,
|
||||||
"name": None, "origin_name": None,
|
"name": None, "origin_name": None,
|
||||||
"callsign": None, "origin_callsign": None,
|
"callsign": None, "origin_callsign": None,
|
||||||
"number": None, "origin_number": None,
|
"number": None, "origin_number": None,
|
||||||
@ -94,21 +118,28 @@ class Channel():
|
|||||||
self.dict[key] = updatedict[key]
|
self.dict[key] = updatedict[key]
|
||||||
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
self.fhdhr.db.set_channel_value(self.dict["id"], "dict", self.dict)
|
||||||
|
|
||||||
|
@property
|
||||||
def lineup_dict(self):
|
def lineup_dict(self):
|
||||||
return {
|
return {
|
||||||
'GuideNumber': self.dict['number'],
|
'GuideNumber': self.dict['number'],
|
||||||
'GuideName': self.dict['name'],
|
'GuideName': self.dict['name'],
|
||||||
'Tags': ",".join(self.dict['tags']),
|
'Tags': ",".join(self.dict['tags']),
|
||||||
'URL': self.stream_url(),
|
'URL': self.stream_url,
|
||||||
'HD': self.dict["HD"],
|
'HD': self.dict["HD"],
|
||||||
"Favorite": self.dict["favorite"],
|
"Favorite": self.dict["favorite"],
|
||||||
}
|
}
|
||||||
|
|
||||||
def stream_url(self):
|
@property
|
||||||
return ('/auto/v%s' % self.dict['number'])
|
def generic_image_url(self):
|
||||||
|
return "/api/images?method=generate&type=channel&message=%s" % self.dict["number"]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def stream_url(self):
|
||||||
|
return '/auto/v%s' % self.dict['number']
|
||||||
|
|
||||||
|
@property
|
||||||
def play_url(self):
|
def play_url(self):
|
||||||
return ('/api/m3u?method=get&channel=%s' % self.dict['number'])
|
return '/api/m3u?method=get&channel=%s' % self.dict['number']
|
||||||
|
|
||||||
def set_favorite(self, enablement):
|
def set_favorite(self, enablement):
|
||||||
if enablement == "+":
|
if enablement == "+":
|
||||||
|
|||||||
@ -3,30 +3,30 @@ import time
|
|||||||
import datetime
|
import datetime
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
epgtype_list = []
|
from .blocks import blocksEPG
|
||||||
device_dir = os.path.dirname(__file__)
|
|
||||||
for entry in os.scandir(device_dir + '/epgtypes'):
|
|
||||||
if entry.is_file():
|
|
||||||
if entry.name[0] != '_':
|
|
||||||
epgtype_list.append(str(entry.name[:-3]))
|
|
||||||
impstring = f'from .epgtypes import {entry.name}'[:-3]
|
|
||||||
exec(impstring)
|
|
||||||
|
|
||||||
|
|
||||||
class EPG():
|
class EPG():
|
||||||
|
|
||||||
def __init__(self, fhdhr, channels, origin):
|
def __init__(self, fhdhr, channels, originwrapper, alternative_epg):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
self.origin = origin
|
self.origin = originwrapper
|
||||||
self.channels = channels
|
self.channels = channels
|
||||||
|
self.alternative_epg = alternative_epg
|
||||||
|
|
||||||
self.epgdict = {}
|
self.epgdict = {}
|
||||||
|
|
||||||
self.epg_method_selfadd()
|
|
||||||
|
|
||||||
self.epg_methods = self.fhdhr.config.dict["epg"]["method"]
|
self.epg_methods = self.fhdhr.config.dict["epg"]["method"]
|
||||||
self.valid_epg_methods = [x for x in self.fhdhr.config.dict["main"]["valid_epg_methods"] if x and x not in [None, "None"]]
|
self.valid_epg_methods = [x for x in self.fhdhr.config.dict["main"]["valid_epg_methods"] if x and x not in [None, "None"]]
|
||||||
|
|
||||||
|
self.blocks = blocksEPG(self.fhdhr, self.channels)
|
||||||
|
self.epg_handling = {
|
||||||
|
"origin": self.origin,
|
||||||
|
"blocks": self.blocks,
|
||||||
|
}
|
||||||
|
self.epg_method_selfadd()
|
||||||
|
|
||||||
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 self.epg_methods:
|
||||||
@ -50,10 +50,8 @@ class EPG():
|
|||||||
|
|
||||||
self.fhdhr.logger.info("Clearing " + epgtypename + " EPG cache.")
|
self.fhdhr.logger.info("Clearing " + epgtypename + " EPG cache.")
|
||||||
|
|
||||||
method_to_call = getattr(self, method)
|
if hasattr(self.epg_handling[method], 'clear_cache'):
|
||||||
if hasattr(method_to_call, 'clear_cache'):
|
self.epg_handling[method].clear_cache()
|
||||||
func_to_call = getattr(method_to_call, 'clear_cache')
|
|
||||||
func_to_call()
|
|
||||||
|
|
||||||
if method in list(self.epgdict.keys()):
|
if method in list(self.epgdict.keys()):
|
||||||
del self.epgdict[method]
|
del self.epgdict[method]
|
||||||
@ -134,17 +132,23 @@ class EPG():
|
|||||||
return next(item for item in event_list if item["id"] == event_id)
|
return next(item for item in event_list if item["id"] == event_id)
|
||||||
|
|
||||||
def epg_method_selfadd(self):
|
def epg_method_selfadd(self):
|
||||||
self.fhdhr.logger.info("Checking for Optional EPG methods.")
|
self.fhdhr.logger.info("Checking for Alternative EPG methods.")
|
||||||
for method in epgtype_list:
|
new_epgtype_list = []
|
||||||
|
for entry in os.scandir(self.fhdhr.config.internal["paths"]["alternative_epg"]):
|
||||||
|
if entry.is_file():
|
||||||
|
if entry.name[0] != '_' and entry.name.endswith(".py"):
|
||||||
|
new_epgtype_list.append(str(entry.name[:-3]))
|
||||||
|
for method in new_epgtype_list:
|
||||||
self.fhdhr.logger.info("Found %s EPG method." % method)
|
self.fhdhr.logger.info("Found %s EPG method." % method)
|
||||||
exec("%s = %s" % ("self." + str(method), str(method) + "." + str(method) + "EPG(self.fhdhr, self.channels)"))
|
self.epg_handling[method] = eval("self.alternative_epg.%s.%sEPG(self.fhdhr, self.channels)" % (method, method))
|
||||||
|
|
||||||
def update(self, method=None):
|
def update(self, method=None):
|
||||||
|
|
||||||
if not method:
|
if (not method or
|
||||||
method = self.def_method
|
|
||||||
if (method == self.fhdhr.config.dict["main"]["dictpopname"] or
|
|
||||||
method not in self.fhdhr.config.dict["main"]["valid_epg_methods"]):
|
method not in self.fhdhr.config.dict["main"]["valid_epg_methods"]):
|
||||||
|
method = self.def_method
|
||||||
|
|
||||||
|
if method == self.fhdhr.config.dict["main"]["dictpopname"]:
|
||||||
method = "origin"
|
method = "origin"
|
||||||
|
|
||||||
epgtypename = method
|
epgtypename = method
|
||||||
@ -152,12 +156,10 @@ class EPG():
|
|||||||
epgtypename = self.fhdhr.config.dict["main"]["dictpopname"]
|
epgtypename = self.fhdhr.config.dict["main"]["dictpopname"]
|
||||||
|
|
||||||
self.fhdhr.logger.info("Updating " + epgtypename + " EPG cache.")
|
self.fhdhr.logger.info("Updating " + epgtypename + " EPG cache.")
|
||||||
method_to_call = getattr(self, method)
|
|
||||||
func_to_call = getattr(method_to_call, 'update_epg')
|
|
||||||
if method == 'origin':
|
if method == 'origin':
|
||||||
programguide = func_to_call(self.channels)
|
programguide = self.epg_handling['origin'].update_epg(self.channels)
|
||||||
else:
|
else:
|
||||||
programguide = func_to_call()
|
programguide = self.epg_handling[method].update_epg()
|
||||||
|
|
||||||
for chan in list(programguide.keys()):
|
for chan in list(programguide.keys()):
|
||||||
floatnum = str(float(chan))
|
floatnum = str(float(chan))
|
||||||
74
fHDHR/device/epg/blocks.py
Normal file
74
fHDHR/device/epg/blocks.py
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class blocksEPG():
|
||||||
|
|
||||||
|
def __init__(self, fhdhr, channels):
|
||||||
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
|
self.channels = channels
|
||||||
|
|
||||||
|
def update_epg(self):
|
||||||
|
programguide = {}
|
||||||
|
|
||||||
|
timestamps = self.timestamps
|
||||||
|
|
||||||
|
for fhdhr_id in list(self.channels.list.keys()):
|
||||||
|
chan_obj = self.channels.list[fhdhr_id]
|
||||||
|
|
||||||
|
if str(chan_obj.dict["number"]) not in list(programguide.keys()):
|
||||||
|
programguide[str(chan_obj.dict["number"])] = chan_obj.epgdict
|
||||||
|
|
||||||
|
clean_prog_dicts = self.empty_channel_epg(timestamps, chan_obj)
|
||||||
|
for clean_prog_dict in clean_prog_dicts:
|
||||||
|
programguide[str(chan_obj.dict["number"])]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
|
return programguide
|
||||||
|
|
||||||
|
def get_content_thumbnail(self, content_id):
|
||||||
|
return "/api/images?method=generate&type=content&message=%s" % content_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def timestamps(self):
|
||||||
|
timestamps = []
|
||||||
|
todaydate = datetime.date.today()
|
||||||
|
for x in range(0, 6):
|
||||||
|
xdate = todaydate + datetime.timedelta(days=x)
|
||||||
|
xtdate = xdate + datetime.timedelta(days=1)
|
||||||
|
|
||||||
|
for hour in range(0, 24):
|
||||||
|
time_start = datetime.datetime.combine(xdate, datetime.time(hour, 0))
|
||||||
|
if hour + 1 < 24:
|
||||||
|
time_end = datetime.datetime.combine(xdate, datetime.time(hour + 1, 0))
|
||||||
|
else:
|
||||||
|
time_end = datetime.datetime.combine(xtdate, datetime.time(0, 0))
|
||||||
|
timestampdict = {
|
||||||
|
"time_start": str(time_start.strftime('%Y%m%d%H%M%S')) + " +0000",
|
||||||
|
"time_end": str(time_end.strftime('%Y%m%d%H%M%S')) + " +0000",
|
||||||
|
}
|
||||||
|
timestamps.append(timestampdict)
|
||||||
|
return timestamps
|
||||||
|
|
||||||
|
def empty_channel_epg(self, timestamps, chan_obj):
|
||||||
|
clean_prog_dicts = []
|
||||||
|
for timestamp in timestamps:
|
||||||
|
content_id = "%s_%s" % (chan_obj.dict["origin_id"], str(timestamp['time_start']).split(" ")[0])
|
||||||
|
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)
|
||||||
|
return clean_prog_dicts
|
||||||
@ -1,66 +0,0 @@
|
|||||||
import datetime
|
|
||||||
|
|
||||||
|
|
||||||
class blocksEPG():
|
|
||||||
|
|
||||||
def __init__(self, fhdhr, channels):
|
|
||||||
self.fhdhr = fhdhr
|
|
||||||
|
|
||||||
self.channels = channels
|
|
||||||
|
|
||||||
def update_epg(self):
|
|
||||||
programguide = {}
|
|
||||||
|
|
||||||
timestamps = []
|
|
||||||
todaydate = datetime.date.today()
|
|
||||||
for x in range(0, 6):
|
|
||||||
xdate = todaydate + datetime.timedelta(days=x)
|
|
||||||
xtdate = xdate + datetime.timedelta(days=1)
|
|
||||||
|
|
||||||
for hour in range(0, 24):
|
|
||||||
time_start = datetime.datetime.combine(xdate, datetime.time(hour, 0))
|
|
||||||
if hour + 1 < 24:
|
|
||||||
time_end = datetime.datetime.combine(xdate, datetime.time(hour + 1, 0))
|
|
||||||
else:
|
|
||||||
time_end = datetime.datetime.combine(xtdate, datetime.time(0, 0))
|
|
||||||
timestampdict = {
|
|
||||||
"time_start": str(time_start.strftime('%Y%m%d%H%M%S')) + " +0000",
|
|
||||||
"time_end": str(time_end.strftime('%Y%m%d%H%M%S')) + " +0000",
|
|
||||||
}
|
|
||||||
timestamps.append(timestampdict)
|
|
||||||
|
|
||||||
for fhdhr_id in list(self.channels.list.keys()):
|
|
||||||
c = self.channels.list[fhdhr_id].dict
|
|
||||||
|
|
||||||
if str(c["number"]) not in list(programguide.keys()):
|
|
||||||
programguide[str(c["number"])] = {
|
|
||||||
"callsign": c["callsign"],
|
|
||||||
"name": c["name"],
|
|
||||||
"number": c["number"],
|
|
||||||
"id": c["origin_id"],
|
|
||||||
"thumbnail": ("/api/images?method=generate&type=channel&message=%s" % (str(c['number']))),
|
|
||||||
"listing": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
for timestamp in timestamps:
|
|
||||||
clean_prog_dict = {
|
|
||||||
"time_start": timestamp['time_start'],
|
|
||||||
"time_end": timestamp['time_end'],
|
|
||||||
"duration_minutes": 60,
|
|
||||||
"thumbnail": ("/api/images?method=generate&type=content&message=%s" % (str(c["origin_id"]) + "_" + str(timestamp['time_start']).split(" ")[0])),
|
|
||||||
"title": "Unavailable",
|
|
||||||
"sub-title": "Unavailable",
|
|
||||||
"description": "Unavailable",
|
|
||||||
"rating": "N/A",
|
|
||||||
"episodetitle": None,
|
|
||||||
"releaseyear": None,
|
|
||||||
"genres": [],
|
|
||||||
"seasonnumber": None,
|
|
||||||
"episodenumber": None,
|
|
||||||
"isnew": False,
|
|
||||||
"id": str(c["origin_id"]) + "_" + str(timestamp['time_start']).split(" ")[0],
|
|
||||||
}
|
|
||||||
|
|
||||||
programguide[str(c["number"])]["listing"].append(clean_prog_dict)
|
|
||||||
|
|
||||||
return programguide
|
|
||||||
@ -24,8 +24,8 @@ class Channels():
|
|||||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||||
channel_dict = channel_obj.dict.copy()
|
channel_dict = channel_obj.dict.copy()
|
||||||
channel_dict["play_url"] = channel_obj.play_url()
|
channel_dict["play_url"] = channel_obj.play_url
|
||||||
channel_dict["stream_url"] = channel_obj.stream_url()
|
channel_dict["stream_url"] = channel_obj.stream_url
|
||||||
channels_info.append(channel_dict)
|
channels_info.append(channel_dict)
|
||||||
channels_info_json = json.dumps(channels_info, indent=4)
|
channels_info_json = json.dumps(channels_info, indent=4)
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@ class M3U():
|
|||||||
"group-title=\"" + self.fhdhr.config.dict["fhdhr"]["friendlyname"] + "\"," + str(channel_obj.dict['name']))
|
"group-title=\"" + self.fhdhr.config.dict["fhdhr"]["friendlyname"] + "\"," + str(channel_obj.dict['name']))
|
||||||
)
|
)
|
||||||
|
|
||||||
fakefile.write("%s\n" % (base_url + channel_obj.stream_url()))
|
fakefile.write("%s%s\n" % (base_url, channel_obj.stream_url))
|
||||||
|
|
||||||
channels_m3u = fakefile.getvalue()
|
channels_m3u = fakefile.getvalue()
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class xmlTV():
|
|||||||
if method == "get":
|
if method == "get":
|
||||||
|
|
||||||
epgdict = self.fhdhr.device.epg.get_epg(source)
|
epgdict = self.fhdhr.device.epg.get_epg(source)
|
||||||
xmltv_xml = self.create_xmltv(base_url, epgdict)
|
xmltv_xml = self.create_xmltv(base_url, epgdict, source)
|
||||||
|
|
||||||
return Response(status=200,
|
return Response(status=200,
|
||||||
response=xmltv_xml,
|
response=xmltv_xml,
|
||||||
@ -78,12 +78,23 @@ 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 create_xmltv(self, base_url, epgdict):
|
def create_xmltv(self, base_url, epgdict, source):
|
||||||
if not epgdict:
|
if not epgdict:
|
||||||
return self.xmltv_empty()
|
return self.xmltv_empty()
|
||||||
|
epgdict.copy()
|
||||||
|
|
||||||
out = self.xmltv_headers()
|
out = self.xmltv_headers()
|
||||||
|
|
||||||
|
if source in ["origin", "blocks", self.fhdhr.config.dict["main"]["dictpopname"]]:
|
||||||
|
for c in list(epgdict.keys()):
|
||||||
|
chan_obj = self.fhdhr.channels.get_channel_obj("origin_id", c["id"])
|
||||||
|
epgdict[chan_obj.dict["number"]] = epgdict.pop(c)
|
||||||
|
epgdict[chan_obj.dict["number"]]["name"] = chan_obj.dict["name"]
|
||||||
|
epgdict[chan_obj.dict["number"]]["callsign"] = chan_obj.dict["callsign"]
|
||||||
|
epgdict[chan_obj.dict["number"]]["number"] = chan_obj.dict["number"]
|
||||||
|
epgdict[chan_obj.dict["number"]]["id"] = chan_obj.dict["origin_id"]
|
||||||
|
epgdict[chan_obj.dict["number"]]["thumbnail"] = chan_obj.thumbnail
|
||||||
|
|
||||||
for c in list(epgdict.keys()):
|
for c in list(epgdict.keys()):
|
||||||
|
|
||||||
c_out = sub_el(out, 'channel', id=str(epgdict[c]['number']))
|
c_out = sub_el(out, 'channel', id=str(epgdict[c]['number']))
|
||||||
@ -95,13 +106,10 @@ class xmlTV():
|
|||||||
sub_el(c_out, 'display-name', text=epgdict[c]['callsign'])
|
sub_el(c_out, 'display-name', text=epgdict[c]['callsign'])
|
||||||
sub_el(c_out, 'display-name', text=epgdict[c]['name'])
|
sub_el(c_out, 'display-name', text=epgdict[c]['name'])
|
||||||
|
|
||||||
if epgdict[c]["thumbnail"] is not None:
|
if self.fhdhr.config.dict["epg"]["images"] == "proxy":
|
||||||
if self.fhdhr.config.dict["epg"]["images"] == "proxy":
|
sub_el(c_out, 'icon', src=(str(base_url) + "/api/images?method=get&type=channel&id=" + str(epgdict[c]['id'])))
|
||||||
sub_el(c_out, 'icon', src=(str(base_url) + "/api/images?method=get&type=channel&id=" + str(epgdict[c]['id'])))
|
|
||||||
else:
|
|
||||||
sub_el(c_out, 'icon', src=(epgdict[c]["thumbnail"]))
|
|
||||||
else:
|
else:
|
||||||
sub_el(c_out, 'icon', src=(str(base_url) + "/api/images?method=generate&type=channel&message=" + urllib.parse.quote(epgdict[c]['name'])))
|
sub_el(c_out, 'icon', src=(epgdict[c]["thumbnail"]))
|
||||||
|
|
||||||
for channelnum in list(epgdict.keys()):
|
for channelnum in list(epgdict.keys()):
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class Lineup_JSON():
|
|||||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||||
if channel_obj.enabled or show == "found":
|
if channel_obj.enabled or show == "found":
|
||||||
lineup_dict = channel_obj.lineup_dict()
|
lineup_dict = channel_obj.lineup_dict
|
||||||
lineup_dict["URL"] = "%s%s" % (base_url, lineup_dict["URL"])
|
lineup_dict["URL"] = "%s%s" % (base_url, lineup_dict["URL"])
|
||||||
if show == "found" and channel_obj.enabled:
|
if show == "found" and channel_obj.enabled:
|
||||||
lineup_dict["Enabled"] = 1
|
lineup_dict["Enabled"] = 1
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class Lineup_XML():
|
|||||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||||
if channel_obj.enabled or show == "found":
|
if channel_obj.enabled or show == "found":
|
||||||
program_out = sub_el(out, 'Program')
|
program_out = sub_el(out, 'Program')
|
||||||
lineup_dict = channel_obj.lineup_dict()
|
lineup_dict = channel_obj.lineup_dict
|
||||||
lineup_dict["URL"] = base_url + lineup_dict["URL"]
|
lineup_dict["URL"] = base_url + lineup_dict["URL"]
|
||||||
if show == "found" and channel_obj.enabled:
|
if show == "found" and channel_obj.enabled:
|
||||||
lineup_dict["Enabled"] = 1
|
lineup_dict["Enabled"] = 1
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class Channels_Editor_HTML():
|
|||||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||||
channel_dict = channel_obj.dict.copy()
|
channel_dict = channel_obj.dict.copy()
|
||||||
channel_dict["play_url"] = channel_obj.play_url()
|
channel_dict["play_url"] = channel_obj.play_url
|
||||||
channelslist.append(channel_dict)
|
channelslist.append(channel_dict)
|
||||||
|
|
||||||
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)
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class Channels_HTML():
|
|||||||
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
for fhdhr_id in list(self.fhdhr.device.channels.list.keys()):
|
||||||
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
channel_obj = self.fhdhr.device.channels.list[fhdhr_id]
|
||||||
channel_dict = channel_obj.dict.copy()
|
channel_dict = channel_obj.dict.copy()
|
||||||
channel_dict["play_url"] = channel_obj.play_url()
|
channel_dict["play_url"] = channel_obj.play_url
|
||||||
channelslist.append(channel_dict)
|
channelslist.append(channel_dict)
|
||||||
if channel_dict["enabled"]:
|
if channel_dict["enabled"]:
|
||||||
channels_dict["Enabled"] += 1
|
channels_dict["Enabled"] += 1
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
from .origin_service import OriginService
|
|
||||||
from .origin_channels import OriginChannels
|
|
||||||
from .origin_epg import OriginEPG
|
|
||||||
|
|
||||||
import fHDHR.exceptions
|
import fHDHR.exceptions
|
||||||
|
|
||||||
@ -26,8 +24,9 @@ class OriginChannels_StandIN():
|
|||||||
|
|
||||||
class OriginServiceWrapper():
|
class OriginServiceWrapper():
|
||||||
|
|
||||||
def __init__(self, fhdhr):
|
def __init__(self, fhdhr, origin):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
self.origin = origin
|
||||||
|
|
||||||
self.servicename = fhdhr.config.dict["main"]["servicename"]
|
self.servicename = fhdhr.config.dict["main"]["servicename"]
|
||||||
|
|
||||||
@ -37,7 +36,7 @@ class OriginServiceWrapper():
|
|||||||
def setup(self):
|
def setup(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.origin = OriginService(self.fhdhr)
|
self.originservice = self.origin.OriginService(self.fhdhr)
|
||||||
self.setup_success = True
|
self.setup_success = True
|
||||||
self.fhdhr.logger.info("%s Setup Success" % self.servicename)
|
self.fhdhr.logger.info("%s Setup Success" % self.servicename)
|
||||||
except fHDHR.exceptions.OriginSetupError as e:
|
except fHDHR.exceptions.OriginSetupError as e:
|
||||||
@ -45,8 +44,8 @@ class OriginServiceWrapper():
|
|||||||
self.setup_success = False
|
self.setup_success = False
|
||||||
|
|
||||||
if self.setup_success:
|
if self.setup_success:
|
||||||
self.channels = OriginChannels(self.fhdhr, self.origin)
|
self.channels = self.origin.OriginChannels(self.fhdhr, self.originservice)
|
||||||
self.epg = OriginEPG(self.fhdhr)
|
self.epg = self.origin.OriginEPG(self.fhdhr)
|
||||||
else:
|
else:
|
||||||
self.channels = OriginChannels_StandIN()
|
self.channels = OriginChannels_StandIN()
|
||||||
self.epg = OriginEPG_StandIN()
|
self.epg = OriginEPG_StandIN()
|
||||||
@ -83,8 +82,8 @@ class OriginServiceWrapper():
|
|||||||
''' will only get called for undefined attributes '''
|
''' will only get called for undefined attributes '''
|
||||||
if hasattr(self.fhdhr, name):
|
if hasattr(self.fhdhr, name):
|
||||||
return eval("self.fhdhr." + name)
|
return eval("self.fhdhr." + name)
|
||||||
if hasattr(self.origin, name):
|
if hasattr(self.originservice, name):
|
||||||
return eval("self.origin." + name)
|
return eval("self.originservice." + name)
|
||||||
elif hasattr(self.channels, name):
|
elif hasattr(self.channels, name):
|
||||||
return eval("self.channels." + name)
|
return eval("self.channels." + name)
|
||||||
elif hasattr(self.epg, name):
|
elif hasattr(self.epg, name):
|
||||||
4
main.py
4
main.py
@ -9,9 +9,11 @@ import pathlib
|
|||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|
||||||
from fHDHR.cli import run
|
from fHDHR.cli import run
|
||||||
|
import alternative_epg
|
||||||
|
import origin
|
||||||
|
|
||||||
SCRIPT_DIR = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
SCRIPT_DIR = pathlib.Path(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
freeze_support()
|
freeze_support()
|
||||||
sys.exit(run.main(SCRIPT_DIR))
|
sys.exit(run.main(SCRIPT_DIR, alternative_epg, origin))
|
||||||
|
|||||||
4
origin/__init__.py
Normal file
4
origin/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# pylama:ignore=W0401,W0611
|
||||||
|
from .origin_service import *
|
||||||
|
from .origin_channels import *
|
||||||
|
from .origin_epg import *
|
||||||
@ -9,15 +9,6 @@ class OriginEPG():
|
|||||||
def __init__(self, fhdhr):
|
def __init__(self, fhdhr):
|
||||||
self.fhdhr = fhdhr
|
self.fhdhr = fhdhr
|
||||||
|
|
||||||
def get_channel_thumbnail(self, channel_id):
|
|
||||||
channel_thumb_url = ("%s%s:%s/service?method=channel.icon&channel_id=%s" %
|
|
||||||
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
|
||||||
self.fhdhr.config.dict["origin"]["address"],
|
|
||||||
str(self.fhdhr.config.dict["origin"]["port"]),
|
|
||||||
str(channel_id)
|
|
||||||
))
|
|
||||||
return channel_thumb_url
|
|
||||||
|
|
||||||
def get_content_thumbnail(self, content_id):
|
def get_content_thumbnail(self, content_id):
|
||||||
item_thumb_url = ("%s%s:%s/service?method=channel.show.artwork&sid=%s&event_id=%s" %
|
item_thumb_url = ("%s%s:%s/service?method=channel.show.artwork&sid=%s&event_id=%s" %
|
||||||
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
("https://" if self.fhdhr.config.dict["origin"]["ssl"] else "http://",
|
||||||
@ -39,26 +30,18 @@ class OriginEPG():
|
|||||||
def update_epg(self, fhdhr_channels):
|
def update_epg(self, fhdhr_channels):
|
||||||
programguide = {}
|
programguide = {}
|
||||||
|
|
||||||
for c in fhdhr_channels.get_channels():
|
for fhdhr_id in list(self.channels.list.keys()):
|
||||||
|
chan_obj = self.channels.list[fhdhr_id]
|
||||||
|
|
||||||
cdict = fHDHR.tools.xmldictmaker(c, ["callsign", "name", "number", "id"])
|
if str(chan_obj.dict['number']) not in list(programguide.keys()):
|
||||||
|
|
||||||
if str(cdict['number']) not in list(programguide.keys()):
|
programguide[str(chan_obj.dict["number"])] = chan_obj.epgdict
|
||||||
|
|
||||||
programguide[str(cdict['number'])] = {
|
|
||||||
"callsign": cdict["callsign"],
|
|
||||||
"name": cdict["name"] or cdict["callsign"],
|
|
||||||
"number": cdict["number"],
|
|
||||||
"id": str(cdict["origin_id"]),
|
|
||||||
"thumbnail": self.get_channel_thumbnail(cdict['origin_id']),
|
|
||||||
"listing": [],
|
|
||||||
}
|
|
||||||
|
|
||||||
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://",
|
||||||
self.fhdhr.config.dict["origin"]["address"],
|
self.fhdhr.config.dict["origin"]["address"],
|
||||||
str(self.fhdhr.config.dict["origin"]["port"]),
|
str(self.fhdhr.config.dict["origin"]["port"]),
|
||||||
str(cdict["origin_id"]),
|
str(chan_obj.dict["origin_id"]),
|
||||||
))
|
))
|
||||||
epg_req = self.fhdhr.web.session.get(epg_url)
|
epg_req = self.fhdhr.web.session.get(epg_url)
|
||||||
epg_dict = xmltodict.parse(epg_req.content)
|
epg_dict = xmltodict.parse(epg_req.content)
|
||||||
@ -97,6 +80,7 @@ class OriginEPG():
|
|||||||
|
|
||||||
# TODO isNEW
|
# TODO isNEW
|
||||||
|
|
||||||
programguide[str(cdict["number"])]["listing"].append(clean_prog_dict)
|
if not any(d['id'] == clean_prog_dict['id'] for d in programguide[str(chan_obj.dict["number"])]["listing"]):
|
||||||
|
programguide[str(chan_obj.dict["number"])]["listing"].append(clean_prog_dict)
|
||||||
|
|
||||||
return programguide
|
return programguide
|
||||||
Loading…
Reference in New Issue
Block a user