Spotify: Исключить и Далее + Хоткей D/В (v8.1)

Добавляет кнопку "Исключить и Далее", а также горячую клавишу 'D' (включая русскую раскладку 'В') для выполнения этого действия.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Spotify: Исключить и Далее + Хоткей D/В (v8.1)
// @namespace    http://tampermonkey.net/
// @version      8.1
// @description  Добавляет кнопку "Исключить и Далее", а также горячую клавишу 'D' (включая русскую раскладку 'В') для выполнения этого действия.
// @author       Gemini
// @match        https://open.spotify.com/*
// @grant        none
// @icon         https://www.google.com/s2/favicons?sz=64&domain=spotify.com
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    console.log('[Spotify Dislike v8.1] Скрипт с горячей клавишей "D/В" запущен.');

    const SCRIPT_BUTTON_ID = 'gemini-dislike-button-v8-1';
    
    // Селекторы, подтвержденные нашей диагностикой
    const LIKE_BUTTON_SELECTOR = 'button[aria-label="Добавить в любимые треки"]';
    const MORE_OPTIONS_BUTTON_SELECTOR = 'button[data-testid="more-button"]';
    const NEXT_BUTTON_SELECTOR = 'button[data-testid="control-button-skip-forward"]';
    
    const DISLIKE_ICON_SVG = `<svg data-encore-id="icon" role="img" aria-hidden="true" class="e-91000-icon e-91000-baseline" style="--encore-icon-height: var(--encore-graphic-size-decorative-smaller); --encore-icon-width: var(--encore-graphic-size-decorative-smaller);" viewBox="0 0 16 16"><path d="M8 1.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0 -13M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8"></path><path d="M11.005 4.995a.75.75 0 0 1 0 1.06L9.061 8l1.944 1.945a.75.75 0 1 1-1.06 1.06L8 9.061l-1.945 1.944a.75.75 0 1 1-1.06-1.06L6.939 8 4.995 6.055a.75.75 0 1 1 1.06-1.06L8 6.939l1.945-1.944a.75.75 0 0 1 1.06 0"></path></svg>`;

    /**
     * Основная функция: исключает трек и переключает на следующий.
     */
    function performDislikeAndSkipAction() {
        console.log('[v8.1] Активирована функция "Исключить и Далее".');
        const moreOptionsButton = document.querySelector(MORE_OPTIONS_BUTTON_SELECTOR);
        if (!moreOptionsButton) {
            console.error('[v8.1] КРИТИЧЕСКАЯ ОШИБКА: Не удалось найти кнопку "Больше опций" (...).');
            return;
        }

        moreOptionsButton.click();

        setTimeout(() => {
            const allMenuItems = document.querySelectorAll('div[id="context-menu"] button[role="menuitem"]');
            let foundButton = null;

            for (const button of allMenuItems) {
                const span = button.querySelector('span');
                if (span && span.textContent.trim() === 'Исключить из музыкальных предпочтений') {
                    foundButton = button;
                    break;
                }
            }

            if (foundButton) {
                foundButton.click();
                setTimeout(() => {
                    const nextButton = document.querySelector(NEXT_BUTTON_SELECTOR);
                    if (nextButton) {
                        nextButton.click();
                    }
                }, 150);

            } else {
                console.error('[v8.1] Ошибка: Меню открылось, но пункт "Исключить..." НЕ найден.');
                document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
            }
        }, 300);
    }
    
    /**
     * Стандартная функция добавления кнопки на панель плеера.
     * @returns 
     */
    function addDislikeButton() {
        if (document.getElementById(SCRIPT_BUTTON_ID)) return;
        
        const likeButton = document.querySelector(LIKE_BUTTON_SELECTOR);
        if (likeButton) {
            const dislikeButton = document.createElement('button');
            dislikeButton.id = SCRIPT_BUTTON_ID;
            dislikeButton.className = likeButton.className;
            dislikeButton.setAttribute('aria-label', 'Исключить и переключить (D/В)');
            dislikeButton.style.marginLeft = '4px';
            const iconWrapper = document.createElement('span');
            iconWrapper.className = 'e-91000-button__icon-wrapper';
            iconWrapper.innerHTML = DISLIKE_ICON_SVG;
            dislikeButton.appendChild(iconWrapper);
            dislikeButton.onclick = performDislikeAndSkipAction;
            likeButton.insertAdjacentElement('afterend', dislikeButton);
        }
    }

    // Ищем место для вставки кнопки каждую секунду
    setInterval(addDislikeButton, 1000);

    // --- ОБРАБОТЧИК ГОРЯЧЕЙ КЛАВИШИ С УЧЕТОМ РАСКЛАДКИ ---
    document.addEventListener('keydown', function(event) {
        const target = event.target;
        const isTyping = target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable;

        // Проверяем код физической клавиши (независимо от раскладки)
        // 'KeyD' - это код для клавиши 'D' на стандартной QWERTY-клавиатуре
        if (event.code === 'KeyD' && !isTyping) {
            console.log('[v8.1] Нажата горячая клавиша D/В.');
            event.preventDefault();
            performDislikeAndSkipAction();
        }
    });

})();