forked from 0x2620/pandora
326 lines
12 KiB
Python
326 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
# vi:si:et:sw=4:sts=4:ts=4
|
|
from __future__ import division, with_statement
|
|
|
|
import os
|
|
import sys
|
|
import shutil
|
|
import time
|
|
import thread
|
|
import codecs
|
|
from glob import glob
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.models import User
|
|
|
|
import ox.jsonc
|
|
from ox.utils import json
|
|
|
|
from archive.extract import supported_formats, AVCONV, avconv_version
|
|
from item.utils import get_by_id
|
|
|
|
|
|
_win = (sys.platform == "win32")
|
|
|
|
RUN_RELOADER = True
|
|
NOTIFIER = None
|
|
|
|
def get_version():
|
|
info = os.path.join(os.path.dirname(__file__), '..', '..', '.bzr/branch/last-revision')
|
|
if os.path.exists(info):
|
|
f = open(info)
|
|
rev = int(f.read().split()[0])
|
|
f.close()
|
|
if rev:
|
|
return u'%s' % rev
|
|
return u'unknown'
|
|
|
|
def load_config():
|
|
with open(settings.SITE_CONFIG) as f:
|
|
try:
|
|
config = ox.jsonc.load(f)
|
|
except:
|
|
config = None
|
|
|
|
with open(settings.DEFAULT_CONFIG) as f:
|
|
try:
|
|
default = ox.jsonc.load(f)
|
|
except:
|
|
default = None
|
|
|
|
if config:
|
|
settings.SITENAME = config['site']['name']
|
|
if getattr(settings, 'SITEURL', False):
|
|
config['site']['url'] = settings.SITEURL
|
|
settings.URL = config['site']['url']
|
|
settings.EMAIL_SUBJECT_PREFIX = '[%s]'%settings.SITENAME
|
|
settings.DEFAULT_FROM_EMAIL = config['site']['email']['system']
|
|
settings.SERVER_EMAIL = config['site']['email']['system']
|
|
config['site']['videoprefix'] = settings.VIDEO_PREFIX
|
|
config['site']['mediaprefix'] = settings.MEDIA_PREFIX
|
|
config['site']['version'] = get_version()
|
|
config['site']['dontValidateUser'] = not settings.AUTH_CHECK_USERNAME
|
|
if not 'folderdepth' in config['site']:
|
|
config['site']['folderdepth'] = settings.USE_IMDB and 4 or 3
|
|
if 'sendReferrer' in config and not 'sendReferrer' in config['site']:
|
|
config['site']['sendReferrer'] = config.pop('sendReferrer')
|
|
|
|
# enable default filters if needed
|
|
default_filters = [f['id'] for f in config['user']['ui']['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']))
|
|
|
|
config['keys'] = {}
|
|
for key in config['itemKeys']:
|
|
config['keys'][key['id']] = key
|
|
|
|
|
|
#add missing defaults
|
|
for section in (
|
|
'capabilities', 'cantPlay', 'itemName', 'itemTitleKeys', 'media', 'posters',
|
|
'site', 'tv', 'user.ui', 'user.ui.part', 'user.ui.showFolder',
|
|
'menuExtras', 'languages'
|
|
):
|
|
parts = map(lambda p: p.replace('\0', '\\.'), section.replace('\\.', '\0').split('.'))
|
|
#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):
|
|
if not c:
|
|
c += d
|
|
sys.stderr.write("adding default value for %s = %s\n" % (
|
|
section, str(d)))
|
|
else:
|
|
for key in d:
|
|
if key not in c:
|
|
sys.stderr.write("adding default value for %s.%s = %s\n" % (
|
|
section, key, str(d[key])))
|
|
c[key] = d[key]
|
|
for key in ('language', ):
|
|
if not key in config:
|
|
sys.stderr.write("adding default value for %s = %s\n" % (key, default[key]))
|
|
config[key] = default[key]
|
|
|
|
key = get_by_id(config['itemKeys'], 'title')
|
|
if not 'autocompleteSort' in key:
|
|
key['autocompleteSort'] = get_by_id(default['itemKeys'], 'title')['autocompleteSort']
|
|
sys.stderr.write("adding default value for itemKeys.title.autocompleteSort = %r\n" % key['autocompleteSort'])
|
|
|
|
old_formats = getattr(settings, 'CONFIG', {}).get('video', {}).get('formats', [])
|
|
formats = config.get('video', {}).get('formats')
|
|
if set(old_formats) != set(formats):
|
|
sformats = supported_formats()
|
|
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 avconv. Make sure you
|
|
dont have a local version of avconv in /usr/local/bin
|
|
and libavcodec-extra-53 and libav-tools are installed:
|
|
|
|
sudo apt-get install libavcodec-extra-53 libav-tools
|
|
|
|
''' % f)
|
|
else:
|
|
sys.stderr.write('''WARNING:
|
|
You dont have "%s" installed.
|
|
To fix this on Ubuntu 12.04, run:
|
|
|
|
sudo apt-get install libavcodec-extra-53 libav-tools
|
|
|
|
check the README for further details.
|
|
|
|
''' % AVCONV)
|
|
|
|
settings.AVCONV_VERSION = avconv_version()
|
|
settings.CONFIG = config
|
|
admin = len(settings.CONFIG['userLevels']) - 1
|
|
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):
|
|
p = u.get_profile()
|
|
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
|
|
|
|
|
|
|
|
def reloader_thread():
|
|
global NOTIFIER
|
|
settings.RELOADER_RUNNING=True
|
|
_config_mtime = 0
|
|
try:
|
|
import pyinotify
|
|
INOTIFY = True
|
|
except:
|
|
INOTIFY = False
|
|
if INOTIFY:
|
|
def add_watch():
|
|
name = os.path.realpath(settings.SITE_CONFIG)
|
|
wm.add_watch(name, pyinotify.IN_CLOSE_WRITE, reload_config)
|
|
|
|
def reload_config(event):
|
|
load_config()
|
|
add_watch()
|
|
|
|
wm = pyinotify.WatchManager()
|
|
add_watch()
|
|
notifier = pyinotify.Notifier(wm)
|
|
NOTIFIER = notifier
|
|
notifier.loop()
|
|
else:
|
|
while RUN_RELOADER:
|
|
try:
|
|
stat = os.stat(settings.SITE_CONFIG)
|
|
mtime = stat.st_mtime
|
|
if _win:
|
|
mtime -= stat.st_ctime
|
|
if mtime > _config_mtime:
|
|
load_config()
|
|
_config_mtime = mtime
|
|
time.sleep(10)
|
|
except:
|
|
#sys.stderr.write("reloading config failed\n")
|
|
pass
|
|
|
|
def update_static():
|
|
oxjs_build = os.path.join(settings.STATIC_ROOT, 'oxjs/tools/build/build.py')
|
|
if os.path.exists(oxjs_build):
|
|
print 'update oxjs'
|
|
if os.path.exists(os.path.join(settings.STATIC_ROOT, 'oxjs/min/Geo/json/Geo.json')):
|
|
geo = '-nogeo'
|
|
else:
|
|
geo = ''
|
|
os.system('%s %s >/dev/null' % (oxjs_build, geo))
|
|
|
|
data = ''
|
|
js = []
|
|
pandora_js = os.path.join(settings.STATIC_ROOT, 'js/pandora.min.js')
|
|
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')):
|
|
for f in files:
|
|
if not f in (
|
|
'pandora.js', 'pandora.min.js'
|
|
) and f.endswith('.js') and len(f.split('.')) == 2:
|
|
f = os.path.join(root, f)
|
|
#ignore old embed js file
|
|
if 'js/embed/' in f:
|
|
continue
|
|
fsite = f.replace('.js', '.%s.js' % settings.CONFIG['site']['id'])
|
|
if os.path.exists(fsite):
|
|
f = fsite
|
|
js.append(f[len(settings.STATIC_ROOT)+1:])
|
|
with open(f) as j:
|
|
data += j.read() + '\n'
|
|
js += [
|
|
'png/icon.png',
|
|
]
|
|
print 'write', pandora_js
|
|
with open(pandora_js, 'w') as f:
|
|
data = ox.js.minify(data)
|
|
f.write(data)
|
|
|
|
print 'write', pandora_json
|
|
with open(pandora_json, 'w') as f:
|
|
json.dump(sorted(js), f, indent=2)
|
|
|
|
for f in (pandora_js, pandora_json):
|
|
os.system('gzip -9 -c "%s" > "%s.gz"' % (f, f))
|
|
|
|
for root, folders, files in os.walk(os.path.join(settings.STATIC_ROOT, 'oxjs/min')):
|
|
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))
|
|
|
|
for name in ('logo', 'icon'):
|
|
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)
|
|
if not os.path.exists(image):
|
|
if os.path.exists(site):
|
|
shutil.copyfile(site, image)
|
|
else:
|
|
shutil.copyfile(pandora, image)
|
|
#locale
|
|
for f in sorted(glob(os.path.join(settings.STATIC_ROOT, 'json/locale.pandora.*.json'))):
|
|
with open(f) as fd:
|
|
locale = json.load(fd)
|
|
site_locale = f.replace('locale.pandora', 'locale.' + settings.CONFIG['site']['id'])
|
|
locale_file = f.replace('locale.pandora', 'locale')
|
|
print 'write', locale_file
|
|
print ' adding', f
|
|
if os.path.exists(site_locale):
|
|
with open(site_locale) as fdl:
|
|
print ' adding', site_locale
|
|
locale.update(json.load(fdl))
|
|
with codecs.open(locale_file, "w", "utf-8") as fd:
|
|
json.dump(locale, fd, ensure_ascii=False)
|
|
os.system('gzip -9 -c "%s" > "%s.gz"' % (locale_file, locale_file))
|
|
|
|
|
|
#download geo data
|
|
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)
|
|
|
|
def update_geoip(force=False):
|
|
path = os.path.join(settings.GEOIP_PATH, 'GeoLiteCity.dat')
|
|
if not os.path.exists(path) or force:
|
|
url = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz'
|
|
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)
|
|
path = os.path.join(settings.GEOIP_PATH, 'GeoLiteCityv6.dat')
|
|
if not os.path.exists(path) or force:
|
|
url = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCityv6-beta/GeoLiteCityv6.dat.gz'
|
|
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)
|
|
|
|
def init():
|
|
if not settings.RELOADER_RUNNING:
|
|
load_config()
|
|
if settings.RELOAD_CONFIG:
|
|
thread.start_new_thread(reloader_thread, ())
|
|
|
|
def shutdown():
|
|
if settings.RELOADER_RUNNING:
|
|
RUN_RELOADER = False
|
|
settings.RELOADER_RUNNING = False
|
|
if NOTIFIER:
|
|
NOTIFIER.stop()
|
|
|
|
|
|
|