⚙️Coub Downloading

Add 3 Buttons to download Video,audio,loop when click button you can open it in new tab by click mouse button or right click selet open in new tab to preview.

  1. // ==UserScript==
  2. // @name ⚙️Coub Downloading
  3. // @namespace Wizzergod
  4. // @version 1.0.3
  5. // @description Add 3 Buttons to download Video,audio,loop when click button you can open it in new tab by click mouse button or right click selet open in new tab to preview.
  6. // @icon https://www.google.com/s2/favicons?sz=64&domain=coub.com
  7. // @author Wizzergod
  8. // @license MIT
  9. // @match *://*.coub.com/*
  10. // @match *://coub.com/*
  11. // @grant GM_download
  12. // ==/UserScript==
  13.  
  14. (function ()
  15. {
  16. 'use strict';
  17.  
  18. function addButton(container, text, url)
  19. {
  20. const button = document.createElement('a');
  21. button.innerText = text;
  22. button.classList.add('coubdl-button');
  23. button.href = url;
  24. button.addEventListener('click', function (event)
  25. {
  26. event.preventDefault();
  27. downloadFile(url, getFileNameFromUrl(url));
  28. });
  29. container.appendChild(button);
  30. }
  31.  
  32. function downloadFile(url, fileName)
  33. {
  34. GM_download(
  35. {
  36. url: url,
  37. name: fileName
  38. });
  39. }
  40.  
  41. function getFileNameFromUrl(url)
  42. {
  43. const matches = url.match(/\/([^\/?#]+)[^\/]*$/);
  44. return matches && matches[1];
  45. }
  46.  
  47. function addControls()
  48. {
  49. const coubContainers = document.querySelectorAll('.coub');
  50.  
  51. coubContainers.forEach(container =>
  52. {
  53. const permalink = container.dataset.permalink;
  54. if (!permalink)
  55. {
  56. return;
  57. }
  58.  
  59. const descriptionControls = container.querySelector('.coub__description');
  60. if (!descriptionControls)
  61. {
  62. return;
  63. }
  64.  
  65. const existingControls = container.querySelector('.coubdl-button-group');
  66. if (existingControls)
  67. {
  68. return;
  69. }
  70.  
  71. const controlsContainer = document.createElement("div");
  72. controlsContainer.classList.add("coubdl-button-group");
  73.  
  74. const dataContainer = container.querySelector(
  75. '.data script[type="text/json"]'
  76. );
  77. if (dataContainer)
  78. {
  79. const data = JSON.parse(dataContainer.textContent);
  80. if (data && data.file_versions && data.file_versions.html5)
  81. {
  82. const html5Data = data.file_versions.html5;
  83.  
  84. if (
  85. html5Data.video &&
  86. html5Data.video.high &&
  87. html5Data.video.high.url
  88. )
  89. {
  90. const videoUrl = html5Data.video.high.url;
  91. addButton(controlsContainer, "⬇️ Video", videoUrl);
  92. }
  93.  
  94. if (
  95. html5Data.audio &&
  96. html5Data.audio.high &&
  97. html5Data.audio.high.url
  98. )
  99. {
  100. const audioUrl = html5Data.audio.high.url;
  101. addButton(controlsContainer, "⬇️ Audio", audioUrl);
  102. }
  103. }
  104.  
  105. if (
  106. data &&
  107. data.file_versions &&
  108. data.file_versions.share &&
  109. data.file_versions.share.default
  110. )
  111. {
  112. const loopedUrl = data.file_versions.share.default;
  113. addButton(controlsContainer, "⬇️ Looped Video", loopedUrl);
  114. }
  115. }
  116.  
  117. descriptionControls.prepend(controlsContainer);
  118. });
  119. }
  120.  
  121. function observeChanges()
  122. {
  123. const observer = new MutationObserver((mutations) =>
  124. {
  125. mutations.forEach((mutation) =>
  126. {
  127. Array.from(mutation.addedNodes).forEach((node) =>
  128. {
  129. if (node.nodeType === Node.ELEMENT_NODE)
  130. {
  131. addControls();
  132. }
  133. });
  134. });
  135. });
  136.  
  137. observer.observe(document.body,
  138. {
  139. childList: true,
  140. subtree: true,
  141. });
  142. }
  143.  
  144. function init()
  145. {
  146. addControls();
  147. observeChanges();
  148. }
  149.  
  150. // Add CSS styles
  151. const style = document.createElement('style');
  152. style.textContent = `
  153. .coubdl-button-group {
  154. display: flex;
  155. flex-direction: row;
  156. justify-content: center;
  157. gap: 10px;
  158. margin-top: 10px;
  159. width: 100%;
  160. position: relative;
  161. }
  162.  
  163. .coubdl-button {
  164. padding: 4px 8px;
  165. color: #000;
  166. background: #fff0;
  167. line-height: 1;
  168. border-radius: 0px;
  169. text-decoration: none;
  170. border: none;
  171. display: inline-block;
  172. transition: background-color 0.3s ease;
  173. }
  174.  
  175. .coubdl-button:hover,
  176. .coubdl-button:active,
  177. .coubdl-button:focus {
  178. color: #0332FF;
  179. }
  180. `;
  181. document.head.appendChild(style);
  182.  
  183. init();
  184.  
  185. })();

QingJ © 2025

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