1
0
mirror of https://github.com/fHDHR/fHDHR_NextPVR.git synced 2025-12-06 08:46:58 -05:00

Add Settings Page, and overhaul Config system

This commit is contained in:
deathbybandaid 2020-11-19 14:09:22 -05:00
parent e98c53526d
commit 38e98d7000
24 changed files with 595 additions and 182 deletions

View File

@ -24,7 +24,7 @@
# update_frequency = 43200 # update_frequency = 43200
[ffmpeg] [ffmpeg]
# ffmpeg_path = ffmpeg # path = ffmpeg
# bytes_per_read = 1152000 # bytes_per_read = 1152000
[direct_stream] [direct_stream]

View File

@ -1,36 +0,0 @@
[main]
uuid =
cache_dir =
thread_method = multiprocessing
[fhdhr]
address = 0.0.0.0
discovery_address = 0.0.0.0
port = 5004
reporting_manufacturer = BoronDust
reporting_model = fHDHR
reporting_firmware_ver = 20201001
reporting_tuner_type = Antenna
device_auth = fHDHR
require_auth = False
[epg]
images = pass
[ffmpeg]
ffmpeg_path = ffmpeg
bytes_per_read = 1152000
[vlc]
vlc_path = cvlc
bytes_per_read = 1152000
[direct_stream]
chunksize = 1048576
[logging]
level = WARNING
[database]
type = sqlite
driver = None

View File

@ -0,0 +1,148 @@
{
"main":{
"uuid":{
"value": "none",
"config_file": true,
"config_web": false
},
"cache_dir":{
"value": "none",
"config_file": true,
"config_web": true
},
"thread_method":{
"value": "multiprocessing",
"config_file": true,
"config_web": true
}
},
"fhdhr":{
"address":{
"value": "0.0.0.0",
"config_file": true,
"config_web": true
},
"discovery_address":{
"value": "none",
"config_file": true,
"config_web": true
},
"port":{
"value": 5004,
"config_file": true,
"config_web": true
},
"reporting_manufacturer":{
"value": "BoronDust",
"config_file": true,
"config_web": true
},
"reporting_model":{
"value": "fHDHR",
"config_file": true,
"config_web": true
},
"reporting_firmware_ver":{
"value": "20201001",
"config_file": true,
"config_web": true
},
"reporting_tuner_type":{
"value": "Antenna",
"config_file": true,
"config_web": true
},
"device_auth":{
"value": "fHDHR",
"config_file": true,
"config_web": true
},
"require_auth":{
"value": false,
"config_file": true,
"config_web": true
}
},
"epg":{
"images":{
"value": "pass",
"config_file": true,
"config_web": true
}
},
"ffmpeg":{
"path":{
"value": "ffmpeg",
"config_file": true,
"config_web": true
},
"bytes_per_read":{
"value": 1152000,
"config_file": true,
"config_web": true
}
},
"vlc":{
"path":{
"value": "cvlc",
"config_file": true,
"config_web": true
},
"bytes_per_read":{
"value": 1152000,
"config_file": true,
"config_web": true
}
},
"direct_stream":{
"chunksize":{
"value": 1048576,
"config_file": true,
"config_web": true
}
},
"logging":{
"level":{
"value": "WARNING",
"config_file": true,
"config_web": true
}
},
"database":{
"type":{
"value": "sqlite",
"config_file": true,
"config_web": false
},
"driver":{
"value": "none",
"config_file": true,
"config_web": false
},
"user":{
"value": "none",
"config_file": true,
"config_web": false
},
"pass":{
"value": "none",
"config_file": true,
"config_web": false
},
"host":{
"value": "none",
"config_file": true,
"config_web": false
},
"port":{
"value": "none",
"config_file": true,
"config_web": false
},
"name":{
"value": "none",
"config_file": true,
"config_web": false
}
}
}

View File

@ -1,25 +0,0 @@
[main]
servicename = NextPVR
dictpopname = nextpvr
reponame = fHDHR_NextPVR
required = nextpvr/pin
valid_epg_methods = None,blocks,origin,zap2it
[fhdhr]
friendlyname = fHDHR-NextPVR
stream_type = direct
tuner_count = 4
reporting_firmware_name = fHDHR_NextPVR
[epg]
method = origin
update_frequency = 43200
[nextpvr]
address = localhost
port = 8866
ssl = False
pin =
weight = 300
epg_update_frequency = 43200
sid =

View File

