import binascii import json import os import struct import base64 from Cryptodome.Cipher import AES from Cryptodome.Util.Padding import unpad from Cryptodome.Util.strxor import strxor as xor from mutagen import mp3, flac, id3 from modules.utils.wrappers import escape_file_not_found, escape_permission_error def regular_filename(filename): """处理替换非法字符""" replaces = { # 处理非法字符所用的替换字典(根据网易云下载的文件分析得到) "|": "|", ":": ":", "<": "<", ">": ">", "?": "?", "/": "/", "\\": "\", "*": "*", '"': """ } for k, v in replaces.items(): filename = filename.replace(k, v) return filename @escape_file_not_found @escape_permission_error def load_and_decrypt_from_ncm(file_path, target_dir, out_format, return_output_path=False) -> dict | str | tuple: # Original author: Nzix Repo: nondanee """解锁指定文件并按照规则保存在指定位置 ``file_path`` 源文件路径 ``target_dir`` 解锁后文件保存路径 ``out_format`` 输出文件格式,使用“字典”格式字符串,若使用源文件名仅替换后缀则传入\"original\"""" core_key = binascii.a2b_hex('687A4852416D736F356B496E62617857') meta_key = binascii.a2b_hex('2331346C6A6B5F215C5D2630553C2728') f = open(file_path, 'rb') # magic header header = f.read(8) assert binascii.b2a_hex(header) == b'4354454e4644414d' f.seek(2, 1) # key data key_length = f.read(4) key_length = struct.unpack(' 1024 ** 2 * 16 else 'mp3'} f.seek(5, 1) # album cover image_space = f.read(4) image_space = struct.unpack('