Skip to content
Permalink
Browse files
Merge pull request #303 from bui/gdrive-beta
ImportSongs: Implement Google Drive beta testing
  • Loading branch information
bui committed Feb 5, 2021
2 parents bc051db + 8865ba2 commit 1fceaadc7d44423f4c4c28cc48b8ab2cf44799b5
70 app.py
@@ -9,9 +9,10 @@
import requests
import schema
import os
import time

from functools import wraps
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash
from flask import Flask, g, jsonify, render_template, request, abort, redirect, session, flash, make_response
from flask_caching import Cache
from flask_session import Session
from flask_wtf.csrf import CSRFProtect, generate_csrf, CSRFError
@@ -113,15 +114,27 @@ def before_request_func():
session.clear()


def get_config():
def get_config(credentials=False):
config_out = {
'songs_baseurl': config.SONGS_BASEURL,
'assets_baseurl': config.ASSETS_BASEURL,
'email': config.EMAIL,
'accounts': config.ACCOUNTS,
'custom_js': config.CUSTOM_JS,
'google_credentials': config.GOOGLE_CREDENTIALS
'custom_js': config.CUSTOM_JS
}
if credentials:
min_level = config.GOOGLE_CREDENTIALS['min_level'] or 0
if not session.get('username'):
user_level = 0
else:
user = db.users.find_one({'username': session.get('username')})
user_level = user['user_level']
if user_level >= min_level:
config_out['google_credentials'] = config.GOOGLE_CREDENTIALS
else:
config_out['google_credentials'] = {
'gdrive_enabled': False
}

if not config_out.get('songs_baseurl'):
config_out['songs_baseurl'] = ''.join([request.host_url, 'songs']) + '/'
@@ -342,6 +355,43 @@ def route_admin_songs_id_delete(id):
return redirect('/admin/songs')


@app.route('/admin/users')
@admin_required(level=50)
def route_admin_users():
user = db.users.find_one({'username': session.get('username')})
max_level = user['user_level'] - 1
return render_template('admin_users.html', config=get_config(), max_level=max_level, username='', level='')


@app.route('/admin/users', methods=['POST'])
@admin_required(level=50)
def route_admin_users_post():
admin_name = session.get('username')
admin = db.users.find_one({'username': admin_name})
max_level = admin['user_level'] - 1

username = request.form.get('username')
level = int(request.form.get('level')) or 0

user = db.users.find_one({'username': username})
if not user:
flash('Error: User was not found.')
elif admin_name == username:
flash('Error: You cannot modify your own level.')
else:
user_level = user['user_level']
if level < 0 or level > max_level:
flash('Error: Invalid level.')
elif user_level > max_level:
flash('Error: This user has higher level than you.')
else:
output = {'user_level': level}
db.users.update_one({'username': username}, {'$set': output})
flash('User updated.')

return render_template('admin_users.html', config=get_config(), max_level=max_level, username=username, level=level)


@app.route('/api/preview')
@app.cache.cached(timeout=15, query_string=True)
def route_api_preview():
@@ -400,7 +450,7 @@ def route_api_categories():
@app.route('/api/config')
@app.cache.cached(timeout=15)
def route_api_config():
config = get_config()
config = get_config(credentials=True)
return jsonify(config)


@@ -611,6 +661,16 @@ def route_api_scores_get():
return jsonify({'status': 'ok', 'scores': scores, 'username': user['username'], 'display_name': user['display_name'], 'don': don})


@app.route('/privacy')
def route_api_privacy():
last_modified = time.strftime('%d %B %Y', time.gmtime(os.path.getmtime('templates/privacy.txt')))
integration = config.GOOGLE_CREDENTIALS['gdrive_enabled']

response = make_response(render_template('privacy.txt', last_modified=last_modified, config=get_config(), integration=integration))
response.headers['Content-type'] = 'text/plain; charset=utf-8'
return response


def make_preview(song_id, song_type, song_ext, preview):
song_path = 'public/songs/%s/main.%s' % (song_id, song_ext)
prev_path = 'public/songs/%s/preview.mp3' % song_id
@@ -1,11 +1,11 @@
# The full URL base asset URL, with trailing slash.
ASSETS_BASEURL = ''
ASSETS_BASEURL = '/assets/'

# The full URL base song URL, with trailing slash.
SONGS_BASEURL = ''
SONGS_BASEURL = '/songs/'

# The email address to display in the "About Simulator" menu.
EMAIL = 'taiko@example.com'
EMAIL = None

