From ba36190f304602e1eb72da2439d2767b0c3b6d39 Mon Sep 17 00:00:00 2001 From: Lost-MSth Date: Sun, 16 Oct 2022 15:49:49 +0800 Subject: [PATCH] [Enhance][Bug fix] Improve setting file & ... - Fix a small bug that `best30` of API cannot have scores whose songs are not in database - At present the setting file can be a module or a file with some of options - Limiter can have multiple rules together now --- .gitignore | 16 +- latest version/api/api_auth.py | 2 +- latest version/config.example.py | 259 ++++++++++++++++++ latest version/core/character.py | 4 +- latest version/core/config_manager.py | 81 ++++++ latest version/core/constant.py | 21 +- latest version/core/error.py | 58 ++-- latest version/core/item.py | 2 +- latest version/core/limiter.py | 25 +- latest version/core/save.py | 6 +- latest version/core/score.py | 3 +- latest version/core/user.py | 3 +- .../database/database_initialize.py | 5 - latest version/main.py | 16 +- latest version/server/__init__.py | 2 +- latest version/server/auth.py | 2 +- latest version/server/func.py | 2 +- latest version/server/init.py | 4 - latest version/server/multiplayer.py | 2 +- latest version/server/others.py | 4 +- latest version/server/user.py | 2 +- latest version/web/login.py | 8 +- latest version/web/system.py | 17 +- 23 files changed, 458 insertions(+), 86 deletions(-) create mode 100644 latest version/config.example.py create mode 100644 latest version/core/config_manager.py diff --git a/.gitignore b/.gitignore index b8ff900..3eca2aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,19 @@ +# log files *.log + +# SSL cert +*.pem +*.key + +# sqlite3 database +*.db +*.db.bak* + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] -*$py.class \ No newline at end of file +*$py.class + +# setting/config files +latest version/config/ +latest version/config.py \ No newline at end of file diff --git a/latest version/api/api_auth.py b/latest version/api/api_auth.py index 851a99d..ca87d0d 100644 --- a/latest version/api/api_auth.py +++ b/latest version/api/api_auth.py @@ -2,10 +2,10 @@ from functools import wraps from traceback import format_exc from core.api_user import APIUser +from core.config_manager import Config from core.error import ArcError, NoAccess, PostError from core.sql import Connect from flask import current_app -from setting import Config from .api_code import error_return diff --git a/latest version/config.example.py b/latest version/config.example.py new file mode 100644 index 0000000..6f1179b --- /dev/null +++ b/latest version/config.example.py @@ -0,0 +1,259 @@ +class Config(): + ''' + This is the example setting file. + The user's setting file's name is `config.py`. + ''' + + ''' + -------------------- + 主机的地址和端口号 + Host and port of your server + ''' + HOST = '0.0.0.0' + PORT = 80 + ''' + -------------------- + ''' + + ''' + -------------------- + 游戏API地址前缀 + Game API's URL prefix + ''' + GAME_API_PREFIX = '/join/21' + ''' + -------------------- + ''' + + ''' + -------------------- + 允许使用的游戏版本,若为空,则默认全部允许 + Allowed game versions + If it is blank, all are allowed. + ''' + ALLOW_APPVERSION = ['3.12.6', '3.12.6c', + '4.0.256', '4.0.256c', '4.1.0', '4.1.0c'] + ''' + -------------------- + ''' + + ''' + -------------------- + 联机功能相关设置,请确保与Link Play服务器端的设置一致 + Setting of your link play server + Please ensure that the settings on the side of Link Play server are consistent. + ''' + # SET_LINKPLAY_SERVER_AS_SUB_PROCESS: 是否同时在本地启动Link Play服务器 + # SET_LINKPLAY_SERVER_AS_SUB_PROCESS: If it is `True`, the link play server will run with the main server locally at the same time. + SET_LINKPLAY_SERVER_AS_SUB_PROCESS = True + # LINKPLAY_HOST: 对主服务器来说的Link Play服务器的地址 + # LINKPLAY_HOST: The address of the linkplay server based on the main server. If it is blank, the link play feature will be disabled. + LINKPLAY_HOST = '0.0.0.0' + LINKPLAY_UDP_PORT = 10900 + LINKPLAY_TCP_PORT = 10901 + LINKPLAY_AUTHENTICATION = 'my_link_play_server' + # LINKPLAY_DISPLAY_HOST: 对客户端来说的Link Play服务器地址,如果为空,则自动获取 + # LINKPLAY_DISPLAY_HOST: The address of the linkplay server based on the client. If it is blank, the host of link play server for the client will be obtained automatically. + LINKPLAY_DISPLAY_HOST = '' + ''' + -------------------- + ''' + + ''' + -------------------- + SSL证书路径 + 留空则使用HTTP + SSL certificate path + If left blank, use HTTP. + ''' + SSL_CERT = '' # *.pem + SSL_KEY = '' # *.key + ''' + -------------------- + ''' + + ''' + -------------------- + 愚人节模式开关 + Switch of April Fool's Day + ''' + IS_APRILFOOLS = True + ''' + -------------------- + ''' + + ''' + -------------------- + 世界排名的最大显示数量 + The largest number of global rank + ''' + WORLD_RANK_MAX = 200 + ''' + -------------------- + ''' + + ''' + -------------------- + 世界模式当前活动图设置 + Current available maps in world mode + ''' + AVAILABLE_MAP = [] # Ex. ['test', 'test2'] + ''' + -------------------- + ''' + + ''' + -------------------- + Web后台管理页面的用户名和密码 + Username and password of web background management page + ''' + USERNAME = 'admin' + PASSWORD = 'admin' + ''' + -------------------- + ''' + + ''' + -------------------- + Web后台管理页面的session秘钥,如果不知道是什么,请不要修改 + Session key of web background management page + If you don't know what it is, please don't modify it. + ''' + SECRET_KEY = '1145141919810' + ''' + -------------------- + ''' + + ''' + -------------------- + API接口完全控制权限Token,留空则不使用 + API interface full control permission Token + If you don't want to use it, leave it blank. + ''' + API_TOKEN = '' + ''' + -------------------- + ''' + + ''' + -------------------- + 歌曲下载地址前缀,留空则自动获取 + Song download address prefix + If left blank, it will be obtained automatically. + ''' + DOWNLOAD_LINK_PREFIX = '' # http://***.com/download/ + ''' + -------------------- + ''' + + ''' + -------------------- + 玩家歌曲下载的24小时次数限制,每个文件算一次 + Player's song download limit times in 24 hours, once per file + ''' + DOWNLOAD_TIMES_LIMIT = 3000 + ''' + 歌曲下载链接的有效时长,单位:秒 + Effective duration of song download link, unit: seconds + ''' + DOWNLOAD_TIME_GAP_LIMIT = 1000 + ''' + -------------------- + ''' + + ''' + -------------------- + Arcaea登录的最大允许设备数量,最小值为1 + The maximum number of devices allowed to log in Arcaea, minimum: 1 + ''' + LOGIN_DEVICE_NUMBER_LIMIT = 1 + ''' + 是否允许同设备多应用共存登录 + 请注意,这个选项设置为True时,下一个选项将自动变为False + If logging in from multiple applications on the same device is allowed + Note that when this option is set to True, the next option automatically becomes False + ''' + ALLOW_LOGIN_SAME_DEVICE = False + ''' + 24小时内登陆设备数超过最大允许设备数量时,是否自动封号(1天、3天、7天、15天、31天) + When the number of login devices exceeds the maximum number of devices allowed to log in Arcaea within 24 hours, whether the account will be automatically banned (1 day, 3 days, 7 days, 15 days, 31 days) + ''' + ALLOW_BAN_MULTIDEVICE_USER_AUTO = True + ''' + -------------------- + ''' + + ''' + -------------------- + 是否记录详细的服务器日志 + If recording detailed server logs is enabled + ''' + ALLOW_INFO_LOG = False + ALLOW_WARNING_LOG = False + ''' + -------------------- + ''' + + ''' + -------------------- + 用户注册时的默认记忆源点数量 + The default amount of memories at the time of user registration + ''' + DEFAULT_MEMORIES = 0 + ''' + -------------------- + ''' + + ''' + -------------------- + 数据库更新时,是否采用最新的角色数据,如果你想采用最新的官方角色数据 + 注意:如果是,旧的数据将丢失;如果否,某些角色的数据变动将无法同步 + If using the latest character data when updating database. If you want to only keep newest official character data, please set it `True`. + Note: If `True`, the old data will be lost; If `False`, the data changes of some characters will not be synchronized. + ''' + UPDATE_WITH_NEW_CHARACTER_DATA = True + ''' + -------------------- + ''' + + ''' + -------------------- + 是否全解锁搭档 + If unlocking all partners is enabled + ''' + CHARACTER_FULL_UNLOCK = True + ''' + -------------------- + ''' + + ''' + -------------------- + 是否全解锁世界歌曲 + If unlocking all world songs is enabled + ''' + WORLD_SONG_FULL_UNLOCK = True + ''' + -------------------- + ''' + + ''' + -------------------- + 是否全解锁世界场景 + If unlocking all world sceneries is enabled + ''' + WORLD_SCENERY_FULL_UNLOCK = True + ''' + -------------------- + ''' + + ''' + -------------------- + 是否强制使用全解锁云端存档 + If forcing full unlocked cloud save is enabled + 请注意,当前对于最终结局的判定为固定在`Testify`解锁之前 + Please note that the current setting of the finale state is before the unlock of `Testify` + ''' + SAVE_FULL_UNLOCK = False + ''' + -------------------- + ''' diff --git a/latest version/core/character.py b/latest version/core/character.py index 3310b4d..ef1f0d6 100644 --- a/latest version/core/character.py +++ b/latest version/core/character.py @@ -1,6 +1,6 @@ -from setting import Config -from .error import ArcError, InputError, NoData, ItemNotEnough +from .config_manager import Config from .constant import Constant +from .error import ArcError, InputError, ItemNotEnough, NoData from .item import Item, ItemCore diff --git a/latest version/core/config_manager.py b/latest version/core/config_manager.py new file mode 100644 index 0000000..96b3de2 --- /dev/null +++ b/latest version/core/config_manager.py @@ -0,0 +1,81 @@ +class Config: + ''' + Default config + ''' + + HOST = '0.0.0.0' + PORT = 80 + + GAME_API_PREFIX = '/join/21' + + ALLOW_APPVERSION = [] # list[str] + + SET_LINKPLAY_SERVER_AS_SUB_PROCESS = True + + LINKPLAY_HOST = '0.0.0.0' + LINKPLAY_UDP_PORT = 10900 + LINKPLAY_TCP_PORT = 10901 + LINKPLAY_AUTHENTICATION = 'my_link_play_server' + LINKPLAY_DISPLAY_HOST = '' + + SSL_CERT = '' + SSL_KEY = '' + + IS_APRILFOOLS = True + + WORLD_RANK_MAX = 200 + + AVAILABLE_MAP = [] # list[str] + + USERNAME = 'admin' + PASSWORD = 'admin' + + SECRET_KEY = '1145141919810' + + API_TOKEN = '' + + DOWNLOAD_LINK_PREFIX = '' + + DOWNLOAD_TIMES_LIMIT = 3000 + DOWNLOAD_TIME_GAP_LIMIT = 1000 + + LOGIN_DEVICE_NUMBER_LIMIT = 1 + ALLOW_LOGIN_SAME_DEVICE = False + ALLOW_BAN_MULTIDEVICE_USER_AUTO = True + + ALLOW_INFO_LOG = False + ALLOW_WARNING_LOG = False + + DEFAULT_MEMORIES = 0 + + UPDATE_WITH_NEW_CHARACTER_DATA = True + + CHARACTER_FULL_UNLOCK = True + WORLD_SONG_FULL_UNLOCK = True + WORLD_SCENERY_FULL_UNLOCK = True + + SAVE_FULL_UNLOCK = False + + # ------------------------------------------ + + # You can change this to make another PTT mechanism. + BEST30_WEIGHT = 1 / 40 + RECENT10_WEIGHT = 1 / 40 + + MAX_FRIEND_COUNT = 50 + + WORLD_MAP_FOLDER_PATH = './database/map/' + SONG_FILE_FOLDER_PATH = './database/songs/' + SONGLIST_FILE_PATH = './database/songs/songlist' + SQLITE_DATABASE_PATH = './database/arcaea_database.db' + + +class ConfigManager: + + @staticmethod + def load(config): + for k, v in config.__dict__.items(): + if k.startswith('__') or k.endswith('__'): + continue + if hasattr(Config, k): + setattr(Config, k, v) diff --git a/latest version/core/constant.py b/latest version/core/constant.py index ebaba0d..532709d 100644 --- a/latest version/core/constant.py +++ b/latest version/core/constant.py @@ -1,4 +1,4 @@ -from setting import Config +from .config_manager import Config class Constant: @@ -9,6 +9,8 @@ class Constant: STAMINA_RECOVER_TICK = 1800000 + COURSE_STAMINA_COST = 4 + CORE_EXP = 250 LEVEL_STEPS = {1: 0, 2: 50, 3: 100, 4: 150, 5: 200, 6: 300, 7: 450, 8: 650, 9: 900, 10: 1200, 11: 1600, 12: 2100, 13: 2700, 14: 3400, 15: 4200, 16: 5100, @@ -19,19 +21,18 @@ class Constant: AYU_UNCAP_BONUS_PROGRESS = 5 SKILL_FATALIS_WORLD_LOCKED_TIME = 3600000 - MAX_FRIEND_COUNT = 50 + MAX_FRIEND_COUNT = Config.MAX_FRIEND_COUNT MY_RANK_MAX_LOCAL_POSITION = 5 MY_RANK_MAX_GLOBAL_POSITION = 9999 - # You can change this to make another PTT mechanism. - BEST30_WEIGHT = 1 / 40 - RECENT10_WEIGHT = 1 / 40 + BEST30_WEIGHT = Config.BEST30_WEIGHT + RECENT10_WEIGHT = Config.RECENT10_WEIGHT - WORLD_MAP_FOLDER_PATH = './database/map/' - SONG_FILE_FOLDER_PATH = './database/songs/' - SONGLIST_FILE_PATH = './database/songs/songlist' - SQLITE_DATABASE_PATH = './database/arcaea_database.db' + WORLD_MAP_FOLDER_PATH = Config.WORLD_MAP_FOLDER_PATH + SONG_FILE_FOLDER_PATH = Config.SONG_FILE_FOLDER_PATH + SONGLIST_FILE_PATH = Config.SONGLIST_FILE_PATH + SQLITE_DATABASE_PATH = Config.SQLITE_DATABASE_PATH DOWNLOAD_TIMES_LIMIT = Config.DOWNLOAD_TIMES_LIMIT DOWNLOAD_TIME_GAP_LIMIT = Config.DOWNLOAD_TIME_GAP_LIMIT @@ -45,8 +46,6 @@ class Constant: LINKPLAY_UDP_PORT = Config.LINKPLAY_UDP_PORT LINKPLAY_AUTHENTICATION = Config.LINKPLAY_AUTHENTICATION - COURSE_STAMINA_COST = 4 - # Well, I can't say a word when I see this. FINALE_SWITCH = [ (0x0015F0, 0x00B032), (0x014C9A, 0x014408), (0x062585, 0x02783B), diff --git a/latest version/core/error.py b/latest version/core/error.py index 59e0e2b..c9ada67 100644 --- a/latest version/core/error.py +++ b/latest version/core/error.py @@ -1,91 +1,111 @@ class ArcError(Exception): def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None: - self.message = message - self.error_code = error_code - self.api_error_code = api_error_code + self.message: str = message + self.error_code: int = error_code + self.api_error_code: int = api_error_code self.extra_data = extra_data - self.status = status + self.status: int = status def __str__(self) -> str: return repr(self.message) class InputError(ArcError): - # 输入类型错误 + '''输入类型错误''' + def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class DataExist(ArcError): - # 数据存在 + '''数据存在''' pass class NoData(ArcError): - # 数据不存在 + '''数据不存在''' + def __init__(self, message=None, error_code=108, api_error_code=-2, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class PostError(ArcError): - # 缺少输入 + '''缺少输入''' + def __init__(self, message=None, error_code=108, api_error_code=-100, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class UserBan(ArcError): - # 用户封禁 + '''用户封禁''' + def __init__(self, message=None, error_code=121, api_error_code=-202, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class ItemNotEnough(ArcError): - # 物品数量不足 + '''物品数量不足''' + def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class ItemUnavailable(ArcError): - # 物品不可用 + '''物品不可用''' + def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class RedeemUnavailable(ArcError): - # 兑换码不可用 + '''兑换码不可用''' + def __init__(self, message=None, error_code=505, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class MapLocked(ArcError): - # 地图锁定 + '''地图锁定''' + def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class StaminaNotEnough(ArcError): - # 体力不足 + '''体力不足''' + def __init__(self, message=None, error_code=107, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class TicketNotEnough(ArcError): - # 记忆源点不足 + '''记忆源点不足''' + def __init__(self, message=None, error_code=-6, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class FriendError(ArcError): - # 好友系统出错 + '''好友系统出错''' + def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=200) -> None: super().__init__(message, error_code, api_error_code, extra_data, status) class NoAccess(ArcError): - # 无权限 - pass + '''无权限''' + + def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=403) -> None: + super().__init__(message, error_code, api_error_code, extra_data, status) class Timeout(ArcError): - # 超时 + '''超时''' pass + + +class RateLimit(ArcError): + '''频率达到限制''' + + def __init__(self, message=None, error_code=108, api_error_code=-999, extra_data=None, status=429) -> None: + super().__init__(message, error_code, api_error_code, extra_data, status) diff --git a/latest version/core/item.py b/latest version/core/item.py index 32e2694..f87018e 100644 --- a/latest version/core/item.py +++ b/latest version/core/item.py @@ -1,5 +1,5 @@ +from .config_manager import Config from .error import InputError, ItemNotEnough, ItemUnavailable, NoData -from setting import Config class Item: diff --git a/latest version/core/limiter.py b/latest version/core/limiter.py index 8d144ab..bdabed9 100644 --- a/latest version/core/limiter.py +++ b/latest version/core/limiter.py @@ -1,4 +1,4 @@ -from limits import parse, strategies +from limits import parse_many, strategies from limits.storage import storage_from_string @@ -6,23 +6,26 @@ class ArcLimiter: storage = storage_from_string("memory://") strategy = strategies.FixedWindowRateLimiter(storage) - def __init__(self, limit: str = None, namespace: str = None): - self._limit = None - self.limit = limit + def __init__(self, limit_str: str = None, namespace: str = None): + self._limits = None + self.limits = limit_str self.namespace = namespace @property - def limit(self): - return self._limit + def limits(self): + return self._limits - @limit.setter - def limit(self, value): + @limits.setter + def limits(self, value: str): if value is None: return - self._limit = parse(value) + self._limits = parse_many(value) def hit(self, key: str, cost: int = 1) -> bool: - return self.strategy.hit(self.limit, self.namespace, key, cost=cost) + flag = True + for limit in self.limits: + flag &= self.strategy.hit(limit, self.namespace, key, cost) + return flag def test(self, key: str) -> bool: - return self.strategy.test(self.limit, self.namespace, key) + return all(self.strategy.test(limit, self.namespace, key) for limit in self.limits) diff --git a/latest version/core/save.py b/latest version/core/save.py index ed6ed72..4841de3 100644 --- a/latest version/core/save.py +++ b/latest version/core/save.py @@ -1,10 +1,8 @@ import json from time import time -from setting import Config - -from core.constant import Constant - +from .config_manager import Config +from .constant import Constant from .error import InputError from .util import md5 diff --git a/latest version/core/score.py b/latest version/core/score.py index 2fb3106..c9601a8 100644 --- a/latest version/core/score.py +++ b/latest version/core/score.py @@ -580,4 +580,5 @@ class UserScoreList: 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] + x = self.c.fetchone() + score.song.song_name = x[0] if x else '' diff --git a/latest version/core/user.py b/latest version/core/user.py index 8c21bf5..f04c29b 100644 --- a/latest version/core/user.py +++ b/latest version/core/user.py @@ -3,9 +3,8 @@ import hashlib import time from os import urandom -from setting import Config - from .character import UserCharacter, UserCharacterList +from .config_manager import Config from .constant import Constant from .error import (ArcError, DataExist, FriendError, InputError, NoAccess, NoData, UserBan) diff --git a/latest version/database/database_initialize.py b/latest version/database/database_initialize.py index a1ed839..af468f2 100644 --- a/latest version/database/database_initialize.py +++ b/latest version/database/database_initialize.py @@ -207,11 +207,6 @@ def main(path='./'): time int, primary key(user_id, song_id, file_name) );''') - # c.execute('''create table if not exists user_download(user_id int, - # time int, - # token text, - # primary key(user_id, time, token) - # );''') c.execute('''create table if not exists item(item_id text, type text, is_available int, diff --git a/latest version/main.py b/latest version/main.py index cee9f9d..2081e1a 100644 --- a/latest version/main.py +++ b/latest version/main.py @@ -2,12 +2,19 @@ import os import sys +from importlib import import_module from logging.config import dictConfig from multiprocessing import Process, set_start_method from traceback import format_exc from flask import Flask, make_response, request, send_from_directory +from core.config_manager import Config, ConfigManager + +if os.path.exists('config.py') or os.path.exists('config'): + ConfigManager.load(import_module('config').Config) + + import api import server import server.init @@ -16,10 +23,9 @@ import web.login from core.constant import Constant from core.download import (UserDownload, get_only_3_song_ids, initialize_songfile) -from core.error import ArcError +from core.error import ArcError, NoAccess, RateLimit from core.sql import Connect from server.func import error_return -from setting import Config app = Flask(__name__) @@ -31,6 +37,7 @@ app = Flask(__name__) os.chdir(sys.path[0]) # 更改工作路径,以便于愉快使用相对路径 + app.config.from_mapping(SECRET_KEY=Config.SECRET_KEY) app.config['SESSION_TYPE'] = 'filesystem' app.register_blueprint(web.login.bp) @@ -62,10 +69,9 @@ def download(file_path): x.song_id, x.file_name = file_path.split('/', 1) x.select_for_check() if x.is_limited: - raise ArcError( - 'You have reached the download limit.', 903, status=429) + raise RateLimit('You have reached the download limit.', 903) if not x.is_valid: - raise ArcError('Expired token.', status=403) + raise NoAccess('Expired token.') x.download_hit() # response = make_response() # response.headers['Content-Type'] = 'application/octet-stream' diff --git a/latest version/server/__init__.py b/latest version/server/__init__.py index 89bed60..d07d4f4 100644 --- a/latest version/server/__init__.py +++ b/latest version/server/__init__.py @@ -1,5 +1,5 @@ +from core.config_manager import Config from flask import Blueprint -from setting import Config from . import (auth, course, friend, multiplayer, others, present, purchase, score, user, world) diff --git a/latest version/server/auth.py b/latest version/server/auth.py index 0484086..de0cbe5 100644 --- a/latest version/server/auth.py +++ b/latest version/server/auth.py @@ -1,11 +1,11 @@ import base64 from functools import wraps +from core.config_manager import Config from core.error import ArcError, NoAccess from core.sql import Connect from core.user import UserAuth, UserLogin from flask import Blueprint, jsonify, request -from setting import Config from .func import arc_try, error_return diff --git a/latest version/server/func.py b/latest version/server/func.py index 109c0ab..b455f1d 100644 --- a/latest version/server/func.py +++ b/latest version/server/func.py @@ -1,9 +1,9 @@ from functools import wraps from traceback import format_exc +from core.config_manager import Config from core.error import ArcError from flask import current_app, jsonify -from setting import Config default_error = ArcError('Unknown Error', status=500) diff --git a/latest version/server/init.py b/latest version/server/init.py index b7761a9..304327f 100644 --- a/latest version/server/init.py +++ b/latest version/server/init.py @@ -25,10 +25,6 @@ def check_before_run(app): f = True - if not os.path.exists('setting.py'): - app.logger.warning('File `setting.py` is missing.') - f = False - if not os.path.exists('database'): app.logger.warning('Folder `database` is missing.') f = False diff --git a/latest version/server/multiplayer.py b/latest version/server/multiplayer.py index 6bd823b..d4e3f7a 100644 --- a/latest version/server/multiplayer.py +++ b/latest version/server/multiplayer.py @@ -1,8 +1,8 @@ +from core.config_manager import Config from core.error import ArcError from core.linkplay import Player, RemoteMultiPlayer, Room from core.sql import Connect from flask import Blueprint, request -from setting import Config from .auth import auth_required from .func import arc_try, success_return diff --git a/latest version/server/others.py b/latest version/server/others.py index c736720..9049c46 100644 --- a/latest version/server/others.py +++ b/latest version/server/others.py @@ -2,7 +2,7 @@ import json from urllib.parse import parse_qs, urlparse from core.download import DownloadList -from core.error import ArcError +from core.error import RateLimit from core.sql import Connect from core.system import GameInfo from core.user import UserOnline @@ -34,7 +34,7 @@ def download_song(user_id): x.song_ids = request.args.getlist('sid') x.url_flag = json.loads(request.args.get('url', 'true')) if x.url_flag and x.is_limited: - raise ArcError('You have reached the download limit.', 903) + raise RateLimit('You have reached the download limit.', 903) x.add_songs() return success_return(x.urls) diff --git a/latest version/server/user.py b/latest version/server/user.py index 01ff83d..655456a 100644 --- a/latest version/server/user.py +++ b/latest version/server/user.py @@ -1,11 +1,11 @@ from core.character import UserCharacter +from core.config_manager import Config from core.error import ArcError, NoAccess from core.item import ItemCore from core.save import SaveData from core.sql import Connect from core.user import User, UserLogin, UserOnline, UserRegister from flask import Blueprint, request -from setting import Config from .auth import auth_required from .func import arc_try, success_return diff --git a/latest version/web/login.py b/latest version/web/login.py index 8bd7877..0735247 100644 --- a/latest version/web/login.py +++ b/latest version/web/login.py @@ -1,10 +1,10 @@ -#import sqlite3 -from flask import (Blueprint, flash, g, redirect, - render_template, request, session, url_for) import functools -from setting import Config import hashlib +from core.config_manager import Config +from flask import (Blueprint, flash, g, redirect, render_template, request, + session, url_for) + bp = Blueprint('login', __name__, url_prefix='/web') diff --git a/latest version/web/system.py b/latest version/web/system.py index 9c0ebfe..e0eb186 100644 --- a/latest version/web/system.py +++ b/latest version/web/system.py @@ -1,9 +1,10 @@ -import os -from core.sql import Connect -import time import hashlib +import os +import time from random import Random -from setting import Config + +from core.config_manager import Config +from core.sql import Connect def int2b(x): @@ -216,10 +217,10 @@ def update_database(): update_one_table(c1, c2, 'api_login') update_one_table(c1, c2, 'chart') update_one_table(c1, c2, 'user_course') - update_one_table(c1, c2, 'course') - update_one_table(c1, c2, 'course_item') - update_one_table(c1, c2, 'course_chart') - update_one_table(c1, c2, 'course_requirement') + # update_one_table(c1, c2, 'course') + # update_one_table(c1, c2, 'course_item') + # update_one_table(c1, c2, 'course_chart') + # update_one_table(c1, c2, 'course_requirement') update_one_table(c1, c2, 'user_char')