Instagram to archive.today URL Queue Manager v1.1.8

Automate archiving Instagram posts on archive.today with a smart queue. CAPTCHA-safe, full processed history (no 1500-limit), smart export filenames by username.// @author thomased (ChatGPT + Gemini + Grok)

// ==UserScript==
// @name         Instagram to archive.today URL Queue Manager v1.1.8
// @namespace    http://tampermonkey.net/
// @version      1.1.8
// @description  Automate archiving Instagram posts on archive.today with a smart queue. CAPTCHA-safe, full processed history (no 1500-limit), smart export filenames by username.// @author       thomased (ChatGPT + Gemini + Grok)
// @match        https://archive.ph/*
// @match        https://archive.today/*
// @match        https://archive.is/*
// @match        https://archive.vn/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  /* ===== CONFIG: tweak these to make WIP even gentler ===== */
  const HOMEPAGE = 'https://archive.ph/';
  const BASE_WIP_POLL_MS = 60 * 1000;        // base wait between WIP reloads (60s)
  const MAX_BACKOFF_EXP = 6;                // cap exponent (2^6 = 64x base -> ~64 min at base=60s)
  const BACKOFF_JITTER_RATIO = 0.12;        // +/- 12% random jitter
  const PROCESS_DELAY = 900;

  /* ===== Utils / storage ===== */
  function log(...args) { console.log('[ArchiveQueue]', ...args); }
  function dbg(...args) { console.debug('[ArchiveQueue]', ...args); }

  function getQueue() { try { return JSON.parse(localStorage.getItem('archiveQueue') || '[]'); } catch (e) { return []; } }
  function saveQueue(q) { localStorage.setItem('archiveQueue', JSON.stringify(q)); updateOverlay(); }
  function getProcessed() { try { return JSON.parse(localStorage.getItem('processedUrls') || '[]'); } catch (e) { return []; } }
  function saveProcessed(url) {
    try {
      const arr = getProcessed();
      if (!arr.includes(url)) {
        arr.push(url);
        localStorage.setItem('processedUrls', JSON.stringify(arr));
      }
      updateOverlay();
    } catch (e) { console.error(e); }
  }
  function getRestricted() { try { return JSON.parse(localStorage.getItem('restrictedUrls') || '[]'); } catch (e) { return []; } }
  function saveRestricted(url, reason = 'unknown') {
    try {
      const arr = getRestricted();
      if (!arr.includes(url)) arr.push(url);
      localStorage.setItem('restrictedUrls', JSON.stringify(arr));
      updateOverlay();
    } catch (e) { console.error(e); }
  }
  function clearAll() {
    if (!confirm('Clear queue, processed & restricted lists?')) return;
    localStorage.removeItem('archiveQueue');
    localStorage.removeItem('processedUrls');
    localStorage.removeItem('restrictedUrls');
    localStorage.removeItem('aq_last_wip_reload');
    sessionStorage.removeItem('forceSaveUrl');
    sessionStorage.removeItem('aq_processing');
    sessionStorage.removeItem('processingPaused');
    location.reload();
  }

  /* ===== UI ===== */
  function createOverlay() {
    if (document.getElementById('aq-overlay')) return;
    const ov = document.createElement('div');
    ov.id = 'aq-overlay';
    Object.assign(ov.style, {
      position: 'fixed', top: '18px', right: '18px', zIndex: 999999,
      background: 'rgba(255,255,255,0.97)', border: '1px solid #888', padding: '10px',
      fontFamily: 'sans-serif', fontSize: '13px', color: '#222', borderRadius: '8px',
      boxShadow: '0 4px 18px rgba(0,0,0,0.2)', maxWidth: '380px', maxHeight: '80vh', overflowY: 'auto'
    });
    ov.innerHTML = `
      <div style="display:flex;justify-content:space-between;align-items:center">
        <strong>Archive Queue v1.1.8</strong>
        <span id="aq-close" style="cursor:pointer;font-weight:bold">×</span>
      </div>
      <div style="display:grid;grid-template-columns:repeat(2,1fr);gap:6px;margin-top:8px">
        <button id="aq-add">Add URLs</button>
        <button id="aq-edit">Edit Queue</button>
        <button id="aq-resume">Resume</button>
        <button id="aq-pause">Pause</button>
        <button id="aq-export">Export Restricted</button>
        <button id="aq-clear">Clear All</button>
      </div>
      <div id="aq-input" style="display:none;margin-top:8px">
        <textarea id="aq-text" style="width:100%;height:80px" placeholder="URLs, one per line"></textarea>
        <div style="display:flex;gap:6px;margin-top:6px"><button id="aq-save">Save</button><button id="aq-cancel">Cancel</button></div>
      </div>
      <div id="aq-edit-area" style="display:none;margin-top:8px">
        <textarea id="aq-edit-text" style="width:100%;height:120px"></textarea>
        <div style="display:flex;gap:6px;margin-top:6px"><button id="aq-update">Update</button><button id="aq-edit-cancel">Cancel</button></div>
      </div>
      <pre id="aq-status" style="white-space:pre-wrap;margin-top:8px;padding:8px;background:#f6f6f6;border-radius:6px"></pre>
      <div id="aq-message" style="font-size:12px;color:#b40010;margin-top:6px"></div>
    `;
    document.body.appendChild(ov);

    ov.querySelector('#aq-close').onclick = () => ov.style.display = 'none';
    ov.querySelector('#aq-add').onclick = () => { document.getElementById('aq-input').style.display = 'block'; document.getElementById('aq-edit-area').style.display = 'none'; };
    ov.querySelector('#aq-edit').onclick = () => { document.getElementById('aq-edit-area').style.display = 'block'; document.getElementById('aq-input').style.display = 'none'; document.getElementById('aq-edit-text').value = getQueue().join('\n'); };
    ov.querySelector('#aq-resume').onclick = () => { sessionStorage.removeItem('processingPaused'); updateOverlay(); processQueue(); };
    ov.querySelector('#aq-pause').onclick = () => { sessionStorage.setItem('processingPaused', '1'); updateOverlay(); };
    ov.querySelector('#aq-export').onclick = exportRestricted;
    ov.querySelector('#aq-clear').onclick = clearAll;
    ov.querySelector('#aq-save').onclick = saveInput;
    ov.querySelector('#aq-cancel').onclick = () => document.getElementById('aq-input').style.display = 'none';
    ov.querySelector('#aq-update').onclick = updateQueue;
    ov.querySelector('#aq-edit-cancel').onclick = () => document.getElementById('aq-edit-area').style.display = 'none';

    updateOverlay();
  }

  function updateOverlay() {
    const q = getQueue().length;
    const p = getProcessed().length;
    const r = getRestricted().length;
    const st = document.getElementById('aq-status');
    if (st) st.textContent = `Queue: ${q}\nProcessed: ${p}\nRestricted: ${r}\nProcessing: ${sessionStorage.getItem('aq_processing') ? 'ACTIVE' : 'IDLE'}`;
    const msg = document.getElementById('aq-message');
    if (msg) {
      const captcha = !!document.querySelector('iframe[src*="recaptcha"], .g-recaptcha, [data-sitekey]') ||
                      (document.body && (document.body.innerText || '').toLowerCase().includes("i'm not a robot"));
      const paused = !!sessionStorage.getItem('processingPaused');
      msg.textContent = paused && captcha ? 'PAUSED - CAPTCHA detected. Solve it and click Resume.' : (paused ? 'PAUSED by user' : '');
    }
  }

  function saveInput() {
    const lines = (document.getElementById('aq-text').value || '').split('\n').map(s => s.trim()).filter(Boolean);
    if (lines.length) {
      const q = getQueue();
      saveQueue(q.concat(lines));
      document.getElementById('aq-text').value = '';
      document.getElementById('aq-input').style.display = 'none';
      updateOverlay();
      setTimeout(processQueue, 250);
    }
  }

  function updateQueue() {
    const lines = (document.getElementById('aq-edit-text').value || '').split('\n').map(s => s.trim()).filter(Boolean);
    saveQueue(lines);
    document.getElementById('aq-edit-area').style.display = 'none';
    updateOverlay();
    setTimeout(processQueue, 250);
  }

  // --- NEW HELPER FUNCTION TO FIND MOST COMMON USERNAME ---
  function findMostCommonUsername(urls) {
      const counts = {};
      const regex = /instagram\.com\/([^/]+)\/p\//;
      for (const url of urls) {
          const match = url.match(regex);
          if (match && match[1]) {
              const username = match[1];
              counts[username] = (counts[username] || 0) + 1;
          }
      }
      const keys = Object.keys(counts);
      if (!keys.length) return 'export';
      return keys.reduce((a, b) => counts[a] > counts[b] ? a : b);
  }

  // --- MODIFIED EXPORT FUNCTION ---
  function exportRestricted() {
      const arr = getRestricted();
      if (!arr.length) return alert('No restricted URLs.');

      const username = findMostCommonUsername(arr);
      const date = new Date().toISOString().slice(0, 10);
      const filename = `${username}_restricted-or-unavailable-urls_${date}.txt`;

      const content = arr.join('\n');
      const blob = new Blob([content], { type: 'text/plain' });
      const a = document.createElement('a');
      a.href = URL.createObjectURL(blob);
      a.download = filename;
      a.click();
      URL.revokeObjectURL(a.href);
  }

  /* ===== Core processing ===== */
  function isPaused() { return !!sessionStorage.getItem('processingPaused'); }
  function setProcessingFlag(val) { if (val) sessionStorage.setItem('aq_processing', '1'); else sessionStorage.removeItem('aq_processing'); }

  function processQueue() {
    if (isPaused()) { log('Processing is paused by user.'); setProcessingFlag(false); updateOverlay(); return; }
    if (sessionStorage.getItem('aq_processing')) { dbg('Already processing on another page/load.'); return; }

    const q = getQueue();
    if (!q.length) { log('Queue empty'); setProcessingFlag(false); updateOverlay(); return; }

    const next = q[0];
    const processed = getProcessed();
    const restricted = getRestricted();

    if (processed.includes(next) || restricted.includes(next)) {
      log('Next already handled, removing from queue:', next);
      q.shift(); saveQueue(q); setTimeout(processQueue, PROCESS_DELAY); return;
    }

    sessionStorage.setItem('aq_processing', '1');
    sessionStorage.setItem('forceSaveUrl', next);
    setProcessingFlag(true);
    updateOverlay();

    const nav = HOMEPAGE + next;
    log('Navigating to pre-check:', nav);
    window.location.href = nav;
  }

  /* ===== Helpers for homepage submit reliability (changed to be CAPTCHA-safe) ===== */
  function waitForInputAndSubmit(forcedUrl, onDone) {
    const SAVE_CLICK_TIMEOUT_MS = 5000;
    const SAVE_CLICK_POLL_MS = 250;
    const start = Date.now();
    let interval = setInterval(() => {
      try {
        // Detect CAPTCHA first — if present, PAUSE processing and don't navigate/reload
        const pageBody = (document.body && (document.body.innerText || '').toLowerCase()) || '';
        const captchaDetected = !!document.querySelector('iframe[src*="recaptcha"], .g-recaptcha, [data-sitekey]') ||
                                pageBody.includes("i'm not a robot") || pageBody.includes('captcha');

        if (captchaDetected) {
          clearInterval(interval);
          log('waitForInputAndSubmit: CAPTCHA detected on homepage/submit page — pausing processing to allow manual solve.');
          sessionStorage.setItem('processingPaused', '1');
          updateOverlay();
          alert('Archive Queue paused: CAPTCHA detected. Solve it in the page, then click Resume in the overlay.');
          onDone && onDone(false);
          return;
        }

        const input = document.querySelector('input#url, input[name="url"], input[type="text"][name="url"]');
        const submit = Array.from(document.querySelectorAll('input[type="submit"], button[type="submit"]'))
                            .find(el => (el.value && el.value.toLowerCase().includes('save')) || (el.textContent && el.textContent.toLowerCase().includes('save')));
        const value = input ? (input.value || '').trim() : '';
        dbg('waitForInputAndSubmit: input-value=', value, 'forced=', forcedUrl, 'submit?', !!submit);
        if (input && value && (!forcedUrl || value === forcedUrl || value.includes(forcedUrl))) {
          if (submit) {
            clearInterval(interval);
            log('Found input with value and save button -> clicking submit.');
            setTimeout(() => { try { submit.click(); } catch (e) { try { submit.dispatchEvent(new Event('click', { bubbles: true })); } catch(_){} } }, 80);
            onDone && onDone(true);
            return;
          } else {
            const form = input.closest('form') || document.querySelector('form[action*="/submit/"], form');
            if (form) {
              clearInterval(interval);
              log('No explicit save button, submitting form as fallback.');
              setTimeout(()=> { try { form.submit(); } catch(e){ try { const btn = form.querySelector('input[type="submit"], button[type="submit"]'); if(btn) btn.click(); } catch(_){} } }, 80);
              onDone && onDone(true);
              return;
            }
          }
        }
        if (Date.now() - start > SAVE_CLICK_TIMEOUT_MS) {
          clearInterval(interval);
          log('Timeout waiting for input/save on homepage.');
          // Before navigating to /submit/, re-check CAPTCHA — if captcha appears (rate-limiting caused it) -> PAUSE instead of navigating
          const pageBody2 = (document.body && (document.body.innerText || '').toLowerCase()) || '';
          const captchaNow = !!document.querySelector('iframe[src*="recaptcha"], .g-recaptcha, [data-sitekey]') ||
                             pageBody2.includes("i'm not a robot") || pageBody2.includes('captcha');
          if (captchaNow) {
            log('Captcha detected at timeout — pausing instead of navigating.');
            sessionStorage.setItem('processingPaused', '1');
            updateOverlay();
            alert('Archive Queue paused: CAPTCHA detected. Solve it in the page, then click Resume in the overlay.');
            onDone && onDone(false);
            return;
          }
          // No captcha — fallback navigate to submit path (same as before)
          if (forcedUrl) {
            window.location.href = `${HOMEPAGE}submit/?url=${encodeURIComponent(forcedUrl)}`;
            onDone && onDone(false);
            return;
          }
          onDone && onDone(false);
        }
      } catch (e) {
        console.error(e);
        clearInterval(interval);
        onDone && onDone(false);
      }
    }, SAVE_CLICK_POLL_MS);
  }

  /* ===== MODIFIED: Gentle WIP handler with backoff + cross-tab scheduling (NO timeout marking) ===== */
  function handleWipPage() {
    log('handleWipPage (gentle backoff, no timeout-marking)');
    const q = getQueue();
    if (!q.length) {
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      return;
    }
    const forced = sessionStorage.getItem('forceSaveUrl') || null;
    const retryKey = 'aq_wip_retries_' + location.pathname;
    let retries = parseInt(sessionStorage.getItem(retryKey) || '0', 10) + 1;
    sessionStorage.setItem(retryKey, String(retries));
    log('WIP: attempt', retries, 'for', forced);

    const share = document.getElementById('SHARE_LONGLINK');
    if (share) {
      const finalLink = share.querySelector('input')?.value || null;
      if (forced) saveProcessed(forced);
      sessionStorage.removeItem('forceSaveUrl');
      sessionStorage.removeItem(retryKey);
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      if (finalLink) {
        log('WIP done -> navigate to final:', finalLink);
        window.location.href = finalLink;
        return;
      } else {
        setTimeout(processQueue, PROCESS_DELAY);
        return;
      }
    }

    const exp = Math.min(retries - 1, MAX_BACKOFF_EXP);
    const base = BASE_WIP_POLL_MS;
    let delay = base * Math.pow(2, exp);
    const jitter = Math.floor((Math.random() * 2 - 1) * BACKOFF_JITTER_RATIO * delay);
    delay = Math.max(1000, delay + jitter);

    const lastScheduled = parseInt(localStorage.getItem('aq_last_wip_reload') || '0', 10);
    const now = Date.now();

    if (lastScheduled > now) {
      const remaining = Math.max(1000, lastScheduled - now);
      log('WIP: another tab already scheduled reload; waiting remaining ms =', remaining);
      setTimeout(() => {
        log('WIP: performing scheduled reload now (other-tab coordination).');
        try { localStorage.removeItem('aq_last_wip_reload'); } catch(e){}
        location.reload();
      }, remaining + 200);
      return;
    } else {
      const scheduledTime = now + delay;
      try { localStorage.setItem('aq_last_wip_reload', String(scheduledTime)); } catch (e) { log('localStorage write failed', e); }
      log('WIP: scheduling reload in ms =', delay, '(scheduled timestamp =', new Date(scheduledTime).toISOString(), ')');
      setTimeout(() => {
        try { localStorage.removeItem('aq_last_wip_reload'); } catch (e) {}
        log('WIP: reloading page now');
        location.reload();
      }, delay + 50);
      return;
    }
  }

  /* ===== Other page handlers (unchanged) ===== */
  function handlePreCheckPage() {
    log('handlePreCheckPage');
    const q = getQueue();
    if (!q.length) { setProcessingFlag(false); return; }
    const current = q[0];
    if (!location.hostname.match(/archive\.(ph|today|is|vn)$/i)) {
      log('On external domain — waiting.');
      return;
    }
    const selectors = ['#CONTENT', '#content', 'div[role="main"]', 'main', 'body'];
    let content = null;
    for (const s of selectors) { content = document.querySelector(s); if (content) break; }
    if (!content) {
      log('No content container found — marking restricted as fallback.');
      saveRestricted(current, 'no-content');
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    const text = (content.innerText || '').toLowerCase();
    if (content.querySelector('.THUMBS-BLOCK') || text.includes('thumbnail') || text.includes('thumb')) {
      log('Archive list detected on pre-check.');
      if (text.includes('redirected to') || text.includes('redirected')) {
        saveRestricted(current, 'redirected');
      } else if (text.includes('restricted photo') || text.includes('you must be 18') || text.includes('post isn\'t available')) {
        saveRestricted(current, 'restricted-content');
      } else {
        saveProcessed(current);
      }
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    const archiveLink = Array.from(content.querySelectorAll('a'))
      .find(a => {
        const t = (a.textContent || '').trim().toLowerCase();
        const h = (a.getAttribute && (a.getAttribute('href')||'')).toLowerCase();
        return t === 'archive this url' || h.includes('?url=') || h.includes('/submit/');
      });
    if (archiveLink) {
      log('Archive-this-url link found. Setting forced submit and clicking link.');
      sessionStorage.setItem('forceSaveUrl', current);
      try { archiveLink.click(); } catch (e) { window.location.href = HOMEPAGE; }
      return;
    }
    log('Pre-check: No results -> mark restricted');
    saveRestricted(current, 'no-results');
    q.shift(); saveQueue(q);
    sessionStorage.removeItem('aq_processing');
    setProcessingFlag(false);
    setTimeout(processQueue, PROCESS_DELAY);
  }

  function handleHomepage() {
    log('handleHomepage');
    const forced = sessionStorage.getItem('forceSaveUrl') || null;
    if (!forced) {
      setProcessingFlag(false);
      setTimeout(processQueue, 350);
      return;
    }
    log('Homepage: forced submit for', forced);
    waitForInputAndSubmit(forced, (clicked) => {
      log('Homepage: waitForInputAndSubmit result clicked=', clicked);
    });
  }

  function handleSubmitPage() {
    log('handleSubmitPage');
    const captcha = document.querySelector('iframe[src*="recaptcha"], .g-recaptcha, [data-sitekey]') ||
                    (document.body.innerText || '').toLowerCase().includes("i'm not a robot") ||
                    (document.body.innerText || '').toLowerCase().includes('captcha');
    if (captcha) {
      log('CAPTCHA detected -> pausing.');
      sessionStorage.setItem('processingPaused', '1');
      updateOverlay();
      // Notify user; let them solve it without script interference.
      alert('Archive Queue paused: CAPTCHA detected. Solve it manually then Resume in the overlay.');
      return;
    }
    const already = document.querySelector('#DIVALREADY, #DIVALREADY2, div[role="dialog"]');
    if (already && (already.innerText || '').toLowerCase().includes('this page was last archived')) {
      log('Submit page shows already archived popup — mark processed.');
      const forced = sessionStorage.getItem('forceSaveUrl') || null;
      if (forced) {
        saveProcessed(forced);
        const q = getQueue(); if (q.length && q[0] === forced) { q.shift(); saveQueue(q); }
        sessionStorage.removeItem('forceSaveUrl');
        sessionStorage.removeItem('aq_processing');
        setProcessingFlag(false);
        setTimeout(processQueue, PROCESS_DELAY);
      }
      return;
    }
    const saveBtn = Array.from(document.querySelectorAll('input[type="submit"], button[type="submit"]'))
      .find(el => ((el.value || '').toLowerCase().includes('save')) || ((el.textContent || '').toLowerCase().includes('save')));
    if (saveBtn) {
      log('Submit page: Save button found -> clicking.');
      setTimeout(()=> { try { saveBtn.click(); } catch (e) { try { saveBtn.dispatchEvent(new Event('click', { bubbles: true })); } catch(_){} } }, 120);
    } else {
      log('Submit page: no save button found.');
    }
  }

  function handleFinalPage() {
    log('handleFinalPage');
    const q = getQueue();
    if (!q.length) { sessionStorage.removeItem('aq_processing'); setProcessingFlag(false); return; }
    const current = q[0];
    const body = (document.body.innerText || '').toLowerCase();
    const already = document.querySelector('#DIVALREADY, #DIVALREADY2, div[role="dialog"]');
    if (already && (already.innerText || '').toLowerCase().includes('this page was last archived')) {
      log('Final: already archived popup -> processed');
      saveProcessed(current);
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('forceSaveUrl');
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    if (body.includes('restricted photo') || body.includes('you must be 18') || body.includes('post isn\'t available') || body.includes('this link may be broken') || body.includes('profile may have been removed') || body.includes('not available')) {
      log('Final: restricted/unavailable detected -> mark restricted');
      saveRestricted(current, 'restricted-or-unavailable');
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    if (document.getElementById('SHARE_LONGLINK') || document.getElementById('HEADER') || document.querySelector('.THUMBS-BLOCK')) {
      log('Final: success detected -> processed');
      saveProcessed(current);
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('forceSaveUrl');
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    if (body.includes('redirected to')) {
      log('Final: redirected to -> restricted');
      saveRestricted(current, 'redirected-final');
      q.shift(); saveQueue(q);
      sessionStorage.removeItem('aq_processing');
      setProcessingFlag(false);
      setTimeout(processQueue, PROCESS_DELAY);
      return;
    }
    const saveBtn = Array.from(document.querySelectorAll('input[type="submit"], button[type="submit"]'))
      .find(el => ((el.value || '').toLowerCase().includes('save')) || ((el.textContent || '').toLowerCase().includes('save')));
    if (saveBtn) {
      log('Final: found save button -> clicking as fallback');
      setTimeout(()=> { try { saveBtn.click(); } catch(e){ try { saveBtn.dispatchEvent(new Event('click', { bubbles: true })); } catch(_){} } }, 80);
      return;
    }
    log('Final: unknown page -> mark restricted (fallback)');
    saveRestricted(current, 'unknown-final');
    q.shift(); saveQueue(q);
    sessionStorage.removeItem('aq_processing');
    setProcessingFlag(false);
    setTimeout(processQueue, PROCESS_DELAY);
  }

  /* ===== Router ===== */
  function mainRouter() {
    createOverlay();
    updateOverlay();

    if (isPaused()) { log('Processing is paused (user).'); setProcessingFlag(false); return; }

    const path = location.pathname || '/';
    const search = location.search || '';

    if (path.startsWith('/wip/')) { handleWipPage(); return; }
    if (path.startsWith('/submit/')) { handleSubmitPage(); return; }
    if (/^\/https?:\/\//i.test(path) || search.toLowerCase().includes('url=')) {
      if (path === '/' && search.toLowerCase().includes('url=')) { handleHomepage(); return; }
      if (path.startsWith('/https://') || path.startsWith('/http://')) { handlePreCheckPage(); return; }
    }
    if (path === '/' || path === '') { handleHomepage(); return; }
    handleFinalPage();
  }

  if (document.readyState === 'loading') window.addEventListener('DOMContentLoaded', mainRouter);
  else mainRouter();

  setTimeout(() => { if (!isPaused()) processQueue(); }, 900);

})();

QingJ © 2025

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