pandora/pandora/app/config.py

378 lines
15 KiB
Python
Raw Permalink Normal View History

2011-10-25 13:30:14 +00:00
# -*- coding: utf-8 -*-
import codecs
2011-10-25 13:30:14 +00:00
import os
import re
2011-10-27 22:15:37 +00:00
import shutil
2015-11-14 14:22:40 +00:00
import subprocess
import sys
2011-10-25 13:30:14 +00:00
import time
2015-11-14 14:22:40 +00:00
from os.path import dirname, exists, join
2013-05-09 10:13:58 +00:00
from glob import glob
2020-05-29 10:17:18 +00:00
import _thread as thread
2011-10-25 13:30:14 +00:00
from django.conf import settings
2018-07-29 20:12:56 +00:00
from django.contrib.auth import get_user_model
2011-10-25 13:30:14 +00:00
import ox.jsonc
from ox.utils import json
from archive.extract import supported_formats
2013-07-22 13:34:57 +00:00
from item.utils import get_by_id
2018-07-29 20:12:56 +00:00
User = get_user_model()
2011-11-07 14:25:16 +00:00
2011-10-25 13:30:14 +00:00
_win = (sys.platform == "win32")
def get_version():
2015-11-14 14:22:40 +00:00
git_dir = join(dirname(dirname(dirname(__file__))), '.git')
if exists(git_dir):
env = {'GIT_DIR': git_dir}
cmd = ['git', 'rev-list', 'HEAD', '--count']
2020-05-15 16:48:58 +00:00
version = subprocess.check_output(cmd, env=env).strip().decode('utf-8')
if settings.VERSION_EPOCH:
version = settings.VERSION_EPOCH + version
return version
2015-11-14 14:22:40 +00:00
else:
return 'unknown'
def load_config(init=False):
2011-10-25 13:30:14 +00:00
with open(settings.SITE_CONFIG) as f:
2011-10-25 13:59:27 +00:00
try:
config = ox.jsonc.load(f)
except ValueError as e:
if init:
print("Failed to parse %s:\n" % settings.SITE_CONFIG)
2016-02-18 10:49:26 +00:00
print(e)
sys.exit(1)
else:
config = None
2011-10-25 13:59:27 +00:00
with open(settings.DEFAULT_CONFIG) as f:
try:
default = ox.jsonc.load(f)
except ValueError as e:
if init:
print("Failed to default config %s:\n" % settings.DEFAULT_CONFIG)
2016-02-18 10:49:26 +00:00
print(e)
sys.exit(1)
else:
default = None
2011-10-25 13:59:27 +00:00
if config:
settings.SITENAME = config['site']['name']
2013-02-24 10:45:29 +00:00
if getattr(settings, 'SITEURL', False):
config['site']['url'] = settings.SITEURL
settings.URL = config['site']['url']
2019-11-15 15:44:43 +00:00
settings.EMAIL_SUBJECT_PREFIX = '[%s]' % settings.SITENAME
settings.DEFAULT_FROM_EMAIL = config['site']['email']['system']
settings.SERVER_EMAIL = config['site']['email']['system']
2011-10-27 10:07:44 +00:00
config['site']['videoprefix'] = settings.VIDEO_PREFIX
config['site']['mediaprefix'] = settings.MEDIA_PREFIX
2017-06-09 07:34:41 +00:00
config['site']['googleapikey'] = getattr(settings, 'GOOGLE_API_KEY')
config['site']['version'] = get_version()
config['site']['dontValidateUser'] = not settings.AUTH_CHECK_USERNAME
2019-11-15 15:44:43 +00:00
if 'folderdepth' not in config['site']:
2013-02-04 13:07:26 +00:00
config['site']['folderdepth'] = settings.USE_IMDB and 4 or 3
2019-11-15 15:44:43 +00:00
if 'sendReferrer' in config and 'sendReferrer' not in config['site']:
config['site']['sendReferrer'] = config.pop('sendReferrer')
2011-10-25 13:59:27 +00:00
# enable default filters if needed
default_filters = [f['id'] for f in config['user']['ui']['filters']]
available_filters = [key['id'] for key in config['itemKeys'] if key.get('filter')]
unknown_ids = set(default_filters) - set(available_filters)
if unknown_ids:
sys.stderr.write('WARNING: unknown item keys in default filters: %s.\n' % list(unknown_ids))
unused_filters = [key for key in available_filters if key not in default_filters]
if len(unused_filters) < len(unknown_ids):
sys.stderr.write('you need at least 5 item filters')
else:
auto_filters = unused_filters[:len(unknown_ids)]
default_filters += auto_filters
for key in auto_filters:
config['user']['ui']['filters'].append({
"id": key, "sort": [{"key": "items", "operator": "-"}]
})
sys.stderr.write(' using the following document filters instead: %s.\n' % auto_filters)
for key in config['itemKeys']:
if key['id'] in default_filters and not key.get('filter'):
key['filter'] = True
sys.stderr.write('enabled filter for "%s" since its used as default filter.\n' % (key['id']))
2011-10-25 13:59:27 +00:00
config['keys'] = {}
for key in config['itemKeys']:
config['keys'][key['id']] = key
2016-08-09 11:56:54 +00:00
# add missing defaults
for section in sorted((
2016-10-04 22:00:03 +00:00
'capabilities', 'cantPlay',
2017-12-15 13:12:30 +00:00
'documentKeys', 'documentRightsLevels',
2016-10-04 22:00:03 +00:00
'entities', 'itemName', 'itemTitleKeys', 'itemKeys', 'media', 'posters',
'site', 'tv', 'user.ui', 'user.ui.part', 'user.ui.showFolder',
2018-09-12 17:29:10 +00:00
'menuExtras', 'languages',
'annotations',
)):
parts = [p.replace('\0', '\\.') for p in section.replace('\\.', '\0').split('.')]
2016-08-09 11:56:54 +00:00
# print('checking', section)
c = config
d = default
while len(parts):
part = parts.pop(0)
d = d[part]
if part not in c:
if isinstance(d, list):
c[part] = []
else:
c[part] = {}
c = c[part]
if isinstance(d, list):
2014-12-26 12:19:36 +00:00
if not c and section not in ('entities', ):
c += d
sys.stderr.write("adding default value:\n\t\"%s\": %s,\n\n" % (
section, json.dumps(d)))
else:
added = []
for key in sorted(d):
if key not in c:
if key not in (
'hidden',
'find',
'findDocuments',
'videoPoints',
):
added.append("\"%s\": %s," % (key, json.dumps(d[key])))
c[key] = d[key]
if added:
sys.stderr.write("adding default %s:\n\t" % section)
sys.stderr.write("\n\t".join(added) + '\n\n')
2017-12-15 13:12:30 +00:00
# add entities if needed
if len(config.get('entities', [])) and not [k for k in config['documentKeys'] if k['id'] == 'entites']:
config['documentKeys'].append({
'id': 'entity',
'title': 'Entity',
'type': 'string',
'find': True
})
2017-12-15 13:12:30 +00:00
key = 'documentRightsLevel'
if key not in config:
config[key] = {}
for level in config['userLevels']:
if level not in config[key]:
config[key] = default.get(key, 0)
config['user']['ui']['documentsSort'] = [
s for s in config['user']['ui']['documentsSort']
if get_by_id(config['documentKeys'], s['key'])
]
if not config['user']['ui']['documentsSort']:
sort_key = [k for k in config['documentKeys'] if k['id'] != '*'][0]
config['user']['ui']['documentsSort'] = [{
"key": sort_key['id'],
"operator": sort_key.get('operator', '+')
}]
2016-08-09 11:56:54 +00:00
for key in ('language', 'importMetadata'):
if key not in config:
sys.stderr.write("adding default value:\n\t\"%s\": %s,\n\n" % (key, json.dumps(default[key])))
config[key] = default[key]
2013-07-22 13:34:57 +00:00
key = get_by_id(config['itemKeys'], 'title')
2015-11-18 13:45:31 +00:00
if not 'autocompleteSort' in key:
2013-07-22 13:34:57 +00:00
key['autocompleteSort'] = get_by_id(default['itemKeys'], 'title')['autocompleteSort']
2015-11-18 13:46:14 +00:00
sys.stderr.write("adding default value to itemKeys.title.autocompleteSort:\n\t\"autocompleteSort\": %s,\n\n" % json.dumps(key['autocompleteSort']))
2013-07-22 13:34:57 +00:00
2017-11-14 16:13:41 +00:00
if 'downloadFormat' not in config['video']:
config['video']['downloadFormat'] = default['video']['downloadFormat']
2020-02-05 16:40:22 +00:00
# enable default document filters if needed
default_filters = [f['id'] for f in config['user']['ui']['documentFilters']]
available_filters = [key['id'] for key in config['documentKeys'] if key.get('filter')]
unknown_ids = set(default_filters) - set(available_filters)
if unknown_ids:
sys.stderr.write('WARNING: unknown document keys in default filters: %s.\n' % list(unknown_ids))
unused_filters = [key for key in available_filters if key not in default_filters]
if len(unused_filters) < len(unknown_ids):
sys.stderr.write('you need at least 5 item filters')
else:
auto_filters = unused_filters[:len(unknown_ids)]
default_filters += auto_filters
for key in auto_filters:
config['user']['ui']['documentFilters'].append({
"id": key, "sort": [{"key": "items", "operator": "-"}]
})
sys.stderr.write(' using the following document filters instead: %s.\n' % auto_filters)
for key in config['documentKeys']:
if key['id'] in default_filters and not key.get('filter'):
key['filter'] = True
sys.stderr.write('enabled filter for document key "%s" since its used as default filter.\n' % (key['id']))
old_formats = getattr(settings, 'CONFIG', {}).get('video', {}).get('formats', [])
formats = config.get('video', {}).get('formats')
if set(old_formats) != set(formats):
sformats = supported_formats()
settings.FFMPEG_SUPPORTS_VP9 = 'vp9' in sformats
2018-08-10 10:12:01 +00:00
try:
settings.CHOP_SUPPORT = int(sformats.get('version', ['0'])[0]) > 2
except:
settings.CHOP_SUPPORT = False
if sformats:
for f in formats:
if f not in sformats or not sformats[f]:
sys.stderr.write('''WARNING:
Your configuration contains a video format "%s" that is
not supported by your version of ffmpeg. Make sure you
dont have a local version of ffmpeg in /usr/local/bin
and ffmpeg is installed from ppa:j/pandora:
sudo add-apt-repository ppa:j/pandora
sudo apt-get install ffmpeg
''' % f)
else:
sys.stderr.write('''WARNING:
You dont have "ffmpeg" installed. To fix this on Ubuntu 14.04, run:
sudo add-apt-repository ppa:j/pandora
sudo apt-get install ffmpeg
check the README for further details.
''')
2011-10-25 13:59:27 +00:00
settings.CONFIG = config
admin = len(settings.CONFIG['userLevels']) - 1
2012-11-27 15:10:17 +00:00
if not 'syncdb' in sys.argv \
and not 'sqldiff' in sys.argv \
and not 'migrate' in sys.argv:
try:
if User.objects.filter(profile__level=admin).count() == 0:
for u in User.objects.filter(is_superuser=True):
2016-02-19 16:34:15 +00:00
p = u.profile
2012-11-27 15:10:17 +00:00
p.level = admin
p.save()
settings.ADMIN = tuple([(u.username, u.email)
for u in User.objects.filter(profile__level=admin)])
settings.MANAGERS = settings.ADMINS
except:
pass
2011-10-25 13:30:14 +00:00
def update_static():
oxjs_build = os.path.join(settings.STATIC_ROOT, 'oxjs/tools/build/build.py')
if os.path.exists(oxjs_build):
2016-02-18 10:49:26 +00:00
print('update oxjs')
os.system('%s >/dev/null' % oxjs_build)
2011-10-25 13:30:14 +00:00
data = ''
js = []
2011-11-03 10:50:05 +00:00
pandora_js = os.path.join(settings.STATIC_ROOT, 'js/pandora.min.js')
2011-10-25 13:30:14 +00:00
pandora_json = os.path.join(settings.STATIC_ROOT, 'json/pandora.json')
for root, folders, files in os.walk(os.path.join(settings.STATIC_ROOT, 'js')):
2011-10-25 13:30:14 +00:00
for f in files:
2018-09-18 21:17:32 +00:00
if f.startswith('._'):
continue
2018-08-08 09:22:19 +00:00
f = os.path.join(root, f)
#ignore old embed js file
if 'js/embed/' in f:
continue
if len(f.split('.')) == 2:
2011-12-20 13:08:30 +00:00
fsite = f.replace('.js', '.%s.js' % settings.CONFIG['site']['id'])
2018-08-08 09:22:19 +00:00
else:
fsite = f
basefile = f.split('.')[0] + '.js'
if f.split('/')[-1] not in (
2018-08-08 09:22:19 +00:00
'pandora.js', 'pandora.min.js'
) and f.endswith('.js') and (
len(f.split('.')) == 2 or
not os.path.exists(basefile) and fsite == f
):
2011-12-19 15:22:38 +00:00
if os.path.exists(fsite):
f = fsite
js.append(f[len(settings.STATIC_ROOT)+1:])
with open(f) as j:
2011-10-25 13:30:14 +00:00
data += j.read() + '\n'
2012-02-16 15:59:31 +00:00
js += [
'png/icon.png',
2012-02-16 15:59:31 +00:00
]
2016-02-18 10:49:26 +00:00
print('write', pandora_js)
data = ox.js.minify(data)
2011-10-25 13:30:14 +00:00
with open(pandora_js, 'w') as f:
f.write(data)
2016-02-18 10:49:26 +00:00
print('write', pandora_json)
2011-10-25 13:30:14 +00:00
with open(pandora_json, 'w') as f:
json.dump(sorted(js), f, indent=2)
2012-01-02 12:53:46 +00:00
for f in (pandora_js, pandora_json):
os.system('gzip -9 -c "%s" > "%s.gz"' % (f, f))
2014-09-26 14:54:20 +00:00
for root, folders, files in os.walk(os.path.join(settings.STATIC_ROOT, 'oxjs/min')):
2012-01-02 12:53:46 +00:00
for f in files:
if os.path.splitext(f)[-1] in ('.js', '.json'):
f = os.path.join(root, f)
os.system('gzip -9 -c "%s" > "%s.gz"' % (f, f))
2017-06-09 07:25:43 +00:00
2017-01-25 16:41:06 +00:00
for name in ('logo', 'icon', 'document'):
2017-06-09 07:25:43 +00:00
site = os.path.join(settings.STATIC_ROOT, 'png/%s.%s.png' % (name, settings.CONFIG['site']['id']))
pandora = os.path.join(settings.STATIC_ROOT, 'png/%s.pandora.png' % name)
image = os.path.join(settings.STATIC_ROOT, 'png/%s.png' % name)
2011-10-27 22:15:37 +00:00
if not os.path.exists(image):
if os.path.exists(site):
shutil.copyfile(site, image)
else:
shutil.copyfile(pandora, image)
2013-05-09 10:13:58 +00:00
#locale
for f in sorted(glob(os.path.join(settings.STATIC_ROOT, 'json/locale.pandora.*.json'))):
with open(f) as fd:
try:
locale = json.load(fd)
except:
print("failed to parse %s" % f)
raise
2013-05-09 20:10:54 +00:00
site_locale = f.replace('locale.pandora', 'locale.' + settings.CONFIG['site']['id'])
locale_file = f.replace('locale.pandora', 'locale')
2016-02-18 10:49:26 +00:00
print('write', locale_file)
print(' adding', f)
2013-05-09 20:10:54 +00:00
if os.path.exists(site_locale):
with open(site_locale) as fdl:
2016-02-18 10:49:26 +00:00
print(' adding', site_locale)
2013-05-09 20:10:54 +00:00
locale.update(json.load(fdl))
2013-12-27 11:03:06 +00:00
with codecs.open(locale_file, "w", "utf-8") as fd:
json.dump(locale, fd, ensure_ascii=False)
2013-05-09 10:13:58 +00:00
os.system('gzip -9 -c "%s" > "%s.gz"' % (locale_file, locale_file))
2011-10-27 22:15:37 +00:00
2011-12-03 16:17:07 +00:00
#download geo data
2012-03-04 19:15:47 +00:00
update_geoip()
#scripts
for script in (settings.ITEM_POSTER, settings.ITEM_ICON, settings.LIST_ICON):
if not os.path.exists(script):
site_script = script.replace('.py', '.%s.py' % settings.CONFIG['site']['id'])
default_script = script.replace('.py', '.pandora.py')
if os.path.exists(site_script):
os.symlink(site_script, script)
else:
os.symlink(default_script, script)
2012-03-04 19:15:47 +00:00
def update_geoip(force=False):
2016-03-04 07:20:44 +00:00
path = os.path.join(settings.GEOIP_PATH, 'GeoLite2-City.mmdb')
2012-03-04 19:15:47 +00:00
if not os.path.exists(path) or force:
2020-05-30 01:13:57 +00:00
index = ox.net.read_url('https://db-ip.com/db/download/ip-to-city-lite').decode()
match = re.compile('href=[\'"](http.*.mmdb.gz)').findall(index)
if match:
url = match[0]
print('download', url)
ox.net.save_url(url, "%s.gz" % path)
if os.path.exists(path):
os.unlink(path)
os.system('gunzip "%s.gz"' % path)
else:
2020-05-30 01:13:57 +00:00
print('failed to download GeoLite2-City.mmdb')
2011-12-03 16:17:07 +00:00
2020-09-27 16:02:23 +00:00
def init():
load_config(True)