Bug fixes

- Fixed touch multiplayer drum being too small and nameplate drawing on top of it
- Fixed #lyric lines being forced to be lowercase and appearing too early
- Fixed exiting session while someone else is using netplay sending you to difficulty selection of the song that the netplay person has selected
- Fixed ≠MM title on song select not having the first symbol rotated
- Fixed nameplate cache in song select and in game not getting cleared
- Increased ping timeout for multiplayer

Admin page fixes
- Add meta viewport tag so that the admin pages can be opened on mobile
- On song list, songs that are not enabled are now marked
- Disable tabbing through diverge notes checkboxes in courses when adding or editing a song
- Add Hash to song adding
- Display an error if a local chart file has not been found while calculating hash
- If calculating the hash results in an error, do not discard all other changes
This commit is contained in:
LoveEevee 2020-04-17 04:53:53 +03:00
parent d98b2d9697
commit f83fab41e3
11 changed files with 97 additions and 59 deletions

25
app.py
View File

@ -67,7 +67,10 @@ def generate_hash(id, form):
else:
if url.startswith("/"):
url = url[1:]
with open(os.path.join("public", url), "rb") as file:
path = os.path.normpath(os.path.join("public", url))
if not os.path.isfile(path):
raise HashException("File not found: %s" % (os.path.abspath(path)))
with open(path, "rb") as file:
md5.update(file.read())
return base64.b64encode(md5.digest())[:-2].decode('utf-8')
@ -244,15 +247,25 @@ def route_admin_songs_new_post():
output['volume'] = float(request.form.get('volume')) or None
output['maker_id'] = int(request.form.get('maker_id')) or None
output['lyrics'] = True if request.form.get('lyrics') else False
output['hash'] = None
output['hash'] = request.form.get('hash')
seq = db.seq.find_one({'name': 'songs'})
seq_new = seq['value'] + 1 if seq else 1
hash_error = False
if request.form.get('gen_hash'):
try:
output['hash'] = generate_hash(seq_new, request.form)
except HashException as e:
hash_error = True
flash('An error occurred: %s' % str(e), 'error')
output['id'] = seq_new
output['order'] = seq_new
db.songs.insert_one(output)
flash('Song created.')
if not hash_error:
flash('Song created.')
db.seq.update_one({'name': 'songs'}, {'$set': {'value': seq_new}}, upsert=True)
@ -296,15 +309,17 @@ def route_admin_songs_id_post(id):
output['lyrics'] = True if request.form.get('lyrics') else False
output['hash'] = request.form.get('hash')
hash_error = False
if request.form.get('gen_hash'):
try:
output['hash'] = generate_hash(id, request.form)
except HashException as e:
hash_error = True
flash('An error occurred: %s' % str(e), 'error')
return redirect('/admin/songs/%s' % id)
db.songs.update_one({'id': id}, {'$set': output})
flash('Changes saved.')
if not hash_error:
flash('Changes saved.')
return redirect('/admin/songs/%s' % id)

View File

