YouTube Channel Playlist Button

Adds a button linking to the channel's playlist on YouTube channel pages

Від 23.09.2024. Дивіться остання версія.

// ==UserScript==
// @name         YouTube Channel Playlist Button
// @namespace    https://greasyfork.org/en/users/703184-floriegl
// @version      1.0
// @description  Adds a button linking to the channel's playlist on YouTube channel pages
// @author       floriegl
// @match        https://www.youtube.com/*
// @license      MIT
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    let ytdAppData = undefined;
    let actionModel = undefined;
    let channelId = undefined;

    function addPlaylistButton() {
        if (!document.getElementById('channel-playlist-link')) {
            actionModel.insertAdjacentHTML('beforeend', `
                <a class="yt-flexible-actions-view-model-wiz__action" id="channel-playlist-link" style="text-decoration: none">
                    <button-view-model class="yt-spec-button-view-model">
                        <button class="yt-spec-button-shape-next yt-spec-button-shape-next--outline yt-spec-button-shape-next--mono yt-spec-button-shape-next--size-m yt-spec-button-shape-next--enable-backdrop-filter-experiment"
                                aria-label="Go to Channel Playlist" title style="">
                            <div class="yt-spec-button-shape-next__button-text-content">Channel Playlist</div>
                            <yt-touch-feedback-shape style="border-radius: inherit;">
                                <div class="yt-spec-touch-feedback-shape yt-spec-touch-feedback-shape--touch-response" aria-hidden="true">
                                    <div class="yt-spec-touch-feedback-shape__stroke" style=""></div>
                                    <div class="yt-spec-touch-feedback-shape__fill" style=""></div>
                                </div>
                            </yt-touch-feedback-shape>
                        </button>
                    </button-view-model>
                </a>`);
        }

        document.getElementById('channel-playlist-link').href = `/playlist?list=UU${channelId.substring(2)}`;
    }

    function extractCurrentChannelId() {
        channelId = null;
        if (ytdAppData) {
            const pageType = ytdAppData.page;
            if (pageType === 'channel' && ytdAppData.endpoint && ytdAppData.endpoint.browseEndpoint) {
                const currentChannelId = ytdAppData.endpoint.browseEndpoint.browseId;
                if (currentChannelId.startsWith('UC')) {
                    channelId = currentChannelId;
                }
            }
        }
    }

    const readdObserver = new MutationObserver(() => {
        if (!document.getElementById('channel-playlist-link')) {
            addPlaylistButton();
        }
    });

    function checkChannelPage() {
        extractCurrentChannelId();
        if (channelId && actionModel) {
            readdObserver.disconnect();
            readdObserver.observe(actionModel, { childList: true, subtree: false });
            addPlaylistButton();
        } else {
            readdObserver.disconnect();
        }
    }

    const ytdApp = document.querySelector('ytd-app');
    const observer = new MutationObserver(() => {
        if (ytdAppData !== ytdApp.data) {
            ytdAppData = ytdApp.data;
            checkChannelPage();
        }
        if (actionModel !== document.querySelector('.yt-flexible-actions-view-model-wiz')) {
            actionModel = document.querySelector('.yt-flexible-actions-view-model-wiz');
            checkChannelPage();
        }
    });
    observer.observe(ytdApp, { childList: true, subtree: true });
})();