@ -0,0 +1,91 @@
{
"main":{
"servicename":{
"value": "NextPVR",
"config_file": false,
"config_web": false
},
"dictpopname":{
"value": "nextpvr",
"config_file": false,
"config_web": false
},
"reponame":{
"value": "fHDHR_NextPVR",
"config_file": false,
"config_web": false
},
"valid_epg_methods":{
"value": "None,blocks,origin,zap2it",
"config_file": false,
"config_web": false
},
"required":{
"value": "nextpvr/pin",
"config_file": false,
"config_web": false
}
},
"fhdhr":{
"friendlyname":{
"value": "fHDHR-NextPVR",
"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_NextPVR",
"config_file": true,
"config_web": true
}
},
"epg":{
"method":{
"value": "origin",
"config_file": true,
"config_web": true
},
"update_frequency":{
"value": 43200,
"config_file": true,
"config_web": true
}
},
"nextpvr":{
"address":{
"value": "localhost",
"config_file": true,
"config_web": true
},
"port":{
"value": 8866,
"config_file": true,
"config_web": true
},
"ssl":{
"value": false,
"config_file": true,
"config_web": true
},
"pin":{
"value": "none",
"config_file": true,
"config_web": true,
"config_web_hidden": true
},
"sid":{
"value": "none",
"config_file": true,
"config_web": false
}
}
}

View File

@ -1,13 +0,0 @@
[zap2it]
delay = 5
postalcode =
affiliate_id = gapzap
country = USA
device = -
headendid = lineupId
isoverride = True
languagecode = en
pref =
timespan = 6
timezone =
userid = -

View File

@ -0,0 +1,64 @@
{
"zap2it":{
"delay":{
"value": 5,
"config_file": true,
"config_web": false
},
"postalcode":{
"value": "none",
"config_file": true,
"config_web": false
},
"affiliate_id":{
"value": "gapzap",
"config_file": true,
"config_web": false
},
"country":{
"value": "USA",
"config_file": true,
"config_web": false
},
"device":{
"value": "-",
"config_file": true,
"config_web": false
},
"headendid":{
"value": "lineupId",
"config_file": true,
"config_web": false
},
"isoverride":{
"value": true,
"config_file": true,
"config_web": false
},
"languagecode":{
"value": "en",
"config_file": true,
"config_web": false
},
"pref":{
"value": "none",
"config_file": true,
"config_web": false
},
"timespan":{
"value": 6,
"config_file": true,
"config_web": false
},
"timezone":{
"value": "none",
"config_file": true,
"config_web": false
},
"userid":{
"value": "-",
"config_file": true,
"config_web": false
}
}
}

View File

@ -24,6 +24,7 @@
<button class="pull-left" onclick="OpenLink('/xmltv')">xmltv</a></button> <button class="pull-left" onclick="OpenLink('/xmltv')">xmltv</a></button>
<button class="pull-left" onclick="OpenLink('/version')">Version</a></button> <button class="pull-left" onclick="OpenLink('/version')">Version</a></button>
<button class="pull-left" onclick="OpenLink('/diagnostics')">Diagnostics</a></button> <button class="pull-left" onclick="OpenLink('/diagnostics')">Diagnostics</a></button>
<button class="pull-left" onclick="OpenLink('/settings')">Settings</a></button>
<a class="pull-right" style="padding: 5px;" href="/api/xmltv?method=get&source={{ fhdhr.device.epg.def_method }}">xmltv</a> <a class="pull-right" style="padding: 5px;" href="/api/xmltv?method=get&source={{ fhdhr.device.epg.def_method }}">xmltv</a>
<a class="pull-right" style="padding: 5px;" href="/api/m3u?method=get&channel=all">m3u</a> <a class="pull-right" style="padding: 5px;" href="/api/m3u?method=get&channel=all">m3u</a>

View File

