mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-10 01:37:27 +08:00
[Bug Fix][Enhance] PTT update lately & Register rate limiter
- Fix a bug that PTT updates delay to next play. - Add the IP and the device rate limiters for user register.
This commit is contained in:
@@ -32,6 +32,7 @@ CODE_MSG = {
|
|||||||
-210: 'Username exists',
|
-210: 'Username exists',
|
||||||
-211: 'Email address exists',
|
-211: 'Email address exists',
|
||||||
-212: 'User code exists',
|
-212: 'User code exists',
|
||||||
|
-213: 'Too many register attempts',
|
||||||
-999: 'Unknown error'
|
-999: 'Unknown error'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,6 +100,8 @@ class Config:
|
|||||||
|
|
||||||
GAME_LOGIN_RATE_LIMIT = '30/5 minutes'
|
GAME_LOGIN_RATE_LIMIT = '30/5 minutes'
|
||||||
API_LOGIN_RATE_LIMIT = '10/5 minutes'
|
API_LOGIN_RATE_LIMIT = '10/5 minutes'
|
||||||
|
GAME_REGISTER_IP_RATE_LIMIT = '10/1 day'
|
||||||
|
GAME_REGISTER_DEVICE_RATE_LIMIT = '3/1 day'
|
||||||
|
|
||||||
|
|
||||||
NOTIFICATION_EXPIRE_TIME = 3 * 60 * 1000
|
NOTIFICATION_EXPIRE_TIME = 3 * 60 * 1000
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from .config_manager import Config
|
from .config_manager import Config
|
||||||
|
|
||||||
ARCAEA_SERVER_VERSION = 'v2.11.3.19'
|
ARCAEA_SERVER_VERSION = 'v2.11.3.20'
|
||||||
ARCAEA_DATABASE_VERSION = 'v2.11.3.19'
|
ARCAEA_DATABASE_VERSION = 'v2.11.3.19'
|
||||||
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class Score:
|
|||||||
# 谱面定数小于等于 0 视为 unranked,返回值会为 0
|
# 谱面定数小于等于 0 视为 unranked,返回值会为 0
|
||||||
if not defnum or defnum <= 0:
|
if not defnum or defnum <= 0:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
all_note = perfect_count + near_count + miss_count
|
all_note = perfect_count + near_count + miss_count
|
||||||
if all_note == 0:
|
if all_note == 0:
|
||||||
return 0
|
return 0
|
||||||
@@ -281,7 +281,8 @@ class UserPlay(UserScore):
|
|||||||
if songfile_hash and songfile_hash != self.song_hash:
|
if songfile_hash and songfile_hash != self.song_hash:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
x = f'''{self.song_token}{self.song_hash}{self.song.song_id}{self.song.difficulty}{self.score}{self.shiny_perfect_count}{self.perfect_count}{self.near_count}{self.miss_count}{self.health}{self.modifier}{self.clear_type}'''
|
x = f'''{self.song_token}{self.song_hash}{self.song.song_id}{self.song.difficulty}{self.score}{self.shiny_perfect_count}{
|
||||||
|
self.perfect_count}{self.near_count}{self.miss_count}{self.health}{self.modifier}{self.clear_type}'''
|
||||||
if self.combo_interval_bonus is not None:
|
if self.combo_interval_bonus is not None:
|
||||||
if self.combo_interval_bonus < 0 or self.combo_interval_bonus > self.all_note_count / 150:
|
if self.combo_interval_bonus < 0 or self.combo_interval_bonus > self.all_note_count / 150:
|
||||||
return False
|
return False
|
||||||
@@ -569,6 +570,18 @@ class Potential:
|
|||||||
(self.user.user_id, r_index, user_score.time_played, user_score.song.song_id, user_score.song.difficulty,
|
(self.user.user_id, r_index, user_score.time_played, user_score.song.song_id, user_score.song.difficulty,
|
||||||
user_score.score, user_score.shiny_perfect_count, user_score.perfect_count, user_score.near_count, user_score.miss_count, user_score.health, user_score.modifier, user_score.clear_type, user_score.rating))
|
user_score.score, user_score.shiny_perfect_count, user_score.perfect_count, user_score.near_count, user_score.miss_count, user_score.health, user_score.modifier, user_score.clear_type, user_score.rating))
|
||||||
|
|
||||||
|
# 更新内存中的数据
|
||||||
|
x = (r_index, user_score.song.song_id,
|
||||||
|
user_score.song.difficulty, user_score.rating)
|
||||||
|
if len(self.r30_tuples) < 30:
|
||||||
|
self.r30_tuples.append(x)
|
||||||
|
return
|
||||||
|
|
||||||
|
for i in range(30):
|
||||||
|
if self.r30_tuples[i][0] == r_index:
|
||||||
|
self.r30_tuples[i] = x
|
||||||
|
break
|
||||||
|
|
||||||
def r30_push_score(self, user_score: 'UserPlay | UserScore') -> None:
|
def r30_push_score(self, user_score: 'UserPlay | UserScore') -> None:
|
||||||
'''根据新成绩调整 r30'''
|
'''根据新成绩调整 r30'''
|
||||||
if self.r30_tuples is None:
|
if self.r30_tuples is None:
|
||||||
|
|||||||
@@ -54,6 +54,12 @@ class User:
|
|||||||
|
|
||||||
|
|
||||||
class UserRegister(User):
|
class UserRegister(User):
|
||||||
|
|
||||||
|
limiter_ip = ArcLimiter(
|
||||||
|
Config.GAME_REGISTER_IP_RATE_LIMIT, 'game_register_ip')
|
||||||
|
limiter_device = ArcLimiter(
|
||||||
|
Config.GAME_REGISTER_DEVICE_RATE_LIMIT, 'game_register_device')
|
||||||
|
|
||||||
def __init__(self, c) -> None:
|
def __init__(self, c) -> None:
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.c = c
|
self.c = c
|
||||||
@@ -141,7 +147,13 @@ class UserRegister(User):
|
|||||||
self.c.execute('''insert or replace into user_char_full values(?,?,?,?,?,?,0)''',
|
self.c.execute('''insert or replace into user_char_full values(?,?,?,?,?,?,0)''',
|
||||||
(self.user_id, i[0], i[1], exp, i[2], 0))
|
(self.user_id, i[0], i[1], exp, i[2], 0))
|
||||||
|
|
||||||
def register(self):
|
def register(self, device_id: str = None, ip: str = None):
|
||||||
|
if device_id is not None and not self.limiter_device.hit(device_id):
|
||||||
|
raise RateLimit(f'''Too many register attempts of device `{
|
||||||
|
device_id}`''', 124, -213)
|
||||||
|
if ip is not None and ip != '127.0.0.1' and not self.limiter_ip.hit(ip):
|
||||||
|
raise RateLimit(f'''Too many register attempts of ip `{
|
||||||
|
ip}`''', 124, -213)
|
||||||
now = int(time.time() * 1000)
|
now = int(time.time() * 1000)
|
||||||
if self.user_code is None:
|
if self.user_code is None:
|
||||||
self._build_user_code()
|
self._build_user_code()
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ def register():
|
|||||||
else:
|
else:
|
||||||
device_id = 'low_version'
|
device_id = 'low_version'
|
||||||
|
|
||||||
new_user.register()
|
ip = request.remote_addr
|
||||||
|
new_user.register(device_id, ip)
|
||||||
|
|
||||||
# 注册后自动登录
|
# 注册后自动登录
|
||||||
user = UserLogin(c)
|
user = UserLogin(c)
|
||||||
user.login(new_user.name, new_user.password,
|
user.login(new_user.name, new_user.password, device_id, ip)
|
||||||
device_id, request.remote_addr)
|
|
||||||
current_app.logger.info(f'New user `{user.user_id}` registered')
|
current_app.logger.info(f'New user `{user.user_id}` registered')
|
||||||
return success_return({'user_id': user.user_id, 'access_token': user.token})
|
return success_return({'user_id': user.user_id, 'access_token': user.token})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user