diff --git a/data/www/style.css b/data/www/style.css new file mode 100644 index 0000000..ae8e1e1 --- /dev/null +++ b/data/www/style.css @@ -0,0 +1,8 @@ +.pull-right { float: right; } + +.pull-lef { float: left; } + +.center { + margin-left: auto; + margin-right: auto; +} diff --git a/fHDHR/__init__.py b/fHDHR/__init__.py index 3f4881b..6835110 100644 --- a/fHDHR/__init__.py +++ b/fHDHR/__init__.py @@ -1,2 +1,2 @@ # coding=utf-8 -fHDHR_VERSION = "v0.2.2-beta" +fHDHR_VERSION = "v0.2.9-beta" diff --git a/fHDHR/api/__init__.py b/fHDHR/api/__init__.py index 6b96c7b..bdec8ec 100644 --- a/fHDHR/api/__init__.py +++ b/fHDHR/api/__init__.py @@ -15,6 +15,19 @@ class HDHR_HTTP_Server(): base_url = request.headers["host"] return fhdhrhub.get_index_html(base_url) + @app.route('/guide') + def channel_guide_html(): + return fhdhrhub.get_channel_guide_html() + + @app.route('/origin') + def origin_html(): + base_url = request.headers["host"] + return fhdhrhub.get_origin_html(base_url) + + @app.route('/style.css', methods=['GET']) + def style_css(): + return send_from_directory(fhdhrhub.config.dict["filedir"]["www_dir"], 'style.css') + @app.route('/favicon.ico', methods=['GET']) def favicon(): return send_from_directory(fhdhrhub.config.dict["filedir"]["www_dir"], @@ -79,6 +92,16 @@ class HDHR_HTTP_Server(): mimetype='application/xml') return "not subscribed" + @app.route('/diagnostics', methods=['GET']) + def debug_html(): + base_url = request.headers["host"] + return fhdhrhub.get_diagnostics_html(base_url) + + @app.route('/version', methods=['GET']) + def version_html(): + base_url = request.headers["host"] + return fhdhrhub.get_version_html(base_url) + @app.route('/debug.json', methods=['GET']) def debug_json(): base_url = request.headers["host"] @@ -96,6 +119,14 @@ class HDHR_HTTP_Server(): response=channels_m3u, mimetype='text/plain') + @app.route('/.m3u', methods=['GET']) + def channel_m3u(channel): + base_url = request.headers["host"] + channel_m3u = fhdhrhub.get_channel_m3u(base_url, channel) + return Response(status=200, + response=channel_m3u, + mimetype='text/plain') + @app.route('/images', methods=['GET']) def images(): image, imagetype = fhdhrhub.get_image(request.args) diff --git a/fHDHR/api/hub/__init__.py b/fHDHR/api/hub/__init__.py index 5f3a2bb..0b25790 100644 --- a/fHDHR/api/hub/__init__.py +++ b/fHDHR/api/hub/__init__.py @@ -11,10 +11,10 @@ class fHDHR_Hub(): self.origin = origin - self.pages = pages.fHDHR_Pages(settings) - self.device = device.fHDHR_Device(settings, origin) + self.pages = pages.fHDHR_Pages(settings, self.device) + self.files = files.fHDHR_Files(settings, self.device) def get_xmltv(self, base_url): @@ -50,6 +50,9 @@ class fHDHR_Hub(): def get_channels_m3u(self, base_url): return self.files.m3u.get_channels_m3u(base_url) + def get_channel_m3u(self, base_url, channel_number): + return self.files.m3u.get_channel_m3u(base_url, channel_number) + def get_stream_info(self, stream_args): return self.device.watch.get_stream_info(stream_args) @@ -58,3 +61,15 @@ class fHDHR_Hub(): def get_index_html(self, base_url): return self.pages.index.get_index_html(base_url) + + def get_channel_guide_html(self): + return self.pages.channel_guide.get_channel_guide_html() + + def get_diagnostics_html(self, base_url): + return self.pages.diagnostics.get_diagnostics_html(base_url) + + def get_version_html(self, base_url): + return self.pages.version.get_version_html(base_url) + + def get_origin_html(self, base_url): + return self.pages.origin.get_origin_html(base_url) diff --git a/fHDHR/api/hub/device/__init__.py b/fHDHR/api/hub/device/__init__.py index 7b337f3..a01c8dd 100644 --- a/fHDHR/api/hub/device/__init__.py +++ b/fHDHR/api/hub/device/__init__.py @@ -14,7 +14,7 @@ class fHDHR_Device(): self.epg = epg.EPG(settings, self.channels) - self.tuners = Tuners(settings) + self.tuners = Tuners(settings, self.epg) self.watch = WatchStream(settings, self.channels, self.tuners) diff --git a/fHDHR/api/hub/device/channels.py b/fHDHR/api/hub/device/channels.py index e710e66..e8becc7 100644 --- a/fHDHR/api/hub/device/channels.py +++ b/fHDHR/api/hub/device/channels.py @@ -56,6 +56,12 @@ class Channels(): self.list_update_time = None self.get_channels() + def get_origin_status(self): + try: + return self.origin.get_status_dict() + except AttributeError: + return {} + def get_channels(self, forceupdate=False): """Pull Channels from origin. diff --git a/fHDHR/api/hub/device/epg.py b/fHDHR/api/hub/device/epg.py index 69921a7..b2c1d77 100644 --- a/fHDHR/api/hub/device/epg.py +++ b/fHDHR/api/hub/device/epg.py @@ -1,6 +1,7 @@ import os import json import time +import datetime from collections import OrderedDict from multiprocessing import Process @@ -16,6 +17,8 @@ class EPG(): self.origin = origin_epg.originEPG(settings, channels) + self.epgdict = None + self.epg_method_selfadd() self.epg_method = self.config.dict["fhdhr"]["epg_method"] @@ -31,12 +34,31 @@ class EPG(): self.epgscan = Process(target=self.epgServerProcess) self.epgscan.start() + def whats_on_now(self, channel): + epgdict = self.get_epg() + listings = epgdict[channel]["listing"] + for listing in listings: + nowtime = datetime.datetime.utcnow() + start_time = datetime.datetime.strptime(listing["time_start"], '%Y%m%d%H%M%S +0000') + end_time = datetime.datetime.strptime(listing["time_end"], '%Y%m%d%H%M%S +0000') + if start_time <= nowtime <= end_time: + epgitem = epgdict[channel].copy() + epgitem["listing"] = [listing] + return epgitem + return None + + def whats_on_allchans(self): + channel_guide_list = [] + for channel in self.channels.get_channels(): + channel_guide_list.append(self.whats_on_now(channel["number"])) + return channel_guide_list + def get_epg(self): - epgdict = None - if os.path.isfile(self.epg_cache_file): - with open(self.epg_cache_file, 'r') as epgfile: - epgdict = json.load(epgfile) - return epgdict + if not self.epgdict: + if os.path.isfile(self.epg_cache_file): + with open(self.epg_cache_file, 'r') as epgfile: + self.epgdict = json.load(epgfile) + return self.epgdict def get_thumbnail(self, itemtype, itemid): if itemtype == "channel": @@ -86,6 +108,7 @@ class EPG(): with open(self.epg_cache_file, 'w') as epgfile: epgfile.write(json.dumps(programguide, indent=4)) print("Wrote " + self.epgtypename + " EPG cache file.") + self.epgdict = programguide def epgServerProcess(self): print("Starting EPG thread...") diff --git a/fHDHR/api/hub/device/tuners.py b/fHDHR/api/hub/device/tuners.py index 503ce11..c801ecf 100644 --- a/fHDHR/api/hub/device/tuners.py +++ b/fHDHR/api/hub/device/tuners.py @@ -1,11 +1,14 @@ import threading +import datetime from fHDHR.exceptions import TunerError +from fHDHR.tools import humanized_time class Tuner(): - def __init__(self, inum): + def __init__(self, inum, epg): self.number = inum + self.epg = epg self.tuner_lock = threading.Lock() self.set_off_status() @@ -20,6 +23,7 @@ class Tuner(): "method": stream_args["method"], "accessed": stream_args["accessed"], "proxied_url": stream_args["channelUri"], + "time_start": datetime.datetime.utcnow(), } def close(self): @@ -28,25 +32,28 @@ class Tuner(): self.tuner_lock.release() def get_status(self): - return self.status + current_status = self.status.copy() + if current_status["status"] == "Active": + current_status["Play Time"] = str( + humanized_time( + int((datetime.datetime.utcnow() - current_status["time_start"]).total_seconds()))) + current_status["time_start"] = str(current_status["time_start"]) + current_status["epg"] = self.epg.whats_on_now(current_status["accessed"].split("v")[-1]) + return current_status def set_off_status(self): - self.status = { - "status": "Inactive", - "method": None, - "accessed": None, - "proxied_url": None, - } + self.status = {"status": "Inactive"} class Tuners(): - def __init__(self, settings): + def __init__(self, settings, epg): self.config = settings + self.epg = epg self.max_tuners = int(self.config.dict["fhdhr"]["tuner_count"]) for i in range(1, self.max_tuners + 1): - exec("%s = %s" % ("self.tuner_" + str(i), "Tuner(i)")) + exec("%s = %s" % ("self.tuner_" + str(i), "Tuner(i, epg)")) def tuner_grab(self, stream_args, tunernum=None): tunerselected = None @@ -81,3 +88,19 @@ class Tuners(): for tunernum in range(1, self.max_tuners + 1): all_status[tunernum] = eval("self.tuner_" + str(tunernum) + ".get_status()") return all_status + + def available_tuner_count(self): + available_tuners = 0 + for tunernum in range(1, self.max_tuners + 1): + tuner_status = eval("self.tuner_" + str(tunernum) + ".get_status()") + if tuner_status["status"] == "Inactive": + available_tuners += 1 + return available_tuners + + def inuse_tuner_count(self): + inuse_tuners = 0 + for tunernum in range(1, self.max_tuners + 1): + tuner_status = eval("self.tuner_" + str(tunernum) + ".get_status()") + if tuner_status["status"] == "Active": + inuse_tuners += 1 + return inuse_tuners diff --git a/fHDHR/api/hub/files/__init__.py b/fHDHR/api/hub/files/__init__.py index e01550c..1c47fe1 100644 --- a/fHDHR/api/hub/files/__init__.py +++ b/fHDHR/api/hub/files/__init__.py @@ -6,7 +6,7 @@ from .lineup_json import Lineup_JSON from .debug_json import Debug_JSON from .lineup_status_json import Lineup_Status_JSON from .xmltv_xml import xmlTV_XML -from .channels_m3u import channels_M3U +from .m3u import channels_M3U class fHDHR_Files(): diff --git a/fHDHR/api/hub/files/channels_m3u.py b/fHDHR/api/hub/files/m3u.py similarity index 52% rename from fHDHR/api/hub/files/channels_m3u.py rename to fHDHR/api/hub/files/m3u.py index 302c6ef..e2f97eb 100644 --- a/fHDHR/api/hub/files/channels_m3u.py +++ b/fHDHR/api/hub/files/m3u.py @@ -53,3 +53,50 @@ class channels_M3U(): ) return fakefile.getvalue() + + def get_channel_m3u(self, base_url, channel_number): + + FORMAT_DESCRIPTOR = "#EXTM3U" + RECORD_MARKER = "#EXTINF" + + fakefile = StringIO() + + xmltvurl = ('%s%s/xmltv.xml' % + ("http://", + base_url)) + + fakefile.write( + "%s\n" % ( + FORMAT_DESCRIPTOR + " " + + "url-tvg=\"" + xmltvurl + "\"" + " " + + "x-tvg-url=\"" + xmltvurl + "\"") + ) + + channel = self.device.channels.get_channel_dict("number", channel_number) + + logourl = ('%s%s/images?source=epg&type=channel&id=%s' % + ("http://", + base_url, + str(channel['id']))) + + fakefile.write( + "%s\n" % ( + RECORD_MARKER + ":0" + " " + + "channelID=\"" + str(channel['id']) + "\" " + + "tvg-chno=\"" + str(channel['number']) + "\" " + + "tvg-name=\"" + str(channel['name']) + "\" " + + "tvg-id=\"" + str(channel['number']) + "\" " + + "tvg-logo=\"" + logourl + "\" " + + "group-title=\"" + self.config.dict["fhdhr"]["friendlyname"] + "," + str(channel['name'])) + ) + + fakefile.write( + "%s\n" % ( + ('%s%s/auto/v%s' % + ("http://", + base_url, + str(channel['number']))) + ) + ) + + return fakefile.getvalue() diff --git a/fHDHR/api/hub/pages/__init__.py b/fHDHR/api/hub/pages/__init__.py index 4a2eda1..a9c5e94 100644 --- a/fHDHR/api/hub/pages/__init__.py +++ b/fHDHR/api/hub/pages/__init__.py @@ -1,11 +1,78 @@ # pylama:ignore=W0611 -from .index_html import Index_HTML +from io import StringIO + from .htmlerror import HTMLerror +from .index_html import Index_HTML +from .origin_html import Origin_HTML +from .diagnostics_html import Diagnostics_HTML +from .version_html import Version_HTML +from .channel_guide_html import Channel_Guide_HTML class fHDHR_Pages(): - def __init__(self, settings): + def __init__(self, settings, device): self.config = settings - self.index = Index_HTML(settings) + self.device = device + + self.page_elements = { + "top": self.pagetop(), + "end": self.pageend() + } + self.htmlerror = HTMLerror(settings) + + self.index = Index_HTML(settings, self.device, self.page_elements) + self.origin = Origin_HTML(settings, self.device, self.page_elements) + self.diagnostics = Diagnostics_HTML(settings, self.device, self.page_elements) + self.version = Version_HTML(settings, self.device, self.page_elements) + self.channel_guide = Channel_Guide_HTML(settings, self.device, self.page_elements) + + def pagetop(self): + friendlyname = self.config.dict["fhdhr"]["friendlyname"] + servicename = str(self.config.dict["main"]["servicename"]) + + return [ + "", + "", + + "", + "%s" % friendlyname, + "", + "", + "", + "", + "