@ -0,0 +1,60 @@
{% extends "base.html" %}
{% block content %}
<h4 style="text-align: center;">fHDHR Settings</h4>
<h4 style="text-align: center;">Settings will require a manual restart.</h4>
{% for config_section in list(web_settings_dict.keys()) %}
{% if config_section == "origin" %}
<h4 style="text-align: center;">{{ fhdhr.config.dict["main"]["dictpopname"] }}</h4>
{% else %}
<h4 style="text-align: center;">{{ config_section }}</h4>
{% endif %}
<table class="center" style="width:100%">
<tr>
<th>Config Name</th>
<th>Config Default Value</th>
<th>Config Value</th>
<th>Update</th>
<th>Reset</th>
</tr>
{% for config_item in list(web_settings_dict[config_section].keys()) %}
<tr>
<td data-th="Config Name">{{ config_item }}</td>
<td data-th="Config Default Value">{{ web_settings_dict[config_section][config_item]["value_default"] }}</td>
<form method="post" action="/api/settings?method=update&redirect=%2Fsettings">
<input type="hidden" name="config_section" value={{ config_section }}>
<input type="hidden" name="config_name" value={{ config_item }}>
<input type="hidden" name="config_default" value={{ web_settings_dict[config_section][config_item]["value_default"] }}>
{% if web_settings_dict[config_section][config_item]["hide"] %}
<td data-th="Config Value"><input type="text" size="50" name="config_value" value=**************></td>
{% else %}
<td data-th="Config Value"><input type="text" size="50" name="config_value" value={{ web_settings_dict[config_section][config_item]["value"] }}></td>
{% endif %}
<td data-th="Update"><input type="submit" value="Update"></td>
</form>
<form method="post" action="/api/settings?method=update&redirect=%2Fsettings">
<input type="hidden" name="config_section" value={{ config_section }}>
<input type="hidden" name="config_name" value={{ config_item }}>
<input type="hidden" name="config_value" value={{ web_settings_dict[config_section][config_item]["value_default"] }}>
<input type="hidden" name="config_default" value={{ web_settings_dict[config_section][config_item]["value_default"] }}>
<td data-th="Reset"><input type="submit" value="Reset"></td>
</form>
</tr>
{% endfor %}
</table>
{% endfor %}
{% endblock %}

View File

