mirror of
https://github.com/Lost-MSth/Arcaea-server.git
synced 2026-02-11 18:47:26 +08:00
[Enhance] PTT record & log DB cleaner
- Add support for recording users' potential each day - Add a log database cleaner tool - A small change: `/user/<user_id> PUT` API can ban user now.
This commit is contained in:
@@ -35,6 +35,16 @@ def logdb_execute_func(sql, *args, **kwargs):
|
||||
c.execute(sql, *args, **kwargs)
|
||||
|
||||
|
||||
def logdb_execute_many_func(sql, *args, **kwargs):
|
||||
with Connect(Constant.SQLITE_LOG_DATABASE_PATH) as c:
|
||||
c.executemany(sql, *args, **kwargs)
|
||||
|
||||
|
||||
def logdb_execute(sql: str, *args, **kwargs):
|
||||
'''异步执行SQL,日志库写入,注意不会直接返回结果'''
|
||||
return BGTask(logdb_execute_func, sql, *args, **kwargs)
|
||||
|
||||
|
||||
def logdb_execute_many(sql: str, *args, **kwargs):
|
||||
'''异步批量执行SQL,日志库写入,注意不会直接返回结果'''
|
||||
return BGTask(logdb_execute_many_func, sql, *args, **kwargs)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from .config_manager import Config
|
||||
|
||||
ARCAEA_SERVER_VERSION = 'v2.11.1.3'
|
||||
ARCAEA_LOG_DATBASE_VERSION = 'v1.1'
|
||||
|
||||
|
||||
class Constant:
|
||||
@@ -101,4 +102,6 @@ class Constant:
|
||||
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', 'user_role']
|
||||
|
||||
LOG_DATABASE_MIGRATE_TABLES = ['cache', 'user_score', 'user_rating']
|
||||
|
||||
UPDATE_WITH_NEW_CHARACTER_DATA = Config.UPDATE_WITH_NEW_CHARACTER_DATA
|
||||
|
||||
@@ -7,11 +7,12 @@ from time import time
|
||||
from traceback import format_exc
|
||||
|
||||
from core.config_manager import Config
|
||||
from core.constant import ARCAEA_SERVER_VERSION
|
||||
from core.constant import ARCAEA_LOG_DATBASE_VERSION, ARCAEA_SERVER_VERSION
|
||||
from core.course import Course
|
||||
from core.download import DownloadList
|
||||
from core.purchase import Purchase
|
||||
from core.sql import Connect, DatabaseMigrator, MemoryDatabase
|
||||
from core.sql import (Connect, DatabaseMigrator, LogDatabaseMigrator,
|
||||
MemoryDatabase)
|
||||
from core.user import UserRegister
|
||||
from core.util import try_rename
|
||||
|
||||
@@ -208,6 +209,29 @@ class FileChecker:
|
||||
self.logger.error(
|
||||
f'Failed to new the file {Config.SQLITE_LOG_DATABASE_PATH}')
|
||||
return False
|
||||
else:
|
||||
# 检查更新
|
||||
with Connect(Config.SQLITE_LOG_DATABASE_PATH) as c:
|
||||
try:
|
||||
x = c.execute(
|
||||
'''select value from cache where key="version"''').fetchone()
|
||||
except:
|
||||
x = None
|
||||
if not x or x[0] != ARCAEA_LOG_DATBASE_VERSION:
|
||||
self.logger.warning(
|
||||
f'Maybe the file `{Config.SQLITE_LOG_DATABASE_PATH}` is an old version.')
|
||||
try:
|
||||
self.logger.info(
|
||||
f'Try to update the file `{Config.SQLITE_LOG_DATABASE_PATH}`')
|
||||
self.update_log_database()
|
||||
self.logger.info(
|
||||
f'Success to update the file `{Config.SQLITE_LOG_DATABASE_PATH}`')
|
||||
except Exception as e:
|
||||
self.logger.error(format_exc())
|
||||
self.logger.error(
|
||||
f'Failed to update the file `{Config.SQLITE_LOG_DATABASE_PATH}`')
|
||||
return False
|
||||
|
||||
if not self.check_file(Config.SQLITE_DATABASE_PATH):
|
||||
# 新建数据库
|
||||
try:
|
||||
@@ -275,6 +299,12 @@ class FileChecker:
|
||||
DatabaseMigrator(old_path, new_path).update_database()
|
||||
os.remove(old_path)
|
||||
|
||||
@staticmethod
|
||||
def update_log_database(old_path: str = Config.SQLITE_LOG_DATABASE_PATH) -> None:
|
||||
'''直接更新日志数据库'''
|
||||
if os.path.isfile(old_path):
|
||||
LogDatabaseMigrator(old_path).update_database()
|
||||
|
||||
def check_song_file(self) -> bool:
|
||||
'''检查song有关文件并初始化缓存'''
|
||||
f = self.check_folder(Config.SONG_FILE_FOLDER_PATH)
|
||||
|
||||
@@ -2,14 +2,15 @@ from base64 import b64encode
|
||||
from os import urandom
|
||||
from time import time
|
||||
|
||||
from .bgtask import logdb_execute
|
||||
from .bgtask import BGTask, logdb_execute
|
||||
from .config_manager import Config
|
||||
from .constant import Constant
|
||||
from .course import CoursePlay
|
||||
from .error import NoData, StaminaNotEnough
|
||||
from .item import ItemCore
|
||||
from .song import Chart
|
||||
from .sql import Query, Sql
|
||||
from .util import md5
|
||||
from .sql import Connect, Query, Sql
|
||||
from .util import get_today_timestamp, md5
|
||||
from .world import WorldPlay
|
||||
|
||||
|
||||
@@ -431,6 +432,18 @@ class UserPlay(UserScore):
|
||||
logdb_execute('''insert into user_score values(?,?,?,?,?,?,?,?,?,?,?,?,?)''', (self.user.user_id, self.song.song_id, self.song.difficulty, self.time_played,
|
||||
self.score, self.shiny_perfect_count, self.perfect_count, self.near_count, self.miss_count, self.health, self.modifier, self.clear_type, self.rating))
|
||||
|
||||
def record_rating_ptt(self, user_rating_ptt: float) -> None:
|
||||
'''向log数据库记录用户ptt变化'''
|
||||
today_timestamp = get_today_timestamp()
|
||||
with Connect(Config.SQLITE_LOG_DATABASE_PATH) as c2:
|
||||
old_ptt = c2.execute('''select rating_ptt from user_rating where user_id=? and time=?''', (
|
||||
self.user.user_id, today_timestamp)).fetchone()
|
||||
|
||||
old_ptt = 0 if old_ptt is None else old_ptt[0]
|
||||
if old_ptt != user_rating_ptt:
|
||||
c2.execute('''insert or replace into user_rating values(?,?,?)''',
|
||||
(self.user.user_id, today_timestamp, user_rating_ptt))
|
||||
|
||||
def upload_score(self) -> None:
|
||||
'''上传分数,包括user的recent更新,best更新,recent30更新,世界模式计算'''
|
||||
self.get_play_state()
|
||||
@@ -474,10 +487,11 @@ class UserPlay(UserScore):
|
||||
self.update_recent30()
|
||||
|
||||
# 总PTT更新
|
||||
self.user.rating_ptt = int(self.ptt.value * 100)
|
||||
user_rating_ptt = self.ptt.value
|
||||
self.user.rating_ptt = int(user_rating_ptt * 100)
|
||||
BGTask(self.record_rating_ptt, user_rating_ptt) # 记录总PTT变换
|
||||
self.c.execute('''update user set rating_ptt = :a where user_id = :b''', {
|
||||
'a': self.user.rating_ptt, 'b': self.user.user_id})
|
||||
# TODO: PTT log
|
||||
|
||||
# 世界模式判断
|
||||
if self.is_world_mode:
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import os
|
||||
import sqlite3
|
||||
import traceback
|
||||
from atexit import register
|
||||
|
||||
from .constant import Constant
|
||||
from .config_manager import Config
|
||||
from .constant import ARCAEA_LOG_DATBASE_VERSION, Constant
|
||||
from .error import ArcError, InputError
|
||||
|
||||
|
||||
@@ -404,6 +406,31 @@ class DatabaseMigrator:
|
||||
self.update_user_char_full(c2) # 更新user_char_full
|
||||
|
||||
|
||||
class LogDatabaseMigrator:
|
||||
|
||||
def __init__(self, c1_path: str = Config.SQLITE_LOG_DATABASE_PATH) -> None:
|
||||
self.c1_path = c1_path
|
||||
# self.c2_path = c2_path
|
||||
self.init_folder_path = Config.DATABASE_INIT_PATH
|
||||
self.c = None
|
||||
|
||||
@property
|
||||
def sql_path(self) -> str:
|
||||
return os.path.join(self.init_folder_path, 'log_tables.sql')
|
||||
|
||||
def table_update(self) -> None:
|
||||
'''直接更新数据库结构'''
|
||||
with open(self.sql_path, 'r') as f:
|
||||
self.c.executescript(f.read())
|
||||
self.c.execute(
|
||||
'''insert or replace into cache values("version", :a, -1);''', {'a': ARCAEA_LOG_DATBASE_VERSION})
|
||||
|
||||
def update_database(self) -> None:
|
||||
with Connect(self.c1_path) as c:
|
||||
self.c = c
|
||||
self.table_update()
|
||||
|
||||
|
||||
class MemoryDatabase:
|
||||
conn = sqlite3.connect('file:arc_tmp?mode=memory&cache=shared', uri=True)
|
||||
|
||||
|
||||
@@ -763,7 +763,7 @@ class UserChanger(UserInfo, UserRegister):
|
||||
if columns is not None:
|
||||
d = {}
|
||||
for column in columns:
|
||||
if column == 'password':
|
||||
if column == 'password' and self.password != '':
|
||||
d[column] = self.hash_pwd
|
||||
else:
|
||||
d[column] = self.__dict__[column]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import hashlib
|
||||
import os
|
||||
from datetime import date
|
||||
from time import mktime
|
||||
|
||||
|
||||
def md5(code: str) -> str:
|
||||
@@ -37,3 +39,8 @@ def try_rename(path: str, new_path: str) -> str:
|
||||
|
||||
os.rename(path, final_path)
|
||||
return final_path
|
||||
|
||||
|
||||
def get_today_timestamp():
|
||||
'''相对于本机本地时间的今天0点的时间戳'''
|
||||
return int(mktime(date.today().timetuple()))
|
||||
|
||||
Reference in New Issue
Block a user