%s


" % friendlyname, + "", + "

" + "
", + + "" % ("/", "fHDHR"), + "" % ("/origin", servicename), + "" % ("/guide", "Guide"), + "" % ("/version", "Version"), + "" % ("/diagnostics", "Diagnostics"), + + "%s" % ("xmltv.xml", "xmltv"), + "%s" % ("channels.m3u", "m3u"), + + "

", + "
" + "
" + ] + + def pageend(self): + return [ + "", + "", + + "" + ] diff --git a/fHDHR/api/hub/pages/channel_guide_html.py b/fHDHR/api/hub/pages/channel_guide_html.py new file mode 100644 index 0000000..6f3d440 --- /dev/null +++ b/fHDHR/api/hub/pages/channel_guide_html.py @@ -0,0 +1,61 @@ +from io import StringIO +import datetime + +from fHDHR.tools import humanized_time + + +class Channel_Guide_HTML(): + + def __init__(self, settings, device, page_elements): + self.config = settings + self.device = device + self.page_elements = page_elements + + def get_channel_guide_html(self, force_update=False): + + friendlyname = self.config.dict["fhdhr"]["friendlyname"] + + nowtime = datetime.datetime.utcnow() + + fakefile = StringIO() + + for line in self.page_elements["top"]: + fakefile.write(line + "\n") + + fakefile.write("