@ -5,6 +5,7 @@ import pathlib
import logging import logging
import subprocess import subprocess
import platform import platform
import json
import fHDHR.exceptions import fHDHR.exceptions
from fHDHR.tools import isint, isfloat, is_arithmetic, is_docker from fHDHR.tools import isint, isfloat, is_arithmetic, is_docker
@ -13,42 +14,148 @@ from fHDHR.tools import isint, isfloat, is_arithmetic, is_docker
class Config(): class Config():
def __init__(self, filename, script_dir): def __init__(self, filename, script_dir):
self.internal = {}
self.conf_default = {}
self.dict = {} self.dict = {}
self.config_file = filename self.config_file = filename
self.parser = configparser.RawConfigParser(allow_no_value=True)
self.load_defaults(script_dir)
print("Loading Configuration File: " + str(self.config_file))
self.read_config(self.config_file)
self.initial_load(script_dir)
self.config_verification() self.config_verification()
def load_defaults(self, script_dir): def initial_load(self, script_dir):
data_dir = pathlib.Path(script_dir).joinpath('data') data_dir = pathlib.Path(script_dir).joinpath('data')
www_dir = pathlib.Path(data_dir).joinpath('www') www_dir = pathlib.Path(data_dir).joinpath('www')
self.dict["filedir"] = { self.internal["paths"] = {
"script_dir": script_dir, "script_dir": script_dir,
"data_dir": data_dir, "data_dir": data_dir,
"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,
"www_images_dir": pathlib.Path(www_dir).joinpath('images'),
"www_templates_dir": pathlib.Path(www_dir).joinpath('templates'), "www_templates_dir": pathlib.Path(www_dir).joinpath('templates'),
"font": pathlib.Path(data_dir).joinpath('garamond.ttf'), "font": pathlib.Path(data_dir).joinpath('garamond.ttf'),
"favicon": pathlib.Path(data_dir).joinpath('favicon.ico'),
"epg_cache": {},
} }
for conffile in os.listdir(self.dict["filedir"]["internal_config"]): for conffile in os.listdir(self.internal["paths"]["internal_config"]):
conffilepath = os.path.join(self.dict["filedir"]["internal_config"], conffile) conffilepath = os.path.join(self.internal["paths"]["internal_config"], conffile)
if str(conffilepath).endswith(".ini"): if str(conffilepath).endswith(".json"):
self.read_config(conffilepath) self.read_json_config(conffilepath)
def read_config(self, conffilepath): print("Loading Configuration File: " + str(self.config_file))
self.read_ini_config(self.config_file)
self.load_versions()
def load_versions(self):
self.internal["versions"] = {
"opersystem": None,
"isdocker": False,
"ffmpeg": "N/A",
"vlc": "N/A"
}
opersystem = platform.system()
self.internal["versions"]["opersystem"] = opersystem
if opersystem in ["Linux", "Darwin"]:
# Linux/Mac
if os.getuid() == 0 or os.geteuid() == 0:
print('Warning: Do not run fHDHR with root privileges.')
elif opersystem in ["Windows"]:
# Windows
if os.environ.get("USERNAME") == "Administrator":
print('Warning: Do not run fHDHR as Administrator.')
else:
print("Uncommon Operating System, use at your own risk.")
isdocker = is_docker()
self.internal["versions"]["isdocker"] = isdocker
if self.dict["fhdhr"]["stream_type"] == "ffmpeg":
try:
ffmpeg_command = [self.dict["ffmpeg"]["path"],
"-version",
"pipe:stdout"
]
ffmpeg_proc = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE)
ffmpeg_version = ffmpeg_proc.stdout.read()
ffmpeg_proc.terminate()
ffmpeg_proc.communicate()
ffmpeg_version = ffmpeg_version.decode().split("version ")[1].split(" ")[0]
except FileNotFoundError:
ffmpeg_version = "Missing"
print("Failed to find ffmpeg.")
self.internal["versions"]["ffmpeg"] = ffmpeg_version
if self.dict["fhdhr"]["stream_type"] == "vlc":
try:
vlc_command = [self.dict["vlc"]["path"],
"--version",
"pipe:stdout"
]
vlc_proc = subprocess.Popen(vlc_command, stdout=subprocess.PIPE)
vlc_version = vlc_proc.stdout.read()
vlc_proc.terminate()
vlc_proc.communicate()
vlc_version = vlc_version.decode().split("version ")[1].split('\n')[0]
except FileNotFoundError:
vlc_version = "Missing"
print("Failed to find vlc.")
self.internal["versions"]["vlc"] = vlc_version
def read_json_config(self, conffilepath):
with open(conffilepath, 'r') as jsonconf:
confimport = json.load(jsonconf)
for section in list(confimport.keys()):
if section not in self.dict.keys():
self.dict[section] = {}
if section not in self.conf_default.keys():
self.conf_default[section] = {}
for key in list(confimport[section].keys()):
if key not in list(self.conf_default[section].keys()):
self.conf_default[section][key] = {}
confvalue = confimport[section][key]["value"]
if isint(confvalue):
confvalue = int(confvalue)
elif isfloat(confvalue):
confvalue = float(confvalue)
elif is_arithmetic(confvalue):
confvalue = eval(confvalue)
elif "," in confvalue:
confvalue = confvalue.split(",")
elif str(confvalue).lower() in ["none"]:
confvalue = None
elif str(confvalue).lower() in ["false"]:
confvalue = False
elif str(confvalue).lower() in ["true"]:
confvalue = True
self.dict[section][key] = confvalue
self.conf_default[section][key]["value"] = confvalue
for config_option in ["config_web_hidden", "config_file", "config_web"]:
if config_option not in list(confimport[section][key].keys()):
config_option_value = False
else:
config_option_value = confimport[section][key][config_option]
if str(config_option_value).lower() in ["none"]:
config_option_value = None
elif str(config_option_value).lower() in ["false"]:
config_option_value = False
elif str(config_option_value).lower() in ["true"]:
config_option_value = True
self.conf_default[section][key][config_option] = config_option_value
def read_ini_config(self, conffilepath):
config_handler = configparser.ConfigParser() config_handler = configparser.ConfigParser()
config_handler.read(conffilepath) config_handler.read(conffilepath)
for each_section in config_handler.sections(): for each_section in config_handler.sections():
@ -57,7 +164,9 @@ class Config():
for (each_key, each_val) in config_handler.items(each_section): for (each_key, each_val) in config_handler.items(each_section):
if not each_val: if not each_val:
each_val = None each_val = None
elif each_val.lower() in ["none", "false"]: elif each_val.lower() in ["none"]:
each_val = None
elif each_val.lower() in ["false"]:
each_val = False each_val = False
elif each_val.lower() in ["true"]: elif each_val.lower() in ["true"]:
each_val = True each_val = True
@ -69,7 +178,15 @@ class Config():
each_val = eval(each_val) each_val = eval(each_val)
elif "," in each_val: elif "," in each_val:
each_val = each_val.split(",") each_val = each_val.split(",")
self.dict[each_section.lower()][each_key.lower()] = each_val
import_val = True
if each_section in list(self.conf_default.keys()):
if each_key in list(self.conf_default[each_section].keys()):
if not self.conf_default[each_section][each_key]["config_file"]:
import_val = False
if import_val:
self.dict[each_section.lower()][each_key.lower()] = each_val
def write(self, section, key, value): def write(self, section, key, value):
if section == self.dict["main"]["dictpopname"]: if section == self.dict["main"]["dictpopname"]:
@ -126,95 +243,26 @@ class Config():
raise fHDHR.exceptions.ConfigurationError("Invalid EPG Method. Exiting...") raise fHDHR.exceptions.ConfigurationError("Invalid EPG Method. Exiting...")
self.dict["epg"]["def_method"] = self.dict["epg"]["method"][0] self.dict["epg"]["def_method"] = self.dict["epg"]["method"][0]
# generate UUID here for when we are not using docker
if not self.dict["main"]["uuid"]: if not self.dict["main"]["uuid"]:
# from https://pynative.com/python-generate-random-string/
# create a string that wouldn't be a real device uuid for
self.dict["main"]["uuid"] = ''.join(random.choice("hijklmnopqrstuvwxyz") for i in range(8)) self.dict["main"]["uuid"] = ''.join(random.choice("hijklmnopqrstuvwxyz") for i in range(8))
self.write('main', 'uuid', self.dict["main"]["uuid"]) self.write('main', 'uuid', self.dict["main"]["uuid"])
if self.dict["main"]["cache_dir"]: if self.dict["main"]["cache_dir"]:
if not pathlib.Path(self.dict["main"]["cache_dir"]).is_dir(): if not pathlib.Path(self.dict["main"]["cache_dir"]).is_dir():
raise fHDHR.exceptions.ConfigurationError("Invalid Cache Directory. Exiting...") raise fHDHR.exceptions.ConfigurationError("Invalid Cache Directory. Exiting...")
self.dict["filedir"]["cache_dir"] = pathlib.Path(self.dict["main"]["cache_dir"]) self.internal["paths"]["cache_dir"] = pathlib.Path(self.dict["main"]["cache_dir"])
cache_dir = self.dict["filedir"]["cache_dir"] cache_dir = self.internal["paths"]["cache_dir"]
logs_dir = pathlib.Path(cache_dir).joinpath('logs') logs_dir = pathlib.Path(cache_dir).joinpath('logs')
self.dict["filedir"]["logs_dir"] = logs_dir self.internal["paths"]["logs_dir"] = logs_dir
if not logs_dir.is_dir(): if not logs_dir.is_dir():
logs_dir.mkdir() logs_dir.mkdir()
self.dict["database"]["path"] = pathlib.Path(cache_dir).joinpath('fhdhr.db') self.dict["database"]["path"] = pathlib.Path(cache_dir).joinpath('fhdhr.db')
for epg_method in self.dict["main"]["valid_epg_methods"]:
if epg_method and epg_method != "None":
epg_cache_dir = pathlib.Path(cache_dir).joinpath(epg_method)
if not epg_cache_dir.is_dir():
epg_cache_dir.mkdir()
if epg_method not in list(self.dict["filedir"]["epg_cache"].keys()):
self.dict["filedir"]["epg_cache"][epg_method] = {}
self.dict["filedir"]["epg_cache"][epg_method]["top"] = epg_cache_dir
epg_web_cache_dir = pathlib.Path(epg_cache_dir).joinpath("web_cache")
if not epg_web_cache_dir.is_dir():
epg_web_cache_dir.mkdir()
self.dict["filedir"]["epg_cache"][epg_method]["web_cache"] = epg_web_cache_dir
self.dict["filedir"]["epg_cache"][epg_method]["epg_json"] = pathlib.Path(epg_cache_dir).joinpath('epg.json')
if self.dict["fhdhr"]["stream_type"] not in ["direct", "ffmpeg", "vlc"]: if self.dict["fhdhr"]["stream_type"] not in ["direct", "ffmpeg", "vlc"]:
raise fHDHR.exceptions.ConfigurationError("Invalid stream type. Exiting...") raise fHDHR.exceptions.ConfigurationError("Invalid stream type. Exiting...")
opersystem = platform.system()
self.dict["main"]["opersystem"] = opersystem
if opersystem in ["Linux", "Darwin"]:
# Linux/Mac
if os.getuid() == 0 or os.geteuid() == 0:
print('Warning: Do not run fHDHR with root privileges.')
elif opersystem in ["Windows"]:
# Windows
if os.environ.get("USERNAME") == "Administrator":
print('Warning: Do not run fHDHR as Administrator.')
else:
print("Uncommon Operating System, use at your own risk.")
isdocker = is_docker()
self.dict["main"]["isdocker"] = isdocker
if self.dict["fhdhr"]["stream_type"] == "ffmpeg":
try:
ffmpeg_command = [self.dict["ffmpeg"]["ffmpeg_path"],
"-version",
"pipe:stdout"
]
ffmpeg_proc = subprocess.Popen(ffmpeg_command, stdout=subprocess.PIPE)
ffmpeg_version = ffmpeg_proc.stdout.read()
ffmpeg_proc.terminate()
ffmpeg_proc.communicate()
ffmpeg_version = ffmpeg_version.decode().split("version ")[1].split(" ")[0]
except FileNotFoundError:
ffmpeg_version = None
self.dict["ffmpeg"]["version"] = ffmpeg_version
else:
self.dict["ffmpeg"]["version"] = "N/A"
if self.dict["fhdhr"]["stream_type"] == "vlc":
try:
vlc_command = [self.dict["vlc"]["vlc_path"],
"--version",
"pipe:stdout"
]
vlc_proc = subprocess.Popen(vlc_command, stdout=subprocess.PIPE)
vlc_version = vlc_proc.stdout.read()
vlc_proc.terminate()
vlc_proc.communicate()
vlc_version = vlc_version.decode().split("version ")[1].split('\n')[0]
except FileNotFoundError:
vlc_version = None
self.dict["vlc"]["version"] = vlc_version
else:
self.dict["vlc"]["version"] = "N/A"
if not self.dict["fhdhr"]["discovery_address"] and self.dict["fhdhr"]["address"] != "0.0.0.0": if not self.dict["fhdhr"]["discovery_address"] and self.dict["fhdhr"]["address"] != "0.0.0.0":
self.dict["fhdhr"]["discovery_address"] = self.dict["fhdhr"]["address"] self.dict["fhdhr"]["discovery_address"] = self.dict["fhdhr"]["address"]
if not self.dict["fhdhr"]["discovery_address"] or self.dict["fhdhr"]["discovery_address"] == "0.0.0.0": if not self.dict["fhdhr"]["discovery_address"] or self.dict["fhdhr"]["discovery_address"] == "0.0.0.0":
@ -227,7 +275,7 @@ class Config():
# Create a custom logger # Create a custom logger
logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s', level=log_level) logging.basicConfig(format='%(name)s - %(levelname)s - %(message)s', level=log_level)
logger = logging.getLogger('fHDHR') logger = logging.getLogger('fHDHR')
log_file = os.path.join(self.dict["filedir"]["logs_dir"], 'fHDHR.log') log_file = os.path.join(self.internal["paths"]["logs_dir"], 'fHDHR.log')
# Create handlers # Create handlers
# c_handler = logging.StreamHandler() # c_handler = logging.StreamHandler()

