Buckets:
| """Restore missing OGG files from a secondary mirror after control-file SHA matching.""" | |
| import os,sys,json,hashlib,tempfile,concurrent.futures,threading,importlib.util,shutil | |
| from pathlib import Path | |
| import requests | |
| from huggingface_hub import HfApi | |
| from playwright.sync_api import sync_playwright | |
| H=Path('/home/user/game-archive');R=H/'reports';B='smodusermc/offline-games';api=HfApi(token=os.environ['HF_TOKEN']);m=json.loads((R/'game-543.json').read_text());records={x['path']:x for x in m['files']};state=json.loads((R/'large-batch-validation.json').read_text());row=next(x for x in state['results'] if x['id']==543) | |
| base='https://raw.githubusercontent.com/3kh0/3kh0-lite/main/projects/there-is-no-game/media/' | |
| controls=[] | |
| for name in ['drag.ogg','dropbounce.ogg','vinyl.ogg']: | |
| f=next(x for x in m['files'] if x['path'].endswith('/'+name));r=requests.get(base+name,timeout=20);r.raise_for_status();sha=hashlib.sha256(r.content).hexdigest();assert sha==f['sha256'];controls.append({'name':name,'sha256':sha,'matches_stored_capture':True}) | |
| missing=[x for x in row['declared_unresolved'] if x.get('path','').endswith('.ogg')];restored=[] | |
| with tempfile.TemporaryDirectory(prefix='large-batch-audio-repair-') as temp: | |
| def fetch(f): | |
| url=base+f['path'].split('/')[-1];r=requests.get(url,timeout=20);r.raise_for_status();assert r.content.startswith(b'OggS');p=Path(temp)/f['path'].split('/')[-1];p.write_bytes(r.content) | |
| return p,{'path':f['path'],'url':url,'bytes':len(r.content),'sha256':hashlib.sha256(r.content).hexdigest(),'content_type':'audio/ogg','provenance':{'type':'secondary public mirror; not claimed to be the author upstream','control_files':'Three existing OGG files matched stored SHA-256 exactly','missing_original_byte_equivalence':'not established','original_url':f['url']}} | |
| with concurrent.futures.ThreadPoolExecutor(max_workers=4) as ex:items=list(ex.map(fetch,missing)) | |
| api.batch_bucket_files(B,add=[(p,f['path']) for p,f in items]) | |
| for p,f in items:p.unlink() | |
| api.download_bucket_files(B,[(f['path'],p) for p,f in items],raise_on_missing_files=True) | |
| for p,f in items: | |
| assert hashlib.sha256(p.read_bytes()).hexdigest()==f['sha256'];records[f['path']]=f;restored.append(f) | |
| m['files']=list(records.values());(R/'game-543.json').write_text(json.dumps(m,indent=2));api.batch_bucket_files(B,add=[(R/'game-543.json','_reports/games/0543.json')]) | |
| # Decode the repaired bytes again in Chromium, with browser network restricted to localhost. | |
| sys.argv=[sys.argv[0]];spec=importlib.util.spec_from_file_location('v',H/'tools/verify_games.py');v=importlib.util.module_from_spec(spec);spec.loader.exec_module(v);shutil.rmtree(v.STAGE,ignore_errors=True);v.STAGE.mkdir() | |
| server=None | |
| try: | |
| for p,f in items: | |
| dest=v.STAGE/f['path'];dest.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(p,dest) | |
| (v.STAGE/'site/__repair__.html').write_text('<!doctype html><title>Repair validation</title>') | |
| S=v.State({'files':restored});S.repair=False;server=v.ThreadingHTTPServer(('127.0.0.1',0),v.Handler);server.state=S;server.daemon_threads=False;threading.Thread(target=server.serve_forever,daemon=True).start() | |
| with sync_playwright() as p: | |
| b=p.chromium.launch(headless=True,args=['--no-sandbox']);c=b.new_context(service_workers='block');origin=f'http://127.0.0.1:{server.server_port}';c.route('**/*',lambda r:r.continue_() if r.request.url.startswith(origin+'/') else r.abort());page=c.new_page();page.goto(origin+'/__repair__.html') | |
| decoded=page.evaluate('''async(paths)=>{const c=new AudioContext();const a=[];for(const path of paths){const r=await fetch(path);const b=await c.decodeAudioData(await r.arrayBuffer());a.push({path,kind:'audio',decoded:true,frames:b.length,duration:b.duration});}await c.close();return a;}''',['/'+f['path'].removeprefix('site/') for f in restored]);b.close() | |
| finally: | |
| if server:server.shutdown();server.server_close() | |
| shutil.rmtree(v.STAGE,ignore_errors=True) | |
| previous=json.loads((R/'large-batch-audio-repair.json').read_text()) if (R/'large-batch-audio-repair.json').exists() else {} | |
| report={'game_id':543,'controls':controls,'restored':previous.get('restored',[])+restored,'decoded':previous.get('decoded',[])+decoded,'scope':'Missing OGG clips restored from the matching-control mirror; original-source M4A alternatives remain missing.'};(R/'large-batch-audio-repair.json').write_text(json.dumps(report,indent=2)) | |
| row['resolved_declared_files']=row.get('resolved_declared_files',[])+missing;row['declared_unresolved']=[x for x in row['declared_unresolved'] if not x.get('path','').endswith('.ogg')];row['files']=len(records);row['sha_comparisons']+=len(restored);row['media'].extend(decoded);row['supplemental_repair_report']='_verification/large-batch-audio-repair.json';row['independent_repairs'].extend(restored) | |
| (R/'large-batch-validation.json').write_text(json.dumps(state,indent=2));api.batch_bucket_files(B,add=[(R/'large-batch-audio-repair.json','_verification/large-batch-audio-repair.json'),(R/'large-batch-validation.json','_verification/large-batch-validation.json')]);print('Control matches',len(controls),'restored/hash-verified/decoded',len(restored)) | |
Xet Storage Details
- Size:
- 5.14 kB
- Xet hash:
- ebdaa0cdf3a6bd32b561f33d920b6c68b1efc3509e258d4d4f90412250923c00
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.