[Enhance] API & LinkPlay & something else

- Add song names for getting the score list (For API)
- Try to ensure thread safety in Link Play (twice again)
- Small change about database timeout
- Have a try to use `nginx` and `gevent` (Yes. I ensure it works well. This will not be viewed as a formal and necessary update.)
This commit is contained in:
Lost-MSth
2022-10-03 23:46:52 +08:00
parent 299c8c582c
commit 8f1c28eb5c
7 changed files with 118 additions and 88 deletions

View File

@@ -90,6 +90,7 @@ def users_user_b30_get(user, user_id):
x = UserScoreList(c, UserInfo(c, user_id))
x.query.limit = 30
x.select_from_user()
x.select_song_name()
r = x.to_dict_list()
rating_sum = sum([i.rating for i in x.scores])
return success_return({'user_id': user_id, 'b30_ptt': rating_sum / 30, 'data': r})

View File

@@ -3,6 +3,8 @@ from functools import lru_cache
from json import loads
from time import time
from flask import url_for
from .constant import Constant
from .error import NoAccess
from .user import User
@@ -118,7 +120,6 @@ class UserDownload:
prefix += '/'
return prefix + self.song_id + '/' + self.file_name + '?t=' + self.token
else:
from flask import url_for
return url_for('download', file_path=self.song_id + '/' + self.file_name, t=self.token, _external=True)
@property

View File

