Release v0.1.29: media previews, clean composer, regional profiles and cloud retention
This commit is contained in:
@@ -315,3 +315,42 @@ class Baidu:
|
||||
return urllib.request.build_opener(DownloadRedirect()).open(urllib.request.Request(address, headers=headers), timeout=30)
|
||||
except Exception:
|
||||
raise self.a.Problem('网盘文件暂时无法读取,请稍后重试', 502) from None
|
||||
|
||||
def verify_backup(self, remote, fs_id, size, digest):
|
||||
"""Read back into a small memory buffer before allowing retention deletion."""
|
||||
sha = hashlib.sha256(); received = 0
|
||||
with self.open_file('shared', dict(remotePath=remote, fsId=str(fs_id))) as response:
|
||||
while chunk := response.read(65536):
|
||||
received += len(chunk)
|
||||
if received > size: raise self.a.Problem('云端备份大小不符,未清理旧备份', 502)
|
||||
sha.update(chunk)
|
||||
if received != size or sha.hexdigest() != digest:
|
||||
raise self.a.Problem('云端备份校验不一致,未清理旧备份', 502)
|
||||
|
||||
def list_directory(self, directory):
|
||||
items = []; seen = set()
|
||||
for start in range(0, 20000, 1000):
|
||||
result = self.request('shared', 'file', 'list', dir=directory, start=start, limit=1000, order='name')
|
||||
page = result.get('list')
|
||||
if not isinstance(page, list): raise self.a.Problem('网盘目录读取不完整,未继续清理', 502)
|
||||
for item in page:
|
||||
path = item.get('path', '')
|
||||
if path in seen: raise self.a.Problem('网盘目录分页重复,未继续清理', 502)
|
||||
seen.add(path); items.append(item)
|
||||
if len(page) < 1000: return items
|
||||
raise self.a.Problem('网盘目录过大,未继续清理', 502)
|
||||
|
||||
def delete_backup_file(self, remote):
|
||||
# Restrict this capability to one generated database file, never a directory or media.
|
||||
root = '/apps/'+self.public_config()['appFolder']+'/数据库备份/'
|
||||
if not remote.startswith(root): raise self.a.Problem('备份清理路径不正确')
|
||||
parts = remote[len(root):].split('/')
|
||||
if len(parts) not in (2, 3) or not re.fullmatch('[a-f0-9]{16}', parts[0]):
|
||||
raise self.a.Problem('备份清理路径不正确')
|
||||
name = parts[-1]
|
||||
if not re.fullmatch('vision-'+parts[0]+r'-\d{8}T\d{12}Z\.sqlite', name) or len(parts) == 3 and parts[1] != name:
|
||||
raise self.a.Problem('备份清理文件名不正确')
|
||||
result = self.request('shared', 'file', 'filemanager', {'async':0, 'filelist':json.dumps([remote])}, opera='delete')
|
||||
info = result.get('info')
|
||||
if result.get('taskid') or not isinstance(info, list) or len(info) != 1 or info[0].get('path') != remote or info[0].get('errno') != 0:
|
||||
raise self.a.Problem('网盘未确认删除结果,请稍后重试', 502)
|
||||
|
||||
Reference in New Issue
Block a user