Youtube "Remove From Playlist" Button

Adds a button next to the three dots menu to remove videos from a playlist with one click on YouTube

目前為 2025-03-31 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Youtube "Remove From Playlist" Button
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6
  5. // @description Adds a button next to the three dots menu to remove videos from a playlist with one click on YouTube
  6. // @author Lynrayy + art13
  7. // @match https://www.youtube.com/*
  8. // @grant none
  9. // @license MIT
  10. // @source https://github.com/lynrayy/YT-RM-BTN
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. console.log('Script started');
  17.  
  18. function addRemoveButton(video) {
  19. console.log('Adding remove button');
  20. const menuRenderer = video.querySelector('ytd-menu-renderer');
  21. if (!menuRenderer || menuRenderer.querySelector('.remove-button')) return;
  22.  
  23. const buttonContainer = document.createElement('button');
  24. buttonContainer.className = 'remove-button style-scope ytd-menu-renderer';
  25. buttonContainer.style.cssText = 'background: none; border: none; cursor: pointer; padding: 0; display: inline-flex; align-items: center; margin-right: 10px;';
  26.  
  27. // Создаём SVG иконку
  28. const trashIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  29. trashIcon.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  30. trashIcon.setAttribute('viewBox', '0 0 24 24');
  31. trashIcon.setAttribute('width', '24');
  32. trashIcon.setAttribute('height', '24');
  33. trashIcon.style.cssText = 'fill: #030303; vertical-align: middle;';
  34.  
  35. // Добавляем путь для иконки корзины
  36. const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  37. path.setAttribute('d', 'M11 17H9V8h2v9zm4-9h-2v9h2V8zm4-4v1h-1v16H6V5H5V4h4V3h6v1h4zm-2 1H7v15h10V5z');
  38. trashIcon.appendChild(path);
  39.  
  40. buttonContainer.appendChild(trashIcon);
  41.  
  42. buttonContainer.addEventListener('click', async () => {
  43. const menuButton = video.querySelector('ytd-menu-renderer yt-icon-button#button');
  44. if (!menuButton) return;
  45.  
  46. menuButton.click();
  47. await new Promise(resolve => setTimeout(resolve, 100));
  48.  
  49. const removeButton = document.querySelector('ytd-menu-service-item-renderer:nth-child(3) tp-yt-paper-item');
  50. if (removeButton) {
  51. removeButton.click();
  52. } else {
  53. alert('It was not possible to delete the video. Please try again.');
  54. }
  55. });
  56.  
  57. // Меняем flex-свойства для корректного выравнивания
  58. menuRenderer.style.display = 'flex';
  59. menuRenderer.style.alignItems = 'center';
  60. menuRenderer.insertBefore(buttonContainer, menuRenderer.firstChild);
  61. }
  62.  
  63. function addRemoveButtons() {
  64. console.log('Adding remove buttons to all videos');
  65. const videoContainers = document.querySelectorAll('ytd-playlist-video-renderer');
  66. videoContainers.forEach(addRemoveButton);
  67. }
  68.  
  69. function init() {
  70. console.log('Initializing script');
  71. addRemoveButtons();
  72.  
  73. const observer = new MutationObserver(mutations => {
  74. mutations.forEach(mutation => {
  75. mutation.addedNodes.forEach(node => {
  76. if (node.nodeType === 1 && node.matches('ytd-playlist-video-renderer')) {
  77. addRemoveButton(node);
  78. }
  79. });
  80. });
  81. });
  82.  
  83. observer.observe(document.body, { childList: true, subtree: true });
  84. window.addEventListener('yt-navigate-finish', addRemoveButtons);
  85. }
  86.  
  87. init();
  88. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址