What's On %s

\n" % friendlyname) + fakefile.write("\n") + + fakefile.write("\n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + + for channel in self.device.epg.whats_on_allchans(): + end_time = datetime.datetime.strptime(channel["listing"][0]["time_end"], '%Y%m%d%H%M%S +0000') + remaining_time = humanized_time(int((end_time - nowtime).total_seconds())) + play_url = ("/%s.m3u\n" % (channel["number"])) + + fakefile.write(" \n") + fakefile.write(" \n" % (channel["name"])) + fakefile.write(" \n" % (channel["number"])) + fakefile.write(" \n" % (channel["listing"][0]["title"])) + fakefile.write(" \n" % (channel["listing"][0]["description"])) + fakefile.write(" \n" % (str(remaining_time))) + fakefile.write(" \n") + + for line in self.page_elements["end"]: + fakefile.write(line + "\n") + + channel_guide_html = fakefile.getvalue() + + return channel_guide_html diff --git a/fHDHR/api/hub/pages/diagnostics_html.py b/fHDHR/api/hub/pages/diagnostics_html.py new file mode 100644 index 0000000..320af20 --- /dev/null +++ b/fHDHR/api/hub/pages/diagnostics_html.py @@ -0,0 +1,43 @@ +from io import StringIO + + +class Diagnostics_HTML(): + + def __init__(self, settings, device, page_elements): + self.config = settings + self.device = device + self.diagnostics_html = None + self.page_elements = page_elements + + def get_diagnostics_html(self, base_url, force_update=False): + if not self.diagnostics_html or force_update: + + fakefile = StringIO() + + for line in self.page_elements["top"]: + fakefile.write(line + "\n") + + # a list of 2 part lists containing button information + button_list = [ + ["Force Channel Update", "chanscan"], + ["debug", "debug.json"], + ["device.xml", "device.xml"], + ["discover.json", "discover.json"], + ["lineup.json", "lineup.json"], + ["lineup_status.json", "lineup_status.json"] + ] + + for button_item in button_list: + button_label = button_item[0] + button_path = button_item[1] + fakefile.write("
\n") + fakefile.write("