View File

@ -104,7 +104,7 @@ class fHDHRdb(object):
db_user = self.config.dict["database"]["user"] db_user = self.config.dict["database"]["user"]
db_pass = self.config.dict["database"]["pass"] db_pass = self.config.dict["database"]["pass"]
db_host = self.config.dict["database"]["host"] db_host = self.config.dict["database"]["host"]
db_port = self.config.dict["database"]["prt"] # Optional db_port = self.config.dict["database"]["port"] # Optional
db_name = self.config.dict["database"]["name"] # Optional, depending on DB db_name = self.config.dict["database"]["name"] # Optional, depending on DB
# Ensure we have all our variables defined # Ensure we have all our variables defined

View File

@ -14,8 +14,6 @@ class zap2itEPG():
self.postalcode = self.fhdhr.config.dict["zap2it"]["postalcode"] self.postalcode = self.fhdhr.config.dict["zap2it"]["postalcode"]
self.fhdhr.web_cache_dir = self.fhdhr.config.dict["filedir"]["epg_cache"]["zap2it"]["web_cache"]
def get_location(self): def get_location(self):
self.fhdhr.logger.warning("Zap2it postalcode not set, attempting to retrieve.") self.fhdhr.logger.warning("Zap2it postalcode not set, attempting to retrieve.")
if not self.postalcode: if not self.postalcode:

