Youtube قوراللىرى ھەممىسى بىر يەرلىك چۈشۈرۈش MP4,mp3

Youtube قورالىنىڭ ھەممىسى بىر يەرلىك چۈشۈرۈشتە mp4, MP3 HIGH QUAقنى قا

بۇ قوليازمىنى قاچىلاش؟
ئاپتورنىڭ تەۋسىيەلىگەن قوليازمىسى

سىز بەلكىم WhatsApp Sticker Creator with Custom Maker Enhanced نى ياقتۇرۇشىڭىز مۇمكىن.

بۇ قوليازمىنى قاچىلاش
  1. // ==UserScript==
  2. // @name Youtube Tools All in one local download mp3 mp4 HIGT QUALITY return dislikes and more
  3. // @name:zh-TW Youtube 工具 多合一本地下載 MP4、MP3
  4. // @name:zh-HK Youtube 工具 多合一本地下載 MP4、MP3
  5. // @name:zh-CN Youtube 工具 多合一本地下載 MP4、MP3
  6. // @name:ja Youtube ツール オールインワンのローカル ダウンロード MP4、MP3
  7. // @name:kr Youtube 도구 올인원 로컬 다운로드 외부 서비스 없이 MP4, MP3
  8. // @name:ar Youtube Tools All in one local download mp3 mp4 HIGT QUALITY return dislikes and more
  9. // @name:bg Youtube-Tools Alles in einem lokalen Download von MP4, MP3.
  10. // @name:cs Nástroje YouTube Vše v jednom místní Stahujte MP4, MP3
  11. // @name:da Youtube-værktøjer Alt i én lokal Download MP4, MP3
  12. // @name:de Youtube-Tools Alles in einem lokalen Download von MP4, MP3
  13. // @name:tel Youtube టూల్స్ అన్నీ ఒకే లోకల్ డౌన్‌లోడ్ MP4, Mp3
  14. // @name:es Youtube Custom Todo en uno Descarga local MP4, MP3.
  15. // @name:en Youtube Tools All in one local download mp3 mp4.
  16. // @name:fr Outils Youtube Tout-en-un local Téléchargez MP4, MP3.
  17. // @name:fr-CA Outils Youtube Tout-en-un local Téléchargez MP4, MP3.
  18. // @name:he כלים של YouTube הכל במקום אחד מקומי הורדה MP4, MP3 באיכות גבוהה ללא שירות חיצוני ועוד.
  19. // @name:hu Youtube Eszközök Minden egy helyen Letöltés MP4, MP3.
  20. // @name:id Alat Youtube Semua dalam satu lokal Unduh MP4, MP3.
  21. // @name:it Strumenti Youtube Tutto in uno Scarica locale MP4, MP3.
  22. // @name:ko Youtube 도구 올인원 로컬 외부 서비스 없이 MP4, MP3
  23. // @name:nb Youtube-verktøy Alt i ett lokalt Last ned MP4, MP3
  24. // @name:nl Youtube Tools Alles in één lokaal Download MP4, MP3
  25. // @name:pl Narzędzia YouTube Wszystko w jednym lokalnym. Pobierz MP4, MP3
  26. // @name:pt-BR Ferramentas do Youtube Tudo em um local Baixe MP4, MP3 DE ALTA QUALIDAD.
  27. // @name:ro YInstrumente Youtube Toate într-un singur local Descărcați MP4, MP3.
  28. // @name:ru Инструменты Youtube Все в одном локальном формате. Загрузите MP4, MP3.
  29. // @name:sk Nástroje YouTube Všetko v jednom miestne Stiahnite si MP4, MP3
  30. // @name:sr Иоутубе алати Све у једном локалном Преузми МП4, МП3
  31. // @name:sv Youtube-verktyg Allt i ett lokalt Ladda ner MP4, MP3
  32. // @name:th เครื่องมือ Youtube ทั้งหมดในที่เดียว ดาวน์โหลด MP4, MP3
  33. // @name:tr Youtube Araçları Hepsi bir arada yerel Harici hizmet olmadan MP4, MP3
  34. // @name:uk Інструменти Youtube Все в одному локальному завантаженні MP4, MP3
  35. // @name:ug Youtube قوراللىرى ھەممىسى بىر يەرلىك چۈشۈرۈش MP4,mp3
  36. // @name:vi Công cụ Youtube Tất cả trong một cục bộ Tải xuống MP4, MP3
  37. // @description:zh-TW Youtube 工具 多合一本地下載 mp4、MP3
  38. // @description:zh-HK Youtube 工具 多合一本地下載 mp4、MP3
  39. // @description:zh-CN Youtube 工具 多合一本地下載 mp4、MP3
  40. // @description:ja Youtube ツール オールインワン ローカル ダウンロード mp4、MP3 、
  41. // @description:kr Youtube 도구 올인원 로컬 다운로드 mp4, MP3
  42. // @description:ar Herramientas de YouTube Todo en uno Descarga local mp4, MP3
  43. // @description:bg Инструменти за Youtube Всичко в едно локално изтегляне mp4,
  44. // @description:cs Nástroje YouTube Vše v jednom místní Stahování mp4, MP3
  45. // @description:da Youtube-værktøjer Alt i ét lokalt Download mp4, MP3
  46. // @description:de YouTube-Tools Alles in einem lokalen Laden Sie MP4, MP3
  47. // @description:tel Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY,
  48. // @description:es Youtube tools todo en uno personlizada youtube a tu estilo y descarga MP4 y MP3
  49. // @description:fr Outils Youtube Tout-en-un local Téléchargez des mp4, des MP3
  50. // @description:fr-CA Outils Youtube Tout-en-un local Téléchargez des mp4, des MP3
  51. // @description:he כלים של YouTube הכל במקום אחד מקומי הורד mp4, MP3
  52. // @description:hu Youtube Eszközök Minden egyben helyi Letöltés mp4, MP3
  53. // @description:id Alat Youtube Semua dalam satu lokal Unduh mp4, MP3
  54. // @description:it Strumenti Youtube Tutto in uno locale Scarica mp4, MP3
  55. // @description:ko Youtube 도구 올인원 로컬 다운로드 mp4, MP3
  56. // @description:nb YoYoutube-verktøy Alt i ett lokalt Last ned mp4, MP3
  57. // @description:nl YouTube-tools Alles in één lokaal Download mp4, MP3
  58. // @description:pl Narzędzia Youtube Wszystko w jednym miejscu Pobierz mp4, MP3
  59. // @description:pt-BR Ferramentas do YouTube Tudo em um só local Baixe mp4, MP3
  60. // @description:ro Instrumente Youtube Toate într-un singur local Descărcați mp4, MP3
  61. // @description:ru Инструменты Youtube Все в одном, локально. Загрузите mp4, MP3
  62. // @description:sk Nástroje YouTube Všetko v jednom miestnom Sťahujte mp4, MP3
  63. // @description:sr Иоутубе алати Све у једном локалном Преузми мп4, МП3
  64. // @description:sv Youtube-verktyg Allt i ett lokalt Ladda ner mp4, MP3
  65. // @description:th เครื่องมือ Youtube ทั้งหมดในที่เดียว ดาวน์โหลด mp4, MP3
  66. // @description:tr Youtube Araçları Hepsi bir arada yerel Harici hizmet olmadan mp4, MP3
  67. // @description:uk Інструменти Youtube Все в одному локальному завантаженні mp4, MP3
  68. // @description:ug Youtube قورالىنىڭ ھەممىسى بىر يەرلىك چۈشۈرۈشتە mp4, MP3 HIGH QUAقنى قا
  69. // @description:vi Công cụ Youtube Tất cả trong một cục bộ Tải xuống mp4, MP3
  70. // @description:en Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY
  71. // @description Youtube Tools All in one local Download mp4, MP3 HIGT QUALITY
  72. // @homepage https://github.com/DeveloperMDCM/
  73. // @version 2.3.4.3
  74. // @author DeveloperMDCM
  75. // @match *://www.youtube.com/*
  76. // @exclude *://music.youtube.com/*
  77. // @exclude *://*.music.youtube.com/*
  78. // @icon https://www.google.com/s2/favicons?sz=64&domain=youtube.com
  79. // @grant GM_info
  80. // @grant GM_addStyle
  81. // @grant GM_setValue
  82. // @grant GM_getValue
  83. // @grant unsafeWindow
  84. // @run-at document-end
  85. // @require https://cdn.jsdelivr.net/npm/izitoast@1.4.0/dist/js/iziToast.min.js
  86. // @compatible chrome
  87. // @compatible firefox
  88. // @compatible opera
  89. // @compatible safari
  90. // @compatible edge
  91. // @license MIT
  92. // @namespace https://github.com/DeveloperMDCM/
  93. // ==/UserScript==
  94.  
  95. (function () {
  96. 'use strict';
  97. let validoUrl = document.location.href;
  98. const $e = (el) => document.querySelector(el); // any element
  99. const $id = (el) => document.getElementById(el); // element by id
  100. const $m = (el) => document.querySelectorAll(el); // multiple all elements
  101. const $cl = (el) => document.createElement(el); // create element
  102. const $sp = (el, pty) => document.documentElement.style.setProperty(el, pty); // set property variable css
  103. const $ap = (el) => document.body.appendChild(el); // append element
  104. const apiDislikes = "https://returnyoutubedislikeapi.com/Votes?videoId="; // Api dislikes
  105. const apiGoogleTranslate = "https://translate.googleapis.com/translate_a/t"; // Api google translate
  106. let selectedBgColor = "#252525"; // Background color menu default
  107. let selectedTextColor = "#ffffff"; // Text color menu default
  108. let selectedBgAccentColor = "#ff0000"; // Accent color menu default
  109. const urlSharedCode = "https://greatest.deepsurf.us/es/scripts/460680-youtube-tools-all-in-one-local-download-mp3-mp4-higt-quality-return-dislikes-and-more";
  110.  
  111. function isFullscreen() {
  112. return document.fullscreenElement !== null;
  113. }
  114. // for translate comments video
  115. const languagesTranslate = {
  116. "af": "Afrikaans",
  117. "sq": "Albanian",
  118. "am": "Amharic",
  119. "ar": "Arabic",
  120. "hy": "Armenian",
  121. "az": "Azerbaijani",
  122. "eu": "Basque",
  123. "be": "Belarusian",
  124. "bn": "Bengali",
  125. "bs": "Bosnian",
  126. "bg": "Bulgarian",
  127. "ca": "Catalan",
  128. "ceb": "Cebuano",
  129. "zh-CN": "Chinese (Simplified)",
  130. "zh-TW": "Chinese (Traditional)",
  131. "co": "Corsican",
  132. "hr": "Croatian",
  133. "cs": "Czech",
  134. "da": "Danish",
  135. "nl": "Dutch",
  136. "en": "English",
  137. "eo": "Esperanto",
  138. "et": "Estonian",
  139. "fi": "Finnish",
  140. "fr": "French",
  141. "fy": "Frisian",
  142. "gl": "Galician",
  143. "ka": "Georgian",
  144. "de": "German",
  145. "el": "Greek",
  146. "gu": "Gujarati",
  147. "ht": "Haitian Creole",
  148. "ha": "Hausa",
  149. "haw": "Hawaiian",
  150. "iw": "Hebrew",
  151. "hi": "Hindi",
  152. "hmn": "Hmong",
  153. "hu": "Hungarian",
  154. "is": "Icelandic",
  155. "ig": "Igbo",
  156. "id": "Indonesian",
  157. "ga": "Irish",
  158. "it": "Italian",
  159. "ja": "Japanese",
  160. "jw": "Javanese",
  161. "kn": "Kannada",
  162. "kk": "Kazakh",
  163. "km": "Khmer",
  164. "ko": "Korean",
  165. "ku": "Kurdish",
  166. "ky": "Kyrgyz",
  167. "lo": "Lao",
  168. "la": "Latin",
  169. "lv": "Latvian",
  170. "lt": "Lithuanian",
  171. "lb": "Luxembourgish",
  172. "mk": "Macedonian",
  173. "mg": "Malagasy",
  174. "ms": "Malay",
  175. "ml": "Malayalam",
  176. "mt": "Maltese",
  177. "mi": "Maori",
  178. "mr": "Marathi",
  179. "mn": "Mongolian",
  180. "my": "Myanmar (Burmese)",
  181. "ne": "Nepali",
  182. "no": "Norwegian",
  183. "ny": "Nyanja (Chichewa)",
  184. "ps": "Pashto",
  185. "fa": "Persian",
  186. "pl": "Polish",
  187. "pt": "Portuguese",
  188. "pa": "Punjabi",
  189. "ro": "Romanian",
  190. "ru": "Russian",
  191. "sm": "Samoan",
  192. "gd": "Scots Gaelic",
  193. "sr": "Serbian",
  194. "st": "Sesotho",
  195. "sn": "Shona",
  196. "sd": "Sindhi",
  197. "si": "Sinhala",
  198. "sk": "Slovak",
  199. "sl": "Slovenian",
  200. "so": "Somali",
  201. "es": "Spanish",
  202. "su": "Sundanese",
  203. "sw": "Swahili",
  204. "sv": "Swedish",
  205. "tl": "Tagalog (Filipino)",
  206. "tg": "Tajik",
  207. "ta": "Tamil",
  208. "te": "Telugu",
  209. "th": "Thai",
  210. "tr": "Turkish",
  211. "uk": "Ukrainian",
  212. "ur": "Urdu",
  213. "uz": "Uzbek",
  214. "vi": "Vietnamese",
  215. "cy": "Welsh",
  216. "xh": "Xhosa",
  217. "yi": "Yiddish",
  218. "yo": "Yoruba",
  219. "zu": "Zulu"
  220. }
  221. function hideCanvas() {
  222. const canvas = $id('wave-visualizer-canvas');
  223. if (canvas) {
  224. canvas.style.opacity = '0';
  225. if (controlPanel) {
  226. controlPanel.style.opacity = '0';
  227. }
  228. }
  229. }
  230.  
  231.  
  232.  
  233. function Notify(type = 'info', message = '', title = '') {
  234. const defaultTitles = {
  235. success: 'Success',
  236. error: 'Error',
  237. info: 'Information',
  238. warning: 'Warning',
  239. };
  240. iziToast[type]({
  241. title: title || defaultTitles[type] || 'Notification',
  242. message: message,
  243. position: 'bottomLeft',
  244. });
  245. }
  246.  
  247.  
  248. const UPDATE_INTERVAL = 1000;
  249. const STORAGE = {
  250. USAGE: 'YT_TOTAL_USAGE',
  251. VIDEO: 'YT_VIDEO_TIME',
  252. SHORTS: 'YT_SHORTS_TIME'
  253. };
  254.  
  255. let usageTime = GM_getValue(STORAGE.USAGE, 0);
  256. let videoTime = GM_getValue(STORAGE.VIDEO, 0);
  257. let shortsTime = GM_getValue(STORAGE.SHORTS, 0);
  258. let lastUpdate = Date.now();
  259. let activeVideo = null;
  260. let activeType = null;
  261.  
  262. // Inicializar almacenamiento
  263. GM_setValue(STORAGE.USAGE, usageTime);
  264. GM_setValue(STORAGE.VIDEO, videoTime);
  265. GM_setValue(STORAGE.SHORTS, shortsTime);
  266.  
  267. function FormatterNumber(num, digits) {
  268. const lookup = [
  269. {
  270. value: 1,
  271. symbol: '',
  272. },
  273. {
  274. value: 1e3,
  275. symbol: ' K',
  276. },
  277. {
  278. value: 1e6,
  279. symbol: ' M',
  280. },
  281. ];
  282. const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  283. const item = lookup
  284. .slice()
  285. .reverse()
  286. .find((item) => {
  287. return num >= item.value;
  288. });
  289. return item
  290. ? (num / item.value).toFixed(digits).replace(rx, '$1') + item.symbol
  291. : '0';
  292. }
  293.  
  294. function paramsVideoURL() {
  295. const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
  296. return parametrosURL.get('v');
  297. }
  298.  
  299. // Dislikes video
  300. async function videoDislike() {
  301.  
  302. validoUrl = document.location.href;
  303.  
  304. const validoVentana = $e('#below > ytd-watch-metadata > div');
  305. if (validoVentana != undefined && document.location.href.split('?v=')[0].includes('youtube.com/watch')) {
  306. validoUrl = paramsVideoURL();
  307. const urlShorts = `${apiDislikes}${validoUrl}`;
  308. try {
  309. const respuesta = await fetch(urlShorts);
  310. const datosShort = await respuesta.json();
  311. const { dislikes } = datosShort;
  312. const dislikes_content = $e('#top-level-buttons-computed > segmented-like-dislike-button-view-model > yt-smartimation > div > div > dislike-button-view-model > toggle-button-view-model > button-view-model > button');
  313. if (dislikes_content !== undefined) {
  314. dislikes_content.style = 'width: 90px';
  315. dislikes_content.innerHTML = `
  316. <svg class="svg-dislike-icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="1" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 13v-8a1 1 0 0 0 -1 -1h-2a1 1 0 0 0 -1 1v7a1 1 0 0 0 1 1h3a4 4 0 0 1 4 4v1a2 2 0 0 0 4 0v-5h3a2 2 0 0 0 2 -2l-1 -5a2 3 0 0 0 -2 -2h-7a3 3 0 0 0 -3 3" /></svg>
  317. ${FormatterNumber(dislikes, 0)}`;
  318. }
  319.  
  320. } catch (error) {
  321. console.log(error);
  322. }
  323. }
  324. }
  325.  
  326. // dislikes shorts
  327. async function shortDislike() {
  328. validoUrl = document.location.href;
  329. const validoVentanaShort = $m(
  330. '#dislike-button > yt-button-shape > label > div > span'
  331. );
  332. if (validoVentanaShort != undefined && document.location.href.split('/')[3] === 'shorts') {
  333. validoUrl = document.location.href.split('/')[4];
  334. const urlShorts = `${apiDislikes}${validoUrl}`;
  335. try {
  336. const respuesta = await fetch(urlShorts);
  337. const datosShort = await respuesta.json();
  338. const { dislikes } = datosShort;
  339. for (let i = 0; i < validoVentanaShort.length; i++) {
  340. validoVentanaShort[i].textContent = `${FormatterNumber(
  341. dislikes,
  342. 0
  343. )}`;
  344. }
  345. } catch (error) {
  346. console.log(error);
  347. }
  348. }
  349. }
  350.  
  351. // Url change in second load
  352. let prevUrl;
  353. let showDislikes = false;
  354.  
  355. setInterval(() => {
  356. const svgDislike = $e('.svg-dislike-ico'); // Check svg in dom
  357. const currUrl = window.location.href;
  358. if (prevUrl !== undefined && currUrl !== prevUrl && !svgDislike && showDislikes) {
  359. setTimeout(async() => {
  360. await videoDislike();
  361. await shortDislike();
  362. },2000)
  363. }
  364. prevUrl = currUrl;
  365. }, 1000);
  366.  
  367.  
  368.  
  369. // Create a Trusted Types policy
  370. const policy = window.trustedTypes?.createPolicy('default', {
  371. createHTML: (input) => input,
  372. });
  373.  
  374.  
  375. // Styles for our enhancement panel
  376. GM_addStyle(`
  377. @import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");
  378. @import url("https://cdn.jsdelivr.net/npm/izitoast@1.4.0/dist/css/iziToast.min.css");
  379. :root {
  380. --primary-custom: #ff0000 !important;
  381. --bg-dark-custom: #1a1a1a !important;
  382. --bg-card-custom: #252525 !important;
  383. --text-custom: #ffffff !important;
  384. --text-custom-secondary: #9e9e9e !important;
  385. --accent-custom: #ff4444 !important;
  386. }
  387. body .container-mdcm {
  388. font-family: "Inter", -apple-system, sans-serif;
  389. color: var(--yt-enhance-menu-text, --text-custom);
  390. }
  391. #toggle-button:hover {
  392. background-color: rgba(255,255,255,0.1);
  393. border-radius: 50%;
  394. opacity: 1 !important;
  395. }
  396. .container-mdcm {
  397. width: 420px;
  398. max-width: 420px;
  399. background-color: var(--yt-enhance-menu-bg, #252525);
  400. border-radius: 16px 16px 0 0;
  401. box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  402. backdrop-filter: blur(15px);
  403. border: 1px solid rgba(255, 255, 255, 0.1);
  404. display: flex;
  405. flex-direction: column;
  406. max-height: 80vh;
  407. overflow-y: auto;
  408. overflow-x: hidden;
  409. height: auto;
  410. }
  411.  
  412. #shareDropdown {
  413. display: none;
  414. position: absolute;
  415. top: 50px;
  416. right: 100px;
  417. background-color: var(--yt-enhance-menu-bg, #252525);
  418. border-radius: 6px;
  419. padding: 10px;
  420. box-shadow: rgba(0, 0, 0, 0.2) 0px 4px 12px;
  421. z-index: 11;
  422. }
  423. #shareDropdown a {
  424. color: var(--text-custom);
  425. text-decoration: none;
  426. line-height: 2;
  427. font-size: 14px;
  428. }
  429. #shareDropdown a:hover {
  430. color: var(--primary-custom);
  431. }
  432. .header-mdcm {
  433. padding: 12px 16px;
  434. border-bottom: 1px solid rgba(255,255,255,0.1);
  435. position: sticky;
  436. top: 0;
  437. background-color: var(--yt-enhance-menu-bg, #252525);
  438. border-radius: 16px 16px 0 0;
  439. z-index: 10;
  440. display: flex;
  441. justify-content: space-between;
  442. align-items: center;
  443. }
  444.  
  445. .header-mdcm h1 {
  446. font-size: 16px;
  447. margin: 0;
  448. font-weight: 600;
  449. display: flex;
  450. align-items: center;
  451. gap: 8px;
  452. }
  453.  
  454.  
  455. .header-mdcm i {
  456. color: var(--primary-custom)
  457. }
  458.  
  459. .icons-mdcm {
  460. display: flex;
  461. gap: 4px;
  462. }
  463. .icons-mdcm i {
  464. color: var(--yh-enhance-menu-accent, var(--text-custom));
  465. }
  466.  
  467. .icon-btn-mdcm {
  468. background: rgba(255,255,255,0.1);
  469. border: none;
  470. color: var(--text-custom);
  471. width: 28px;
  472. height: 28px;
  473. border-radius: 6px;
  474. cursor: pointer;
  475. transition: all 0.3s;
  476. }
  477.  
  478. .icon-btn-mdcm:hover {
  479. background: rgba(255,255,255,0.2);
  480. transform: translateY(-2px);
  481. }
  482.  
  483. .icon-btn-mdcm i {
  484. color: var(--text-custom);
  485. outline: none;
  486. text-decoration: none;
  487. }
  488.  
  489. .tabs-mdcm {
  490. padding: 10px 12px;
  491. margin: 10px 0;
  492. position: sticky;
  493. top: 50px;
  494. background-color: var(--yt-enhance-menu-bg, #252525);
  495. z-index: 10;
  496. display: flex;
  497. gap: 8px;
  498. -ms-overflow-style: none;
  499. padding-bottom: 8px;
  500. }
  501.  
  502.  
  503. .tabs-mdcm::-webkit-scrollbar {
  504. height: 0px;
  505. background-color: transparent;
  506. }
  507.  
  508. .tabs-mdcm:hover::-webkit-scrollbar {
  509. height: 6px;
  510. }
  511.  
  512. .tabs-mdcm::-webkit-scrollbar-thumb {
  513. background-color: rgba(255, 0, 0, 0.5);
  514. border-radius: 3px;
  515. }
  516.  
  517. .tabs-mdcm::-webkit-scrollbar-track {
  518. background-color: transparent;
  519. }
  520.  
  521. .tab-mdcm {
  522. padding: 6px 10px;
  523. border: none;
  524. background: rgba(255,255,255,0.05);
  525. cursor: pointer;
  526. font-size: 12px;
  527. color: var(--text-custom-secondary);
  528. border-radius: 6px;
  529. transition: all 0.3s;
  530. flex: 1;
  531. display: flex;
  532. align-items: center;
  533. gap: 6px;
  534. flex-shrink: 0;
  535. justify-content: center;
  536. white-space: nowrap;
  537. }
  538.  
  539. .tab-mdcm svg {
  540. width: 14px;
  541. height: 14px;
  542. fill: currentColor;
  543. }
  544.  
  545. .tab-mdcm.active {
  546. background: var(--yt-enhance-menu-accent, --primary-custom) !important;
  547. color: var(--text-custom);
  548. font-weight: 500;
  549. box-shadow: 0 4px 12px rgba(255,0,0,0.2);
  550. }
  551.  
  552. .tab-mdcm:hover:not(.active) {
  553. background: rgba(255,255,255,0.1);
  554. transform: translateY(-1px);
  555. }
  556.  
  557. .options-mdcm {
  558. flex: 1;
  559. overflow-y: auto;
  560. padding: 0 16px 0;
  561. scrollbar-width: thin;
  562. scrollbar-color: var(--primary-custom) var(--bg-dark-custom);
  563. max-height: 300px;
  564. display: grid;
  565. grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  566. gap: 8px;
  567. }
  568.  
  569. .options-settings-mdcm {
  570. flex: 1;
  571. overflow-y: auto;
  572. padding: 0 16px 0;
  573. scrollbar-width: thin;
  574. scrollbar-color: var(--primary-custom) var(--bg-dark-custom);
  575. max-height: 300px;
  576. display: grid;
  577. gap: 8px;
  578. }
  579.  
  580. .card-items-end {
  581. display: flex;
  582. justify-content: space-between;
  583. align-items: center;
  584. width: 175px;
  585. }
  586.  
  587. .radio-mdcm {
  588. width: 14px;
  589. height: 14px;
  590. accent-color: var(--primary-custom);
  591. }
  592. .color-picker-mdcm {
  593. width: 50px;
  594. height: 24px;
  595. border: 1px solid rgba(255, 255, 255, 0.2);
  596. background: rgba(255, 255, 255, 0.1);
  597. border-radius: 4px;
  598. cursor: pointer;
  599. transition: all 0.3s;
  600. }
  601.  
  602. .color-picker-mdcm:hover {
  603. background: rgba(255, 255, 255, 0.2);
  604. }
  605.  
  606. .options-mdcm::-webkit-scrollbar, .options-settings-mdcm::-webkit-scrollbar {
  607. width: 6px;
  608. }
  609.  
  610. .options-mdcm::-webkit-scrollbar-track, .options-settings-mdcm::-webkit-scrollbar-track {
  611. background: var(--bg-dark-custom);
  612. border-radius: 3px;
  613. }
  614.  
  615. .options-mdcm::-webkit-scrollbar-thumb, .options-settings-mdcm::-webkit-scrollbar-thumb {
  616. background: var(--primary-custom);
  617. border-radius: 3px;
  618. }
  619.  
  620. .options-mdcm::-webkit-scrollbar-thumb:hover, .options-settings-mdcm::-webkit-scrollbar-thumb:hover {
  621. background: var(--accent-custom);
  622. }
  623.  
  624. .options-mdcm::after, .options-settings-mdcm::after {
  625. content: '';
  626. display: block;
  627. }
  628.  
  629. .option-mdcm {
  630. display: grid;
  631. grid-template-columns: auto 1fr;
  632. align-items: center;
  633. margin-bottom: 0;
  634. padding: 5px;
  635. background: rgba(255,255,255,0.05);
  636. border-radius: 6px;
  637. transition: all 0.3s;
  638. border: 1px solid rgba(255,255,255,0.05);
  639. color: var(--yt-)
  640. gap: 6px;
  641. }
  642.  
  643. .option-mdcm:hover {
  644. background: rgba(255,255,255,0.08);
  645. border-color: rgba(255,255,255,0.1);
  646. }
  647. .option-settings-mdcm {
  648. display: flex;
  649. justify-content: space-between;
  650. align-items: center;
  651. margin-bottom: 0;
  652. padding: 6px;
  653. background: rgba(255, 255, 255, 0.05);
  654. border-radius: 6px;
  655. transition: all 0.3s;
  656. border: 1px solid rgba(255, 255, 255, 0.05);
  657. gap: 6px;
  658. }
  659.  
  660. .option-settings-mdcm:hover {
  661. background: rgba(255,255,255,0.08);
  662. border-color: rgba(255,255,255,0.1);
  663. }
  664. .tab-content {
  665. display: none;
  666. }
  667. .tab-content.active {
  668. display: block;
  669. margin-bottom: 10px;
  670. }
  671.  
  672. .checkbox-mdcm {
  673. width: 14px;
  674. height: 14px;
  675. accent-color: var(--yt-enhance-menu-accent, --primary-custom) !important;
  676. }
  677.  
  678. label {
  679. font-size: 12px;
  680. color: var(--text-custom);
  681. }
  682.  
  683. .slider-container-mdcm {
  684. background: rgba(255,255,255,0.05);
  685. padding: 10px;
  686. border-radius: 6px;
  687. }
  688.  
  689. .slider-mdcm {
  690. width: 100%;
  691. height: 3px;
  692. accent-color: var(--yt-enhance-menu-accent, --primary-custom) !important;
  693. margin: 10px 0;
  694. }
  695.  
  696. .reset-btn-mdcm {
  697. padding: 5px 10px;
  698. border: 1px solid rgba(255,255,255,0.2);
  699. background: rgba(255,255,255,0.1);
  700. color: var(--text-custom);
  701. border-radius: 4px;
  702. cursor: pointer;
  703. font-size: 11px;
  704. transition: all 0.3s;
  705. }
  706.  
  707. .reset-btn-mdcm:hover {
  708. background: rgba(255,255,255,0.2);
  709. }
  710.  
  711. .quality-selector-mdcm select {
  712. position: relative;
  713. padding: 3px;
  714. outline: none;
  715. border-radius: 4px;
  716. border: 1px solid rgba(255,255,255,0.2);
  717. background: var(--yt-enhance-menu-accent, --primary-custom) !important;
  718. color: var(--text-custom);
  719. width: fit-content;
  720. appearance: none;
  721. cursor: pointer;
  722. font-size: 11px;
  723. }
  724.  
  725. .quality-selector-mdcm {
  726. background: rgba(255,255,255,0.05);
  727. padding: 10px;
  728. border-radius: 6px;
  729. }
  730.  
  731. .select-wrapper-mdcm {
  732. position: relative;
  733. display: inline-block;
  734. }
  735.  
  736. .select-wrapper-mdcm select {
  737. -webkit-appearance: auto;
  738. -moz-appearance: auto;
  739. }
  740. .actions-mdcm {
  741. position: sticky;
  742. top: 0;
  743. padding: 12px 16px;
  744. backdrop-filter: blur(15px);
  745. background-color: var(--yt-enhance-menu-bg, #252525);
  746. display: flex;
  747. gap: 6px;
  748. width: 390px;
  749. border-radius: 0 0 16px 16px;
  750. justify-content: space-between;
  751. align-items: center;
  752. }
  753.  
  754. .action-buttons-mdcm {
  755. display: flex;
  756. gap: 6px;
  757. }
  758.  
  759. .action-btn-mdcm {
  760. flex: 1;
  761. padding: 8px;
  762. border: none;
  763. border-radius: 6px;
  764. background: var(--primary-custom);
  765. color: var(--text-custom);
  766. cursor: pointer;
  767. font-size: 12px;
  768. font-weight: 500;
  769. transition: all 0.3s;
  770. display: flex;
  771. align-items: center;
  772. justify-content: center;
  773. gap: 4px;
  774. box-shadow: 0 4px 12px rgba(255,0,0,0.2);
  775. }
  776.  
  777. .action-btn:hover {
  778. transform: translateY(-2px);
  779. box-shadow: 0 6px 16px rgba(255,0,0,0.3);
  780. }
  781.  
  782. textarea.textarea-mdcm {
  783. width: 100%;
  784. height: 50px;
  785. margin-top: 10px;
  786. margin-bottom: 12px;
  787. padding: 8px;
  788. background: rgba(255,255,255,0.05);
  789. border: 1px solid rgba(255,255,255,0.1);
  790. border-radius: 6px;
  791. color: var(--text-custom);
  792. font-size: 11px;
  793. resize: none;
  794. transition: all 0.3s;
  795. }
  796.  
  797. textarea.textarea-mdcm:focus {
  798. outline: none;
  799. border-color: var(--primary-custom);
  800. background: rgba(255,255,255,0.08);
  801. }
  802.  
  803. @keyframes fadeIn {
  804. from { opacity: 0; transform: translateY(10px); }
  805. to { opacity: 1; transform: translateY(0); }
  806. }
  807.  
  808. .container-mdcm {
  809. animation: fadeIn 0.3s ease-out;
  810. }
  811.  
  812. .developer-mdcm {
  813. font-size: 10px;
  814. color: var(--text-custom-secondary);
  815. }
  816.  
  817. .developer-mdcm a {
  818. color: var(--primary-custom);
  819. text-decoration: none;
  820. }
  821.  
  822. /* Styles for the import/export area */
  823. #importExportArea {
  824. display: none;
  825. padding: 16px;
  826. margin: 0px;
  827. background-color: var(--yt-enhance-menu-bg, #252525);
  828. border-radius: 16px;
  829. box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
  830. }
  831.  
  832. #importExportArea.active {
  833. display: block;
  834. margin-top: 10px;
  835. }
  836.  
  837. /* Style the textarea */
  838. #importExportArea textarea {
  839. width: 370px;
  840. height: 20px;
  841. margin-bottom: 10px;
  842. padding: 8px;
  843. border: 1px solid rgba(255, 255, 255, 0.2);
  844. border-radius: 6px;
  845. background-color: rgba(255, 255, 255, 0.05);
  846. color: var(--text-custom);
  847. font-size: 12px;
  848. resize: vertical;
  849. }
  850.  
  851. /* Style the buttons */
  852. #importExportArea .action-buttons-mdcm {
  853. display: flex;
  854. justify-content: space-between;
  855. gap: 10px;
  856. }
  857.  
  858. #importExportArea .action-btn-mdcm {
  859. flex: 1;
  860. padding: 10px 16px;
  861. border: none;
  862. border-radius: 6px;
  863. background-color: var(--primary-custom);
  864. color: var(--text-custom);
  865. font-size: 14px;
  866. font-weight: 500;
  867. cursor: pointer;
  868. transition: background-color 0.3s ease;
  869. }
  870.  
  871. #importExportArea .action-btn-mdcm:hover {
  872. background-color: var(--accent-custom);
  873. }
  874. #yt-stats {
  875. position: fixed;
  876. top: 60px;
  877. right: 20px;
  878. background: #1a1a1a;
  879. color: white;
  880. padding: 15px;
  881. border-radius: 10px;
  882. width: 320px;
  883. box-shadow: 0 4px 12px rgba(0,0,0,0.4);
  884. font-family: Arial, sans-serif;
  885. display: none;
  886. }
  887. #yt-stats-toggle {
  888. font-size: 12px;
  889. color: #fff;
  890. padding: 12px 20px;
  891. border-radius: 5px;
  892. cursor: pointer;
  893. }
  894. .stat-row {
  895. margin: 15px 0;
  896. }
  897. .progress {
  898. height: 6px;
  899. background: #333;
  900. border-radius: 3px;
  901. margin: 8px 0;
  902. }
  903. .progress-bar {
  904. height: 100%;
  905. transition: width 0.3s;
  906. }
  907. .total-bar { background: #44aaff; }
  908. .video-bar { background: #00ff88; }
  909. .shorts-bar { background: #ff4444; }
  910. #cinematics {
  911. position: absolute !important;
  912. width: 90vw !important;
  913. height: 100vh ;
  914. }
  915. #cinematics div {
  916. position: fixed;
  917. inset: 0px;
  918. pointer-events: none;
  919. transform: scale(1.5, 2);
  920. }
  921. #cinematics > div > div > canvas:nth-child(1), #cinematics > div > div > canvas:nth-child(2) {
  922. position: absolute !important;
  923. width: 90vw !important;
  924. height: 100vh ;
  925. }
  926.  
  927. // .html5-video-player.unstarted-mode {
  928. // background-image: url('https://avatars.githubusercontent.com/u/54366580?v=4');
  929. // background-repeat: no-repeat;
  930. // background-position: 50% 50%;
  931. // display: flex;
  932. // justify-content: center;
  933. // align-items: center;
  934. // }
  935. #yt-enhancement-panel {
  936. position: fixed;
  937. top: 60px;
  938. right: 20px;
  939. z-index: 9999;
  940. }
  941. .color-picker {
  942. width: 100%;
  943. margin: 0;
  944. padding: 0;
  945. border: none;
  946. background: none;
  947. }
  948. .slider {
  949. width: 100%;
  950. }
  951. #toggle-panel {
  952. z-index: 10000;
  953. color: white;
  954. padding: 5px;
  955. border: none;
  956. cursor: pointer;
  957. display: flex;
  958. justify-content: center;
  959. transition: all 0.5s ease;
  960. width: 43px;
  961. border-radius: 100px;
  962. }
  963. #icon-menu-settings {
  964. display: flex;
  965. align-items: center;
  966. justify-content: center;
  967. width: 24px;
  968. height: 24px;
  969. padding: 7px;
  970. font-size: 20px;
  971. color: var(--yt-spec-icon-inactive);
  972. cursor: pointer;
  973. user-select: none;
  974. filter: drop-shadow(2px 4px 6px black);
  975. }
  976. .theme-option {
  977. margin-bottom: 15px;
  978. }
  979. .theme-option label {
  980. display: flex;
  981. align-items: center;
  982. }
  983. .theme-option {
  984. position: relative;
  985. width: auto;
  986. margin-bottom: 10px;
  987. padding: 10px;
  988. border-radius: 4px;
  989. cursor: pointer;
  990. }
  991.  
  992. .theme-preview {
  993. position: absolute;
  994. top: 0;
  995. left: 0;
  996. right: 0;
  997. bottom: 0;
  998. border-radius: 10px;
  999. border: 1px solid #000;
  1000. z-index: 1;
  1001. }
  1002.  
  1003. .theme-option input[type="radio"] {
  1004. position: relative;
  1005. z-index: 2;
  1006. margin-right: 10px;
  1007. cursor: pointer;
  1008. }
  1009.  
  1010. .theme-name {
  1011. position: relative;
  1012. z-index: 2;
  1013. font-size: 15px;
  1014. color: #fff;
  1015. }
  1016.  
  1017. .theme-option label {
  1018. display: flex;
  1019. align-items: center;
  1020. width: 100%;
  1021. position: relative;
  1022. z-index: 2;
  1023. }
  1024.  
  1025. .buttons-tranlate, .select-traductor {
  1026. background: #000;
  1027. font-size: 10px;
  1028. border: none;
  1029. color: #fbf4f4 !important;
  1030. padding: 3px 0;
  1031. margin-left: 10px;
  1032. width: 70px;
  1033. border-radius: 10px;
  1034. }
  1035. .buttons-tranlate:hover {
  1036. cursor: pointer;
  1037. background-color: #6b6b6b;
  1038. }
  1039. button.botones_div {
  1040. margin: 0;
  1041. padding: 0;
  1042. }
  1043.  
  1044. .tab-button:hover {
  1045. background-color: #ec3203 !important;
  1046. color: #ffffff !important;
  1047. cursor: pointer;
  1048. }
  1049.  
  1050. .traductor-container {
  1051. display: inline-block;
  1052. align-items: center;
  1053. gap: 8px;
  1054. margin-top: 4px;
  1055. }
  1056. #eyes {
  1057. opacity: 0;
  1058. position: absolute;
  1059. height: 24px;
  1060. left: 0;
  1061. width: 24px;
  1062. }
  1063.  
  1064. /* width */
  1065. ::-webkit-scrollbar {
  1066. width: 4px;
  1067. height: 10px;
  1068. }
  1069.  
  1070. /* Track */
  1071. ::-webkit-scrollbar-track {
  1072. background: ##d5d5d5;
  1073.  
  1074. }
  1075.  
  1076. /* Handle */
  1077. ::-webkit-scrollbar-thumb {
  1078. background: #000;
  1079.  
  1080. }
  1081.  
  1082. .color-boxes {
  1083. display: flex;
  1084. gap: 8px;
  1085. }
  1086. .color-box {
  1087. width: 20px;
  1088. height: 20px;
  1089. border: 1px solid rgb(221 221 221 / 60%);
  1090. border-radius: 4px;
  1091. cursor: pointer;
  1092. }
  1093. .color-box.selected {
  1094. border: 2px solid var(--primary-custom);
  1095. filter: drop-shadow(0px 1px 6px red);
  1096. }
  1097.  
  1098. .containerButtons {
  1099. display: flex;
  1100. justify-content: center;
  1101. align-items: center;
  1102. flex-wrap: wrap;
  1103. gap: 10px;
  1104. }
  1105. .containerButtons > button:hover {
  1106. cursor: pointer;
  1107. }
  1108. body {
  1109. padding: 0;
  1110. margin: 0;
  1111. overflow-y: scroll;
  1112. overflow-x: hidden;
  1113. }
  1114. .style-scope.ytd-comments {
  1115. overflow-y: auto;
  1116. overflow-x: hidden;
  1117. height: auto;
  1118. }
  1119. ytd-comment-view-model[is-reply] #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model, ytd-comment-view-model[is-creator-reply] #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model {
  1120. width: 40px;
  1121. height: 40px;
  1122. border-radius: 50%;
  1123. }
  1124. img.yt-img-shadow {
  1125. border-radius: 50% !important;
  1126. }
  1127. #author-thumbnail.ytd-comment-view-model yt-img-shadow.ytd-comment-view-model {
  1128. width: 40px;
  1129. height: 40px;
  1130. border-radius: 50%;
  1131. overflow: visible;
  1132. }
  1133. ytd-item-section-renderer.ytd-watch-next-secondary-results-renderer {
  1134. --ytd-item-section-item-margin: 8px;
  1135. overflow-y: auto;
  1136. overflow-x: hidden;
  1137. height: auto;
  1138. }
  1139. .right-section.ytcp-header {
  1140. display: flex;
  1141. flex: 1;
  1142. align-items: center;
  1143. gap: 45px;
  1144. justify-content: end;
  1145. }
  1146. #meta.ytd-playlist-panel-video-renderer {
  1147. min-width: 0;
  1148. padding: 0 8px;
  1149. display: flexbox;
  1150. display: flex;
  1151. flex-direction: column-reverse;
  1152. flex: 1;
  1153. flex-basis: 0.000000001px;
  1154. }
  1155.  
  1156. .containerall {
  1157. display: flex;
  1158. align-items: center;
  1159. justify-content: center;
  1160. width: 50%;
  1161. margin: auto;
  1162. }
  1163. }
  1164. .container .botoncalidades {
  1165. margin: 3px 2px;
  1166. width: 24.6%;
  1167. }
  1168.  
  1169. .botoncalidades:first-child {
  1170. background-color: #0af;
  1171. }
  1172.  
  1173. .botoncalidades:last-child {
  1174. background-color: red;
  1175. width: 100px;
  1176. }
  1177.  
  1178. .selectcalidades,
  1179. .botoncalidades,
  1180. .selectcalidadesaudio {
  1181. width: 50%;
  1182. height: 27.8px;
  1183. background-color: #fff;
  1184. color: #000;
  1185. font-size: 25px;
  1186. text-align: center;
  1187. border: 1px solid black;
  1188. border-radius: 10px;
  1189. border: none;
  1190. font-size: 20px;
  1191. margin: 2px 2px;
  1192. }
  1193.  
  1194. .botoncalidades {
  1195. width: 70px;
  1196. height: 30px;
  1197. background-color: rgb(4, 156, 22);
  1198. border: 0px solid #000;
  1199. color: #fff;
  1200. font-size: 20px;
  1201. border-radius: 10px;
  1202. margin: 2px 2px;
  1203. }
  1204.  
  1205. .botoncalidades:hover,
  1206. .bntcontainer:hover {
  1207. cursor: pointer;
  1208. }
  1209.  
  1210. .ocultarframe,
  1211. .ocultarframeaudio {
  1212. display: none;
  1213. }
  1214. .checked_updates {
  1215. cursor: pointer;
  1216. }
  1217.  
  1218. #export-config, #import-config {
  1219. width: 100%;
  1220. display: flex;
  1221. align-items: center;
  1222. justify-content: center;
  1223. gap: 10px;
  1224. background-color: var(--yt-enhance-menu-accent, --primary-custom) !important;;
  1225. color: #ffffff;
  1226. border: none;
  1227. padding: 5px;
  1228. }
  1229. #export-config:hover, #import-config:hover {
  1230. background-color: #ff0000;
  1231. color: #ffffff;
  1232. cursor: pointer;
  1233. }
  1234.  
  1235. .yt-image-avatar-download {
  1236. position: absolute;
  1237. bottom: -10px;
  1238. right: -14px;
  1239. border: none;
  1240. z-index: 1000;
  1241. background: transparent;
  1242. filter: drop-shadow(1px 0 6px red);
  1243. color: var(--ytcp-text-primary);
  1244. cursor: pointer;
  1245. }
  1246.  
  1247. .custom-classic-btn {
  1248. display: flex;
  1249. align-items: center;
  1250. justify-content: center;
  1251. background-color: rgba(255,255,255,0.1);
  1252. border-radius: 50%;
  1253. border: none;
  1254. width: 48px;
  1255. height: 48px;
  1256. color: var(--yt-spec-icon-inactive);
  1257. font-size: 24px;
  1258. margin: 0px 8px;
  1259. cursor: pointer;
  1260. }
  1261. .custom-classic-btn:hover {
  1262. background-color: rgba(255,255,255,0.2);
  1263. }
  1264. `);
  1265.  
  1266.  
  1267. // botons bottom video player
  1268.  
  1269. const thumbnailVideo = `
  1270. <button title="Image video" class="botones_div" type="button" id="imagen">
  1271.  
  1272. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-photo-down" width="24"
  1273. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1274. stroke-linecap="round" stroke-linejoin="round">
  1275. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1276. <path d="M15 8h.01"></path>
  1277. <path d="M12.5 21h-6.5a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v6.5"></path>
  1278. <path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l4 4"></path>
  1279. <path d="M14 14l1 -1c.653 -.629 1.413 -.815 2.13 -.559"></path>
  1280. <path d="M19 16v6"></path>
  1281. <path d="M22 19l-3 3l-3 -3"></path>
  1282. </svg>
  1283. </button>
  1284. `;
  1285.  
  1286. const filterEyes = `
  1287. <div style="position:relative; ">
  1288. <button title="Filter eyes" class="botones_div" type="button">
  1289. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-brightness-half"
  1290. width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"
  1291. fill="none" stroke-linecap="round" stroke-linejoin="round">
  1292. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1293. <path d="M12 9a3 3 0 0 0 0 6v-6z"></path>
  1294. <path
  1295. d="M6 6h3.5l2.5 -2.5l2.5 2.5h3.5v3.5l2.5 2.5l-2.5 2.5v3.5h-3.5l-2.5 2.5l-2.5 -2.5h-3.5v-3.5l-2.5 -2.5l2.5 -2.5z">
  1296. </path>
  1297. </svg>
  1298. <input id="eyes" list="presetColors" type="color" value="#ffffff">
  1299. <datalist id="presetColors">
  1300. <option value="#000000" />
  1301. <option value="#fbff00" />
  1302. <option value="#ff0000" />
  1303. <option value="#00ff00" />
  1304. <option value="#0000ff" />
  1305. </datalist>
  1306. <div id="ojosprotect"
  1307. style="position: fixed; pointer-events: none; width: 100%; height: 100%; left: 0px; top: 0px; opacity: 0.2; z-index: 10; display: block;">
  1308. </div>
  1309. </div>
  1310. </button>
  1311. `;
  1312.  
  1313. const resetButton = `
  1314. <button title="reset" class="botones_div" type="button" id="reset_button">
  1315. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-power" width="24"
  1316. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1317. stroke-linecap="round" stroke-linejoin="round">
  1318. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1319. <path d="M7 6a7.75 7.75 0 1 0 10 0"></path>
  1320. <path d="M12 4l0 8"></path>
  1321. </svg>
  1322. </button>
  1323. `;
  1324.  
  1325. const repeatVideo = `
  1326. <button title="Repeat video" class="botones_div" type="button" id="repeatvideo">
  1327.  
  1328. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat" width="24"
  1329. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1330. stroke-linecap="round" stroke-linejoin="round">
  1331. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1332. <path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3"></path>
  1333. <path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3 -3l3 -3"></path>
  1334. </svg>
  1335. </button>
  1336. `;
  1337.  
  1338. const downloadMp4Mp3 = `
  1339. <button title="MP4" type="button" class="btn1 botones_div">
  1340. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-file-download"
  1341. width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1342. stroke-linecap="round" stroke-linejoin="round">
  1343. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1344. <path d="M14 3v4a1 1 0 0 0 1 1h4"></path>
  1345. <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"></path>
  1346. <path d="M12 17v-6"></path>
  1347. <path d="M9.5 14.5l2.5 2.5l2.5 -2.5"></path>
  1348. </svg>
  1349. </button>
  1350. <button title="MP3" type="button" class="btn2 botones_div">
  1351.  
  1352. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-file-music" width="24"
  1353. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1354. stroke-linecap="round" stroke-linejoin="round">
  1355. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1356. <path d="M14 3v4a1 1 0 0 0 1 1h4"></path>
  1357. <path d="M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2z"></path>
  1358. <path d="M11 16m-1 0a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"></path>
  1359. <path d="M12 16l0 -5l2 1"></path>
  1360. </svg>
  1361. </button>
  1362. <button title="Close" type="button" class="btn3 botones_div">
  1363. <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-circle-x" width="24"
  1364. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  1365. stroke-linecap="round" stroke-linejoin="round">
  1366. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1367. <path d="M12 12m-9 0a9 9 0 1 0 18 0a9 9 0 1 0 -18 0"></path>
  1368. <path d="M10 10l4 4m0 -4l-4 4"></path>
  1369. </svg>
  1370. </button>
  1371. `;
  1372.  
  1373. const donwloadExternal = `
  1374.  
  1375. <button title="External Download" type="button" class="external_link botones_div">
  1376.  
  1377. <svg class="icon icon-tabler icon-tabler-external-link" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
  1378. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  1379. <path d="M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6"></path>
  1380. <path d="M11 13l9 -9"></path>
  1381. <path d="M15 4h5v5"></path>
  1382. </svg>
  1383. </button>
  1384.  
  1385. `;
  1386. const viewExternalVideo = `
  1387.  
  1388. <button title="view External no cookie" type="button" class="view_external_link botones_div">
  1389.  
  1390. <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M3 16m0 1a1 1 0 0 1 1 -1h3a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-3a1 1 0 0 1 -1 -1z" /><path d="M4 12v-6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-6" /><path d="M12 8h4v4" /><path d="M16 8l-5 5" /></svg>
  1391. </button>
  1392.  
  1393. `;
  1394.  
  1395. const pictureToPicture = `
  1396. <button title="Picture to picture" type="button" class="video_picture_to_picture botones_div">
  1397.  
  1398. <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M11 19h-6a2 2 0 0 1 -2 -2v-10a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v4" /><path d="M14 14m0 1a1 1 0 0 1 1 -1h5a1 1 0 0 1 1 1v3a1 1 0 0 1 -1 1h-5a1 1 0 0 1 -1 -1z" /></svg>
  1399. </button>
  1400.  
  1401. `;
  1402. const screenShot = `
  1403. <button title="Screenshot video" type="button" class="screenshot_video botones_div">
  1404. <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 8h.01" /><path d="M6 13l2.644 -2.644a1.21 1.21 0 0 1 1.712 0l3.644 3.644" /><path d="M13 13l1.644 -1.644a1.21 1.21 0 0 1 1.712 0l1.644 1.644" /><path d="M4 8v-2a2 2 0 0 1 2 -2h2" /><path d="M4 16v2a2 2 0 0 0 2 2h2" /><path d="M16 4h2a2 2 0 0 1 2 2v2" /><path d="M16 20h2a2 2 0 0 0 2 -2v-2" /></svg>
  1405. </button>
  1406.  
  1407. `;
  1408.  
  1409. const checkUpdates = `
  1410. <button title="Check new updates" type="button" class="checked_updates botones_div">
  1411. <svg width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M20 11a8.1 8.1 0 0 0 -15.5 -2m-.5 -4v4h4" /><path d="M4 13a8.1 8.1 0 0 0 15.5 2m.5 4v-4h-4" /></svg>
  1412. </button>
  1413. `;
  1414.  
  1415. const bufferVideo = `
  1416. <button title="Buffer video" type="button" class="buffer_video botones_div">
  1417. <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-align-box-right-stretch"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 17h2" /><path d="M3 5a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-14z" /><path d="M11 12h6" /><path d="M13 7h4" /></svg>
  1418. </button>
  1419. `;
  1420.  
  1421.  
  1422. const menuBotones = `
  1423. <main>
  1424. <div class="container">
  1425. <form>
  1426. <div class="containerButtons">
  1427. ${thumbnailVideo}
  1428. ${bufferVideo}
  1429. ${filterEyes}
  1430. ${resetButton}
  1431. ${repeatVideo}
  1432. ${downloadMp4Mp3}
  1433. ${donwloadExternal}
  1434. ${viewExternalVideo}
  1435. ${pictureToPicture}
  1436. ${screenShot}
  1437. ${checkUpdates}
  1438. </div>
  1439. <div>
  1440. </div>
  1441. </form>
  1442.  
  1443. </div>
  1444. <div class="content_collapsible_colors" style="margin-top: 10px">
  1445.  
  1446. <form class="formulariodescarga" action="">
  1447. <div class="containerall">
  1448. <select class="selectcalidades ocultarframe" required>
  1449. <option selected disabled>Calidad del video / Quality video</option>
  1450. <option value="360">360p Mp4</option>
  1451. <option value="480">480p Mp4</option>
  1452. <option value="720">720p HD Mp4 Default</option>
  1453. <option value="1080">1080p FULL HD Mp4</option>
  1454. <option value="4k">2160p 4K WEBM</option>
  1455. <option value="8k">4320p 8K WEBM</option>
  1456. </select>
  1457. <iframe id="descargando" style="z-index: 99; border: none; height: 27.4px; width: 50%;" class="containerall ocultarframe" src="" frameborder="0"></iframe>
  1458.  
  1459. </div>
  1460. </form>
  1461. <form class="formulariodescargaaudio" action="">
  1462. <div class="containerall">
  1463. <select class="selectcalidadesaudio ocultarframeaudio" required>
  1464. <option selected disabled>Calidad del Audio / Quality Audio</option>
  1465. <option value="flac">Audio FLAC UHQ</option>
  1466. <option value="wav">Audio WAV UHQ</option>
  1467. <option value="mp3">Audio MP3 Default</option>
  1468. <option value="m4a">Audio M4A</option>
  1469. <option value="aac">Audio AAC</option>
  1470. <option value="opus">Audio OPUS</option>
  1471. <option value="ogg">Audio OGG</option>
  1472. </select>
  1473. <iframe id="descargandomp3" style="z-index: 99; border: none; height: 27.4px; width: 50%;" class="containerall ocultarframeaudio" src="" frameborder="0"></iframe>
  1474.  
  1475. </iframe>
  1476.  
  1477. </div>
  1478. </form>
  1479. </main>
  1480. `;
  1481.  
  1482.  
  1483. // Define themes
  1484. const themes = [
  1485. {
  1486. name: 'Default / Reload',
  1487. gradient: '',
  1488. textColor: '',
  1489. raised: '',
  1490. btnTranslate: '',
  1491. CurrentProgressVideo: '',
  1492. videoDuration: '',
  1493. colorIcons: '',
  1494. textLogo: '',
  1495. primaryColor: '',
  1496. secondaryColor: '',
  1497. },
  1498. {
  1499. name: 'Midnight Blue',
  1500. gradient: 'linear-gradient(135deg, #1e3a8a, #3b82f6)',
  1501. textColor: '#ffffff',
  1502. raised: '#f00',
  1503. btnTranslate: '#000',
  1504. CurrentProgressVideo: '#0f0',
  1505. videoDuration: '#fff',
  1506. colorIcons: '#fff',
  1507. textLogo: '#f00',
  1508. },
  1509. {
  1510. name: 'Forest Green',
  1511. gradient: 'linear-gradient(135deg, #14532d, #22c55e)',
  1512. textColor: '#ffffff',
  1513. raised: '#303131',
  1514. btnTranslate: '#000',
  1515. CurrentProgressVideo: '#0f0',
  1516. videoDuration: '#fff',
  1517. colorIcons: '#fff',
  1518. textLogo: '#f00',
  1519. },
  1520. {
  1521. name: 'Sunset Orange',
  1522. gradient: 'linear-gradient(135deg, #7c2d12, #f97316)',
  1523. textColor: '#ffffff',
  1524. raised: '#303131',
  1525. btnTranslate: '#000',
  1526. CurrentProgressVideo: '#0f0',
  1527. videoDuration: '#fff',
  1528. colorIcons: '#fff',
  1529. textLogo: '#f00',
  1530. },
  1531. {
  1532. name: 'Royal Purple',
  1533. gradient: 'linear-gradient(135deg, #4c1d95, #8b5cf6)',
  1534. textColor: '#ffffff',
  1535. raised: '#303131',
  1536. btnTranslate: '#000',
  1537. CurrentProgressVideo: '#0f0',
  1538. videoDuration: '#fff',
  1539. colorIcons: '#fff',
  1540. textLogo: '#f00',
  1541. },
  1542. {
  1543. name: 'Cherry Blossom',
  1544. gradient: 'linear-gradient(135deg, #a9005c, #fc008f)',
  1545. textColor: '#ffffff',
  1546. raised: '#fc008f',
  1547. btnTranslate: '#000',
  1548. CurrentProgressVideo: '#0f0',
  1549. videoDuration: '#fff',
  1550. colorIcons: '#fff',
  1551. textLogo: '#f00',
  1552. },
  1553. {
  1554. name: 'Red Dark',
  1555. gradient: 'linear-gradient(135deg, #790909, #f70131)',
  1556. textColor: '#ffffff',
  1557. raised: '#303131',
  1558. btnTranslate: '#000',
  1559. CurrentProgressVideo: '#0f0',
  1560. videoDuration: '#fff',
  1561. colorIcons: '#fff',
  1562. textLogo: '#f00',
  1563. },
  1564. {
  1565. name: 'Raind ',
  1566. gradient: 'linear-gradient(90deg, #3f5efb 0%, #fc466b) 100%',
  1567. textColor: '#ffffff',
  1568. raised: '#303131',
  1569. btnTranslate: '#000',
  1570. CurrentProgressVideo: '#0f0',
  1571. videoDuration: '#fff',
  1572. colorIcons: '#fff',
  1573. textLogo: '#f00',
  1574. },
  1575. {
  1576. name: 'Neon',
  1577. gradient: 'linear-gradient(273deg, #ee49fd 0%, #6175ff 100%)',
  1578. textColor: '#ffffff',
  1579. raised: '#303131',
  1580. btnTranslate: '#000',
  1581. CurrentProgressVideo: '#0f0',
  1582. videoDuration: '#fff',
  1583. colorIcons: '#fff',
  1584. textLogo: '#f00',
  1585. },
  1586. {
  1587. name: 'Azure',
  1588. gradient: 'linear-gradient(273deg, #0172af 0%, #74febd 100%)',
  1589. textColor: '#ffffff',
  1590. raised: '#303131',
  1591. btnTranslate: '#000',
  1592. CurrentProgressVideo: '#0f0',
  1593. videoDuration: '#fff',
  1594. colorIcons: '#fff',
  1595. textLogo: '#f00',
  1596. },
  1597. {
  1598. name: 'Butterfly',
  1599. gradient: 'linear-gradient(273deg, #ff4060 0%, #fff16a 100%)',
  1600. textColor: '#ffffff',
  1601. raised: '#303131',
  1602. btnTranslate: '#000',
  1603. CurrentProgressVideo: '#0f0',
  1604. videoDuration: '#fff',
  1605. colorIcons: '#fff',
  1606. textLogo: '#f00',
  1607. },
  1608. {
  1609. name: 'Colombia',
  1610. gradient:
  1611. 'linear-gradient(174deg, #fbf63f 0%, #0000bb 45%, #ff0000 99%)',
  1612. textColor: '#ffffff',
  1613. raised: '#303131',
  1614. btnTranslate: '#000',
  1615. CurrentProgressVideo: '#0f0',
  1616. videoDuration: '#fff',
  1617. colorIcons: '#fff',
  1618. textLogo: '#f00',
  1619. },
  1620. ];
  1621.  
  1622. // Create our enhancement panel
  1623. const panel = $cl('div');
  1624.  
  1625. panel.id = 'yt-enhancement-panel';
  1626.  
  1627. // Generate theme options HTML
  1628. const themeOptionsHTML = themes
  1629. .map(
  1630. (theme, index) => `
  1631. <label >
  1632. <div class="theme-option">
  1633. <div class="theme-preview" style="background: ${theme.gradient};"></div>
  1634. <input type="radio" name="theme" value="${index}" ${
  1635. index === 0 ? 'checked' : ''
  1636. }>
  1637. <span style="${theme.name === 'Default / Reload Page' ? 'color: red; ' : '' }" class="theme-name">${theme.name}</span>
  1638. </div>
  1639. </label>
  1640. `
  1641. )
  1642. .join('');
  1643.  
  1644. const languageOptionsHTML = Object.entries(languagesTranslate)
  1645. .map(([code, name]) => {
  1646. const selected = code === languagesTranslate ? 'selected' : '';
  1647. return `<option value="${code}" ${selected}>${name}</option>`;
  1648. })
  1649. .join('');
  1650.  
  1651.  
  1652.  
  1653. function checkDarkModeActive() {
  1654. const pref = document.cookie.split('; ').find(c => c.startsWith('PREF='));
  1655. if (!pref) return 'light';
  1656. const params = new URLSearchParams(pref.split('&').join('&'));
  1657. const darkModes = ['400', '4000000', '40000400', '40000000'];
  1658. return darkModes.includes(params.get('f6')) ? 'dark' : 'light';
  1659. }
  1660.  
  1661. let isDarkModeActive = checkDarkModeActive();
  1662.  
  1663.  
  1664. // Use Trusted Types to set innerHTML
  1665. const menuHTML = `
  1666. <div class="container-mdcm">
  1667. <div class="header-mdcm">
  1668. <h1> <i class="fa-brands fa-youtube"></i> YouTube Tools</h1>
  1669. <div class="icons-mdcm">
  1670. <a href="https://update.greatest.deepsurf.us/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js"
  1671. target="_blank">
  1672. <button class="icon-btn-mdcm">
  1673. <i class="fa-solid fa-arrows-rotate"></i>
  1674. </button>
  1675. </a>
  1676. <a href="https://github.com/DeveloperMDCM" target="_blank">
  1677. <button class="icon-btn-mdcm">
  1678. <i class="fa-brands fa-github"></i>
  1679. </button>
  1680. </a>
  1681. <button class="icon-btn-mdcm" id="shareBtn-mdcm">
  1682. <i class="fa-solid fa-share-alt"></i>
  1683. </button>
  1684. <button class="icon-btn-mdcm" id="importExportBtn">
  1685. <i class="fa-solid fa-file-import"></i>
  1686. </button>
  1687. <button id="menu-settings-icon" class="icon-btn-mdcm tab-mdcm" data-tab="menu-settings">
  1688. <i class="fa-solid fa-gear"></i>
  1689. </button>
  1690. <button class="icon-btn-mdcm close_menu_settings">
  1691. <i class="fa-solid fa-xmark"></i>
  1692. </button>
  1693. </div>
  1694. </div>
  1695.  
  1696. <div class="tabs-mdcm">
  1697. <button class="tab-mdcm active" data-tab="general">
  1698. <i class="fa-solid fa-shield-halved"></i>
  1699. General
  1700. </button>
  1701. <button class="tab-mdcm" data-tab="themes">
  1702. <i class="fa-solid fa-palette"></i>
  1703. Themes
  1704. </button>
  1705. <button class="tab-mdcm" data-tab="stats">
  1706. <i class="fa-solid fa-square-poll-vertical"></i>
  1707. Stats
  1708. </button>
  1709. <button class="tab-mdcm" data-tab="headers">
  1710. <i class="fa-regular fa-newspaper"></i>
  1711. Header
  1712. </button>
  1713. </div>
  1714.  
  1715.  
  1716. <div id="general" class="tab-content active">
  1717.  
  1718. <div class="options-mdcm">
  1719. <label>
  1720. <div class="option-mdcm">
  1721. <input type="checkbox" class="checkbox-mdcm" id="hide-comments-toggle"> Hide Comments
  1722. </div>
  1723. </label>
  1724. <label>
  1725. <div class="option-mdcm">
  1726. <input type="checkbox" class="checkbox-mdcm" id="hide-sidebar-toggle"> Hide Sidebar
  1727. </div>
  1728. </label>
  1729. <label>
  1730. <div class="option-mdcm">
  1731. <input type="checkbox" class="checkbox-mdcm" id="autoplay-toggle"> Disable Autoplay
  1732. </div>
  1733. </label>
  1734. <label>
  1735. <div class="option-mdcm">
  1736. <input type="checkbox" class="checkbox-mdcm" id="subtitles-toggle"> Disable Subtitles
  1737. </div>
  1738. </label>
  1739. <label>
  1740. <div class="option-mdcm">
  1741. <input type="checkbox" class="checkbox-mdcm" checked id="dislikes-toggle"> Show Dislikes
  1742. </div>
  1743. </label>
  1744. <label>
  1745. <div class="option-mdcm">
  1746. <input type="checkbox" class="checkbox-mdcm" id="themes-toggle"> Active Themes
  1747. </div>
  1748. </label>
  1749. <label>
  1750. <div class="option-mdcm">
  1751. <input type="checkbox" class="checkbox-mdcm" id="translation-toggle"> Translate comments
  1752. </div>
  1753. </label>
  1754. <label>
  1755. <div class="option-mdcm">
  1756. <input type="checkbox" class="checkbox-mdcm" id="avatars-toggle"> Download avatars
  1757. </div>
  1758. </label>
  1759. <label>
  1760. <div class="option-mdcm">
  1761. <input type="checkbox" class="checkbox-mdcm" id="reverse-mode-toggle"> Reverse mode
  1762. </div>
  1763. </label>
  1764. <label>
  1765. <div class="option-mdcm">
  1766. <input type="checkbox" class="checkbox-mdcm" checked id="wave-visualizer-toggle"> Wave visualizer Beta
  1767. </div>
  1768. </label>
  1769. <div class="quality-selector-mdcm" style="grid-column: span 2;">
  1770. <div class="select-wrapper-mdcm">
  1771. <label>Effect wave visualizer:
  1772. <select class="tab-button-active" id="select-wave-visualizer-select">
  1773. <option value="linea">Line smooth</option>
  1774. <option value="barras">Vertical bars</option>
  1775. <option value="curva">Curved</option>
  1776. <option value="picos">Smooth peaks</option>
  1777. <option value="solida">Solid wave</option>
  1778. <option value="dinamica">Dynamic wave</option>
  1779. <option value="montana">Smooth mountain</option>
  1780. </select>
  1781. </label>
  1782. </div>
  1783. </div>
  1784. <div class="quality-selector-mdcm" style="grid-column: span 2;">
  1785. <div class="select-wrapper-mdcm">
  1786. <label>Default video player quality:
  1787. <select class="tab-button-active" id="select-video-qualitys-select">
  1788. <option value="144">144</option>
  1789. <option value="240">240</option>
  1790. <option value="360">360</option>
  1791. <option value="480">480</option>
  1792. <option value="720">720</option>
  1793. <option value="1080">1080</option>
  1794. <option value="1440">1440</option>
  1795. <option value="2160">2160</option>
  1796. </select>
  1797. </label>
  1798. </div>
  1799. </div>
  1800. <div class="quality-selector-mdcm" style="grid-column: span 2;">
  1801. <div class="select-wrapper-mdcm">
  1802. <label>Language for translate comments:
  1803. <select class="tab-button-active" id="select-languages-comments-select">
  1804. ${languageOptionsHTML}
  1805. </select>
  1806. </label>
  1807. </div>
  1808. </div>
  1809. <div class="slider-container-mdcm" style="grid-column: span 2;">
  1810. <label>Video Player Size: <span id="player-size-value">100</span>%</label>
  1811. <input type="range" id="player-size-slider" class="slider-mdcm" min="50" max="150" value="100">
  1812. <button class="reset-btn-mdcm" id="reset-player-size">Reset video size</button>
  1813. </div>
  1814. </div>
  1815. </div>
  1816.  
  1817. <div id="themes" class="tab-content">
  1818. <div class="themes-hidden">
  1819. <div class="options-mdcm" style="margin-bottom: 10px;">
  1820. <div>
  1821. <h4>Choose a Theme</h4>
  1822. <p>Disable cinematic Lighting</p>
  1823. ${isDarkModeActive === 'dark' ? '' : '<p style="color: red; margin: 10px 0;font-size: 11px;">Activate dark mode to use this option</p>'}
  1824. </div>
  1825. </div>
  1826. <div class="options-mdcm">
  1827. <label>
  1828. <div class="theme-option option-mdcm">
  1829. <input type="radio" class="radio-mdcm" name="theme" value="custom" checked>
  1830. <span class="theme-name">Custom</span>
  1831. </div>
  1832. </label>
  1833. <label>
  1834. <div class="theme-option option-mdcm theme-selected-normal">
  1835. <input type="radio" class="radio-mdcm" name="theme" value="normal">
  1836. <span class="theme-name">Selected Themes</span>
  1837. </div>
  1838. </label>
  1839. </div>
  1840. <div class="themes-options">
  1841. <div class="options-mdcm">
  1842. ${themeOptionsHTML}
  1843. </div>
  1844. </div>
  1845. <div class="theme-custom-options">
  1846. <div class="options-mdcm">
  1847. <div class="option-mdcm">
  1848. <div class="card-items-end">
  1849. <label>Progressbar Video:</label>
  1850. <input type="color" id="progressbar-color-picker" class="color-picker-mdcm" value="#ff0000">
  1851. </div>
  1852. </div>
  1853. <div class="option-mdcm">
  1854. <div class="card-items-end">
  1855. <label>Background Color:</label>
  1856. <input type="color" id="bg-color-picker" class="color-picker-mdcm" value="#000000">
  1857. </div>
  1858. </div>
  1859. <div class="option-mdcm">
  1860. <div class="card-items-end">
  1861. <label>Primary Color:</label>
  1862. <input type="color" id="primary-color-picker" class="color-picker-mdcm" value="#ffffff">
  1863. </div>
  1864. </div>
  1865. <div class="option-mdcm">
  1866. <div class="card-items-end">
  1867. <label>Secondary Color:</label>
  1868. <input type="color" id="secondary-color-picker" class="color-picker-mdcm" value="#ffffff">
  1869. </div>
  1870. </div>
  1871. <div class="option-mdcm">
  1872. <div class="card-items-end">
  1873. <label>Header Color:</label>
  1874. <input type="color" id="header-color-picker" class="color-picker-mdcm" value="#000000">
  1875. </div>
  1876. </div>
  1877. <div class="option-mdcm">
  1878. <div class="card-items-end">
  1879. <label>Icons Color:</label>
  1880. <input type="color" id="icons-color-picker" class="color-picker-mdcm" value="#ffffff">
  1881. </div>
  1882. </div>
  1883. <div class="option-mdcm">
  1884. <div class="card-items-end">
  1885. <label>Menu Color:</label>
  1886. <input type="color" id="menu-color-picker" class="color-picker-mdcm" value="#000000">
  1887. </div>
  1888. </div>
  1889. <div class="option-mdcm">
  1890. <div class="card-items-end">
  1891. <label>Line Color Preview:</label>
  1892. <input type="color" id="line-color-picker" class="color-picker-mdcm" value="#ff0000">
  1893. </div>
  1894. </div>
  1895. <div class="option-mdcm">
  1896. <div class="card-items-end">
  1897. <label>Time Color Preview:</label>
  1898. <input type="color" id="time-color-picker" class="color-picker-mdcm" value="#ffffff">
  1899. </div>
  1900. </div>
  1901. </div>
  1902. </div>
  1903. </div>
  1904. </div>
  1905.  
  1906. <div id="stats" class="tab-content">
  1907. <div id="yt-stats-toggle">
  1908. <div class="stat-row">
  1909. <div>Foreground Time</div>
  1910. <div class="progress">
  1911. <div class="progress-bar total-bar" id="usage-bar"></div>
  1912. </div>
  1913. <div id="total-time">0h 0m 0s</div>
  1914. </div>
  1915. <div class="stat-row">
  1916. <div>Video Time</div>
  1917. <div class="progress">
  1918. <div class="progress-bar video-bar" id="video-bar"></div>
  1919. </div>
  1920. <div id="video-time">0h 0m 0s</div>
  1921. </div>
  1922. <div class="stat-row">
  1923. <div>Shorts Time</div>
  1924. <div class="progress">
  1925. <div class="progress-bar shorts-bar" id="shorts-bar"></div>
  1926. </div>
  1927. <div id="shorts-time">0h 0m 0s</div>
  1928. </div>
  1929. </div>
  1930. </div>
  1931.  
  1932. <div id="headers" class="tab-content">
  1933. <div class="options-mdcm">
  1934. <label>Available in next update</label>
  1935. </div>
  1936. </div>
  1937.  
  1938.  
  1939. <div id="menu-settings" class="tab-content">
  1940. <div class="options-mdcm">
  1941. <h4 style="margin: 10px 0">Menu Appearance</h4>
  1942. </div>
  1943. <div class="options-settings-mdcm">
  1944. <div class="option-settings-mdcm">
  1945. <label>Backgrounds:</label>
  1946. <div class="color-boxes" id="bg-color-options">
  1947. <div class="color-box" data-type="bg" data-value="#252525" style="background-color: #252525;"></div>
  1948. <div class="color-box" data-type="bg" data-value="#1e1e1e" style="background-color: #1e1e1e;"></div>
  1949. <div class="color-box" data-type="bg" data-value="#3a3a3a" style="background-color: #3a3a3a;"></div>
  1950. <div class="color-box" data-type="bg" data-value="#4a4a4a" style="background-color: #4a4a4a;"></div>
  1951. <div class="color-box" data-type="bg" data-value="#000000" style="background-color: #000000;"></div>
  1952. <div class="color-box" data-type="bg" data-value="#00000000" style="background-color: #00000000;"></div>
  1953. <div class="color-box" data-type="bg" data-value="#2d2d2d" style="background-color: #2d2d2d;"></div>
  1954. <div class="color-box" data-type="bg" data-value="#444" style="background-color: #444;"></div>
  1955. </div>
  1956. </div>
  1957.  
  1958. <div class="option-settings-mdcm">
  1959. <label>Accent Colors:</label>
  1960. <div class="color-boxes" id="bg-accent-color-options">
  1961. <div class="color-box" data-type="accent" data-value="#ff0000" style="background-color: #ff0000;"></div>
  1962. <div class="color-box" data-type="accent" data-value="#000000" style="background-color: #000000;"></div>
  1963. <div class="color-box" data-type="accent" data-value="#009c37 " style="background-color: #009c37 ;"></div>
  1964. <div class="color-box" data-type="accent" data-value="#0c02a0 " style="background-color: #0c02a0 ;"></div>
  1965. </div>
  1966. </div>
  1967.  
  1968. <div class="option-settings-mdcm">
  1969. <label>Titles Colors:</label>
  1970. <div class="color-boxes" id="text-color-options">
  1971. <div class="color-box" data-type="color" data-value="#ffffff" style="background-color: #ffffff;"></div>
  1972. <div class="color-box" data-type="color" data-value="#cccccc" style="background-color: #cccccc;"></div>
  1973. <div class="color-box" data-type="color" data-value="#b3b3b3" style="background-color: #b3b3b3;"></div>
  1974. <div class="color-box" data-type="color" data-value="#00ffff" style="background-color: #00ffff;"></div>
  1975. <div class="color-box" data-type="color" data-value="#00ff00" style="background-color: #00ff00;"></div>
  1976. <div class="color-box" data-type="color" data-value="#ffff00" style="background-color: #ffff00;"></div>
  1977. <div class="color-box" data-type="color" data-value="#ffcc00" style="background-color: #ffcc00;"></div>
  1978. <div class="color-box" data-type="color" data-value="#ff66cc" style="background-color: #ff66cc;"></div>
  1979. </div>
  1980. </div>
  1981. </div>
  1982. </div>
  1983.  
  1984. <div id="importExportArea">
  1985. <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
  1986. <h3>Import / Export Settings</h3>
  1987. <button class="icon-btn-mdcm" id="closeImportExportBtn">
  1988. <i class="fa-solid fa-xmark"></i>
  1989. </button>
  1990. </div>
  1991. <textarea id="config-data" placeholder="Paste configuration here to import"></textarea>
  1992. <div class="action-buttons-mdcm">
  1993. <button id="export-config" class="action-btn-mdcm">Export</button>
  1994. <button id="import-config" class="action-btn-mdcm">Import</button>
  1995. </div>
  1996. </div>
  1997.  
  1998. <div id="shareDropdown">
  1999. <a href="https://www.facebook.com/sharer/sharer.php?u=${urlSharedCode}" target="_blank" data-network="facebook"
  2000. class="share-link"><i class="fa-brands fa-facebook"></i> Facebook</a><br>
  2001. <a href="https://twitter.com/intent/tweet?url=${urlSharedCode}" target="_blank" data-network="twitter"
  2002. class="share-link"><i class="fa-brands fa-twitter"></i> Twitter</a><br>
  2003. <a href="https://api.whatsapp.com/send?text=${urlSharedCode}" target="_blank" data-network="whatsapp"
  2004. class="share-link"><i class="fa-brands fa-whatsapp"></i> WhatsApp</a><br>
  2005. <a href="https://www.linkedin.com/sharing/share-offsite/?url=${urlSharedCode}" target="_blank"
  2006. data-network="linkedin" class="share-link"><i class="fa-brands fa-linkedin"></i> LinkedIn</a><br>
  2007. </div>
  2008.  
  2009.  
  2010. </div>
  2011. <div class="actions-mdcm">
  2012. <div class="developer-mdcm">
  2013. Developed by <a href="https://github.com/DeveloperMDCM" target="_blank">DeveloperMDCM</a>
  2014. </div>
  2015. <span style="color: #fff" ;>v2.3.4.2</span>
  2016. </div>
  2017. `;
  2018. const panelHTML = policy
  2019. ? policy.createHTML(`
  2020. ${menuHTML}
  2021. `)
  2022. : `
  2023. ${menuHTML}
  2024. `;
  2025.  
  2026. panel.innerHTML = panelHTML;
  2027. $ap(panel);
  2028.  
  2029. function addIcon() {
  2030. const topBar = $e('ytd-topbar-menu-button-renderer');
  2031. if (!topBar || $id('icon-menu-settings')) return;
  2032. const toggleButton = $cl('div');
  2033. toggleButton.id = 'toggle-button';
  2034. const icon = $cl('i');
  2035. icon.id = 'icon-menu-settings';
  2036. icon.classList.add('fa-solid', 'fa-gear');
  2037. toggleButton.appendChild(icon);
  2038. topBar.parentElement.insertBefore(toggleButton, topBar);
  2039. // Toggle panel visibility
  2040. let openMenu = false;
  2041. toggleButton.addEventListener('click', () => {
  2042. openMenu = !openMenu;
  2043. // openMenu
  2044. // ? (toggleButton.style.backgroundColor = '#f00')
  2045. // : (toggleButton.style.backgroundColor = 'transparent');
  2046. panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
  2047. });
  2048.  
  2049. }
  2050.  
  2051. addIcon();
  2052. let openMenu = false;
  2053.  
  2054. const close_menu_settings = $e('.close_menu_settings');
  2055. close_menu_settings.addEventListener('click', () => {
  2056. openMenu = !openMenu;
  2057. panel.style.display = panel.style.display === 'none' ? 'block' : 'none';
  2058. });
  2059.  
  2060. // $ap(toggleButton);
  2061.  
  2062.  
  2063.  
  2064.  
  2065. // Tab functionality
  2066. const tabButtons = $m('.tab-mdcm');
  2067. const tabContents = $m('.tab-content');
  2068.  
  2069. tabButtons.forEach((button) => {
  2070. button.addEventListener('click', () => {
  2071. const tabName = button.getAttribute('data-tab');
  2072. tabButtons.forEach((btn) => btn.classList.remove('active'));
  2073. tabContents.forEach((content) => content.classList.remove('active'));
  2074. button.classList.add('active');
  2075. $id(tabName).classList.add('active');
  2076. });
  2077. });
  2078. // Function to save settings
  2079. function saveSettings() {
  2080. const settings = {
  2081. theme: $e('input[name="theme"]:checked').value,
  2082. bgColorPicker: $id('bg-color-picker').value,
  2083. progressbarColorPicker: $id('progressbar-color-picker').value,
  2084. primaryColorPicker: $id('primary-color-picker').value,
  2085. secondaryColorPicker: $id('secondary-color-picker').value,
  2086. headerColorPicker: $id('header-color-picker').value,
  2087. iconsColorPicker: $id('icons-color-picker').value,
  2088. menuColorPicker: $id('menu-color-picker').value,
  2089. lineColorPicker: $id('line-color-picker').value,
  2090. timeColorPicker: $id('time-color-picker').value,
  2091. dislikes: $id('dislikes-toggle').checked,
  2092. themes: $id('themes-toggle').checked,
  2093. translation: $id('translation-toggle').checked,
  2094. avatars: $id('avatars-toggle').checked,
  2095. reverseMode: $id('reverse-mode-toggle').checked,
  2096. waveVisualizer: $id('wave-visualizer-toggle').checked,
  2097. waveVisualizerSelected: $id('select-wave-visualizer-select').value,
  2098. hideComments: $id('hide-comments-toggle').checked,
  2099. hideSidebar: $id('hide-sidebar-toggle').checked,
  2100. disableAutoplay: $id('autoplay-toggle').checked,
  2101. // cinematicLighting: $id('cinematic-lighting-toggle').checked,
  2102. disableSubtitles: $id('subtitles-toggle').checked,
  2103. // fontSize: $id('font-size-slider').value,
  2104. playerSize: $id('player-size-slider').value,
  2105. selectVideoQuality: $id('select-video-qualitys-select').value,
  2106. languagesComments: $id('select-languages-comments-select').value,
  2107. // menuBgColor: $id('menu-bg-color-picker').value,
  2108. // menuTextColor: $id('menu-text-color-picker').value,
  2109. menu_developermdcm: {
  2110. bg: selectedBgColor,
  2111. color: selectedTextColor,
  2112. accent: selectedBgAccentColor
  2113. }
  2114. // menuFontSize: $id('menu-font-size-slider').value,
  2115. };
  2116.  
  2117. GM_setValue('ytSettingsMDCM', JSON.stringify(settings));
  2118. }
  2119.  
  2120.  
  2121. // Function to load settings
  2122. function loadSettings() {
  2123. const settings = JSON.parse(GM_getValue('ytSettingsMDCM', '{}'));
  2124. if (settings.theme) {
  2125. $e(`input[name="theme"][value="${settings.theme}"]`).checked = true;
  2126. }
  2127. settings.menu_developermdcm = settings.menu_developermdcm || {
  2128. bg: "#252525",
  2129. color: "#ffffff",
  2130. accent: "#ff0000"
  2131. };
  2132. $id('bg-color-picker').value = settings.bgColorPicker || '#000000';
  2133. $id('progressbar-color-picker').value = settings.progressbarColorPicker || '#ff0000';
  2134. $id('primary-color-picker').value = settings.primaryColorPicker || '#ffffff';
  2135. $id('secondary-color-picker').value = settings.secondaryColorPicker || '#ffffff';
  2136. $id('header-color-picker').value = settings.headerColorPicker || '#000';
  2137. $id('icons-color-picker').value = settings.iconsColorPicker || '#ffffff';
  2138. $id('menu-color-picker').value = settings.menuColorPicker || '#000';
  2139. $id('line-color-picker').value = settings.lineColorPicker || '#ff0000';
  2140. $id('time-color-picker').value = settings.timeColorPicker || '#ffffff';
  2141. $id('dislikes-toggle').checked = settings.dislikes || false;
  2142. $id('themes-toggle').checked = settings.themes || false;
  2143. $id('translation-toggle').checked = settings.translation || false;
  2144. $id('avatars-toggle').checked = settings.avatars || false;
  2145. $id('reverse-mode-toggle').checked = settings.reverseMode || false;
  2146. $id('wave-visualizer-toggle').checked = settings.waveVisualizer || false;
  2147. $id('select-wave-visualizer-select').value = settings.waveVisualizerSelected || 'dinamica';
  2148. $id('hide-comments-toggle').checked = settings.hideComments || false;
  2149. $id('hide-sidebar-toggle').checked = settings.hideSidebar || false;
  2150. $id('autoplay-toggle').checked = settings.disableAutoplay || false;
  2151. // $id('cinematic-lighting-toggle').checked = settings.cinematicLighting || false;
  2152. $id('subtitles-toggle').checked = settings.disableSubtitles || false;
  2153. // $id('font-size-slider').value = settings.fontSize || 16;
  2154. $id('player-size-slider').value = settings.playerSize || 100;
  2155. $id('select-video-qualitys-select').value = settings.selectVideoQuality || '720';
  2156. $id('select-languages-comments-select').value = settings.languagesComments || 'en';
  2157. // $id('menu-bg-color-picker').value = settings.menuBgColor || '#000000';
  2158. // $id('menu-text-color-picker').value = settings.menuTextColor || '#ffffff';
  2159. // $id('menu-font-size-slider').value = settings.menuFontSize || 14;
  2160. // Asegurar existencia de menu_developermdcm
  2161. selectedBgColor = settings.menu_developermdcm.bg;
  2162. selectedTextColor = settings.menu_developermdcm.color;
  2163. selectedBgAccentColor = settings.menu_developermdcm.accent;
  2164. $m('#bg-color-options .color-box').forEach(el => {
  2165. el.classList.toggle('selected', el.dataset.value === selectedBgColor);
  2166. });
  2167.  
  2168. $m('#text-color-options .color-box').forEach(el => {
  2169. el.classList.toggle('selected', el.dataset.value === selectedTextColor);
  2170. });
  2171.  
  2172. $m('#bg-accent-color-options .color-box').forEach(el => {
  2173. el.classList.toggle('selected', el.dataset.value === selectedBgAccentColor);
  2174. });
  2175.  
  2176. // Apply menu colors
  2177. $sp('--yt-enhance-menu-bg', selectedBgColor);
  2178. $sp('--yt-enhance-menu-text', selectedTextColor);
  2179. $sp('--yt-enhance-menu-accent', selectedBgAccentColor);
  2180. updateSliderValues();
  2181.  
  2182. setTimeout(() => {
  2183. applySettings();
  2184. if(settings.dislikes) {
  2185. videoDislike();
  2186. shortDislike();
  2187. showDislikes = true;
  2188. }
  2189. }, 500);
  2190. }
  2191.  
  2192. $m('.color-box').forEach(box => {
  2193. box.addEventListener('click', () => {
  2194. const type = box.dataset.type;
  2195. const value = box.dataset.value;
  2196. if (type === 'bg') {
  2197. selectedBgColor = value;
  2198. $sp('--yt-enhance-menu-bg', value);
  2199. $m('#bg-color-options .color-box').forEach(el => {
  2200. el.classList.remove('selected');
  2201. });
  2202. box.classList.add('selected');
  2203. } else if (type === 'color') {
  2204. selectedTextColor = value;
  2205. $sp('--yt-enhance-menu-text', value);
  2206. $m('#text-color-options .color-box').forEach(el => {
  2207. el.classList.remove('selected');
  2208. });
  2209. box.classList.add('selected');
  2210. }
  2211. else if (type === 'accent') {
  2212. selectedBgAccentColor = value;
  2213. $sp('--yt-enhance-menu-accent', value);
  2214. $m('#bg-accent-color-options .color-box').forEach(el => {
  2215. el.classList.remove('selected');
  2216. });
  2217. box.classList.add('selected');
  2218. }
  2219. saveSettings();
  2220. });
  2221. });
  2222. function updateSliderValues() {
  2223. $id('player-size-value').textContent = $id('player-size-slider').value;
  2224. }
  2225.  
  2226. $id('reset-player-size').addEventListener('click', () => {
  2227. $id('player-size-slider').value = 100;
  2228. updateSliderValues();
  2229. applySettings();
  2230. });
  2231.  
  2232. // Function to apply settings
  2233. function applySettings() {
  2234. const formulariodescarga = $e('.formulariodescarga');
  2235. const formulariodescargaaudio = $e('.formulariodescargaaudio');
  2236. if (formulariodescarga != undefined) {
  2237. formulariodescarga.classList.add('ocultarframe');
  2238. formulariodescargaaudio.classList.add('ocultarframe');
  2239. }
  2240. const settings = {
  2241. theme: $e('input[name="theme"]:checked').value,
  2242. bgColorPicker: $id('bg-color-picker').value,
  2243. progressbarColorPicker: $id('progressbar-color-picker').value,
  2244. primaryColorPicker: $id('primary-color-picker').value,
  2245. secondaryColorPicker: $id('secondary-color-picker').value,
  2246. headerColorPicker: $id('header-color-picker').value,
  2247. iconsColorPicker: $id('icons-color-picker').value,
  2248. menuColorPicker: $id('menu-color-picker').value,
  2249. lineColorPicker: $id('line-color-picker').value,
  2250. timeColorPicker: $id('time-color-picker').value,
  2251. dislikes: $id('dislikes-toggle').checked,
  2252. themes: $id('themes-toggle').checked,
  2253. translation: $id('translation-toggle').checked,
  2254. avatars: $id('avatars-toggle').checked,
  2255. reverseMode: $id('reverse-mode-toggle').checked,
  2256. waveVisualizer: $id('wave-visualizer-toggle').checked,
  2257. waveVisualizerSelected: $id('select-wave-visualizer-select').value,
  2258. hideComments: $id('hide-comments-toggle').checked,
  2259. hideSidebar: $id('hide-sidebar-toggle').checked,
  2260. disableAutoplay: $id('autoplay-toggle').checked,
  2261. // cinematicLighting: $id('cinematic-lighting-toggle').checked,
  2262. disableSubtitles: $id('subtitles-toggle').checked,
  2263. // fontSize: $id('font-size-slider').value,
  2264. playerSize: $id('player-size-slider').value,
  2265. selectVideoQuality: $id('select-video-qualitys-select').value,
  2266. languagesComments: $id('select-languages-comments-select').value,
  2267. // menuBgColor: $id('menu-bg-color-picker').value,
  2268. // menuTextColor: $id('menu-text-color-picker').value,
  2269. menu_developermdcm: {
  2270. bg: selectedBgColor,
  2271. color: selectedTextColor,
  2272. accent: selectedBgAccentColor
  2273. }
  2274. // menuFontSize: $id('menu-font-size-slider').value,
  2275. };
  2276. $sp('--yt-enhance-menu-bg', settings.menu_developermdcm.bg);
  2277. $sp('--yt-enhance-menu-text', settings.menu_developermdcm.color);
  2278. $sp('--yt-enhance-menu-accent', settings.menu_developermdcm.accent);
  2279. renderizarButtons();
  2280. $id('shareBtn-mdcm').addEventListener('click', function(event) {
  2281. event.stopPropagation();
  2282. const dropdown = $id('shareDropdown');
  2283. dropdown.style.display = dropdown.style.display === 'block' ? 'none' : 'block';
  2284. });
  2285. document.addEventListener('click', function(event) {
  2286. event.stopPropagation();
  2287. const dropdown = $id('shareDropdown');
  2288. const shareButton = $id('shareBtn-mdcm');
  2289. if (event.target !== shareButton) {
  2290. dropdown.style.display = 'none';
  2291. }
  2292. });
  2293.  
  2294. $id('importExportBtn').addEventListener('click', function() {
  2295. $id('importExportArea').classList.toggle('active');
  2296. });
  2297.  
  2298. $id('closeImportExportBtn').addEventListener('click', function() {
  2299. $id('importExportArea').classList.remove('active');
  2300. });
  2301.  
  2302.  
  2303. // Hide comments
  2304. const commentsSection = $id('comments');
  2305. if (commentsSection) {
  2306. commentsSection.style.display = settings.hideComments ? 'none' : 'block';
  2307. }
  2308. // Active inactive Themes
  2309. const themesMenuSection = $e('.themes-hidden');
  2310. if (themesMenuSection) {
  2311. themesMenuSection.style.display = settings.themes ? 'block' : 'none';
  2312. }
  2313.  
  2314. // Hide sidebar
  2315. const sidebarSection = $e('#secondary > #secondary-inner');
  2316. if (sidebarSection) {
  2317. sidebarSection.classList.add('side-moi');
  2318. const sidebarSection2 = $e('.side-moi');
  2319.  
  2320. sidebarSection2.style.display = settings.hideSidebar ? 'none' : 'block';
  2321. }
  2322.  
  2323. // Disable autoplay
  2324. const autoplayToggle = $e('.ytp-autonav-toggle-button');
  2325. if (autoplayToggle) {
  2326. const isCurrentlyOn =
  2327. autoplayToggle.getAttribute('aria-checked') === 'true';
  2328. if (settings.disableAutoplay && isCurrentlyOn) {
  2329. autoplayToggle.click();
  2330. } else if (!settings.disableAutoplay && !isCurrentlyOn) {
  2331. autoplayToggle.click();
  2332. }
  2333. }
  2334. // Disable subtitles
  2335. const subtitleToggle = $e('.ytp-subtitles-button');
  2336. if (subtitleToggle) {
  2337. const isCurrentlyOn =
  2338. subtitleToggle.getAttribute('aria-pressed') === 'true';
  2339. if (settings.disableSubtitles && isCurrentlyOn) {
  2340. subtitleToggle.click();
  2341. } else if (!settings.disableSubtitles && !isCurrentlyOn) {
  2342. subtitleToggle.click();
  2343. }
  2344. }
  2345. // Disable cinematicLighting
  2346. // const buttonSettingVideo = $e(".ytp-settings-button");
  2347. // if(buttonSettingVideo && !settings.cinematicLighting) {
  2348. // buttonSettingVideo.click();
  2349. // setTimeout(() => {
  2350. // buttonSettingVideo.click();
  2351. // },50)
  2352. // }
  2353.  
  2354. // Adjust font size
  2355. // $e('body').style.fontSize = `${settings.fontSize}px`;
  2356.  
  2357. // Adjust player size
  2358. const player = $e('video');
  2359. if (player) {
  2360. player.style.transform = `scale(${settings.playerSize / 100})`;
  2361. }
  2362.  
  2363. // selected video quality
  2364. const video = $e('div#movie_player');
  2365. let ytPlayerQuality = localStorage.getItem('yt-player-quality');
  2366. $m('#select-video-qualitys-select, #select-languages-comments-select').forEach(el => {
  2367. el.addEventListener('change', () => {
  2368. applySettings();
  2369. });
  2370. });
  2371. // $e('#select-languages-comments-select').addEventListener('change', () => {
  2372. // applySettings();
  2373. // })
  2374. if (video != undefined) {
  2375. if (ytPlayerQuality) {
  2376. let qualitySettings = JSON.parse(ytPlayerQuality);
  2377. qualitySettings.data = JSON.stringify({ quality: settings.selectVideoQuality, previousQuality: 240 });
  2378. localStorage.setItem('yt-player-quality', JSON.stringify(qualitySettings));
  2379. } else {
  2380. let defaultQualitySettings = {
  2381. data: JSON.stringify({ quality: 720, previousQuality: 240 }),
  2382. expiration: Date.now() + (365 * 24 * 60 * 60 * 1000),
  2383. creation: Date.now()
  2384. };
  2385. localStorage.setItem('yt-player-quality', JSON.stringify(defaultQualitySettings));
  2386. }
  2387. }
  2388.  
  2389. // Apply menu appearance settings
  2390. // $sp('--yt-enhance-menu-bg', settings.menuBgColor);
  2391. // $sp('--yt-enhance-menu-text', settings.menuTextColor);
  2392. // $sp('--yt-enhance-menu-font-size', `${settings.menuFontSize}px`);
  2393.  
  2394. // Apply theme
  2395. const selectedTheme = themes[settings.theme];
  2396. const isThemeCustom = $e(`input[name="theme"][value="custom"]`).checked;
  2397. const isThemeNormal = $e(`input[name="theme"][value="normal"]`).checked;
  2398. const themeCustomOptions = $e('.theme-custom-options');
  2399. const themeNormal = $e('.theme-selected-normal');
  2400. if(isThemeCustom != undefined) {
  2401. themeNormal.style.display = "flex"
  2402. themeCustomOptions.style.display = "flex";
  2403. $e('.themes-options').style.display = "none";
  2404. }
  2405. if(isThemeNormal) {
  2406. $e(`input[name="theme"][value="custom"]`).checked = false;
  2407. }
  2408.  
  2409.  
  2410.  
  2411.  
  2412. function checkDarkMode() {
  2413. if(settings.themes) {
  2414. if (isDarkModeActive === 'dark' && !isThemeCustom) {
  2415. // Apply theme
  2416. $e('.themes-options').style.display = "block";
  2417. themeNormal.style.display = "none";
  2418. themeCustomOptions.style.display = "none";
  2419.  
  2420. if(settings.theme === '0') {
  2421. GM_addStyle(`
  2422. .botones_div {
  2423. background-color: transparent;
  2424. border: none;
  2425. color: #ccc !important;
  2426. user-select: none;
  2427. }
  2428. `);
  2429. return;
  2430. }
  2431. $sp('--yt-spec-base-background', selectedTheme.gradient);
  2432. $sp('--yt-spec-text-primary', selectedTheme.textColor);
  2433. $sp('--yt-spec-text-secondary', selectedTheme.textColor);
  2434. $sp('--yt-spec-menu-background', selectedTheme.gradient);
  2435. $sp('--yt-spec-icon-inactive', selectedTheme.textColor);
  2436. $sp('--yt-spec-brand-icon-inactive', selectedTheme.textColor);
  2437. $sp('--yt-spec-brand-icon-active', selectedTheme.gradient);
  2438. $sp('--yt-spec-static-brand-red', selectedTheme.gradient); // line current time
  2439. $sp('--yt-spec-raised-background', selectedTheme.raised);
  2440. $sp('--yt-spec-static-brand-red', selectedTheme.CurrentProgressVideo);
  2441. $sp('--yt-spec-static-brand-white', selectedTheme.textColor);
  2442. $sp('--ytd-searchbox-background', selectedTheme.gradient);
  2443. $sp('--ytd-searchbox-text-color', selectedTheme.textColor);
  2444. $sp('--ytcp-text-primary', settings.textColor);
  2445. GM_addStyle(`
  2446. .botones_div {
  2447. background-color: transparent;
  2448. border: none;
  2449. color: #999999;
  2450. user-select: none;
  2451. }
  2452. .ytp-menuitem[aria-checked=true] .ytp-menuitem-toggle-checkbox {
  2453. background: ${selectedTheme.gradient} !important;
  2454. }
  2455. #background.ytd-masthead { background: ${selectedTheme.gradient} !important; }
  2456. .ytp-swatch-background-color {
  2457. background: ${
  2458. selectedTheme.gradient
  2459. } !important;
  2460. }
  2461. #shorts-container, #page-manager.ytd-app {
  2462. background: ${selectedTheme.gradient.replace(/(#[0-9a-fA-F]{6})/g, `$1${36}`)};
  2463. }
  2464. ytd-engagement-panel-title-header-renderer[shorts-panel] #header.ytd-engagement-panel-title-header-renderer {
  2465. background: ${selectedTheme.gradient} !important;}
  2466. .buttons-tranlate {
  2467. background: ${selectedTheme.btnTranslate} !important;
  2468. }
  2469. .badge-shape-wiz--thumbnail-default {
  2470. color: ${selectedTheme.videoDuration} !important;
  2471. background: ${selectedTheme.gradient} !important;
  2472. }
  2473. #logo-icon {
  2474. color: ${selectedTheme.textLogo} !important;
  2475. }
  2476. .yt-spec-button-shape-next--overlay.yt-spec-button-shape-next--text {
  2477. color: ${selectedTheme.iconsColor} !important;
  2478. }
  2479. .ytd-topbar-menu-button-renderer #button.ytd-topbar-menu-button-renderer {
  2480. color: ${selectedTheme.iconsColor} !important;
  2481. }
  2482. .yt-spec-icon-badge-shape--style-overlay .yt-spec-icon-badge-shape__icon {
  2483. color: ${selectedTheme.iconsColor} !important;
  2484. }
  2485. .ytp-svg-fill {
  2486. fill: ${selectedTheme.iconsColor} !important;
  2487. }
  2488. #ytp-id-30,#ytp-id-17,#ytp-id-19,#ytp-id-20{
  2489. fill: ${selectedTheme.iconsColor} !important;
  2490. }
  2491. `);
  2492. } else if(isDarkModeActive === 'dark' && isThemeCustom) {
  2493. $sp('--yt-spec-base-background', settings.bgColorPicker);
  2494. $sp('--yt-spec-text-primary', settings.primaryColorPicker);
  2495. $sp('--yt-spec-text-secondary', settings.secondaryColorPicker);
  2496. $sp('--yt-spec-menu-background', settings.menuColorPicker);
  2497. $sp('--yt-spec-icon-inactive', settings.iconsColorPicker);
  2498. $sp('--yt-spec-brand-icon-inactive', settings.primaryColorPicker);
  2499. $sp('--yt-spec-brand-icon-active', settings.primaryColorPicker);
  2500. $sp('--yt-spec-raised-background', settings.headerColorPicker);
  2501. $sp('--yt-spec-static-brand-red', settings.lineColorPicker);
  2502. $sp('--yt-spec-static-brand-white', settings.timeColorPicker);
  2503. $sp('--ytd-searchbox-background', settings.primaryColorPicker);
  2504. $sp('--ytd-searchbox-text-color', settings.secondaryColorPicker);
  2505. $sp('--ytcp-text-primary', settings.primaryColorPicker);
  2506. GM_addStyle(`
  2507. .html5-video-player {
  2508. color: ${settings.primaryColorPicker} !important;
  2509. }
  2510. .ytp-volume-slider-handle:before, .ytp-volume-slider-handle, .ytp-tooltip.ytp-preview:not(.ytp-text-detail) {
  2511. background-color: ${settings.iconsColorPicker} !important;
  2512. }
  2513. .ytp-autonav-toggle-button[aria-checked=true] {
  2514. background-color: ${settings.iconsColorPicker} !important;
  2515. }
  2516. .tp-yt-iron-icon {
  2517. fill: ${settings.iconsColorPicker} !important;
  2518. }
  2519. .botones_div {
  2520. background-color: transparent;
  2521. border: none;
  2522. color: ${settings.iconsColorPicker} !important;
  2523. user-select: none;
  2524. }
  2525. #container.ytd-searchbox {
  2526. color: red !important;
  2527. }
  2528. .ytp-menuitem[aria-checked=true] .ytp-menuitem-toggle-checkbox {
  2529. background: ${settings.primaryColorPicker} !important;
  2530. }
  2531. .yt-spec-icon-shape {
  2532. display: flex;
  2533. align-items: center;
  2534. justify-content: center;
  2535. width: 100%;
  2536. height: 100%;
  2537. color: ${settings.iconsColorPicker} !important;
  2538. }
  2539. .ytp-time-current, .ytp-time-separator, .ytp-time-duration {
  2540. color: ${settings.iconsColorPicker} !important;
  2541. }
  2542. #background.ytd-masthead { background: ${settings.headerColorPicker} !important; }
  2543. .ytp-swatch-background-color {
  2544. background: ${
  2545. settings.progressbarColorPicker
  2546. } !important;
  2547. }
  2548. #shorts-container, #page-manager.ytd-app {
  2549. background: ${settings.bgColorPicker}36;
  2550. }
  2551. ytd-engagement-panel-title-header-renderer[shorts-panel] #header.ytd-engagement-panel-title-header-renderer {
  2552. background: ${settings.bgColorPicker} !important;}
  2553. .badge-shape-wiz--thumbnail-default {
  2554. color: ${settings.timeColorPicker} !important;
  2555. background: ${settings.secondaryColor} !important;
  2556. }
  2557. #logo-icon {
  2558. color: ${settings.primaryColorPicker} !important;
  2559. }
  2560. .yt-spec-button-shape-next--overlay.yt-spec-button-shape-next--text {
  2561. color: ${settings.iconsColorPicker} !important;
  2562. }
  2563. .ytd-topbar-menu-button-renderer #button.ytd-topbar-menu-button-renderer {
  2564. color: ${settings.iconsColorPicker} !important;
  2565. }
  2566. .yt-spec-icon-badge-shape--style-overlay .yt-spec-icon-badge-shape__icon {
  2567. color: ${settings.iconsColorPicker} !important;
  2568. }
  2569. .ytp-svg-fill {
  2570. fill: ${settings.iconsColorPicker} !important;
  2571. }
  2572. #ytp-id-30,#ytp-id-17,#ytp-id-19,#ytp-id-20{
  2573. fill: ${settings.iconsColorPicker} !important;
  2574. }
  2575. `);
  2576. } else {
  2577. GM_addStyle(`
  2578. .botones_div {
  2579. background-color: transparent;
  2580. border: none;
  2581. color: #000 !important;
  2582. user-select: none;
  2583. }
  2584. `);
  2585. }
  2586. } else {
  2587. GM_addStyle(`
  2588. .botones_div {
  2589. background-color: transparent;
  2590. border: none;
  2591. color: #ccc !important;
  2592. user-select: none;
  2593. }
  2594. `);
  2595. }
  2596. }
  2597.  
  2598. GM_addStyle(`
  2599. #columns.style-scope.ytd-watch-flexy {
  2600. flex-direction: ${settings.reverseMode ? 'row-reverse' : 'row'} !important;
  2601. padding-left: ${settings.reverseMode ? '20px' : '0'} !important;
  2602. }
  2603. #secondary.style-scope.ytd-watch-flexy {display: ${settings.hideSidebar ? 'none' : 'block'} !important;}
  2604.  
  2605.  
  2606. #icon-menu-settings {
  2607. color: ${settings.iconsColorPicker} !important;
  2608. }
  2609. .ytp-chrome-bottom {
  2610. width: ${settings.hideSidebar ? '100%' : ''} !important;
  2611. ${settings.hideSidebar ? 'left: 0;' : ''}
  2612. }
  2613. .ytp-progress-bar-container {
  2614. left: ${settings.hideSidebar ? '4px' : ''} !important;
  2615. }
  2616. `);
  2617.  
  2618. checkDarkMode();
  2619.  
  2620. function checkForVideo() {
  2621. if(!settings.waveVisualizer) {
  2622. cleanup(false);
  2623. return;
  2624. }
  2625. const video = $e('video');
  2626. const miniPlayer = $e('.ytp-miniplayer-ui');
  2627. if ((video && document.location.href.includes('watch')) || miniPlayer) {
  2628. if (isFullscreen()) {
  2629. hideCanvas();
  2630. return;
  2631. }
  2632. if (video === currentVideo && isSetup) {
  2633. if (controlPanel && video.paused === false) {
  2634. showCanvas();
  2635. }
  2636. } else {
  2637. cleanup(true)
  2638. setupAudioAnalyzer(video);
  2639. }
  2640. }
  2641. }
  2642.  
  2643. // checkForVideo();
  2644. let currentUrl = window.location.href;
  2645. let urlCheckInterval = setInterval(function () {
  2646. if (window.location.href !== currentUrl) {
  2647. currentUrl = window.location.href;
  2648. checkUrlChange();
  2649. }
  2650. }, 1000);
  2651.  
  2652. function checkUrlChange() {
  2653. setTimeout(() => {
  2654. applySettings();
  2655. }, 1000);
  2656. clearInterval(urlCheckInterval);
  2657. }
  2658.  
  2659. function downloadDescriptionVideo() {
  2660. if ($e('#button_copy_description')) return;
  2661. const containerDescription = $e('#bottom-row.style-scope.ytd-watch-metadata');
  2662. if (!containerDescription) {
  2663. console.warn('No se encontró el contenedor de descripción. No se insertará el botón.');
  2664. return;
  2665. }
  2666. const buttomHTML = `
  2667. <div id="button_copy_description" style="display: flex; justify-content: end; align-items: center;margin-top: 10px;" >
  2668. <button id="copy-description" class="botones_div" type="button" style="cursor: pointer;">
  2669. <i style="font-size: 20px;" class="fa-solid fa-copy"></i>
  2670. </button>
  2671. </div>
  2672. `;
  2673. containerDescription.insertAdjacentHTML('beforebegin', buttomHTML);
  2674. $id('copy-description').addEventListener('click', () => {
  2675. const ldJson = [...document.querySelectorAll('script[type="application/ld+json"]')];
  2676. for (let script of ldJson) {
  2677. try {
  2678. const data = JSON.parse(script.innerText);
  2679. if (data['@type'] === 'VideoObject') {
  2680. const description =
  2681. `📅 Date published: ${data.uploadDate || 'No disponible'}\n` +
  2682. `Author: ${data.author || 'No disponible'}\n` +
  2683. `🎬 Name video: ${data.name || 'No disponible'}\n` +
  2684. `🖼️ Thumbnail: ${Array.isArray(data.thumbnailUrl) ? data.thumbnailUrl.join(', ') : data.thumbnailUrl || 'No disponible'}\n` +
  2685. `📝 Description: ${data.description || 'No disponible'}\n\n\n` +
  2686. `🎭 Category: ${data.genre || 'No disponible'}\n`;
  2687. navigator.clipboard.writeText(description);
  2688. }
  2689. } catch (e) {
  2690. Notify('error', 'Error parsing JSON-LD');
  2691. } finally {
  2692. Notify('success', 'Descripción copiada');
  2693. }
  2694. }
  2695. });
  2696. }
  2697. downloadDescriptionVideo();
  2698.  
  2699.  
  2700. async function traductor() {
  2701. const texto = $m('#content-text');
  2702. if ($e('.buttons-tranlate')) return;
  2703. const languages = languagesTranslate;
  2704. const idiomaDestino = $id('select-languages-comments-select').value;
  2705. for (let i = 0; i < texto.length; i++) {
  2706. const optionsHTML = Object.entries(languages)
  2707. .map(([code, name]) => {
  2708. const selected = code === idiomaDestino ? 'selected' : '';
  2709. return `<option value="${code}" ${selected}>${name}</option>`;
  2710. })
  2711. .join('');
  2712. const controlsHTML = `
  2713. <div class="traductor-container" data-index="${i}">
  2714. <button class="buttons-tranlate" id="btn${i}"> Translate <i class="fa-solid fa-language"></i></button>
  2715. <select class="select-traductor" id="select${i}">
  2716. ${optionsHTML}
  2717. </select>
  2718. </div>
  2719. `;
  2720. texto[i].insertAdjacentHTML('afterend', controlsHTML);
  2721. }
  2722. const botones = $m('.buttons-tranlate');
  2723. const selects = $m('.select-traductor');
  2724. botones.forEach((boton, i) => {
  2725. boton.addEventListener('click', () => {
  2726. const selectedLang = selects[i].value;
  2727. const urlLista = `?client=dict-chrome-ex&sl=auto&tl=${selectedLang}&q=` + texto[i].textContent;
  2728. fetch(apiGoogleTranslate + urlLista)
  2729. .then((response) => response.json())
  2730. .then((datos) => {
  2731. texto[i].textContent = datos[0][0];
  2732. botones[i].textContent = 'Translated';
  2733. })
  2734. .catch((err) => {
  2735. console.error('Error en la traducción:', err);
  2736. });
  2737. });
  2738. });
  2739. }
  2740.  
  2741. function limpiarHTML(selector) {
  2742. $m(selector).forEach((button) => button.remove());
  2743. }
  2744.  
  2745. function checkScroll () {
  2746. const avatars = $m('#author-thumbnail-button #img.style-scope.yt-img-shadow');
  2747. if (avatars.length > 0 && settings.avatars) {
  2748. limpiarHTML('.yt-image-avatar-download');
  2749. agregarBotonesDescarga();
  2750. }
  2751. const divEl = $e('#content-text');
  2752. const divEl2 = $e('ytd-item-section-renderer[static-comments-header] #contents');
  2753. if (settings.translation) {
  2754. if (divEl !== undefined || divEl2 !== undefined) {
  2755. limpiarHTML('.buttons-tranlate');
  2756. limpiarHTML('.select-traductor');
  2757. traductor();
  2758. }
  2759. }
  2760. }
  2761.  
  2762. window.onscroll = () => {
  2763. checkScroll();
  2764. }
  2765.  
  2766.  
  2767. const contentScrollable = $e('.anchored-panel.style-scope.ytd-shorts #contents.style-scope.ytd-item-section-renderer.style-scope.ytd-item-section-renderer');
  2768. if (contentScrollable) {
  2769. const observer = new IntersectionObserver((entries) => {
  2770. entries.forEach(entry => {
  2771. if (entry.isIntersecting) {
  2772. contentScrollable.addEventListener('scroll', () => {
  2773. checkScroll();
  2774. });
  2775. }
  2776. });
  2777. }, { threshold: 0.1 });
  2778. observer.observe(contentScrollable);
  2779. }
  2780. function agregarBotonesDescarga() {
  2781. const avatars = $m('#author-thumbnail-button #img.style-scope.yt-img-shadow');
  2782. avatars.forEach((img) => {
  2783. if (img.parentElement.querySelector('.yt-image-avatar-download')) return;
  2784. const button = $cl('button');
  2785. button.innerHTML = '<i class="fa fa-download"></i>';
  2786. button.classList.add('yt-image-avatar-download');
  2787. button.onclick = async function () {
  2788. try {
  2789. const imageUrl = img.src.split('=')[0];
  2790. const response = await fetch(imageUrl);
  2791. const blob = await response.blob();
  2792. const blobUrl = URL.createObjectURL(blob);
  2793. const parentComment = img.closest('ytd-comment-thread-renderer, ytd-comment-renderer');
  2794. const nameElement = parentComment?.querySelector('#author-text');
  2795. let authorName = nameElement ? nameElement.textContent.trim() : 'avatar';
  2796. authorName = authorName.replace(/[\/\\:*?"<>|]/g, '');
  2797. const link = $cl('a');
  2798. link.href = blobUrl;
  2799. link.download = `${authorName}_avatar.jpg` || 'avatar.jpg';
  2800. document.body.appendChild(link);
  2801. link.click();
  2802. document.body.removeChild(link);
  2803. URL.revokeObjectURL(blobUrl);
  2804. } catch (error) {
  2805. console.error('Error al descargar la imagen:', error);
  2806. }
  2807. };
  2808. img.parentElement.style.position = 'relative';
  2809. img.parentElement.appendChild(button);
  2810. });
  2811. }
  2812.  
  2813. const BUTTON_CLASS = 'custom-classic-btn';
  2814.  
  2815. const redirectToClassic = () => {
  2816. const videoId = window.location.pathname.split('/').pop();
  2817. const classicUrl = `https://www.youtube.com/watch?v=${videoId}`;
  2818. window.open(classicUrl, '_blank');
  2819. $e('video.video-stream.html5-main-video').pause();
  2820. };
  2821.  
  2822.  
  2823. const createButton = () => {
  2824. const button = $cl('button');
  2825. button.classList.add(BUTTON_CLASS);
  2826. button.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-screen-share"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M21 12v3a1 1 0 0 1 -1 1h-16a1 1 0 0 1 -1 -1v-10a1 1 0 0 1 1 -1h9" /><path d="M7 20l10 0" /><path d="M9 16l0 4" /><path d="M15 16l0 4" /><path d="M17 4h4v4" /><path d="M16 9l5 -5" /></svg>';
  2827. button.title = 'Classic mode';
  2828. button.onclick = redirectToClassic;
  2829. return button;
  2830. };
  2831.  
  2832. const insertButtons = () => {
  2833. const isShortsPage = document.location.pathname.startsWith('/shorts');
  2834.  
  2835. if (isShortsPage) {
  2836. $m('#actions').forEach(actionsContainer => {
  2837. if (!actionsContainer.querySelector(`.${BUTTON_CLASS}`)) {
  2838. actionsContainer.prepend(createButton());
  2839. }
  2840. });
  2841. } else {
  2842. $m(`.${BUTTON_CLASS}`).forEach(button => button.remove());
  2843. }
  2844. };
  2845.  
  2846. const observeDOM = () => {
  2847. const observer = new MutationObserver(() => {
  2848. insertButtons();
  2849. addIcon();
  2850. // obs.disconnect();
  2851. });
  2852. observer.observe(document.body, {
  2853. childList: true,
  2854. subtree: true
  2855. });
  2856. };
  2857.  
  2858. insertButtons();
  2859. observeDOM();
  2860.  
  2861.  
  2862. const targetNode = $e('body');
  2863.  
  2864. if (targetNode != undefined) {
  2865. const element = $e('ytd-item-section-renderer[static-comments-header] #contents');
  2866. if(element != undefined && settings.theme !== 'custom') {
  2867. const observerElementDom = (elem) => {
  2868. const observer = new IntersectionObserver(entries => {
  2869.  
  2870. if(entries[0].isIntersecting) {
  2871.  
  2872. element.style.background = `${selectedTheme.gradient ?? ''}`;
  2873. } else {return}
  2874. })
  2875.  
  2876. return observer.observe($e(`${elem}`))
  2877.  
  2878. }
  2879. observerElementDom('ytd-item-section-renderer[static-comments-header] #contents')
  2880. }
  2881. }
  2882. // Stats
  2883. function formatTime(seconds) {
  2884. if (isNaN(seconds)) return '0h 0m 0s';
  2885. seconds = Math.floor(seconds);
  2886. const h = Math.floor(seconds / 3600);
  2887. const m = Math.floor((seconds % 3600) / 60);
  2888. const s = seconds % 60;
  2889. return `${h}h ${m}m ${s}s`;
  2890. }
  2891.  
  2892. function updateUI() {
  2893. $id('total-time').textContent = formatTime(usageTime);
  2894. $id('video-time').textContent = formatTime(videoTime);
  2895. $id('shorts-time').textContent = formatTime(shortsTime);
  2896.  
  2897. const maxTime = 86400; // 24 hours
  2898. $id('usage-bar').style.width =
  2899. `${(usageTime / maxTime) * 100}%`;
  2900. $id('video-bar').style.width =
  2901. `${(videoTime / maxTime) * 100}%`;
  2902. $id('shorts-bar').style.width =
  2903. `${(shortsTime / maxTime) * 100}%`;
  2904. }
  2905.  
  2906. function detectContentType(videoElement) {
  2907. if (/\/shorts\//.test(window.location.pathname)) return 'shorts';
  2908. let parent = videoElement;
  2909. while ((parent = parent.parentElement) !== null) {
  2910. if (parent.classList.contains('shorts-container') ||
  2911. parent.classList.contains('reel-video') ||
  2912. parent.tagName === 'YTD-REEL-VIDEO-RENDERER') {
  2913. return 'shorts';
  2914. }
  2915. }
  2916.  
  2917. if (videoElement.closest('ytd-watch-flexy') ||
  2918. videoElement.closest('#primary-inner')) {
  2919. return 'video';
  2920. }
  2921. if (videoElement.closest('ytd-thumbnail') ||
  2922. videoElement.closest('ytd-rich-item-renderer')) {
  2923. return 'video';
  2924. }
  2925.  
  2926. return null;
  2927. }
  2928.  
  2929. function findActiveVideo() {
  2930. const videos = $m('video');
  2931. for (const video of videos) {
  2932. if (!video.paused && !video.ended && video.readyState > 2) {
  2933. return video;
  2934. }
  2935. }
  2936. return null;
  2937. }
  2938.  
  2939. function cleanup(fullCleanup = false) {
  2940. if (fullCleanup && animationId) {
  2941. cancelAnimationFrame(animationId);
  2942. animationId = null;
  2943. }
  2944. // Remueve los event listeners que afectan la UI
  2945. if (currentVideo) {
  2946. currentVideo.removeEventListener('play', showCanvas);
  2947. currentVideo.removeEventListener('pause', hideCanvas);
  2948. currentVideo.removeEventListener('ended', hideCanvas);
  2949. }
  2950. if (fullCleanup) {
  2951. // Remueve UI and disconnect from video
  2952. if (canvas && canvas.parentNode) {
  2953. canvas.parentNode.removeChild(canvas);
  2954. canvas = null;
  2955. ctx = null;
  2956. }
  2957. if (controlPanel && controlPanel.parentNode) {
  2958. controlPanel.parentNode.removeChild(controlPanel);
  2959. controlPanel = null;
  2960. }
  2961. if (source) {
  2962. try {
  2963. source.disconnect();
  2964. } catch (err) {
  2965. console.error("Error desconectando el source:", err);
  2966. }
  2967. source = null;
  2968. }
  2969. if (audioCtx) {
  2970. try {
  2971. audioCtx.close();
  2972. } catch (err) {
  2973. console.error("Error cerrando AudioContext:", err);
  2974. }
  2975. audioCtx = null;
  2976. }
  2977. if (currentVideo && currentVideo[PROCESSED_FLAG]) {
  2978. delete currentVideo[PROCESSED_FLAG];
  2979. }
  2980. currentVideo = null;
  2981. isSetup = false;
  2982. } else {
  2983. if (canvas) {
  2984. canvas.style.opacity = '0';
  2985. }
  2986. if (controlPanel) {
  2987. controlPanel.style.opacity = '0';
  2988. }
  2989. }
  2990. }
  2991.  
  2992. function createCanvasOverlay() {
  2993. if (canvas) return;
  2994. const parent = document.body;
  2995. canvas = document.createElement('canvas');
  2996. canvas.id = 'wave-visualizer-canvas';
  2997. canvas.width = window.innerWidth;
  2998. canvas.height = canvasHeight;
  2999. canvas.style.position = 'fixed';
  3000. canvas.style.left = '0';
  3001. canvas.style.top = '0';
  3002. canvas.style.width = '100%';
  3003. canvas.style.pointerEvents = 'none';
  3004. canvas.style.backgroundColor = 'transparent';
  3005. canvas.style.zIndex = '10000';
  3006. canvas.style.opacity = '0';
  3007. canvas.style.transition = 'opacity 0.3s';
  3008.  
  3009. parent.appendChild(canvas);
  3010. ctx = canvas.getContext('2d');
  3011. }
  3012. function createControlPanelWave() {
  3013. if (controlPanel) return;
  3014.  
  3015. controlPanel = $cl('div');
  3016. controlPanel.id = 'wave-visualizer-control';
  3017. const selectAppend = $id('select-wave-visualizer-select');
  3018. waveStyle = settings.waveVisualizerSelected;
  3019. selectAppend.addEventListener('change', (e) => {
  3020. waveStyle = e.target.value;
  3021. selectAppend.value = e.target.value;
  3022. saveSettings();
  3023. });
  3024.  
  3025. }
  3026.  
  3027.  
  3028. function showCanvas() {
  3029. const canvas = $id('wave-visualizer-canvas');
  3030. if (audioCtx && audioCtx.state === 'suspended') {
  3031. audioCtx.resume();
  3032. }
  3033. if (canvas) {
  3034. canvas.style.opacity = '1';
  3035. if (controlPanel) controlPanel.style.opacity = '1';
  3036. }
  3037. }
  3038.  
  3039. // setting Audio y Analyser
  3040. function setupAudioAnalyzer(video) {
  3041. if (video[PROCESSED_FLAG]) {
  3042. Notify('error', "This video already has a MediaElementSource, skipping setup");
  3043. return;
  3044. }
  3045. video[PROCESSED_FLAG] = true;
  3046. cleanup(false);
  3047. currentVideo = video;
  3048. createCanvasOverlay();
  3049. createControlPanelWave();
  3050. if (!audioCtx) {
  3051. const AudioContext = window.AudioContext || window.webkitAudioContext;
  3052. audioCtx = new AudioContext();
  3053. }
  3054. analyser = audioCtx.createAnalyser();
  3055. analyser.fftSize = 2048;
  3056. analyser.smoothingTimeConstant = 0.85;
  3057. bufferLength = analyser.fftSize;
  3058. dataArray = new Uint8Array(bufferLength);
  3059. smoothedData = new Array(bufferLength).fill(128);
  3060. try {
  3061. source = audioCtx.createMediaElementSource(video);
  3062. source.connect(analyser);
  3063. analyser.connect(audioCtx.destination);
  3064. } catch (e) {
  3065. Notify('error', "MediaElementSource or error:", e);
  3066. cleanup(true);
  3067. return setupAudioAnalyzer(video); // clean full
  3068. }
  3069. video.removeEventListener('play', showCanvas);
  3070. video.removeEventListener('pause', hideCanvas);
  3071. video.removeEventListener('ended', hideCanvas);
  3072.  
  3073. video.addEventListener('play', showCanvas);
  3074. video.addEventListener('pause', hideCanvas);
  3075. video.addEventListener('ended', hideCanvas);
  3076. const updateCanvasSize = () => {
  3077. if (canvas) {
  3078. canvas.width = window.innerWidth;
  3079. canvas.height = canvasHeight;
  3080. }
  3081. };
  3082.  
  3083. window.removeEventListener('resize', updateCanvasSize);
  3084. window.addEventListener('resize', updateCanvasSize);
  3085. draw();
  3086. isSetup = true;
  3087. }
  3088. function draw() {
  3089. animationId = requestAnimationFrame(draw);
  3090. if (parseFloat(canvas.style.opacity) <= 0) return;
  3091.  
  3092. analyser.getByteTimeDomainData(dataArray);
  3093. for (let i = 0; i < bufferLength; i++) {
  3094. smoothedData[i] += smoothingFactor * (dataArray[i] - smoothedData[i]);
  3095. }
  3096. ctx.clearRect(0, 0, canvas.width, canvas.height);
  3097. let sliceWidth = canvas.width / bufferLength;
  3098.  
  3099. switch(waveStyle) {
  3100. case 'linea': {
  3101. ctx.lineWidth = 2;
  3102. ctx.strokeStyle = 'lime';
  3103. ctx.beginPath();
  3104. let x = 0;
  3105. for (let i = 0; i < bufferLength; i++) {
  3106. let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
  3107. if (i === 0) ctx.moveTo(x, amplitude);
  3108. else ctx.lineTo(x, amplitude);
  3109. x += sliceWidth;
  3110. }
  3111. ctx.stroke();
  3112. break;
  3113. }
  3114. case 'barras': {
  3115. let x = 0;
  3116. for (let i = 0; i < bufferLength; i += 5) {
  3117. let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
  3118. ctx.fillStyle = 'cyan';
  3119. ctx.fillRect(x, 0, sliceWidth * 4, amplitude);
  3120. x += sliceWidth * 5;
  3121. }
  3122. break;
  3123. }
  3124. case 'curva': {
  3125. ctx.lineWidth = 2;
  3126. ctx.strokeStyle = 'yellow';
  3127. ctx.beginPath();
  3128. ctx.moveTo(0, Math.max(0, smoothedData[0] - 128) * scale);
  3129. for (let i = 0; i < bufferLength - 1; i++) {
  3130. let x0 = i * sliceWidth;
  3131. let x1 = (i + 1) * sliceWidth;
  3132. let y0 = Math.max(0, smoothedData[i] - 128) * scale;
  3133. let y1 = Math.max(0, smoothedData[i + 1] - 128) * scale;
  3134. let cp1x = x0 + sliceWidth / 3;
  3135. let cp1y = y0;
  3136. let cp2x = x1 - sliceWidth / 3;
  3137. let cp2y = y1;
  3138. ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x1, y1);
  3139. }
  3140. ctx.stroke();
  3141. break;
  3142. }
  3143. case 'picos': {
  3144. ctx.fillStyle = 'magenta';
  3145. let x = 0;
  3146. for (let i = 0; i < bufferLength; i += 5) {
  3147. let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
  3148. ctx.beginPath();
  3149. ctx.arc(x, amplitude, 2, 0, Math.PI * 2);
  3150. ctx.fill();
  3151. x += sliceWidth * 5;
  3152. }
  3153. break;
  3154. }
  3155. case 'solida': {
  3156. ctx.beginPath();
  3157. let x = 0;
  3158. ctx.moveTo(0, 0);
  3159. for (let i = 0; i < bufferLength; i++) {
  3160. let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
  3161. ctx.lineTo(x, amplitude);
  3162. x += sliceWidth;
  3163. }
  3164. ctx.lineTo(canvas.width, 0);
  3165. ctx.closePath();
  3166. ctx.fillStyle = 'rgba(0,255,0,0.3)';
  3167. ctx.fill();
  3168. break;
  3169. }
  3170. case 'dinamica': {
  3171. let gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  3172. gradient.addColorStop(0, 'red');
  3173. gradient.addColorStop(0.5, 'purple');
  3174. gradient.addColorStop(1, 'blue');
  3175. ctx.lineWidth = 3;
  3176. ctx.strokeStyle = gradient;
  3177. ctx.beginPath();
  3178. let x = 0;
  3179. for (let i = 0; i < bufferLength; i++) {
  3180. let amplitude = Math.max(0, smoothedData[i] - 128) * scale;
  3181. if (i === 0) ctx.moveTo(x, amplitude);
  3182. else ctx.lineTo(x, amplitude);
  3183. x += sliceWidth;
  3184. }
  3185. ctx.stroke();
  3186. break;
  3187. }
  3188. case 'montana': {
  3189. ctx.beginPath();
  3190. let x = 0;
  3191. ctx.moveTo(0, 0);
  3192. for (let i = 0; i < bufferLength; i++) {
  3193. let amp = (smoothedData[i] - 128) * scale * 0.8;
  3194. ctx.lineTo(x, amp);
  3195. x += sliceWidth;
  3196. }
  3197. ctx.lineTo(canvas.width, 0);
  3198. ctx.closePath();
  3199. ctx.fillStyle = 'rgba(128,128,255,0.4)';
  3200. ctx.fill();
  3201. break;
  3202. }
  3203. default:
  3204. break;
  3205. }
  3206. }
  3207.  
  3208. const observer = new MutationObserver(() => {
  3209. const newVideo = findActiveVideo();
  3210. if (newVideo !== activeVideo) {
  3211. activeVideo = newVideo;
  3212. if (activeVideo) {
  3213. activeType = detectContentType(activeVideo);
  3214. }
  3215. }
  3216. });
  3217.  
  3218. checkForVideo();
  3219. setInterval(() => {
  3220. const now = Date.now();
  3221. // checkForVideo();
  3222. const delta = (now - lastUpdate) / 1000;
  3223. if (document.visibilityState === 'visible') {
  3224. usageTime += delta;
  3225. }
  3226. if (activeVideo && !activeVideo.paused) {
  3227. if (activeType === 'video') {
  3228. videoTime += delta;
  3229. } else if (activeType === 'shorts') {
  3230. shortsTime += delta;
  3231. }
  3232. }
  3233. lastUpdate = now;
  3234. // save stats
  3235. GM_setValue(STORAGE.USAGE, usageTime);
  3236. GM_setValue(STORAGE.VIDEO, videoTime);
  3237. GM_setValue(STORAGE.SHORTS, shortsTime);
  3238. updateUI();
  3239. }, UPDATE_INTERVAL);
  3240.  
  3241.  
  3242.  
  3243.  
  3244.  
  3245.  
  3246. observer.observe(document.body, {
  3247. childList: true,
  3248. subtree: true,
  3249. attributes: true
  3250. });
  3251. updateUI();
  3252.  
  3253. // end stats
  3254. saveSettings();
  3255. }
  3256.  
  3257. let validoBotones = true;
  3258. function renderizarButtons() {
  3259. const addButton = $e('.style-scope .ytd-watch-metadata');
  3260. const addButton2 = $e('#contents');
  3261.  
  3262. if (addButton != undefined && validoBotones) {
  3263. validoBotones = false;
  3264. const isVisible = !!(
  3265. addButton.offsetWidth ||
  3266. addButton.offsetHeight ||
  3267. addButton.getClientRects().length
  3268. );
  3269. if (isVisible) {
  3270. addButton.insertAdjacentHTML("beforebegin", menuBotones);
  3271. } else if (addButton2 != undefined) {
  3272. addButton.insertAdjacentHTML("beforebegin", menuBotones);
  3273. }
  3274. }
  3275.  
  3276. const formulariodescarga = $e('.formulariodescarga');
  3277. const formulariodescargaaudio = $e('.formulariodescargaaudio');
  3278. const framedescarga = $e('#descargando');
  3279. const framedescargamp3 = $e('#descargandomp3');
  3280. const btn1mp4 = $e('.btn1');
  3281. const btn2mp3 = $e('.btn2');
  3282. const btn3cancel = $e('.btn3');
  3283. const selectcalidades = $e('.selectcalidades');
  3284. const selectcalidadesaudio = $e('.selectcalidadesaudio');
  3285.  
  3286. [formulariodescarga, formulariodescargaaudio].forEach(form =>
  3287. form?.addEventListener('click', e => e.preventDefault())
  3288. );
  3289. selectcalidades?.addEventListener('change', e => {
  3290. framedescarga.src = `https://loader.to/api/button/?url=${window.location.href}&f=${e.target.value}&color=0af`;
  3291. framedescarga.classList.remove('ocultarframe');
  3292. });
  3293. selectcalidadesaudio?.addEventListener('change', e => {
  3294. framedescargamp3.src = `https://loader.to/api/button/?url=${window.location.href}&f=${e.target.value}&color=049c16`;
  3295. framedescargamp3.classList.remove('ocultarframeaudio');
  3296. });
  3297. btn3cancel?.addEventListener('click', () => {
  3298. formulariodescarga.style.display = 'none';
  3299. formulariodescargaaudio.style.display = 'none';
  3300. });
  3301. btn1mp4?.addEventListener('click', () => {
  3302. selectcalidades?.classList.remove('ocultarframe');
  3303. framedescarga?.classList.add('ocultarframe');
  3304. formulariodescarga?.classList.remove('ocultarframe');
  3305. formulariodescarga.style.display = '';
  3306. selectcalidadesaudio?.classList.add('ocultarframeaudio');
  3307. formulariodescargaaudio?.classList.add('ocultarframe');
  3308. formulariodescarga?.reset();
  3309. });
  3310. btn2mp3?.addEventListener('click', () => {
  3311. formulariodescargaaudio?.classList.remove('ocultarframe');
  3312. formulariodescarga?.classList.add('ocultarframe');
  3313. framedescargamp3?.classList.remove('ocultarframeaudio');
  3314. formulariodescargaaudio.style.display = '';
  3315. selectcalidadesaudio?.classList.remove('ocultarframeaudio');
  3316. framedescargamp3?.classList.add('ocultarframeaudio');
  3317. formulariodescargaaudio?.reset();
  3318. });
  3319. // Invertir contenido
  3320.  
  3321. // const background_image = $e('#background_image');
  3322. // const color_bg = $e('#color_bg');
  3323. // const alertShown = localStorage.getItem('alertShown');
  3324. // const alertShownBg = localStorage.getItem('alertShownBg');
  3325. // if (!alertShown) {
  3326. // color_bg.addEventListener('change', () => {
  3327. // alert('disable cinematic mode in the video');
  3328. // localStorage.setItem('alertShown', true);
  3329. // });
  3330. // }
  3331. // if (!alertShownBg) {
  3332. // background_image.addEventListener('input', () => {
  3333. // alert('disable cinematic mode in the video');
  3334. // localStorage.setItem('alertShownBg', true);
  3335. // });
  3336. // }
  3337.  
  3338.  
  3339.  
  3340. const btnImagen = $e('#imagen');
  3341. const formularioButtons = $e('#eyes');
  3342. function initClickEvent() {
  3343. const bufferVideo = $e('.buffer_video');
  3344. if (!bufferVideo) {
  3345. return;
  3346. }
  3347. // Evita duplicar el evento
  3348. if (!bufferVideo.dataset.listenerAdded) {
  3349. bufferVideo.addEventListener("click", () => {
  3350. const video = $e("video.video-stream.html5-main-video");
  3351. if (!video) {
  3352. console.log("No se encontró el video en la página.");
  3353. return;
  3354. }
  3355. const event = new MouseEvent("contextmenu", {
  3356. bubbles: true,
  3357. cancelable: true
  3358. });
  3359. video.dispatchEvent(event);
  3360. setTimeout(() => {
  3361. const option = $e("body > div.ytp-popup.ytp-contextmenu > div > div > div:nth-child(7)");
  3362. if (option) {
  3363. option.click();
  3364. } else {
  3365. console.log("Opción no encontrada, intenta aumentar el tiempo de espera.");
  3366. }
  3367. }, 1000);
  3368. });
  3369. bufferVideo.dataset.listenerAdded = "true";
  3370. }
  3371. }
  3372. setInterval(initClickEvent, 2000);
  3373.  
  3374. // valido modo oscuro y venta de video
  3375. // Repeat video button
  3376. let countRepeat = 0; // count
  3377. const repeat = $e('#repeatvideo'); // Repeat button
  3378. const imarepeat = $e('.icon-tabler-repeat'); // img repeat
  3379. const videoFull = $e(
  3380. '#movie_player > div.html5-video-container > video'
  3381. );
  3382. if(repeat != undefined) {
  3383.  
  3384. repeat.onclick = () => {
  3385. if (
  3386. $e('#cinematics > div') != undefined ||
  3387. videoFull != undefined
  3388. ) {
  3389. countRepeat += 1;
  3390. setInterval(() => {
  3391. switch (countRepeat) {
  3392. case 1:
  3393. document
  3394. .querySelector(
  3395. '#movie_player > div.html5-video-container > video'
  3396. )
  3397. .setAttribute('loop', 'true');
  3398. imarepeat.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat-off" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
  3399. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  3400. <path d="M4 12v-3c0 -1.336 .873 -2.468 2.08 -2.856m3.92 -.144h10m-3 -3l3 3l-3 3"></path>
  3401. <path d="M20 12v3a3 3 0 0 1 -.133 .886m-1.99 1.984a3 3 0 0 1 -.877 .13h-13m3 3l-3 -3l3 -3"></path>
  3402. <path d="M3 3l18 18"></path>
  3403. </svg> `; // img repeat
  3404. break;
  3405. case 2:
  3406. countRepeat = 0;
  3407. document
  3408. .querySelector(
  3409. '#movie_player > div.html5-video-container > video'
  3410. )
  3411. .removeAttribute('loop');
  3412. imarepeat.innerHTML = ` <svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-repeat" width="24"
  3413. height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none"
  3414. stroke-linecap="round" stroke-linejoin="round">
  3415. <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
  3416. <path d="M4 12v-3a3 3 0 0 1 3 -3h13m-3 -3l3 3l-3 3"></path>
  3417. <path d="M20 12v3a3 3 0 0 1 -3 3h-13m3 3l-3 -3l3 -3"></path>
  3418. </svg>`;
  3419. break;
  3420. }
  3421. }, 1000);
  3422. }
  3423. }
  3424. }
  3425.  
  3426. // Background transparent
  3427.  
  3428. const cinematica = $e('#cinematics > div');
  3429. if (cinematica != undefined) {
  3430. cinematica.style =
  3431. 'position: fixed; inset: 0px; pointer-events: none; transform: scale(1.5, 2)';
  3432. }
  3433. const btnReset = $e('#reset_button'); // Reset button
  3434. if (btnReset != undefined) {
  3435. btnReset.addEventListener('click', function () {
  3436. if (localStorage.getItem('colores') != null) {
  3437. localStorage.removeItem('colores');
  3438. $e('#ojosprotect').style.backgroundColor =
  3439. 'transparent';
  3440. setTimeout(() => {
  3441. location.reload();
  3442. }, 400);
  3443. }
  3444. });
  3445. }
  3446.  
  3447. if (btnImagen != undefined) {
  3448. btnImagen.onclick = () => {
  3449. if (
  3450. $e('#cinematics > div') != undefined ||
  3451. videoFull != undefined
  3452. ) {
  3453. const parametrosURL = new URLSearchParams(window.location.search);
  3454. let enlace = parametrosURL.get('v');
  3455. const imageUrl = `https://i.ytimg.com/vi/${enlace}/maxresdefault.jpg`;
  3456. fetch(imageUrl)
  3457. .then((response) => {
  3458. if (!response.ok) {
  3459. throw new Error(`HTTP error! Status: ${response.status}`);
  3460. }
  3461. return response.blob();
  3462. })
  3463. .then((blob) => {
  3464. const imageSizeKB = blob.size / 1024;
  3465. if (imageSizeKB >= 20) {
  3466. window.open(
  3467. `https://i.ytimg.com/vi/${enlace}/maxresdefault.jpg`,
  3468. 'popUpWindow',
  3469. 'height=500,width=400,left=100,top=100,resizable=yes,scrollbars=yes,toolbar=yes,menubar=no,location=no,directories=no, status=yes'
  3470. );
  3471. const imageUrlObject = URL.createObjectURL(blob);
  3472. const enlaceDescarga = $cl('a');
  3473. enlaceDescarga.href = imageUrlObject;
  3474. const titleVideo = $e(
  3475. 'h1.style-scope.ytd-watch-metadata'
  3476. ).innerText;
  3477. enlaceDescarga.download = `${titleVideo}_maxresdefault.jpg`;
  3478. enlaceDescarga.click();
  3479. URL.revokeObjectURL(imageUrlObject);
  3480. } else {
  3481. console.log(
  3482. 'La imagen no excede los 20 KB. No se descargará.'
  3483. );
  3484. }
  3485. })
  3486. .catch((error) => {
  3487. alert('No found image');
  3488. console.error('Error al obtener la imagen:', error);
  3489. });
  3490. }
  3491. };
  3492. }
  3493. // for background image file photo higt quality
  3494. // const fileInput = $id('background_image');
  3495. // const backgroundDiv = $e('ytd-app');
  3496.  
  3497. // const storedImage = localStorage.getItem('backgroundImage');
  3498. // if (storedImage) {
  3499. // backgroundDiv.style = `background-size: contain; background-repeat: repeat; background-image: url(${storedImage}) !important`;
  3500. // }
  3501.  
  3502. // fileInput.addEventListener('change', (event) => {
  3503. // const file = event.target.files[0];
  3504. // if (file) {
  3505. // const reader = new FileReader();
  3506. // reader.onload = function (e) {
  3507. // const imageUrl = e.target.result;
  3508. // localStorage.setItem('backgroundImage', imageUrl);
  3509. // backgroundDiv.style.backgroundImage = `url(${imageUrl})`;
  3510. // };
  3511. // reader.readAsDataURL(file);
  3512. // }
  3513. // });
  3514.  
  3515.  
  3516. const externalLink = $e('.external_link');
  3517. if (externalLink != undefined) {
  3518. externalLink.onclick = () => {
  3519. const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
  3520. let enlace;
  3521. enlace = parametrosURL.get('v');
  3522. window.open(
  3523. `https://www.y2mate.com/es/convert-youtube/${enlace}`,
  3524. 'popUpWindow',
  3525. 'height=800,width=1000,left=50%,top=100,resizable=no,scrollbars=yes,toolbar=no,menubar=yes,location=no,directories=yes, status=no'
  3526. );
  3527. };
  3528. }
  3529. const viewExternalLink = $e('.view_external_link');
  3530. if (viewExternalLink != undefined) {
  3531. viewExternalLink.onclick = () => {
  3532. $e('video').click();
  3533. const parametrosURL = new URLSearchParams(window.location.search); // Url parametros
  3534. let enlace;
  3535. enlace = parametrosURL.get('v');
  3536. window.open(
  3537. `https://www.youtube.com/embed/${enlace}?rel=0&controls=2&color=white&iv_load_policy=3&showinfo=0&modestbranding=1&autoplay=1`
  3538. );
  3539. };
  3540. }
  3541. const viewPictureToPicture = $e(
  3542. '.video_picture_to_picture'
  3543. );
  3544. if (viewPictureToPicture != undefined) {
  3545. viewPictureToPicture.onclick = () => {
  3546. const video = $e('video');
  3547. if ('pictureInPictureEnabled' in document) {
  3548. if (!document.pictureInPictureElement) {
  3549. video
  3550. .requestPictureInPicture()
  3551. .then(() => {
  3552. })
  3553. .catch((error) => {
  3554. console.error(
  3555. 'Error al activar el modo Picture-in-Picture:',
  3556. error
  3557. );
  3558. });
  3559. } else {
  3560. // video picture
  3561. }
  3562. } else {
  3563. alert('Picture-in-Picture not supported');
  3564. }
  3565. };
  3566.  
  3567. // Filtro de pantalla
  3568. if (formularioButtons != undefined) {
  3569. formularioButtons.addEventListener('input', function () {
  3570. if (
  3571. $e('#cinematics > div') != undefined ||
  3572. videoFull != undefined
  3573. ) {
  3574. $e('#ojosprotect').style.backgroundColor =
  3575. formularioButtons.value;
  3576. }
  3577. });
  3578. }
  3579. clearInterval(renderizarButtons);
  3580. }
  3581.  
  3582. const checked_updates = $e('.checked_updates');
  3583.  
  3584. if (checked_updates != undefined) {
  3585. checked_updates.onclick = () => {
  3586. window.open(
  3587. `https://update.greatest.deepsurf.us/scripts/460680/Youtube%20Tools%20All%20in%20one%20local%20download%20mp3%20mp4%20HIGT%20QUALITY%20return%20dislikes%20and%20more.user.js`
  3588. );
  3589. };
  3590. }
  3591.  
  3592. const screenShotVideo = $e('.screenshot_video');
  3593. if (screenShotVideo != undefined) {
  3594. screenShotVideo.onclick = () => {
  3595. const video = $e('video');
  3596. const canvas = $cl('canvas');
  3597. canvas.width = video.videoWidth;
  3598. canvas.height = video.videoHeight;
  3599. const context = canvas.getContext('2d');
  3600. context.drawImage(video, 0, 0, canvas.width, canvas.height);
  3601. const imagenURL = canvas.toDataURL('image/png');
  3602. const enlaceDescarga = $cl('a');
  3603. enlaceDescarga.href = imagenURL;
  3604. const titleVideo = $e(
  3605. 'h1.style-scope.ytd-watch-metadata'
  3606. ).innerText;
  3607. enlaceDescarga.download = `${video.currentTime.toFixed(
  3608. 0
  3609. )}s_${titleVideo}.png`;
  3610. enlaceDescarga.click();
  3611. };
  3612. } else {
  3613. const containerButtons = $e('.containerButtons');
  3614.  
  3615. if (containerButtons != undefined) {
  3616. containerButtons.innerHTML = '';
  3617. }
  3618. }
  3619. clearInterval(renderizarButtons);
  3620. }
  3621.  
  3622.  
  3623.  
  3624.  
  3625. console.log('Script en ejecución by: DeveloperMDCM');
  3626. const HEADER_STYLE = 'color: #F00; font-size: 24px; font-family: sans-serif;';
  3627. const MESSAGE_STYLE = 'color: #00aaff; font-size: 16px; font-family: sans-serif;';
  3628. const CODE_STYLE = 'font-size: 14px; font-family: monospace;';
  3629.  
  3630. console.log(
  3631. '%cYoutube Tools Extension NEW UI\n' +
  3632. '%cRun %c(v2.3.4.2)\n' +
  3633. 'By: DeveloperMDCM.',
  3634. HEADER_STYLE,
  3635. CODE_STYLE,
  3636. MESSAGE_STYLE
  3637. );
  3638.  
  3639. if (!localStorage.getItem('notification-developerMDCM')) {
  3640. Notify('info', 'Youtube Tools by: DeveloperMDCM :)');
  3641. localStorage.setItem('notification-developerMDCM', true);
  3642. }
  3643.  
  3644.  
  3645.  
  3646.  
  3647.  
  3648.  
  3649. // Add event listeners to all inputs
  3650. const inputs = $m('input');
  3651. inputs.forEach((input) => {
  3652. input.addEventListener('change', applySettings);
  3653. if (input.type === 'range') {
  3654. input.addEventListener('change', () => {
  3655. updateSliderValues();
  3656. applySettings();
  3657. });
  3658. }
  3659. });
  3660.  
  3661. // Export configuration
  3662.  
  3663. // Settings saved
  3664. // const settings = GM_getValue('ytSettingsMDCM', '{}');
  3665. // $id('config-data').value = settings;
  3666.  
  3667. $id('export-config').addEventListener('click', () => {
  3668. const settings = GM_getValue('ytSettingsMDCM', '{}');
  3669. $id('config-data').value = settings;
  3670. const configData = settings;
  3671. try {
  3672. JSON.parse(configData); // Validate JSON
  3673. GM_setValue('ytSettingsMDCM', configData);
  3674. setTimeout(() => {
  3675. Notify('success', 'Configuration export successfully!');
  3676. }, 1000);
  3677. } catch (e) {
  3678. Notify('error', 'Invalid configuration data. Please check and try again.');
  3679. }
  3680. });
  3681. // Import configuration
  3682. $id('import-config').addEventListener('click', () => {
  3683. const configData = $id('config-data').value;
  3684. try {
  3685. JSON.parse(configData); // Validate JSON
  3686. GM_setValue('ytSettingsMDCM', configData);
  3687. setTimeout(() => {
  3688. Notify('success', 'Configuration imported successfully!');
  3689. window.location.reload();
  3690. }, 1000);
  3691. window.location.reload();
  3692. } catch (e) {
  3693. Notify('error', 'Invalid configuration data. Please check and try again.');
  3694. }
  3695. });
  3696. panel.style.display = 'none';
  3697.  
  3698. // var for wave
  3699. let currentVideo = null;
  3700. let waveStyle = 'dinamica';
  3701. let audioCtx = null;
  3702. let analyser = null;
  3703. let source = null;
  3704. let animationId = null;
  3705. let canvas = null;
  3706. let ctx = null;
  3707. let controlPanel = null;
  3708. let bufferLength = 0;
  3709. let dataArray = null;
  3710. let smoothedData = [];
  3711. let isSetup = false;
  3712. const smoothingFactor = 0.05;
  3713. const canvasHeight = 240;
  3714. const scale = canvasHeight / 90;
  3715. const PROCESSED_FLAG = 'wave_visualizer_processed';
  3716. // Load saved settings
  3717. // Visible element DOM
  3718. function checkElement(selector, callback) {
  3719. const interval = setInterval(() => {
  3720. if ($e(selector)) {
  3721. clearInterval(interval);
  3722. callback();
  3723. }
  3724. }, 100);
  3725. }
  3726.  
  3727. const checkActiveWave = $id('wave-visualizer-toggle');
  3728. checkActiveWave.addEventListener('change', () => {
  3729. const waveVisualizer = $e('#wave-visualizer-toggle');
  3730. if (waveVisualizer.checked) {
  3731. Notify('success', 'Wave visualizer enabled');
  3732. } else {
  3733. hideCanvas();
  3734. Notify('success', 'Wave visualizer disabled realod page');
  3735. setTimeout(() => {
  3736. window.location.reload();
  3737. }, 1000);
  3738. }
  3739. });
  3740.  
  3741. checkElement('ytd-topbar-menu-button-renderer', loadSettings);
  3742. // validate change url SPA youtube
  3743. document.addEventListener('yt-navigate-finish', () => {
  3744. if (!document.location.href.includes('watch')) {
  3745. hideCanvas();
  3746. }
  3747. });
  3748. })();