mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-11 10:27:27 +08:00
Add a register api
- Add a register api - Change requirements, which flask version should be over 2.0
This commit is contained in:
@@ -1,19 +1,34 @@
|
|||||||
|
from flask import jsonify
|
||||||
|
|
||||||
|
|
||||||
def code_get_msg(code):
|
def code_get_msg(code):
|
||||||
# api接口code获取msg,返回字符串
|
# api接口code获取msg,返回字符串
|
||||||
msg = {
|
msg = {
|
||||||
'0': '',
|
0: '',
|
||||||
'-1': 'See status code',
|
-1: 'See status code',
|
||||||
'-2': 'No data',
|
-2: 'No data',
|
||||||
'-3': 'No data or user',
|
-3: 'No data or user',
|
||||||
'-4': 'No user_id',
|
-4: 'No user_id',
|
||||||
'-100': 'Wrong post data',
|
-100: 'Wrong post data',
|
||||||
'-101': 'Wrong data type',
|
-101: 'Wrong data type',
|
||||||
'-102': 'Wrong query parameter',
|
-102: 'Wrong query parameter',
|
||||||
'-103': 'Wrong sort parameter',
|
-103: 'Wrong sort parameter',
|
||||||
'-104': 'Wrong sort order parameter',
|
-104: 'Wrong sort order parameter',
|
||||||
'-201': 'Wrong username or password',
|
-201: 'Wrong username or password',
|
||||||
'-202': 'User is banned',
|
-202: 'User is banned',
|
||||||
'-999': 'Unknown error'
|
-203: 'Username exists',
|
||||||
|
-204: 'Email address exists',
|
||||||
|
-999: 'Unknown error'
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg[str(code)]
|
return msg[code]
|
||||||
|
|
||||||
|
|
||||||
|
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
|
||||||
|
# 构造返回,返回jsonify处理过后的response_class
|
||||||
|
if msg == '':
|
||||||
|
msg = code_get_msg(code)
|
||||||
|
if code < 0:
|
||||||
|
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
|
||||||
|
else:
|
||||||
|
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ from flask import (
|
|||||||
)
|
)
|
||||||
import functools
|
import functools
|
||||||
import api.api_auth
|
import api.api_auth
|
||||||
import api.users
|
from . import users
|
||||||
import api.songs
|
import api.songs
|
||||||
from api.api_code import code_get_msg
|
from .api_code import code_get_msg, return_encode
|
||||||
|
|
||||||
|
|
||||||
bp = Blueprint('api', __name__, url_prefix='/api/v1')
|
bp = Blueprint('api', __name__, url_prefix='/api/v1')
|
||||||
|
bp.register_blueprint(users.bp)
|
||||||
|
|
||||||
|
|
||||||
class Query():
|
class Query():
|
||||||
@@ -62,16 +63,6 @@ def get_query_parameter(request, query_able=[], sort_able=[]):
|
|||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
def return_encode(code: int = 0, data: dict = {}, status: int = 200, msg: str = ''):
|
|
||||||
# 构造返回,返回jsonify处理过后的response_class
|
|
||||||
if msg == '':
|
|
||||||
msg = code_get_msg(code)
|
|
||||||
if code < 0:
|
|
||||||
return jsonify({'status': status, 'code': code, 'data': {}, 'msg': msg})
|
|
||||||
else:
|
|
||||||
return jsonify({'status': status, 'code': code, 'data': data, 'msg': msg})
|
|
||||||
|
|
||||||
|
|
||||||
@bp.route('/')
|
@bp.route('/')
|
||||||
def ping():
|
def ping():
|
||||||
return return_encode()
|
return return_encode()
|
||||||
@@ -111,7 +102,7 @@ def token_delete(user):
|
|||||||
def users_get(query, user):
|
def users_get(query, user):
|
||||||
# 查询全用户信息
|
# 查询全用户信息
|
||||||
|
|
||||||
data = api.users.get_users(query)
|
data = users.get_users(query)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
return return_encode(-2)
|
return return_encode(-2)
|
||||||
@@ -133,7 +124,7 @@ def users_user_get(user, user_id):
|
|||||||
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
return return_encode(-1, {}, 403, 'No permission')
|
return return_encode(-1, {}, 403, 'No permission')
|
||||||
|
|
||||||
data = api.users.get_user_info(user_id)
|
data = users.get_user_info(user_id)
|
||||||
|
|
||||||
if not data:
|
if not data:
|
||||||
return return_encode(-3)
|
return return_encode(-3)
|
||||||
@@ -152,7 +143,7 @@ def users_user_b30_get(user, user_id):
|
|||||||
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
return return_encode(-1, {}, 403, 'No permission')
|
return return_encode(-1, {}, 403, 'No permission')
|
||||||
|
|
||||||
data = api.users.get_user_b30(user_id)
|
data = users.get_user_b30(user_id)
|
||||||
|
|
||||||
if data['data'] == []:
|
if data['data'] == []:
|
||||||
return return_encode(-3)
|
return return_encode(-3)
|
||||||
@@ -173,7 +164,7 @@ def users_user_best_get(query, user, user_id):
|
|||||||
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
return return_encode(-1, {}, 403, 'No permission')
|
return return_encode(-1, {}, 403, 'No permission')
|
||||||
|
|
||||||
data = api.users.get_user_best(user_id, query)
|
data = users.get_user_best(user_id, query)
|
||||||
|
|
||||||
if data['data'] == []:
|
if data['data'] == []:
|
||||||
return return_encode(-3)
|
return return_encode(-3)
|
||||||
@@ -192,7 +183,7 @@ def users_user_r30_get(user, user_id):
|
|||||||
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
if user_id != user.user_id and not 'select' in user.power and user.user_id != 0: # 查别人需要select权限
|
||||||
return return_encode(-1, {}, 403, 'No permission')
|
return return_encode(-1, {}, 403, 'No permission')
|
||||||
|
|
||||||
data = api.users.get_user_r30(user_id)
|
data = users.get_user_r30(user_id)
|
||||||
|
|
||||||
if data['data'] == []:
|
if data['data'] == []:
|
||||||
return return_encode(-3)
|
return return_encode(-3)
|
||||||
|
|||||||
@@ -1,9 +1,48 @@
|
|||||||
|
from flask import (
|
||||||
|
Blueprint, request, jsonify
|
||||||
|
)
|
||||||
|
|
||||||
|
from .api_code import code_get_msg, return_encode
|
||||||
|
from .api_auth import role_required
|
||||||
|
from core.user import RegisterUser
|
||||||
|
from core.error import ArcError, PostError
|
||||||
from server.sql import Connect
|
from server.sql import Connect
|
||||||
from server.sql import Sql
|
from server.sql import Sql
|
||||||
import time
|
import time
|
||||||
import web.webscore
|
import web.webscore
|
||||||
import server.info
|
import server.info
|
||||||
|
|
||||||
|
bp = Blueprint('users', __name__, url_prefix='/users')
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('', methods=['POST'])
|
||||||
|
@role_required(request, ['change'])
|
||||||
|
def users_post(user):
|
||||||
|
# 注册用户
|
||||||
|
with Connect() as c:
|
||||||
|
new_user = RegisterUser(c)
|
||||||
|
try:
|
||||||
|
if 'name' in request.json:
|
||||||
|
new_user.set_name(request.json['name'])
|
||||||
|
else:
|
||||||
|
raise PostError('No name provided.')
|
||||||
|
|
||||||
|
if 'password' in request.json:
|
||||||
|
new_user.set_password(request.json['password'])
|
||||||
|
else:
|
||||||
|
raise PostError('No password provided.')
|
||||||
|
|
||||||
|
if 'email' in request.json:
|
||||||
|
new_user.set_email(request.json['email'])
|
||||||
|
else:
|
||||||
|
raise PostError('No email provided.')
|
||||||
|
|
||||||
|
new_user.register()
|
||||||
|
except ArcError as e:
|
||||||
|
return return_encode(e.api_error_code)
|
||||||
|
|
||||||
|
return return_encode(0, {'user_id': new_user.user_id, 'user_code': new_user.user_code})
|
||||||
|
|
||||||
|
|
||||||
def get_users(query=None):
|
def get_users(query=None):
|
||||||
# 获取全用户信息,返回字典列表
|
# 获取全用户信息,返回字典列表
|
||||||
|
|||||||
0
latest version/core/__init__.py
Normal file
0
latest version/core/__init__.py
Normal file
28
latest version/core/error.py
Normal file
28
latest version/core/error.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
class ArcError(Exception):
|
||||||
|
api_error_code = -999
|
||||||
|
error_code = 108
|
||||||
|
message = None
|
||||||
|
|
||||||
|
def __init__(self, message=None, error_code=None, api_error_code=None) -> None:
|
||||||
|
self.message = message
|
||||||
|
if error_code:
|
||||||
|
self.error_code = error_code
|
||||||
|
if api_error_code:
|
||||||
|
self.api_error_code = api_error_code
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
return repr(self.message)
|
||||||
|
|
||||||
|
|
||||||
|
class InputError(ArcError):
|
||||||
|
def __init__(self, message=None, error_code=None, api_error_code=-100) -> None:
|
||||||
|
super().__init__(message, error_code, api_error_code)
|
||||||
|
|
||||||
|
|
||||||
|
class DataExist(ArcError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PostError(ArcError):
|
||||||
|
def __init__(self, message=None, error_code=None, api_error_code=-100) -> None:
|
||||||
|
super().__init__(message, error_code, api_error_code)
|
||||||
83
latest version/core/sql.py
Normal file
83
latest version/core/sql.py
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import sqlite3
|
||||||
|
from flask import current_app
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
class Connect():
|
||||||
|
# 数据库连接类,上下文管理
|
||||||
|
|
||||||
|
def __init__(self, file_path='./database/arcaea_database.db'):
|
||||||
|
"""
|
||||||
|
数据库连接,默认连接arcaea_database.db
|
||||||
|
接受:文件路径
|
||||||
|
返回:sqlite3连接操作对象
|
||||||
|
"""
|
||||||
|
self.file_path = file_path
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
self.conn = sqlite3.connect(self.file_path)
|
||||||
|
self.c = self.conn.cursor()
|
||||||
|
return self.c
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
if self.conn:
|
||||||
|
self.conn.commit()
|
||||||
|
self.conn.close()
|
||||||
|
|
||||||
|
if exc_type is not None:
|
||||||
|
current_app.logger.error(
|
||||||
|
traceback.format_exception(exc_type, exc_val, exc_tb))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class Sql():
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def select(c, table_name, target_column=[], query=None):
|
||||||
|
# 执行查询单句sql语句,返回fetchall数据
|
||||||
|
# 使用准确查询,且在单表内
|
||||||
|
|
||||||
|
sql = 'select '
|
||||||
|
sql_dict = {}
|
||||||
|
if len(target_column) >= 2:
|
||||||
|
sql += target_column[0]
|
||||||
|
for i in range(1, len(target_column)):
|
||||||
|
sql += ',' + target_column[i]
|
||||||
|
sql += ' from ' + table_name
|
||||||
|
elif len(target_column) == 1:
|
||||||
|
sql += target_column[0] + ' from ' + table_name
|
||||||
|
else:
|
||||||
|
sql += '* from ' + table_name
|
||||||
|
|
||||||
|
where_field = []
|
||||||
|
where_value = []
|
||||||
|
if query:
|
||||||
|
for i in query.query:
|
||||||
|
where_field.append(i)
|
||||||
|
where_value.append(query.query[i])
|
||||||
|
|
||||||
|
if where_field and where_value:
|
||||||
|
sql += ' where '
|
||||||
|
sql += where_field[0] + '=:' + where_field[0]
|
||||||
|
sql_dict[where_field[0]] = where_value[0]
|
||||||
|
if len(where_field) >= 2:
|
||||||
|
for i in range(1, len(where_field)):
|
||||||
|
sql_dict[where_field[i]] = where_value[i]
|
||||||
|
sql += ' and ' + where_field[i] + '=:' + where_field[i]
|
||||||
|
|
||||||
|
if query and query.sort:
|
||||||
|
sql += ' order by ' + \
|
||||||
|
query.sort[0]['column'] + ' ' + query.sort[0]['order']
|
||||||
|
for i in range(1, len(query.sort)):
|
||||||
|
sql += ', ' + query.sort[i]['column'] + \
|
||||||
|
' ' + query.sort[i]['order']
|
||||||
|
|
||||||
|
if query and query.limit >= 0:
|
||||||
|
sql += ' limit :limit offset :offset'
|
||||||
|
sql_dict['limit'] = query.limit
|
||||||
|
sql_dict['offset'] = query.offset
|
||||||
|
|
||||||
|
c.execute(sql, sql_dict)
|
||||||
|
|
||||||
|
return c.fetchall()
|
||||||
106
latest version/core/user.py
Normal file
106
latest version/core/user.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
from .error import ArcError, InputError, DataExist
|
||||||
|
from setting import Config
|
||||||
|
import hashlib
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class User:
|
||||||
|
name = None
|
||||||
|
email = None
|
||||||
|
password = None
|
||||||
|
user_id = None
|
||||||
|
user_code = None
|
||||||
|
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterUser(User):
|
||||||
|
def __init__(self, c) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.c = c
|
||||||
|
|
||||||
|
def set_name(self, name: str):
|
||||||
|
if 3 <= len(name) <= 16:
|
||||||
|
self.c.execute(
|
||||||
|
'''select exists(select * from user where name = :name)''', {'name': name})
|
||||||
|
if self.c.fetchone() == (0,):
|
||||||
|
self.name = name
|
||||||
|
else:
|
||||||
|
raise DataExist('Username exists.', 101, -203)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise InputError('Username is invalid.')
|
||||||
|
|
||||||
|
def set_password(self, password: str):
|
||||||
|
if 8 <= len(password) <= 32:
|
||||||
|
self.password = password
|
||||||
|
self.hash_pwd = hashlib.sha256(password.encode("utf8")).hexdigest()
|
||||||
|
else:
|
||||||
|
raise InputError('Password is invalid.')
|
||||||
|
|
||||||
|
def set_email(self, email: str):
|
||||||
|
# 邮箱格式懒得多判断
|
||||||
|
if 4 <= len(email) <= 32 and '@' in email and '.' in email:
|
||||||
|
self.c.execute(
|
||||||
|
'''select exists(select * from user where email = :email)''', {'email': email})
|
||||||
|
if self.c.fetchone() == (0,):
|
||||||
|
self.email = email
|
||||||
|
else:
|
||||||
|
raise DataExist('Email address exists.', 102, -204)
|
||||||
|
else:
|
||||||
|
raise InputError('Email address is invalid.')
|
||||||
|
|
||||||
|
def _build_user_code(self):
|
||||||
|
from random import randint
|
||||||
|
random_times = 0
|
||||||
|
|
||||||
|
while random_times <= 1000:
|
||||||
|
random_times += 1
|
||||||
|
user_code = ''.join([str(randint(0, 9)) for _ in range(9)])
|
||||||
|
self.c.execute('''select exists(select * from user where user_code = :user_code)''',
|
||||||
|
{'user_code': user_code})
|
||||||
|
if self.c.fetchone() == (0,):
|
||||||
|
break
|
||||||
|
|
||||||
|
if random_times <= 1000:
|
||||||
|
self.user_code = user_code
|
||||||
|
else:
|
||||||
|
raise ArcError('No available user code.')
|
||||||
|
|
||||||
|
def _build_user_id(self):
|
||||||
|
# 生成user_id,往后加1
|
||||||
|
self.c.execute('''select max(user_id) from user''')
|
||||||
|
x = self.c.fetchone()
|
||||||
|
if x[0] is not None:
|
||||||
|
self.user_id = x[0] + 1
|
||||||
|
else:
|
||||||
|
self.user_id = 2000001
|
||||||
|
|
||||||
|
def _insert_user_char(self):
|
||||||
|
# 为用户添加初始角色
|
||||||
|
self.c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(self.user_id, 0, 1, 0, 0, 0))
|
||||||
|
self.c.execute('''insert into user_char values(?,?,?,?,?,?)''',
|
||||||
|
(self.user_id, 1, 1, 0, 0, 0))
|
||||||
|
self.c.execute(
|
||||||
|
'''select character_id, max_level, is_uncapped from character''')
|
||||||
|
x = self.c.fetchall()
|
||||||
|
if x:
|
||||||
|
for i in x:
|
||||||
|
exp = 25000 if i[1] == 30 else 10000
|
||||||
|
self.c.execute('''insert into user_char_full values(?,?,?,?,?,?)''',
|
||||||
|
(self.user_id, i[0], i[1], exp, i[2], 0))
|
||||||
|
|
||||||
|
def register(self):
|
||||||
|
now = int(time.time() * 1000)
|
||||||
|
self._build_user_code()
|
||||||
|
self._build_user_id()
|
||||||
|
self._insert_user_char()
|
||||||
|
|
||||||
|
self.c.execute('''insert into user(user_id, name, password, join_date, user_code, rating_ptt,
|
||||||
|
character_id, is_skill_sealed, is_char_uncapped, is_char_uncapped_override, is_hide_rating, favorite_character, max_stamina_notification_enabled, current_map, ticket, prog_boost, email)
|
||||||
|
values(:user_id, :name, :password, :join_date, :user_code, 0, 0, 0, 0, 0, 0, -1, 0, '', :memories, 0, :email)
|
||||||
|
''', {'user_code': self.user_code, 'user_id': self.user_id, 'join_date': now, 'name': self.name, 'password': self.hash_pwd, 'memories': Config.DEFAULT_MEMORIES, 'email': self.email})
|
||||||
|
self.c.execute('''insert into recent30(user_id) values(:user_id)''', {
|
||||||
|
'user_id': self.user_id})
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
flask
|
flask==2.0.2
|
||||||
cryptography
|
cryptography
|
||||||
|
|||||||
Reference in New Issue
Block a user