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

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

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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();
        }
    });

})();