Google Play Mirror Link

Google Play Mirror Link Redirect

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name               Google Play Mirror Link
// @name:zh-CN         Google Play 镜像商店跳转
// @description        Google Play Mirror Link Redirect
// @description:zh-CN  Google Play 镜像商店一键跳转到镜像网站
// @namespace          https://www.runningcheese.com/p03
// @author             RunningCheese
// @version            0.1
// @description        在 Google Play 应用商店页面添加镜像搜索按钮
// @match              https://play.google.com/store/apps/details?id=*
// @match              https://play.google.com/store/apps/details/*?id=*
// @icon               https://t2.gstatic.com/faviconV2?client=SOCIAL&url=http://play.google.com&size=32
// @grant              none
// @run-at             document-start
// @license            MIT
// ==/UserScript==

(function() {
    'use strict';

    // 获取当前应用包名
    const appId = new URLSearchParams(window.location.search).get('id');
    if (!appId) return;

    // 注入CSS样式
    const style = document.createElement('style');
    style.textContent = `
        .gp-download-dropdown {
            position: relative;
            display: inline-block;
        }
        .gp-dropdown-content {
            display: none;
            position: absolute;
            background-color: #ffffff;
            min-width: 160px;
            box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
            z-index: 1000;
            border-radius: 4px;
            right: 0;
            top: 100%;
            margin-top: 4px;
            border: 1px solid #dadce0;
        }
        .gp-dropdown-content a {
            color: #3c4043;
            padding: 12px 16px;
            text-decoration: none;
            display: block;
            font-size: 14px;
            font-family: 'Google Sans',Roboto,Arial,sans-serif;
        }
        .gp-dropdown-content a:hover {
            background-color: #f1f3f4;
        }
        .gp-show {
            display: block;
        }
    `;
    (document.head || document.documentElement).appendChild(style);

    // 获取应用名称
    function getAppName() {
        const h1 = document.querySelector('h1');
        return h1 ? h1.textContent.trim() : appId;
    }

    // 创建下载下拉菜单
    function createDownloadDropdown() {
        const container = document.createElement('div');
        container.className = 'u4ICaf gp-download-dropdown';

        const button = document.createElement('button');
        button.className = 'P9KVBf VfPpkd-LgbsSe VfPpkd-LgbsSe-OWXEXe-k8QpJ VfPpkd-LgbsSe-OWXEXe-dgl2Hf nCP5yc AjY5Oe DuMIQc LQeN7 MjT6xe sOCCfd brKGGd BhQfub ishze P44HY';
        button.setAttribute('aria-label', 'Download Options');

        const span = document.createElement('span');
        span.textContent = '镜像下载';
        span.style.marginRight = '4px';
        button.appendChild(span);

        // Add arrow icon
        const arrow = document.createElement('span');
        arrow.innerHTML = '▼';
        arrow.style.fontSize = '10px';
        button.appendChild(arrow);

        const dropdown = document.createElement('div');
        dropdown.className = 'gp-dropdown-content';

        const appName = getAppName();
        const links = [
            { name: '豌豆荚', url: `https://www.wandoujia.com/search?key=${appName}` },
            { name: 'APKPure', url: `https://apkpure.com/cn/search?q=${appId}` },
            { name: 'GitHub', url: `https://github.com/search?q=${encodeURIComponent(appName)}` },
            { name: '-------', url: '#' },
            { name: 'LiteAPKs', url: `https://liteapks.com/?s=${encodeURIComponent(appName)}` },
            { name: 'Appteka', url: `https://appteka.store/search?q=${encodeURIComponent(appName)}` },
            { name: '9Mod', url: `https://9mod.com/?s=${encodeURIComponent(appName)}` },
            { name: 'APKMody', url: `https://apkmody.mobi/?s=${encodeURIComponent(appName)}` },
            { name: 'ModDroid', url: `https://moddroid.com/search/?s=${encodeURIComponent(appName)}` }
        ];

        links.forEach(link => {
            const a = document.createElement('a');
            a.href = link.url;
            a.target = '_blank';
            a.textContent = link.name;
            dropdown.appendChild(a);
        });

        // 异步获取英文名称并更新链接
        fetch(`https://play.google.com/store/apps/details?id=${appId}&hl=en`)
            .then(response => response.text())
            .then(html => {
                const parser = new DOMParser();
                const doc = parser.parseFromString(html, "text/html");
                const h1 = doc.querySelector('h1');
                if (h1) {
                    const enAppName = h1.textContent.split(' - ')[0].trim();
                    const nameBasedLinks = {
                        'LiteAPKs': `https://liteapks.com/?s=${encodeURIComponent(enAppName)}`,
                        'ModDroid': `https://moddroid.com/search/?s=${encodeURIComponent(enAppName)}`,
                        'Appteka': `https://appteka.store/search?q=${encodeURIComponent(enAppName)}`
                    };

                    Array.from(dropdown.children).forEach(a => {
                        if (nameBasedLinks[a.textContent]) {
                            a.href = nameBasedLinks[a.textContent];
                        }
                    });
                }
            })
            .catch(err => console.error('Failed to fetch English app name', err));

        button.onclick = function(e) {
            e.stopPropagation();
            dropdown.classList.toggle('gp-show');
        };

        // Close dropdown when clicking outside
        document.addEventListener('click', function(e) {
            if (!container.contains(e.target)) {
                dropdown.classList.remove('gp-show');
            }
        });

        container.appendChild(button);
        container.appendChild(dropdown);
        return container;
    }

    // 在安装按钮旁插入下载下拉菜单
    function insertButton() {
        const buttonContainer = document.querySelector('.kk2r5b .edaMIf .bGJWSe > c-wiz > div');
        if (!buttonContainer) return false;

        // 检查是否已存在下载按钮
        if (buttonContainer.querySelector('.gp-download-dropdown')) return false;

        const downloadDropdown = createDownloadDropdown();
        buttonContainer.appendChild(downloadDropdown);
        return true;
    }

    const tryInsert = () => insertButton();

    if (!tryInsert()) {
        const timer = setInterval(() => {
            if (tryInsert()) {
                clearInterval(timer);
            }
        }, 120);

        const observer = new MutationObserver(() => {
            if (tryInsert()) {
                clearInterval(timer);
                observer.disconnect();
            }
        });

        observer.observe(document.documentElement, {
            childList: true,
            subtree: true
        });

        setTimeout(() => {
            clearInterval(timer);
            observer.disconnect();
        }, 15000);
    }
})();