# -*- coding: utf-8 -*-
r"""B98 — CÁCH CHUẨN lấy ẢNH GỐC từ Zalo (chốt 13/10/2026):
Bước 1 (như mọi lần): dump khối tin, lọc ảnh theo id >= mốc đầu ngày -> canvas->base64 (ảnh đơn: gốc luôn).
Bước 2 (CHỈ khi ảnh về dạng ALBUM: thumbnail trong danh sách < 400 px): click LẦN LƯỢT từng thumbnail
  -> viewer nạp ảnh gốc (768x1024 .. 1920x2560) -> gom mọi img.zimg-el có naturalWidth >= 400 chưa gặp
  (khoá theo đuôi blob src, cap 1400 px) -> lưu, md5 khử trùng.
Không dùng phím ArrowRight (KHÔNG ăn với viewer Zalo)."""
import base64, hashlib, os, re, subprocess, time

S = 'tri1310'
DICH = r'C:\Claw 2\QC\images\_zalo_tri_1310_full'
CAN = 1400
os.makedirs(DICH, exist_ok=True)
LOG = open(r'C:\Claw 2\QC\_log_zalo_tri_1310_full.txt', 'a', encoding='utf-8')
log = lambda *a: (print(*a, flush=True), LOG.write(' '.join(str(x) for x in a) + '\n'), LOG.flush())


def ev(js, t=240):
    r = subprocess.run(['browser-act', '--session', S, 'eval', js], capture_output=True, text=True,
                       encoding='utf-8', errors='replace', timeout=t)
    return ((r.stdout or '') + (r.stderr or '')).strip()


def khoa_src(s):
    return s.split('/')[-1][:22]


seen_src, seen_md5 = set(), set()
for f in os.listdir(DICH):
    if f.endswith('.jpg'):
        seen_md5.add(hashlib.md5(open(os.path.join(DICH, f), 'rb').read()).hexdigest()[:12])
log('  đã có sẵn %d ảnh trong thư mục' % len(seen_md5))

for lan in (0, 1):
    for i in range(24):
        ev("(()=>{const t=[...document.querySelectorAll('img.zimg-el')].filter(x=>x.naturalWidth<400); const g=t[%d]; if(!g) return 'het'; const c=g.closest('.img-center-box')||g.parentElement; (c||g).click(); return 'ok';})()" % i)
        time.sleep(3)
        ds = ev("(()=>{const l=[...document.querySelectorAll('img.zimg-el')].filter(x=>x.naturalWidth>=400); return JSON.stringify(l.map(x=>x.naturalWidth+'x'+x.naturalHeight+'#'+(x.src||'')));})()")
        try:
            ds = ds[ds.index('['):ds.rindex(']') + 1].replace('\\"', '"')   # bỏ escape \" của browser-act
            arr = re.findall(r'"(\d+x\d+)#([^"]+)"', ds)
        except Exception:
            arr = []
        moi = 0
        for kich, src in arr:
            k = khoa_src(src)
            if k in seen_src:
                continue
            ev("(()=>{const g=[...document.querySelectorAll('img.zimg-el')].find(x=>(x.src||'').indexOf('%s')>=0); if(!g) return 'x'; g.scrollIntoView({block:'center'}); const k=%d/g.naturalWidth; const w=Math.round(g.naturalWidth*k), h=Math.round(g.naturalHeight*k); const c=document.createElement('canvas'); c.width=w; c.height=h; c.getContext('2d').drawImage(g,0,0,w,h); try{window.__B=c.toDataURL('image/jpeg',0.9);}catch(e){return 'LOI';} return 'OK '+window.__B.length;})()" % (k, CAN))
            r = ev('String(window.__B?window.__B.length:0)').strip()
            if not r.isdigit() or int(r) < 1000:
                continue
            tong = int(r)
            phan, vt = [], 0
            while vt < tong:
                z = ev('String(window.__B.slice(%d,%d))' % (vt, vt + 30000)).strip()
                if z.startswith('"') and z.endswith('"'):
                    z = z[1:-1]
                phan.append(z); vt += 30000
            chuoi = ''.join(phan)
            if len(chuoi) < tong * 0.9:
                continue
            th = base64.b64decode(chuoi.split(',', 1)[1])
            md5 = hashlib.md5(th).hexdigest()[:12]
            seen_src.add(k)
            if md5 in seen_md5:
                continue
            seen_md5.add(md5)
            moi += 1
            ten = os.path.join(DICH, 'goc_%02d.jpg' % len(seen_md5))
            open(ten, 'wb').write(th)
            log('   %-16s %8d B  %-10s md5 %s' % (os.path.basename(ten), len(th), kich, md5))
        if lan == 0 and i == 23:
            log('  (hết 24 thumbnail, chạy vòng 2 để bắt ảnh sót)')
    log('  vòng %d: tổng %d ảnh gốc' % (lan + 1, len(seen_md5)))
    if len(seen_md5) >= 15:
        break

ev("(()=>{document.dispatchEvent(new KeyboardEvent('keydown',{key:'Escape',keyCode:27,which:27,bubbles:true})); return 1;})()")
log('  === CHỐT: %d ảnh gốc trong %s' % (len(seen_md5), DICH))
LOG.close()