View File

@ -35,7 +35,7 @@ class imageHandler():
colorBackground = "#228822" colorBackground = "#228822"
colorText = "#717D7E" colorText = "#717D7E"
colorOutline = "#717D7E" colorOutline = "#717D7E"
fontname = str(self.fhdhr.config.dict["filedir"]["font"]) fontname = str(self.fhdhr.config.internal["paths"]["font"])
font = PIL.ImageFont.truetype(fontname, fontsize) font = PIL.ImageFont.truetype(fontname, fontsize)
text_width, text_height = self.getSize(message, font) text_width, text_height = self.getSize(message, font)

View File

@ -42,7 +42,7 @@ class FFMPEG_Stream():
def ffmpeg_command_assemble(self, stream_args): def ffmpeg_command_assemble(self, stream_args):
ffmpeg_command = [ ffmpeg_command = [
self.fhdhr.config.dict["ffmpeg"]["ffmpeg_path"], self.fhdhr.config.dict["ffmpeg"]["path"],
"-i", stream_args["channelUri"], "-i", stream_args["channelUri"],
] ]
ffmpeg_command.extend(self.ffmpeg_duration(stream_args)) ffmpeg_command.extend(self.ffmpeg_duration(stream_args))

View File

@ -44,7 +44,7 @@ class VLC_Stream():
def vlc_command_assemble(self, stream_args): def vlc_command_assemble(self, stream_args):
vlc_command = [ vlc_command = [
self.fhdhr.config.dict["vlc"]["vlc_path"], self.fhdhr.config.dict["vlc"]["path"],
"-I", "dummy", stream_args["channelUri"], "-I", "dummy", stream_args["channelUri"],
] ]
vlc_command.extend(self.vlc_duration(stream_args)) vlc_command.extend(self.vlc_duration(stream_args))

