from pathlib import Path import shutil import re from app.core.database import get_db_connection import app.core.config as config_module OLD_AVATAR_PREFIX = "/uploads/user/avatar/" NEW_AVATAR_PREFIX = "/uploads/user/" OLD_VOICEPRINT_PREFIX = "uploads/user/voiceprint/" NEW_VOICEPRINT_PREFIX = "uploads/user/" def move_tree_contents(old_dir: Path, new_dir: Path): if not old_dir.exists(): return False new_dir.mkdir(parents=True, exist_ok=True) moved = False for item in old_dir.iterdir(): target = new_dir / item.name if item.resolve() == target.resolve(): continue if target.exists(): continue shutil.move(str(item), str(target)) moved = True return moved def migrate_avatar_files(): legacy_root = config_module.LEGACY_AVATAR_DIR if not legacy_root.exists(): return for user_dir in legacy_root.iterdir(): if not user_dir.is_dir(): continue target_dir = config_module.get_user_avatar_dir(user_dir.name) move_tree_contents(user_dir, target_dir) def migrate_voiceprint_files(): legacy_root = config_module.LEGACY_VOICEPRINT_DIR if not legacy_root.exists(): return for user_dir in legacy_root.iterdir(): if not user_dir.is_dir(): continue target_dir = config_module.get_user_voiceprint_dir(user_dir.name) move_tree_contents(user_dir, target_dir) def migrate_avatar_urls(cursor): cursor.execute("SELECT user_id, avatar_url FROM sys_users WHERE avatar_url LIKE %s", (f"{OLD_AVATAR_PREFIX}%",)) rows = cursor.fetchall() for row in rows: avatar_url = row["avatar_url"] if not avatar_url: continue match = re.match(r"^/uploads/user/avatar/(\d+)/(.*)$", avatar_url) if not match: continue user_id, filename = match.groups() new_url = f"/uploads/user/{user_id}/avatar/{filename}" cursor.execute("UPDATE sys_users SET avatar_url = %s WHERE user_id = %s", (new_url, row["user_id"])) def migrate_voiceprint_paths(cursor): try: cursor.execute("SELECT vp_id, file_path FROM user_voiceprint WHERE file_path LIKE %s", (f"{OLD_VOICEPRINT_PREFIX}%",)) except Exception: return rows = cursor.fetchall() for row in rows: file_path = row["file_path"] if not file_path: continue match = re.match(r"^uploads/user/voiceprint/(\d+)/(.*)$", file_path) if not match: continue user_id, filename = match.groups() new_path = f"uploads/user/{user_id}/voiceprint/{filename}" cursor.execute("UPDATE user_voiceprint SET file_path = %s WHERE vp_id = %s", (new_path, row["vp_id"])) def main(): migrate_avatar_files() migrate_voiceprint_files() with get_db_connection() as connection: cursor = connection.cursor(dictionary=True) migrate_avatar_urls(cursor) migrate_voiceprint_paths(cursor) connection.commit() if __name__ == "__main__": main()