NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name My Video (Web Video Player) // @namespace https://openuserjs.org/users/XDHx86/scripts // @version 1.6.5 // @description Custom video player with custom UI and shortcuts, EVERYTHING is customizable. Works on facebook, youtube and almost all websites. // @icon https://visualpharm.com/assets/563/Clapperboard-595b40b75ba036ed117d5939.svg // @author XDHx86 // @copyright 2020, XDHx86 (https://openuserjs.org/users/XDHx86) // @license MIT // @downloadURL https://openuserjs.org/install/XDHx86/My_Video_(Web_Video_Player).js // @updateURL https://openuserjs.org/meta/XDHx86/My_Video_(Web_Video_Player).meta.js // @exclude https://www.youtube.com/live_chat* // @match http*://*/* // @match file://*/*.avi // @match file://*/*.mkv // @match file://*/*.m4v // @match file://*/*.flv // @match file://*/*.divx // @match file://*/*.mpeg // @match file://*/*.webm // @match file://*/*.mp4 // @match file://*/*.wmv // @match file://*/*.mov // @match file://*/*.ogv // @match file://*/*.ogm // @match file://*/*.ogx // @connect www.y2mate.com // @connect fbdown.net // @grant GM_setValue // @grant GM_listValues // @grant GM_getValue // @grant GM_download // @grant GM_addStyle // @grant GM_notification // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @grant GM_xmlhttpRequest // ==/UserScript== (function() { 'use strict'; { let version = GM_getValue('scriptversion', ''); if (!version || version != GM_info.script.version) { GM_setValue('scriptversion', GM_info.script.version); window.open('https://openuserjs.org/scripts/XDHx86/My_Video_(Web_Video_Player)#changelog', '_blank'); } } Object.defineProperty(Object.prototype, 'MV_search', { value: function(value, options) { let output = { found: false }, altv, checkit = (inp, opt) => { let output = false; if (opt) { if (opt instanceof RegExp && opt.test(inp)) output = true; else if (typeof opt == 'string' && inp && inp.includes && inp.includes(value)) output = true; } else if (inp == value) output = true; return output; }; if (Array.isArray(this)) { for (let i = 0; i < this.length; i++) { if (typeof this[i] == 'object') { let obj = this[i]; for (let w in obj) { if (checkit(obj[w], options)) { output = { found: true, obj: obj, child: w, index: i, value: obj[w] }; break; } } if (output.found) break; } else if (Array.isArray(this[i])) { let arr = this[i]; for (let j = 0; j < arr.length; j++) { if (checkit(arr[j], options)) { output = { found: true, array: arr, index: j, parentindex: i, value: arr[j] }; break; } } if (output.found) break; } else if (checkit(this[i], options)) { output = { found: true, array: this, index: i, value: this[i] }; break; } } } else { for (let e in this) { if (typeof this[e] == 'object') { let obj = this[e]; for (let w in obj) { if (checkit(obj[w], options)) { output = { found: true, obj: obj, sub: w, child: e, value: obj[w]}; break; } } if (output.found) break; } else if (Array.isArray(this[e])) { let arr = this[e]; for (let i = 0; i < arr.length; i++) { if (checkit(arr[i])) { output = { found: true, array: arr, index: i, child: e, value: arr[i] }; break; } } if (output.found) break; } else if (checkit(this[e], options)) { output = { found: true, obj: this, child: e, value: this[e] }; break; } } } return output; }, enumerable: false }); Object.defineProperty(Object.prototype, 'MV_deepSearch', { value: function(value) { let output = { found: false }, search; if (Array.isArray(this)) { for (let i = 0; i < this.length; i++) { if (this[i] == value) { output = { found: true, array: this, index: i }; break; } else if (typeof this[i] == 'object' || Array.isArray(this[i])) { if (this[i]) search = this[i].MV_deepSearch(value); if (search && search.found) { output = search; output.parentindex = i; output.child = i; break; } } } } else if (typeof this == 'object') { for (let e in this) { if (this[e] == value) { output = { found: true, obj: this, sub: e }; break; } else if (typeof this[e] == 'object' || Array.isArray(this[e])) { if (this[e]) search = this[e].MV_deepSearch(value); if (search && search.found) { output = search; output.child = e; output.index = e; break; } } } } return output; }, enumerable: false }); Object.defineProperty(Object.prototype, 'MV_hasClass', { value: function(classes) { let output = false; if (!this.classList) return output; if (!Array.isArray(classes)) classes = [classes]; for (let i = 0; i < classes.length; i++) if (this.classList.contains(classes[i])) output = true; return output; }, enumerable: false }); String.prototype.MV_includes = function(arr) { let output = false; for (let i = 0; i < arr.length; i++) if (this.includes(arr[i])) output = true; return output; } String.prototype.MV_getName = function() { let output, res = this.split('/').MV_search('', /\.(avi|mkv|flv|divx|mpe?g|webm|mp4|wmv|mov|ogv|ogm|ogx)/); if (res.found) { let newr = res.value.split(/\.(avi|mkv|flv|divx|mpe?g|webm|mp4|wmv|mov|ogv|ogm|ogx)/); newr.pop(); output = newr.join('.'); } return output; } Number.prototype.MV_format = String.prototype.MV_format = function() { let time = parseFloat(this), sec = '00', hour = '00', min = '00'; if (time >= 0 && time < 60) { sec = Math.floor(time); } else if (time >= 60 && time < 3600) { min = (time / 60); sec = ((min % 1) * 60); } else if (time >= 3600) { hour = (time / 3600); min = ((hour % 1) * 60); sec = ((min % 1) * 60); } if (hour < 10) hour = '0' + Math.floor(hour); else hour = Math.floor(hour); if (min < 10) min = '0' + Math.floor(min); else min = Math.floor(min); if (sec < 10) sec = '0' + Math.floor(sec); else sec = Math.floor(sec); return hour + ':' + min + ':' + sec; } if (GM_getValue('firsttime', true)) { GM_setValue('play', 'KeyK'); GM_setValue('stop', 'KeyS'); GM_setValue('volplus', 'ArrowUp'); GM_setValue('volminus', 'ArrowDown'); GM_setValue('volstep', 0.05); GM_setValue('mute', 'KeyM'); GM_setValue('smallback', 'Comma'); GM_setValue('smallforward', 'Period'); GM_setValue('smallstep', 3); GM_setValue('bigback', 'KeyJ'); GM_setValue('bigforward', 'KeyL'); GM_setValue('bigstep', 30); GM_setValue('incplayback', 'KeyT'); GM_setValue('decplayback', 'KeyY'); GM_setValue('playbackstep', 0.1); GM_setValue('resplayback', 'KeyR'); GM_setValue('fullscreen', 'KeyF'); GM_setValue('download', 'KeyD'); GM_setValue('pipm', 'KeyP'); GM_setValue('loop', 'KeyO'); GM_setValue('customui', 'KeyZ'); GM_setValue('smallctrl', 10); GM_setValue('smallshift', 20); GM_setValue('bigctrl', 90); GM_setValue('bigshift', 120); GM_setValue('exclusions', ['placeholder', 'www.soundcloud.com', 'www.spotify.com', 'open.spotify.com', 'discord.com']); GM_setValue('disabledbtns', ['placeholder']); GM_setValue('savedtime', ['placeholder']); GM_setValue('hage', 7); GM_setValue('autoresume', false); GM_setValue('autocustomui', false); GM_setValue('nocustomui', ['placeholder', 'www.youtube.com', 'www.facebook.com']); GM_setValue('noautoresume', ['placeholder', 'www.youtube.com', 'www.facebook.com']); GM_setValue('cuicss', ['linear-gradient(140deg, rgba(0, 0, 0, 1) 0%, rgba(85, 85, 85, 1) 89%, rgba(153, 153, 153, 1) 100%)', '#fff3', 'inherit', '#111', '#ccc', '#333', '#111', '#111', '#ccc', '#333', '#000', 'transparent', '#111', '#000', '#ccc', '#ccc', '#ccc', '#ccc', '#fff', '#0007']); GM_setValue('ccss', ''); GM_setValue('firsttime', false); } let play = GM_getValue('play', 'KeyK'), stop = GM_getValue('stop', 'KeyS'), volplus = GM_getValue('volplus', 'ArrowUp'), volminus = GM_getValue('volminus', 'ArrowDown'), volstep = parseFloat(GM_getValue('volstep', 0.05)), mute = GM_getValue('mute', 'KeyM'), smallback = GM_getValue('smallback', 'Comma'), smallforward = GM_getValue('smallforward', 'Period'), smallstep = parseFloat(GM_getValue('smallstep', 3)), bigback = GM_getValue('bigback', 'KeyJ'), bigforward = GM_getValue('bigforward', 'KeyL'), bigstep = parseFloat(GM_getValue('bigstep', 30)), incplayback = GM_getValue('incplayback', 'KeyT'), decplayback = GM_getValue('decplayback', 'KeyY'), playbackstep = parseFloat(GM_getValue('playbackstep', 0.1)), resplayback = GM_getValue('resplayback', 'KeyR'), fullscreen = GM_getValue('fullscreen', 'KeyF'), download = GM_getValue('download', 'KeyD'), pipm = GM_getValue('pipm', 'KeyP'), loop = GM_getValue('loop', 'KeyO'), customui = GM_getValue('customui', 'Keyz'), smallctrl = parseFloat(GM_getValue('smallctrl', 10)), smallshift = parseFloat(GM_getValue('smallshift', 20)), bigctrl = parseFloat(GM_getValue('bigctrl', 90)), bigshift = parseFloat(GM_getValue('bigshift', 120)), exclusions = GM_getValue('exclusions', ['placeholder', 'www.soundcloud.com', 'www.spotify.com', 'open.spotify.com', 'discord.com']), disabledbtns = GM_getValue('disabledbtns', ['placeholder']), savedtime = GM_getValue('savedtime', ['placeholder']), hage = parseFloat(GM_getValue('hage', 7)), autoresume = GM_getValue('autoresume', false), autocustomui = GM_getValue('autocustomui', false), nocustomui = GM_getValue('nocustomui', ['placeholder', 'www.youtube.com', 'www.facebook.com']), noautoresume = GM_getValue('noautoresume', ['placeholder', 'www.youtube.com', 'www.facebook.com']), cuicss = GM_getValue('cuicss', ['linear-gradient(140deg, rgba(0, 0, 0, 1) 0%, rgba(85, 85, 85, 1) 89%, rgba(153, 153, 153, 1) 100%)', '#fff3', 'inherit', '#111', '#ccc', '#333', '#111', '#111', '#ccc', '#333', '#000', 'transparent', '#111', '#000', '#ccc', '#ccc', '#ccc', '#ccc', '#fff', '#0007']), ccss = GM_getValue('ccss', ''), KEY = { code: play, altKey: false, ctrlKey: false, shiftKey: false, metaKey: false, target: { tagName: 'DIV' } }, sch, och, bch, fch, sach, sbch, CSS, CCSS, CUICSS, CUIBC; if (!Array.isArray(savedtime)) { savedtime = JSON.parse(savedtime); GM_setValue('savedtime', savedtime); } if (!Array.isArray(exclusions)) { exclusions = JSON.parse(exclusions); GM_setValue('exclusions', exclusions); } if (!Array.isArray(disabledbtns)) { disabledbtns = JSON.parse(disabledbtns); GM_setValue('disabledbtns', disabledbtns); } if (!Array.isArray(nocustomui)) { nocustomui = JSON.parse(nocustomui); GM_setValue('nocustomui', nocustomui); } if (!Array.isArray(noautoresume)) { noautoresume = JSON.parse(noautoresume); GM_setValue('noautoresume', noautoresume); } const s = document.createElement('div'), m = document.createElement('div'), a = document.createElement('div'), f = document.createElement('div'), x = document.createElement('div'), c = document.createElement('div'), o = document.createElement('div'), u = document.createElement('div'), p = document.createElement('div'), k = document.createElement('div'), svga = '<svg xmlns="http://www.w3.org/2000/svg" style="display: inline-block; width: 20px; fill: #090; margin-right: 5px !important; transform: rotate(-90deg);" viewBox="0 0 26 26"> <path d="M13,15.405l8.764-8.584c0.392-0.383,1.019-0.38,1.406,0.008l1.536,1.536c0.391,0.391,0.39,1.026-0.002,1.417L13.707,20.707 C13.512,20.902,13.256,21,13,21c-0.256,0-0.512-0.098-0.707-0.293L1.296,9.782c-0.393-0.39-0.394-1.025-0.002-1.417L2.83,6.829 c0.387-0.387,1.015-0.391,1.406-0.008L13,15.405z"/> </svg>', svgplay = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 7 5 L 7 19 L 19 12 L 7 5 z"/> </svg>', svgpause = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 5 5 L 5 19 L 10 19 L 10 5 L 5 5 z M 14 5 L 14 19 L 19 19 L 19 5 L 14 5 z"/> </svg>', svgstop = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 5 5 L 5 19 L 19 19 L 19 5 L 5 5 z"/> </svg>', svgdownload = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 10 0 L 10 10 L 6.5 10 L 12 17.5 L 17.5 10 L 14 10 L 14 0 L 10 0 z M 0 22 L 0 24 L 24 24 L 24 22 L 0 22 z"/> </svg>', svgtheater = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"> <path d="M3,39V9h42v30H3z M7,35h34V13H7V35z"/> </svg>', svgfullscreen = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"> <path d="M 6 6 L 6 18 A 2.0002 2.0002 0 1 0 10 18 L 10 10 L 18 10 A 2.0002 2.0002 0 1 0 18 6 L 6 6 z M 32 6 A 2.0002 2.0002 0 0 0 31.859375 9.9980469 A 2.0002 2.0002 0 0 0 32 10 L 40 10 L 40 18 A 2.0002 2.0002 0 0 0 41.830078 20.021484 A 2.0002 2.0002 0 0 0 42.029297 20.027344 A 2.0002 2.0002 0 0 0 44 18 L 44 6 L 32 6 z M 7.9707031 30.972656 A 2.0002 2.0002 0 0 0 6 33 L 6 45 L 18 45 A 2.0002 2.0002 0 0 0 18.199219 44.992188 A 2.0002 2.0002 0 0 0 18 41 L 10 41 L 10 33 A 2.0002 2.0002 0 0 0 7.9707031 30.972656 z M 41.970703 30.972656 A 2.0002 2.0002 0 0 0 40 33 L 40 41 L 32 41 A 2.0002 2.0002 0 1 0 32 45 L 44 45 L 44 33 A 2.0002 2.0002 0 0 0 41.970703 30.972656 z"/> </svg>', svgnormalscreen = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"> <path d="M 16.970703 4.9726562 A 2.0002 2.0002 0 0 0 15 7 L 15 15 L 7 15 A 2.0002 2.0002 0 1 0 7 19 L 19 19 L 19 7 A 2.0002 2.0002 0 0 0 16.970703 4.9726562 z M 32.970703 4.9726562 A 2.0002 2.0002 0 0 0 31.003906 6.8613281 A 2.0002 2.0002 0 0 0 31 7 L 31 19 L 43 19 A 2.0002 2.0002 0 0 0 43.199219 18.992188 A 2.0002 2.0002 0 0 0 43 15 L 35 15 L 35 7 A 2.0002 2.0002 0 0 0 32.970703 4.9726562 z M 7 31 A 2.0002 2.0002 0 1 0 7 35 L 15 35 L 15 43 A 2.0002 2.0002 0 1 0 19 43 L 19 31 L 7 31 z M 31 31 L 31 43 A 2.0002 2.0002 0 1 0 35 43 L 35 35 L 43 35 A 2.0002 2.0002 0 1 0 43 31 L 31 31 z"/> </svg>', svgvolmute = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 3 L 6 9 L 2 9 L 2 15 L 6 15 L 12 21 L 12 3 z M 14.71875 7.28125 L 13.28125 8.71875 L 16.09375 11.5 L 13.28125 14.28125 L 14.71875 15.71875 L 17.5 12.90625 L 20.28125 15.71875 L 21.71875 14.28125 L 18.90625 11.5 L 21.71875 8.71875 L 20.28125 7.28125 L 17.5 10.09375 L 14.71875 7.28125 z"/> </svg>', svgvollow = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 3 L 6 9 L 2 9 L 2 15 L 6 15 L 12 21 L 12 3 z M 14 8.09375 L 14 15.8125 C 15.7 15.4125 17 13.9 17 12 C 17 10.1 15.7 8.59375 14 8.09375 z"/> </svg>', svgvolmid = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 3 L 6 9 L 2 9 L 2 15 L 6 15 L 12 21 L 12 3 z M 14 5 L 14 7 C 16.279 7.465 18 9.586 18 12 C 18 14.414 16.279 16.535 14 17 L 14 19 C 17.386 18.512 20 15.519 20 12 C 20 8.481 17.386 5.488 14 5 z M 14 9 L 14 15 C 15.125 14.689 16 13.475 16 12 C 16 10.525 15.125 9.388 14 9 z"/> </svg>', svgvolhigh = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M 12 3 L 6 9 L 2 9 L 2 15 L 6 15 L 12 21 L 12 3 z M 14 3.09375 L 14 5.09375 C 17.4 5.59375 20 8.5 20 12 C 20 15.5 17.4 18.40625 14 18.90625 L 14 20.90625 C 18.5 20.40625 22 16.6 22 12 C 22 7.4 18.5 3.59375 14 3.09375 z M 14 8.09375 L 14 15.8125 C 15.7 15.4125 17 13.9 17 12 C 17 10.1 15.7 8.59375 14 8.09375 z"/> </svg>', svgsubtitle = '<svg viewBox="0 0 1920 1920" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" clip-rule="evenodd" d="M213.333 0C95.513 0 0 95.513 0 213.333V1706.67C0 1824.49 95.513 1920 213.333 1920H1706.67c117.82 0 213.33-95.51 213.33-213.33V213.333C1920 95.513 1824.49 0 1706.67 0H213.333ZM320 1200c0-44.18 35.817-80 80-80h693.33c44.19 0 80 35.82 80 80s-35.81 80-80 80H400c-44.183 0-80-35.82-80-80Zm1066.67 0c0-44.18 35.81-80 80-80H1520c44.18 0 80 35.82 80 80s-35.82 80-80 80h-53.33c-44.19 0-80-35.82-80-80Zm-640.003 320c0-44.18 35.817-80 80-80H1520c44.18 0 80 35.82 80 80s-35.82 80-80 80H826.667c-44.183 0-80-35.82-80-80ZM320 1520c0-44.18 35.817-80 80-80h53.333c44.183 0 80 35.82 80 80s-35.817 80-80 80H400c-44.183 0-80-35.82-80-80Z"/> </svg>'; function ui() { CSS = GM_addStyle(`.MV_settings, .MV_menu, .MV_alert, .MV_filter, .MV_converter, .MV_styler, .MV_customui, .MV_ovarlay, .MV_exclusions, .MV_subtitles { width: fit-content; width: -moz-fit-content; height: fit-content; height: -moz-fit-content; font-family: Arial; font-size: 14px; z-index: 2147483644; position: fixed; transition: all 0.5s ease; user-select: none; line-height: initial; margin: 0; padding: 0; background-color: #000; color: #090; } .MV_menu *, .MV_filter *, .MV_styler *, .MV_exclusions *, .MV_converter *, .MV_subtitles * { transition: all 0.5s; } .MV_alert { z-index: 2147483647; bottom: 3%; width: 500px; height: fit-content; height: -moz-fit-content; border-radius: 20px; border: 1px #090 solid; display: none; opacity: 0; cursor: default; text-align: center; padding: 25px; font-weight: 700; font-size: 25px; } .MV_settings { bottom: 0; left: 0; padding: 5px; border-top-right-radius: 5px; cursor: pointer; opacity: 0.7; font-family: cursive; font-weight: 700; border-left: 7px #090 solid; } .MV_settings:hover { opacity: 1; } .MV_menu::-webkit-resizer, .MV_menu::-webkit-scrollbar-corner, .MV_menu::-webkit-scrollbar-button { width: 0; height: 0; display: none; } .MV_menu::-webkit-scrollbar-thumb { background-color: #090; } .MV_menu::-webkit-scrollbar-track, .MV_menu::-webkit-scrollbar { background-color: #000; width: 10px; } .MV_menu { top: 2%; left: 0; padding: 20px; width: 400px; margin-left: -600px; border-radius: 0px 15px 15px 0px; scrollbar-color: #090 #000; scrollbar-width: thin; } .MV_menu h2, .MV_styler h2, .MV_styler h3, .MV_filter h2, .MV_exclusions h2, .MV_converter h2, .MV_subtitles h2 { font-size: 22px; margin: 0; transition: inherit; color: #090; cursor: pointer; font-weight: bolder; font-family: Helvetica Neue, Segoe UI, Helvetica, Arial, sans-serif; } .MV_help { cursor: help; border-bottom: 2px #aaa dotted; } .MV_filter h2, .MV_exclusions h2, .MV_converter h2 { cursor: default; } .MV_styler h3 { font-size: 18px; cursor: default; margin: 3px; } .MV_menu input[type=number], .MV_menu input[type=text], .MV_filter input[type=text], .MV_styler input, .MV_subtitles input { width: auto; min-width: 100px; margin: 2px; background-color: #111; color: #777;border: none; padding: 2px; text-transform: capitalize; margin-left: 15px; text-align: center; font-weight: bolder; outline: none; transition: inherit; } .MV_menu input[type=number]:focus, .MV_menu input[type=text]:focus, .MV_styler input:focus, .MV_filter input:focus .MV_subtitles input:focus { box-shadow: 0 0 5px 2px #090; padding: 3px; margin: 5px 1px 5px 10px; outline: none; border: 1px solid #090; } .MV_menu input:invalid, .MV_filter input:invalid, .MV_styler input:invalid, .MV_subtitles input:invalid { box-shadow: 0 0 5px 2px #900; outline: 0; border: 1px solid #900; } .MV_filter select, .MV_exclusions select, .MV_converter select { border: 1px solid #090; margin: 2px; background-color: #000; color: #090; outline: none; cursor: pointer; font-size: 20px; padding: 3px 10px; } .MV_s, .MV_o, .MV_b, .MV_f, .MV_sb, .MV_sa { overflow: hidden; height: 0px; transition: inherit; } .MV_b input[type=file] { cursor: pointer; background-color: #000; color: #090; padding: 3px; border: 1px solid #090; } .MV_btn { transition: inherit; border: none; color: #000; background-color: #090; outline: 0; font-family: sans-serif; cursor: pointer; padding: 5px 20px; font-weight: bolder; margin-left: 10px; margin-top: 10px; } .MV_btn:hover { color: #090; background-color: #000; } [class^="MV_"] *:disabled { opacity: 0.6 !important; cursor: not-allowed !important; color: #000 !important; background-color: #090 !important; } .MV_overlay { z-index: 2147483640 !important; top: 0; right: 0; position: fixed; background-color: #000; opacity: 0.7; display: none; height: 100%; width: 100%; } .MV_styler, .MV_filter, .MV_exclusions, .MV_converter, .MV_subtitles { box-shadow: 0 0 20px 20px #090; top: 20px; display: none; padding: 20px; margin: 20px auto; border-radius: 20px; } .MV_customui { display: none; top: 0; left: 0; width: 100%; height: 100%; z-index: 2147483635 !important; } .MV_hidden { display: none !important; } .MV_subb { display: block; bottom: 40px; position: absolute; padding: 10px; font-size: 1.5em; color: #fff; background: #000; overflow-wrap: normal; transition: none 0s ease 0s !important; } #MV_sub { display: none !important; } `); CUICSS = GM_addStyle(`.MV_ctheater .MV_wrapper { display: grid; align-content: center; } .MV_container { text-align: initial; margin: auto; display: block; height: -moz-fit-content; width: -moz-fit-content; height: fit-content; width: fit-content; } .MV_container video:not(.MV_vfullscreen, .MV_framed, .MV_maxheight) { height: auto !important; } .MV_container video { width: 100% !important; position: static !important; } .MV_vfullscreen, .MV_container .MV_framed, .MV_maxheight { height: 100% !important } .MV_theater { width: 80%; height: 80%; transition: none !important; } .MV_theater video { height: 100% !important; width: 100% !important; background-color: #000 !important; } .MV_controls { display: none; position: relative; z-index: 2; margin-top: -40px; height: 40px; width: 100%; opacity: 0; transition: all 0.5s !important; } .MV_controls:hover { display: block !important; opacity: 1 !important; cursor: default !important; } .MV_cbtn { font-size: 14px; font-family: "Segeo UI", "Helvetica Neue", "Helvetica"; margin-left: 5px; border: none; background-size: contain; background-repeat: no-repeat; display: inline-block; width: 25px; height: 25px; padding: 0; cursor: pointer; text-align: center; vertical-align: middle; } .MV_lbtns { float: left; height: 30px; } .MV_cbtn:first-child { margin-left: 0; } .MV_cbtn:hover { opacity: 0.5; } .MV_cbtn svg { height: 20px; } .MV_rbtns { float: right; height: 30px; } .MV_bar { height: 10px; position: absolute; width: 100%; overflow: hidden; } .MV_bar, .MV_bar * { transition: none !important; min-width: 0%; max-width: 100%; } .MV_highlight { transition: none !important; position: absolute; z-index: 4; display: none; bottom: 50px; color: #ccc; background-color: #000; margin-left: -30px; padding: 3px; border-radius: 5px; opacity: 1; text-align: center; } .MV_thumbnail, .MV_thumbnail * { max-width: 120px; max-height: 120px; display: block; } .MV_played, .MV_loaded { height: 30px; display: inline-block; } .MV_played { z-index: 2; margin-right: -5px; width: 0; position: relative; } .MV_loaded { z-index: 1; position: absolute; width: 0%; } .MV_thumb { z-index: 3; position: absolute; width: 10px; height: inherit; display: inline-block; cursor: pointer; } .MV_customui * { transition: inherit; user-select: none; } .MV_lbtns, .MV_rbtns { top: 10px; position: relative; } .MV_time { font-size: 16px; font-weight: 700; text-align: center; vertical-align: middle; user-select: text; } .MV_vol input { border-radius: 0; padding: 0; height: auto; float: right; width: 50px; -moz-appearance: none; appearance: none; border: none; outline: none; cursor: pointer; } .MV_vol input::-webkit-slider-thumb, .MV_vol input::-moz-range-thumb {-moz-appearance: none; appearance: none; width: 7%; max-width: 100%; min-width: 0%; height: 100%; opacity: 0.7; } .MV_vol:before { margin: 10px; margin-left: -10px; content: attr(data-content); bottom: -7px; position: absolute; text-align: center; opacity: 1; } .MV_vol { overflow: hidden; text-align: center; vertical-align: middle; width: 0; display: inline-block; white-space: nowrap; position: relative; } .MV_playbackm { display: inline-grid; height: 150px; align-self: flex-start; text-align: center; width: 0; overflow: hidden; white-space: nowrap; position: relative; bottom: 150px; z-index: 4; } .MV_playbackm span { padding: 3px; font-weight: 700; cursor: pointer; } .MV_buffer { position: absolute; height: 50px; width: 50px; animation: MV_rotate 2s linear infinite; border: 5px solid; border-radius: 50%; } .MV_theater .MV_resizer { display: block !important; } .MV_resizer { display: none; width: 10px; height: 10px; margin-left: 100%; background-color: #ccc; cursor: se-resize; } @keyframes MV_rotate { from {transform: rotate(0deg);} to {transform:rotate(360deg);} }`); CUIBC = GM_addStyle(`.MV_customui { background-image: ${cuicss[0]}; } .MV_controls { background: ${cuicss[1]}; } .MV_time { background: ${cuicss[2]}; color: ${cuicss[15]}; } .MV_vol input { background: ${cuicss[3]}; } .MV_vol input::-moz-range-thumb, .MV_vol input::-webkit-slider-thumb { background: ${cuicss[4]}; } .MV_playbackm span, .MV_playbackm { background: ${cuicss[5]}; color: ${cuicss[16]}; } .MV_playbackm span:hover { background: ${cuicss[6]}; color: ${cuicss[17]}; } .MV_bar { background: ${cuicss[7]}; } .MV_played { background: ${cuicss[8]}; } .MV_loaded { background: ${cuicss[9]}; } .MV_thumb { background: ${cuicss[10]}; } .MV_cbtn { background: ${cuicss[11]}; color: ${cuicss[14]}; } .MV_ctheater { background: ${cuicss[12]} } .MV_cbtn svg { fill: ${cuicss[13]}; } .MV_buffer { border-color: ${cuicss[13]} transparent; } .MV_vol:before { color: ${cuicss[14]}; .MV_subb { color: ${cuicss[18]}; background: ${cuicss[19]}; }`); CCSS = GM_addStyle(ccss); s.innerHTML = 'XDHx86 - MyVideo v1.6 | Settings'; m.innerHTML = `<h2> ${svga} Shortcuts: </h2> <div class="MV_s"> Play: <input type="text"> <br> Stop: <input type="text"> <br> Volume Up: <input type="text"> <br> Volume Down: <input type="text"> <br> Volume Step: <input type="number" min="0.01" max="0.2" step="0.01"> <br> Mute: <input type="text"> <br> Short Backward: <input type="text"> <br> Short Forward: <input type="text"> <br> Short Step: <input type="number" min="3" max="30" step="1"> <br> Long Backward: <input type="text"> <br> Long Forward: <input type="text"> <br> Long Step: <input type="number" min="10" max="120" step="1"> <br> Decrease Playback Rate: <input type="text"> <br> Increase Playback Rate: <input type="text"> <br> Playback Rate Step: <input type="number" min="0.1" max="0.5" step="0.1"> <br> Reset Playback Rate: <input type="text"> <br> Fullscreen: <input type="text"> <br> Download: <input type="text"> <br> Play in Picture Mode: <input type="text"> <br> Loop: <input type="text"> <br> Custom Video Player: <input type="text"> <br> </div> <h2> ${svga} General: </h2> <div class="MV_o"> Auto resume from last stop: <br> Yes <input type="radio" name="ar"> No <input type="radio" name="ar"> <br> Auto use custom video player: <br> Yes <input type="radio" name="cu"> No <input type="radio" name="cu"> <br> Don't use custom video player on this site (${location.host}): <br> Yes <input type="radio" name="nc"> No <input type="radio" name="nc"> <br> Don't auto resume on this site (${location.host}): <br> Yes <input type="radio" name="dr"> No <input type="radio" name="dr"> <br> <span class="MV_help" title="Click to see notes"> Delete history older than (Days): </span> <input type="number" min="3" max="30" step="1"> <br> Ctrl short step: <input type="number" min="5" max="100" step="1"> <br> Shift short step: <input type="number" min="5" max="100" step="1"> <br> Ctrl long step: <input type="number" min="10" max="600" step="1"> <br> Shift long step: <input type="number" min="10" max="600" step="1"> <br> Customize styles: <button class="MV_btn"> Open Styler </button> <br> <span class="MV_help" title="Click to see notes"> Disable Keys: </span> <button class="MV_btn"> Config Keys </button> <br> Execlusions: <button class="MV_btn"> Config Exclusions </button> </div> <h2> ${svga} Backup & Restore: </h2> <div class="MV_b"> Backup: <button class="MV_btn"> Backup </button> <br> Restore: <input type="file"> <button class="MV_btn"> Restore </button> </div> <h2> ${svga} Feedback: </h2> <div class="MV_f"> <button class=MV_btn> Send an Email </button> </div> <br> <button class="MV_btn"> Save </button> <button class="MV_btn"> Reset </button>`; c.innerHTML = `<h2> ${svga} Basic Styling: </h2> <div class="MV_sb"> <h3> Background Colors: </h3> Custom UI: <input type="text"> <br> Controls Bar: <input type="text"> <br> Time: <input type="text"> <br> Volume Menu: <input type="text"> <br> Volume Slider: <input type="text"> <br> Playback Menu: <input type="text"> <br> Playback Menu Button (Hover): <input type="text"> <br> Progress Bar: <input type="text"> <br> Progress Bar (Played): <input type="text"> <br> Progress Bar (Loaded): <input type="text"> <br> Progress Bar (Thumb): <input type="text"> <br> Buttons: <input type="text"> <br> Theater Mode: <input type="text"> <br> <h3> Button & Text Colors: </h3> Buttons: <input type="text"> <br> Button Text: <input type="text"> <br> Time: <input type="text"> <br> Playback Menu Button (Text): <input type="text"> <br> Playback Menu Text (Hover): <input type="text"> <br> Subtitle Text Color: <input type="text"> <br> Subtitle Background Color: <input type="text"> </div> <h2> ${svga} Advanced Styling </h2> <div class="MV_sa"> Open Advanced Styler: <button class="MV_btn"> Open </button> </div> <br> <button class="MV_btn"> Save </button> <button class="MV_btn"> Reset </button>`; x.innerHTML = `<h2> Exclusions: </h2> Add <select> <option value="page"> Page </option> <option value="website"> Website </option> </select> <button class="MV_btn"> To Exclusions </button> <h2> Execluded: </h2> <select size="6"> </select> <br> <button class="MV_btn" disabled> Remove </button>`; f.innerHTML = `<h2> Disable Keys: </h2> <h3> Disabled buttons only work on this website and not globally.<br><br>Disabled buttons will work inside custom UI. </h3> Key: <input type=text> <button class=MV_btn> Disable </button> <br> <h2> Disabled Buttons: </h2> <select size=6> </select> <br> <button class="MV_btn" disabled> Remove </button>`; u.innerHTML = `<div class="MV_wrapper"> <div class="MV_container"> <div class="MV_controls"> <div class="MV_highlight"> <span class="MV_thumbnail"> </span> <span class="MV_currenttime"> </span> </div> <div class="MV_bar"> <div class="MV_loaded"> </div> <div class="MV_played"> </div> <div class="MV_thumb"> </div> </div> <div class="MV_lbtns"> <button class="MV_cbtn">${svgpause}</button> <button class="MV_cbtn">${svgstop}</button> <span class="MV_time">00:00:00/00:00:00</span> </div> <div class="MV_rbtns"> <span class="MV_vol" data-content="20"> <input type="range" min="0" max="100" step="1"> </span> <button class="MV_cbtn">${svgvolhigh}</button> <button class="MV_cbtn">${svgsubtitle}</button> <button class="MV_cbtn">1.0x</button> <div class="MV_playbackm"> <span> 0.2 </span> <span> 0.5 </span> <span> 1.0 </span> <span> 1.2 </span> <span> 1.5 </span> <span> 2.0 </span> </div> <button class="MV_cbtn">${svgdownload}</button> <button class="MV_cbtn">${svgtheater}</button> <button class="MV_cbtn">${svgfullscreen}</button> </div> </div> <div class="MV_buffer"> </div> <div class="MV_resizer"> </div> <div class="MV_subb" style="display: none;"> <span class="MV_capt"> </span> <p id="MV_sub"></p> </div> </div> </div>`; p.innerHTML = `<h2> Video Converter: </h2> Choose video quality and format: <select> </select> <br> <button class=MV_btn> Download </button> ${location.href.includes('youtube.com') ? ` <br> <br> Download this video thubnail: <a href="https://i.ytimg.com/vi/${location.href.substr(location.href.indexOf('v=')+2).includes('&') ? location.href.substr(location.href.indexOf('v=')+2).substr(0, location.href.substr(location.href.indexOf('v=')+2).indexOf('&')) : location.href.substr(location.href.indexOf('v=')+2)}/maxresdefault.jpg" target="_blank"> Download </a> <br> <br> Credits goes to <a href="https://www.y2mate.com/" traget="_blank">https://www.y2mate.com/</a>` : ` <br> <br> Credits goes to <a href="https://fbdown.net/" traget="_blank">https://fbdown.net/</a>`}`; k.innerHTML = `<h2> Import Subtitle </h2> <br> Upload Subtitle: <input type="file" accept=".srt,.vtt"> <br> <button class="MV_btn"> Import </button>` s.className = 'MV_settings'; m.className = 'MV_menu'; a.className = 'MV_alert'; x.className = 'MV_exclusions'; f.className = 'MV_filter'; c.className = 'MV_styler'; u.className = 'MV_customui'; o.className = 'MV_overlay'; p.className = 'MV_converter'; k.className = 'MV_subtitles'; document.body.appendChild(s); document.body.appendChild(m); document.body.appendChild(x); document.body.appendChild(a); document.body.appendChild(f); document.body.appendChild(c); document.body.appendChild(u); document.body.appendChild(o); document.body.appendChild(p); document.body.appendChild(k); { let p = 20; m.querySelector('.MV_s').style.height = '-moz-fit-content'; m.querySelector('.MV_s').style.height = 'fit-content'; sch = m.querySelector('.MV_s').offsetHeight + p; m.querySelector('.MV_s').style.height = '0'; m.querySelector('.MV_o').style.height = '-moz-fit-content'; m.querySelector('.MV_o').style.height = 'fit-content'; och = m.querySelector('.MV_o').offsetHeight + p; m.querySelector('.MV_o').style.height = '0'; m.querySelector('.MV_b').style.height = '-moz-fit-content'; m.querySelector('.MV_b').style.height = 'fit-content'; bch = m.querySelector('.MV_b').offsetHeight + p; m.querySelector('.MV_b').style.height = '0'; m.querySelector('.MV_f').style.height = '-moz-fit-content'; m.querySelector('.MV_f').style.height = 'fit-content'; fch = m.querySelector('.MV_f').offsetHeight + p; m.querySelector('.MV_f').style.height = '0'; c.style.display = 'block'; c.querySelector('.MV_sb').style.height = '-moz-fit-content'; c.querySelector('.MV_sb').style.height = 'fit-content'; sbch = c.querySelector('.MV_sb').offsetHeight + p; c.querySelector('.MV_sb').style.height = '0'; c.querySelector('.MV_sa').style.height = '-moz-fit-content'; c.querySelector('.MV_sa').style.height = 'fit-content'; sach = c.querySelector('.MV_sa').offsetHeight + p; c.querySelector('.MV_sa').style.height = '0'; c.style.display = 'none'; } document.body.onclick = e => { let path = e.target; for (let i = 0; i < 10; i++) { if (path.MV_hasClass(['MV_menu', 'MV_alert', 'MV_styler', 'MV_overlay', 'MV_settings', 'MV_filter', 'MV_exclusions', 'MV_converter', 'MV_subtitles', 'MV_container'])) return; else if (path.parentElement && path.parentElement.classList) path = path.parentElement; if (i == 9) { sh('sf'); sh('of'); sh('bf'); sh('ff'); sh('stf'); sh('flf'); sh('xcf'); sh('subf'); sh('menuf'); } } } s.onclick = () => { if (m.style.marginLeft == '0' || m.style.marginLeft == '0px') { sh('menuf'); sh('sf'); sh('of'); sh('bf'); sh('ff'); sh('stf'); sh('flf'); sh('xcf'); sh('cvf'); sh('subf'); } else sh('menut'); } s.oncontextmenu = e => { if (confirm('Right-clicking this menu adds this website (' + location.host + ') to exclusions, are you sure you want that?')) { e.preventDefault(); if (!exclusions.includes(location.host)) { exclusions.push(location.host); GM_setValue('exclusions', exclusions); rvals(); } remove(); } else if (confirm('Then exclude this page only? (' + location.href + ')')) { e.preventDefault(); if (!exclusions.includes(location.href)) { exclusions.push(location.href); GM_setValue('exclusions', exclusions); rvals(); } remove(); } } m.querySelectorAll('h2')[0].onclick = () => { if (m.querySelector('.MV_s').style.height == '0' || m.querySelector('.MV_s').style.height == '0px') { sh('st'); sh('of'); sh('bf'); sh('ff'); } else sh('sf'); } m.querySelectorAll('h2')[1].onclick = () => { if (m.querySelector('.MV_o').style.height == '0' || m.querySelector('.MV_o').style.height == '0px') { sh('sf'); sh('ot'); sh('bf'); sh('ff'); } else sh('of'); } m.querySelectorAll('h2')[2].onclick = () => { if (m.querySelector('.MV_b').style.height == '0' || m.querySelector('.MV_b').style.height == '0px') { sh('sf'); sh('of'); sh('bt'); sh('ff'); } else sh('bf'); } m.querySelectorAll('h2')[3].onclick = () => { if (m.querySelector('.MV_f').style.height == '0' || m.querySelector('.MV_f').style.height == '0px') { sh('sf'); sh('of'); sh('bf'); sh('ft'); } else sh('ff'); } m.querySelectorAll('.MV_btn')[0].onclick = () => { if (c.style.display == 'block') { sh('flf'); sh('stf'); sh('cvf'); sh('xcf'); } else { sh('flf'); sh('xcf'); sh('cvf'); sh('stt'); } } m.querySelectorAll('.MV_btn')[1].onclick = () => { if (f.style.display == 'block') { sh('flf'); sh('xcf'); sh('cvf'); sh('stf'); } else { sh('stf'); sh('xcf'); sh('cvf'); sh('flt'); } } m.querySelectorAll('.MV_btn')[2].onclick = () => { if (x.style.display == 'block') { sh('flf'); sh('xcf'); sh('cvf'); sh('stf'); } else { sh('stf'); sh('flf'); sh('cvf'); sh('xct'); } } o.onclick = () => { sh('stf'); sh('flf'); sh('xcf'); sh('cvf'); sh('subf'); } c.querySelectorAll('h2')[0].onclick = () => { if (c.querySelector('.MV_sb').style.height == '0' || c.querySelector('.MV_sb').style.height == '0px') { sh('faf'); sh('fbt'); } else sh('fbf'); } c.querySelectorAll('h2')[1].onclick = () => { if (c.querySelector('.MV_sa').style.height == '0' || c.querySelector('.MV_sa').style.height == '0px') { sh('fbf'); sh('fat'); } else sh('faf'); } f.querySelector('input').onkeydown = e => e.preventDefault(); f.querySelector('input').onkeyup = function(e) { if (/capslock|f[0-9]|home|end|pageup|delete|backspace|escape|tab|pagedown|insert|numlock|backquote/i.test(e.code)) alt('No special characters allowed!'); else if (!e.code || e.key == 'Clear') return; else if (e.ctrlKey || e.altKey || e.metaKey || e.shiftKey) alt('No special characters allowed!'); else if (e.code == 'Enter') this.nextElementSibling.click(); else if (!/control|shift|alt|meta|osl|osr/i.test(e.code)) { this.value = e.code; this.setCustomValidity(''); } } if (location.host.includes('facebook')) p.querySelector('button').innerText = 'Download'; } function sh(w) { switch (w) { case 'menuf': m.style.marginLeft = '-600px'; break; case 'menut': m.style.marginLeft = '0px'; break; case 'sf': m.querySelector('.MV_s').style.height = '0px'; m.querySelectorAll('svg')[0].style.transform = 'rotate(-90deg)'; break; case 'st': m.querySelector('.MV_s').style.height = sch + 'px'; m.querySelectorAll('svg')[0].style.transform = 'rotate(0deg)'; break; case 'of': m.querySelector('.MV_o').style.height = '0px'; m.querySelectorAll('svg')[1].style.transform = 'rotate(-90deg)'; break; case 'ot': m.querySelector('.MV_o').style.height = och + 'px'; m.querySelectorAll('svg')[1].style.transform = 'rotate(0deg)'; break; case 'bf': m.querySelector('.MV_b').style.height = '0px'; m.querySelectorAll('svg')[2].style.transform = 'rotate(-90deg)'; break; case 'bt': m.querySelector('.MV_b').style.height = bch + 'px'; m.querySelectorAll('svg')[2].style.transform = 'rotate(0deg)'; break; case 'ff': m.querySelector('.MV_f').style.height = '0px'; m.querySelectorAll('svg')[3].style.transform = 'rotate(-90deg)'; break; case 'ft': m.querySelector('.MV_f').style.height = fch + 'px'; m.querySelectorAll('svg')[3].style.transform = 'rotate(0deg)'; break; case 'flf': f.style.display = 'none'; o.style.display = 'none'; break; case 'flt': f.style.display = 'block'; o.style.display = 'block'; f.style.left = (document.body.offsetWidth - f.offsetWidth) / 2 + 'px'; break; case 'stf': c.style.display = 'none'; o.style.display = 'none'; break; case 'stt': c.style.display = 'block'; o.style.display = 'block'; c.style.left = (document.body.offsetWidth - c.offsetWidth) / 2 + 'px'; break; case 'xcf': x.style.display = 'none'; o.style.display = 'none'; break; case 'xct': x.style.display = 'block'; o.style.display = 'block'; x.style.left = (document.body.offsetWidth - x.offsetWidth) / 2 + 'px'; break; case 'cvf': p.style.display = 'none'; o.style.display = 'none'; break; case 'cvt': sh('flf'); sh('stf'); sh('xcf'); p.style.display = 'block'; o.style.display = 'block'; p.style.left = (document.body.offsetWidth - p.offsetWidth) / 2 + 'px'; break; case 'fbf': c.querySelector('.MV_sb').style.height = '0px'; c.querySelectorAll('svg')[0].style.transform = 'rotate(-90deg)'; break; case 'fbt': c.querySelector('.MV_sb').style.height = sbch + 'px'; c.querySelectorAll('svg')[0].style.transform = 'rotate(0deg)'; break; case 'faf': c.querySelector('.MV_sa').style.height = '0px'; c.querySelectorAll('svg')[1].style.transform = 'rotate(-90deg)'; break; case 'fat': c.querySelector('.MV_sa').style.height = sach + 'px'; c.querySelectorAll('svg')[1].style.transform = 'rotate(0deg)'; break; case 'subt': k.style.display = 'block'; o.style.display = 'block'; k.style.left = (document.body.offsetWidth - k.offsetWidth) / 2 + 'px'; break; case 'subf': k.style.display = 'none'; o.style.display = 'none'; break; } } function set() { const inputst = m.querySelectorAll('input[type=text]'), inputsn = m.querySelectorAll('input[type=number]'), inputsr = m.querySelectorAll('input[type=radio]'), valst = [play, stop, volplus, volminus, mute, smallback, smallforward, bigback, bigforward, incplayback, decplayback, resplayback, fullscreen, download, pipm, loop, customui], valstn = ['play', 'stop', 'volplus', 'volminus', 'mute', 'smallback', 'smallforward', 'bigback', 'bigforward', 'incplayback', 'decplayback', 'resplayback', 'fullscreen', 'download', 'pipm', 'loop', 'customui'], valsn = [volstep, smallstep, bigstep, playbackstep, hage, smallctrl, smallshift, bigctrl, bigshift], valsnn = ['volstep', 'smallstep', 'bigstep', 'playbackstep', 'hage', 'smallctrl', 'smallshift', 'bigctrl', 'bigshift'], backup = m.querySelectorAll('.MV_btn')[3], restore = m.querySelectorAll('.MV_btn')[4], feedbck = m.querySelectorAll('.MV_btn')[5], save = m.querySelectorAll('.MV_btn')[6], reset = m.querySelectorAll('.MV_btn')[7], help = m.querySelectorAll('.MV_help'), inputsc = c.querySelectorAll('input'), advcss = c.querySelectorAll('.MV_btn')[0], csave = c.querySelectorAll('.MV_btn')[1], creset = c.querySelectorAll('.MV_btn')[2], fselect = f.querySelector('select'), fbtns = f.querySelectorAll('.MV_btn'), xselects = x.querySelectorAll('select'), xbtns = x.querySelectorAll('.MV_btn'), subbtn = k.querySelector('button'), convselect = p.querySelector('select'), convbtn = p.querySelector('button'); let i = 0; for (let elm of inputst) { elm.value = valst[i]; elm.setAttribute('mv-og', elm.value); elm.setAttribute('mv-name', valstn[i]); i++; elm.onkeydown = e => { if ((e.shiftKey && e.code != 'Tab') || /tab/i.test(e.code)) return; else e.preventDefault(); } elm.onkeyup = function(e) { if (/capslock|f[0-9]|home|end|pageup|pagedown|insert|numlock|backquote/i.test(e.code)) alt('No special characters allowed!'); else if (e.ctrlKey || e.altKey || e.metaKey || (e.shiftKey && e.code != 'Tab')) alt('No special characters allowed!'); else if (!e.code || e.key == 'Clear') return; else if (e.code == 'Delete' || e.code == 'Backspace') this.value = this.getAttribute('mv-og'); else if (e.code == 'Escape') this.blur(); else if (e.code == 'Enter' && this.nextElementSibling.nextElementSibling) this.nextElementSibling.nextElementSibling.focus(); else if (!/control|shift|alt|meta|osl|osr/i.test(e.code) && e.code != 'Tab') this.value = e.code; } elm.onblur = function() { if (!/digit|numpad|key|space|bracket|semi|comma|period|slash|(^quote)|minus|arrow|equal/i.test(this.value)) { alt('No special characters allowed!'); this.value = this.getAttribute('mv-og'); } let v = this.value.toLowerCase(), a = inputst, c = []; for (let e of a) c.push(e.value.toLowerCase()); if (c.indexOf(v) != c.lastIndexOf(v)) { alt('This value is already assigned!'); this.value = this.getAttribute('mv-og'); } } } let j = 0; for (let elm of inputsn) { elm.value = valsn[j]; elm.setAttribute('mv-og', elm.value); elm.setAttribute('mv-name', valsnn[j]); j++; elm.onkeydown = e => { if ((e.shiftKey && e.code != 'Tab') || /tab|backspace|period|arrow/i.test(e.code)) return; else e.preventDefault(); } elm.onkeyup = function(e) { if (e.ctrlKey || e.altKey || e.metaKey || (e.shiftKey && e.code != 'Tab')) alt('No special characters allowed!'); else if (!e.code || e.key == 'Clear') return; else if (e.code == 'Delete') this.value = this.getAttribute('mv-og'); else if (e.code == 'Escape') this.blur(); else if (e.code == 'Enter' && this.nextElementSibling.nextElementSibling) this.nextElementSibling.nextElementSibling.focus(); else if (e.code == 'Period') this.value += '.0'; else if (!/control|shift|alt|meta|osl|enter|osr/i.test(e.code) && e.code != 'Tab' && (e.key <= 9 && e.key >= 0)) this.value += e.key; } elm.onblur = function() { if (isNaN(parseFloat(this.value)) || this.value > parseFloat(this.max) || this.value < parseFloat(this.min) || !this.validity.valid) { alt(`Invalid value! No more than ${this.max} nor less than ${this.min} and divisible by ${this.step}.`, 7000); this.value = this.getAttribute('mv-og'); } } } { if (autoresume) inputsr[0].checked = true; else inputsr[1].checked = true; if (autocustomui) inputsr[2].checked = true; else inputsr[3].checked = true; if (nocustomui.includes(location.host)) inputsr[4].checked = true; else inputsr[5].checked = true; if (noautoresume.includes(location.host)) inputsr[6].checked = true; else inputsr[7].checked = true; let result = disabledbtns.MV_search(location.host); if (result.found && result.obj.buttons.length > 0) for (let i = 0; i < result.obj.buttons.length; i++) fselect.options.add(new Option(result.obj.buttons[i], result.obj.buttons[i])); for (let i = 0; i < exclusions.length; i++) xselects[1].options.add(new Option(exclusions[i], exclusions[i])); } for (let elm of help) elm.onclick = () => window.open('https://openuserjs.org/scripts/XDHx86/My_Video_(Web_Video_Player)#notes'); let kk = 0; for (let elm of inputsc) { elm.value = cuicss[kk]; elm.style.textTransform = 'none'; kk++; } backup.onclick = () => br(0); restore.onclick = () => br(1); feedbck.onclick = feedback; save.onclick = () => { for (let e of inputst) if (e.getAttribute('mv-name')) GM_setValue(e.getAttribute('mv-name'), e.value); for (let e of inputsn) if (e.getAttribute('mv-name')) GM_setValue(e.getAttribute('mv-name'), e.value); if (inputsr[0].checked) GM_setValue('autoresume', true); else GM_setValue('autoresume', false); if (inputsr[2].checked) GM_setValue('autocustomui', true); else GM_setValue('autocustomui', false); if (inputsr[4].checked) { if (!nocustomui.includes(location.host)) nocustomui.push(location.host); GM_setValue('nocustomui', nocustomui); } else { if (nocustomui.includes(location.host)) nocustomui.splice(nocustomui.indexOf(location.host), 1); GM_setValue('nocustomui', nocustomui); } if (inputsr[6].checked) { if (!noautoresume.includes(location.host)) noautoresume.push(location.host); GM_setValue('noautoresume', noautoresume); } else { if (noautoresume.includes(location.host)) noautoresume.splice(noautoresume.indexOf(location.host), 1); GM_setValue('noautoresume', noautoresume); } rvals(); alt('Settings will take effect immediately.'); } reset.onclick = () => { if (confirm('Are you sure you want to reset the script?\nThis cannot be undone and it will DELETE all the saved data')) { GM_setValue('firsttime', true); if (confirm('Changes will take effect after reload, reload now?')) location.reload(); } } advcss.onclick = () => { const win = window.open('', 'MV_advCSS', 'menubar=no,status=no,titlebar=no,location=no,top=0,height=' + window.screen.availHeight - 200 + 'width=' + window.screen.availWidth / 2), doc = win.document; doc.head.innerHTML = `<style> body { font-family: arial; background-color: #333; color: #090; } .container { padding: 20px; } .header { text-align: center; } .note { margin: 20px 30px; display: flex; align-content: center; } .text { display: block; margin: auto; width: 100%; height: 100%; } .MV_btn { transition: all 0.5s; border: none; color: #000; background-color: #090; outline: 0; font-family: sans-serif; cursor: pointer; padding: 5px 20px; font-weight: bolder; margin-left: 10px; margin-top: 10px; } .MV_btn:hover { color: #090; background-color: #000; } textarea::selection { color: #000; background-color: #070770; } textarea { width: 700px; display: inline-block; height: 600px; background-color: #000; border: 1px #090 solid; outline: 0; max-width: 700px; max-height: 700px; box-shadow: 0 0 5px 2px #090; margin: 0 10px; color: #090; font-size: 14px; font-weight: 600; font-family: arial; }</style>`; doc.body.innerHTML = `<div class=container> <h2 class=header> Advanced CSS Editor </h2> <span class=note> Notes: <br> - Please don't actually use this to write your code, just use an editor then paste here. </span> <div class=text> <textarea spellcheck=false>${ccss}</textarea> <button class=MV_btn> Copy main CSS </button> <button class=MV_btn> Copy custom UI CSS </button> <textarea style="opacity: 0; width: 0; height: 0;" readonly=readonly>${CSS.innerHTML}</textarea> <textarea style="opacity: 0; width: 0; height: 0;" readonly=readonly>${CUICSS.innerHTML}</textarea> </div> <button class=MV_btn> Save </button> <button class=MV_btn> Reset </button> </div>`; let et = doc.querySelectorAll('textarea')[0], css = doc.querySelectorAll('textarea')[1], cuicss = doc.querySelectorAll('textarea')[2], cssb = doc.querySelectorAll('.MV_btn')[0], cuicssb = doc.querySelectorAll('.MV_btn')[1], save = doc.querySelectorAll('.MV_btn')[2], reset = doc.querySelectorAll('.MV_btn')[3]; cssb.onclick = () => { css.select(); win.document.execCommand('copy'); win.alert('Copied to clipboard'); } cuicssb.onclick = () => { cuicss.select(); win.document.execCommand('copy'); win.alert('Copied to clipboard'); } save.onclick = () => { GM_setValue('ccss', et.value); rvals(); ucss(); win.alert('Settings will take effect immediately.'); } reset.onclick = () => { if (!win.confirm('Are you sure you want to reset it? This cannot be undone and will delete all CSS code written.')) return; et.innerHTML = ''; et.value = ''; GM_setValue('ccss', ''); rvals(); ucss(); win.alert('Settings will take effect immediately.'); } } csave.onclick = () => { let a = [], validate = c => { let img = document.createElement('img'); img.style = 'background: rgb(0, 0, 0)'; img.style = 'background: ' + c; if (img.style.background != 'rgb(0, 0, 0)' && img.style.background != '') return true; img.style = 'background: rgb(255, 255, 255)'; img.style = 'background: ' + c; return (img.style.background != 'rgb(255, 255, 255)' && img.style.background != ''); }; for (let e of inputsc) { if (!validate(e.value)) { e.setCustomValidity('Invalid value!'); e.reportValidity(); e.onfocus = function() { this.setCustomValidity('Invalid value!'); this.reportValidity(); } e.onchange = function() { this.onchange = null; this.onfocus = null; this.setCustomValidity(''); } } else a.push(e.value); } if (a.length == 20) { GM_setValue('cuicss', a); rvals(); alt('Settings will take effect immediately.'); ucss(); } } creset.onclick = () => { GM_setValue('cuicss', ['linear-gradient(140deg, rgba(0, 0, 0, 1) 0%, rgba(85, 85, 85, 1) 89%, rgba(153, 153, 153, 1) 100%)', '#fff3', 'inherit', '#111', '#ccc', '#333', '#111', '#111', '#ccc', '#333', '#000', 'transparent', '#111', '#000', '#ccc', '#ccc', '#ccc', '#ccc', '#fff', '#0007']); rvals(); ucss(); let k = 0; for (let elm of inputsc) { elm.value = cuicss[k]; elm.style.textTransform = 'none'; k++; } alt('Settings will take effect immediately.'); } fselect.onchange = function() { if (this.selectedIndex > -1) fbtns[1].disabled = false; else fbtns[1].disabled = false; } fbtns[0].onclick = () => { let i = f.querySelector('input'); if (!i.value || i.value == '') { alt('Forgot to add the button to disable?'); i.setCustomValidity('Invalid Value!'); i.reportValidity(); } else { let result = disabledbtns.MV_search(location.host); if (result.found) { if (!result.obj.buttons.includes(i.value)) { fselect.options.add(new Option(i.value, i.value)); result.obj.buttons.push(i.value); GM_setValue('disabledbtns', disabledbtns); rvals(); alt('Disabled successfully.'); } else alt('Button already disabled.'); } else { let obj = { host: location.host, buttons: [i.value] }; fselect.options.add(new Option(i.value, i.value)); disabledbtns.push(obj); GM_setValue('disabledbtns', disabledbtns); rvals(); alt('Disabled successfully.'); } } } fbtns[1].onclick = function() { if (fselect.selectedIndex > -1) { if (confirm('Are you sure you want to remove this rule?')) { this.disabled = true; let d = disabledbtns.MV_search(location.host).obj.buttons; d.splice(d.indexOf(fselect.value), 1); GM_setValue('disabledbtns', disabledbtns); rvals(); fselect.selectedOptions[0].remove(); } } } xselects[1].onchange = function() { if (this.selectedIndex > -1) xbtns[1].disabled = false; else xbtns[1].disabled = false; } xbtns[0].onclick = () => { let w = xselects[0].value; if (exclusions.includes(location.href) || exclusions.includes(location.host)) { alt('Page/Website is already excluded'); return; } if (w == 'page') { if (!confirm('Are you sure you want to add (' + location.href + ') to exclusions?')) return; xselects[1].options.add(new Option(location.href, location.href)); exclusions.push(location.href); GM_setValue('exclusions', exclusions); rvals(); remove(); } else { if (!confirm('Are you sure you want to add (' + location.host + ') to exclusions?')) return; xselects[1].options.add(new Option(location.host, location.host)); exclusions.push(location.host); GM_setValue('exclusions', exclusions); rvals(); remove(); } } xbtns[1].onclick = function() { if (xselects[1].selectedIndex > -1) { if (confirm('Are you sure you want to remove this rule?')) { this.disabled = true; exclusions.splice(exclusions.MV_search(xselects[1].value).index, 1); GM_setValue('exclusions', exclusions); rvals(); xselects[1].selectedOptions[0].remove(); } } } subbtn.onclick = () => { const reader = new FileReader(); reader.onload = e => { u.querySelector('#MV_sub').innerText = reader.result; alt('Please wait for a moment'); sh('subf'); subthis() } reader.readAsText(k.querySelector('input').files[0]); u.querySelectorAll('.MV_cbtn')[3].onclick = remsub; } convbtn.onclick = () => { let rs = { vid: convselect.selectedOptions[0].getAttribute('mv-vid'), key: convselect.selectedOptions[0].value } if (location.host.includes('facebook')) Download('', convselect.selectedOptions[0].getAttribute('mv-title'), convselect.value); else if (location.host.includes('youtube')) convert2('youtube', rs); if (location.host.includes('youtube')) { p.querySelector('select').disabled = true; p.querySelector('button').innerText = 'Converting...'; p.querySelector('button').disabled = true; } } } function cuiset() { const container = u.querySelector('.MV_container'), controls = u.querySelector('.MV_controls'), bar = u.querySelector('.MV_bar'), loaded = u.querySelector('.MV_loaded'), played = u.querySelector('.MV_played'), thumb = u.querySelector('.MV_thumb'), highlight = u.querySelector('.MV_highlight'), currenttime = u.querySelector('.MV_highlight .MV_currenttime'), thumbnail = u.querySelector('.MV_highlight .MV_thumbnail'), btns = u.querySelectorAll('.MV_cbtn'), time = u.querySelector('.MV_time'), volm = u.querySelector('.MV_vol'), vol = u.querySelector('input'), playbackm = u.querySelector('.MV_playbackm'), buffer = u.querySelector('.MV_buffer'), resizer = u.querySelector('.MV_resizer'), treechange = new CustomEvent('treechange', { cancelable: false, detail: { vid() { return container.querySelector('video'); } } }), observer = new MutationObserver(() => container.dispatchEvent(treechange)); observer.observe(container, { childList: true }); container.addEventListener('treechange', e => { if (e.detail.vid() && u.style.display == 'block') { e.detail.vid().onloadedmetadata = ee => { let v = e.detail.vid(); douiplz(v); douiplz(v); } } else if (!e.detail.vid() && u.style.display == 'block') douiplz('exit'); }); let idle = 0; container.onclick = e => { if (e.target.tagName != 'VIDEO') return; btns[0].click(); } container.ondblclick = e => { if (e.target.tagName != 'VIDEO') return; btns[6].click(); } container.onmousemove = () => { controls.style.display = 'block'; container.style.cursor = 'default'; setTimeout(() => { controls.style.opacity = 1; }, 10); idle = 0; } container.onwheel = e => { e.preventDefault(); let v = u.querySelector('video'); if (e.deltaY > 0) { if (v.muted) v.muted = false; if (v.volume - volstep >= 0) v.volume -= volstep; else v.volume = 0; } else if (e.deltaY < 0) { if (v.muted) v.muted = false; if (v.volume + volstep <= 1) v.volume += volstep; else v.volume = 1; } } container.onkeydown = e => { let vals = [play, stop, volplus, volminus, mute, smallback, smallforward, bigback, bigforward, incplayback, decplayback, resplayback, fullscreen, download, pipm, loop, customui], v = u.querySelector('video'); if (e.altKey || e.metaKey || vals.includes(e.code) || ((e.ctrlKey || e.shiftKey) && !['ArrowLeft', 'ArrowRight', 'Space', loop].includes(e.code))) return; if (e.code == 'ArrowLeft' && !e.ctrlKey && !e.shiftKey) v.currentTime -= smallstep; else if (e.code == 'ArrowRight' && !e.ctrlKey && !e.shiftKey) v.currentTime += smallstep; if (e.code == 'ArrowLeft' && e.ctrlKey && !e.shiftKey) v.currentTime -= smallctrl; else if (e.code == 'ArrowRight' && e.ctrlKey && !e.shiftKey) v.currentTime += smallctrl; if (e.code == 'ArrowLeft' && !e.ctrlKey && e.shiftKey) v.currentTime -= smallshift; else if (e.code == 'ArrowRight' && !e.ctrlKey && e.shiftKey) v.currentTime += smallshift; else if (e.code == 'ArrowUp') { if (v.volume + volstep <= 1) v.volume += volstep; else v.volume = 1; } else if (e.code == 'ArrowDown') { if (v.volume - volstep >= 0) v.volume -= volstep; else v.volume = 0; } else if (e.code == 'Space') { if (v.paused) v.play(); else v.pause(); } } u.onfullscreenchange = () => { let v = u.querySelector('video'), fullscreenelm = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; if (fullscreenelm) btns[6].innerHTML = svgnormalscreen; else { if (container.MV_hasClass('MV_theater')) { container.classList.remove('MV_theater'); u.classList.remove('MV_ctheater'); s.style.display = 'block'; container.style.width = ''; container.style.height = ''; container.style.maxWidth = container.getAttribute('mv-maxw'); } if (v.MV_hasClass('MV_vfullscreen')) { v.classList.remove('MV_vfullscreen'); s.style.display = 'block'; } buffer.style.left = (v.offsetLeft + (v.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (v.offsetTop + (v.offsetHeight / 2) - 30) + 'px'; btns[6].innerHTML = svgfullscreen; } } setInterval(() => { idle++; if (idle >= 3) { controls.style.opacity = 0; container.style.cursor = 'none'; setTimeout(() => { controls.style.display = 'none'; }, 500); } }, 1000); btns[0].onclick = () => { let v = u.querySelector('video'); if (v.paused) btns[0].innerHTML = svgpause; else btns[0].innerHTML = svgplay; KEY.code = play; handler(KEY); } btns[1].onclick = () => { KEY.code = stop; handler(KEY); } btns[2].onclick = () => { if (volm.style.width == '80px') volm.style.width = '0'; else volm.style.width = '80px'; } btns[3].onclick = () => { if (location.host == 'www.youtube.com') { let ysub = document.querySelector('.captions-text'), usub = u.querySelector('.MV_capt'); function ttt(ml) { let ysub = document.querySelector('.captions-text'), usub = u.querySelector('.MV_capt'), subb = u.querySelector('.MV_subb'); usub.innerText = ysub.innerText; subb.style.display = 'block'; subb.style.left = ((document.body.offsetWidth - subb.offsetWidth) / 2) - 20 + 'px'; } const obs = new MutationObserver(ttt) if (ysub) { obs.observe(ysub, { attributes: true, childList: true, subtree: true }); alt('Added YT Subtitles'); } else if (confirm('Adding subtitles in youtube adds the original captions in the video, if this is the inteded action please select the caption and enable it first before enabling the subtitle option. Otherwise select OK to upload your own.')) { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), v = u.querySelector('video'); if (isfullscreen) { KEY.code = fullscreen; handler(KEY); } v.pause(); sh('subt'); } } else { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), v = u.querySelector('video'); if (isfullscreen) { KEY.code = fullscreen; handler(KEY); } v.pause(); sh('subt'); } } btns[4].onclick = () => { if (playbackm.style.width == '30px') playbackm.style.width = '0'; else playbackm.style.width = '30px'; } btns[5].onclick = () => { KEY.code = download; handler(KEY); } btns[6].onclick = () => { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), v = u.querySelector('video'); if (isfullscreen) { KEY.code = fullscreen; handler(KEY); } dofull(u); container.style.width = ''; container.style.height = ''; container.style.maxWidth = container.getAttribute('mv-maxw'); if (container.MV_hasClass('MV_theater')) { container.classList.remove('MV_theater'); u.classList.remove('MV_ctheater'); } else { container.classList.add('MV_theater'); u.classList.add('MV_ctheater'); } buffer.style.left = (v.offsetLeft + (v.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (v.offsetTop + (v.offsetHeight / 2) - 30) + 'px'; } btns[7].onclick = () => { if (container.MV_hasClass('MV_theater')) { container.classList.remove('MV_theater'); u.classList.remove('MV_ctheater'); dofull(u); } let v = u.querySelector('video'); container.style.width = ''; container.style.height = ''; container.style.maxWidth = container.getAttribute('mv-maxw'); buffer.style.left = (v.offsetLeft + (v.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (v.offsetTop + (v.offsetHeight / 2) - 30) + 'px'; KEY.code = fullscreen; handler(KEY); } vol.onmousedown = () => { let v = u.querySelector('video'); vol.onmousemove = () => { if (v.muted) v.muted = false; v.volume = vol.value / 100; } vol.onmouseup = () => { if (v.muted) v.muted = false; v.volume = vol.value / 100; vol.onmousedown = null; } } vol.onkeydown = e => { e.preventDefault(); vol.blur(); container.focus(); } vol.onkeyup = e => { e.preventDefault(); vol.blur(); container.focus(); } for (let elm of btns) { elm.onkeydown = elm.onkeyup = e => { e.preventDefault(); container.focus(); } } playbackm.onclick = e => { if (e.target.tagName == 'SPAN') { let val = parseFloat(e.target.innerText), v = u.querySelector('video'); v.playbackRate = val; } } function calct(e, v, c = 0) { let rect = bar.getBoundingClientRect(), x = e.clientX - rect.left, d = (x / bar.offsetWidth) * v.duration; if (d < 0) d = 0; else if (d > v.duration) d = v.duration; if (c == 0) { v.currentTime = d; played.style.width = x + 'px'; highlight.style.left = x + 'px'; } else if (c == 1) { v.currentTime = d; played.style.width = x + 'px'; currenttime.innerText = d.MV_format(); if (v.videoHeight < 1440 && !v.src.startsWith('blob')) getvidth(v.src, d); highlight.style.left = x + 'px'; } else { currenttime.innerText = d.MV_format(); if (v.videoHeight < 1440 && !v.src.startsWith('blob')) getvidth(v.src, d); highlight.style.left = x + 'px'; } } let downed = false; bar.onmousedown = e => { let v = u.querySelector('video'); calct(e, v); downed = true; window.onmousemove = ee => { highlight.style.display = 'inline-block'; calct(ee, v, 1); } window.onmouseup = () => { highlight.style.display = 'none'; window.onmousemove = null; downed = false; } } bar.onmouseover = () => { bar.onmousemove = e => { let v = u.querySelector('video'); highlight.style.display = 'inline-block'; calct(e, v, 2); } } bar.onmouseout = () => { if (!downed) highlight.style.display = 'none'; } resizer.onmousedown = e => { let v = u.querySelector('video'), startX, startY, startWidth, startHeight; container.style.maxWidth = ''; startX = e.clientX; startY = e.clientY; startWidth = parseInt(getComputedStyle(container).width, 10); startHeight = parseInt(getComputedStyle(container).height, 10); window.onmousemove = ee => { container.style.width = (startWidth + ee.clientX - startX) + 'px'; container.style.height = (startHeight + ee.clientY - startY) + 'px'; buffer.style.left = (v.offsetLeft + (v.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (v.offsetTop + (v.offsetHeight / 2) - 30) + 'px'; } window.onmouseup = () => { window.onmousemove = null; window.onmouseup = null; buffer.style.left = (v.offsetLeft + (v.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (v.offsetTop + (v.offsetHeight / 2) - 30) + 'px'; } } } function vidset(v) { const container = u.querySelector('.MV_container'), loaded = u.querySelector('.MV_loaded'), played = u.querySelector('.MV_played'), time = u.querySelector('.MV_time'), volm = u.querySelector('.MV_vol'), vol = u.querySelector('input'), btns = u.querySelectorAll('.MV_cbtn'), buffer = u.querySelector('.MV_buffer'), inframe = () => window.self != window.top, vwidth = () => { let output; for (let i = 40; i < 300;) { if (16 * i >= window.innerWidth) { output = 16 * (i - 20); break; } i = i + 10; } return output + 'px'; }; { if (inframe()) { container.style.maxWidth = window.innerWidth.toFixed(0) + 'px'; v.classList.add('MV_framed'); s.classList.add('MV_hidden'); container.setAttribute('mv-maxw', container.style.maxWidth); } else if ((v.videoWidth > window.innerWidth || v.videoWidth == 0) && !inframe()) { container.style.maxWidth = vwidth(); container.setAttribute('mv-maxw', container.style.maxWidth); } if ((v.videoHeight > window.innerHeight && v.videoHeight > v.videoWidth) && !inframe()) v.classList.add('MV_maxheight'); if (v.paused) btns[0].innerHTML = svgplay; else btns[0].innerHTML = svgpause; let volume = v.volume; vol.value = (v.volume * 100).toFixed(0); volm.setAttribute('data-content', (v.volume * 100).toFixed(0)); if (v.volume == 0) btns[2].innerHTML = svgvolmute; else if (v.muted) btns[2].innerHTML = svgvolmute; else if (v.volume > 0 && v.volume < 0.33) btns[2].innerHTML = svgvollow; else if (v.volume > 0.33 && v.volume < 0.66) btns[2].innerHTML = svgvolmid; else if (v.volume > 0.66) btns[2].innerHTML = svgvolhigh; btns[4].innerText = v.playbackRate.toFixed(1); played.style.width = ((v.currentTime / v.duration) * 100) + '%'; time.innerText = v.currentTime.MV_format() + '/' + v.duration.MV_format(); buffer.style.left = (container.offsetLeft + (container.offsetWidth / 2) - 30) + 'px'; buffer.style.top = (container.offsetTop + (container.offsetHeight / 2) - 30) + 'px'; buffer.style.display = 'none'; try { for (let i = 0; i < v.buffered.length; i++) { let start = v.buffered.start(i), end = v.buffered.end(i), time = v.currentTime; if (time >= start && time <= end) { let percent = v.buffered.end(i) / v.duration; if (percent * 100 >= 95) percent = 100; else percent = 100 * Math.min(1, Math.max(0, percent)); loaded.style.width = percent + '%'; } } } catch (e) { return; } } v.addEventListener('play', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; btns[0].innerHTML = svgpause; }); v.addEventListener('pause', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; btns[0].innerHTML = svgplay; }); v.addEventListener('volumechange', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; if (this.volume == 0) btns[2].innerHTML = svgvolmute; else if (this.volume > 0 && this.volume < 0.33) btns[2].innerHTML = svgvollow; else if (this.volume > 0.33 && this.volume < 0.66) btns[2].innerHTML = svgvolmid; else if (this.volume > 0.66) btns[2].innerHTML = svgvolhigh; vol.value = (this.volume * 100).toFixed(0); volm.setAttribute('data-content', (this.volume * 100).toFixed(0)); }); v.addEventListener('ratechange', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; btns[4].innerText = this.playbackRate.toFixed(1); }); v.addEventListener('timeupdate', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; played.style.width = ((this.currentTime / this.duration) * 100) + '%'; time.innerText = this.currentTime.MV_format() + '/' + this.duration.MV_format(); for (let i = 0; i < this.buffered.length; i++) { let start = this.buffered.start(i), end = this.buffered.end(i), time = this.currentTime; if (time >= start && time <= end) { let percent = this.buffered.end(i) / this.duration; if (percent * 100 >= 95) percent = 100; else percent = 100 * Math.min(1, Math.max(0, percent)); loaded.style.width = percent + '%'; } } }); v.addEventListener('progress', function() { if (!this.parentElement.MV_hasClass('MV_container')) return; for (let i = 0; i < this.buffered.length; i++) { let start = this.buffered.start(i), end = this.buffered.end(i), time = this.currentTime; if (time >= start && time <= end) { let percent = this.buffered.end(i) / this.duration; if (percent * 100 >= 95) percent = 100; else percent = 100 * Math.min(1, Math.max(0, percent)); loaded.style.width = percent + '%'; } } }); v.addEventListener('waiting', () => { buffer.style.display = 'block'; }); v.addEventListener('canplay', () => { buffer.style.display = 'none'; }); v.addEventListener('ended', () => { if (u.style.display == 'block' && document.fullscreenElement && document.fullscreenElement.MV_hasClass('MV_container')) { KEY.code = fullscreen; handler(KEY); } }); } let ogv; function douiplz(v) { let order = () => { for (let i = 0; i < v.parentElement.children.length; i++) if (v.parentElement.children[i].tagName == 'VIDEO') return i; }, controls = () => { if (v.controls) return true; else return false; }; if (v == 'exit') { u.style.display = 'none'; ogv = false; return; } if (!ogv) { ogv = { parent: v.parentElement, order: order(), controls: controls() }; u.style.display = 'block'; u.querySelector('.MV_container').insertBefore(v, u.querySelector('.MV_container').firstChild); v.controls = false; vidset(v); v.focus(); } else { u.style.display = 'none'; v.controls = ogv.controls; ogv.parent.insertBefore(v, ogv.parent.children[ogv.order]); ogv = false; } } function alt(msg, time=3000) { a.innerText = msg; a.style.cursor = 'default'; a.style.margin = '0 ' + (document.body.offsetWidth - 500) / 2 + 'px'; a.style.display = 'block'; setTimeout(() => { a.style.opacity = '1'; }, 200); setTimeout(() => { a.style.opacity = '0'; }, time); setTimeout(() => { a.style.display = 'none'; }, time + 600); } function rvals() { play = GM_getValue('play', 'KeyK'); stop = GM_getValue('stop', 'KeyS'); volplus = GM_getValue('volplus', 'ArrowUp'); volminus = GM_getValue('volminus', 'ArrowDown'); volstep = parseFloat(GM_getValue('volstep', 0.05)); mute = GM_getValue('mute', 'KeyM'); smallback = GM_getValue('smallback', 'Comma'); smallforward = GM_getValue('smallforward', 'Period'); smallstep = parseFloat(GM_getValue('smallstep', 3)); bigback = GM_getValue('bigback', 'KeyJ'); bigforward = GM_getValue('bigforward', 'KeyL'); bigstep = parseFloat(GM_getValue('bigstep', 30)); incplayback = GM_getValue('incplayback', 'KeyT'); decplayback = GM_getValue('decplayback', 'KeyY'); playbackstep = parseFloat(GM_getValue('playbackstep', 0.1)); resplayback = GM_getValue('resplayback', 'KeyR'); fullscreen = GM_getValue('fullscreen', 'KeyF'); download = GM_getValue('download', 'KeyD'); pipm = GM_getValue('pipm', 'KeyP'); loop = GM_getValue('loop', 'KeyO'); customui = GM_getValue('customui', 'KeyZ'); smallctrl = parseFloat(GM_getValue('smallctrl', 10)); smallshift = parseFloat(GM_getValue('smallshift', 20)); bigctrl = parseFloat(GM_getValue('bigctrl', 90)); bigshift = parseFloat(GM_getValue('bigshift', 120)); exclusions = GM_getValue('exclusions', ['placeholder', 'www.soundcloud.com', 'www.spotify.com', 'open.spotify.com', 'discord.com']); disabledbtns = GM_getValue('disabledbtns', ['placeholder']); savedtime = GM_getValue('savedtime', ['placeholder']); hage = parseFloat(GM_getValue('hage', 7)); autoresume = GM_getValue('autoresume', false); autocustomui = GM_getValue('autocustomui', false); nocustomui = GM_getValue('nocustomui', ['placeholder', 'www.youtube.com', 'www.facebook.com']); noautoresume = GM_getValue('noautoresume', ['placeholder', 'www.youtube.com', 'www.facebook.com']); cuicss = GM_getValue('cuicss', ['linear-gradient(140deg, rgba(0, 0, 0, 1) 0%, rgba(85, 85, 85, 1) 89%, rgba(153, 153, 153, 1) 100%)', '#fff3', 'inherit', '#111', '#ccc', '#333', '#111', '#111', '#ccc', '#333', '#000', 'transparent', '#111', '#000', '#ccc', '#ccc', '#ccc', '#ccc', '#fff', '#0007']); ccss = GM_getValue('ccss', ''); } function ucss() { CUIBC.remove(); CCSS.remove(); CUIBC = GM_addStyle(`.MV_customui { background-image: ${cuicss[0]}; } .MV_controls { background: ${cuicss[1]}; } .MV_time { background: ${cuicss[2]}; color: ${cuicss[15]}; } .MV_vol input { background: ${cuicss[3]}; } .MV_vol input::-moz-range-thumb, .MV_vol input::-webkit-slider-thumb { background: ${cuicss[4]}; } .MV_playbackm span, .MV_playbackm { background: ${cuicss[5]}; color: ${cuicss[16]}; } .MV_playbackm span:hover { background: ${cuicss[6]}; color: ${cuicss[17]}; } .MV_bar { background: ${cuicss[7]}; } .MV_played { background: ${cuicss[8]}; } .MV_loaded { background: ${cuicss[9]}; } .MV_thumb { background: ${cuicss[10]}; } .MV_cbtn { background: ${cuicss[11]}; color: ${cuicss[14]}; } .MV_ctheater { background: ${cuicss[12]} } .MV_cbtn svg { fill: ${cuicss[13]}; } .MV_buffer { border-color: ${cuicss[13]} transparent; } .MV_vol:before { color: ${cuicss[14]}; } .MV_subb { color: ${cuicss[18]}; background: ${cuicss[19]}; }`); CCSS = GM_addStyle(ccss); } let recording = []; function record(v) { v.addEventListener('timeupdate', function() { let search1 = savedtime.MV_search(this.src), search2 = savedtime.MV_search(location.href); if (!recording.includes(this.src)) { recording.push(this.src); if ((search1.found || (search2.found && document.querySelectorAll('video').length == 1)) && !this.paused && this.currentTime < 20) resume(v); } if (this.currentTime > 20) { if (search1.found) { let obj = search1.obj; obj.href = location.href; obj.time = this.currentTime; obj.lastplayed = (new Date); } else if (search2.found && document.querySelectorAll('video').length == 1) { let obj = search2.obj; obj.src = this.src; obj.time = this.currentTime; obj.lastplayed = (new Date); } else { let obj = { href: location.href, src: this.src, time: this.currentTime, lastplayed: (new Date) }; savedtime.push(obj); } GM_setValue('savedtime', savedtime); rvals(); } }); v.addEventListener('ended', function() { this.setAttribute('mv-active', false); }); } function resume(v) { if (noautoresume.includes(location.host)) return; if (this && this.tagName == 'VIDEO') v = this; let search1 = savedtime.MV_search(v.src), search2 = savedtime.MV_search(location.href); if (search2.found && autoresume && document.querySelectorAll('video').length == 1) v.currentTime = search2.obj.time; else if (search1.found && autoresume) v.currentTime = search1.obj.time; else if ((search1.found || (search2.found && document.querySelectorAll('video').length == 1)) && !autoresume && v.currentTime < 20) { let time; if (search1.obj) time = search1.obj.time.MV_format(); else time = search2.obj.time.MV_format(); if (confirm('You stopped at (' + time + ') last time, continue?')) { if (search2.found && document.querySelectorAll('video').length == 1) v.currentTime = search2.obj.time; else if (search1.found) v.currentTime = search1.obj.time; if (confirm('Auto resume next time?')) { GM_setValue('autoresume', true); m.querySelector('input[name=ar]').checked = true; rvals(); } } else v.onplay = null; } else v.onplay = null; v.onplay = null; } function selectv() { window.oncontextmenu = t => { t.preventDefault(); let e = t.target; if (e.tagName == 'VIDEO') { e.setAttribute('mv-active', true); e.onended = () => e.setAttribute('mv-active', false); } else if (e.querySelector('video')) { e.querySelector('video').setAttribute('mv-active', true); e.querySelector('video').addEventListener('ended', function() { this.setAttribute('mv-active', false); }); alt('Video selected, press stop (' + stop + ') to disable selection.'); } else if (e.parentElement.querySelector('video')) { e.parentElement.querySelector('video').setAttribute('mv-active', true); e.parentElement.querySelector('video').addEventListener('ended', function() { this.setAttribute('mv-active', false); }); alt('Video selected, press stop (' + stop + ') to disable selection.'); } else if (e.parentElement.parentElement.querySelector('video')) { e.parentElement.parentElement.querySelector('video').setAttribute('mv-active', true); e.parentElement.parentElement.querySelector('video').addEventListener('ended', function() { this.setAttribute('mv-active', false); }); alt('Video selected, press stop (' + stop + ') to disable selection.'); } else if (e.parentElement.parentElement.parentElement.querySelector('video')) { e.parentElement.parentElement.parentElement.querySelector('video').setAttribute('mv-active', true); e.parentElement.parentElement.parentElement.querySelector('video').addEventListener('ended', function() { this.setAttribute('mv-active', false); }); alt('Video selected, press stop (' + stop + ') to disable selection.'); } else alt('Could\'t find the video unfortunately. :('); window.oncontextmenu = null; } } function convert(url, title) { GM_xmlhttpRequest({ url: 'https://fbdown.net/download.php', method: 'POST', data: 'URLz=' + encodeURIComponent(url), headers: { 'content-type': 'application/x-www-form-urlencoded;', 'host': 'fbdown.net', 'origin': 'https://fbdown.net', 'referer': 'https://fbdown.net/index.php' }, onload: r => { const doc = (new DOMParser).parseFromString(r.responseText, 'text/html'), sdl = doc.querySelector('#sdlink'), hdl = doc.querySelector('#hdlink'), sel = p.querySelector('select'); sel.innerHTML = ''; if (!hdl && !sdl) alt('An error has occured please try again.'); else { if (sdl && sdl.href) { let op = `<option value="${sdl.href}" mv-title="${title}"> SD Video </option>`; sel.innerHTML += op; } if (hdl && hdl.href) { let op = `<option value="${hdl.href}" mv-title="${title}"> HD Video </option>`; sel.innerHTML += op; } sh('cvt'); } } }); } function convert2(url, resolved) { if (!resolved) { GM_xmlhttpRequest({ url: 'https://www.y2mate.com/mates/en874/analyzeV2/ajax', method: 'POST', data: 'k_query=' + encodeURIComponent(url) + '&k_page=home&hl=en&q_auto=0', headers: { 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }, onload: r => { const json = JSON.parse(r.responseText), sel = p.querySelector('select'); if (json.c_status == 'FAILED') alt('Something went wrong, try again later.'); else { sh('cvt'); sel.innerHTML = ''; const title = json.title, links = json.links, vid = json.vid, mp4 = links.mp4, mp3 = links.mp3; for (let e in mp4) { const key = mp4[e].k, text = mp4[e].q_text, quality = mp4[e].q, op = `<option value="${key}" mv-vid="${vid}" mv-title="${title}" mv-quality="${quality}">${text}</option>`; sel.innerHTML += op; } for (let e in mp3) { const key = mp3[e].k, text = mp3[e].q_text, quality = mp3[e].q, op = `<option value="${key}" mv-vid="${vid}" mv-title="${title}" mv-quality="${quality}">${text}</option>`; sel.innerHTML += op; } } } }); } else { GM_xmlhttpRequest({ url: 'https://www.y2mate.com/mates/convertV2/index', method: 'POST', data: `vid=${resolved.vid}&k=${resolved.key}`, headers: { 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8' }, onload: r => { p.querySelector('select').disabled = false; p.querySelector('button').innerText = 'Download'; p.querySelector('button').disabled = false; const json = JSON.parse(r.responseText); if (json.c_status == 'FAILED') alt('Something went wrong, try again later.'); else { const dlink = json.dlink, title = json.title, ext = json.ftype Download('', title, dlink, ext); } } }); } } function Download(e, given, source, ext) { let src = source || e.src, title = given || src.MV_getName() || document.title || 'video', getlink = () => { let p = e.parentElement; do p = p.parentElement; while (!p.querySelector('a[aria-label="Enlarge"]') && !p.querySelector('div[aria-label="Enter fullscreen"]')); let l = p.querySelector('a[aria-label="Enlarge"]').href || p.querySelector('div[aria-label="Enter fullscreen"]').href; l.includes('__cft') ? l = l.substr(0, l.indexOf('__cft')-1) : l; return l; }, gettitle = () => { let p = e.parentElement; do p = p.parentElement; while (!p.querySelector('div[dir=auto]') && !p.querySelector('span[dir=auto]')); return (p.querySelector('div[dir=auto]') || p.querySelector('span[dir=auto]')).innerText; }; if (location.protocol.includes('file')) { alt('Trying to download a local file? Really??'); return; } title = title.trim(); if (!/\.(avi|mkv|flv|divx|mpe?g|webm|mp4|wmv|mov|ogv|ogm|ogx|m4v|m4a|mp3|aac)$/.test(title)) title += '.' + (ext || 'mp4'); title = title.replaceAll(/[\/\\|<>"?*:]\n/gm, '-'); if (location.href.includes('youtube.com') && !ext) convert2(location.href); else if (location.href.includes('facebook.com')) { if (u.style.display != 'block') convert(getlink(), gettitle()); else alt('Please exit custom UI first.'); } GM_download({ url: src, name: title, saveAs: true, onerror: function(error) { console.error(error); if (error.details === undefined) { if (GM_info.downloadMode == 'native') alt('Current Download Mode Isn\'t Compatible With The Script, Please Change The Download Mode To "Default" Or "Browser API" In TamperMonkey Settings!', 5000); else if (error.error.includes('canceled')) alt('Download Canceled.'); else if (error.error.includes('not_succeeded')) { GM_notification({ title: 'Download Failed!', text: 'Reason: NETWORK_ERROR\nClick Here To Restart.', onclick: () => Download(e, given, source, ext) }); } else if (error.error == 'filename must not contain illegal characters') { let newtitle = prompt('Please rename the file!\n\nFile name contains illegal characters / \\ | < > " ? * :\n\nCurrent name: '+title); if (newtitle === null || newtitle == title) { if (confirm('Cancel download?\n\nOK - Yes, cancel.\nCancel - No, don\'t cancel.')) return; else { newtitle = prompt('Then please rename the file!!!\n\nFile name contains illegal characters / \\ | < > " ? * :\n\nCurrent name: ' + title); if (newtitle === null || newtitle == title) alt('Download Canceled.'); else Download(e, newtitle, source, ext); } } else Download(e, newtitle, source, ext); } else if (!source) { if (location.href.includes('youtube.com')) convert2(location.href); else if (location.href.includes('facebook.com')) { if (u.style.display != 'block') convert(getlink(), gettitle()); else alt('Please exit custom UI first.'); } else alt('Cannot download this video, try online video converters.'); } else Download(e, given, source, ext); } else if (error.details.current == 'SERVER_FORBIDDEN') { GM_notification({ title: 'Download Failed!', text: 'Reason: SERVER_FORBIDDEN\nDetails: Server Closed Connection Due To Unauthorized Access OR The Link Expired.\nPlease Reload Then Try Again!', }); return; } else if (error.details.current != 'USER_CANCELED') { GM_notification({ title: 'Download Failed!', text: 'Reason: USER_CANCELED\nClick Here To Restart.', onclick: () => Download(e, given, source, ext) }); } } }); } let noffsetw, noffseth, noffsetl, foffsetw, foffseth; function dofull(e) { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), buffer = u.querySelector('.MV_buffer'), v = u.querySelector('video') || e; if (e.tagName == 'VIDEO') { if (!e.getAttribute('mv-ogctrls')) { e.setAttribute('mv-ogctrls', e.controls); e.controls = true; } else e.controls = e.getAttribute('mv-ogctrls'); } if (!isfullscreen) { if (e.requestFullscreen) e.requestFullscreen(); else if (e.mozRequestFullScreen) e.mozRequestFullScreen(); else if (e.webkitRequestFullScreen) e.webkitRequestFullScreen(); else if (e.msRequestFullscreen) e.msRequestFullscreen(); s.style.display = 'none'; v.classList.add('MV_vfullscreen'); if (e.MV_hasClass('MV_container')) { noffsetw = v.offsetWidth; noffseth = v.offsetHeight; noffsetl = v.offsetLeft; buffer.style.left = ((window.screen.width / 2) - 30) + 'px'; buffer.style.top = ((window.screen.height / 2) - 30) + 'px'; } } else { if (document.exitFullscreen) document.exitFullscreen(); else if (document.webkitExitFullscreen) document.webkitExitFullscreen(); else if (document.mozCancelFullScreen) document.mozCancelFullScreen(); else if (document.msExitFullscreen) document.msExitFullscreen(); s.style.display = 'block'; v.classList.remove('MV_vfullscreen'); if (e.MV_hasClass('MV_container')) { buffer.style.left = (noffsetl + (noffsetw / 2) - 30) + 'px'; buffer.style.top = ((noffseth / 2) - 30) + 'px'; } } } function timedloop(t1, t2, v) { let timer = () => { if (v.currentTime >= t2) v.currentTime = t1; }; v.addEventListener('timeupdate', timer); window.MV_timerloop = timer; v.play(); } function handler(e) { if (e.target.tagName == 'INPUT' || e.target.tagName == 'TEXTAREA' || e.altKey || e.metaKey || ((e.ctrlKey || e.shiftKey) && ![bigforward, bigback, smallforward, smallback, loop].includes(e.code)) || (e.target.tagName == 'DIV' && (e.target.MV_search('comment', 'includes').found || e.target.MV_search('Comment', 'includes').found || e.target.MV_search('editor', 'includes').found || e.target.MV_search('Editor', 'includes').found))) return; let key = e.code, v = document.querySelectorAll('video'), f, ui = false, fe = document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement, vals = [play, stop, volplus, volminus, mute, smallback, smallforward, bigback, bigforward, decplayback, incplayback, resplayback, fullscreen, download, pipm, loop, customui]; if (u.style.display == 'block') ui = true; if (disabledbtns.MV_search(location.host).found && disabledbtns.MV_search(location.host).obj.buttons.includes(key) && !ui) { if (ogv.parent) ogv.parent.focus(); else document.body.focus(); return; } if (vals.includes(key)) { if (u.style.display == 'block') { v = u.querySelector('video'); f = v.parentElement; } else if (fe && fe.tagName == 'VIDEO') v = fe; else if (fe && fe.querySelector('video')) v = fe.querySelector('video'); else if (v.length == 1) v = v[0]; else { let ps = []; for (let i = 0; i < v.length; i++) { let e = v[i]; if (!e.paused) ps.push(e); } if (ps.length == 1) v = ps[0]; else if (document.querySelector('video[mv-active=true]')) v = document.querySelector('video[mv-active=true]'); else { alt('Multiple videos found, please select one by right clicking it.', 5000); selectv(); return; } } } else return; if (v) v.setAttribute('mv-active', true); if (!f) f = v; if (ui) v.focus(); if (key == play) { if (v.paused) v.play(); else v.pause(); } else if (key == stop) { v.currentTime = 0; v.pause(); v.setAttribute('mv-active', false); } else if (key == volplus) { if (v.muted) v.muted = false; if (v.volume + volstep <= 1) v.volume += volstep; else v.volume = 1; } else if (key == volminus) { if (v.muted) v.muted = false; if (v.volume - volstep >= 0) v.volume -= volstep; else v.volume = 0; } else if (key == mute) { let btn = u.querySelectorAll('.MV_cbtn')[2]; if (v.muted) { v.muted = false; let vol = v.volume; v.volume = 0.5; v.volume = vol; } else { v.muted = true; setTimeout(() => { btn.innerHTML = svgvolmute; }, 10); } } else if (key == smallback && !e.ctrlKey && !e.shiftKey) v.currentTime -= smallstep; else if (key == smallforward && !e.ctrlKey && !e.shiftKey) v.currentTime += smallstep; else if (key == bigback && !e.ctrlKey && !e.shiftKey) v.currentTime -= bigstep; else if (key == bigforward && !e.ctrlKey && !e.shiftKey) v.currentTime += bigstep; else if (key == smallback && e.ctrlKey && !e.shiftKey) v.currentTime -= smallctrl; else if (key == smallforward && e.ctrlKey && !e.shiftKey) v.currentTime += smallctrl; else if (key == bigback && e.ctrlKey && !e.shiftKey) v.currentTime -= bigctrl; else if (key == bigforward && e.ctrlKey && !e.shiftKey) v.currentTime += bigctrl; else if (key == smallback && !e.ctrlKey && e.shiftKey) v.currentTime -= smallshift; else if (key == smallforward && !e.ctrlKey && e.shiftKey) v.currentTime += smallshift; else if (key == bigback && !e.ctrlKey && e.shiftKey) v.currentTime -= bigshift; else if (key == bigforward && !e.ctrlKey && e.shiftKey) v.currentTime += bigshift; else if (key == decplayback) { if (v.playbackRate + playbackstep <= 5) v.playbackRate += playbackstep; else v.playbackRate = 5; } else if (key == incplayback) { if (v.playbackRate - playbackstep >= 0.1) v.playbackRate -= playbackstep; else v.playbackRate = 0.1; } else if (key == resplayback) v.playbackRate = 1; else if (key == fullscreen) dofull(f); else if (key == download) Download(v); else if (key == pipm) { if (document.pictureInPictureElement) document.exitPictureInPicture(); else if (document.pictureInPictureEnabled) v.requestPictureInPicture(); } else if (key == loop && !e.ctrlKey && e.shiftKey) { if (!window.MV_timerloop) { v.pause(); let time1 = v.currentTime, controler = e => { v.removeEventListener('seeked', controler); let time2 = v.currentTime; alt('Looping from ' + time1.MV_format() + ' To ' + time2.MV_format()); timedloop(time1, time2, v); }; alt('Loop start point set: ' + time1.MV_format() + '\nPlease set end point by seeking.'); v.addEventListener('seeked', controler); } else { v.removeEventListener('timeupdate', window.MV_timerloop); window.MV_timerloop = undefined; alt('Looping stopped.'); } } else if (key == loop) { if (v.loop) v.loop = false; else v.loop = true; } else if (key == customui) douiplz(v); } function deleteold() { for (let i = 1; i < savedtime.length; i++) { let e = savedtime[i]; if (e.lastplayed) { let age = (new Date((new Date) - (new Date(e.lastplayed)))).getDate(); if (age > hage + 1) savedtime.splice(i, 1); } } GM_setValue('savedtime', savedtime); rvals(); } function br(mode) { const i = document.querySelector('.MV_b input'), fr = new FileReader(), f = i.files[0]; let res; if (!fr) alt('File API not supported!'); else if (mode == 0) { const a = document.createElement('a'), date = (new Date).toDateString().split(' '), time = date[2] + '-' + date[1], names = GM_listValues(), values = [], parsed = []; names.forEach(e => { values.push(GM_getValue(e)); }); parsed.push(names); parsed.push(values); a.href = 'data:text/plain;charset=utf-8,' + encodeURIComponent(JSON.stringify(parsed)); a.download = '(' + time + ').XDHx86_MyVideo.data.txt'; a.click(); a.remove(); } else if (mode == 1) { if (!f) { alt('Please select a file!'); return; } fr.onload = () => { res = fr.result; } fr.readAsText(f); setTimeout(() => { let arr = JSON.parse(res), g = arr[0], v = arr[1]; if (!g || !g.MV_search('firsttime').found) alt('This is not a backup file, please check the uploaded file.'); else { for (let i = 0; i < g.length; i++) GM_setValue(g[i], v[i]); if (confirm('Settings will take effect after reload.\nReload now?')) location.reload(); } }, 1500); } } function feedback() { let html = document.createElement('div'), css = document.createElement('style'); html.className = 'MV_fcontainer'; html.innerHTML = '<div class="MV_main"> <h3 class="MV_head"> Subject: </h3> <input class="MV_sub"> <h3 class="MV_head"> Message Body: </h3> <span> Please don\'t actually use this to write your message and use an editor then paste here. </span> <br> <textarea class="MV_msg" spellcheck="true" style=" "></textarea> <br> <br> <button class="MV_send"> Send </button> </div>'; css.innerHTML = '.MV_fcontainer { z-index: 2147483644; top: 0; left: 0; position: absolute; background-color: #000c; color: #090; width: 100%; height: 100%; display: flex; transition: all 0.5s; user-select: none; } .MV_main { margin: auto; transition: inherit; background-color: #000; height: 70%; padding: 20px; border-radius: 15px; width: 50%; box-shadow: 0 0 20px 20px #090; } .MV_head { margin: 15px 0 0; } .MV_fcontainer input { width: auto; min-width: 100px; margin: 2px; background-color: #111; color: #777; border: none; padding: 2px; outline: 0; margin-left: 15px; font-weight: bolder; outline: 0; transition: inherit; } .MV_fcontainer input:focus { box-shadow: 0 0 5px 2px #090; padding: 3px; margin: 5px 1px 5px 10px; outline: 0; border: 1px solid #090; } .MV_fcontainer span { margin-left: 15px; } .MV_msg { width: calc(100% - 40px); height: calc(100% - 250px); min-width: 100px; margin: 2px; background-color: #111; color: #777; border: none; padding: 2px; outline: 0; margin-left: 15px; font-weight: bolder; outline: 0; transition: inherit; } .MV_send:hover { color: #090; background-color: #000; } .MV_send { transition: inherit; border: none; color: #000; background-color: #090; outline: 0; font-family: sans-serif; cursor: pointer; padding: 5px 20px; font-weight: bolder; margin-left: 10px; margin-top: 10px; }'; document.body.appendChild(html); document.head.appendChild(css); html.onclick = e => { if (e.target.MV_hasClass('MV_fcontainer')) { html.remove(); css.remove(); } } html.querySelector('.MV_send').onclick = () => { let sub = html.querySelector('.MV_sub'), msg = html.querySelector('.MV_msg'), validate = () => { let output = true; if (!msg.value) { msg.setCustomValidity('Message body is required'); msg.reportValidity(); msg.onfocus = () => msg.setCustomValidity(''); alt('Message body is required!'); output = false; } return output; }; if (validate()) { if (!sub.value) sub.value = 'My Video v' + GM_info.script.version + ' feedback'; let link = 'mailto:xdhx86@gmail.com&subject=' + encodeURIComponent(sub.value) + '&body=' + encodeURIComponent(msg.value); window.open(link, '_blank'); html.remove(); css.remove(); alt('Thanks for the feedback!'); } } } function getvidth(link, seekto=0) { let vid = document.createElement('video'), thumbnail = u.querySelector('.MV_thumbnail'); thumbnail.innerHTML = '<span class="MV_rotate"></span>'; vid.src = link; vid.load(); vid.onloadedmetadata = () => { if (vid.duration < seekto) seekto = vid.duration; vid.onseeked = () => { let canvas = document.createElement('canvas'); canvas.width = vid.videoWidth; canvas.height = vid.videoHeight; let ctx = canvas.getContext('2d'); ctx.drawImage(vid, 0, 0, canvas.width, canvas.height); thumbnail.innerHTML = ''; thumbnail.appendChild(ctx.canvas); vid.remove(); ctx = canvas = vid = undefined; } setTimeout(() => { vid.currentTime = seekto; }, 200); } } function remove() { c.remove(); f.remove(); m.remove(); o.remove(); s.remove(); u.remove(); x.remove(); window.onkeydown = null; for (let e of document.querySelectorAll('video')) e.onplay = null; let cmd = GM_registerMenuCommand('Remove from exclusions ('+location.host+')', () => { if (exclusions.MV_search(location.href).found) { if (!confirm('Are you sure you want to remove (' + location.href + ') from exclusions?')) return; exclusions.splice(exclusions.MV_search(location.href).index, 1); GM_setValue('exclusions', exclusions); rvals(); include(); } else { if (!confirm('Are you sure you want to remove (' + location.host + ') from exclusions?')) return; exclusions.splice(exclusions.MV_search(location.host).index, 1); GM_setValue('exclusions', exclusions); rvals(); include(); } GM_unregisterMenuCommand(cmd); }); alt('Added successfully. To remove go to TamperMonkey addon menu'); setTimeout(() => a.remove, 6000); } let removesubpls; function subthis() { removesubpls = false; let subj = [{ key: '0', from: '00:00:00', to: '00:00:00', text: 'Place Holder' }], arr = u.querySelector('#MV_sub').innerHTML.split('<br><br>'); arr.forEach(e => { if (e.split('<br>')[1]) { let parts = e.split('<br>'), key = parts[0], from = parts[1].split(' --> ')[0].split(',')[0], to = parts[1].split(' --> ')[1].split(',')[0], text = parts.splice(2).join(' '), obj = { key: key, from: from, to: to, text: text }; subj.push(obj); } }); u.querySelector('video').addEventListener('timeupdate', function(e) { let time = u.querySelector('.MV_time').innerText.split('/')[0], subb = u.querySelector('.MV_subb'), capt = u.querySelector('.MV_capt'); if (removesubpls) { capt.innerText = ''; subb.style.display = 'none'; return; } for (let i = 0; i < subj.length; i++) { if (subj[i].from < time && subj[i].to > time) { capt.innerText = subj[i].text; subb.style.display = 'block'; } if (subj[i].from == time) { capt.innerText = subj[i].text; subb.style.display = 'block'; } if (subj[i].to == time) { capt.innerText = ''; subb.style.display = 'none'; } } subb.style.left = ((document.body.offsetWidth - subb.offsetWidth) / 2) - 20 + 'px'; }); alt('Subtitle imported successfully'); } function remsub() { let v = u.querySelector('video'), subb = u.querySelector('.MV_subb'), capt = u.querySelector('.MV_capt'), sub = u.querySelector('#MV_sub'), subbtn = u.querySelectorAll('.MV_cbtn')[3]; v.pause(); if (!confirm('This will remove current subtitle, are you sure?')) return; removesubpls = true; subb.style.display = 'none'; sub.innerHTML = ''; subbtn.onclick = () => { if (location.host == 'www.youtube.com') { let ysub = document.querySelector('.captions-text'), usub = u.querySelector('.MV_capt'); function ttt(ml) { let ysub = document.querySelector('.captions-text'), usub = u.querySelector('.MV_capt'), subb = u.querySelector('.MV_subb'); usub.innerText = ysub.innerText; subb.style.display = 'block'; subb.style.left = ((document.body.offsetWidth - subb.offsetWidth) / 2) - 20 + 'px'; } const obs = new MutationObserver(ttt) if (ysub) { obs.observe(ysub, { attributes: true, childList: true, subtree: true }); alt('Added YT Subtitles'); } else if (confirm('Adding subtitles in youtube adds the original captions in the video, if this is the inteded action please select the caption and enable it first before enabling the subtitle option. Otherwise select OK to upload your own.')) { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), v = u.querySelector('video'); if (isfullscreen) { KEY.code = fullscreen; handler(KEY); } v.pause(); sh('subt'); } } else { let isfullscreen = (document.fullscreenElement && document.fullscreenElement !== null) || (document.webkitFullscreenElement && document.webkitFullscreenElement !== null) || (document.mozFullScreenElement && document.mozFullScreenElement !== null) || (document.msFullscreenElement && document.msFullscreenElement !== null), v = u.querySelector('video'); if (isfullscreen) { KEY.code = fullscreen; handler(KEY); } v.pause(); sh('subt'); } } } let INTERVAL, tracked = []; function include() { ui(); set(); cuiset(); window.onkeydown = handler; INTERVAL = setInterval(() => { for (let e of document.querySelectorAll('video')) { if (!tracked.includes(e.src)) { let search1 = savedtime.MV_search(e.src), search2 = savedtime.MV_search(location.href); record(e); tracked.push(e.src); if ((search1.found || (search2.found && document.querySelectorAll('video').length == 1))) e.onplay = resume; else e.onplay = null; } } }, 3000); } if (location.href.MV_includes(exclusions)) { let cmd = GM_registerMenuCommand('Remove from exclusions ('+location.host+')', () => { if (exclusions.MV_search(location.href).found) { if (!confirm('Are you sure you want to remove (' + location.href + ') from exclusions?')) return; exclusions.splice(exclusions.MV_search(location.href).index, 1); GM_setValue('exclusions', exclusions); rvals(); include(); alt('Removed successfully.'); } else { if (!confirm('Are you sure you want to remove (' + location.host + ') from exclusions?')) return; exclusions.splice(exclusions.MV_search(location.host).index, 1); GM_setValue('exclusions', exclusions); rvals(); include(); alt('Removed successfully.'); } GM_unregisterMenuCommand(cmd); }); } else { include(); let added = false, cuiloader = (retries=0) => { if (retries >= 3 || added) return; if (autocustomui && document.querySelectorAll('video').length == 1) { let v = document.querySelector('video'); added = true; v.ontimeupdate = v.oncanplay = v.onplay = v.onplaying = v.onprogress = e => { v.ontimeupdate = v.oncanplay = v.onplay = v.onplaying = v.onprogress = null; if (u.style.display != 'block') douiplz(v); } } } if (!nocustomui.includes(location.host)) { let i = 0, int = setInterval(() => { if (!added) { cuiloader(i); i++; } if (added || i >= 3) clearInterval(int); }, 3000); } } deleteold(); GM_registerMenuCommand('Feedback', feedback); })();