asp

Adds a custom button and sends data to a server using fetch API with extra permissions.

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         asp
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  Adds a custom button and sends data to a server using fetch API with extra permissions.
// @author       You
// @match        https://www.youtube.com/watch*
// @grant        none
// @connect      localhost
// ==/UserScript==

(function () {
    'use strict';

    const BUTTON_ID = 'custom-tm-xpath-button';

    // Create and inject the button
    function createButton() {
        const button = document.createElement('button');
        button.id = BUTTON_ID;
        button.textContent = 'Soundpad';
        button.style.marginLeft = '10px';
        button.style.padding = '6px 12px';
        button.style.fontSize = '14px';
        button.style.border = 'none';
        button.style.backgroundColor = '#272727';
        button.style.color = '#fff';
        button.style.cursor = 'pointer';
        button.style.fontFamily = '"Roboto","Arial",sans-serif';
        button.style.fontWeight = 500;
        button.style.borderRadius = '99999px';
        button.onclick = () => sendDataToServer(window.location.href); // Send current video URL
        return button;
    }

    // Function to send data to the server using fetch
    function sendDataToServer(videoUrl) {
        fetch('http://localhost:8955/', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ url: videoUrl }),
        })
        .then(response => response.text())
        .then(data => {
            console.log('Response from server:', data);
        })
        .catch(error => {
            console.error('Error sending data to server:', error);
        });
    }

    // Inject custom styles
    function injectStyles() {
        const styles = `
            #${BUTTON_ID}:hover {
                background-color: #3f3f3f;
            }
        `;

        const styleSheet = document.createElement("style");
        styleSheet.type = "text/css";
        styleSheet.innerText = styles;
        document.head.appendChild(styleSheet);
    }

    // Function to inject both the button and styles
    function injectButtonAndStyles() {
        const xpath = '/html/body/ytd-app/div[1]/ytd-page-manager/ytd-watch-flexy/div[5]/div[1]/div/div[2]/ytd-watch-metadata/div/div[2]/div[2]/div/div/ytd-menu-renderer';
        const result = document.evaluate(xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

        const targetElement = result.singleNodeValue;

        if (!targetElement || document.getElementById(BUTTON_ID)) return;

        // Inject styles first
        injectStyles();

        // Inject button
        const button = createButton();
        targetElement.appendChild(button);

        console.log('[YouTubeButton] Custom button and stylesheet added to target XPath');
    }

    // Ensure the page is fully loaded before trying to inject the button and styles
    window.onload = function () {
        // First try after the window has fully loaded
        injectButtonAndStyles();

        // Fallback for dynamic page updates (SPA)
        const observer = new MutationObserver(() => {
            injectButtonAndStyles();
        });

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

})();