feat: add private journals and centralized Baidu media storage for v0.1.28

This commit is contained in:
Codex
2026-10-04 19:22:31 +08:00
parent 61968adf94
commit 67709832c5
21 changed files with 1187 additions and 35 deletions
+29 -11
View File
@@ -17,12 +17,13 @@ class Backups:
self.a = app
self.guard = threading.Lock()
self.running = False
self.stage = ''
def config(self):
return self.a.setting('backup_config', dict(enabled=False, time='03:00', keep=14, networkPath='', revision=0))
return {'baidu': False, **self.a.setting('backup_config', dict(enabled=False, time='03:00', keep=14, networkPath='', revision=0))}
def status(self):
return dict(config=self.config(), running=self.running,
return dict(config=self.config(), running=self.running, stage=self.stage,
localPath=str(self.a.DATA/'managed-backups'),
last=self.a.setting('backup_last', None),
history=self.a.setting('backup_history', [])[-20:][::-1])
@@ -73,11 +74,14 @@ class Backups:
return folder
def save(self, data):
if set(data) != {'enabled','time','keep','networkPath','revision'}:
data = {'baidu': False, **data}
if set(data) != {'enabled','time','keep','networkPath','revision','baidu'}:
raise self.a.Problem('备份设置字段不完整')
with self.guard:
if self.running:
raise self.a.Problem('备份正在执行,请完成后再调整设置', 409)
if not isinstance(data['baidu'], bool): raise self.a.Problem('网盘备份设置不正确')
if data['baidu']: self.a.BAIDU.token('shared')
with self.a.LOCK:
old = self.config()
if type(data['revision']) is not int or data['revision'] != old['revision']:
@@ -96,7 +100,10 @@ class Backups:
if self.running:
raise self.a.Problem('已有备份正在执行', 409)
self.running = True
threading.Thread(target=self.run, args=(reason,), daemon=True).start()
try: threading.Thread(target=self.run, args=(reason,), daemon=True).start()
except Exception:
with self.guard: self.running = False
raise
return dict(started=True)
def prune(self, folder, prefix, keep):
@@ -106,11 +113,13 @@ class Backups:
def run(self, reason='manual'):
a = self.a
config = self.config()
result = dict(at=dt.datetime.now(dt.timezone.utc).isoformat(), reason=reason,
localOk=False, networkOk=False, networkRequested=bool(config['networkPath']))
localOk=False, networkOk=False, baiduOk=False, networkRequested=False, baiduRequested=False)
temporary = network_temp = None
try:
config = self.config()
result.update(networkRequested=bool(config['networkPath']), baiduRequested=config['baidu'])
self.stage = '正在生成本机数据库副本'
local = a.DATA/'managed-backups'
local.mkdir(mode=0o700, exist_ok=True)
instance = a.setting('backup_instance')
@@ -133,6 +142,7 @@ class Backups:
result.update(localOk=True, file=name, bytes=target.stat().st_size, sha256=digest)
self.prune(local, prefix, config['keep'])
if config['networkPath']:
self.stage = '正在复制到网络目录'
network = self.network_folder(config['networkPath'])
network_temp = network/(name+'.partial')
shutil.copyfile(target, network_temp)
@@ -143,6 +153,11 @@ class Backups:
os.replace(network_temp, network/name)
result['networkOk'] = True
self.prune(network, prefix, config['keep'])
if config['baidu']:
self.stage = '正在上传百度网盘'
remote = '/apps/'+a.BAIDU.public_config()['appFolder']+'/数据库备份/'+instance+'/'+name+'/'+name
uploaded = a.BAIDU.upload('shared', target, remote)
result.update(baiduOk=True, baiduPath=remote, baiduFileId=str(uploaded['fs_id']))
except Exception as error:
result['error'] = str(error)[:300] or '备份未完成'
finally:
@@ -151,11 +166,14 @@ class Backups:
if temporary_path and temporary_path.exists(): temporary_path.unlink()
except OSError:
pass
with a.LOCK:
a.set_setting('backup_last', result)
history = a.setting('backup_history', [])
a.set_setting('backup_history', (history+[result])[-100:])
self.running = False
try:
with a.LOCK:
a.set_setting('backup_last', result)
history = a.setting('backup_history', [])
a.set_setting('backup_history', (history+[result])[-100:])
finally:
with self.guard:
self.running = False; self.stage = ''
return result
def tick(self, now=None):