@@ -128,7 +128,7 @@ class Score:
return self.rating
def to_dict(self) -> dict:
return {
r = {
"rating": self.rating,
"modifier": self.modifier,
"time_played": self.time_played,
@@ -142,6 +142,9 @@ class Score:
"difficulty": self.song.difficulty,
"song_id": self.song.song_id
}
if self.song.song_name is not None:
r["song_name"] = self.song.song_name
return r
class UserScore(Score):
@@ -569,3 +572,12 @@ class UserScoreList:
x = Sql(self.c).select('best_score', query=self.query)
self.scores = [UserScore(self.c, self.user).from_list(i) for i in x]
def select_song_name(self) -> None:
'''为所有成绩中的song_id查询song_name'''
if self.scores is None:
return
for score in self.scores:
self.c.execute(
'''select name from chart where song_id = ?''', (score.song.song_id,))
score.song.song_name = self.c.fetchone()[0]

View File

@@ -8,6 +8,7 @@ class Chart:
self.c = c
self.set_chart(song_id, difficulty)
self.defnum: int = None
self.song_name: str = None
def to_dict(self) -> dict:
return {

View File

@@ -19,7 +19,7 @@ class Connect:
self.file_path = file_path
def __enter__(self):
self.conn = sqlite3.connect(self.file_path)
self.conn = sqlite3.connect(self.file_path, timeout=10)
self.c = self.conn.cursor()
return self.c

View File

@@ -65,30 +65,27 @@ def clear_room(room):
def memory_clean(now):
# 内存清理
lock.acquire()
with lock:
clean_room_list = []
clean_player_list = []
for token in link_play_data:
room = link_play_data[token]['room']
if now - room.timestamp >= Config.TIME_LIMIT:
clean_room_list.append(room.room_id)
clean_room_list = []
clean_player_list = []
for token in link_play_data:
room = link_play_data[token]['room']
if now - room.timestamp >= Config.TIME_LIMIT:
clean_room_list.append(room.room_id)
if now - room.players[link_play_data[token]['player_index']].last_timestamp // 1000 >= Config.TIME_LIMIT:
clean_player_list.append(token)
if now - room.players[link_play_data[token]['player_index']].last_timestamp // 1000 >= Config.TIME_LIMIT:
clean_player_list.append(token)
for room_id in room_id_dict:
if now - room_id_dict[room_id].timestamp >= Config.TIME_LIMIT:
clean_room_list.append(room_id)
for room_id in room_id_dict:
if now - room_id_dict[room_id].timestamp >= Config.TIME_LIMIT:
clean_room_list.append(room_id)
for room_id in clean_room_list:
if room_id in room_id_dict:
clear_room(room_id_dict[room_id])
for room_id in clean_room_list:
if room_id in room_id_dict:
clear_room(room_id_dict[room_id])
for token in clean_player_list:
clear_player(token)
lock.release()
for token in clean_player_list:
clear_player(token)
class UDP_handler(socketserver.BaseRequestHandler):
@@ -163,35 +160,37 @@ def data_swap(data: list) -> str:
song_unlock = base64.b64decode(data[2])
key = urandom(16)
room_id = unique_random(room_id_dict)
with lock:
room_id = unique_random(room_id_dict)
room = Room()
room.room_id = room_id
room_id_dict[room_id] = room
room = Room()
room.room_id = room_id
room_id_dict[room_id] = room
player_id = unique_random(player_dict, 3)
player = Player()
player.player_id = player_id
player.set_player_name(name)
player_dict[player_id] = player
player_id = unique_random(player_dict, 3)
player = Player()
player.player_id = player_id
player.set_player_name(name)
player_dict[player_id] = player
player.song_unlock = song_unlock
room.song_unlock = song_unlock
room.host_id = player_id
room.players[0] = player
room.player_num = 1
player.song_unlock = song_unlock
room.song_unlock = song_unlock
room.host_id = player_id
room.players[0] = player
room.player_num = 1
room_code = unique_random(room_code_dict, random_func=random_room_code)
room.room_code = room_code
room_code_dict[room_code] = room
room_code = unique_random(
room_code_dict, random_func=random_room_code)
room.room_code = room_code
room_code_dict[room_code] = room
token = room_id
player.token = token
token = room_id
player.token = token
link_play_data[token] = {'key': key,
'room': room,
'player_index': 0,
'player_id': player_id}
link_play_data[token] = {'key': key,
'room': room,
'player_index': 0,
'player_id': player_id}
logging.info('TCP-Create room `%s` by player `%s`' % (room_code, name))
return '|'.join([str(x) for x in (0, room_code, room_id, token, base64.b64encode(key).decode('utf-8'), player_id)])
@@ -201,42 +200,43 @@ def data_swap(data: list) -> str:
# data = ['2', name, song_unlock, room_code]
# song_unlock: base64 str
room_code = data[3].upper()
with lock:
if room_code not in room_code_dict:
# 房间号错误
return '1202'
room = room_code_dict[room_code]
if room_code not in room_code_dict:
# 房间号错误
return '1202'
room = room_code_dict[room_code]
if room.player_num == 4:
# 满人
return '1201'
elif room.state != 2:
# 无法加入
return '1205'
if room.player_num == 4:
# 满人
return '1201'
elif room.state != 2:
# 无法加入
return '1205'
name = data[1]
song_unlock = base64.b64decode(data[2])
key = urandom(16)
token = unique_random(link_play_data)
player_id = unique_random(player_dict, 3)
with lock:
token = unique_random(link_play_data)
player_id = unique_random(player_dict, 3)
player = Player()
player.player_id = player_id
player.set_player_name(name)
player.token = token
player_dict[player_id] = player
player.song_unlock = song_unlock
room.update_song_unlock()
for i in range(4):
if room.players[i].player_id == 0:
room.players[i] = player
player_index = i
break
link_play_data[token] = {'key': key,
'room': room,
'player_index': player_index,
'player_id': player_id}
player = Player()
player.player_id = player_id
player.set_player_name(name)
player.token = token
player_dict[player_id] = player
player.song_unlock = song_unlock
room.update_song_unlock()
for i in range(4):
if room.players[i].player_id == 0:
room.players[i] = player
player_index = i
break
link_play_data[token] = {'key': key,
'room': room,
'player_index': player_index,
'player_id': player_id}
logging.info('TCP-Player `%s` joins room `%s`' % (name, room_code))
return '|'.join([str(x) for x in (0, room_code, room.room_id, token, base64.b64encode(key).decode('utf-8'), player_id, base64.b64encode(room.song_unlock).decode('utf-8'))])
@@ -245,12 +245,13 @@ def data_swap(data: list) -> str:
# 房间信息更新
# data = ['3', token]
token = int(data[1])
if token in link_play_data:
r = link_play_data[token]
logging.info('TCP-Room `%s` info update' % room_code)
return '|'.join([str(x) for x in (0, r['room'].room_code, r['room'].room_id, base64.b64encode(r['key']).decode('utf-8'), r['room'].players[r['player_index']].player_id, base64.b64encode(r['room'].song_unlock).decode('utf-8'))])
else:
return '108'
with lock:
if token in link_play_data:
r = link_play_data[token]
logging.info('TCP-Room `%s` info update' % room_code)
return '|'.join([str(x) for x in (0, r['room'].room_code, r['room'].room_id, base64.b64encode(r['key']).decode('utf-8'), r['room'].players[r['player_index']].player_id, base64.b64encode(r['room'].song_unlock).decode('utf-8'))])
else:
return '108'
def link_play(ip: str = Config.HOST, udp_port: int = Config.UDP_PORT, tcp_port: int = Config.TCP_PORT):

View File

@@ -6,7 +6,7 @@ from logging.config import dictConfig
from multiprocessing import Process, set_start_method
from traceback import format_exc
from flask import Flask, request, send_from_directory
from flask import Flask, make_response, request, send_from_directory
import api
import server
@@ -14,14 +14,20 @@ import server.init
import web.index
import web.login
from core.constant import Constant
from core.download import UserDownload, initialize_songfile, get_only_3_song_ids
from core.download import (UserDownload, get_only_3_song_ids,
initialize_songfile)
from core.error import ArcError
from core.sql import Connect
from server.func import error_return
from setting import Config
app = Flask(__name__)
wsgi_app = app.wsgi_app
# from werkzeug.middleware.proxy_fix import ProxyFix
# app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
# from flask_cors import CORS
# CORS(app, supports_credentials=True)
os.chdir(sys.path[0]) # 更改工作路径,以便于愉快使用相对路径
@@ -59,6 +65,10 @@ def download(file_path):
raise ArcError('You have reached the download limit.', 903)
if x.is_valid:
x.insert_user_download()
# response = make_response()
# response.headers['Content-Type'] = 'application/octet-stream'
# response.headers['X-Accel-Redirect'] = '/nginx_download/' + file_path
# return response
return send_from_directory(Constant.SONG_FILE_FOLDER_PATH, file_path, as_attachment=True, conditional=True)
except ArcError as e:
if Config.ALLOW_WARNING_LOG:
@@ -68,11 +78,15 @@ def download(file_path):
def tcp_server_run():
if Config.SSL_CERT and Config.SSL_KEY:
app.run(Config.HOST, Config.PORT, ssl_context=(
Config.SSL_CERT, Config.SSL_KEY))
if False:
from gevent.pywsgi import WSGIServer
WSGIServer(("127.0.0.1", 5000), app).serve_forever()
else:
app.run(Config.HOST, Config.PORT)
if Config.SSL_CERT and Config.SSL_KEY:
app.run(Config.HOST, Config.PORT, ssl_context=(
Config.SSL_CERT, Config.SSL_KEY))
else:
app.run(Config.HOST, Config.PORT)
def main():