Кнопка скачать для больших файлов

Скрипт Tampermonkey для скачивания файлов с Яндекс.Диска без установки клиента

// ==UserScript==
// @name         Кнопка скачать для больших файлов
// @namespace    http://tampermonkey.net/
// @version      2025-04-10
// @description  Скрипт Tampermonkey для скачивания файлов с Яндекс.Диска без установки клиента
// @author       You
// @match        https://disk.yandex.ru/d/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=yandex.ru
// @run-at        document-start
// @license GNU AGPLv3
// ==/UserScript==

(function() {
    'use strict';

    function addCustomStyles() {
        const style = document.createElement('style');
        style.type = 'text/css';
        style.innerHTML = `
            button.DownloadBtn {
    margin-left: 12px;
    margin-right: 12px;
}
        `;
        document.head.appendChild(style);
    }

    const getDownloadLink = () => {
        return new Promise((resolve,reject)=>{
            const obj = JSON.parse(document.querySelector(`#store-prefetch`).textContent);
            const actions = document.querySelector(".action-buttons");
            const fiberNode = actions[Object.keys(actions).find(k => k.startsWith('__reactInternal'))];
            const currentId = fiberNode.memoizedProps.children.find(e=>e.props?.resourceId)?.props.resourceId;
            const currentDir = obj.resources[currentId];
            const downloadData = {"hash":currentDir.hash,"sk":obj.environment.sk,"uid":obj.user.id}
            fetch("https://disk.yandex.ru/public/api/download-url", {
                "headers": {
                    "accept": "*/*",
                    "accept-language": "ru,tr;q=0.9,he;q=0.8,ar;q=0.7,en-US;q=0.6,en;q=0.5,bg;q=0.4",
                    "cache-control": "no-cache",
                    "content-type": "text/plain",
                    "pragma": "no-cache",
                    "sec-ch-ua": "\"Chromium\";v=\"134\", \"Not:A-Brand\";v=\"24\", \"Google Chrome\";v=\"134\"",
                    "sec-ch-ua-mobile": "?0",
                    "sec-ch-ua-platform": "\"Windows\"",
                    "sec-fetch-dest": "empty",
                    "sec-fetch-mode": "cors",
                    "sec-fetch-site": "same-origin",
                    "x-requested-with": "XMLHttpRequest",
                    "x-retpath-y": location.href
                },
                "referrer": location.href,
                "referrerPolicy": "strict-origin-when-cross-origin",
                "body": encodeURIComponent(JSON.stringify(downloadData)),
                "method": "POST",
                "mode": "cors",
                "credentials": "include"
            }).then(e=>e.json()).then(e=>resolve(e.data.url)).catch(e=>reject(e))
        })
    }

    function createDownloadButton() {
        const button = document.createElement('button');
        button.type = 'button';
        button.className = 'DownloadBtn Button2 Button2_view_raised Button2_size_m download-button action-buttons__button action-buttons__button_download';
        button.setAttribute('aria-disabled', 'false');
        button.setAttribute('autocomplete', 'off');

        const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
        svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
        svg.setAttribute('xmlns:xlink', 'http://www.w3.org/1999/xlink');
        svg.setAttribute('focusable', 'false');
        svg.setAttribute('aria-hidden', 'true');
        svg.setAttribute('width', '16');
        svg.setAttribute('height', '16');
        svg.setAttribute('viewBox', '0 0 16 16');

        const path1 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        path1.setAttribute('fill', 'currentColor');
        path1.setAttribute('d', 'M10.632 4.843 8.803 6.672V1h-2v5.672L4.975 4.843 3.56 6.257 7.803 10.5l4.243-4.243z');

        const path2 = document.createElementNS('http://www.w3.org/2000/svg', 'path');
        path2.setAttribute('fill', 'currentColor');
        path2.setAttribute('d', 'M1 12V8h2v4a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V8h2v4a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3');

        svg.appendChild(path1);
        svg.appendChild(path2);

        const textSpan = document.createElement('span');
        textSpan.className = 'Button2-Text';
        textSpan.textContent = 'Без установки Я.Диска';

        const iconSpan = document.createElement('span');
        iconSpan.className = 'Button2-Icon Button2-Icon_side_left';
        iconSpan.appendChild(svg);

        button.appendChild(iconSpan);
        button.appendChild(textSpan);

        button.addEventListener('click',()=>{
            getDownloadLink().then(e=>window.open(e,"_blank"))
        });

        return button;
    }

    function addDownloadButton() {
        const actionButtons = document.querySelector('.action-buttons');
        if (actionButtons && !document.querySelector('.DownloadBtn')) {
            const downloadButton = createDownloadButton();
            actionButtons.appendChild(downloadButton);
            addCustomStyles();
        } else {
            console.warn('Элемент .action-buttons не найден на странице.');
        }
    }

    window.addEventListener('load', () => {
        addDownloadButton();

        const observer = new MutationObserver(() => {
            addDownloadButton();
            observer.disconnect();
        });

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