taiko-web/app.py

185 lines
5.5 KiB
Python
Raw Normal View History

2018-08-26 18:14:56 +02:00
#!/usr/bin/env python2
2018-10-17 23:16:53 +02:00
from __future__ import division
2018-10-10 22:57:29 +02:00
import json
2018-08-26 18:14:56 +02:00
import sqlite3
2018-08-27 14:28:30 +02:00
import re
import os
2018-10-17 23:16:53 +02:00
from flask import Flask, g, jsonify, render_template, request, abort, redirect
2019-02-14 11:31:23 +01:00
from flask_caching import Cache
2018-10-17 23:16:53 +02:00
from ffmpy import FFmpeg
2018-08-26 18:14:56 +02:00
app = Flask(__name__)
2019-02-14 11:31:23 +01:00
try:
app.cache = Cache(app, config={'CACHE_TYPE': 'redis'})
except RuntimeError:
2019-02-14 11:36:39 +01:00
import tempfile
2019-02-14 11:31:23 +01:00
app.cache = Cache(app, config={'CACHE_TYPE': 'filesystem', 'CACHE_DIR': tempfile.gettempdir()})
2018-08-26 18:14:56 +02:00
DATABASE = 'taiko.db'
2019-02-06 19:49:25 +01:00
DEFAULT_URL = 'https://github.com/bui/taiko-web/'
2018-08-26 18:14:56 +02:00
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
2018-08-26 18:14:56 +02:00
return db
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
2018-10-28 10:59:49 +01:00
def get_config():
if os.path.isfile('config.json'):
try:
config = json.load(open('config.json', 'r'))
except ValueError:
2019-02-20 23:02:44 +01:00
print('WARNING: Invalid config.json, using default values')
2018-10-28 10:59:49 +01:00
config = {}
else:
2019-02-20 23:02:44 +01:00
print('WARNING: No config.json found, using default values')
2018-10-28 10:59:49 +01:00
config = {}
if not config.get('songs_baseurl'):
config['songs_baseurl'] = ''.join([request.host_url, 'songs']) + '/'
if not config.get('assets_baseurl'):
config['assets_baseurl'] = ''.join([request.host_url, 'assets']) + '/'
2018-12-05 22:55:28 +01:00
config['_version'] = get_version()
2018-10-28 10:59:49 +01:00
return config
2018-12-05 22:47:35 +01:00
def get_version():
2019-02-06 19:49:25 +01:00
version = {'commit': None, 'commit_short': '', 'version': None, 'url': DEFAULT_URL}
2018-12-05 22:47:35 +01:00
if os.path.isfile('version.json'):
2019-02-06 19:49:25 +01:00
try:
ver = json.load(open('version.json', 'r'))
except ValueError:
print('Invalid version.json file')
return version
for key in version.keys():
if ver.get(key):
version[key] = ver.get(key)
2018-12-05 22:47:35 +01:00
return version
2018-08-26 18:14:56 +02:00
@app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
2018-10-10 22:57:29 +02:00
@app.route('/')
2019-02-14 11:36:39 +01:00
@app.cache.cached(timeout=15)
2018-10-10 22:57:29 +02:00
def route_index():
2018-12-05 22:47:35 +01:00
version = get_version()
2018-10-28 10:59:49 +01:00
return render_template('index.html', version=version, config=get_config())
2018-10-10 22:57:29 +02:00
2018-10-17 23:16:53 +02:00
@app.route('/api/preview')
2020-02-22 14:09:07 +01:00
@app.cache.cached(timeout=15, query_string=True)
2018-10-17 23:16:53 +02:00
def route_api_preview():
song_id = request.args.get('id', None)
if not song_id or not re.match('^[0-9]+$', song_id):
abort(400)
song_row = query_db('select * from songs where id = ? and enabled = 1', (song_id,))
if not song_row:
abort(400)
song_type = song_row[0]['type']
prev_path = make_preview(song_id, song_type, song_row[0]['preview'])
2018-10-17 23:16:53 +02:00
if not prev_path:
return redirect(get_config()['songs_baseurl'] + '%s/main.mp3' % song_id)
2018-10-17 23:16:53 +02:00
return redirect(get_config()['songs_baseurl'] + '%s/preview.mp3' % song_id)
2018-10-17 23:16:53 +02:00
2018-08-26 18:14:56 +02:00
@app.route('/api/songs')
2019-02-14 11:31:23 +01:00
@app.cache.cached(timeout=15)
2018-08-26 18:14:56 +02:00
def route_api_songs():
songs = query_db('select s.*, m.name, m.url from songs s left join makers m on s.maker_id = m.maker_id where enabled = 1')
2018-11-25 23:42:24 +01:00
2018-09-26 20:30:57 +02:00
raw_categories = query_db('select * from categories')
categories = {}
for cat in raw_categories:
categories[cat['id']] = cat['title']
2018-11-25 23:42:24 +01:00
raw_song_skins = query_db('select * from song_skins')
song_skins = {}
for skin in raw_song_skins:
song_skins[skin[0]] = {'name': skin['name'], 'song': skin['song'], 'stage': skin['stage'], 'don': skin['don']}
2018-11-25 23:42:24 +01:00
2018-08-27 14:28:30 +02:00
songs_out = []
for song in songs:
song_id = song['id']
song_type = song['type']
preview = song['preview']
2018-11-25 23:42:24 +01:00
category_out = categories[song['category']] if song['category'] in categories else ''
song_skin_out = song_skins[song['skin_id']] if song['skin_id'] in song_skins else None
2019-11-25 01:58:07 +01:00
maker = None
if song['maker_id'] == 0:
2019-11-25 01:58:07 +01:00
maker = 0
elif song['maker_id'] and song['maker_id'] > 0:
maker = {'name': song['name'], 'url': song['url'], 'id': song['maker_id']}
2018-09-26 20:30:57 +02:00
songs_out.append({
'id': song_id,
'title': song['title'],
'title_lang': song['title_lang'],
'subtitle': song['subtitle'],
'subtitle_lang': song['subtitle_lang'],
2018-09-26 20:30:57 +02:00
'stars': [
song['easy'], song['normal'], song['hard'], song['oni'], song['ura']
2018-09-26 20:30:57 +02:00
],
'preview': preview,
2019-01-25 02:42:05 +01:00
'category': category_out,
'type': song_type,
'offset': song['offset'],
'song_skin': song_skin_out,
'volume': song['volume'],
'maker': maker,
'hash': song['hash']
2018-09-26 20:30:57 +02:00
})
2018-08-26 18:14:56 +02:00
2018-08-27 14:28:30 +02:00
return jsonify(songs_out)
2018-08-26 18:14:56 +02:00
2018-10-27 23:42:28 +02:00
@app.route('/api/config')
2019-02-14 11:31:23 +01:00
@app.cache.cached(timeout=15)
2018-10-27 23:42:28 +02:00
def route_api_config():
2018-10-28 10:59:49 +01:00
config = get_config()
2018-10-27 23:42:28 +02:00
return jsonify(config)
2019-02-20 23:02:44 +01:00
def make_preview(song_id, song_type, preview):
2018-10-17 23:16:53 +02:00
song_path = 'public/songs/%s/main.mp3' % song_id
prev_path = 'public/songs/%s/preview.mp3' % song_id
if os.path.isfile(song_path) and not os.path.isfile(prev_path):
2019-02-20 23:42:18 +01:00
if not preview or preview <= 0:
2019-02-06 19:49:25 +01:00
print('Skipping #%s due to no preview' % song_id)
2018-10-17 23:16:53 +02:00
return False
2019-02-06 19:49:25 +01:00
print('Making preview.mp3 for song #%s' % song_id)
2018-10-17 23:16:53 +02:00
ff = FFmpeg(inputs={song_path: '-ss %s' % preview},
outputs={prev_path: '-codec:a libmp3lame -ar 32000 -b:a 92k -y -loglevel panic'})
2018-10-17 23:16:53 +02:00
ff.run()
return prev_path
2018-08-26 18:14:56 +02:00
if __name__ == '__main__':
2018-08-27 14:28:30 +02:00
app.run(port=34801)