diff --git a/core/database.py b/core/database.py index 3323ccc..cd9680c 100644 --- a/core/database.py +++ b/core/database.py @@ -68,7 +68,7 @@ class Database: ) """) - # 游戏状态表 + # 游戏状态表(新增 confirmed 列用于标记可回收状态) cursor.execute(""" CREATE TABLE IF NOT EXISTS game_states ( id INTEGER PRIMARY KEY AUTOINCREMENT, @@ -78,9 +78,18 @@ class Database: state_data TEXT, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, + confirmed INTEGER DEFAULT 0, UNIQUE(chat_id, user_id, game_type) ) """) + + # 幂等迁移:为已有表增加 confirmed 列 + try: + cursor.execute("ALTER TABLE game_states ADD COLUMN confirmed INTEGER DEFAULT 0") + logger.info("为 game_states 增加 confirmed 列") + except Exception: + # 列已存在或不可变更时忽略 + pass # 创建索引 cursor.execute(""" @@ -253,14 +262,31 @@ class Database: state_json = json.dumps(state_data, ensure_ascii=False) cursor.execute(""" - INSERT INTO game_states (chat_id, user_id, game_type, state_data, created_at, updated_at) - VALUES (?, ?, ?, ?, ?, ?) + INSERT INTO game_states (chat_id, user_id, game_type, state_data, created_at, updated_at, confirmed) + VALUES (?, ?, ?, ?, ?, ?, 0) ON CONFLICT(chat_id, user_id, game_type) - DO UPDATE SET state_data = ?, updated_at = ? - """, (chat_id, user_id, game_type, state_json, current_time, current_time, - state_json, current_time)) + DO UPDATE SET state_data = excluded.state_data, + updated_at = excluded.updated_at, + confirmed = 0 + """, (chat_id, user_id, game_type, state_json, current_time, current_time)) logger.debug(f"保存游戏状态: chat_id={chat_id}, user_id={user_id}, game_type={game_type}") + + def confirm_game_state(self, chat_id: int, user_id: int, game_type: str): + """标记游戏状态为已确认(可由清理器删除) + + Args: + chat_id: 会话ID + user_id: 用户ID + game_type: 游戏类型 + """ + cursor = self.conn.cursor() + current_time = int(time.time()) + cursor.execute( + "UPDATE game_states SET confirmed = 1, updated_at = ? WHERE chat_id = ? AND user_id = ? AND game_type = ?", + (current_time, chat_id, user_id, game_type) + ) + logger.debug(f"确认游戏状态: chat_id={chat_id}, user_id={user_id}, game_type={game_type}") def delete_game_state(self, chat_id: int, user_id: int, game_type: str): """删除游戏状态 @@ -286,8 +312,9 @@ class Database: cursor = self.conn.cursor() cutoff_time = int(time.time()) - timeout + # 仅删除已确认(confirmed=1)的旧会话,避免误删进行中的长时任务 cursor.execute( - "DELETE FROM game_states WHERE updated_at < ?", + "DELETE FROM game_states WHERE confirmed = 1 AND updated_at < ?", (cutoff_time,) ) deleted = cursor.rowcount @@ -413,11 +440,15 @@ class Database: # 确保用户存在 self.get_or_create_user(user_id) - # 更新用户积分 + # 更新用户积分(不触碰 last_checkin_date): + # 若不存在则插入;存在则 points += ? 且更新 updated_at cursor.execute(""" - INSERT OR REPLACE INTO user_points (user_id, points, created_at, updated_at) - VALUES (?, COALESCE((SELECT points FROM user_points WHERE user_id = ?), 0) + ?, ?, ?) - """, (user_id, user_id, points, current_time, current_time)) + INSERT INTO user_points (user_id, points, created_at, updated_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(user_id) DO UPDATE SET + points = user_points.points + excluded.points, + updated_at = excluded.updated_at + """, (user_id, points, current_time, current_time)) logger.info(f"用户 {user_id} 成功获得 {points} 积分,来源:{source}") return True