SecureMyPass Multi-Login Export Bot (final)

Loop through multiple accounts: login → my-links → export CSV

当前为 2025-08-20 提交的版本,查看 最新版本

// ==UserScript==
// @name         SecureMyPass Multi-Login Export Bot (final)
// @namespace    https://securemypass.com/
// @version      1.3
// @description  Loop through multiple accounts: login → my-links → export CSV
// @match        https://securemypass.com/*
// @run-at       document-end
// @grant        none
// ==/UserScript==

(function() {
  'use strict';

  if (window.__SMP_BARE__) return;
  window.__SMP_BARE__ = true;

  // --- UI ---
  const box = document.createElement('div');
  box.style = `
    position:fixed;bottom:20px;right:20px;z-index:999999;
    background:#111;color:#eee;padding:10px;border:1px solid #333;border-radius:6px;
    font:13px/1.4 system-ui;width:260px
  `;
  box.innerHTML = `
    <h3 style="margin:0 0 6px;font-size:14px">SMP Bot</h3>
    <label>Number of Accounts</label>
    <input id="smpCount" type="number" value="1" min="1" style="width:100%;margin:4px 0"/>
    <div id="smpCreds"></div>
    <button id="smpStart" style="margin-top:6px;width:100%">Start</button>
    <div id="smpLog" style="margin-top:6px;font-size:12px;color:#aaa">Idle</div>
  `;
  document.body.appendChild(box);

  const el = (id) => box.querySelector(id);
  const log = (m) => el('#smpLog').textContent = m;

  const renderCreds = () => {
    const n = parseInt(el('#smpCount').value || '1', 10);
    const wrap = el('#smpCreds');
    wrap.innerHTML = '';
    for (let i=0;i<n;i++) {
      wrap.innerHTML += `
        <div style="border:1px solid #333;padding:4px;margin:4px 0;border-radius:4px">
          <div>Account ${i+1}</div>
          <input class="smpUser" type="text" placeholder="Username" style="width:100%"/>
          <input class="smpPass" type="password" placeholder="Password" style="width:100%"/>
        </div>
      `;
    }
  };
  renderCreds();
  el('#smpCount').addEventListener('input', renderCreds);

  // --- Helpers ---
  const sleep = (ms) => new Promise(r=>setTimeout(r,ms));
  const getByXPath = (xp) => document.evaluate(xp, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;

  // Retry loop for export button
  async function waitForExportButton(timeout=20000) {
    const t0 = performance.now();
    while (true) {
      let el = getByXPath('//button[contains(., "Export")]');
      if (el) return el;
      if (performance.now() - t0 > timeout) throw new Error("Export button not found");
      await sleep(500);
    }
  }

  // --- Main flow ---
  async function runForAccount(username,password) {
    log("Typing username…");
    getByXPath('//*[@id="loginUsername"]').value = username;
    await sleep(500);

    log("Clicking continue…");
    getByXPath('//*[@id="root"]/div[1]/main/div/div/div/div/div[1]/div/form/div[2]/button').click();
    await sleep(2000);

    log("Typing password…");
    getByXPath('//*[@id="loginPassword"]').value = password;
    await sleep(500);

    log("Clicking login…");
    getByXPath('//*[@id="root"]/div[1]/main/div/div/div/div/div[1]/div/form/div[2]/button').click();
    await sleep(3000);

    log("Going to My Links…");
    location.href = "https://securemypass.com/my-links";
    await new Promise(r => window.addEventListener('load', r, {once:true}));
    await sleep(2000);

    log("Waiting for Export button…");
    const exp = await waitForExportButton();
    await sleep(1000);
    exp.click();
    log("Export clicked (check downloads).");
    await sleep(3000);
  }

  // --- Start button ---
  el('#smpStart').onclick = async () => {
    const users = [...box.querySelectorAll('.smpUser')].map(i=>i.value.trim());
    const passes = [...box.querySelectorAll('.smpPass')].map(i=>i.value);
    for (let i=0;i<users.length;i++) {
      if (!users[i] || !passes[i]) { log("Missing credentials"); return; }
      log(`Running account ${i+1}/${users.length}`);
      try { await runForAccount(users[i], passes[i]); }
      catch(e){ console.error(e); log("Error: "+e.message); }
      await sleep(5000); // pause before next account
    }
    log("All done.");
  };

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址