# Whether to use the user account system.
ACCOUNTS = True
@@ -39,5 +39,6 @@
'gdrive_enabled': False,
'api_key': '',
'oauth_client_id': '',
'project_number': ''
'project_number': '',
'min_level': None
}
@@ -112,10 +112,15 @@ kbd{
margin-right: 0.4em;
}
.center-buttons{
display: flex;
justify-content: center;
margin: 1.5em 0;
}
.account-view .center-buttons{
margin: 0.3em 0;
}
.center-buttons>div{
text-align: center;
margin: 0.2em 0;
}
.center-buttons .taibtn{
margin: 0 0.2em;
}
@@ -93,6 +93,11 @@ class Account{
this.inputForms.push(this.accountDel.password)
this.accountDelDiv = this.getElement("accountdel-div")

this.linkPrivacy = this.getElement("privacy-btn")
this.setAltText(this.linkPrivacy, strings.account.privacy)
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
this.items.push(this.linkPrivacy)

this.logoutButton = this.getElement("logout-btn")
this.setAltText(this.logoutButton, strings.account.logout)
pageEvents.add(this.logoutButton, ["mousedown", "touchstart"], this.onLogout.bind(this))
@@ -245,6 +250,12 @@ class Account{

pageEvents.add(this.registerButton, ["mousedown", "touchstart"], this.onSwitchMode.bind(this))
this.items.push(this.registerButton)

this.linkPrivacy = this.getElement("privacy-btn")
this.setAltText(this.linkPrivacy, strings.account.privacy)
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
this.items.push(this.linkPrivacy)

if(!register){
this.items.push(this.loginButton)
}
@@ -282,11 +293,17 @@ class Account{
this.onSwitchMode()
}else if(selected === this.loginButton){
this.onLogin()
}else if(selected === this.linkPrivacy){
assets.sounds["se_don"].play()
this.openPrivacy()
}
}else if(name === "previous" || name === "next"){
selected.classList.remove("selected")
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
this.items[this.selected].classList.add("selected")
if(this.items[this.selected] === this.linkPrivacy){
this.items[this.selected].scrollIntoView()
}
assets.sounds["se_ka"].play()
}else if(name === "back"){
this.onEnd()
@@ -380,6 +397,19 @@ class Account{
}
})
}
openPrivacy(event){
if(event){
if(event.type === "touchstart"){
event.preventDefault()
}else if(event.which !== 1){
return
}
}
if(this.locked){
return
}
open("privacy")
}
onLogout(){
if(event){
if(event.type === "touchstart"){
@@ -583,6 +613,7 @@ class Account{
pageEvents.remove(this.customdonResetBtn, ["click", "touchstart"])
pageEvents.remove(this.accounPassButton, ["click", "touchstart"])
pageEvents.remove(this.accountDelButton, ["click", "touchstart"])
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
pageEvents.remove(this.logoutButton, ["mousedown", "touchstart"])
pageEvents.remove(this.saveButton, ["mousedown", "touchstart"])
for(var i = 0; i < this.inputForms.length; i++){
@@ -602,6 +633,7 @@ class Account{
delete this.accountDelButton
delete this.accountDel
delete this.accountDelDiv
delete this.linkPrivacy
delete this.logoutButton
delete this.saveButton
delete this.inputForms
@@ -615,12 +647,14 @@ class Account{
for(var i = 0; i < this.form.length; i++){
pageEvents.remove(this.registerButton, ["keydown", "keyup", "keypress"])
}
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
delete this.errorDiv
delete this.form
delete this.password2
delete this.remember
delete this.loginButton
delete this.registerButton
delete this.linkPrivacy
}
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
delete this.endButton
@@ -36,7 +36,10 @@ class CustomSongs{
this.linkLocalFolder.parentNode.removeChild(this.linkLocalFolder)
}

var groupGdrive = document.getElementById("group-gdrive")
this.linkGdriveFolder = document.getElementById("link-gdrivefolder")
this.linkGdriveAccount = document.getElementById("link-gdriveaccount")
this.linkPrivacy = document.getElementById("link-privacy")
if(gameConfig.google_credentials.gdrive_enabled){
this.setAltText(this.linkGdriveFolder, strings.customSongs.gdriveFolder)
pageEvents.add(this.linkGdriveFolder, ["mousedown", "touchstart"], this.gdriveFolder.bind(this))
@@ -45,8 +48,15 @@ class CustomSongs{
this.linkGdriveFolder.classList.add("selected")
this.selected = this.items.length - 1
}
this.setAltText(this.linkGdriveAccount, strings.customSongs.gdriveAccount)
pageEvents.add(this.linkGdriveAccount, ["mousedown", "touchstart"], this.gdriveAccount.bind(this))
this.items.push(this.linkGdriveAccount)
this.setAltText(this.linkPrivacy, strings.account.privacy)
pageEvents.add(this.linkPrivacy, ["mousedown", "touchstart"], this.openPrivacy.bind(this))
this.items.push(this.linkPrivacy)
}else{
this.linkGdriveFolder.parentNode.removeChild(this.linkGdriveFolder)
groupGdrive.style.display = "none"
this.linkPrivacy.parentNode.removeChild(this.linkPrivacy)
}

this.endButton = this.getElement("view-end-button")
@@ -237,13 +247,67 @@ class CustomSongs{
}else if(e !== "cancel"){
return Promise.reject(e)
}
}).finally(() => {
var addRemove = !gpicker || !gpicker.oauthToken ? "add" : "remove"
this.linkGdriveAccount.classList[addRemove]("hiddenbtn")
})
}
gdriveAccount(event){
if(event){
if(event.type === "touchstart"){
event.preventDefault()
}else if(event.which !== 1){
return
}
}
if(this.locked || this.mode !== "main"){
return
}
this.changeSelected(this.linkGdriveAccount)
this.locked = true
this.loading(true)
if(!gpicker){
var gpickerPromise = loader.loadScript("/src/js/gpicker.js").then(() => {
gpicker = new Gpicker()
})
}else{
var gpickerPromise = Promise.resolve()
}
gpickerPromise.then(() => {
return gpicker.switchAccounts(locked => {
this.locked = locked
this.loading(locked)
}, error => {
this.showError(error)
})
}).then(() => {
this.locked = false
this.loading(false)
}).catch(error => {
if(error !== "cancel"){
this.showError(error)
}
})
}
openPrivacy(event){
if(event){
if(event.type === "touchstart"){
event.preventDefault()
}else if(event.which !== 1){
return
}
}
if(this.locked || this.mode !== "main"){
return
}
this.changeSelected(this.linkPrivacy)
open("privacy")
}
loading(show){
if(show){
loader.screen.appendChild(this.loaderDiv)
}else{
loader.screen.removeChild(this.loaderDiv)
}else if(this.loaderDiv.parentNode){
this.loaderDiv.parentNode.removeChild(this.loaderDiv)
}
}
songsLoaded(songs){
@@ -276,11 +340,19 @@ class CustomSongs{
}else if(selected === this.linkGdriveFolder){
assets.sounds["se_don"].play()
this.gdriveFolder()
}else if(selected === this.linkGdriveAccount){
assets.sounds["se_don"].play()
this.gdriveAccount()
}else if(selected === this.linkPrivacy){
assets.sounds["se_don"].play()
this.openPrivacy()
}
}
}else if(name === "previous" || name === "next"){
selected.classList.remove("selected")
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
do{
this.selected = this.mod(this.items.length, this.selected + (name === "next" ? 1 : -1))
}while(this.items[this.selected] === this.linkPrivacy && name !== "previous")
this.items[this.selected].classList.add("selected")
assets.sounds["se_ka"].play()
}else if(name === "back" || name === "backEsc"){
@@ -327,6 +399,8 @@ class CustomSongs{
}, 500)
}
showError(text){
this.locked = false
this.loading(false)
if(this.mode === "error"){
return
}
@@ -352,6 +426,8 @@ class CustomSongs{
}
if(gameConfig.google_credentials.gdrive_enabled){
pageEvents.remove(this.linkGdriveFolder, ["mousedown", "touchstart"])
pageEvents.remove(this.linkGdriveAccount, ["mousedown", "touchstart"])
pageEvents.remove(this.linkPrivacy, ["mousedown", "touchstart"])
}
pageEvents.remove(this.endButton, ["mousedown", "touchstart"])
pageEvents.remove(this.errorDiv, ["mousedown", "touchstart"])
@@ -363,6 +439,8 @@ class CustomSongs{
delete this.browse
delete this.linkLocalFolder
delete this.linkGdriveFolder
delete this.linkGdriveAccount
delete this.linkPrivacy
delete this.endButton
delete this.items
delete this.loaderDiv

0 comments on commit 1fceaad

Please sign in to comment.