\n" % (button_path, button_label)) + fakefile.write("
\n") + fakefile.write("\n") + + for line in self.page_elements["end"]: + fakefile.write(line + "\n") + + self.diagnostics_html = fakefile.getvalue() + + return self.diagnostics_html diff --git a/fHDHR/api/hub/pages/index_html.py b/fHDHR/api/hub/pages/index_html.py index f447047..95e0672 100644 --- a/fHDHR/api/hub/pages/index_html.py +++ b/fHDHR/api/hub/pages/index_html.py @@ -3,74 +3,47 @@ from io import StringIO class Index_HTML(): - def __init__(self, settings): + def __init__(self, settings, device, page_elements): self.config = settings - self.index_html = None + self.device = device + self.page_elements = page_elements def get_index_html(self, base_url, force_update=False): - if not self.index_html or force_update: - friendlyname = self.config.dict["fhdhr"]["friendlyname"] + fakefile = StringIO() - fakefile = StringIO() + for line in self.page_elements["top"]: + fakefile.write(line + "\n") - fakefile.write("\n") - fakefile.write("\n") + fakefile.write("

fHDHR Status

") + fakefile.write("\n") - fakefile.write("\n") - fakefile.write("%s\n" % friendlyname) - fakefile.write("\n") - fakefile.write("\n") + fakefile.write("
PlayChannel NameChannel NumberChannel ThumbnailContent TitleContent ThumbnailContent DescriptionContent Remaining Time
%s\n" % (play_url, "Play")) + fakefile.write(" %s%s\"%s\"\n" % (channel["thumbnail"], channel["name"])) + fakefile.write(" %s\"%s\"\n" % (channel["listing"][0]["thumbnail"], channel["listing"][0]["title"])) + fakefile.write(" %s%s
\n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") - fakefile.write("

%s

\n" % friendlyname) - fakefile.write("\n") + total_channels = self.device.channels.get_station_total() - fakefile.write("

Primary fHDHR Links

") - fakefile.write("\n") + tuners_in_use = self.device.tuners.inuse_tuner_count() + max_tuners = self.device.tuners.max_tuners - # a list of 2 part lists containing button information - button_list = [ - ["xmltv", "xmltv.xml"], - ["m3u", "channels.m3u"], - ["debug", "debug.json"], - ["Force Channel Update", "chanscan"] - ] + tableguts = [ + ["Script Directory", str(self.config.dict["filedir"]["script_dir"])], + ["Config File", str(self.config.config_file)], + ["Cache Path", str(self.config.dict["filedir"]["cache_dir"])], + ["Total Channels", str(total_channels)], + ["Tuner Usage", "%s/%s" % (str(tuners_in_use), str(max_tuners))] + ] - for button_item in button_list: - button_label = button_item[0] - button_path = button_item[1] - fakefile.write("
\n") - fakefile.write("

\n" % (button_path, button_label)) - fakefile.write("
\n") - fakefile.write("\n") + for guts in tableguts: + fakefile.write(" \n") + fakefile.write(" \n" % (guts[0])) + fakefile.write(" \n" % (guts[1])) + fakefile.write(" \n") - fakefile.write("

Other fHDHR Links

") + for line in self.page_elements["end"]: + fakefile.write(line + "\n") - # a list of 2 part lists containing button information - button_list = [ - ["device.xml", "device.xml"], - ["discover.json", "discover.json"], - ["lineup.json", "lineup.json"], - ["lineup_status.json", "lineup_status.json"] - ] - - for button_item in button_list: - button_label = button_item[0] - button_path = button_item[1] - fakefile.write("
\n") - fakefile.write("

\n" % (button_path, button_label)) - fakefile.write("
\n") - fakefile.write("\n") - - fakefile.write("\n") - fakefile.write("\n") - - fakefile.write("") - - self.index_html = fakefile.getvalue() - - return self.index_html + return fakefile.getvalue() diff --git a/fHDHR/api/hub/pages/origin_html.py b/fHDHR/api/hub/pages/origin_html.py new file mode 100644 index 0000000..d6e8021 --- /dev/null +++ b/fHDHR/api/hub/pages/origin_html.py @@ -0,0 +1,39 @@ +from io import StringIO + + +class Origin_HTML(): + + def __init__(self, settings, device, page_elements): + self.config = settings + self.device = device + self.page_elements = page_elements + + def get_origin_html(self, base_url, force_update=False): + + servicename = str(self.config.dict["main"]["servicename"]) + + fakefile = StringIO() + + for line in self.page_elements["top"]: + fakefile.write(line + "\n") + + fakefile.write("

%s Status

" % (servicename)) + fakefile.write("\n") + + fakefile.write("
%s%s
\n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + + origin_status_dict = self.device.channels.get_origin_status() + for key in list(origin_status_dict.keys()): + fakefile.write(" \n") + fakefile.write(" \n" % (str(key))) + fakefile.write(" \n" % (str(origin_status_dict[key]))) + fakefile.write(" \n") + + for line in self.page_elements["end"]: + fakefile.write(line + "\n") + + return fakefile.getvalue() diff --git a/fHDHR/api/hub/pages/version_html.py b/fHDHR/api/hub/pages/version_html.py new file mode 100644 index 0000000..1297ee6 --- /dev/null +++ b/fHDHR/api/hub/pages/version_html.py @@ -0,0 +1,34 @@ +from io import StringIO + +from fHDHR import fHDHR_VERSION + + +class Version_HTML(): + + def __init__(self, settings, device, page_elements): + self.config = settings + self.device = device + self.page_elements = page_elements + + def get_version_html(self, base_url, force_update=False): + + fakefile = StringIO() + + for line in self.page_elements["top"]: + fakefile.write(line + "\n") + + fakefile.write("
%s%s
\n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + fakefile.write(" \n") + + fakefile.write(" \n") + fakefile.write(" \n" % ("fHDHR")) + fakefile.write(" \n" % (str(fHDHR_VERSION))) + fakefile.write(" \n") + + for line in self.page_elements["end"]: + fakefile.write(line + "\n") + + return fakefile.getvalue() diff --git a/fHDHR/config/__init__.py b/fHDHR/config/__init__.py index 0f1acb6..bfc25b9 100644 --- a/fHDHR/config/__init__.py +++ b/fHDHR/config/__init__.py @@ -30,6 +30,7 @@ class Config(): data_dir = pathlib.Path(script_dir).joinpath('data') www_dir = pathlib.Path(data_dir).joinpath('www') + www_images_dir = pathlib.Path(www_dir).joinpath('images') self.dict["filedir"] = { "script_dir": script_dir, @@ -38,6 +39,7 @@ class Config(): "cache_dir": pathlib.Path(data_dir).joinpath('cache'), "internal_config": pathlib.Path(data_dir).joinpath('internal_config'), "www_dir": www_dir, + "www_images_dir": www_images_dir, "font": pathlib.Path(data_dir).joinpath('garamond.ttf'), "favicon": pathlib.Path(data_dir).joinpath('favicon.ico'), "epg_cache": {}, diff --git a/fHDHR/origin/origin_channels.py b/fHDHR/origin/origin_channels.py index df83f02..a1bb561 100644 --- a/fHDHR/origin/origin_channels.py +++ b/fHDHR/origin/origin_channels.py @@ -59,6 +59,18 @@ class OriginService(): return loginsuccess + def get_status_dict(self): + nextpvr_address = ('%s%s:%s' % + ("https://" if self.config.dict["origin"]["ssl"] else "http://", + self.config.dict["origin"]["address"], + str(self.config.dict["origin"]["port"]), + )) + ret_status_dict = { + "Login": "Success", + "Address": nextpvr_address, + } + return ret_status_dict + def get_channels(self): data_url = ('%s%s:%s/service?method=channel.list&sid=%s' % diff --git a/fHDHR/tools/__init__.py b/fHDHR/tools/__init__.py index a7b27ca..e7ff989 100644 --- a/fHDHR/tools/__init__.py +++ b/fHDHR/tools/__init__.py @@ -76,6 +76,39 @@ def hours_between_datetime(first_time, later_time): return (timebetween.total_seconds() / 60 / 60) +def humanized_time(countdownseconds): + time = float(countdownseconds) + if time == 0: + return "just now" + year = time // (365 * 24 * 3600) + time = time % (365 * 24 * 3600) + day = time // (24 * 3600) + time = time % (24 * 3600) + time = time % (24 * 3600) + hour = time // 3600 + time %= 3600 + minute = time // 60 + time %= 60 + second = time + displaymsg = None + timearray = ['year', 'day', 'hour', 'minute', 'second'] + for x in timearray: + currenttimevar = eval(x) + if currenttimevar >= 1: + timetype = x + if currenttimevar > 1: + timetype = str(x+"s") + if displaymsg: + displaymsg = str(displaymsg + " " + str(int(currenttimevar)) + " " + timetype) + else: + displaymsg = str(str(int(currenttimevar)) + " " + timetype) + if not displaymsg: + return "just now" + return displaymsg + # just for ignoring a pep error + year, day, hour, minute, second + + class WebReq(): def __init__(self): self.session = requests.Session()
%s%s