Copy YouTube Channel Video Info (Simplest)

Copy video titles, dates, and views - simplest version.

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

You will need to install an extension such as Tampermonkey to install this script.

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

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

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

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

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Copy YouTube Channel Video Info (Simplest)
// @match        https://www.youtube.com/*/videos
// @grant        none
// @version      1
// @author       lmdw
// @description  Copy video titles, dates, and views - simplest version.
// @namespace https://greasyfork.org/users/1436006
// ==/UserScript==

(function() {
    'use strict';

    // --- CẤU HÌNH ---
    const SCROLL_DELAY = 1500;
    const LOAD_CHECK_DELAY = 3000;
    const MAX_CHECK_ATTEMPTS = 5;
    const OUTPUT_FORMAT = "{title} / {date} / {views}";

    // --- HẾT PHẦN CẤU HÌNH ---

    function countVideoTitles() {
        return document.querySelectorAll('a#video-title-link yt-formatted-string#video-title').length;
    }

    function getVideoInfo() {
        const videoContainers = document.querySelectorAll('ytd-rich-grid-media');
        let videoData = [];

        for (const container of videoContainers) {
            const titleElement = container.querySelector('a#video-title-link yt-formatted-string#video-title');
            const title = titleElement ? titleElement.innerText.trim() : "Không có tiêu đề";

            const metaBlocks = container.querySelectorAll(".inline-metadata-item.style-scope.ytd-video-meta-block");
            let date = "Không có ngày";
            let views = "Không có lượt xem";

            if (metaBlocks.length >= 2) {
                date = metaBlocks[1] ? metaBlocks[1].innerText.trim() : "Không có ngày";
                views = metaBlocks[0] ? metaBlocks[0].innerText.trim() : "Không có lượt xem";
            }

            let output = OUTPUT_FORMAT
                .replace("{title}", title)
                .replace("{date}", date)
                .replace("{views}", views);

            videoData.push(output);
        }
        return videoData;
    }

    function copyVideoInfoToClipboard(videoData, message) {
         if (videoData.length === 0) {
            alert("Không tìm thấy video nào.");
            return;
        }
        const allVideoInfo = videoData.join('\n');
        navigator.clipboard.writeText(allVideoInfo)
            .then(() => {
                alert(message);
            })
            .catch(err => {
                console.error('Lỗi khi copy:', err);
                alert("Có lỗi xảy ra khi copy. Vui lòng thử lại.");
            });
    }

    function scrollToBottomAndLoad(callback) {
        let initialTitleCount = countVideoTitles();
        let checkAttempts = 0;

        function scrollAndWait() {
            window.scrollTo(0, document.documentElement.scrollHeight);
            console.log("Đang cuộn...");
            setTimeout(checkIfLoaded, LOAD_CHECK_DELAY);
        }

        function checkIfLoaded() {
            let newTitleCount = countVideoTitles();

            if (newTitleCount > initialTitleCount) {
                // Đã load thêm, tiếp tục cuộn
                initialTitleCount = newTitleCount;
                checkAttempts = 0;
                scrollAndWait();
            } else {
                // Không load thêm
                checkAttempts++;
                if (checkAttempts >= MAX_CHECK_ATTEMPTS) {
                    // Copy ngay lập tức những gì hiện có
                    callback(getVideoInfo(), "Đã dừng cuộn và copy thông tin video hiện có.");
                    return;
                } else {
                    console.log("Chưa load thêm, thử lại sau " + LOAD_CHECK_DELAY + "ms. Lần thử: ", checkAttempts);
                    setTimeout(checkIfLoaded, LOAD_CHECK_DELAY);
                }
            }
        }

         //Bắt đầu
        if(initialTitleCount === 0){
          alert("Không tìm thấy video nào");
          return;
        }
        scrollAndWait();
    }

  function startCopyProcess() {

        const shouldScroll = confirm("Bạn có muốn cuộn trang để tải thêm video không?");

        if (shouldScroll) {

            scrollToBottomAndLoad(copyVideoInfoToClipboard); //Truyền callback vào

        } else {
              const videoData = getVideoInfo();
            if (videoData.length > 0){
                copyVideoInfoToClipboard(videoData, "Đã copy thông tin video hiện có.");
            } else{
              alert("Không tìm thấy video nào");
            }

        }
    }

    // --- Thêm nút Copy ---
    const button = document.createElement('button');
    button.textContent = 'Copy Video Info';
    button.style.position = 'fixed';
    button.style.top = '10px';
    button.style.right = '10px';
    button.style.zIndex = '9999';
    button.style.backgroundColor = '#4CAF50';
    button.style.border = 'none';
    button.style.color = 'white';
    button.style.padding = '10px 20px';
    button.style.textAlign = 'center';
    button.style.textDecoration = 'none';
    button.style.display = 'inline-block';
    button.style.fontSize = '16px';
    button.style.cursor = 'pointer';
    button.addEventListener('click', startCopyProcess);
    document.body.appendChild(button);
})();