mirror of
https://github.com/jiojciojsioe3/a3cjroijsiojiorj.git
synced 2024-11-15 07:21:50 +08:00
Add base directory support
- Base directory can be changed in config.py from the default / to, for example, /taiko-web/ - See tools/nginx_subdir.conf for an example nginx configuration with a base directory - Custom error pages can be used, they can be set in config.py
This commit is contained in:
parent
ba1a6ab306
commit
fd32ecb004
1
.gitignore
vendored
1
.gitignore
vendored
@ -53,3 +53,4 @@ config.py
|
|||||||
public/assets/song_skins
|
public/assets/song_skins
|
||||||
.venv
|
.venv
|
||||||
public/src/js/plugin
|
public/src/js/plugin
|
||||||
|
.hidden
|
||||||
|
92
app.py
92
app.py
@ -15,7 +15,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash, make_response
|
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash, make_response, send_from_directory
|
||||||
from flask_caching import Cache
|
from flask_caching import Cache
|
||||||
from flask_session import Session
|
from flask_session import Session
|
||||||
from flask_wtf.csrf import CSRFProtect, generate_csrf, CSRFError
|
from flask_wtf.csrf import CSRFProtect, generate_csrf, CSRFError
|
||||||
@ -33,6 +33,7 @@ def take_config(name, required=False):
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
client = MongoClient(host=take_config('MONGO', required=True)['host'])
|
client = MongoClient(host=take_config('MONGO', required=True)['host'])
|
||||||
|
basedir = take_config('BASEDIR') or '/'
|
||||||
|
|
||||||
app.secret_key = take_config('SECRET_KEY') or 'change-me'
|
app.secret_key = take_config('SECRET_KEY') or 'change-me'
|
||||||
app.config['SESSION_TYPE'] = 'redis'
|
app.config['SESSION_TYPE'] = 'redis'
|
||||||
@ -79,8 +80,8 @@ def generate_hash(id, form):
|
|||||||
raise HashException('Invalid response from %s (status code %s)' % (resp.url, resp.status_code))
|
raise HashException('Invalid response from %s (status code %s)' % (resp.url, resp.status_code))
|
||||||
md5.update(resp.content)
|
md5.update(resp.content)
|
||||||
else:
|
else:
|
||||||
if url.startswith("/"):
|
if url.startswith(basedir):
|
||||||
url = url[1:]
|
url = url[len(basedir):]
|
||||||
path = os.path.normpath(os.path.join("public", url))
|
path = os.path.normpath(os.path.join("public", url))
|
||||||
if not os.path.isfile(path):
|
if not os.path.isfile(path):
|
||||||
raise HashException("File not found: %s" % (os.path.abspath(path)))
|
raise HashException("File not found: %s" % (os.path.abspath(path)))
|
||||||
@ -129,6 +130,7 @@ def before_request_func():
|
|||||||
|
|
||||||
def get_config(credentials=False):
|
def get_config(credentials=False):
|
||||||
config_out = {
|
config_out = {
|
||||||
|
'basedir': basedir,
|
||||||
'songs_baseurl': take_config('SONGS_BASEURL', required=True),
|
'songs_baseurl': take_config('SONGS_BASEURL', required=True),
|
||||||
'assets_baseurl': take_config('ASSETS_BASEURL', required=True),
|
'assets_baseurl': take_config('ASSETS_BASEURL', required=True),
|
||||||
'email': take_config('EMAIL'),
|
'email': take_config('EMAIL'),
|
||||||
@ -138,6 +140,10 @@ def get_config(credentials=False):
|
|||||||
'preview_type': take_config('PREVIEW_TYPE') or 'mp3',
|
'preview_type': take_config('PREVIEW_TYPE') or 'mp3',
|
||||||
'multiplayer_url': take_config('MULTIPLAYER_URL')
|
'multiplayer_url': take_config('MULTIPLAYER_URL')
|
||||||
}
|
}
|
||||||
|
relative_urls = ['songs_baseurl', 'assets_baseurl']
|
||||||
|
for name in relative_urls:
|
||||||
|
if not config_out[name].startswith("/") and not config_out[name].startswith("http://") and not config_out[name].startswith("https://"):
|
||||||
|
config_out[name] = basedir + config_out[name]
|
||||||
if credentials:
|
if credentials:
|
||||||
google_credentials = take_config('GOOGLE_CREDENTIALS')
|
google_credentials = take_config('GOOGLE_CREDENTIALS')
|
||||||
min_level = google_credentials['min_level'] or 0
|
min_level = google_credentials['min_level'] or 0
|
||||||
@ -200,24 +206,24 @@ def is_hex(input):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@app.route('/')
|
@app.route(basedir)
|
||||||
def route_index():
|
def route_index():
|
||||||
version = get_version()
|
version = get_version()
|
||||||
return render_template('index.html', version=version, config=get_config())
|
return render_template('index.html', version=version, config=get_config())
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/csrftoken')
|
@app.route(basedir + 'api/csrftoken')
|
||||||
def route_csrftoken():
|
def route_csrftoken():
|
||||||
return jsonify({'status': 'ok', 'token': generate_csrf()})
|
return jsonify({'status': 'ok', 'token': generate_csrf()})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin')
|
@app.route(basedir + 'admin')
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin():
|
def route_admin():
|
||||||
return redirect('/admin/songs')
|
return redirect(basedir + 'admin/songs')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs')
|
@app.route(basedir + 'admin/songs')
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin_songs():
|
def route_admin_songs():
|
||||||
songs = sorted(list(db.songs.find({})), key=lambda x: x['id'])
|
songs = sorted(list(db.songs.find({})), key=lambda x: x['id'])
|
||||||
@ -226,7 +232,7 @@ def route_admin_songs():
|
|||||||
return render_template('admin_songs.html', songs=songs, admin=user, categories=list(categories), config=get_config())
|
return render_template('admin_songs.html', songs=songs, admin=user, categories=list(categories), config=get_config())
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs/<int:id>')
|
@app.route(basedir + 'admin/songs/<int:id>')
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin_songs_id(id):
|
def route_admin_songs_id(id):
|
||||||
song = db.songs.find_one({'id': id})
|
song = db.songs.find_one({'id': id})
|
||||||
@ -242,7 +248,7 @@ def route_admin_songs_id(id):
|
|||||||
song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user, config=get_config())
|
song=song, categories=categories, song_skins=song_skins, makers=makers, admin=user, config=get_config())
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs/new')
|
@app.route(basedir + 'admin/songs/new')
|
||||||
@admin_required(level=100)
|
@admin_required(level=100)
|
||||||
def route_admin_songs_new():
|
def route_admin_songs_new():
|
||||||
categories = list(db.categories.find({}))
|
categories = list(db.categories.find({}))
|
||||||
@ -254,7 +260,7 @@ def route_admin_songs_new():
|
|||||||
return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers, config=get_config(), id=seq_new)
|
return render_template('admin_song_new.html', categories=categories, song_skins=song_skins, makers=makers, config=get_config(), id=seq_new)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs/new', methods=['POST'])
|
@app.route(basedir + 'admin/songs/new', methods=['POST'])
|
||||||
@admin_required(level=100)
|
@admin_required(level=100)
|
||||||
def route_admin_songs_new_post():
|
def route_admin_songs_new_post():
|
||||||
output = {'title_lang': {}, 'subtitle_lang': {}, 'courses': {}}
|
output = {'title_lang': {}, 'subtitle_lang': {}, 'courses': {}}
|
||||||
@ -303,10 +309,10 @@ def route_admin_songs_new_post():
|
|||||||
|
|
||||||
db.seq.update_one({'name': 'songs'}, {'$set': {'value': seq_new}}, upsert=True)
|
db.seq.update_one({'name': 'songs'}, {'$set': {'value': seq_new}}, upsert=True)
|
||||||
|
|
||||||
return redirect('/admin/songs/%s' % str(seq_new))
|
return redirect(basedir + 'admin/songs/%s' % str(seq_new))
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs/<int:id>', methods=['POST'])
|
@app.route(basedir + 'admin/songs/<int:id>', methods=['POST'])
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin_songs_id_post(id):
|
def route_admin_songs_id_post(id):
|
||||||
song = db.songs.find_one({'id': id})
|
song = db.songs.find_one({'id': id})
|
||||||
@ -356,10 +362,10 @@ def route_admin_songs_id_post(id):
|
|||||||
if not hash_error:
|
if not hash_error:
|
||||||
flash('Changes saved.')
|
flash('Changes saved.')
|
||||||
|
|
||||||
return redirect('/admin/songs/%s' % id)
|
return redirect(basedir + 'admin/songs/%s' % id)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/songs/<int:id>/delete', methods=['POST'])
|
@app.route(basedir + 'admin/songs/<int:id>/delete', methods=['POST'])
|
||||||
@admin_required(level=100)
|
@admin_required(level=100)
|
||||||
def route_admin_songs_id_delete(id):
|
def route_admin_songs_id_delete(id):
|
||||||
song = db.songs.find_one({'id': id})
|
song = db.songs.find_one({'id': id})
|
||||||
@ -368,10 +374,10 @@ def route_admin_songs_id_delete(id):
|
|||||||
|
|
||||||
db.songs.delete_one({'id': id})
|
db.songs.delete_one({'id': id})
|
||||||
flash('Song deleted.')
|
flash('Song deleted.')
|
||||||
return redirect('/admin/songs')
|
return redirect(basedir + 'admin/songs')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/users')
|
@app.route(basedir + 'admin/users')
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin_users():
|
def route_admin_users():
|
||||||
user = db.users.find_one({'username': session.get('username')})
|
user = db.users.find_one({'username': session.get('username')})
|
||||||
@ -379,7 +385,7 @@ def route_admin_users():
|
|||||||
return render_template('admin_users.html', config=get_config(), max_level=max_level, username='', level='')
|
return render_template('admin_users.html', config=get_config(), max_level=max_level, username='', level='')
|
||||||
|
|
||||||
|
|
||||||
@app.route('/admin/users', methods=['POST'])
|
@app.route(basedir + 'admin/users', methods=['POST'])
|
||||||
@admin_required(level=50)
|
@admin_required(level=50)
|
||||||
def route_admin_users_post():
|
def route_admin_users_post():
|
||||||
admin_name = session.get('username')
|
admin_name = session.get('username')
|
||||||
@ -411,7 +417,7 @@ def route_admin_users_post():
|
|||||||
return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)
|
return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/preview')
|
@app.route(basedir + 'api/preview')
|
||||||
@app.cache.cached(timeout=15, query_string=True)
|
@app.cache.cached(timeout=15, query_string=True)
|
||||||
def route_api_preview():
|
def route_api_preview():
|
||||||
song_id = request.args.get('id', None)
|
song_id = request.args.get('id', None)
|
||||||
@ -432,7 +438,7 @@ def route_api_preview():
|
|||||||
return redirect(get_config()['songs_baseurl'] + '%s/preview.mp3' % song_id)
|
return redirect(get_config()['songs_baseurl'] + '%s/preview.mp3' % song_id)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/songs')
|
@app.route(basedir + 'api/songs')
|
||||||
@app.cache.cached(timeout=15)
|
@app.cache.cached(timeout=15)
|
||||||
def route_api_songs():
|
def route_api_songs():
|
||||||
songs = list(db.songs.find({'enabled': True}, {'_id': False, 'enabled': False}))
|
songs = list(db.songs.find({'enabled': True}, {'_id': False, 'enabled': False}))
|
||||||
@ -460,20 +466,20 @@ def route_api_songs():
|
|||||||
|
|
||||||
return jsonify(songs)
|
return jsonify(songs)
|
||||||
|
|
||||||
@app.route('/api/categories')
|
@app.route(basedir + 'api/categories')
|
||||||
@app.cache.cached(timeout=15)
|
@app.cache.cached(timeout=15)
|
||||||
def route_api_categories():
|
def route_api_categories():
|
||||||
categories = list(db.categories.find({},{'_id': False}))
|
categories = list(db.categories.find({},{'_id': False}))
|
||||||
return jsonify(categories)
|
return jsonify(categories)
|
||||||
|
|
||||||
@app.route('/api/config')
|
@app.route(basedir + 'api/config')
|
||||||
@app.cache.cached(timeout=15)
|
@app.cache.cached(timeout=15)
|
||||||
def route_api_config():
|
def route_api_config():
|
||||||
config = get_config(credentials=True)
|
config = get_config(credentials=True)
|
||||||
return jsonify(config)
|
return jsonify(config)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/register', methods=['POST'])
|
@app.route(basedir + 'api/register', methods=['POST'])
|
||||||
def route_api_register():
|
def route_api_register():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not schema.validate(data, schema.register):
|
if not schema.validate(data, schema.register):
|
||||||
@ -514,7 +520,7 @@ def route_api_register():
|
|||||||
return jsonify({'status': 'ok', 'username': username, 'display_name': username, 'don': don})
|
return jsonify({'status': 'ok', 'username': username, 'display_name': username, 'don': don})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/login', methods=['POST'])
|
@app.route(basedir + 'api/login', methods=['POST'])
|
||||||
def route_api_login():
|
def route_api_login():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not schema.validate(data, schema.login):
|
if not schema.validate(data, schema.login):
|
||||||
@ -541,14 +547,14 @@ def route_api_login():
|
|||||||
return jsonify({'status': 'ok', 'username': result['username'], 'display_name': result['display_name'], 'don': don})
|
return jsonify({'status': 'ok', 'username': result['username'], 'display_name': result['display_name'], 'don': don})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/logout', methods=['POST'])
|
@app.route(basedir + 'api/logout', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_logout():
|
def route_api_logout():
|
||||||
session.clear()
|
session.clear()
|
||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/account/display_name', methods=['POST'])
|
@app.route(basedir + 'api/account/display_name', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_account_display_name():
|
def route_api_account_display_name():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -568,7 +574,7 @@ def route_api_account_display_name():
|
|||||||
return jsonify({'status': 'ok', 'display_name': display_name})
|
return jsonify({'status': 'ok', 'display_name': display_name})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/account/don', methods=['POST'])
|
@app.route(basedir + 'api/account/don', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_account_don():
|
def route_api_account_don():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -593,7 +599,7 @@ def route_api_account_don():
|
|||||||
return jsonify({'status': 'ok', 'don': {'body_fill': don_body_fill, 'face_fill': don_face_fill}})
|
return jsonify({'status': 'ok', 'don': {'body_fill': don_body_fill, 'face_fill': don_face_fill}})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/account/password', methods=['POST'])
|
@app.route(basedir + 'api/account/password', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_account_password():
|
def route_api_account_password():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -621,7 +627,7 @@ def route_api_account_password():
|
|||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/account/remove', methods=['POST'])
|
@app.route(basedir + 'api/account/remove', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_account_remove():
|
def route_api_account_remove():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -640,7 +646,7 @@ def route_api_account_remove():
|
|||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/scores/save', methods=['POST'])
|
@app.route(basedir + 'api/scores/save', methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_scores_save():
|
def route_api_scores_save():
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -663,7 +669,7 @@ def route_api_scores_save():
|
|||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/scores/get')
|
@app.route(basedir + 'api/scores/get')
|
||||||
@login_required
|
@login_required
|
||||||
def route_api_scores_get():
|
def route_api_scores_get():
|
||||||
username = session.get('username')
|
username = session.get('username')
|
||||||
@ -680,7 +686,7 @@ def route_api_scores_get():
|
|||||||
return jsonify({'status': 'ok', 'scores': scores, 'username': user['username'], 'display_name': user['display_name'], 'don': don})
|
return jsonify({'status': 'ok', 'scores': scores, 'username': user['username'], 'display_name': user['display_name'], 'don': don})
|
||||||
|
|
||||||
|
|
||||||
@app.route('/privacy')
|
@app.route(basedir + 'privacy')
|
||||||
def route_api_privacy():
|
def route_api_privacy():
|
||||||
last_modified = time.strftime('%d %B %Y', time.gmtime(os.path.getmtime('templates/privacy.txt')))
|
last_modified = time.strftime('%d %B %Y', time.gmtime(os.path.getmtime('templates/privacy.txt')))
|
||||||
integration = take_config('GOOGLE_CREDENTIALS')['gdrive_enabled'] if take_config('GOOGLE_CREDENTIALS') else False
|
integration = take_config('GOOGLE_CREDENTIALS')['gdrive_enabled'] if take_config('GOOGLE_CREDENTIALS') else False
|
||||||
@ -706,10 +712,26 @@ def make_preview(song_id, song_type, song_ext, preview):
|
|||||||
|
|
||||||
return prev_path
|
return prev_path
|
||||||
|
|
||||||
|
error_pages = take_config('ERROR_PAGES') or {}
|
||||||
|
|
||||||
|
def create_error_page(code, url):
|
||||||
|
if url.startswith("http://") or url.startswith("https://"):
|
||||||
|
resp = requests.get(url)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
app.register_error_handler(code, lambda e: (resp.content, code))
|
||||||
|
else:
|
||||||
|
if url.startswith(basedir):
|
||||||
|
url = url[len(basedir):]
|
||||||
|
path = os.path.normpath(os.path.join("public", url))
|
||||||
|
if os.path.isfile(path):
|
||||||
|
app.register_error_handler(code, lambda e: (send_from_directory(".", path), code))
|
||||||
|
|
||||||
|
for code in error_pages:
|
||||||
|
if error_pages[code]:
|
||||||
|
create_error_page(code, error_pages[code])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import argparse
|
import argparse
|
||||||
from flask import send_from_directory
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description='Run the taiko-web development server.')
|
parser = argparse.ArgumentParser(description='Run the taiko-web development server.')
|
||||||
parser.add_argument('port', type=int, metavar='PORT', nargs='?', default=34801, help='Port to listen on.')
|
parser.add_argument('port', type=int, metavar='PORT', nargs='?', default=34801, help='Port to listen on.')
|
||||||
@ -717,11 +739,11 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mode.')
|
parser.add_argument('-d', '--debug', action='store_true', help='Enable debug mode.')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@app.route('/src/<path:path>')
|
@app.route(basedir + 'src/<path:path>')
|
||||||
def send_src(path):
|
def send_src(path):
|
||||||
return send_from_directory('public/src', path)
|
return send_from_directory('public/src', path)
|
||||||
|
|
||||||
@app.route('/assets/<path:path>')
|
@app.route(basedir + 'assets/<path:path>')
|
||||||
def send_assets(path):
|
def send_assets(path):
|
||||||
return send_from_directory('public/assets', path)
|
return send_from_directory('public/assets', path)
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
# The base URL for Taiko Web, with trailing slash.
|
||||||
|
BASEDIR = '/'
|
||||||
|
|
||||||
# The full URL base asset URL, with trailing slash.
|
# The full URL base asset URL, with trailing slash.
|
||||||
ASSETS_BASEURL = '/assets/'
|
ASSETS_BASEURL = '/assets/'
|
||||||
|
|
||||||
@ -7,6 +10,11 @@ SONGS_BASEURL = '/songs/'
|
|||||||
# Multiplayer websocket URL. Defaults to /p2 if blank.
|
# Multiplayer websocket URL. Defaults to /p2 if blank.
|
||||||
MULTIPLAYER_URL = ''
|
MULTIPLAYER_URL = ''
|
||||||
|
|
||||||
|
# Send static files for custom error pages
|
||||||
|
ERROR_PAGES = {
|
||||||
|
404: ''
|
||||||
|
}
|
||||||
|
|
||||||
# The email address to display in the "About Simulator" menu.
|
# The email address to display in the "About Simulator" menu.
|
||||||
EMAIL = None
|
EMAIL = None
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ class CustomSongs{
|
|||||||
this.loading(true)
|
this.loading(true)
|
||||||
var importSongs = new ImportSongs(true)
|
var importSongs = new ImportSongs(true)
|
||||||
if(!gpicker){
|
if(!gpicker){
|
||||||
var gpickerPromise = loader.loadScript("/src/js/gpicker.js").then(() => {
|
var gpickerPromise = loader.loadScript("src/js/gpicker.js").then(() => {
|
||||||
gpicker = new Gpicker()
|
gpicker = new Gpicker()
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
|
@ -13,11 +13,11 @@ class Loader{
|
|||||||
|
|
||||||
var promises = []
|
var promises = []
|
||||||
|
|
||||||
promises.push(this.ajax("/src/views/loader.html").then(page => {
|
promises.push(this.ajax("src/views/loader.html").then(page => {
|
||||||
this.screen.innerHTML = page
|
this.screen.innerHTML = page
|
||||||
}))
|
}))
|
||||||
|
|
||||||
promises.push(this.ajax("/api/config").then(conf => {
|
promises.push(this.ajax("api/config").then(conf => {
|
||||||
gameConfig = JSON.parse(conf)
|
gameConfig = JSON.parse(conf)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class Loader{
|
|||||||
assets.js.push("lib/oggmented-wasm.js")
|
assets.js.push("lib/oggmented-wasm.js")
|
||||||
}
|
}
|
||||||
assets.js.forEach(name => {
|
assets.js.forEach(name => {
|
||||||
this.addPromise(this.loadScript("/src/js/" + name), "/src/js/" + name)
|
this.addPromise(this.loadScript("src/js/" + name), "src/js/" + name)
|
||||||
})
|
})
|
||||||
|
|
||||||
var pageVersion = versionLink.href
|
var pageVersion = versionLink.href
|
||||||
@ -59,7 +59,7 @@ class Loader{
|
|||||||
assets.css.forEach(name => {
|
assets.css.forEach(name => {
|
||||||
var stylesheet = document.createElement("link")
|
var stylesheet = document.createElement("link")
|
||||||
stylesheet.rel = "stylesheet"
|
stylesheet.rel = "stylesheet"
|
||||||
stylesheet.href = "/src/css/" + name + this.queryString
|
stylesheet.href = "src/css/" + name + this.queryString
|
||||||
document.head.appendChild(stylesheet)
|
document.head.appendChild(stylesheet)
|
||||||
})
|
})
|
||||||
var checkStyles = () => {
|
var checkStyles = () => {
|
||||||
@ -124,13 +124,13 @@ class Loader{
|
|||||||
|
|
||||||
assets.views.forEach(name => {
|
assets.views.forEach(name => {
|
||||||
var id = this.getFilename(name)
|
var id = this.getFilename(name)
|
||||||
var url = "/src/views/" + name + this.queryString
|
var url = "src/views/" + name + this.queryString
|
||||||
this.addPromise(this.ajax(url).then(page => {
|
this.addPromise(this.ajax(url).then(page => {
|
||||||
assets.pages[id] = page
|
assets.pages[id] = page
|
||||||
}), url)
|
}), url)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addPromise(this.ajax("/api/categories").then(cats => {
|
this.addPromise(this.ajax("api/categories").then(cats => {
|
||||||
assets.categories = JSON.parse(cats)
|
assets.categories = JSON.parse(cats)
|
||||||
assets.categories.forEach(cat => {
|
assets.categories.forEach(cat => {
|
||||||
if(cat.song_skin){
|
if(cat.song_skin){
|
||||||
@ -150,7 +150,7 @@ class Loader{
|
|||||||
infoFill: "#656565"
|
infoFill: "#656565"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}), "/api/categories")
|
}), "api/categories")
|
||||||
|
|
||||||
var url = gameConfig.assets_baseurl + "img/vectors.json" + this.queryString
|
var url = gameConfig.assets_baseurl + "img/vectors.json" + this.queryString
|
||||||
this.addPromise(this.ajax(url).then(response => {
|
this.addPromise(this.ajax(url).then(response => {
|
||||||
@ -159,7 +159,7 @@ class Loader{
|
|||||||
|
|
||||||
this.afterJSCount =
|
this.afterJSCount =
|
||||||
[
|
[
|
||||||
"/api/songs",
|
"api/songs",
|
||||||
"blurPerformance",
|
"blurPerformance",
|
||||||
"categories"
|
"categories"
|
||||||
].length +
|
].length +
|
||||||
@ -178,7 +178,7 @@ class Loader{
|
|||||||
style.appendChild(document.createTextNode(css.join("\n")))
|
style.appendChild(document.createTextNode(css.join("\n")))
|
||||||
document.head.appendChild(style)
|
document.head.appendChild(style)
|
||||||
|
|
||||||
this.addPromise(this.ajax("/api/songs").then(songs => {
|
this.addPromise(this.ajax("api/songs").then(songs => {
|
||||||
songs = JSON.parse(songs)
|
songs = JSON.parse(songs)
|
||||||
songs.forEach(song => {
|
songs.forEach(song => {
|
||||||
var directory = gameConfig.songs_baseurl + song.id + "/"
|
var directory = gameConfig.songs_baseurl + song.id + "/"
|
||||||
@ -203,7 +203,7 @@ class Loader{
|
|||||||
})
|
})
|
||||||
assets.songsDefault = songs
|
assets.songsDefault = songs
|
||||||
assets.songs = assets.songsDefault
|
assets.songs = assets.songsDefault
|
||||||
}), "/api/songs")
|
}), "api/songs")
|
||||||
|
|
||||||
var categoryPromises = []
|
var categoryPromises = []
|
||||||
assets.categories //load category backgrounds to DOM
|
assets.categories //load category backgrounds to DOM
|
||||||
@ -276,7 +276,7 @@ class Loader{
|
|||||||
}), "blurPerformance")
|
}), "blurPerformance")
|
||||||
|
|
||||||
if(gameConfig.accounts){
|
if(gameConfig.accounts){
|
||||||
this.addPromise(this.ajax("/api/scores/get").then(response => {
|
this.addPromise(this.ajax("api/scores/get").then(response => {
|
||||||
response = JSON.parse(response)
|
response = JSON.parse(response)
|
||||||
if(response.status === "ok"){
|
if(response.status === "ok"){
|
||||||
account.loggedIn = true
|
account.loggedIn = true
|
||||||
@ -286,7 +286,7 @@ class Loader{
|
|||||||
scoreStorage.load(response.scores)
|
scoreStorage.load(response.scores)
|
||||||
pageEvents.send("login", account.username)
|
pageEvents.send("login", account.username)
|
||||||
}
|
}
|
||||||
}), "/api/scores/get")
|
}), "api/scores/get")
|
||||||
}
|
}
|
||||||
|
|
||||||
settings = new Settings()
|
settings = new Settings()
|
||||||
|
@ -32,7 +32,7 @@ class P2Connection{
|
|||||||
if(this.closed && !this.disabled){
|
if(this.closed && !this.disabled){
|
||||||
this.closed = false
|
this.closed = false
|
||||||
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
var wsProtocol = location.protocol == "https:" ? "wss:" : "ws:"
|
||||||
this.socket = new WebSocket(gameConfig.multiplayer_url ? gameConfig.multiplayer_url : wsProtocol + "//" + location.host + "/p2")
|
this.socket = new WebSocket(gameConfig.multiplayer_url ? gameConfig.multiplayer_url : wsProtocol + "//" + location.host + location.pathname + "p2")
|
||||||
pageEvents.race(this.socket, "open", "close").then(response => {
|
pageEvents.race(this.socket, "open", "close").then(response => {
|
||||||
if(response.type === "open"){
|
if(response.type === "open"){
|
||||||
return this.openEvent()
|
return this.openEvent()
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
|
||||||
<link href="/src/css/admin.css" rel="stylesheet">
|
<link href="{{config.basedir}}src/css/admin.css" rel="stylesheet">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<a href="/admin/songs">Songs</a>
|
<a href="{{config.basedir}}admin/songs">Songs</a>
|
||||||
<a href="/admin/users">Users</a>
|
<a href="{{config.basedir}}admin/users">Users</a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
{% extends 'admin.html' %}
|
{% extends 'admin.html' %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% if admin.user_level >= 100 %}
|
{% if admin.user_level >= 100 %}
|
||||||
<a href="/admin/songs/new" class="side-button">New song</a>
|
<a href="{{config.basedir}}admin/songs/new" class="side-button">New song</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<h1>Songs</h1>
|
<h1>Songs</h1>
|
||||||
{% for message in get_flashed_messages() %}
|
{% for message in get_flashed_messages() %}
|
||||||
<div class="message">{{ message }}</div>
|
<div class="message">{{ message }}</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% for song in songs %}
|
{% for song in songs %}
|
||||||
<a href="/admin/songs/{{ song.id }}" class="song-link">
|
<a href="{{config.basedir}}admin/songs/{{ song.id }}" class="song-link">
|
||||||
<div class="song">
|
<div class="song">
|
||||||
{% if song.title_lang.en and song.title_lang.en != song.title %}
|
{% if song.title_lang.en and song.title_lang.en != song.title %}
|
||||||
<p><span class="song-id">{{ song.id }}.</span>
|
<p><span class="song-id">{{ song.id }}.</span>
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
<meta name="robots" content="noimageindex">
|
<meta name="robots" content="noimageindex">
|
||||||
<meta name="color-scheme" content="only light">
|
<meta name="color-scheme" content="only light">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/src/css/loader.css?{{version.commit_short}}">
|
<link rel="stylesheet" href="src/css/loader.css?{{version.commit_short}}">
|
||||||
|
|
||||||
<script src="/src/js/assets.js?{{version.commit_short}}"></script>
|
<script src="src/js/assets.js?{{version.commit_short}}"></script>
|
||||||
<script src="/src/js/strings.js?{{version.commit_short}}"></script>
|
<script src="src/js/strings.js?{{version.commit_short}}"></script>
|
||||||
<script src="/src/js/pageevents.js?{{version.commit_short}}"></script>
|
<script src="src/js/pageevents.js?{{version.commit_short}}"></script>
|
||||||
<script src="/src/js/loader.js?{{version.commit_short}}"></script>
|
<script src="src/js/loader.js?{{version.commit_short}}"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -29,8 +29,8 @@
|
|||||||
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
<a href="{{version.url}}" target="_blank" rel="noopener" id="version-link" class="stroke-sub" alt="taiko-web (unknown version)">taiko-web (unknown version)</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<script src="/src/js/browsersupport.js?{{version.commit_short}}"></script>
|
<script src="src/js/browsersupport.js?{{version.commit_short}}"></script>
|
||||||
<script src="/src/js/main.js?{{version.commit_short}}"></script>
|
<script src="src/js/main.js?{{version.commit_short}}"></script>
|
||||||
<noscript>
|
<noscript>
|
||||||
<div data-nosnippet id="unsupportedBrowser">
|
<div data-nosnippet id="unsupportedBrowser">
|
||||||
<div id="unsupportedWarn">!</div>
|
<div id="unsupportedWarn">!</div>
|
||||||
|
28
tools/nginx_subdir.conf
Normal file
28
tools/nginx_subdir.conf
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
#server_name taiko.example.com;
|
||||||
|
|
||||||
|
location /taiko-web/ {
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Host $server_name;
|
||||||
|
proxy_pass http://127.0.0.1:34801;
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~ ^/taiko-web/(assets|songs|src)/ {
|
||||||
|
rewrite ^/taiko-web/(.*) /$1 break;
|
||||||
|
root /srv/taiko-web/public;
|
||||||
|
location ~ ^/taiko-web/songs/([0-9]+)/preview\.mp3$ {
|
||||||
|
set $id $1;
|
||||||
|
rewrite ^/taiko-web/(.*) /$1 break;
|
||||||
|
try_files $uri /taiko-web/api/preview?id=$id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
location /taiko-web/p2 {
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_pass http://127.0.0.1:34802;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user