feat: 完善淘宝小程序拍照、报告与登录流程
接入本地实时识别和自动三连拍,调整报告裁切、商品跳转、分享标题及居中页眉;完善游客会话、后台渠道隔离、部署脚本与回归测试。
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Serve public voice assets with MP3 MIME/range support; keep app services running.
|
||||
|
||||
Run on the existing Ubuntu host using sudo. Only manifest-listed public files
|
||||
are copied. Nginx config is backed up and rolled back if validation/reload fails.
|
||||
"""
|
||||
import json
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
SOURCE = Path('/home/ubuntu/juzi/h5/assets/voice')
|
||||
PUBLIC = Path('/var/www/juzi-voice-20261102')
|
||||
CONFIG = Path('/etc/nginx/sites-available/juzi')
|
||||
BACKUP = CONFIG.with_name('juzi.voice-20261102.bak')
|
||||
MARKER = '# BEGIN juzi-voice-media 20261102'
|
||||
BLOCK = ''' # BEGIN juzi-voice-media 20261102
|
||||
location ^~ /state/assets/voice/ {
|
||||
alias /var/www/juzi-voice-20261102/;
|
||||
types { audio/mpeg mp3; application/json json; }
|
||||
default_type application/octet-stream;
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
limit_except GET HEAD { deny all; }
|
||||
}
|
||||
# END juzi-voice-media 20261102
|
||||
|
||||
'''
|
||||
|
||||
def checked(command):
|
||||
result = subprocess.run(command, capture_output=True, text=True)
|
||||
if result.returncode:
|
||||
raise RuntimeError('command failed: ' + ' '.join(command) + '\n' + result.stderr)
|
||||
|
||||
def main():
|
||||
manifest = json.loads((SOURCE / 'manifest.json').read_text())
|
||||
names = manifest['files']
|
||||
assert names and all(isinstance(name, str) and re.fullmatch(r'[a-z0-9-]+', name) for name in names)
|
||||
files = [SOURCE / (name + '.mp3') for name in names] + [SOURCE / 'manifest.json']
|
||||
assert all(file.is_file() and not file.is_symlink() and file.resolve().parent == SOURCE.resolve() for file in files)
|
||||
original = CONFIG.read_text()
|
||||
if MARKER not in original:
|
||||
assert not BACKUP.exists(), 'existing backup must be preserved'
|
||||
assert original.count(' location /state/ {') == 1
|
||||
PUBLIC.mkdir(mode=0o755, parents=True, exist_ok=True)
|
||||
assert PUBLIC.resolve() == Path('/var/www/juzi-voice-20261102')
|
||||
for file in files:
|
||||
target = PUBLIC / file.name
|
||||
assert not target.is_symlink()
|
||||
shutil.copyfile(file, target)
|
||||
target.chmod(0o644)
|
||||
if MARKER not in original:
|
||||
shutil.copy2(CONFIG, BACKUP)
|
||||
CONFIG.write_text(original.replace(' location /state/ {', BLOCK + ' location /state/ {', 1))
|
||||
try:
|
||||
checked(['nginx', '-t'])
|
||||
checked(['systemctl', 'reload', 'nginx'])
|
||||
except Exception:
|
||||
shutil.copy2(BACKUP, CONFIG)
|
||||
checked(['nginx', '-t'])
|
||||
checked(['systemctl', 'reload', 'nginx'])
|
||||
raise
|
||||
else:
|
||||
checked(['nginx', '-t'])
|
||||
print(json.dumps({'publicFiles': len(files), 'nginxConfigValid': True,
|
||||
'backup': str(BACKUP), 'businessServicesRestarted': False}))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user