""" Direct capture script for JS MINING AND ENGINEERING EMP201 periods. Uses .click() on the EMP201 link (form loads on same page via JS). """ import base64 import json import os import re import subprocess import tempfile import time AB = "C:\\Users\\SJ\\AppData\\Roaming\\npm\\agent-browser.cmd" PERIOD_URLS = { "202603": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=168198289&TaxPayerID=31142387&ReadOnly=1&Period=202603&TPReturnITID=0&TPReturnPITID=79672519&HistoryInd=1", "202604": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=168885394&TaxPayerID=31142387&ReadOnly=1&Period=202604&TPReturnITID=0&TPReturnPITID=80251983&HistoryInd=1", "202605": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=169701876&TaxPayerID=31142387&ReadOnly=1&Period=202605&TPReturnITID=0&TPReturnPITID=80776676&HistoryInd=1", "202606": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=170268751&TaxPayerID=31142387&ReadOnly=1&Period=202606&TPReturnITID=0&TPReturnPITID=81270492&HistoryInd=1", "202607": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=170816319&TaxPayerID=31142387&ReadOnly=1&Period=202607&TPReturnITID=0&TPReturnPITID=81856371&HistoryInd=1", "202608": "https://secure.sarsefiling.co.za/EFDotNet/LoadPage.aspx?PageCode=EMP2013LANDING&ReturnTypeID=36&ReturnGroupID=171605060&TaxPayerID=31142387&ReadOnly=1&Period=202608&TPReturnITID=0&TPReturnPITID=82341489&HistoryInd=1", } def run_ab(*args, timeout=30): tmp = tempfile.NamedTemporaryFile(mode="w", delete=False, encoding="utf-8", errors="replace", prefix="ab_", suffix=".out") tmp_path = tmp.name tmp.close() try: result = subprocess.run([AB, *args], stdout=open(tmp_path, "w", encoding="utf-8", errors="replace"), stderr=subprocess.DEVNULL, timeout=timeout) with open(tmp_path, "r", encoding="utf-8", errors="replace") as f: out = f.read().strip() finally: try: os.unlink(tmp_path) except OSError: pass if result.returncode != 0: raise RuntimeError(f"agent-browser {args!r} failed: {out}") return out def eval_js(js): b64 = base64.b64encode(js.encode("utf-8")).decode("ascii") out = run_ab("eval", "-b", b64) if out == "null" or not out: return None if out.startswith('"') and out.endswith('"'): out = json.loads(out) return out def navigate_iframe_to(url): js = f"document.querySelectorAll('iframe')[0].src = {json.dumps(url)}; 'ok'" eval_js(js) def click_emp201_link(): """Click the EMP201 link inside the iframe; form loads on same page via JS.""" js = """(() => { const ifr = document.querySelectorAll('iframe')[0]; const doc = ifr.contentDocument; const links = Array.from(doc.querySelectorAll('a')); // Find link with text 'EMP201' or href with BPEMP201Form let target = links.find(a => a.href && a.href.includes('BPEMP201Form')); if (!target) target = links.find(a => a.textContent.trim() === 'EMP201'); if (!target) return JSON.stringify({ clicked: false, reason: 'no link' }); target.click(); return JSON.stringify({ clicked: true, href: target.href }); })()""" return eval_js(js) def read_input_xml(): js = """(() => { const ifr = document.querySelectorAll('iframe')[0]; const doc = ifr.contentDocument; const all = Array.from(doc.querySelectorAll('input')); const x = all.find(i => i.name === 'InputXML'); return x ? x.value : ''; })()""" res = eval_js(js) return res or "" def parse_input_xml(xml_str): xml_str = (xml_str.replace("<", "<").replace(">", ">") .replace(""", '"').replace("&", "&")) def get(tag): m = re.search(rf"<{tag}>([^<]*)", xml_str) return m.group(1) if m else "" return { "company_name": get("TRADING_NAME"), "paye_no": get("PAYE_REF_NO"), "payment_period": get("PAYMENT_PERIOD"), "paye_payable": get("PAYE_AMT"), "sdl_payable": get("SDL_AMT"), "uif_payable": get("UIF_AMT"), "total_payable": get("TOTAL_PAYMENT"), "payment_ref_no": get("PAYMENT_REF_NO"), } def main(): periods_wanted = ["202603", "202604", "202605", "202606", "202607", "202608"] results = [] for period in periods_wanted: if period not in PERIOD_URLS: continue href = PERIOD_URLS[period] print(f"\n{period}: navigating to work page...", flush=True) navigate_iframe_to(href) time.sleep(3.5) print(f" clicking EMP201 link...", flush=True) click_emp201_link() # Wait longer for form to load for i in range(6): time.sleep(2) xml = read_input_xml() if xml: break if not xml: print(f" {period}: no InputXML after 12s", flush=True) continue fields = parse_input_xml(xml) fields["period"] = period results.append(fields) print(f" {period}: PAYE={fields['paye_payable']} SDL={fields['sdl_payable']} UIF={fields['uif_payable']} Total={fields['total_payable']} Ref={fields['payment_ref_no']}", flush=True) # Navigate back to work page (back to landing) so next iteration's navigate works # The navigate_iframe_to sets a new URL, so we don't need to click Back print("\n\n=== FINAL RESULTS ===", flush=True) print(json.dumps(results, indent=2), flush=True) out_path = r"C:\Users\SJ\Downloads\js_mining_emp201_results.json" with open(out_path, "w", encoding="utf-8") as f: json.dump(results, f, indent=2) print(f"\nSaved to {out_path}", flush=True) if __name__ == "__main__": main()