-
Notifications
You must be signed in to change notification settings - Fork 1
/
music_logger.py
127 lines (102 loc) · 4.66 KB
/
music_logger.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import threading
from datetime import datetime
from json import dumps, loads
from time import sleep
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
from config import Development
from models import Track, db
app = Flask(__name__)
app.config.from_object(Development) # change loaded config name to change attributes
db.init_app(app)
socketio = SocketIO(app)
@app.route('/')
def page():
return render_template("index.html")
# for legacy programs
@app.route('/latest.json')
def latest():
return tracks_to_json(Track.query.order_by(Track.created_at).first())
@app.route('/Details')
def details():
return render_template("index.html", detailed=True)
@socketio.on('connect')
def startup():
tracks = Track.query.order_by(Track.created_at).limit(20).all()
print("got signal")
emit('connected', tracks_to_json(tracks), json=True)
@socketio.on('addTrack')
def add_track(track):
a_track = loads(track)
db_track = Track(a_track['artist'], a_track['title'], a_track['group'],
a_track['time'], a_track['request'], a_track['requester'])
db.session.add(db_track)
db.session.commit()
emit('addTracks', track, json=True, broadcast=True)
@socketio.on('updateTrack')
def update_track(track):
dict_track = loads(track)
track_to_update = Track.query.get(dict_track['id'])
for column in dict_track:
setattr(track_to_update, column, dict_track[column])
db.session.commit()
emit('updateTrack', track, json=True, broadcast=True)
@socketio.on('removeTrack')
def remove_track(track_id):
track = Track.query.get(track_id)
db.session.delete(track)
db.session.commit()
emit('removeTrack', track_id, broadcast=True)
@socketio.on('query')
def search_track(start=None, end=None, title=None, artist=None):
results = Track.query
if start is not None:
results = results.filter_by(Track.time >= start)
if end is not None:
results = results.filter_by(Track.time <= end)
if artist is not None:
results = results.filter(Track.artist.like(artist))
if title is not None:
results = results.filter(Track.title.like(artist))
emit('results', tracks_to_json(results.limit().all()), json=True)
# watch over the database and push updates when rvdl or another source updates and it does not go through the server.
# note: this might not be a good idea if the application ever has to scale since constantly checking for updates to rows
# is taxing on databases, especially mysql. If performance is bad you will have to have this server listen to rvdl's
# command output over udp instead of querying the database directly for changes. This will increase performance in all
# accept a few edge cases. However whatever you do, DO NOT OPEN UP A TRANSACTION FOR EVERY REQUEST. This leads to
# a security and memory leak issue this application was designed to fix compared to the php version.
def db_overwatch():
# TODO: have threaded function that connects to database, make updated tracks
# query: SELECT * FROM Tracks JOIN Groups ON Tracks.group_id=Groups.id WHERE Tracks.created_at >= time;
# repeat this query every few seconds, .
# If not will have to keep a local copy cached to make sure duplicates are not sent.
time = datetime.now()
old_tracks = Track.query(Track.created_at >= time).all()
while True:
new_tracks = Track.query(Track.created_at >= time).all() # get all newly created tracks since last check
new_tracks = [track for track in new_tracks if track not in old_tracks] # filter out already emitted tracks
emit("addTracks", tracks_to_json(new_tracks))
old_tracks = new_tracks + [track for track in old_tracks if track.created_at >= time]
sleep(3)
return db_overwatch()
def tracks_to_json(query):
"""function for converting tracks to json and prettifying the
json while debugging, switch to compact for deployment"""
obj = []
if isinstance(query, list):
for track in query:
obj.append({'id': track.id, 'artist': track.artist, 'title': track.title,
'time': track.created_at.strftime("%x %I:%M %p"), 'requester': track.requester,
'group': track.group.name})
else:
obj.append({'id': query.id, 'artist': query.artist, 'title': query.title,
'time': query.created_at.strftime("%x %I:%M %p"), 'requester': query.requester,
'group': query.group.name})
if app.testing:
return dumps(obj, sort_keys=True, indent=4)
else:
return dumps(obj, separators=(',', ':'))
if __name__ == '__main__':
app.run()
socketio.run(app)
threading.Thread(db_overwatch())