Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
minor
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
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
Christian Knuchel
minor
Commits
118d8764
Commit
118d8764
authored
Mar 02, 2019
by
Fence
🌈
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add covers resource and version api
parent
6fc121d9
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
188 additions
and
24 deletions
+188
-24
gen_test_jwt.py
gen_test_jwt.py
+2
-1
local.py
local.py
+4
-1
minor/app.py
minor/app.py
+4
-2
minor/controller/__init__.py
minor/controller/__init__.py
+2
-1
minor/controller/covers.py
minor/controller/covers.py
+123
-0
minor/controller/music.py
minor/controller/music.py
+30
-16
minor/model.py
minor/model.py
+5
-0
minor/util.py
minor/util.py
+17
-2
minor/version.py
minor/version.py
+1
-1
No files found.
gen_test_jwt.py
View file @
118d8764
...
...
@@ -2,7 +2,8 @@ import sys
import
jwt
from
datetime
import
datetime
,
timedelta
expires
=
15
expires
=
100
# todo add third argument
payload
=
{
"song"
:
"5b9ae72fc0368e3b9c8a6027"
}
key
=
None
...
...
local.py
View file @
118d8764
from
minor
import
App
app
=
App
({
"UPLOAD_DIR"
:
"./upload"
})
app
=
App
({
"MUSIC_UPLOAD_DIR"
:
"./upload"
,
"IMAGE_UPLOAD_DIR"
:
"./upload"
})
app
.
run
()
\ No newline at end of file
minor/app.py
View file @
118d8764
from
flask
import
Flask
from
minor.controller
import
ApiController
,
MusicController
from
minor.controller
import
ApiController
,
MusicController
,
CoverController
from
minor.error_handlers
import
set_error_handlers
class
App
(
object
):
...
...
@@ -13,7 +13,9 @@ class App(object):
db
.
init_app
(
self
.
_flask
)
ApiController
(
self
).
register
(
self
.
_flask
)
MusicController
(
self
.
_flask
.
config
[
"UPLOAD_DIR"
]).
register
(
self
.
_flask
)
MusicController
(
self
.
_flask
.
config
[
"MUSIC_UPLOAD_DIR"
],
self
.
_flask
.
config
[
"IMAGE_UPLOAD_DIR"
]).
register
(
self
.
_flask
)
CoverController
(
self
.
_flask
.
config
[
"IMAGE_UPLOAD_DIR"
]).
register
(
self
.
_flask
)
def
run
(
self
,
host
=
"127.0.0.1"
,
port
=
5000
):
self
.
_flask
.
run
(
host
=
host
,
port
=
port
)
...
...
minor/controller/__init__.py
View file @
118d8764
from
minor.controller.api
import
ApiController
from
minor.controller.music
import
MusicController
\ No newline at end of file
from
minor.controller.music
import
MusicController
from
minor.controller.covers
import
CoverController
minor/controller/covers.py
0 → 100644
View file @
118d8764
import
json
import
os
import
uuid
from
flask_controller
import
FlaskController
,
route
from
werkzeug.utils
import
secure_filename
from
minor.decorators
import
auth_required
from
flask
import
request
,
jsonify
,
send_file
from
minor.model
import
Song
,
Cover
from
minor.util
import
get_ext
,
img_exts
,
get_page
,
transform_mongo_dict
def
generate_file_name
(
extension
):
return
str
(
uuid
.
uuid1
())
+
"."
+
extension
@
route
(
"/api/v1/covers"
)
class
CoverController
(
FlaskController
):
def
__init__
(
self
,
upload_dir
):
self
.
_upload_dir
=
upload_dir
@
auth_required
@
route
(
"/"
,
methods
=
[
"GET"
])
def
all_covers
(
self
,
payload
=
None
):
start
=
request
.
args
.
get
(
"start"
)
try
:
if
start
is
not
None
:
start
=
int
(
start
)
else
:
start
=
0
except
ValueError
:
return
jsonify
({
"code"
:
400
,
"message"
:
"bad_request"
}),
400
limit
=
20
covers
=
get_page
(
Cover
,
start
,
limit
)
count
=
Cover
.
objects
.
count
()
# covers is an array of dicts which represent Cover models
# also songs is an array of arrays with objectid's... mongoengine is really bad for serialization
for
cover
in
covers
:
print
(
cover
)
cover
[
"songs"
]
=
list
(
map
(
lambda
s
:
s
[
0
][
"$oid"
],
cover
[
"songs"
]))
if
covers
:
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
,
"data"
:
covers
,
"count"
:
count
,
"limit"
:
limit
}),
200
else
:
return
jsonify
({
"code"
:
204
,
"message"
:
"no content"
,
"count"
:
0
,
"limit"
:
limit
}),
204
@
auth_required
@
route
(
"/<id>"
,
methods
=
[
"GET"
])
def
cover_by_id
(
self
,
id
,
payload
=
None
):
try
:
cover
=
Cover
.
objects
.
get
(
id
=
id
)
except
Cover
.
DoesNotExist
:
return
jsonify
({
"code"
:
404
,
"message"
:
"not found"
}),
404
cover
=
transform_mongo_dict
(
json
.
loads
(
cover
.
to_json
()))
# songs is an array of arrays with objectid's...
# mongoengine is really bad for serialization
cover
[
"songs"
]
=
list
(
map
(
lambda
s
:
s
[
0
][
"$oid"
],
cover
[
"songs"
]))
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
,
"data"
:
cover
}),
200
@
auth_required
@
route
(
"/<id>/file"
,
methods
=
[
"GET"
])
def
cover_file
(
self
,
id
,
payload
=
None
):
try
:
cover
=
Cover
.
objects
.
get
(
id
=
id
)
except
Cover
.
DoesNotExist
:
return
jsonify
({
"code"
:
404
,
"message"
:
"not found"
}),
404
return
send_file
(
os
.
path
.
abspath
(
os
.
path
.
join
(
self
.
_upload_dir
,
secure_filename
(
cover
.
file
))))
@
auth_required
@
route
(
"/"
,
methods
=
[
"POST"
])
def
cover_upload
(
self
,
payload
=
None
):
if
'file'
in
request
.
files
:
file
=
request
.
files
[
"file"
]
if
file
.
filename
is
not
''
:
ext
=
get_ext
(
file
.
filename
,
img_exts
)
if
ext
is
not
None
:
name
=
secure_filename
(
generate_file_name
(
ext
))
path
=
os
.
path
.
join
(
self
.
_upload_dir
,
name
)
file
.
save
(
path
)
# add new cover to db
cover
=
Cover
(
file
=
name
,
songs
=
[])
cover
.
save
()
cover
.
reload
()
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
,
"data"
:
{
"id"
:
str
(
cover
.
id
)}}),
200
return
jsonify
({
"code"
:
400
,
"message"
:
"bad_request"
}),
400
@
auth_required
@
route
(
"/<id>/song"
,
methods
=
[
"POST"
])
def
cover_add_song
(
self
,
id
,
payload
=
None
):
json
=
request
.
get_json
()
try
:
cover
=
Cover
.
objects
.
get
(
id
=
id
)
except
Cover
.
DoesNotExist
:
return
jsonify
({
"code"
:
404
,
"message"
:
"not found"
}),
404
if
"song_id"
in
json
:
try
:
song
=
Song
.
objects
.
get
(
id
=
json
[
"song_id"
])
except
Song
.
DoesNotExist
:
return
jsonify
({
"code"
:
400
,
"message"
:
"song does not exist"
}),
400
cover
.
update
(
push__songs
=
[
song
])
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
}),
200
else
:
return
jsonify
({
"code"
:
400
,
"message"
:
"bad_request"
}),
400
minor/controller/music.py
View file @
118d8764
import
os
import
os.path
import
json
from
flask
import
request
,
jsonify
,
Response
from
flask
import
request
,
jsonify
,
Response
,
send_file
from
flask_controller
import
FlaskController
,
route
from
werkzeug.utils
import
secure_filename
from
mutagen.mp3
import
MP3
from
minor.decorators
import
json_required
,
auth_required
from
minor.model
import
Song
from
minor.util
import
get_ext
,
transform_mongo_dict
from
minor.model
import
Song
,
Cover
from
minor.util
import
get_ext
,
transform_mongo_dict
,
get_page
@
route
(
"/api/music"
)
@
route
(
"/api/
v1/
music"
)
class
MusicController
(
FlaskController
):
def
__init__
(
self
,
upload_dir
):
def
__init__
(
self
,
upload_dir
,
cover_dir
):
self
.
_upload_dir
=
upload_dir
self
.
_cover_upload_dir
=
cover_dir
@
auth_required
@
route
(
"/listen"
)
...
...
@@ -37,25 +38,25 @@ class MusicController(FlaskController):
@
route
(
"/songs"
)
def
all_songs
(
self
,
payload
=
None
):
start
=
request
.
args
.
get
(
"start"
)
limit
=
20
if
start
is
None
:
start
=
0
else
:
start
=
int
(
start
)
-
1
try
:
if
start
is
not
None
:
start
=
int
(
start
)
else
:
start
=
0
except
ValueError
:
return
jsonify
({
"code"
:
400
,
"message"
:
"bad_request"
}),
400
songs
=
Song
.
objects
.
skip
(
start
).
limit
(
limit
)
count
=
Song
.
objects
.
count
()
limit
=
20
# ech mongoengine is garbage
songs_dict_arr
=
json
.
loads
(
songs
.
to_json
())
songs
=
list
(
map
(
lambda
x
:
transform_mongo_dict
(
x
),
songs_dict_arr
))
songs
=
get_page
(
Song
,
start
,
limit
)
count
=
Song
.
objects
.
count
()
# check if songs is empty
if
songs
:
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
,
"data"
:
songs
,
"count"
:
count
,
"limit"
:
limit
}),
200
else
:
return
jsonify
({
"code"
:
400
,
"message"
:
"bad_request"
}),
400
return
jsonify
({
"code"
:
204
,
"message"
:
"no content"
,
"count"
:
0
,
"limit"
:
limit
}),
204
@
auth_required
@
route
(
"/songs/<id>"
)
...
...
@@ -82,6 +83,19 @@ class MusicController(FlaskController):
else
:
return
jsonify
({
"code"
:
200
,
"message"
:
"ok"
,
"data"
:
False
}),
200
@
auth_required
@
route
(
"/songs/<id>/cover"
)
def
song_cover
(
self
,
id
,
payload
=
None
):
try
:
song
=
Song
.
objects
.
get
(
id
=
id
)
except
Song
.
DoesNotExist
:
return
jsonify
({
"code"
:
404
,
"message"
:
"not found"
}),
404
try
:
cover
=
Cover
.
objects
(
songs
=
[
song
]).
limit
(
1
).
get
()
return
send_file
(
os
.
path
.
abspath
(
os
.
path
.
join
(
self
.
_cover_upload_dir
,
secure_filename
(
cover
.
file
))))
except
Cover
.
DoesNotExist
:
return
jsonify
({
"code"
:
204
,
"message"
:
"no content"
}),
204
@
auth_required
@
json_required
@
route
(
"/songs"
,
methods
=
[
"POST"
])
...
...
minor/model.py
View file @
118d8764
...
...
@@ -15,6 +15,11 @@ class Song(Document):
playtime
=
IntField
()
class
Cover
(
Document
):
file
=
StringField
(
required
=
True
)
songs
=
ListField
(
ReferenceField
(
Song
,
reverse_delete_rule
=
CASCADE
))
class
MajorInstance
(
Document
):
issuer
=
StringField
(
required
=
True
)
key
=
StringField
(
required
=
True
)
minor/util.py
View file @
118d8764
exts
=
[
"mp3"
,
"ogg"
,
"flac"
]
import
json
img_exts
=
[
"jpg"
,
"jpeg"
,
"png"
]
song_exts
=
[
"mp3"
,
"ogg"
,
"flac"
]
def
get_ext
(
filename
):
def
get_ext
(
filename
,
exts
=
song_exts
):
if
'.'
in
filename
and
filename
.
rsplit
(
'.'
,
1
)[
1
].
lower
()
in
exts
:
return
filename
.
rsplit
(
'.'
,
1
)[
1
].
lower
()
else
:
...
...
@@ -12,3 +15,15 @@ def transform_mongo_dict(mongo_dict):
mongo_dict
[
"id"
]
=
mongo_dict
[
"_id"
][
"$oid"
]
del
mongo_dict
[
"_id"
]
return
mongo_dict
def
get_page
(
model
,
start
=
0
,
limit
=
20
):
if
start
!=
0
:
# can't really remember why we do this uhhhh
start
=
start
-
1
models
=
model
.
objects
.
skip
(
start
).
limit
(
limit
)
# ech mongoengine is garbage
dict_arr
=
json
.
loads
(
models
.
to_json
())
return
list
(
map
(
lambda
x
:
transform_mongo_dict
(
x
),
dict_arr
))
minor/version.py
View file @
118d8764
number
=
0.
1
number
=
0.
5
name
=
"minor"
\ No newline at end of file
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