Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
T
Taiko Web
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Taiko Web
Commits
5a68978e
Commit
5a68978e
authored
Mar 16, 2020
by
Bui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implement song addition/deletion
parent
c63b5eba
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
305 additions
and
65 deletions
+305
-65
.gitignore
.gitignore
+1
-2
app.py
app.py
+99
-45
config.example.json
config.example.json
+0
-6
config.example.py
config.example.py
+32
-0
public/src/css/admin.css
public/src/css/admin.css
+20
-0
templates/admin_song_detail.html
templates/admin_song_detail.html
+11
-6
templates/admin_song_new.html
templates/admin_song_new.html
+121
-0
templates/admin_songs.html
templates/admin_songs.html
+6
-0
tools/migrate_db.py
tools/migrate_db.py
+15
-6
No files found.
.gitignore
View file @
5a68978e
...
...
@@ -49,6 +49,5 @@ public/api
taiko.db
version.json
public/index.html
config.
json
config.
py
public/assets/song_skins
secret.txt
app.py
View file @
5a68978e
#!/usr/bin/env python3
import
bcrypt
import
config
import
json
import
re
import
schema
...
...
@@ -14,27 +15,18 @@ from ffmpy import FFmpeg
from
pymongo
import
MongoClient
app
=
Flask
(
__name__
)
client
=
MongoClient
()
try
:
app
.
secret_key
=
open
(
'secret.txt'
)
.
read
()
.
strip
()
except
FileNotFoundError
:
app
.
secret_key
=
os
.
urandom
(
24
)
.
hex
()
with
open
(
'secret.txt'
,
'w'
)
as
fp
:
fp
.
write
(
app
.
secret_key
)
fp
.
close
()
client
=
MongoClient
(
host
=
config
.
MONGO
[
'host'
])
app
.
secret_key
=
config
.
SECRET_KEY
app
.
config
[
'SESSION_TYPE'
]
=
'redis'
app
.
config
[
'SESSION_COOKIE_HTTPONLY'
]
=
False
app
.
cache
=
Cache
(
app
,
config
=
{
'CACHE_TYPE'
:
'redis'
}
)
app
.
cache
=
Cache
(
app
,
config
=
config
.
REDIS
)
sess
=
Session
()
sess
.
init_app
(
app
)
db
=
client
.
taiko
db
=
client
[
config
.
MONGO
[
'database'
]]
db
.
users
.
create_index
(
'username'
,
unique
=
True
)
DEFAULT_URL
=
'https://github.com/bui/taiko-web/'
db
.
songs
.
create_index
(
'id'
,
unique
=
True
)
def
api_error
(
message
):
return
jsonify
({
'status'
:
'error'
,
'message'
:
message
})
...
...
@@ -49,17 +41,19 @@ def login_required(f):
return
decorated_function
def
admin_required
(
f
):
def
admin_required
(
level
):
def
decorated_function
(
f
):
@
wraps
(
f
)
def
decorated_function
(
*
args
,
**
kwargs
):
def
wrapper
(
*
args
,
**
kwargs
):
if
not
session
.
get
(
'username'
):
return
abort
(
403
)
user
=
db
.
users
.
find_one
({
'username'
:
session
.
get
(
'username'
)})
if
user
[
'user_level'
]
<
50
:
if
user
[
'user_level'
]
<
level
:
return
abort
(
403
)
return
f
(
*
args
,
**
kwargs
)
return
wrapper
return
decorated_function
...
...
@@ -71,27 +65,24 @@ def before_request_func():
def
get_config
():
if
os
.
path
.
isfile
(
'config.json'
):
try
:
config
=
json
.
load
(
open
(
'config.json'
,
'r'
))
except
ValueError
:
print
(
'WARNING: Invalid config.json, using default values'
)
config
=
{}
else
:
print
(
'WARNING: No config.json found, using default values'
)
config
=
{}
config_out
=
{
'songs_baseurl'
:
config
.
SONGS_BASEURL
,
'assets_baseurl'
:
config
.
ASSETS_BASEURL
,
'email'
:
config
.
EMAIL
,
'accounts'
:
config
.
ACCOUNTS
}
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'
])
+
'/'
if
not
config
_out
.
get
(
'songs_baseurl'
):
config
_out
[
'songs_baseurl'
]
=
''
.
join
([
request
.
host_url
,
'songs'
])
+
'/'
if
not
config
_out
.
get
(
'assets_baseurl'
):
config
_out
[
'assets_baseurl'
]
=
''
.
join
([
request
.
host_url
,
'assets'
])
+
'/'
config
[
'_version'
]
=
get_version
()
return
config
config
_out
[
'_version'
]
=
get_version
()
return
config
_out
def
get_version
():
version
=
{
'commit'
:
None
,
'commit_short'
:
''
,
'version'
:
None
,
'url'
:
DEFAULT_
URL
}
version
=
{
'commit'
:
None
,
'commit_short'
:
''
,
'version'
:
None
,
'url'
:
config
.
URL
}
if
os
.
path
.
isfile
(
'version.json'
):
try
:
ver
=
json
.
load
(
open
(
'version.json'
,
'r'
))
...
...
@@ -114,20 +105,21 @@ def route_index():
@
app
.
route
(
'/admin'
)
@
admin_required
@
admin_required
(
level
=
50
)
def
route_admin
():
return
redirect
(
'/admin/songs'
)
@
app
.
route
(
'/admin/songs'
)
@
admin_required
@
admin_required
(
level
=
50
)
def
route_admin_songs
():
songs
=
db
.
songs
.
find
({})
return
render_template
(
'admin_songs.html'
,
songs
=
list
(
songs
))
user
=
db
.
users
.
find_one
({
'username'
:
session
[
'username'
]})
return
render_template
(
'admin_songs.html'
,
songs
=
list
(
songs
),
admin
=
user
)
@
app
.
route
(
'/admin/songs/<int:id>'
)
@
admin_required
@
admin_required
(
level
=
50
)
def
route_admin_songs_id
(
id
):
song
=
db
.
songs
.
find_one
({
'id'
:
id
})
if
not
song
:
...
...
@@ -142,8 +134,58 @@ def route_admin_songs_id(id):
song
=
song
,
categories
=
categories
,
song_skins
=
song_skins
,
makers
=
makers
,
admin
=
user
)
@
app
.
route
(
'/admin/songs/new'
)
@
admin_required
(
level
=
100
)
def
route_admin_songs_new
():
categories
=
list
(
db
.
categories
.
find
({}))
song_skins
=
list
(
db
.
song_skins
.
find
({}))
makers
=
list
(
db
.
makers
.
find
({}))
return
render_template
(
'admin_song_new.html'
,
categories
=
categories
,
song_skins
=
song_skins
,
makers
=
makers
)
@
app
.
route
(
'/admin/songs/new'
,
methods
=
[
'POST'
])
@
admin_required
(
level
=
100
)
def
route_admin_songs_new_post
():
output
=
{
'title_lang'
:
{},
'subtitle_lang'
:
{},
'courses'
:
{}}
output
[
'enabled'
]
=
True
if
request
.
form
.
get
(
'enabled'
)
else
False
output
[
'title'
]
=
request
.
form
.
get
(
'title'
)
or
None
output
[
'subtitle'
]
=
request
.
form
.
get
(
'subtitle'
)
or
None
for
lang
in
[
'ja'
,
'en'
,
'cn'
,
'tw'
,
'ko'
]:
output
[
'title_lang'
][
lang
]
=
request
.
form
.
get
(
'title_
%
s'
%
lang
)
or
None
output
[
'subtitle_lang'
][
lang
]
=
request
.
form
.
get
(
'subtitle_
%
s'
%
lang
)
or
None
for
course
in
[
'easy'
,
'normal'
,
'hard'
,
'oni'
,
'ura'
]:
if
request
.
form
.
get
(
'course_
%
s'
%
course
):
output
[
'courses'
][
course
]
=
{
'stars'
:
int
(
request
.
form
.
get
(
'course_
%
s'
%
course
)),
'branch'
:
True
if
request
.
form
.
get
(
'branch_
%
s'
%
course
)
else
False
}
else
:
output
[
'courses'
][
course
]
=
None
output
[
'category_id'
]
=
int
(
request
.
form
.
get
(
'category_id'
))
or
None
output
[
'type'
]
=
request
.
form
.
get
(
'type'
)
output
[
'offset'
]
=
float
(
request
.
form
.
get
(
'offset'
))
or
None
output
[
'skin_id'
]
=
int
(
request
.
form
.
get
(
'skin_id'
))
or
None
output
[
'preview'
]
=
float
(
request
.
form
.
get
(
'preview'
))
or
None
output
[
'volume'
]
=
float
(
request
.
form
.
get
(
'volume'
))
or
None
output
[
'maker_id'
]
=
int
(
request
.
form
.
get
(
'maker_id'
))
or
None
output
[
'hash'
]
=
None
seq
=
db
.
seq
.
find_one
({
'name'
:
'songs'
})
seq_new
=
seq
[
'value'
]
+
1
if
seq
else
1
output
[
'id'
]
=
seq_new
output
[
'order'
]
=
seq_new
db
.
songs
.
insert_one
(
output
)
flash
(
'Song created.'
)
db
.
seq
.
update_one
({
'name'
:
'songs'
},
{
'$set'
:
{
'value'
:
seq_new
}},
upsert
=
True
)
return
redirect
(
'/admin/songs/
%
s'
%
str
(
seq_new
))
@
app
.
route
(
'/admin/songs/<int:id>'
,
methods
=
[
'POST'
])
@
admin_required
@
admin_required
(
level
=
100
)
def
route_admin_songs_id_post
(
id
):
song
=
db
.
songs
.
find_one
({
'id'
:
id
})
if
not
song
:
...
...
@@ -183,6 +225,18 @@ def route_admin_songs_id_post(id):
return
redirect
(
'/admin/songs/
%
s'
%
id
)
@
app
.
route
(
'/admin/songs/<int:id>/delete'
,
methods
=
[
'POST'
])
@
admin_required
(
level
=
100
)
def
route_admin_songs_id_delete
(
id
):
song
=
db
.
songs
.
find_one
({
'id'
:
id
})
if
not
song
:
return
abort
(
404
)
db
.
songs
.
delete_one
({
'id'
:
id
})
flash
(
'Song deleted.'
)
return
redirect
(
'/admin/songs'
)
@
app
.
route
(
'/api/preview'
)
@
app
.
cache
.
cached
(
timeout
=
15
,
query_string
=
True
)
def
route_api_preview
():
...
...
config.example.json
deleted
100644 → 0
View file @
c63b5eba
{
"songs_baseurl"
:
""
,
"assets_baseurl"
:
""
,
"email"
:
""
,
"accounts"
:
true
}
config.example.py
0 → 100644
View file @
5a68978e
# The full URL base asset URL, with trailing slash.
ASSETS_BASEURL
=
''
# The full URL base song URL, with trailing slash.
SONGS_BASEURL
=
''
# The email address to display in the "About Simulator" menu.
EMAIL
=
'taiko@example.com'
# Whether to use the user account system.
ACCOUNTS
=
True
# MongoDB server settings.
MONGO
=
{
'host'
:
[
'localhost:27017'
],
'database'
:
'taiko'
}
# Redis server settings, used for sessions + cache.
REDIS
=
{
'CACHE_TYPE'
:
'redis'
,
'CACHE_REDIS_HOST'
:
'127.0.0.1'
,
'CACHE_REDIS_PORT'
:
6379
,
'CACHE_REDIS_PASSWORD'
:
None
,
'CACHE_REDIS_DB'
:
None
}
# Secret key used for sessions.
SECRET_KEY
=
'change-me'
# Git repository base URL.
URL
=
'https://github.com/bui/taiko-web/'
public/src/css/admin.css
View file @
5a68978e
...
...
@@ -130,3 +130,23 @@ h1 small {
margin-bottom
:
10px
;
color
:
white
;
}
.save-song
{
font-size
:
22pt
;
width
:
120px
;
}
.delete-song
button
{
float
:
right
;
margin-top
:
-25px
;
font-size
:
12pt
;
}
.side-button
{
float
:
right
;
background
:
green
;
padding
:
5px
20px
;
color
:
white
;
text-decoration
:
none
;
margin-top
:
25px
;
}
templates/admin_song_detail.html
View file @
5a68978e
...
...
@@ -46,19 +46,19 @@
<div
class=
"form-field"
>
<p>
Courses
</p>
<label
for=
"course_easy"
>
Easy
</label>
<input
type=
"number"
id=
"course_easy"
value=
"{{song.courses.easy.stars}}"
name=
"course_easy"
min=
"
1
"
max=
"10"
>
<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>
<label
for=
"course_normal"
>
Normal
</label>
<input
type=
"number"
id=
"course_normal"
value=
"{{song.courses.normal.stars}}"
name=
"course_normal"
min=
"
1
"
max=
"10"
>
<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>
<label
for=
"course_hard"
>
Hard
</label>
<input
type=
"number"
id=
"course_hard"
value=
"{{song.courses.hard.stars}}"
name=
"course_hard"
min=
"
1
"
max=
"10"
>
<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>
<label
for=
"course_oni"
>
Oni
</label>
<input
type=
"number"
id=
"course_oni"
value=
"{{song.courses.oni.stars}}"
name=
"course_oni"
min=
"
1
"
max=
"10"
>
<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>
<label
for=
"course_ura"
>
Ura
</label>
<input
type=
"number"
id=
"course_ura"
value=
"{{song.courses.ura.stars}}"
name=
"course_ura"
min=
"
1
"
max=
"10"
>
<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>
</div>
...
...
@@ -115,7 +115,12 @@
</select>
</div>
<button
type=
"submit"
>
Save
</button>
<button
type=
"submit"
class=
"save-song"
>
Save
</button>
</form>
{% if admin.user_level >= 100 %}
<form
class=
"delete-song"
method=
"post"
action=
"/admin/songs/{{song.id}}/delete"
onsubmit=
"return confirm('Are you sure you wish to delete this song?');"
>
<button
type=
"submit"
>
Delete song
</button>
</form>
{% endif %}
</div>
{% endblock %}
templates/admin_song_new.html
0 → 100644
View file @
5a68978e
{% extends 'admin.html' %}
{% block content %}
<h1>
New song
</h1>
{% for message in get_flashed_messages() %}
<div
class=
"message"
>
{{ message }}
</div>
{% endfor %}
<div
class=
"song-form"
>
<form
method=
"post"
>
<div
class=
"form-field"
>
<span
class=
"checkbox"
><input
type=
"checkbox"
name=
"enabled"
id=
"enabled"
checked
><label
for=
"enabled"
>
Enabled
</label></span>
</div>
<div
class=
"form-field"
>
<p>
Title
</p>
<label
for=
"title"
>
Original
</label>
<input
type=
"text"
id=
"title"
value=
""
name=
"title"
required
>
<label
for=
"title_ja"
>
Japanese
</label>
<input
type=
"text"
id=
"title_ja"
value=
""
name=
"title_ja"
>
<label
for=
"title_en"
>
English
</label>
<input
type=
"text"
id=
"title_en"
value=
""
name=
"title_en"
>
<label
for=
"title_cn"
>
Chinese (Simplified)
</label>
<input
type=
"text"
id=
"title_cn"
value=
""
name=
"title_cn"
>
<label
for=
"title_tw"
>
Chinese (Traditional)
</label>
<input
type=
"text"
id=
"title_tw"
value=
""
name=
"title_tw"
>
<label
for=
"title_ko"
>
Korean
</label>
<input
type=
"text"
id=
"title_ko"
value=
""
name=
"title_ko"
>
</div>
<div
class=
"form-field"
>
<p>
Subtitle
</p>
<label
for=
"subtitle"
>
Original
</label>
<input
type=
"text"
id=
"subtitle"
value=
""
name=
"subtitle"
>
<label
for=
"subtitle_ja"
>
Japanese
</label>
<input
type=
"text"
id=
"subtitle_ja"
value=
""
name=
"subtitle_ja"
>
<label
for=
"subtitle_en"
>
English
</label>
<input
type=
"text"
id=
"subtitle_en"
value=
""
name=
"subtitle_en"
>
<label
for=
"subtitle_cn"
>
Chinese (Simplified)
</label>
<input
type=
"text"
id=
"subtitle_cn"
value=
""
name=
"subtitle_cn"
>
<label
for=
"subtitle_tw"
>
Chinese (Traditional)
</label>
<input
type=
"text"
id=
"subtitle_tw"
value=
""
name=
"subtitle_tw"
>
<label
for=
"subtitle_ko"
>
Korean
</label>
<input
type=
"text"
id=
"subtitle_ko"
value=
""
name=
"subtitle_ko"
>
</div>
<div
class=
"form-field"
>
<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>
<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>
<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>
<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>
<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>
</div>
<div
class=
"form-field"
>
<p><label
for=
"category_id"
>
Category
</label></p>
<select
name=
"category_id"
id=
"category_id"
>
<option
value=
"0"
>
(none)
</option>
{% for category in categories %}
<option
value=
"{{ category.id }}"
>
{{ category.title }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"form-field"
>
<p><label
for=
"type"
>
Type
</label></p>
<select
name=
"type"
id=
"type"
>
<option
value=
"tja"
>
TJA
</option>
<option
value=
"osu"
>
osu!taiko
</option>
</select>
</div>
<div
class=
"form-field"
>
<p><label
for=
"offset"
>
Offset
</label></p>
<input
type=
"text"
id=
"offset"
value=
""
name=
"offset"
required
>
</div>
<div
class=
"form-field"
>
<p><label
for=
"skin_id"
>
Skin
</label></p>
<select
name=
"skin_id"
id=
"skin_id"
>
<option
value=
"0"
>
(none)
</option>
{% for skin in song_skins %}
<option
value=
"{{ skin.id }}"
>
{{ skin.name }}
</option>
{% endfor %}
</select>
</div>
<div
class=
"form-field"
>
<p><label
for=
"preview"
>
Preview
</label></p>
<input
type=
"text"
id=
"preview"
value=
""
name=
"preview"
required
>
</div>
<div
class=
"form-field"
>
<p><label
for=
"volume"
>
Volume
</label></p>
<input
type=
"text"
id=
"volume"
value=
""
name=
"volume"
required
>
</div>
<div
class=
"form-field"
>
<p><label
for=
"maker_id"
>
Maker
</label></p>
<select
name=
"maker_id"
id=
"maker_id"
>
<option
value=
"0"
>
(none)
</option>
{% for maker in makers %}
<option
value=
"{{ maker.id }}"
>
{{ maker.name }}
</option>
{% endfor %}
</select>
</div>
<button
type=
"submit"
class=
"save-song"
>
Save
</button>
</form>
</div>
{% endblock %}
templates/admin_songs.html
View file @
5a68978e
{% extends 'admin.html' %}
{% block content %}
{% if admin.user_level >= 100 %}
<a
href=
"/admin/songs/new"
class=
"side-button"
>
New song
</a>
{% endif %}
<h1>
Songs
</h1>
{% for message in get_flashed_messages() %}
<div
class=
"message"
>
{{ message }}
</div>
{% endfor %}
{% for song in songs %}
<a
href=
"/admin/songs/{{ song.id }}"
class=
"song-link"
>
<div
class=
"song"
>
...
...
tools/migrate_db.py
View file @
5a68978e
...
...
@@ -4,24 +4,30 @@
import
sqlite3
from
pymongo
import
MongoClient
client
=
MongoClient
()
client
.
drop_database
(
'taiko'
)
db
=
client
.
taiko
import
os
,
sys
,
inspect
current_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
inspect
.
getfile
(
inspect
.
currentframe
())))
parent_dir
=
os
.
path
.
dirname
(
current_dir
)
sys
.
path
.
insert
(
0
,
parent_dir
)
import
config
client
=
MongoClient
(
config
.
MONGO
[
'host'
])
client
.
drop_database
(
config
.
MONGO
[
'database'
])
db
=
client
[
config
.
MONGO
[
'database'
]]
sqdb
=
sqlite3
.
connect
(
'taiko.db'
)
sqdb
.
row_factory
=
sqlite3
.
Row
curs
=
sqdb
.
cursor
()
def
migrate_songs
():
curs
.
execute
(
'select * from songs'
)
curs
.
execute
(
'select * from songs
order by id
'
)
rows
=
curs
.
fetchall
()
for
row
in
rows
:
song
=
{
'id'
:
row
[
'id'
],
'title'
:
row
[
'title'
],
'title_lang'
:
{
'ja'
:
row
[
'title'
]},
'title_lang'
:
{
'ja'
:
row
[
'title'
]
,
'en'
:
None
,
'cn'
:
None
,
'tw'
:
None
,
'ko'
:
None
},
'subtitle'
:
row
[
'subtitle'
],
'subtitle_lang'
:
{
'ja'
:
row
[
'subtitle'
]},
'subtitle_lang'
:
{
'ja'
:
row
[
'subtitle'
]
,
'en'
:
None
,
'cn'
:
None
,
'tw'
:
None
,
'ko'
:
None
},
'courses'
:
{
'easy'
:
None
,
'normal'
:
None
,
'hard'
:
None
,
'oni'
:
None
,
'ura'
:
None
},
'enabled'
:
True
if
row
[
'enabled'
]
else
False
,
'category_id'
:
row
[
'category'
],
...
...
@@ -63,6 +69,9 @@ def migrate_songs():
song
[
'subtitle_lang'
][
'en'
]
=
lang
db
.
songs
.
insert_one
(
song
)
last_song
=
song
[
'id'
]
db
.
seq
.
insert_one
({
'name'
:
'songs'
,
'value'
:
last_song
})
def
migrate_makers
():
curs
.
execute
(
'select * from makers'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment