mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-10 17:57:57 +08:00
Code refactoring
- Code refactoring - Fix a bug that the other player will not become the host of the room at once, when the player disconnect in link play. > Maybe add many unknown bugs. XD > The song database `arcsong.db` will not used in the future. You can use a tool in `tool` folder to import old data.
This commit is contained in:
@@ -1,15 +1,19 @@
|
||||
from .error import ArcError, InputError, DataExist, NoAccess, NoData, UserBan, FriendError
|
||||
from .constant import Constant
|
||||
from .character import UserCharacter
|
||||
from .score import Score
|
||||
from .world import Map
|
||||
from .item import get_user_cores
|
||||
from setting import Config
|
||||
import hashlib
|
||||
import base64
|
||||
import hashlib
|
||||
import time
|
||||
from os import urandom
|
||||
|
||||
from setting import Config
|
||||
|
||||
from .character import UserCharacter, UserCharacterList
|
||||
from .constant import Constant
|
||||
from .error import (ArcError, DataExist, FriendError, InputError, NoAccess,
|
||||
NoData, UserBan)
|
||||
from .item import UserItemList
|
||||
from .score import Score
|
||||
from .sql import Connect
|
||||
from .world import Map, UserMap, UserStamina
|
||||
|
||||
|
||||
def code_get_id(c, user_code: str) -> int:
|
||||
# 用user_code获取user_id
|
||||
@@ -35,7 +39,7 @@ class User:
|
||||
self.user_code = None
|
||||
|
||||
self.join_date = None
|
||||
self.rating_ptt = None
|
||||
self.rating_ptt: int = None # 100 times
|
||||
|
||||
self.ticket = None
|
||||
self.world_rank_score = None
|
||||
@@ -269,7 +273,7 @@ class UserAuth(User):
|
||||
return self.user_id
|
||||
|
||||
|
||||
class UserOnline(User):
|
||||
class UserInfo(User):
|
||||
def __init__(self, c, user_id=None) -> None:
|
||||
super().__init__()
|
||||
self.c = c
|
||||
@@ -282,16 +286,77 @@ class UserOnline(User):
|
||||
self.max_stamina_notification_enabled = False
|
||||
self.prog_boost = 0
|
||||
|
||||
self.__cores = None
|
||||
self.__friends = None
|
||||
self.__cores: list = None
|
||||
self.__packs: list = None
|
||||
self.__singles: list = None
|
||||
self.characters: 'UserCharacterList' = None
|
||||
self.__friends: list = None
|
||||
self.__world_unlocks: list = None
|
||||
self.__world_songs: list = None
|
||||
self.curr_available_maps: list = None
|
||||
|
||||
@property
|
||||
def cores(self) -> list:
|
||||
if self.__cores is None:
|
||||
self.__cores = get_user_cores(self.c, self)
|
||||
x = UserItemList(self.c, self.user_id).select_from_type('core')
|
||||
self.__cores = [{'core_type': i.item_id,
|
||||
'amount': i.amount} for i in x.items]
|
||||
|
||||
return self.__cores
|
||||
|
||||
@property
|
||||
def singles(self) -> list:
|
||||
if self.__singles is None:
|
||||
x = UserItemList(self.c, self.user_id).select_from_type('single')
|
||||
self.__singles = [i.item_id for i in x.items]
|
||||
|
||||
return self.__singles
|
||||
|
||||
@property
|
||||
def packs(self) -> list:
|
||||
if self.__packs is None:
|
||||
x = UserItemList(self.c, self.user_id).select_from_type('pack')
|
||||
self.__packs = [i.item_id for i in x.items]
|
||||
|
||||
return self.__packs
|
||||
|
||||
@property
|
||||
def world_unlocks(self) -> list:
|
||||
if self.__world_unlocks is None:
|
||||
x = UserItemList(self.c, self.user_id).select_from_type(
|
||||
'world_unlock')
|
||||
self.__world_unlocks = [i.item_id for i in x.items]
|
||||
|
||||
return self.__world_unlocks
|
||||
|
||||
@property
|
||||
def world_songs(self) -> list:
|
||||
if self.__world_songs is None:
|
||||
x = UserItemList(
|
||||
self.c, self.user_id).select_from_type('world_song')
|
||||
self.__world_songs = [i.item_id for i in x.items]
|
||||
|
||||
return self.__world_songs
|
||||
|
||||
def select_characters(self) -> None:
|
||||
self.characters = UserCharacterList(self.c, self)
|
||||
self.characters.select_user_characters()
|
||||
|
||||
@property
|
||||
def characters_list(self) -> list:
|
||||
if self.characters is None:
|
||||
self.select_characters()
|
||||
return [x.character_id for x in self.characters.characters]
|
||||
|
||||
@property
|
||||
def character_displayed(self) -> 'UserCharacter':
|
||||
'''对外显示的角色'''
|
||||
if self.favorite_character is None:
|
||||
return self.character
|
||||
|
||||
self.favorite_character.select_character_uncap_condition(self)
|
||||
return self.favorite_character
|
||||
|
||||
@property
|
||||
def friends(self) -> list:
|
||||
# 得到用户的朋友列表
|
||||
@@ -350,16 +415,65 @@ class UserOnline(User):
|
||||
r["best_clear_type"] = best_clear_type
|
||||
return [r]
|
||||
|
||||
def change_character(self, character_id: int, skill_sealed: bool = False):
|
||||
# 用户角色改变,包括技能封印的改变
|
||||
self.character = UserCharacter(self.c, character_id)
|
||||
self.character.select_character_uncap_condition(self)
|
||||
self.is_skill_sealed = skill_sealed
|
||||
def select_curr_available_maps(self) -> None:
|
||||
self.curr_available_maps: list = []
|
||||
for i in Config.AVAILABLE_MAP:
|
||||
self.curr_available_maps.append(Map(i))
|
||||
|
||||
self.c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
|
||||
'a': 1 if self.is_skill_sealed else 0, 'b': self.character.character_id, 'c': self.character.is_uncapped, 'd': self.character.is_uncapped_override, 'e': self.user_id})
|
||||
@property
|
||||
def curr_available_maps_list(self) -> list:
|
||||
if self.curr_available_maps is None:
|
||||
self.select_curr_available_maps()
|
||||
return [x.to_dict() for x in self.curr_available_maps]
|
||||
|
||||
def select_user(self):
|
||||
def to_dict(self) -> dict:
|
||||
'''返回用户信息的字典,其实就是/user/me'''
|
||||
if self.name is None:
|
||||
self.select_user()
|
||||
|
||||
# 这是考虑有可能favourite_character设置了用户未拥有的角色,同时提前计算角色列表
|
||||
character_list = self.characters_list
|
||||
if self.favorite_character and self.favorite_character.character_id in character_list:
|
||||
favorite_character_id = self.favorite_character.character_id
|
||||
else:
|
||||
favorite_character_id = -1
|
||||
return {
|
||||
"is_aprilfools": Config.IS_APRILFOOLS,
|
||||
"curr_available_maps": self.curr_available_maps_list,
|
||||
"character_stats": [x.to_dict for x in self.characters.characters],
|
||||
"friends": self.friends,
|
||||
"settings": {
|
||||
"favorite_character": favorite_character_id,
|
||||
"is_hide_rating": self.is_hide_rating,
|
||||
"max_stamina_notification_enabled": self.max_stamina_notification_enabled
|
||||
},
|
||||
"user_id": self.user_id,
|
||||
"name": self.name,
|
||||
"user_code": self.user_code,
|
||||
"display_name": self.name,
|
||||
"ticket": self.ticket,
|
||||
"character": self.character.character_id,
|
||||
"is_locked_name_duplicate": False,
|
||||
"is_skill_sealed": self.is_skill_sealed,
|
||||
"current_map": self.current_map.map_id,
|
||||
"prog_boost": self.prog_boost,
|
||||
"next_fragstam_ts": self.next_fragstam_ts,
|
||||
"max_stamina_ts": self.stamina.max_stamina_ts,
|
||||
"stamina": self.stamina.stamina,
|
||||
"world_unlocks": self.world_unlocks,
|
||||
"world_songs": self.world_songs,
|
||||
"singles": self.singles,
|
||||
"packs": self.packs,
|
||||
"characters": self.characters_list,
|
||||
"cores": self.cores,
|
||||
"recent_score": self.recent_score_list,
|
||||
"max_friend": Constant.MAX_FRIEND_COUNT,
|
||||
"rating": self.rating_ptt,
|
||||
"join_date": self.join_date,
|
||||
"global_rank": self.global_rank
|
||||
}
|
||||
|
||||
def select_user(self) -> None:
|
||||
# 查user表所有信息
|
||||
self.c.execute(
|
||||
'''select * from user where user_id = :x''', {'x': self.user_id})
|
||||
@@ -386,19 +500,205 @@ class UserOnline(User):
|
||||
self.favorite_character = None if x[23] == - \
|
||||
1 else UserCharacter(self.c, x[23])
|
||||
self.max_stamina_notification_enabled = x[24] == 1
|
||||
self.current_map = Map(x[25])
|
||||
self.current_map = Map(x[25]) if x[25] is not None else Map('')
|
||||
self.ticket = x[26]
|
||||
self.prog_boost = x[27]
|
||||
self.email = x[28]
|
||||
self.world_rank_score = x[29]
|
||||
self.ban_flag = x[30]
|
||||
self.prog_boost = x[27] if x[27] is not None else 0
|
||||
self.email = x[28] if x[28] is not None else ''
|
||||
self.world_rank_score = x[29] if x[29] is not None else 0
|
||||
self.ban_flag = x[30] if x[30] is not None else ''
|
||||
|
||||
self.next_fragstam_ts = x[31]
|
||||
self.max_stamina_ts = x[32]
|
||||
self.stamina = x[33]
|
||||
self.next_fragstam_ts = x[31] if x[31] else 0
|
||||
|
||||
self.stamina = UserStamina(self.c, self)
|
||||
self.stamina.set_value(x[32], x[33])
|
||||
|
||||
def select_user_about_current_map(self) -> None:
|
||||
self.c.execute('''select current_map from user where user_id = :a''',
|
||||
{'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if x:
|
||||
self.current_map = Map(x[0])
|
||||
|
||||
def select_user_about_stamina(self) -> None:
|
||||
self.c.execute('''select max_stamina_ts, stamina from user where user_id = :a''',
|
||||
{'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.stamina = UserStamina(self.c, self)
|
||||
self.stamina.set_value(x[0], x[1])
|
||||
|
||||
def select_user_about_character(self) -> None:
|
||||
'''
|
||||
查询user表有关角色的信息
|
||||
'''
|
||||
self.c.execute('''select name, character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, favorite_character from user where user_id = :a''', {
|
||||
'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.name = x[0]
|
||||
self.character = UserCharacter(self.c, x[1], self)
|
||||
self.is_skill_sealed = x[2] == 1
|
||||
self.character.is_uncapped = x[3] == 1
|
||||
self.character.is_uncapped_override = x[4] == 1
|
||||
self.favorite_character = None if x[5] == - \
|
||||
1 else UserCharacter(self.c, x[5], self)
|
||||
|
||||
def select_user_about_world_play(self) -> None:
|
||||
'''
|
||||
查询user表有关世界模式打歌的信息
|
||||
'''
|
||||
self.c.execute(
|
||||
'''select character_id, max_stamina_ts, stamina, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, current_map from user where user_id=?''', (self.user_id,))
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.character = UserCharacter(self.c, x[0], self)
|
||||
self.stamina = UserStamina(self.c, self)
|
||||
self.stamina.set_value(x[1], x[2])
|
||||
self.is_skill_sealed = x[3] == 1
|
||||
self.character.is_uncapped = x[4] == 1
|
||||
self.character.is_uncapped_override = x[5] == 1
|
||||
self.current_map = UserMap(self.c, x[6], self)
|
||||
|
||||
def select_user_about_world_rank_score(self) -> None:
|
||||
'''
|
||||
查询user表有关世界模式排名的信息
|
||||
'''
|
||||
self.c.execute(
|
||||
'''select world_rank_score from user where user_id=?''', (self.user_id,))
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.world_rank_score = x[0]
|
||||
|
||||
@property
|
||||
def global_rank(self) -> int:
|
||||
'''用户世界排名,如果超过设定最大值,返回0'''
|
||||
if self.world_rank_score is None:
|
||||
self.select_user_about_world_rank_score()
|
||||
if self.world_rank_score is None:
|
||||
return 0
|
||||
|
||||
self.c.execute(
|
||||
'''select count(*) from user where world_rank_score > ?''', (self.world_rank_score,))
|
||||
y = self.c.fetchone()
|
||||
if y and y[0] + 1 <= Config.WORLD_RANK_MAX:
|
||||
return y[0] + 1
|
||||
|
||||
return 0
|
||||
|
||||
def update_global_rank(self) -> None:
|
||||
'''用户世界排名计算,有新增成绩则要更新'''
|
||||
with Connect() as c2:
|
||||
c2.execute('''select song_id, rating_ftr, rating_byn from chart''')
|
||||
x = c2.fetchall()
|
||||
if x:
|
||||
song_list_ftr = [self.user_id]
|
||||
song_list_byn = [self.user_id]
|
||||
for i in x:
|
||||
if i[1] > 0:
|
||||
song_list_ftr.append(i[0])
|
||||
if i[2] > 0:
|
||||
song_list_byn.append(i[0])
|
||||
|
||||
if len(song_list_ftr) >= 2:
|
||||
self.c.execute('''select sum(score) from best_score where user_id=? and difficulty=2 and song_id in ({0})'''.format(
|
||||
','.join(['?']*(len(song_list_ftr)-1))), tuple(song_list_ftr))
|
||||
|
||||
x = self.c.fetchone()
|
||||
if x[0] is not None:
|
||||
score_sum = x[0]
|
||||
else:
|
||||
score_sum = 0
|
||||
|
||||
if len(song_list_byn) >= 2:
|
||||
self.c.execute('''select sum(score) from best_score where user_id=? and difficulty=3 and song_id in ({0})'''.format(
|
||||
','.join(['?']*(len(song_list_byn)-1))), tuple(song_list_byn))
|
||||
|
||||
x = self.c.fetchone()
|
||||
if x[0] is not None:
|
||||
score_sum += x[0]
|
||||
else:
|
||||
score_sum += 0
|
||||
|
||||
self.c.execute('''update user set world_rank_score = :b where user_id = :a''', {
|
||||
'a': self.user_id, 'b': score_sum})
|
||||
|
||||
self.world_rank_score = score_sum
|
||||
|
||||
def select_user_about_ticket(self) -> None:
|
||||
'''
|
||||
查询user表有关记忆源点的信息
|
||||
'''
|
||||
self.c.execute('''select ticket from user where user_id = :a''', {
|
||||
'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.ticket = x[0]
|
||||
|
||||
def update_user_about_ticket(self, ticket: int = None) -> None:
|
||||
'''更新记忆源点'''
|
||||
if ticket is not None:
|
||||
self.ticket = ticket
|
||||
self.c.execute('''update user set ticket = :a where user_id = :b''', {
|
||||
'a': self.ticket, 'b': self.user_id})
|
||||
|
||||
def select_user_about_fragstam(self) -> None:
|
||||
'''
|
||||
查询user表有关碎片购买体力时间的信息
|
||||
'''
|
||||
self.c.execute('''select next_fragstam_ts from user where user_id = :a''', {
|
||||
'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.next_fragstam_ts = x[0] if x[0] else 0
|
||||
|
||||
def update_user_about_fragstam(self, next_fragstam_ts: int = None) -> None:
|
||||
'''更新碎片购买体力时间'''
|
||||
if next_fragstam_ts is not None:
|
||||
self.next_fragstam_ts = next_fragstam_ts
|
||||
self.c.execute('''update user set next_fragstam_ts = :a where user_id = :b''', {
|
||||
'a': self.next_fragstam_ts, 'b': self.user_id})
|
||||
|
||||
def select_user_about_name(self) -> None:
|
||||
'''
|
||||
查询user表有关用户名的信息
|
||||
'''
|
||||
self.c.execute('''select name from user where user_id = :a''', {
|
||||
'a': self.user_id})
|
||||
x = self.c.fetchone()
|
||||
if not x:
|
||||
raise NoData('No user.', 108, -3)
|
||||
|
||||
self.name = x[0]
|
||||
|
||||
|
||||
class UserOnline(UserInfo):
|
||||
|
||||
def __init__(self, c, user_id=None) -> None:
|
||||
super().__init__(c, user_id)
|
||||
|
||||
def change_character(self, character_id: int, skill_sealed: bool = False):
|
||||
'''用户角色改变,包括技能封印的改变'''
|
||||
self.character = UserCharacter(self.c, character_id, self)
|
||||
self.character.select_character_uncap_condition()
|
||||
self.is_skill_sealed = skill_sealed
|
||||
|
||||
self.c.execute('''update user set is_skill_sealed = :a, character_id = :b, is_char_uncapped = :c, is_char_uncapped_override = :d where user_id = :e''', {
|
||||
'a': 1 if self.is_skill_sealed else 0, 'b': self.character.character_id, 'c': self.character.is_uncapped, 'd': self.character.is_uncapped_override, 'e': self.user_id})
|
||||
|
||||
def add_friend(self, friend_id: int):
|
||||
# 加好友
|
||||
'''加好友'''
|
||||
if self.user_id == friend_id:
|
||||
raise FriendError('Add yourself as a friend.', 604)
|
||||
|
||||
@@ -411,8 +711,7 @@ class UserOnline(User):
|
||||
raise FriendError('The user has been your friend.', 602)
|
||||
|
||||
def delete_friend(self, friend_id: int):
|
||||
# 删好友
|
||||
|
||||
'''删好友'''
|
||||
self.c.execute('''select exists(select * from friend where user_id_me = :x and user_id_other = :y)''',
|
||||
{'x': self.user_id, 'y': friend_id})
|
||||
if self.c.fetchone() == (1,):
|
||||
@@ -420,3 +719,30 @@ class UserOnline(User):
|
||||
{'x': self.user_id, 'y': friend_id})
|
||||
else:
|
||||
raise FriendError('No user or the user is not your friend.', 401)
|
||||
|
||||
def update_prog_boost(self, prog_boost: int = None) -> None:
|
||||
'''更新`prog_boost`'''
|
||||
if prog_boost:
|
||||
self.prog_boost = prog_boost
|
||||
self.c.execute('''update user set prog_boost = :a where user_id = :b''',
|
||||
{'a': self.prog_boost, 'b': self.user_id})
|
||||
|
||||
def change_favorite_character(self, character_id: int) -> None:
|
||||
'''更改用户的favorite_character'''
|
||||
self.favorite_character = UserCharacter(self.c, character_id, self)
|
||||
self.c.execute('''update user set favorite_character = :a where user_id = :b''',
|
||||
{'a': self.favorite_character.character_id, 'b': self.user_id})
|
||||
|
||||
def change_is_hide_rating(self, is_hide_rating: bool = None) -> None:
|
||||
'''更改用户的is_hide_rating'''
|
||||
if is_hide_rating is not None:
|
||||
self.is_hide_rating = is_hide_rating
|
||||
self.c.execute('''update user set is_hide_rating = :a where user_id = :b''',
|
||||
{'a': self.is_hide_rating, 'b': self.user_id})
|
||||
|
||||
def change_max_stamina_notification_enabled(self, max_stamina_notification_enabled: bool = None) -> None:
|
||||
'''更改用户的max_stamina_notification_enabled'''
|
||||
if max_stamina_notification_enabled is not None:
|
||||
self.max_stamina_notification_enabled = max_stamina_notification_enabled
|
||||
self.c.execute('''update user set max_stamina_notification_enabled = :a where user_id = :b''',
|
||||
{'a': self.max_stamina_notification_enabled, 'b': self.user_id})
|
||||
|
||||
Reference in New Issue
Block a user