CyPwn → LiveContainer Installer (iOS)

On ipa.cypwn.xyz, replace TrollStore's apple-magnifier installer links with LiveContainer's install URL so the IPA installs inside LiveContainer.

目前為 2025-09-23 提交的版本,檢視 最新版本

// ==UserScript==
// @name         CyPwn → LiveContainer Installer (iOS)
// @namespace    sharmanhall
// @version      0.1
// @description  On ipa.cypwn.xyz, replace TrollStore's apple-magnifier installer links with LiveContainer's install URL so the IPA installs inside LiveContainer.
// @author       sharmanhall
// @match        https://ipa.cypwn.xyz/*
// @match        *://*/*
// @grant        none
// @license      MIT
// @run-at       document-start
// @noframes
// ==/UserScript==

(function () {
  'use strict';

  // ---- prefs ----
  const VERBOSE = true;                        // console logs
  const ONLY_ON_CYPWN = true;                  // set false to also translate TrollStore links on any site
  const PATCH_ANCHORS = true;                  // hook <a href="apple-magnifier://install?url=...">
  const PATCH_WINDOW_NAV = true;               // intercept window.open / location.assign / location.replace
  const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);

  // Respect ONLY_ON_CYPWN
  if (ONLY_ON_CYPWN && !location.hostname.endsWith('ipa.cypwn.xyz')) return;

  function log(...args){ if (VERBOSE) console.log('[LC-CyPwn]', ...args); }

  // Build livecontainer://install?url=<encoded IPA URL>
  function toLcInstallFromAppleMagnifier(urlLike) {
    try {
      const u = (urlLike instanceof URL) ? urlLike : new URL(urlLike);
      if (u.protocol !== 'apple-magnifier:' || u.pathname.replace(/^\//,'') !== 'install') return null;
      const ipaUrl = u.searchParams.get('url');
      if (!ipaUrl) return null;
      // Encode the IPA URL to be safe inside query
      const encoded = encodeURIComponent(ipaUrl);
      return `livecontainer://install?url=${encoded}`;
    } catch {
      // Fallback regex parse
      const m = String(urlLike).match(/^apple-magnifier:\/\/install\?url=(.+)$/i);
      if (!m) return null;
      const encoded = encodeURIComponent(decodeURIComponent(m[1]));
      return `livecontainer://install?url=${encoded}`;
    }
  }

  function redirectToLC(lcUrl) {
    log('→ LiveContainer install:', lcUrl);
    // replace() avoids polluting history
    location.replace(lcUrl);
  }

  // ---- Anchor rewriting ----
  function hookAnchor(a) {
    if (!a || a.dataset.lcCypwn === '1') return;
    const href = a.getAttribute('href');
    if (!href || !href.startsWith('apple-magnifier://install')) return;

    a.addEventListener('click', (e) => {
      try {
        const lc = toLcInstallFromAppleMagnifier(href);
        if (isIOS && lc) {
          e.preventDefault();
          e.stopPropagation();
          redirectToLC(lc);
        }
      } catch (err) {
        log('Anchor handler error:', err);
      }
    }, { capture: true, passive: false });

    a.dataset.lcCypwn = '1';
    log('Hooked TrollStore → LC link:', href);
  }

  if (PATCH_ANCHORS) {
    // Initial pass
    document.addEventListener('DOMContentLoaded', () => {
      document.querySelectorAll('a[href^="apple-magnifier://install"]').forEach(hookAnchor);
    });

    // Early pass (for immediate interactions)
    try {
      document.querySelectorAll('a[href^="apple-magnifier://install"]').forEach(hookAnchor);
    } catch {}

    // Observe dynamic additions
    const mo = new MutationObserver((muts) => {
      for (const m of muts) {
        for (const node of m.addedNodes) {
          if (node.nodeType !== 1) continue;
          if (node.tagName === 'A' && node.href?.startsWith('apple-magnifier://install')) {
            hookAnchor(node);
          } else {
            node.querySelectorAll?.('a[href^="apple-magnifier://install"]').forEach(hookAnchor);
          }
        }
      }
    });
    mo.observe(document.documentElement, { childList: true, subtree: true });
  }

  // ---- Intercept JS navigations (best-effort) ----
  if (PATCH_WINDOW_NAV) {
    // window.open
    const _open = window.open;
    window.open = function(url, ...rest) {
      try {
        if (typeof url === 'string' && url.startsWith('apple-magnifier://install')) {
          const lc = toLcInstallFromAppleMagnifier(url);
          if (isIOS && lc) { redirectToLC(lc); return null; }
        }
      } catch (e) { log('window.open patch error:', e); }
      return _open.apply(this, [url, ...rest]);
    };

    // location.assign / replace
    const _assign = Location.prototype.assign;
    const _replace = Location.prototype.replace;

    Location.prototype.assign = function(url) {
      try {
        if (typeof url === 'string' && url.startsWith('apple-magnifier://install')) {
          const lc = toLcInstallFromAppleMagnifier(url);
          if (isIOS && lc) return _replace.call(this, lc);
        }
      } catch (e) { log('location.assign patch error:', e); }
      return _assign.call(this, url);
    };

    Location.prototype.replace = function(url) {
      try {
        if (typeof url === 'string' && url.startsWith('apple-magnifier://install')) {
          const lc = toLcInstallFromAppleMagnifier(url);
          if (isIOS && lc) return _replace.call(this, lc);
        }
      } catch (e) { log('location.replace patch error:', e); }
      return _replace.call(this, url);
    };
  }
})();