View File

@ -13,7 +13,7 @@ class fHDHR_HTTP_Server():
def __init__(self, fhdhr): def __init__(self, fhdhr):
self.fhdhr = fhdhr self.fhdhr = fhdhr
self.template_folder = fhdhr.config.dict["filedir"]["www_templates_dir"] self.template_folder = fhdhr.config.internal["paths"]["www_templates_dir"]
self.app = Flask("fHDHR", template_folder=self.template_folder) self.app = Flask("fHDHR", template_folder=self.template_folder)

View File

@ -1,5 +1,6 @@
from .cluster import Cluster from .cluster import Cluster
from .settings import Settings
from .channels import Channels from .channels import Channels
from .lineup_post import Lineup_Post from .lineup_post import Lineup_Post
from .xmltv import xmlTV from .xmltv import xmlTV
@ -17,6 +18,7 @@ class fHDHR_API():
self.fhdhr = fhdhr self.fhdhr = fhdhr
self.cluster = Cluster(fhdhr) self.cluster = Cluster(fhdhr)
self.settings = Settings(fhdhr)
self.channels = Channels(fhdhr) self.channels = Channels(fhdhr)
self.xmltv = xmlTV(fhdhr) self.xmltv = xmlTV(fhdhr)
self.m3u = M3U(fhdhr) self.m3u = M3U(fhdhr)

View File

@ -0,0 +1,40 @@
from flask import request, redirect
import urllib.parse
class Settings():
endpoints = ["/api/settings"]
endpoint_name = "api_settings"
endpoint_methods = ["GET", "POST"]
def __init__(self, fhdhr):
self.fhdhr = fhdhr
def __call__(self, *args):
return self.get(*args)
def get(self, *args):
method = request.args.get('method', default="get", type=str)
redirect_url = request.args.get('redirect', default=None, type=str)
if method == "update":
config_section = request.form.get('config_section', None)
config_name = request.form.get('config_name', None)
config_value = request.form.get('config_value', None)
if not config_section or not config_name or not config_value:
if redirect_url:
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Failed" % method))
else:
return "%s Falied" % method
if config_section == "origin":
config_section = self.fhdhr.config.dict["main"]["dictpopname"]
self.fhdhr.config.write(config_section, config_name, config_value)
if redirect_url:
return redirect(redirect_url + "?retmessage=" + urllib.parse.quote("%s Success" % method))
else:
return "%s Success" % method

View File

@ -13,6 +13,6 @@ class Favicon_ICO():
def get(self, *args): def get(self, *args):
return send_from_directory(self.fhdhr.config.dict["filedir"]["www_dir"], return send_from_directory(self.fhdhr.config.internal["paths"]["www_dir"],
'favicon.ico', 'favicon.ico',
mimetype='image/vnd.microsoft.icon') mimetype='image/vnd.microsoft.icon')

View File

@ -13,5 +13,5 @@ class Style_CSS():
def get(self, *args): def get(self, *args):
return send_from_directory(self.fhdhr.config.dict["filedir"]["www_dir"], return send_from_directory(self.fhdhr.config.internal["paths"]["www_dir"],
'style.css') 'style.css')

