Add upgrade system for settings and automatically add missing settings to file
This commit is contained in:
parent
642484bbb2
commit
865e5a6bce
191
settings.py
191
settings.py
@ -1,39 +1,139 @@
|
|||||||
import ast
|
import ast
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import collections
|
||||||
|
|
||||||
default_settings = '''route_tor = False
|
settings_info = collections.OrderedDict([
|
||||||
port_number = 8080
|
('route_tor', {
|
||||||
allow_foreign_addresses = False
|
'type': bool,
|
||||||
|
'default': False,
|
||||||
|
'comment': '',
|
||||||
|
}),
|
||||||
|
|
||||||
# 0 - off by default
|
('port_number', {
|
||||||
# 1 - only manually created subtitles on by default
|
'type': int,
|
||||||
# 2 - enable even if automatically generated is all that's available
|
'default': 8080,
|
||||||
subtitles_mode = 0
|
'comment': '',
|
||||||
|
}),
|
||||||
|
|
||||||
# ISO 639 language code: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
('allow_foreign_addresses', {
|
||||||
subtitles_language = "en"
|
'type': bool,
|
||||||
|
'default': False,
|
||||||
|
'comment': '''This will allow others to connect to your Youtube Local instance as a website.
|
||||||
|
For security reasons, enabling this is not recommended.''',
|
||||||
|
}),
|
||||||
|
|
||||||
enable_related_videos = True
|
('subtitles_mode', {
|
||||||
enable_comments = True
|
'type': int,
|
||||||
enable_comment_avatars = True
|
'default': 0,
|
||||||
|
'comment': '''0 - off by default
|
||||||
|
1 - only manually created subtitles on by default
|
||||||
|
2 - enable even if automatically generated is all that's available''',
|
||||||
|
}),
|
||||||
|
|
||||||
# 0 to sort by top
|
('subtitles_language', {
|
||||||
# 1 to sort by newest
|
'type': str,
|
||||||
default_comment_sorting = 0
|
'default': 'en',
|
||||||
|
'comment': '''ISO 639 language code: https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes''',
|
||||||
|
}),
|
||||||
|
|
||||||
# developer use to debug 403s
|
('related_videos_mode', {
|
||||||
gather_googlevideo_domains = False
|
'type': int,
|
||||||
|
'default': 1,
|
||||||
|
'comment': '''0 - Related videos disabled
|
||||||
|
1 - Related videos always shown
|
||||||
|
2 - Related videos hidden; shown by clicking a button'''
|
||||||
|
}),
|
||||||
|
|
||||||
# save all responses from youtube for debugging
|
('comments_mode', {
|
||||||
debugging_save_responses = False
|
'type': int,
|
||||||
'''
|
'default': 1,
|
||||||
exec(default_settings)
|
'comment': '''0 - Video comments disabled
|
||||||
allowed_targets = set(("route_tor", "port_number", "allow_foreign_addresses", "subtitles_mode", "subtitles_language", "enable_related_videos", "enable_comments", "enable_comment_avatars", "default_comment_sorting", "gather_googlevideo_domains", "debugging_save_responses"))
|
1 - Video comments always shown
|
||||||
|
2 - Video comments hidden; shown by clicking a button''',
|
||||||
|
}),
|
||||||
|
|
||||||
|
('enable_comment_avatars', {
|
||||||
|
'type': bool,
|
||||||
|
'default': True,
|
||||||
|
'comment': '',
|
||||||
|
}),
|
||||||
|
|
||||||
|
('default_comment_sorting', {
|
||||||
|
'type': int,
|
||||||
|
'default': 0,
|
||||||
|
'comment': '''0 to sort by top
|
||||||
|
1 to sort by newest''',
|
||||||
|
}),
|
||||||
|
|
||||||
|
('gather_googlevideo_domains', {
|
||||||
|
'type': bool,
|
||||||
|
'default': False,
|
||||||
|
'comment': '''Developer use to debug 403s''',
|
||||||
|
}),
|
||||||
|
|
||||||
|
('debugging_save_responses', {
|
||||||
|
'type': bool,
|
||||||
|
'default': False,
|
||||||
|
'comment': '''Save all responses from youtube for debugging''',
|
||||||
|
}),
|
||||||
|
|
||||||
|
('settings_version', {
|
||||||
|
'type': int,
|
||||||
|
'default': 2,
|
||||||
|
'comment': '''Do not change, remove, or comment out this value, or else your settings may be lost or corrupted'''
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
acceptable_targets = settings_info.keys() | {'enable_comments', 'enable_related_videos'}
|
||||||
|
|
||||||
|
|
||||||
|
def comment_string(comment):
|
||||||
|
result = ''
|
||||||
|
for line in comment.splitlines():
|
||||||
|
result += '# ' + line + '\n'
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def create_missing_settings_string(current_settings):
|
||||||
|
result = ''
|
||||||
|
for setting_name, setting_dict in settings_info.items():
|
||||||
|
if setting_name not in current_settings:
|
||||||
|
result += comment_string(setting_dict['comment']) + setting_name + ' = ' + repr(setting_dict['default']) + '\n\n'
|
||||||
|
return result
|
||||||
|
|
||||||
|
def create_default_settings_string():
|
||||||
|
return settings_to_string({})
|
||||||
|
|
||||||
|
def default_settings():
|
||||||
|
return {key: setting_info['default'] for key, setting_info in settings_info.items()}
|
||||||
|
|
||||||
|
def settings_to_string(settings):
|
||||||
|
'''Given a dictionary with the setting names/setting values for the keys/values, outputs a settings file string.
|
||||||
|
Fills in missing values from the defaults.'''
|
||||||
|
result = ''
|
||||||
|
for setting_name, default_setting_dict in settings_info.items():
|
||||||
|
if setting_name in settings:
|
||||||
|
value = settings[setting_name]
|
||||||
|
else:
|
||||||
|
value = default_setting_dict['default']
|
||||||
|
result += comment_string(default_setting_dict['comment']) + setting_name + ' = ' + repr(value) + '\n\n'
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade_to_2(current_settings):
|
||||||
|
'''Upgrade to settings version 2'''
|
||||||
|
new_settings = current_settings.copy()
|
||||||
|
if 'enable_comments' in current_settings:
|
||||||
|
new_settings['comments_mode'] = int(current_settings['enable_comments'])
|
||||||
|
del new_settings['enable_comments']
|
||||||
|
if 'enable_related_videos' in current_settings:
|
||||||
|
new_settings['related_videos_mode'] = int(current_settings['enable_related_videos'])
|
||||||
|
del new_settings['enable_related_videos']
|
||||||
|
return new_settings
|
||||||
|
|
||||||
def log_ignored_line(line_number, message):
|
def log_ignored_line(line_number, message):
|
||||||
print("settings.txt: Ignoring line " + str(node.lineno) + " (" + message + ")")
|
print("WARNING: Ignoring settings.txt line " + str(node.lineno) + " (" + message + ")")
|
||||||
|
|
||||||
|
|
||||||
if os.path.isfile("settings.txt"):
|
if os.path.isfile("settings.txt"):
|
||||||
print("Running in portable mode")
|
print("Running in portable mode")
|
||||||
@ -46,18 +146,23 @@ else:
|
|||||||
if not os.path.exists(settings_dir):
|
if not os.path.exists(settings_dir):
|
||||||
os.makedirs(settings_dir)
|
os.makedirs(settings_dir)
|
||||||
|
|
||||||
|
settings_file_path = os.path.join(settings_dir, 'settings.txt')
|
||||||
|
|
||||||
|
locals().update(default_settings())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(settings_dir, 'settings.txt'), 'r', encoding='utf-8') as file:
|
with open(settings_file_path, 'r', encoding='utf-8') as file:
|
||||||
settings_text = file.read()
|
settings_text = file.read()
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
with open(os.path.join(settings_dir, 'settings.txt'), 'a', encoding='utf-8') as file:
|
with open(settings_file_path, 'w', encoding='utf-8') as file:
|
||||||
file.write(default_settings)
|
file.write(create_default_settings_string())
|
||||||
else:
|
else:
|
||||||
if re.fullmatch(r'\s*', settings_text): # blank file
|
if re.fullmatch(r'\s*', settings_text): # blank file
|
||||||
with open(os.path.join(settings_dir, 'settings.txt'), 'a', encoding='utf-8') as file:
|
with open(settings_file_path, 'w', encoding='utf-8') as file:
|
||||||
file.write(default_settings)
|
file.write(create_default_settings_string())
|
||||||
else:
|
else:
|
||||||
|
# parse settings in a safe way, without exec
|
||||||
|
current_settings = {}
|
||||||
attributes = {
|
attributes = {
|
||||||
ast.NameConstant: 'value',
|
ast.NameConstant: 'value',
|
||||||
ast.Num: 'n',
|
ast.Num: 'n',
|
||||||
@ -78,15 +183,37 @@ else:
|
|||||||
log_ignored_line(node.lineno, "only simple single-variable assignments allowed")
|
log_ignored_line(node.lineno, "only simple single-variable assignments allowed")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if target.id not in allowed_targets:
|
if target.id not in acceptable_targets:
|
||||||
log_ignored_line(node.lineno, "target is not a valid setting")
|
log_ignored_line(node.lineno, target.id + " is not a valid setting")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if type(node.value) not in (ast.NameConstant, ast.Num, ast.Str):
|
if type(node.value) not in (ast.NameConstant, ast.Num, ast.Str):
|
||||||
log_ignored_line(node.lineno, "only literals allowed for values")
|
log_ignored_line(node.lineno, "only literals allowed for values")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
locals()[target.id] = node.value.__getattribute__(attributes[type(node.value)])
|
current_settings[target.id] = node.value.__getattribute__(attributes[type(node.value)])
|
||||||
|
|
||||||
|
|
||||||
|
if 'settings_version' not in current_settings:
|
||||||
|
print('Upgrading settings.txt')
|
||||||
|
new_settings = upgrade_to_2(current_settings)
|
||||||
|
locals().update(new_settings)
|
||||||
|
new_settings_string = settings_to_string(new_settings)
|
||||||
|
with open(settings_file_path, 'w', encoding='utf-8') as file:
|
||||||
|
file.write(new_settings_string)
|
||||||
|
|
||||||
|
# some settings not in the file, add those missing settings to the file
|
||||||
|
elif len(settings_info.keys() - current_settings.keys()) != 0:
|
||||||
|
print('Adding missing settings to settings.txt')
|
||||||
|
append_text = create_missing_settings_string(current_settings)
|
||||||
|
with open(settings_file_path, 'a', encoding='utf-8') as file:
|
||||||
|
file.write('\n\n' + append_text)
|
||||||
|
locals().update(current_settings)
|
||||||
|
else:
|
||||||
|
locals().update(current_settings)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if route_tor:
|
if route_tor:
|
||||||
print("Tor routing is ON")
|
print("Tor routing is ON")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user