@ -56,7 +56,7 @@
ideographicComma: /[、。]/,
apostrophe: /[']/,
degree: /[゚°]/,
brackets: /[\(\)\[\]「」『』【】:;]/,
brackets: /[\(\)\[\]「」『』【】:;]/,
tilde: /[\-~〜_]/,
tall: /[bdfghj-l-t♪]/,
i: /[i]/,

View File

@ -409,10 +409,6 @@ class Loader{
})
}
clean(error){
var fontDetectDiv = document.getElementById("fontdetectHelper")
if(fontDetectDiv){
fontDetectDiv.parentNode.removeChild(fontDetectDiv)
}
delete this.loaderDiv
delete this.loaderPercentage
delete this.loaderProgress

View File

@ -153,6 +153,7 @@
var sectionBegin = true
var lastBpm = bpm
var lastGogo = gogo
var lyricsLine = null
var currentMeasure = []
var firstNote = true
@ -265,6 +266,18 @@
}
note_chain = [];
}
if("lyricsLine" in note){
if(!this.lyrics){
this.lyrics = []
}
if(this.lyrics.length !== 0){
this.lyrics[this.lyrics.length - 1].end = note.start
}
this.lyrics.push({
start: note.start,
text: note.lyricsLine
})
}
}
if (note_chain.length > 1 && currentMeasure.length >= 8) {
checkChain(note_chain, currentMeasure.length, false);
@ -281,6 +294,10 @@
lastBpm = bpm
lastGogo = gogo
}
if(lyricsLine !== null){
circleObj.lyricsLine = lyricsLine
lyricsLine = null
}
currentMeasure.push(circleObj)
}
}
@ -293,12 +310,21 @@
gogo: gogo
})
}else if(!circleObj){
currentMeasure.push({
var circleObj2 = {
bpm: bpm,
scroll: scroll
})
}
if(lyricsLine !== null){
circleObj2.lyricsLine = lyricsLine
lyricsLine = null
}
currentMeasure.push(circleObj2)
}
if(circleObj){
if(lyricsLine !== null){
circleObj.lyricsLine = lyricsLine
lyricsLine = null
}
currentMeasure.push(circleObj)
}
}
@ -307,8 +333,9 @@
var line = this.data[lineNum]
if(line.slice(0, 1) === "#"){
var line = line.slice(1).toLowerCase()
var line = line.slice(1)
var [name, value] = this.split(line, " ")
name = name.toLowerCase()
switch(name){
case "gogostart":
@ -415,16 +442,7 @@
branchObj[branchName] = currentBranch
break
case "lyric":
if(!this.lyrics){
this.lyrics = []
}
if(this.lyrics.length !== 0){
this.lyrics[this.lyrics.length - 1].end = ms
}
this.lyrics.push({
start: ms,
text: value.trim().replace(regexLinebreak, "\n")
})
lyricsLine = value.replace(regexLinebreak, "\n").trim()
break
}
@ -512,13 +530,8 @@
}
break
case ",":
if(currentMeasure.length === 0 && (bpm !== lastBpm || gogo !== lastGogo)){
insertNote({
type: "event",
bpm: bpm,
scroll: scroll,
gogo: gogo
})
if(currentMeasure.length === 0 && (bpm !== lastBpm || gogo !== lastGogo || lyricsLine !== null)){
insertBlankNote()
}
pushMeasure()
currentMeasure = []

View File

@ -2642,6 +2642,7 @@ class SongSelect{
this.difficultyCache.clean()
this.sessionCache.clean()
this.currentSongCache.clean()
this.nameplateCache.clean()
assets.sounds["bgm_songsel"].stop()
if(!this.bgmEnabled){
snd.musicGain.fadeIn()

View File

@ -591,8 +591,8 @@
this.nameplateCache.get({
ctx: ctx,
x: 320,
y: this.player === 2 ? 460 : 20,
x: touchMultiplayer ? 47 : 320,
y: touchMultiplayer ? (this.player === 2 ? 361 : 119) : (this.player === 2 ? 460 : 20),
w: 273,
h: 66,
id: "1p",
@ -743,7 +743,7 @@
y: animPos.y2
}]
var touchTop = frameTop + (touchMultiplayer ? 135 : 0)
var touchTop = frameTop + (touchMultiplayer ? 135 : 0) + (this.player === 2 ? -165 : 0)
this.touchDrum = (() => {
var sw = 842
var sh = 340
@ -2263,6 +2263,7 @@
this.comboCache.clean()
this.pauseCache.clean()
this.branchCache.clean()
this.nameplateCache.clean()
versionDiv.classList.remove("version-hide")
loader.screen.parentNode.appendChild(versionDiv)

View File

@ -52,12 +52,12 @@ async def connection(ws, path):
await ws.send(status_event())
while True:
try:
message = await asyncio.wait_for(ws.recv(), timeout=5)
message = await asyncio.wait_for(ws.recv(), timeout=10)
except asyncio.TimeoutError:
# Keep user connected
pong_waiter = await ws.ping()
try:
await asyncio.wait_for(pong_waiter, timeout=5)
await asyncio.wait_for(pong_waiter, timeout=10)
except asyncio.TimeoutError:
# Disconnect
break
@ -338,8 +338,10 @@ async def connection(ws, path):
sent_msg2 = status_event()
await asyncio.wait([
ws.send(sent_msg1),
user["other_user"]["ws"].send(sent_msg1)
])
await asyncio.wait([
ws.send(sent_msg2),
user["other_user"]["ws"].send(sent_msg1),
user["other_user"]["ws"].send(sent_msg2)
])
del user["other_user"]["other_user"]

View File

@ -3,6 +3,7 @@
<head>
<meta charset="utf-8">
<title>Taiko Web Admin</title>
<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="/src/css/admin.css" rel="stylesheet">

View File

@ -52,19 +52,19 @@
<p>Courses</p>
<label for="course_easy">Easy</label>
<input type="number" id="course_easy" value="{{song.courses.easy.stars}}" name="course_easy" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_easy" id="branch_easy"{% if song.courses.easy.branch %} checked{% endif %}><label for="branch_easy"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_easy" id="branch_easy"{% if song.courses.easy.branch %} checked{% endif %} tabindex="-1"><label for="branch_easy"> Diverge Notes</label></span>
<label for="course_normal">Normal</label>
<input type="number" id="course_normal" value="{{song.courses.normal.stars}}" name="course_normal" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_normal" id="branch_normal"{% if song.courses.normal.branch %} checked{% endif %}><label for="branch_normal"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_normal" id="branch_normal"{% if song.courses.normal.branch %} checked{% endif %} tabindex="-1"><label for="branch_normal"> Diverge Notes</label></span>
<label for="course_hard">Hard</label>
<input type="number" id="course_hard" value="{{song.courses.hard.stars}}" name="course_hard" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_hard" id="branch_hard"{% if song.courses.hard.branch %} checked{% endif %}><label for="branch_hard"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_hard" id="branch_hard"{% if song.courses.hard.branch %} checked{% endif %} tabindex="-1"><label for="branch_hard"> Diverge Notes</label></span>
<label for="course_oni">Oni</label>
<input type="number" id="course_oni" value="{{song.courses.oni.stars}}" name="course_oni" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_oni" id="branch_oni"{% if song.courses.oni.branch %} checked{% endif %}><label for="branch_oni"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_oni" id="branch_oni"{% if song.courses.oni.branch %} checked{% endif %} tabindex="-1"><label for="branch_oni"> Diverge Notes</label></span>
<label for="course_ura">Ura</label>
<input type="number" id="course_ura" value="{{song.courses.ura.stars}}" name="course_ura" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_ura" id="branch_ura"{% if song.courses.ura.branch %} checked{% endif %}><label for="branch_ura"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_ura" id="branch_ura"{% if song.courses.ura.branch %} checked{% endif %} tabindex="-1"><label for="branch_ura"> Diverge Notes</label></span>
</div>
<div class="form-field">

View File

@ -48,19 +48,19 @@
<p>Courses</p>
<label for="course_easy">Easy</label>
<input type="number" id="course_easy" value="" name="course_easy" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_easy" id="branch_easy"><label for="branch_easy"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_easy" id="branch_easy" tabindex="-1"><label for="branch_easy"> Diverge Notes</label></span>
<label for="course_normal">Normal</label>
<input type="number" id="course_normal" value="" name="course_normal" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_normal" id="branch_normal"><label for="branch_normal"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_normal" id="branch_normal" tabindex="-1"><label for="branch_normal"> Diverge Notes</label></span>
<label for="course_hard">Hard</label>
<input type="number" id="course_hard" value="" name="course_hard" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_hard" id="branch_hard"><label for="branch_hard"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_hard" id="branch_hard" tabindex="-1"><label for="branch_hard"> Diverge Notes</label></span>
<label for="course_oni">Oni</label>
<input type="number" id="course_oni" value="" name="course_oni" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_oni" id="branch_oni"><label for="branch_oni"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_oni" id="branch_oni" tabindex="-1"><label for="branch_oni"> Diverge Notes</label></span>
<label for="course_ura">Ura</label>
<input type="number" id="course_ura" value="" name="course_ura" min="0" max="10">
<span class="checkbox"><input type="checkbox" name="branch_ura" id="branch_ura"><label for="branch_ura"> Diverge Notes</label></span>
<span class="checkbox"><input type="checkbox" name="branch_ura" id="branch_ura" tabindex="-1"><label for="branch_ura"> Diverge Notes</label></span>
</div>
<div class="form-field">
@ -83,7 +83,7 @@
<div class="form-field">
<p><label for="offset">Offset</label></p>
<input type="text" id="offset" value="" name="offset" required>
<input type="text" id="offset" value="0" name="offset" required>
</div>
<div class="form-field">
@ -103,7 +103,7 @@
<div class="form-field">
<p><label for="volume">Volume</label></p>
<input type="text" id="volume" value="" name="volume" required>
<input type="text" id="volume" value="1.0" name="volume" required>
</div>
<div class="form-field">
@ -121,6 +121,11 @@
<span class="checkbox"><input type="checkbox" name="lyrics" id="lyrics"><label for="lyrics"> Enabled</label></span>
</div>
<div class="form-field">
<p><label for="hash">Hash</label></p>
<input type="text" id="hash" value="" name="hash"> <span class="checkbox"><input type="checkbox" name="gen_hash" id="gen_hash"><label for="gen_hash"> Generate</label></span>
</div>
<button type="submit" class="save-song">Save</button>
</form>
</div>

View File

@ -10,10 +10,14 @@
{% for song in songs %}
<a href="/admin/songs/{{ song.id }}" class="song-link">
<div class="song">
{% if song.title_lang.en %}
<p><span class="song-id">{{ song.id }}.</span> {{ song.title_lang.en }} <small>({{ song.title }})</small></p>
{% if song.title_lang.en and song.title_lang.en != song.title %}
<p><span class="song-id">{{ song.id }}.</span>
{% if not song.enabled %}(Not enabled){% endif %}
{{ song.title_lang.en }} <small>({{ song.title }})</small></p>
{% else %}
<p><span class="song-id">{{ song.id }}.</span> {{ song.title }}</p>
<p><span class="song-id">{{ song.id }}.</span>
{% if not song.enabled %}(Not enabled){% endif %}
{{ song.title }}</p>
{% endif %}
</div>
</a>