feat: 完善淘宝小程序拍照、报告与登录流程
接入本地实时识别和自动三连拍,调整报告裁切、商品跳转、分享标题及居中页眉;完善游客会话、后台渠道隔离、部署脚本与回归测试。
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Publish an explicitly selected public video and player; reload nginx only."""
|
||||
import argparse
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shutil
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
|
||||
PUBLIC = Path('/var/www/juzi-media/videos')
|
||||
CONFIG = Path('/etc/nginx/sites-available/juzi')
|
||||
MARKER = '# BEGIN juzi-public-videos'
|
||||
BLOCK = ''' # BEGIN juzi-public-videos
|
||||
location ^~ /media/videos/ {
|
||||
alias /var/www/juzi-media/videos/;
|
||||
autoindex off;
|
||||
types { video/mp4 mp4; text/html html; }
|
||||
default_type application/octet-stream;
|
||||
charset utf-8;
|
||||
add_header X-Content-Type-Options nosniff;
|
||||
add_header Cache-Control "public, max-age=3600";
|
||||
limit_except GET HEAD { deny all; }
|
||||
}
|
||||
# END juzi-public-videos
|
||||
|
||||
'''
|
||||
|
||||
|
||||
def checked(args):
|
||||
subprocess.run(args, check=True, capture_output=True, text=True)
|
||||
|
||||
|
||||
def digest(path):
|
||||
result = hashlib.sha256()
|
||||
with path.open('rb') as stream:
|
||||
for chunk in iter(lambda: stream.read(1024 * 1024), b''):
|
||||
result.update(chunk)
|
||||
return result.hexdigest()
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('staging')
|
||||
parser.add_argument('stem')
|
||||
parser.add_argument('sha256')
|
||||
args = parser.parse_args()
|
||||
assert re.fullmatch(r'[a-z0-9-]{1,80}', args.stem)
|
||||
assert re.fullmatch(r'[a-f0-9]{64}', args.sha256)
|
||||
staging = Path(args.staging)
|
||||
assert staging.resolve() == staging and staging.parent == Path('/tmp')
|
||||
assert staging.name.startswith('juzi-public-video-') and not staging.is_symlink()
|
||||
sources = [staging / (args.stem + suffix) for suffix in ('.mp4', '.html')]
|
||||
assert all(p.is_file() and not p.is_symlink() for p in sources)
|
||||
assert digest(sources[0]) == args.sha256, 'uploaded video checksum mismatch'
|
||||
assert not CONFIG.is_symlink()
|
||||
original = CONFIG.read_text()
|
||||
if MARKER not in original:
|
||||
assert 'location ^~ /media/videos/' not in original
|
||||
assert original.count(' location /state/ {') == 1
|
||||
for directory in [PUBLIC.parent, PUBLIC]:
|
||||
assert not directory.is_symlink()
|
||||
directory.mkdir(mode=0o755, exist_ok=True)
|
||||
assert directory.resolve() == directory
|
||||
for source in sources:
|
||||
target = PUBLIC / source.name
|
||||
assert not target.is_symlink()
|
||||
if target.exists():
|
||||
assert digest(target) == digest(source), 'refusing to overwrite a different published file'
|
||||
else:
|
||||
shutil.copyfile(source, target)
|
||||
target.chmod(0o644)
|
||||
if MARKER not in original:
|
||||
stamp = datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S%fZ')
|
||||
backup = CONFIG.with_name('juzi.public-video-' + stamp + '.bak')
|
||||
assert not backup.exists()
|
||||
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
|
||||
print('nginx backup: ' + str(backup))
|
||||
else:
|
||||
assert BLOCK in original, 'existing video location differs; inspect before changing'
|
||||
checked(['nginx', '-t'])
|
||||
print('video sha256: ' + digest(PUBLIC / sources[0].name))
|
||||
print('player: https://1me.xajuzi.com/media/videos/' + args.stem + '.html')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user