mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-11 10:27:27 +08:00
[Bug fix][Refactor] Course scores & Download
- Fix a bug that scores in course mode cannot calculate rating - Make some optimization for downloading songs
This commit is contained in:
@@ -96,6 +96,6 @@ class Constant:
|
|||||||
]
|
]
|
||||||
|
|
||||||
DATABASE_MIGRATE_TABLES = ['user', 'friend', 'best_score', 'recent30', 'user_world', 'item', 'user_item', 'purchase', 'purchase_item', 'user_save',
|
DATABASE_MIGRATE_TABLES = ['user', 'friend', 'best_score', 'recent30', 'user_world', 'item', 'user_item', 'purchase', 'purchase_item', 'user_save',
|
||||||
'login', 'present', 'user_present', 'present_item', 'redeem', 'user_redeem', 'redeem_item', 'api_login', 'chart', 'user_course', 'user_char']
|
'login', 'present', 'user_present', 'present_item', 'redeem', 'user_redeem', 'redeem_item', 'api_login', 'chart', 'user_course', 'user_char', 'user_role']
|
||||||
|
|
||||||
UPDATE_WITH_NEW_CHARACTER_DATA = Config.UPDATE_WITH_NEW_CHARACTER_DATA
|
UPDATE_WITH_NEW_CHARACTER_DATA = Config.UPDATE_WITH_NEW_CHARACTER_DATA
|
||||||
@@ -99,7 +99,7 @@ class UserDownload:
|
|||||||
def generate_token(self) -> None:
|
def generate_token(self) -> None:
|
||||||
self.token_time = int(time())
|
self.token_time = int(time())
|
||||||
self.token = md5(str(self.user.user_id) + self.song_id +
|
self.token = md5(str(self.user.user_id) + self.song_id +
|
||||||
self.file_name + str(self.token_time))
|
self.file_name + str(self.token_time) + str(os.urandom(8)))
|
||||||
|
|
||||||
def insert_download_token(self) -> None:
|
def insert_download_token(self) -> None:
|
||||||
'''将数据插入数据库,让这个下载链接可用'''
|
'''将数据插入数据库,让这个下载链接可用'''
|
||||||
@@ -111,14 +111,14 @@ class UserDownload:
|
|||||||
'''生成下载链接'''
|
'''生成下载链接'''
|
||||||
if self.token is None:
|
if self.token is None:
|
||||||
self.generate_token()
|
self.generate_token()
|
||||||
self.insert_download_token()
|
# self.insert_download_token() # 循环插入速度慢,改为executemany
|
||||||
if Constant.DOWNLOAD_LINK_PREFIX:
|
if Constant.DOWNLOAD_LINK_PREFIX:
|
||||||
prefix = Constant.DOWNLOAD_LINK_PREFIX
|
prefix = Constant.DOWNLOAD_LINK_PREFIX
|
||||||
if prefix[-1] != '/':
|
if prefix[-1] != '/':
|
||||||
prefix += '/'
|
prefix += '/'
|
||||||
return prefix + self.song_id + '/' + self.file_name + '?t=' + self.token
|
return f'{prefix}{self.song_id}/{self.file_name}?t={self.token}'
|
||||||
else:
|
else:
|
||||||
return url_for('download', file_path=self.song_id + '/' + self.file_name, t=self.token, _external=True)
|
return url_for('download', file_path=f'{self.song_id}/{self.file_name}', t=self.token, _external=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hash(self) -> str:
|
def hash(self) -> str:
|
||||||
@@ -140,67 +140,100 @@ class DownloadList(UserDownload):
|
|||||||
self.downloads: list = []
|
self.downloads: list = []
|
||||||
self.urls: dict = {}
|
self.urls: dict = {}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_all_cache():
|
||||||
|
'''清除所有歌曲文件有关缓存'''
|
||||||
|
get_song_file_md5.cache_clear()
|
||||||
|
get_only_3_song_ids.cache_clear()
|
||||||
|
DownloadList.get_one_song_file_names.cache_clear()
|
||||||
|
DownloadList.get_all_song_ids.cache_clear()
|
||||||
|
|
||||||
def clear_download_token(self) -> None:
|
def clear_download_token(self) -> None:
|
||||||
'''清除过期下载链接'''
|
'''清除过期下载链接'''
|
||||||
self.c_m.execute('''delete from download_token where time<?''',
|
self.c_m.execute('''delete from download_token where time<?''',
|
||||||
(int(time()) - Constant.DOWNLOAD_TIME_GAP_LIMIT,))
|
(int(time()) - Constant.DOWNLOAD_TIME_GAP_LIMIT,))
|
||||||
|
|
||||||
def add_one_song(self, song_id: str) -> None:
|
def insert_download_tokens(self) -> None:
|
||||||
dir_list = os.listdir(os.path.join(
|
'''插入所有下载链接'''
|
||||||
Constant.SONG_FILE_FOLDER_PATH, song_id))
|
self.c_m.executemany('''insert or replace into download_token values(?,?,?,?,?)''', [(
|
||||||
|
self.user.user_id, x.song_id, x.file_name, x.token, x.token_time) for x in self.downloads])
|
||||||
|
|
||||||
re = {}
|
@staticmethod
|
||||||
for i in dir_list:
|
@lru_cache(maxsize=2048)
|
||||||
|
def get_one_song_file_names(song_id: str) -> list:
|
||||||
|
'''获取一个歌曲文件夹下的所有合法文件名,有lru缓存'''
|
||||||
|
r = []
|
||||||
|
for i in os.listdir(os.path.join(Constant.SONG_FILE_FOLDER_PATH, song_id)):
|
||||||
if os.path.isfile(os.path.join(Constant.SONG_FILE_FOLDER_PATH, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg', '3.ogg', 'video.mp4', 'video_audio.ogg']:
|
if os.path.isfile(os.path.join(Constant.SONG_FILE_FOLDER_PATH, song_id, i)) and i in ['0.aff', '1.aff', '2.aff', '3.aff', 'base.ogg', '3.ogg', 'video.mp4', 'video_audio.ogg']:
|
||||||
if song_id in get_only_3_song_ids() and i not in ['3.aff', '3.ogg']:
|
if song_id in get_only_3_song_ids() and i not in ['3.aff', '3.ogg']:
|
||||||
continue
|
continue
|
||||||
x = UserDownload(self.c_m, self.user)
|
r.append(i)
|
||||||
# self.downloads.append(x) # 这实际上没有用
|
return r
|
||||||
x.song_id = song_id
|
|
||||||
x.file_name = i
|
|
||||||
if i == 'base.ogg':
|
|
||||||
if 'audio' not in re:
|
|
||||||
re['audio'] = {}
|
|
||||||
|
|
||||||
re['audio']["checksum"] = x.hash
|
def add_one_song(self, song_id: str) -> None:
|
||||||
if self.url_flag:
|
|
||||||
re['audio']["url"] = x.url
|
|
||||||
elif i == '3.ogg':
|
|
||||||
if 'audio' not in re:
|
|
||||||
re['audio'] = {}
|
|
||||||
|
|
||||||
if self.url_flag:
|
re = {}
|
||||||
re['audio']['3'] = {"checksum": x.hash, "url": x.url}
|
for i in self.get_one_song_file_names(song_id):
|
||||||
else:
|
x = UserDownload(self.c_m, self.user)
|
||||||
re['audio']['3'] = {"checksum": x.hash}
|
self.downloads.append(x)
|
||||||
elif i == 'video.mp4' or i == 'video_audio.ogg':
|
x.song_id = song_id
|
||||||
if 'additional_files' not in re:
|
x.file_name = i
|
||||||
re['additional_files'] = []
|
if i == 'base.ogg':
|
||||||
|
if 'audio' not in re:
|
||||||
|
re['audio'] = {}
|
||||||
|
|
||||||
if self.url_flag:
|
re['audio']["checksum"] = x.hash
|
||||||
re['additional_files'].append(
|
if self.url_flag:
|
||||||
{"checksum": x.hash, "url": x.url, 'file_name': i})
|
re['audio']["url"] = x.url
|
||||||
else:
|
elif i == '3.ogg':
|
||||||
re['additional_files'].append(
|
if 'audio' not in re:
|
||||||
{"checksum": x.hash, 'file_name': i})
|
re['audio'] = {}
|
||||||
|
|
||||||
|
if self.url_flag:
|
||||||
|
re['audio']['3'] = {"checksum": x.hash, "url": x.url}
|
||||||
else:
|
else:
|
||||||
if 'chart' not in re:
|
re['audio']['3'] = {"checksum": x.hash}
|
||||||
re['chart'] = {}
|
elif i == 'video.mp4' or i == 'video_audio.ogg':
|
||||||
|
if 'additional_files' not in re:
|
||||||
|
re['additional_files'] = []
|
||||||
|
|
||||||
if self.url_flag:
|
if self.url_flag:
|
||||||
re['chart'][i[0]] = {"checksum": x.hash, "url": x.url}
|
re['additional_files'].append(
|
||||||
else:
|
{"checksum": x.hash, "url": x.url, 'file_name': i})
|
||||||
re['chart'][i[0]] = {"checksum": x.hash}
|
else:
|
||||||
|
re['additional_files'].append(
|
||||||
|
{"checksum": x.hash, 'file_name': i})
|
||||||
|
else:
|
||||||
|
if 'chart' not in re:
|
||||||
|
re['chart'] = {}
|
||||||
|
|
||||||
|
if self.url_flag:
|
||||||
|
re['chart'][i[0]] = {"checksum": x.hash, "url": x.url}
|
||||||
|
else:
|
||||||
|
re['chart'][i[0]] = {"checksum": x.hash}
|
||||||
|
|
||||||
self.urls.update({song_id: re})
|
self.urls.update({song_id: re})
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
@lru_cache()
|
||||||
|
def get_all_song_ids() -> list:
|
||||||
|
'''获取全歌曲文件夹列表,有lru缓存'''
|
||||||
|
return list(filter(lambda x: os.path.isdir(os.path.join(Constant.SONG_FILE_FOLDER_PATH, x)), os.listdir(Constant.SONG_FILE_FOLDER_PATH)))
|
||||||
|
|
||||||
def add_songs(self, song_ids: list = None) -> None:
|
def add_songs(self, song_ids: list = None) -> None:
|
||||||
'''添加一个或多个歌曲到下载列表,若`song_ids`为空,则添加所有歌曲'''
|
'''添加一个或多个歌曲到下载列表,若`song_ids`为空,则添加所有歌曲'''
|
||||||
if song_ids is not None:
|
if song_ids is not None:
|
||||||
self.song_ids = song_ids
|
self.song_ids = song_ids
|
||||||
|
|
||||||
x = self.song_ids if self.song_ids else os.listdir(
|
if not self.song_ids:
|
||||||
Constant.SONG_FILE_FOLDER_PATH)
|
self.song_ids = self.get_all_song_ids()
|
||||||
for i in x:
|
for i in self.song_ids:
|
||||||
if os.path.isdir(os.path.join(Constant.SONG_FILE_FOLDER_PATH, i)):
|
|
||||||
self.add_one_song(i)
|
self.add_one_song(i)
|
||||||
|
else:
|
||||||
|
for i in self.song_ids:
|
||||||
|
if os.path.isdir(os.path.join(Constant.SONG_FILE_FOLDER_PATH, i)):
|
||||||
|
self.add_one_song(i)
|
||||||
|
|
||||||
|
if self.url_flag:
|
||||||
|
self.clear_download_token()
|
||||||
|
self.insert_download_tokens()
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ class UserPlay(UserScore):
|
|||||||
self.course_play_state = -1
|
self.course_play_state = -1
|
||||||
return None
|
return None
|
||||||
# raise NoData('No token data.')
|
# raise NoData('No token data.')
|
||||||
self.song.set_chart(x[2], x[3])
|
# self.song.set_chart(x[2], x[3])
|
||||||
if x[4]:
|
if x[4]:
|
||||||
self.course_play = CoursePlay(self.c, self.user, self)
|
self.course_play = CoursePlay(self.c, self.user, self)
|
||||||
self.course_play.course_id = x[4]
|
self.course_play.course_id = x[4]
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ if Config.DEPLOY_MODE == 'waitress':
|
|||||||
@app.after_request
|
@app.after_request
|
||||||
def after_request(response):
|
def after_request(response):
|
||||||
app.logger.info(
|
app.logger.info(
|
||||||
f'B {request.remote_addr} - - {request.method} {request.path} {response.status_code}')
|
f'{request.remote_addr} - - {request.method} {request.path} {response.status_code}')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@@ -116,8 +116,8 @@ def tcp_server_run():
|
|||||||
WSGIServer(host_port, app, log=app.logger).serve_forever()
|
WSGIServer(host_port, app, log=app.logger).serve_forever()
|
||||||
elif Config.DEPLOY_MODE == 'waitress':
|
elif Config.DEPLOY_MODE == 'waitress':
|
||||||
# waitress WSGI server
|
# waitress WSGI server
|
||||||
from waitress import serve
|
|
||||||
import logging
|
import logging
|
||||||
|
from waitress import serve
|
||||||
logger = logging.getLogger('waitress')
|
logger = logging.getLogger('waitress')
|
||||||
logger.setLevel(logging.INFO)
|
logger.setLevel(logging.INFO)
|
||||||
serve(app, host=Config.HOST, port=Config.PORT)
|
serve(app, host=Config.HOST, port=Config.PORT)
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
from core.constant import Constant
|
from core.constant import Constant
|
||||||
from core.course import UserCourseList
|
from core.course import UserCourseList
|
||||||
from core.error import ArcError
|
|
||||||
from core.item import ItemCore
|
from core.item import ItemCore
|
||||||
from core.sql import Connect
|
from core.sql import Connect
|
||||||
from core.user import UserOnline
|
from core.user import UserOnline
|
||||||
|
|||||||
@@ -35,8 +35,6 @@ def download_song(user_id):
|
|||||||
x.url_flag = json.loads(request.args.get('url', 'true'))
|
x.url_flag = json.loads(request.args.get('url', 'true'))
|
||||||
if x.url_flag and x.is_limited:
|
if x.url_flag and x.is_limited:
|
||||||
raise RateLimit('You have reached the download limit.', 903)
|
raise RateLimit('You have reached the download limit.', 903)
|
||||||
if x.url_flag:
|
|
||||||
x.clear_download_token()
|
|
||||||
|
|
||||||
x.add_songs()
|
x.add_songs()
|
||||||
return success_return(x.urls)
|
return success_return(x.urls)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import server.arcscore
|
import server.arcscore
|
||||||
from core.download import get_only_3_song_ids, initialize_songfile
|
from core.download import DownloadList, initialize_songfile
|
||||||
from core.init import FileChecker
|
from core.init import FileChecker
|
||||||
from core.rank import RankList
|
from core.rank import RankList
|
||||||
from core.sql import Connect
|
from core.sql import Connect
|
||||||
@@ -290,8 +290,7 @@ def update_database():
|
|||||||
def update_song_hash():
|
def update_song_hash():
|
||||||
# 更新数据库内谱面文件hash值
|
# 更新数据库内谱面文件hash值
|
||||||
try:
|
try:
|
||||||
get_only_3_song_ids.cache_clear()
|
DownloadList.clear_all_cache()
|
||||||
get_only_3_song_ids()
|
|
||||||
initialize_songfile()
|
initialize_songfile()
|
||||||
flash('数据刷新成功 Success refresh data.')
|
flash('数据刷新成功 Success refresh data.')
|
||||||
except:
|
except:
|
||||||
|
|||||||
Reference in New Issue
Block a user