View File

@ -8,6 +8,7 @@ from .streams_html import Streams_HTML
from .version_html import Version_HTML from .version_html import Version_HTML
from .guide_html import Guide_HTML from .guide_html import Guide_HTML
from .xmltv_html import xmlTV_HTML from .xmltv_html import xmlTV_HTML
from .settings import Settings_HTML
class fHDHR_Pages(): class fHDHR_Pages():
@ -16,6 +17,7 @@ class fHDHR_Pages():
self.fhdhr = fhdhr self.fhdhr = fhdhr
self.index = Index_HTML(fhdhr) self.index = Index_HTML(fhdhr)
self.settings = Settings_HTML(fhdhr)
self.origin = Origin_HTML(fhdhr) self.origin = Origin_HTML(fhdhr)
self.cluster = Cluster_HTML(fhdhr) self.cluster = Cluster_HTML(fhdhr)
self.diagnostics = Diagnostics_HTML(fhdhr) self.diagnostics = Diagnostics_HTML(fhdhr)

View File

@ -17,9 +17,9 @@ class Index_HTML():
max_tuners = self.fhdhr.device.tuners.max_tuners max_tuners = self.fhdhr.device.tuners.max_tuners
fhdhr_status_dict = { fhdhr_status_dict = {
"Script Directory": str(self.fhdhr.config.dict["filedir"]["script_dir"]), "Script Directory": str(self.fhdhr.config.internal["paths"]["script_dir"]),
"Config File": str(self.fhdhr.config.config_file), "Config File": str(self.fhdhr.config.config_file),
"Cache Path": str(self.fhdhr.config.dict["filedir"]["cache_dir"]), "Cache Path": str(self.fhdhr.config.internal["paths"]["cache_dir"]),
"Total Channels": str(self.fhdhr.device.channels.get_station_total()), "Total Channels": str(self.fhdhr.device.channels.get_station_total()),
"Tuner Usage": ("%s/%s" % (str(tuners_in_use), str(max_tuners))), "Tuner Usage": ("%s/%s" % (str(tuners_in_use), str(max_tuners))),
} }

View File

@ -0,0 +1,33 @@
from flask import request, render_template
class Settings_HTML():
endpoints = ["/settings", "/settings.html"]
endpoint_name = "settings"
def __init__(self, fhdhr):
self.fhdhr = fhdhr
def __call__(self, *args):
return self.get(*args)
def get(self, *args):
web_settings_dict = {}
for config_section in list(self.fhdhr.config.conf_default.keys()):
web_settings_dict[config_section] = {}
for config_item in list(self.fhdhr.config.conf_default[config_section].keys()):
if self.fhdhr.config.conf_default[config_section][config_item]["config_web"]:
real_config_section = config_section
if config_section == self.fhdhr.config.dict["main"]["dictpopname"]:
real_config_section = "origin"
web_settings_dict[config_section][config_item] = {
"value": self.fhdhr.config.dict[real_config_section][config_item],
"value_default": self.fhdhr.config.conf_default[config_section][config_item]["value"],
"hide": self.fhdhr.config.conf_default[config_section][config_item]["config_web_hidden"]
}
if not len(web_settings_dict[config_section].keys()):
del web_settings_dict[config_section]
return render_template('settings.html', request=request, fhdhr=self.fhdhr, web_settings_dict=web_settings_dict, list=list)

View File

@ -17,9 +17,9 @@ class Version_HTML():
version_dict = { version_dict = {
"fHDHR": self.fhdhr.version, "fHDHR": self.fhdhr.version,
"Python": sys.version, "Python": sys.version,
"Operating System": self.fhdhr.config.dict["main"]["opersystem"], "Operating System": self.fhdhr.config.internal["versions"]["opersystem"],
"Using Docker": self.fhdhr.config.dict["main"]["isdocker"], "Using Docker": self.fhdhr.config.internal["versions"]["isdocker"],
"ffmpeg": self.fhdhr.config.dict["ffmpeg"]["version"], "ffmpeg": self.fhdhr.config.internal["versions"]["ffmpeg"],
"vlc": self.fhdhr.config.dict["vlc"]["version"], "vlc": self.fhdhr.config.internal["versions"]["vlc"],
} }
return render_template('version.html', request=request, fhdhr=self.fhdhr, version_dict=version_dict, list=list) return render_template('version.html', request=request, fhdhr=self.fhdhr, version_dict=version_dict, list=list)