diff --git a/README.md b/README.md index 7801e180..044a3cb8 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,4 @@ export BRANCH=stable # change to 'master' to get current developement version More info at https://code.0x2620.org/0x2620/pandora/wiki/Customization -## Update - - To update your existing instlalation run - - pandoractl update diff --git a/ctl b/ctl index b78183ba..28c74e12 100755 --- a/ctl +++ b/ctl @@ -17,7 +17,7 @@ if [ "$action" = "init" ]; then SUDO="" PANDORA_USER=`ls -l update.py | cut -f3 -d" "` if [ `whoami` != $PANDORA_USER ]; then - SUDO="sudo -E -H -u $PANDORA_USER" + SUDO="sudo -H -u $PANDORA_USER" fi $SUDO python3 -m venv --system-site-packages . branch=`cat .git/HEAD | sed 's@/@\n@g' | tail -n1` @@ -62,10 +62,11 @@ if [ ! -z $cmd ]; then SUDO="" PANDORA_USER=`ls -l update.py | cut -f3 -d" "` if [ `whoami` != $PANDORA_USER ]; then - SUDO="sudo -E -H -u $PANDORA_USER" + SUDO="sudo -H -u $PANDORA_USER" fi shift - exec $SUDO "$BASE/$cmd" $@ + $SUDO "$BASE/$cmd" $@ + exit $? fi if [ `whoami` != 'root' ]; then diff --git a/docker/base/install.sh b/docker/base/install.sh index 2d016eba..5c209f07 100755 --- a/docker/base/install.sh +++ b/docker/base/install.sh @@ -30,8 +30,6 @@ apt-get update -qq apt-get install -y \ netcat-openbsd \ sudo \ - rsync \ - iproute2 \ vim \ wget \ pwgen \ @@ -49,20 +47,17 @@ apt-get install -y \ python3-cssselect \ python3-html5lib \ python3-ox \ - python3-elasticsearch \ oxframe \ ffmpeg \ mkvtoolnix \ gpac \ imagemagick \ poppler-utils \ + youtube-dl \ ipython3 \ - tesseract-ocr \ - tesseract-ocr-eng \ postfix \ postgresql-client -apt-get install -y --no-install-recommends youtube-dl rtmpdump apt-get clean rm -f /install.sh diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 123883f8..cd78c6f4 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -8,8 +8,6 @@ export LANG=en_US.UTF-8 mkdir -p /run/pandora chown -R ${user}.${user} /run/pandora -update="/usr/bin/sudo -u $user -E -H /srv/pandora/update.py" - # pan.do/ra services if [ "$action" = "pandora" ]; then if [ ! -e /srv/pandora/initialized ]; then @@ -28,12 +26,12 @@ if [ "$action" = "pandora" ]; then /overlay/install.py echo "Initializing database..." - echo "CREATE EXTENSION pg_trgm;" | /srv/pandora/pandora/manage.py dbshell || true + echo "CREATE EXTENSION pg_trgm;" | /srv/pandora/pandora/manage.py dbshell /srv/pandora/pandora/manage.py init_db - $update db + /srv/pandora/update.py db echo "Generating static files..." + /srv/pandora/update.py static chown -R ${user}.${user} /srv/pandora/ - $update static touch /srv/pandora/initialized fi /srv/pandora_base/docker/wait-for db 5432 @@ -46,53 +44,54 @@ if [ "$action" = "encoding" ]; then /srv/pandora_base/docker/wait-for-file /srv/pandora/initialized /srv/pandora_base/docker/wait-for rabbitmq 5672 name=pandora-encoding-$(hostname) - cd /srv/pandora/pandora exec /usr/bin/sudo -u $user -E -H \ - /srv/pandora/bin/celery \ - -A app worker \ - -Q encoding -n ${name} \ - --pidfile /run/pandora/encoding.pid \ - --maxtasksperchild 500 \ - -c 1 \ - -l INFO + /srv/pandora/bin/python \ + /srv/pandora/pandora/manage.py \ + celery worker \ + -c 1 \ + -Q encoding -n $name \ + -l INFO fi if [ "$action" = "tasks" ]; then /srv/pandora_base/docker/wait-for-file /srv/pandora/initialized /srv/pandora_base/docker/wait-for rabbitmq 5672 name=pandora-default-$(hostname) - cd /srv/pandora/pandora exec /usr/bin/sudo -u $user -E -H \ - /srv/pandora/bin/celery \ - -A app worker \ - -Q default,celery -n ${name} \ - --pidfile /run/pandora/tasks.pid \ + /srv/pandora/bin/python \ + /srv/pandora/pandora/manage.py \ + celery worker \ + -Q default,celery -n $name \ --maxtasksperchild 1000 \ -l INFO fi if [ "$action" = "cron" ]; then /srv/pandora_base/docker/wait-for-file /srv/pandora/initialized /srv/pandora_base/docker/wait-for rabbitmq 5672 - cd /srv/pandora/pandora exec /usr/bin/sudo -u $user -E -H \ - /srv/pandora/bin/celery \ - -A app beat \ - -s /run/pandora/celerybeat-schedule \ + /srv/pandora/bin/python \ + /srv/pandora/pandora/manage.py \ + celerybeat -s /run/pandora/celerybeat-schedule \ --pidfile /run/pandora/cron.pid \ -l INFO fi if [ "$action" = "websocketd" ]; then /srv/pandora_base/docker/wait-for-file /srv/pandora/initialized /srv/pandora_base/docker/wait-for rabbitmq 5672 - cd /srv/pandora/pandora exec /usr/bin/sudo -u $user -E -H \ /srv/pandora/bin/python \ /srv/pandora/pandora/manage.py websocketd fi # pan.do/ra management and update -if [ "$action" = "ctl" ]; then +if [ "$action" = "manage.py" ]; then shift - exec /srv/pandora/ctl "$@" + exec /usr/bin/sudo -u $user -E -H \ + /srv/pandora/pandora/manage.py "$@" +fi +if [ "$action" = "update.py" ]; then + shift + exec /usr/bin/sudo -u $user -E -H \ + /srv/pandora/update.py "$@" fi if [ "$action" = "bash" ]; then shift diff --git a/docker/install.sh b/docker/install.sh index 081a18af..e1a87181 100755 --- a/docker/install.sh +++ b/docker/install.sh @@ -56,9 +56,13 @@ cp /srv/pandora/docker/entrypoint.sh /entrypoint.sh mv /srv/pandora/ /srv/pandora_base/ mkdir /pandora ln -s /pandora /srv/pandora - -cat > /usr/local/bin/pandoractl << EOF +cat > /usr/local/bin/update.py << EOF #!/bin/sh -exec /srv/pandora/ctl \$@ +exec /srv/pandora/update.py \$@ EOF -chmod +x /usr/local/bin/pandoractl + +cat > /usr/local/bin/manage.py << EOF +#!/bin/sh +exec /srv/pandora/pandora/manage.py \$@ +EOF +chmod +x /usr/local/bin/manage.py /usr/local/bin/update.py diff --git a/docker/publish.sh b/docker/publish.sh deleted file mode 100644 index f4ef0193..00000000 --- a/docker/publish.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# push new version of pan.do/ra to docker hub -set -e - -cd /tmp -git clone https://code.0x2620.org/0x2620/pandora -cd pandora -./docker/build.sh - -docker push 0x2620/pandora-base:latest -docker push 0x2620/pandora-nginx:latest -docker push 0x2620/pandora:latest diff --git a/docker/setup-docker-compose.sh b/docker/setup-docker-compose.sh index 2f48179f..7665e7b8 100755 --- a/docker/setup-docker-compose.sh +++ b/docker/setup-docker-compose.sh @@ -26,7 +26,7 @@ and to get started run this: To update pan.do/ra run: - docker-compose run pandora ctl update + docker-compose run pandora update.py EOF touch __init__.py diff --git a/docker/wait-for-file b/docker/wait-for-file index d4fe19d6..83b043e4 100755 --- a/docker/wait-for-file +++ b/docker/wait-for-file @@ -1,5 +1,5 @@ #!/bin/sh -TIMEOUT=180 +TIMEOUT=60 TARGET="$1" for i in `seq $TIMEOUT` ; do diff --git a/pandora/app/config.py b/pandora/app/config.py index 3e96ac27..e950e5e9 100644 --- a/pandora/app/config.py +++ b/pandora/app/config.py @@ -24,6 +24,9 @@ User = get_user_model() _win = (sys.platform == "win32") +RUN_RELOADER = True +NOTIFIER = None + def get_version(): git_dir = join(dirname(dirname(dirname(__file__))), '.git') if exists(git_dir): @@ -254,6 +257,46 @@ check the README for further details. 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): @@ -364,7 +407,10 @@ def update_geoip(force=False): print('failed to download GeoLite2-City.mmdb') def init(): - load_config(True) + if not settings.RELOADER_RUNNING: + load_config(True) + if settings.RELOAD_CONFIG: + thread.start_new_thread(reloader_thread, ()) def shutdown(): if settings.RELOADER_RUNNING: diff --git a/pandora/app/management/commands/init_db.py b/pandora/app/management/commands/init_db.py index a7957395..92ac750f 100644 --- a/pandora/app/management/commands/init_db.py +++ b/pandora/app/management/commands/init_db.py @@ -11,8 +11,6 @@ def run(cmd): stdout, stderr = p.communicate() if p.returncode != 0: - print('failed to run:', cmd) - print(stdout) print(stderr) sys.exit(1) diff --git a/pandora/archive/external.py b/pandora/archive/external.py index cb0e7ef1..510d3f70 100644 --- a/pandora/archive/external.py +++ b/pandora/archive/external.py @@ -36,10 +36,8 @@ info_key_map = { 'display_id': 'id', } -def get_info(url, referer=None): +def get_info(url): cmd = ['youtube-dl', '-j', '--all-subs', url] - if referer: - cmd += ['--referer', referer] p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) @@ -59,8 +57,6 @@ def get_info(url, referer=None): info[-1]['tags'] = [] if 'upload_date' in i and i['upload_date']: info[-1]['date'] = '-'.join([i['upload_date'][:4], i['upload_date'][4:6], i['upload_date'][6:]]) - if 'referer' not in info[-1]: - info[-1]['referer'] = url return info def add_subtitles(item, media, tmp): @@ -88,9 +84,9 @@ def add_subtitles(item, media, tmp): sub.selected = True sub.save() -def download(item_id, url, referer=None): +def download(item_id, url): item = Item.objects.get(public_id=item_id) - info = get_info(url, referer) + info = get_info(url) if not len(info): return '%s contains no videos' % url media = info[0] @@ -100,12 +96,7 @@ def download(item_id, url, referer=None): tmp = tmp.decode('utf-8') os.chdir(tmp) cmd = ['youtube-dl', '-q', media['url']] - if referer: - cmd += ['--referer', referer] - elif 'referer' in media: - cmd += ['--referer', media['referer']] - - if settings.CONFIG['video'].get('reuseUpload', False): + if settings.CONFIG['video'].get('reuseUload', False): max_resolution = max(settings.CONFIG['video']['resolutions']) format = settings.CONFIG['video']['formats'][0] if format == 'mp4': diff --git a/pandora/archive/extract.py b/pandora/archive/extract.py index ebfd2ae7..dcb9bdcf 100644 --- a/pandora/archive/extract.py +++ b/pandora/archive/extract.py @@ -2,13 +2,13 @@ import os from os.path import exists + import fractions -import math -import re -import shutil import subprocess import tempfile import time +import math +import shutil from distutils.spawn import find_executable from glob import glob @@ -63,8 +63,8 @@ def supported_formats(): 'webm': 'libvpx' in stdout and 'libvorbis' in stdout, 'vp8': 'libvpx' in stdout and 'libvorbis' in stdout, 'vp9': 'libvpx-vp9' in stdout and 'libopus' in stdout, - 'mp4': 'libx264' in stdout and bool(re.compile('DEA.L. aac').findall(stdout)), - 'h264': 'libx264' in stdout and bool(re.compile('DEA.L. aac').findall(stdout)), + 'mp4': 'libx264' in stdout and 'DEA.L. aac' in stdout, + 'h264': 'libx264' in stdout and 'DEA.L. aac' in stdout, } def stream(video, target, profile, info, audio_track=0, flags={}): @@ -145,13 +145,6 @@ def stream(video, target, profile, info, audio_track=0, flags={}): audioquality = -1 audiobitrate = '22k' audiochannels = 1 - elif profile == '0p': - info['video'] = [] - audiorate = 48000 - audioquality = 6 - audiobitrate = None - audiochannels = None - audio_codec = 'libopus' else: height = 96 diff --git a/pandora/archive/models.py b/pandora/archive/models.py index 56080815..05882c40 100644 --- a/pandora/archive/models.py +++ b/pandora/archive/models.py @@ -336,9 +336,7 @@ class File(models.Model): def done_cb(): if done: - info = ox.avinfo(self.data.path) - del info['path'] - self.info.update(info) + self.info.update(ox.avinfo(self.data.path)) self.parse_info() # reject invalid uploads if self.info.get('oshash') != self.oshash: @@ -483,13 +481,6 @@ class File(models.Model): user.is_staff or \ self.item.user == user or \ self.item.groups.filter(id__in=user.groups.all()).count() > 0 - if 'instances' in data and 'filename' in self.info and self.data: - data['instances'].append({ - 'ignore': False, - 'path': self.info['filename'], - 'user': self.item.user.username if self.item and self.item.user else 'system', - 'volume': 'Direct Upload' - }) if not can_see_media: if 'instances' in data: data['instances'] = [] diff --git a/pandora/archive/tasks.py b/pandora/archive/tasks.py index a2aa3d8e..022cd377 100644 --- a/pandora/archive/tasks.py +++ b/pandora/archive/tasks.py @@ -200,8 +200,8 @@ def update_stream(id): c.save() @task(queue="encoding") -def download_media(item_id, url, referer=None): - return external.download(item_id, url, referer) +def download_media(item_id, url): + return external.download(item_id, url) @task(queue='default') def move_media(data, user): diff --git a/pandora/archive/views.py b/pandora/archive/views.py index 308e7c10..848bfc7e 100644 --- a/pandora/archive/views.py +++ b/pandora/archive/views.py @@ -195,9 +195,7 @@ def addMedia(request, data): response['data']['item'] = f.item.public_id response['data']['itemUrl'] = request.build_absolute_uri('/%s' % f.item.public_id) if not f.available: - changelog_data = data.copy() - changelog_data['oshash'] = oshash - add_changelog(request, changelog_data, f.item.public_id) + add_changelog(request, data, f.item.public_id) else: if 'item' in data: i = Item.objects.get(public_id=data['item']) @@ -222,15 +220,11 @@ def addMedia(request, data): if 'info' in data and data['info'] and isinstance(data['info'], dict): f.info = data['info'] f.info['extension'] = extension - if 'filename' in data: - f.info['filename'] = data['filename'] f.parse_info() f.save() response['data']['item'] = i.public_id response['data']['itemUrl'] = request.build_absolute_uri('/%s' % i.public_id) - changelog_data = data.copy() - changelog_data['oshash'] = oshash - add_changelog(request, changelog_data, i.public_id) + add_changelog(request, data, i.public_id) return render_to_json_response(response) actions.register(addMedia, cache=False) @@ -745,7 +739,6 @@ def addMediaUrl(request, data): takes { url: string, // url - referer: string // optional referer url item: string // item } returns { @@ -758,7 +751,7 @@ def addMediaUrl(request, data): response = json_response() i = Item.objects.get(public_id=data['item']) Task.start(i, request.user) - t = tasks.download_media.delay(data['item'], data['url'], data.get('referer')) + t = tasks.download_media.delay(data['item'], data['url']) response['data']['taskId'] = t.task_id add_changelog(request, data, data['item']) return render_to_json_response(response) diff --git a/pandora/document/management/commands/rebuild_documentfind.py b/pandora/document/management/commands/rebuild_documentfind.py index 157072c3..af56b748 100644 --- a/pandora/document/management/commands/rebuild_documentfind.py +++ b/pandora/document/management/commands/rebuild_documentfind.py @@ -5,6 +5,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models diff --git a/pandora/document/management/commands/sync_documentsort.py b/pandora/document/management/commands/sync_documentsort.py index ed3b13e2..fa6cb5d8 100644 --- a/pandora/document/management/commands/sync_documentsort.py +++ b/pandora/document/management/commands/sync_documentsort.py @@ -5,6 +5,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch diff --git a/pandora/document/tasks.py b/pandora/document/tasks.py index 7bede1a9..f08983bb 100644 --- a/pandora/document/tasks.py +++ b/pandora/document/tasks.py @@ -1,4 +1,4 @@ -import ox +# -*- coding: utf-8 -*- from celery.task import task @task(queue="encoding") @@ -6,20 +6,3 @@ def extract_fulltext(id): from . import models d = models.Document.objects.get(id=id) d.update_fulltext() - - -@task(queue='default') -def bulk_edit(data, username): - from django.db import transaction - from . import models - from item.models import Item - user = models.User.objects.get(username=username) - item = 'item' in data and Item.objects.get(public_id=data['item']) or None - documents = models.Document.objects.filter(pk__in=map(ox.fromAZ, data['id'])) - for document in documents: - if document.editable(user, item): - with transaction.atomic(): - document.refresh_from_db() - document.edit(data, user, item) - document.save() - return {} diff --git a/pandora/document/views.py b/pandora/document/views.py index 5fc47466..84279ac9 100644 --- a/pandora/document/views.py +++ b/pandora/document/views.py @@ -23,7 +23,6 @@ from archive.chunk import process_chunk from changelog.models import add_changelog from . import models -from . import tasks def get_document_or_404_json(request, id): response = {'status': {'code': 404, @@ -132,13 +131,13 @@ def editDocument(request, data): item = 'item' in data and Item.objects.get(public_id=data['item']) or None if data['id']: if isinstance(data['id'], list): - add_changelog(request, data) - t = tasks.bulk_edit.delay(data, request.user.username) - response['data']['taskId'] = t.task_id + documents = models.Document.objects.filter(pk__in=map(ox.fromAZ, data['id'])) else: - document = models.Document.get(data['id']) + documents = [models.Document.get(data['id'])] + for document in documents: if document.editable(request.user, item): - add_changelog(request, data) + if document == documents[0]: + add_changelog(request, data) document.edit(data, request.user, item) document.save() response['data'] = document.json(user=request.user, item=item) diff --git a/pandora/item/management/commands/get_frame.py b/pandora/item/management/commands/get_frame.py index fe96f9b1..1aaba624 100644 --- a/pandora/item/management/commands/get_frame.py +++ b/pandora/item/management/commands/get_frame.py @@ -4,6 +4,7 @@ from django.core.management.base import BaseCommand from django.conf import settings from django.db import transaction +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models diff --git a/pandora/item/management/commands/rebuild_filter.py b/pandora/item/management/commands/rebuild_filter.py index 8beaa7c9..eb52b13b 100644 --- a/pandora/item/management/commands/rebuild_filter.py +++ b/pandora/item/management/commands/rebuild_filter.py @@ -6,6 +6,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models import clip.models diff --git a/pandora/item/management/commands/rebuild_find.py b/pandora/item/management/commands/rebuild_find.py index 7681682d..8418fc2f 100644 --- a/pandora/item/management/commands/rebuild_find.py +++ b/pandora/item/management/commands/rebuild_find.py @@ -5,6 +5,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models import clip.models diff --git a/pandora/item/management/commands/rebuild_indexes.py b/pandora/item/management/commands/rebuild_indexes.py index fb197f4c..5ad61971 100644 --- a/pandora/item/management/commands/rebuild_indexes.py +++ b/pandora/item/management/commands/rebuild_indexes.py @@ -5,6 +5,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models import clip.models diff --git a/pandora/item/management/commands/rebuild_posters.py b/pandora/item/management/commands/rebuild_posters.py deleted file mode 100644 index d22e4882..00000000 --- a/pandora/item/management/commands/rebuild_posters.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- - -import os -from glob import glob - -from django.core.management.base import BaseCommand - -import app.monkey_patch -from ... import models -from ... import tasks - -class Command(BaseCommand): - """ - rebuild posters for all items. - """ - help = 'rebuild all posters for all items.' - args = '' - - def handle(self, **options): - offset = 0 - chunk = 100 - count = models.Item.objects.count() - while offset <= count: - for i in models.Item.objects.all().order_by('id')[offset:offset+chunk]: - print(i) - if i.poster: - i.poster.delete() - i.make_poster() - offset += chunk diff --git a/pandora/item/management/commands/rebuild_sort.py b/pandora/item/management/commands/rebuild_sort.py index fbcc7d96..5e29ade8 100644 --- a/pandora/item/management/commands/rebuild_sort.py +++ b/pandora/item/management/commands/rebuild_sort.py @@ -6,6 +6,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models diff --git a/pandora/item/management/commands/sqlfindindex.py b/pandora/item/management/commands/sqlfindindex.py index 4348f6cb..81c39488 100644 --- a/pandora/item/management/commands/sqlfindindex.py +++ b/pandora/item/management/commands/sqlfindindex.py @@ -5,6 +5,7 @@ from django.core.management.base import BaseCommand from django.db import connection, transaction from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models diff --git a/pandora/item/management/commands/sync_itemsort.py b/pandora/item/management/commands/sync_itemsort.py index bc34e949..4640229d 100644 --- a/pandora/item/management/commands/sync_itemsort.py +++ b/pandora/item/management/commands/sync_itemsort.py @@ -5,6 +5,7 @@ from django.db import connection, transaction from django.db.models import fields from django.conf import settings +settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models import clip.models diff --git a/pandora/item/models.py b/pandora/item/models.py index 04ec81dd..1733e896 100644 --- a/pandora/item/models.py +++ b/pandora/item/models.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import json -import logging import os import re import shutil @@ -43,7 +42,6 @@ from user.utils import update_groups from user.models import Group import archive.models -logger = logging.getLogger(__name__) User = get_user_model() @@ -857,7 +855,7 @@ class Item(models.Model): values = list(set(values)) else: values = self.get(key, '') - if values and isinstance(values, list) and isinstance(values[0], str): + if isinstance(values, list): save(key, '\n'.join(values)) else: save(key, values) @@ -1024,7 +1022,7 @@ class Item(models.Model): elif sort_type == 'string': value = self.get(source, '') if isinstance(value, list): - value = ','.join([str(v) for v in value]) + value = ','.join(value) value = utils.sort_string(value)[:955] set_value(s, name, value) elif sort_type == 'words': @@ -1101,11 +1099,7 @@ class Item(models.Model): _current_values.append(value[0]) current_values = _current_values - try: - current_values = list(set(current_values)) - except: - logger.error('invalid facet data for %s: %s', key, current_values) - current_values = [] + current_values = list(set(current_values)) current_values = [ox.decode_html(ox.strip_tags(v)) for v in current_values] current_values = [unicodedata.normalize('NFKD', v) for v in current_values] self.update_facet_values(key, current_values) diff --git a/pandora/item/tasks.py b/pandora/item/tasks.py index a7c0c68a..27511acc 100644 --- a/pandora/item/tasks.py +++ b/pandora/item/tasks.py @@ -5,7 +5,6 @@ from urllib.parse import quote import gzip import os import random -import logging from celery.task import task, periodic_task from django.conf import settings @@ -17,9 +16,6 @@ from app.utils import limit_rate from taskqueue.models import Task -logger = logging.getLogger(__name__) - - @periodic_task(run_every=timedelta(days=1), queue='encoding') def cronjob(**kwargs): if limit_rate('item.tasks.cronjob', 8 * 60 * 60): @@ -354,18 +350,3 @@ def update_sitemap(base_url): f.write(data) with gzip.open(sitemap, 'wb') as f: f.write(data) - - -@task(queue='default') -def bulk_edit(data, username): - from django.db import transaction - from . import models - from .views import edit_item - user = models.User.objects.get(username=username) - items = models.Item.objects.filter(public_id__in=data['id']) - for item in items: - if item.editable(user): - with transaction.atomic(): - item.refresh_from_db() - response = edit_item(user, item, data) - return {} diff --git a/pandora/item/views.py b/pandora/item/views.py index 62c6b21a..23fadc29 100644 --- a/pandora/item/views.py +++ b/pandora/item/views.py @@ -533,18 +533,17 @@ def get(request, data): return render_to_json_response(response) actions.register(get) -def edit_item(user, item, data): - data = data.copy() +def edit_item(request, item, data): update_clips = False response = json_response(status=200, text='ok') if 'rightslevel' in data: - if user.profile.capability('canEditRightsLevel'): + if request.user.profile.capability('canEditRightsLevel'): item.level = int(data['rightslevel']) else: response = json_response(status=403, text='permission denied') del data['rightslevel'] if 'user' in data: - if user.profile.get_level() in ('admin', 'staff') and \ + if request.user.profile.get_level() in ('admin', 'staff') and \ models.User.objects.filter(username=data['user']).exists(): new_user = models.User.objects.get(username=data['user']) if new_user != item.user: @@ -552,10 +551,10 @@ def edit_item(user, item, data): update_clips = True del data['user'] if 'groups' in data: - if not user.profile.capability('canManageUsers'): + if not request.user.profile.capability('canManageUsers'): # Users wihtout canManageUsers can only add/remove groups they are not in groups = set([g.name for g in item.groups.all()]) - user_groups = set([g.name for g in user.groups.all()]) + user_groups = set([g.name for g in request.user.groups.all()]) other_groups = list(groups - user_groups) data['groups'] = [g for g in data['groups'] if g in user_groups] + other_groups r = item.edit(data) @@ -598,7 +597,7 @@ def add(request, data): i.make_poster() del data['title'] if data: - response = edit_item(request.user, item, data) + response = edit_item(request, item, data) response['data'] = item.json() add_changelog(request, request_data, item.public_id) return render_to_json_response(response) @@ -620,16 +619,16 @@ def edit(request, data): see: add, find, get, lookup, remove, upload ''' if isinstance(data['id'], list): - add_changelog(request, data) - t = tasks.bulk_edit.delay(data, request.user.username) - response = json_response(status=200, text='ok') - response['data']['taskId'] = t.task_id + items = models.Item.objects.filter(public_id__in=data['id']) else: - item = get_object_or_404_json(models.Item, public_id=data['id']) + items = [get_object_or_404_json(models.Item, public_id=data['id'])] + for item in items: if item.editable(request.user): - add_changelog(request, data) - response = edit_item(request.user, item, data) + request_data = data.copy() + response = edit_item(request, item, data) response['data'] = item.json() + if item == items[0]: + add_changelog(request, request_data) else: response = json_response(status=403, text='permission denied') return render_to_json_response(response) @@ -1030,10 +1029,7 @@ def download(request, id, resolution=None, format='webm', part=None): return HttpResponseForbidden() elif r is True: response = HttpResponse(FileWrapper(video), content_type=content_type) - try: - response['Content-Length'] = os.path.getsize(video.name) - except: - pass + response['Content-Length'] = os.path.getsize(video.name) else: response = HttpFileResponse(r, content_type=content_type) else: diff --git a/pandora/manage.py b/pandora/manage.py index 4800a366..700a1802 100755 --- a/pandora/manage.py +++ b/pandora/manage.py @@ -73,3 +73,5 @@ if __name__ == "__main__": sys.stderr.write("Error: Can't find '%s'.\nBefore you run pan.do/ra you must create it\n" % settings.SITE_CONFIG) sys.exit(1) execute_from_command_line(sys.argv) + import app.config + app.config.shutdown() diff --git a/pandora/settings.py b/pandora/settings.py index b2596015..99eda0ba 100644 --- a/pandora/settings.py +++ b/pandora/settings.py @@ -220,6 +220,7 @@ XACCELREDIRECT = False SITE_CONFIG = join(PROJECT_ROOT, 'config.jsonc') DEFAULT_CONFIG = join(PROJECT_ROOT, 'config.pandora.jsonc') +RELOAD_CONFIG = False #used if CONFIG['canDownloadVideo'] is set TRACKER_URL = "udp://tracker.openbittorrent.com:80" @@ -274,6 +275,7 @@ SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') DATA_UPLOAD_MAX_MEMORY_SIZE = 32 * 1024 * 1024 +RELOADER_RUNNING = False #you can ignore things below this line #========================================================================= LOCAL_APPS = [] diff --git a/pandora/user/utils.py b/pandora/user/utils.py index 5328a464..49fa7884 100644 --- a/pandora/user/utils.py +++ b/pandora/user/utils.py @@ -22,7 +22,7 @@ def get_location(ip): else: try: location = g.city(ip) - except: + except GeoIP2Exception: try: location = g.country(s.ip) except: diff --git a/pandora/websocket/worker.py b/pandora/websocket/worker.py index 9a3d7bd4..1a0e633d 100644 --- a/pandora/websocket/worker.py +++ b/pandora/websocket/worker.py @@ -24,7 +24,7 @@ class Worker(ConsumerMixin): def process_task(self, body, message): try: - if isinstance(body, dict) and body.get('task') == 'trigger_event': + if body['task'] == 'trigger_event': daemon.trigger_event(*body['args']) except: logger.error('faild to trigger event %s', body, exc_info=True) diff --git a/requirements.txt b/requirements.txt index b03274a2..7f286c46 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -Django==3.0.10 +Django==3.0.6 simplejson chardet celery<5.0,>4.3 @@ -6,11 +6,10 @@ django-celery-results django-extensions==2.2.9 gunicorn==20.0.4 html5lib -requests<3.0.0,>=2.24.0 -urllib3<2.0.0,>=1.25.2 +requests==2.23.0 tornado<5 -geoip2==4.1.0 -youtube-dl>=2021.4.26 +geoip2==3.0.0 +youtube-dl>=2020.5.8 python-memcached elasticsearch future diff --git a/static/js/addFilesDialog.js b/static/js/addFilesDialog.js index 4bfa0a71..2a4e023c 100644 --- a/static/js/addFilesDialog.js +++ b/static/js/addFilesDialog.js @@ -106,7 +106,7 @@ pandora.ui.addFilesDialog = function(options) { }); var selectItems = []; - if (pandora.user.ui.item && options.editable) { + if (!pandora.site.itemRequiresVideo && pandora.user.ui.item) { selectItems.push({ id: 'add', title: Ox._( @@ -114,23 +114,31 @@ pandora.ui.addFilesDialog = function(options) { [pandora.site.itemName.singular.toLowerCase()] ) }); - } - if (options.items.length > 1) { selectItems.push({ - id: 'multiple', + id: 'one', title: Ox._( - 'Create multiple {0}', - [pandora.site.itemName.plural.toLowerCase()] + options.items.length > 1 ? 'Create new {0} with multiple parts' : 'Create new {0}', + [pandora.site.itemName.singular.toLowerCase()] + ) + }); + } else { + if (options.items.length > 1) { + selectItems.push({ + id: 'multiple', + title: Ox._( + 'Create multiple {0}', + [pandora.site.itemName.plural.toLowerCase()] + ) + }); + } + selectItems.push({ + id: 'one', + title: Ox._( + 'Create one {0} with multiple parts', + [pandora.site.itemName.singular.toLowerCase()] ) }); } - selectItems.push({ - id: 'one', - title: Ox._( - options.items.length > 1 ? 'Create new {0} with multiple parts' : 'Create new {0}', - [pandora.site.itemName.singular.toLowerCase()] - ) - }); var $select = Ox.Select({ items: selectItems, width: 256 @@ -216,7 +224,6 @@ pandora.ui.addFilesDialog = function(options) { ), function(result) { pandora.api.addMediaUrl({ url: item.url, - referer: item.referer, item: id }, callback); }); diff --git a/static/js/addItemDialog.js b/static/js/addItemDialog.js index 238a7d6e..d41a9ed3 100644 --- a/static/js/addItemDialog.js +++ b/static/js/addItemDialog.js @@ -222,8 +222,7 @@ pandora.ui.addItemDialog = function(options) { } return value; }); - values.url = info.url; - values.referer = info.referer; + values.url= info.url; return Ox.extend(info, values); } @@ -271,16 +270,10 @@ pandora.ui.addItemDialog = function(options) { } else { $screen.stop(); that.close(); - (pandora.user.ui.item ? pandora.api.get : Ox.noop)({ - id: pandora.user.ui.item, - keys: ['editable'] - }, function(result) { - pandora.ui.addFilesDialog({ - action: selected, - items: items, - editable: pandora.user.ui.item && result.data.editable - }).open(); - }) + pandora.ui.addFilesDialog({ + action: selected, + items: items + }).open(); } }) } diff --git a/static/js/addRemoveKeyDialog.js b/static/js/addRemoveKeyDialog.js deleted file mode 100644 index 107d55bc..00000000 --- a/static/js/addRemoveKeyDialog.js +++ /dev/null @@ -1,124 +0,0 @@ - -pandora.ui.addRemoveKeyDialog = function(options) { - var item = Ox.getObjectById(pandora.site.documentKeys, options.key), - itemTitle = Ox._(item ? item.title : options.key), - dialogTitle = Ox._('Add/Remove {0}', [itemTitle]); - - return Ox.Element('') - .addClass('OxLight') - .html(' [+]') - .css({ - cursor: 'pointer', - }) - .options({ - tooltip: dialogTitle - }) - .on('click', function(event) { - var add, remove, - dialog = Ox.Dialog({ - buttons: [ - Ox.Button({ - title: Ox._('Cancel') - }) - .css({margin: '4px 4px 4px 0'}) - .bindEvent({ - click: function() { - dialog.close() - } - }), - Ox.Button({ - title: Ox._('Update'), - width: 52 - }).bindEvent({ - click: function() { - var addValue = add.value() - var removeValue = remove.value() - if (!addValue.length && !removeValue.length) { - dialog.close() - return - } - var $loading = Ox.LoadingScreen({ - width: 256, - height: 64 - }) - dialog.options({ - content: $loading.start() - }) - var ids = options.ids; - pandora.api[{ - 'items': 'find', - 'documents': 'findDocuments', - }[options.section]]({ - query: { - conditions: [{key: 'id', operator: '&', value: ids}] - }, - range: [0, ids.length], - keys: ['id', options.key] - - }, function(result) { - Ox.serialForEach(result.data.items, - function(item, index, items, callback) { - var changed = false - var value = item[options.key] || [] - if (addValue.length && !Ox.contains(value, addValue)) { - value.push(addValue) - changed = true - } - if (removeValue.length && Ox.contains(value, removeValue)) { - value = value.filter(function(v) { return v != removeValue; } ) - changed = true - } - if (changed) { - var edit = {id: item.id} - edit[options.key] = value - pandora.api[{ - 'items': 'edit', - 'documents': 'editDocument', - }[options.section]](edit, function(response) { - callback() - }) - } else { - callback() - } - }, - function() { - $loading.stop() - dialog.close() - } - ) - }) - } - }) - ], - closeButton: true, - content: Ox.Element() - .css({ - padding: '8px' - }) - .append( - add = Ox.Input({ - width: 240, - type: 'input', - label: 'Add' - }) - ) - .append( - Ox.Element().html('').css({ - height: '8px' - }) - ) - .append( - remove = Ox.Input({ - width: 240, - type: 'input', - label: 'Remove' - }) - ), - height: 64, - removeOnClose: true, - title: dialogTitle, - width: 256 - }).open(); - }) - -} diff --git a/static/js/collection.js b/static/js/collection.js index 5b188f7f..51017b50 100644 --- a/static/js/collection.js +++ b/static/js/collection.js @@ -13,6 +13,20 @@ pandora.ui.collection = function() { if (view == 'list') { that = Ox.TableList({ + draggable: true, + keys: keys, + items: function(data, callback) { + pandora.api.findDocuments(Ox.extend(data, { + query: ui.findDocuments + }), callback); + return Ox.clone(data, true); + }, + selected: ui.collectionSelection, + sort: ui.collectionSort.concat([ + {key: 'extension', operator: '+'}, + {key: 'title', operator: '+'} + ]), + unique: 'id', columns: pandora.site.documentSortKeys.filter(function(key) { return !key.capability || pandora.hasCapability(key.capability); @@ -26,11 +40,7 @@ pandora.ui.collection = function() { defaultWidth: key.columnWidth, format: (function() { return function(value, data) { - var value = pandora.formatDocumentKey(key, data); - if (Ox.isArray(value)) { - value = value.join(', '); - } - return value; + return pandora.formatDocumentKey(key, data); } })(), id: key.id, @@ -44,25 +54,7 @@ pandora.ui.collection = function() { }; }), columnsVisible: true, - columnsMovable: true, - columnsRemovable: true, - columnsResizable: true, - columnsVisible: true, - draggable: true, - items: function(data, callback) { - pandora.api.findDocuments(Ox.extend(data, { - query: ui.findDocuments - }), callback); - return Ox.clone(data, true); - }, - keys: keys, scrollbarVisible: true, - selected: ui.collectionSelection, - sort: ui.collectionSort.concat([ - {key: 'extension', operator: '+'}, - {key: 'title', operator: '+'} - ]), - unique: 'id', }) .bindEvent({ columnchange: function(data) { diff --git a/static/js/documentInfoView.js b/static/js/documentInfoView.js index bb69563e..4e40a84e 100644 --- a/static/js/documentInfoView.js +++ b/static/js/documentInfoView.js @@ -218,7 +218,6 @@ pandora.ui.documentInfoView = function(data, isMixed) { .append( Ox.EditableContent({ editable: canEdit, - placeholder: formatLight(Ox._( isMixed.title ? 'Mixed title' : 'Untitled')), tooltip: canEdit ? pandora.getEditTooltip() : '', value: data.title || '' }) @@ -572,13 +571,6 @@ pandora.ui.documentInfoView = function(data, isMixed) { } }) .appendTo($element); - if (isMixed[key] && Ox.contains(listKeys, key)) { - pandora.ui.addRemoveKeyDialog({ - ids: ui.collectionSelection, - key: key, - section: ui.section - }).appendTo($element) - } } }); $element.appendTo($text); diff --git a/static/js/documentsPanel.js b/static/js/documentsPanel.js index 2337352b..e1663aba 100644 --- a/static/js/documentsPanel.js +++ b/static/js/documentsPanel.js @@ -810,8 +810,9 @@ pandora.ui.documentsPanel = function(options) { item: function(data, sort, size) { var sortKey = sort[0].key, infoKey = sortKey == 'title' ? 'extension' : sortKey, - key = Ox.getObjectById(pandora.site.documentKeys, infoKey), - info = pandora.formatDocumentKey(key, data, size), + info = ( + Ox.getObjectById(pandora.site.documentKeys, infoKey).format || Ox.identity + )(data[infoKey]), size = size || 128; return { height: Math.round(data.ratio > 1 ? size / data.ratio : size), diff --git a/static/js/editDialog.js b/static/js/editDialog.js index 8e646d97..f35747c0 100644 --- a/static/js/editDialog.js +++ b/static/js/editDialog.js @@ -4,12 +4,14 @@ pandora.ui.editDialog = function() { var ui = pandora.user.ui, hasChanged = false, - ids = ui.listSelection, - keys = ['editable'].concat(pandora.site.itemKeys.filter(function(key) { + ids = ui.listSelection.filter(function(id) { + return pandora.$ui.list.value(id, 'editable'); + }), + keys = pandora.site.itemKeys.filter(function(key) { return key.id != '*' }).map(function(key) { return key.id - })), + }), listKeys = pandora.site.itemKeys.filter(function(key) { return Ox.isArray(key.type); }).map(function(key){ @@ -84,51 +86,26 @@ pandora.ui.editDialog = function() { } ], operator: '&' - }, - range: [0, ids.length] + } }, function(result) { var data = {}, isMixed = {}, - updateTitle = false, - items = result.data.items.filter(function(item) { - if (!item.editable) { - updateTitle = true - } - return item.editable; - }); - - if (updateTitle) { - that.options({ - title: Ox._('Edit Metadata for {0}', [ - Ox.formatNumber(items.length) + ' ' + Ox._( - items.length == 1 ? pandora.site.itemName.singular : pandora.site.itemName.plural - ) - ]) - }) - // no editable items - if (!items.length) { - that.close() - return - } - } - keys.filter(function(key) { - return key != 'editable' - }).forEach(function(key) { + items = result.data.items; + keys.forEach(function(key) { var isArray = Ox.contains(listKeys, key), values = items.map(function(item) { return item[key]; }); if (isArray) { values = values.map(function(value) { - value = value || [] - return value.join ? value.join(separator) : value; + return (value || []).join(separator); }); } if (Ox.unique(values).length > 1) { isMixed[key] = true; } data[key] = isMixed[key] ? null - : isArray && values.length ? values[0].split(separator) + : isArray ? values[0].split(separator) : values[0]; }); that.options({ diff --git a/static/js/editDocumentsDialog.js b/static/js/editDocumentsDialog.js index 97b329ff..620cc153 100644 --- a/static/js/editDocumentsDialog.js +++ b/static/js/editDocumentsDialog.js @@ -3,12 +3,14 @@ pandora.ui.editDocumentsDialog = function() { var ui = pandora.user.ui, hasChanged = false, - ids = ui.collectionSelection, - keys = ['editable'].concat(pandora.site.documentKeys.filter(function(key) { + ids = ui.collectionSelection.filter(function(id) { + return pandora.$ui.list.value(id, 'editable'); + }), + keys = pandora.site.documentKeys.filter(function(key) { return key.id != '*' }).map(function(key) { return key.id - })), + }), listKeys = pandora.site.documentKeys.filter(function(key) { return Ox.isArray(key.type); }).map(function(key){ @@ -83,36 +85,12 @@ pandora.ui.editDocumentsDialog = function() { } ], operator: '&' - }, - range: [0, ids.length] + } }, function(result) { var data = {}, isMixed = {}, - updateTitle = false, - items = result.data.items.filter(function(item) { - if (!item.editable) { - updateTitle = true - } - return item.editable; - }); - if (updateTitle) { - that.options({ - title: Ox._('Edit Metadata for {0}', [ - Ox.formatNumber(items.length) + ' ' + Ox._( - items.length == 1 ? 'Document' : 'Documents' - ) - ]) - }) - // no editable items - if (!items.length) { - that.close() - return - } - } - - keys.filter(function(key) { - return key != 'editable' - }).forEach(function(key) { + items = result.data.items; + keys.forEach(function(key) { var isArray = Ox.contains(listKeys, key), values = items.map(function(item) { return item[key]; diff --git a/static/js/editor.js b/static/js/editor.js index 28d3b5ba..3d53d89a 100644 --- a/static/js/editor.js +++ b/static/js/editor.js @@ -205,9 +205,9 @@ pandora.ui.editor = function(data) { }).open(); }, editannotation: function(data) { - Ox.Log('', 'editAnnotation', data.id, data); + Ox.Log('', 'editAnnotation', data); function callback(result) { - Ox.Log('', 'editAnnotation result', result.data.id, result); + Ox.Log('', 'editAnnotation result', result); if (!Ox.isEmpty(result.data)) { result.data.date = Ox.formatDate( result.data.modified.slice(0, 10), '%B %e, %Y' @@ -222,56 +222,21 @@ pandora.ui.editor = function(data) { pandora.UI.set('videoPoints.' + ui.item + '.annotation', result.data.id.split('/')[1] || ''); Ox.Request.clearCache(); }; - var edit = { - 'in': data['in'], - out: data.out, - value: data.value - } if (data.id[0] == '_') { - edit.item = ui.item; - edit.layer = data.layer; - - if (queue[data.id]) { - queue[data.id].push(edit); - } else { - queue[data.id] = []; - pandora.api.addAnnotation(edit, function(result) { - callback(result); - var id = result.data.id, - pending = queue[id]; - delete queue[id]; - pending && pending.length && Ox.serialForEach(pending, function(edit, index, array, callback) { - edit.id = id - Ox.Log('', 'process pending editAnnotation request', id, edit); - pandora.api.editAnnotation(edit, function(result) { - callback(); - }) - }, function() { - Ox.Request.clearCache(); - }); - }); - } + pandora.api.addAnnotation({ + 'in': data['in'], + item: ui.item, + layer: data.layer, + out: data.out, + value: data.value + }, callback); } else { - edit.id = data.id; - if (queue[data.id]) { - queue[data.id].push(edit); - } else { - queue[data.id] = []; - pandora.api.editAnnotation(edit, function(result) { - callback(result); - var pending = queue[edit.id]; - delete queue[edit.id]; - pending && pending.length && Ox.serialForEach(pending, function(edit, index, array, cb) { - Ox.Log('', 'process pending editAnnotation request', edit.id, edit); - pandora.api.editAnnotation(edit, function(result) { - callback(result); - cb(); - }) - }, function() { - Ox.Request.clearCache(); - }); - }); - } + pandora.api.editAnnotation({ + id: data.id, + 'in': data['in'], + out: data.out, + value: data.value + }, callback); } }, embedselection: function() { @@ -422,8 +387,7 @@ pandora.ui.editor = function(data) { pandora_videotimeline: function(data) { that.options({timeline: data.value}); } - }), - queue = []; + }); pandora._dontSelectResult = false; diff --git a/static/js/importAnnotationsDialog.js b/static/js/importAnnotationsDialog.js index 13e83118..559a8fa7 100644 --- a/static/js/importAnnotationsDialog.js +++ b/static/js/importAnnotationsDialog.js @@ -5,6 +5,7 @@ pandora.ui.importAnnotationsDialog = function(options) { var layers = pandora.site.layers.filter(function(layer) { return layer.canAddAnnotations[pandora.user.level]; }), + languages = Ox.sortBy(Ox.LANGUAGES.map(function(language) { return {id: language.code, title: language.name}; }), 'title'), @@ -12,12 +13,7 @@ pandora.ui.importAnnotationsDialog = function(options) { $content = Ox.Element().css({margin: '16px'}), $layerSelect = Ox.Select({ - items: [{ - id: '', - type: '', - title: Ox._('Select Layer...'), - disabled: true, - }].concat(layers), + items: layers, label: Ox._('Layer'), labelWidth: 128, width: 384 @@ -26,12 +22,7 @@ pandora.ui.importAnnotationsDialog = function(options) { marginTop: '16px' }) .bindEvent({ - change: function(data) { - updateLanguageSelect() - that[ - (data.value.length && $fileInput.value().length) ? 'enableButton' : 'disableButton' - ]('import'); - } + change: updateLanguageSelect }) .appendTo($content), @@ -81,16 +72,13 @@ pandora.ui.importAnnotationsDialog = function(options) { var format = Ox.last(data.value[0].name.split('.')); $formatSelect.options({value: format}); var subtitlesLayer = pandora.getSubtitlesLayer() - if ( - subtitlesLayer && !$layerSelect.value().length && - format == 'srt' && Ox.getObjectById(layers, subtitlesLayer) - ) { + if (subtitlesLayer && format == 'srt' && Ox.getObjectById(layers, subtitlesLayer)) { $layerSelect.options({value: subtitlesLayer}) } updateLanguageSelect(); } that[ - (data.value.length && $layerSelect.value().length) ? 'enableButton' : 'disableButton' + data.value.length ? 'enableButton' : 'disableButton' ]('import'); } }) @@ -238,10 +226,9 @@ pandora.ui.importAnnotationsDialog = function(options) { } function updateLanguageSelect() { - var layer = $layerSelect.value(), - layerType = layer.length ? Ox.getObjectById( - pandora.site.layers, layer, - ).type : ''; + var layerType = Ox.getObjectById( + pandora.site.layers, $layerSelect.value() + ).type; if (layerType != 'text') { $languageSelect.value(pandora.site.language); } diff --git a/static/js/importMediaDialog.js b/static/js/importMediaDialog.js index 419aeb4e..05bfff24 100644 --- a/static/js/importMediaDialog.js +++ b/static/js/importMediaDialog.js @@ -132,7 +132,6 @@ pandora.ui.importMediaDialog = function(options) { pandora.api.edit(edit, function(result) { pandora.api.addMediaUrl({ url: info.url, - referer: info.referer, item: edit.id }, function(result) { if (result.data.taskId) { diff --git a/static/js/infoView.js b/static/js/infoView.js index f094f947..6e68a95a 100644 --- a/static/js/infoView.js +++ b/static/js/infoView.js @@ -198,7 +198,9 @@ pandora.ui.infoView = function(data, isMixed) { top: margin + 'px', right: margin + 'px' }) - .appendTo($info); + .appendTo($info), + + $capabilities; [$options, $edit].forEach(function($element) { $element.find('input').css({ @@ -228,7 +230,6 @@ pandora.ui.infoView = function(data, isMixed) { Ox.EditableContent({ editable: canEdit, tooltip: canEdit ? pandora.getEditTooltip() : '', - placeholder: formatLight(Ox._( isMixed.title ? 'Mixed title' : 'Untitled')), value: data.title || '' }) .css({ @@ -345,7 +346,7 @@ pandora.ui.infoView = function(data, isMixed) { .append(formatKey('Rights Level', 'statistics')) .append($rightsLevel) .appendTo($statistics); - pandora.renderRightsLevel(that, $rightsLevel, data, isMixed, isMultiple, canEdit); + renderRightsLevel(); // Notes -------------------------------------------------------------------- @@ -495,6 +496,15 @@ pandora.ui.infoView = function(data, isMixed) { return ret; } + function getRightsLevelElement(rightsLevel) { + return Ox.Theme.formatColorLevel( + rightsLevel, + pandora.site.rightsLevels.map(function(rightsLevel) { + return rightsLevel.name; + }) + ); + } + function getValue(key, value) { return !value ? '' : Ox.contains(specialListKeys, key) ? value.join('; ') @@ -502,6 +512,81 @@ pandora.ui.infoView = function(data, isMixed) { : value; } + function renderCapabilities(rightsLevel) { + var capabilities = [].concat( + canEdit ? [{name: 'canSeeItem', symbol: 'Find'}] : [], + [ + {name: 'canPlayClips', symbol: 'PlayInToOut'}, + {name: 'canPlayVideo', symbol: 'Play'}, + {name: 'canDownloadVideo', symbol: 'Download'} + ] + ), + userLevels = canEdit ? pandora.site.userLevels : [pandora.user.level]; + $capabilities.empty(); + userLevels.forEach(function(userLevel, i) { + var $element, + $line = $('
') + .css({ + height: '16px', + marginBottom: '4px' + }) + .appendTo($capabilities); + if (canEdit) { + $element = Ox.Theme.formatColorLevel(i, userLevels.map(function(userLevel) { + return Ox.toTitleCase(userLevel); + }), [0, 240]); + Ox.Label({ + textAlign: 'center', + title: Ox.toTitleCase(userLevel), + width: 60 + }) + .addClass('OxColor OxColorGradient') + .css({ + float: 'left', + height: '12px', + paddingTop: '2px', + background: $element.css('background'), + fontSize: '8px', + color: $element.css('color') + }) + .data({OxColor: $element.data('OxColor')}) + .appendTo($line); + } + capabilities.forEach(function(capability) { + var hasCapability = pandora.hasCapability(capability.name, userLevel) >= rightsLevel, + $element = Ox.Theme.formatColorLevel(hasCapability, ['', '']); + Ox.Button({ + tooltip: (canEdit ? Ox.toTitleCase(userLevel) : 'You') + ' ' + + (hasCapability ? 'can' : 'can\'t') + ' ' + + Ox.toSlashes(capability.name) + .split('/').slice(1).join(' ') + .toLowerCase(), + title: capability.symbol, + type: 'image' + }) + .addClass('OxColor OxColorGradient') + .css({background: $element.css('background')}) + .css('margin' + (canEdit ? 'Left' : 'Right'), '4px') + .data({OxColor: $element.data('OxColor')}) + .appendTo($line); + }); + if (!canEdit) { + Ox.Button({ + title: Ox._('Help'), + tooltip: Ox._('About Rights'), + type: 'image' + }) + .css({marginLeft: '52px'}) + .bindEvent({ + click: function() { + pandora.UI.set({page: 'rights'}); + } + }) + .appendTo($line); + } + }); + } + function renderGroup(keys) { var $element; keys.forEach(function(key) { displayedKeys.push(key) }); @@ -530,13 +615,6 @@ pandora.ui.infoView = function(data, isMixed) { } }) .appendTo($element); - if (isMixed[key] && Ox.contains(listKeys, key)) { - pandora.ui.addRemoveKeyDialog({ - ids: ui.listSelection, - key: key, - section: ui.section - }).appendTo($element) - } } }); $element.appendTo($text); @@ -554,6 +632,53 @@ pandora.ui.infoView = function(data, isMixed) { } } + function renderRightsLevel() { + var $rightsLevelElement = getRightsLevelElement(data.rightslevel), + $rightsLevelSelect; + $rightsLevel.empty(); + if (canEdit) { + $rightsLevelSelect = Ox.Select({ + items: pandora.site.rightsLevels.map(function(rightsLevel, i) { + return {id: i, title: rightsLevel.name}; + }), + width: 128, + value: data.rightslevel + }) + .addClass('OxColor OxColorGradient') + .css({ + marginBottom: '4px', + background: $rightsLevelElement.css('background') + }) + .data({OxColor: $rightsLevelElement.data('OxColor')}) + .bindEvent({ + change: function(event) { + var rightsLevel = event.value; + $rightsLevelElement = getRightsLevelElement(rightsLevel); + $rightsLevelSelect + .css({background: $rightsLevelElement.css('background')}) + .data({OxColor: $rightsLevelElement.data('OxColor')}) + renderCapabilities(rightsLevel); + var edit = { + id: isMultiple ? ui.listSelection : data.id, + rightslevel: rightsLevel + }; + pandora.api.edit(edit, function(result) { + that.triggerEvent('change', Ox.extend({}, 'rightslevel', rightsLevel)); + }); + } + }) + .appendTo($rightsLevel); + } else { + $rightsLevelElement + .css({ + marginBottom: '4px' + }) + .appendTo($rightsLevel); + } + $capabilities = $('
').appendTo($rightsLevel); + renderCapabilities(data.rightslevel); + } + function toggleIconSize() { iconSize = iconSize == 256 ? 512 : 256; iconWidth = iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio); diff --git a/static/js/infoView.padma.js b/static/js/infoView.padma.js index e5e894d0..93125b48 100644 --- a/static/js/infoView.padma.js +++ b/static/js/infoView.padma.js @@ -44,12 +44,6 @@ pandora.ui.infoView = function(data, isMixed) { $options = Ox.MenuButton({ items: [ - { - id: 'toggle', - title: Ox._('Toggle {0} size...', [ - Ox._(ui.icons == 'posters' ? 'poster' : 'icon') - ]), - }, { id: 'delete', title: Ox._('Delete {0}...', [pandora.site.itemName.singular]), @@ -68,9 +62,7 @@ pandora.ui.infoView = function(data, isMixed) { }) .bindEvent({ click: function(data_) { - if (data_.id == 'toggle') { - toggleIconSize() - } else if (data_.id == 'delete') { + if (data_.id == 'delete') { pandora.$ui.deleteItemsDialog = pandora.ui.deleteItemsDialog({ items: [data] }).open(); @@ -212,7 +204,9 @@ pandora.ui.infoView = function(data, isMixed) { top: margin + 'px', right: margin + 'px' }) - .appendTo($info); + .appendTo($info), + + $capabilities; [$options, $edit].forEach(function($element) { $element.find('input').css({ @@ -443,7 +437,7 @@ pandora.ui.infoView = function(data, isMixed) { .append(formatKey(Ox._('Rights Level'), 'statistics')) .append($rightsLevel) .appendTo($statistics); - pandora.renderRightsLevel(that, $rightsLevel, data, isMixed, isMultiple, canEdit); + renderRightsLevel(); // User and Groups --------------------------------------------------------- if (!isMultiple) { @@ -634,12 +628,100 @@ pandora.ui.infoView = function(data, isMixed) { return formatLink(key, ret, key == 'date' && value); } + function getRightsLevelElement(rightsLevel) { + return Ox.Theme.formatColorLevel( + rightsLevel, + pandora.site.rightsLevels.map(function(rightsLevel) { + return rightsLevel.name; + }) + ); + } + function getValue(key, value) { return !value ? '' : Ox.contains(listKeys, key) ? value.join(', ') : value; } + function renderCapabilities(rightsLevel) { + var capabilities = [].concat( + canEdit ? [{name: 'canSeeItem', symbol: 'Find'}] : [], + [ + {name: 'canPlayClips', symbol: 'PlayInToOut'}, + {name: 'canPlayVideo', symbol: 'Play'}, + {name: 'canDownloadVideo', symbol: 'Download'} + ] + ), + userLevels = canEdit ? pandora.site.userLevels : [pandora.user.level]; + $capabilities.empty(); + userLevels.forEach(function(userLevel, i) { + var $element, + $line = $('
') + .css({ + height: '16px', + marginBottom: '4px' + }) + .appendTo($capabilities); + if (canEdit) { + $element = Ox.Theme.formatColorLevel(i, userLevels.map(function(userLevel) { + return Ox.toTitleCase(userLevel); + }), [0, 240]); + Ox.Label({ + textAlign: 'center', + title: Ox._(Ox.toTitleCase(userLevel)), + width: 60 + }) + .addClass('OxColor OxColorGradient') + .css({ + float: 'left', + height: '12px', + paddingTop: '2px', + background: $element.css('background'), + fontSize: '8px', + color: $element.css('color') + }) + .data({OxColor: $element.data('OxColor')}) + .appendTo($line); + } + capabilities.forEach(function(capability) { + var hasCapability = pandora.hasCapability(capability.name, userLevel) >= rightsLevel, + $element = Ox.Theme.formatColorLevel(hasCapability, ['', '']); + Ox.Button({ + tooltip: Ox._('{0} ' + + (hasCapability ? 'can' : 'can\'t') + ' ' + + Ox.toSlashes(capability.name) + .split('/').slice(1).join(' ') + .toLowerCase() + .replace('see item', 'see the item') + .replace('play video', 'play the full video') + .replace('download video', 'download the video'), + [canEdit ? Ox._(Ox.toTitleCase(userLevel)) : Ox._('You')]), + title: capability.symbol, + type: 'image' + }) + .addClass('OxColor OxColorGradient') + .css({background: $element.css('background')}) + .css('margin' + (canEdit ? 'Left' : 'Right'), '4px') + .data({OxColor: $element.data('OxColor')}) + .appendTo($line); + }); + if (!canEdit) { + Ox.Button({ + title: Ox._('Help'), + tooltip: Ox._('About Rights'), + type: 'image' + }) + .css({marginLeft: '52px'}) + .bindEvent({ + click: function() { + pandora.UI.set({page: 'rights'}); + } + }) + .appendTo($line); + } + }); + } + function renderGroup(keys) { var $element; if (canEdit || keys.filter(function(key) { @@ -675,6 +757,53 @@ pandora.ui.infoView = function(data, isMixed) { } } + function renderRightsLevel() { + var $rightsLevelElement = getRightsLevelElement(data.rightslevel), + $rightsLevelSelect; + $rightsLevel.empty(); + if (canEdit) { + $rightsLevelSelect = Ox.Select({ + items: pandora.site.rightsLevels.map(function(rightsLevel, i) { + return {id: i, title: Ox._(rightsLevel.name)}; + }), + width: 128, + value: data.rightslevel + }) + .addClass('OxColor OxColorGradient') + .css({ + marginBottom: '4px', + background: $rightsLevelElement.css('background') + }) + .data({OxColor: $rightsLevelElement.data('OxColor')}) + .bindEvent({ + change: function(event) { + var rightsLevel = event.value; + $rightsLevelElement = getRightsLevelElement(rightsLevel); + $rightsLevelSelect + .css({background: $rightsLevelElement.css('background')}) + .data({OxColor: $rightsLevelElement.data('OxColor')}) + renderCapabilities(rightsLevel); + var edit = { + id: isMultiple ? ui.listSelection : data.id, + rightslevel: rightsLevel + }; + pandora.api.edit(edit, function(result) { + that.triggerEvent('change', Ox.extend({}, 'rightslevel', rightsLevel)); + }); + } + }) + .appendTo($rightsLevel); + } else { + $rightsLevelElement + .css({ + marginBottom: '4px' + }) + .appendTo($rightsLevel); + } + $capabilities = $('
').appendTo($rightsLevel); + renderCapabilities(data.rightslevel); + } + function toggleIconSize() { iconSize = iconSize == 256 ? 512 : 256; iconWidth = iconRatio > 1 ? iconSize : Math.round(iconSize * iconRatio); diff --git a/static/js/infoViewUtils.js b/static/js/infoViewUtils.js index 6c415c1b..9ab90665 100644 --- a/static/js/infoViewUtils.js +++ b/static/js/infoViewUtils.js @@ -14,145 +14,3 @@ pandora.cleanupDate = function(value) { return value }; -pandora.renderRightsLevel = function(that, $rightsLevel, data, isMixed, isMultiple, canEdit) { - var ui = pandora.user.ui, - rightsLevels = pandora.site.rightsLevels.map(function(rightsLevel) { - return rightsLevel.name; - }).concat(isMultiple ? ['Mixed'] : []), - rightsLevel = isMixed.rightslevel ? rightsLevels.length - 1 : data.rightslevel, - $capabilities, - $rightsLevelElement = getRightsLevelElement(rightsLevel), - $rightsLevelSelect; - $rightsLevel.empty(); - if (canEdit) { - $rightsLevelSelect = Ox.Select({ - items: pandora.site.rightsLevels.map(function(rightsLevel, i) { - return {id: i, title: Ox._(rightsLevel.name)}; - }).concat(isMultiple ? [ - {id: rightsLevels.length - 1, title: Ox._('Mixed'), disabled: true} - ] : []), - width: 128, - value: rightsLevel - }) - .addClass('OxColor OxColorGradient') - .css({ - marginBottom: '4px', - background: $rightsLevelElement.css('background') - }) - .data({OxColor: $rightsLevelElement.data('OxColor')}) - .bindEvent({ - change: function(event) { - var rightsLevel = event.value; - $rightsLevelElement = getRightsLevelElement(rightsLevel); - $rightsLevelSelect - .css({background: $rightsLevelElement.css('background')}) - .data({OxColor: $rightsLevelElement.data('OxColor')}) - if (rightsLevel < pandora.site.rightsLevels.length) { - renderCapabilities(rightsLevel); - var edit = { - id: isMultiple ? ui.listSelection : data.id, - rightslevel: rightsLevel - }; - pandora.api.edit(edit, function(result) { - that.triggerEvent('change', Ox.extend({}, 'rightslevel', rightsLevel)); - }); - } - } - }) - .appendTo($rightsLevel); - } else { - $rightsLevelElement - .css({ - marginBottom: '4px' - }) - .appendTo($rightsLevel); - } - $capabilities = $('
').appendTo($rightsLevel); - !isMixed.rightslevel && renderCapabilities(data.rightslevel); - - - function getRightsLevelElement(rightsLevel) { - return Ox.Theme.formatColorLevel(rightsLevel, rightsLevels) - } - - function renderCapabilities(rightsLevel) { - var capabilities = [].concat( - canEdit ? [{name: 'canSeeItem', symbol: 'Find'}] : [], - [ - {name: 'canPlayClips', symbol: 'PlayInToOut'}, - {name: 'canPlayVideo', symbol: 'Play'}, - {name: 'canDownloadVideo', symbol: 'Download'} - ] - ), - userLevels = canEdit ? pandora.site.userLevels : [pandora.user.level]; - $capabilities.empty(); - userLevels.forEach(function(userLevel, i) { - var $element, - $line = $('
') - .css({ - height: '16px', - marginBottom: '4px' - }) - .appendTo($capabilities); - if (canEdit) { - $element = Ox.Theme.formatColorLevel(i, userLevels.map(function(userLevel) { - return Ox.toTitleCase(userLevel); - }), [0, 240]); - Ox.Label({ - textAlign: 'center', - title: Ox._(Ox.toTitleCase(userLevel)), - width: 60 - }) - .addClass('OxColor OxColorGradient') - .css({ - float: 'left', - height: '12px', - paddingTop: '2px', - background: $element.css('background'), - fontSize: '8px', - color: $element.css('color') - }) - .data({OxColor: $element.data('OxColor')}) - .appendTo($line); - } - capabilities.forEach(function(capability) { - var hasCapability = pandora.hasCapability(capability.name, userLevel) >= rightsLevel, - $element = Ox.Theme.formatColorLevel(hasCapability, ['', '']); - Ox.Button({ - tooltip: Ox._('{0} ' - + (hasCapability ? 'can' : 'can\'t') + ' ' - + Ox.toSlashes(capability.name) - .split('/').slice(1).join(' ') - .toLowerCase() - .replace('see item', 'see the item') - .replace('play video', 'play the full video') - .replace('download video', 'download the video'), - [canEdit ? Ox._(Ox.toTitleCase(userLevel)) : Ox._('You')]), - title: capability.symbol, - type: 'image' - }) - .addClass('OxColor OxColorGradient') - .css({background: $element.css('background')}) - .css('margin' + (canEdit ? 'Left' : 'Right'), '4px') - .data({OxColor: $element.data('OxColor')}) - .appendTo($line); - }); - if (!canEdit) { - Ox.Button({ - title: Ox._('Help'), - tooltip: Ox._('About Rights'), - type: 'image' - }) - .css({marginLeft: '52px'}) - .bindEvent({ - click: function() { - pandora.UI.set({page: 'rights'}); - } - }) - .appendTo($line); - } - }); - } - -} - diff --git a/static/js/mainMenu.js b/static/js/mainMenu.js index 9ff8a94e..e1a80b5e 100644 --- a/static/js/mainMenu.js +++ b/static/js/mainMenu.js @@ -442,37 +442,7 @@ pandora.ui.mainMenu = function() { }); } } else if (data.id == 'deletefromarchive') { - if (ui.section == 'items') { - var ids; - if (ui.item) { - ids = [ui.item] - } else { - ids = ui.listSelection - } - pandora.api.find({ - query: { - conditions: [{ - key: 'id', - operator: '&', - value: ids - }], - operator: '&' - }, - keys: ['id', 'title'], - range: [0, ui.listSelection.length] - }, function(result) { - pandora.$ui.deleteItemsDialog = pandora.ui.deleteItemsDialog({ - items: result.data.items - }, function() { - Ox.Request.clearCache(); - if (ui.item) { - pandora.UI.set({item: ''}); - } else { - pandora.$ui.list.reloadList() - } - }).open(); - }); - } else if (ui.section == 'documents') { + if (ui.section == 'documents') { var files; if (ui.document) { files = [pandora.$ui.document.info()]; @@ -1394,9 +1364,6 @@ pandora.ui.mainMenu = function() { { id: 'clearclipboard', title: Ox._('Clear Clipboard'), disabled: !clipboardItems}, {}, { id: 'delete', title: Ox._('{0} {1} {2}', [deleteVerb, selectionItemName, listName]), disabled: !canDelete, keyboard: 'delete' }, - ui._list ? [ - { id: 'deletefromarchive', title: Ox._('{0} {1} {2}', [Ox._('Delete'), selectionItemName, Ox._('from Archive')]), disabled: !canDelete } - ] : [], {}, { id: 'undo', title: undoText ? Ox._('Undo {0}', [undoText]) : Ox._('Undo'), disabled: !undoText, keyboard: 'control z' }, { id: 'redo', title: redoText ? Ox._('Redo {0}', [redoText]) : Ox._('Redo'), disabled: !redoText, keyboard: 'shift control z' }, diff --git a/static/js/mediaExistsDialog.js b/static/js/mediaExistsDialog.js index 4388b652..a6bcad98 100644 --- a/static/js/mediaExistsDialog.js +++ b/static/js/mediaExistsDialog.js @@ -58,16 +58,10 @@ pandora.ui.mediaExistsDialog = function(options) { return existing.indexOf(item.oshash) == -1; }); that.close(); - (pandora.user.ui.item ? pandora.api.get : Ox.noop)({ - id: pandora.user.ui.item, - keys: ['editable'] - }, function(result) { - pandora.ui.addFilesDialog({ - action: options.action, - items: items, - editable: pandora.user.ui.item && result.data.editable - }).open(); - }) + pandora.ui.addFilesDialog({ + action: options.action, + items: items + }).open(); } }) ]; diff --git a/static/js/utils.js b/static/js/utils.js index 574e4a87..d4d0f610 100644 --- a/static/js/utils.js +++ b/static/js/utils.js @@ -375,11 +375,7 @@ pandora.clickLink = function(e, selectEmbed) { if (match) { (selectEmbed || pandora.$ui.textPanel.selectEmbed)(parseInt(match[1])); } else { - if (e.target.target == '_blank') { - pandora.openLink(e.target.href); - } else { - pandora.openURL(e.target.href); - } + pandora.openURL(e.target.href); } }; @@ -729,11 +725,11 @@ pandora.uploadDroppedFiles = function(files) { pandora.enableBatchEdit = function(section) { var ui = pandora.user.ui; if (section == 'documents') { - return !ui.document && ui.collectionSelection.length > 1 && ui.collectionSelection.some(function(item) { + return !ui.document && ui.collectionSelection.length > 1 && ui.collectionSelection.every(function(item) { return pandora.$ui.list && pandora.$ui.list.value(item, 'editable'); }) } else { - return !ui.item && ui.listSelection.length > 1 && ui.listSelection.some(function(item) { + return !ui.item && ui.listSelection.length > 1 && ui.listSelection.every(function(item) { return pandora.$ui.list && pandora.$ui.list.value(item, 'editable'); }) } @@ -2659,9 +2655,8 @@ pandora.openURL = function(url) { }; pandora.safeDocumentName = function(name) { - ['\\?', '#', '%', '/'].forEach(function(c) { - var r = new RegExp(c, 'g') - name = name.replace(r, '_'); + ['?', '#', '%'].forEach(function(c) { + name = name.replace(c, '_'); }) return name; }; diff --git a/update.py b/update.py index 2d52da38..3a2c7a40 100755 --- a/update.py +++ b/update.py @@ -80,7 +80,7 @@ def get_release(): def reload_notice(base): - print('\nPlease restart pan.do/ra to finish the update:\n\tsudo pandoractl reload\n') + print('\nPlease restart pan.do/ra to finish the update:\n\tsudo %s/ctl reload\n' % base) def check_services(base): @@ -297,8 +297,6 @@ if __name__ == "__main__": run_sql(sql) run(join(base, 'pandora/manage.py'), 'migrate', 'system') run(join(base, 'pandora/manage.py'), 'update_geoip') - if old <= 6383: - run('./bin/pip', 'install', '-r', 'requirements.txt') else: if len(sys.argv) == 1: branch = get_branch() diff --git a/vm/README.md b/vm/README.md index 6f935dd1..ff055e0c 100644 --- a/vm/README.md +++ b/vm/README.md @@ -42,5 +42,5 @@ Pan.do/ra is installed in /srv/pandora and is served with nginx on http://pandor to get the latest version of pan.do/ra cd /srv/pandora - pandoractl update + ./update.py diff --git a/vm/pandora_install.sh b/vm/pandora_install.sh index 75adf3d0..ec77d3b0 100755 --- a/vm/pandora_install.sh +++ b/vm/pandora_install.sh @@ -89,7 +89,6 @@ apt-get install -y \ python3-pyinotify \ python3-simplejson \ python3-lxml \ - python3-cssselect \ python3-html5lib \ python3-ox \ python3-elasticsearch \ @@ -119,7 +118,6 @@ fi if [ "$RABBITMQ" == "local" ]; then RABBITPWD=$(pwgen -n 16 -1) rabbitmqctl add_user pandora $RABBITPWD - rabbitmqctl change_password pandora $RABBITPWD rabbitmqctl add_vhost /pandora rabbitmqctl set_permissions -p /pandora pandora ".*" ".*" ".*" CELERY_BROKER_URL="amqp://pandora:$RABBITPWD@localhost:5672//pandora" @@ -187,7 +185,7 @@ fi # if pandora is running inside a container, expose backend at port 2620 if [ "$LXC" == "yes" ]; then - sed -i "s/127.0.0.1/[::]/g" /srv/pandora/pandora/gunicorn_config.py + sed -i s/127.0.0.1/0.0.0.0/g /srv/pandora/pandora/gunicorn_config.py echo "WEBSOCKET_ADDRESS = \"0.0.0.0\"" >> /srv/pandora/pandora/local_settings.py fi /srv/pandora/ctl start @@ -201,6 +199,7 @@ if [ "$NGINX" == "local" ]; then cp "/srv/pandora/etc/nginx/pandora" "/etc/nginx/sites-available/pandora" rm -f /etc/nginx/sites-enabled/default /etc/nginx/sites-enabled/pandora ln -s ../sites-available/pandora /etc/nginx/sites-enabled/pandora +ln -s /srv/pandora/ctl /usr/local/bin/pandoractl read -r -d '' GZIP <