您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Some fixes for Youtube polymer engine
当前为
// ==UserScript== // @name Youtube polymer engine fixes // @description Some fixes for Youtube polymer engine // @namespace bo.gd.an[at]rambler.ru // @version 2.5.11 // @match https://www.youtube.com/* // @compatible firefox 56 // @author Bogudan // @grant GM_info // @grant GM.info // @grant GM_getValue // @grant GM.getValue // @grant GM_setValue // @grant GM.setValue // @noframes // @run-at document-start // @license CC-BY-NC-ND-4.0 // ==/UserScript== (function () { 'use strict'; if (document.location.pathname == '/error') // нам нечего делать на страницах с ошибками return; // test local storage availability and load settings from there first let settings, ls, saver; try { function lsTest (st, v) { st.setItem ('__fix_test__', v); return st.getItem ('__fix_test__') == v; }; const _s = window.localStorage; if (lsTest (_s, 'qwe') && lsTest (_s, 'rty')) { // do 2 times just in case LS stored value once, but does not let change it later ls = _s; ls.removeItem ('__fix_test__'); settings = JSON.parse (ls.getItem ('__fix__settings__')); } } catch (e) { } // select storage: GM_*/GM.* or local storage (in case userscript manager does not grant us GMs) if (typeof (GM_getValue) !== 'undefined' && typeof (GM_setValue) !== 'undefined' && GM_getValue && GM_setValue) { saver = function () { GM_setValue ('settings', settings); if (ls) ls.removeItem ('__fix__settings__'); } if (!settings) settings = GM_getValue ('settings', {}); else saver (); settings.storage = 'GM_*Value'; } else if (typeof (GM) !== 'undefined' && GM && GM.getValue && GM.setValue) { saver = function () { (async () => await GM.setValue ('settings', settings)) (); if (ls) ls.removeItem ('__fix__settings__'); }; if (!settings) settings = (async () => await GM.getValue ('settings', {})) (); else saver (); settings.storage = 'GM.*Value'; } else if (ls) { if (!settings) settings = {}; saver = function () { ls.setItem ('__fix__settings__', JSON.stringify (settings)); }; settings.storage = 'window.localStorage.*Item'; } else settings = {}; // delete old settings if ("default_player_640" in settings) { // удалено в 0.5 settings.default_player = settings.default_player_640 ? 3 : 0; delete settings.default_player_640; } if ("reduce_thumbnail" in settings) { // удалено в 0.6.0 settings.thumbnail_size = settings.reduce_thumbnail ? 2 : 0; delete settings.reduce_thumbnail; } if ("reduce_font" in settings) { // удалено в 2.5.8: размеры текста уменьшились на стороне YT settings.fix_removed_placeholder = settings.reduce_font; delete settings.reduce_font; } // set default values const gminfo = typeof (GM_info) !== 'undefined' && GM_info || typeof (GM) !== 'undefined' && GM && GM.info; const fix_version = gminfo && gminfo.script && gminfo.script.version; if (fix_version) { settings.version = fix_version; if (!("inst_ver" in settings)) settings.inst_ver = fix_version; } if (!("align_player" in settings)) settings.align_player = 0; if (!("default_player" in settings)) settings.default_player = 0; if (!("hide_guide" in settings)) settings.hide_guide = true; if (!("hide_yt_suggested_blocks" in settings)) settings.hide_yt_suggested_blocks = true; if (!("logo_target" in settings)) settings.logo_target = ""; if (!("fix_removed_placeholder" in settings)) settings.fix_removed_placeholder = true; if (!("theater_player" in settings)) settings.theater_player = 0; if (!("thumbnail_size" in settings)) settings.thumbnail_size = 2; if (!("thumbnail_size_m" in settings)) settings.thumbnail_size_m = 720; if (!("unfix_header" in settings)) settings.unfix_header = true; if (!("search_thumbnail" in settings)) settings.search_thumbnail = 0; if (!("clear_search" in settings)) settings.clear_search = false; if (!("channel_top" in settings)) settings.channel_top = 0; if (!("try_load_more" in settings)) settings.try_load_more = false; if (!("unbound_video_title" in settings)) settings.unbound_video_title = false; if (!("video_quality" in settings)) settings.video_quality = 0; if (!("no_resume_time" in settings)) settings.no_resume_time = false; console.log ('fix settings:', settings); // catch "settings" page if (document.location.pathname == '/fix-settings') { document.title = "YouTube Polymer Fixes: Settings"; const back = document.createElement ('div'); back.className = 'ytfixback'; const plane = document.createElement ('div'); plane.className = 'ytfix'; const style = document.createElement ('style'); style.type = 'text/css'; style.innerHTML = ` .ytfix{position:absolute;left:0;top:0;right:0;background:#eee;padding:3em} .ytfix_line{margin:1em} .ytfix_line span,.ytfix_line input,.ytfix_line select{margin-right:1em} .ytfix_field{padding:0.2em;border:1px solid #888} .ytfix_button{padding:0.4em;border:1px solid #888} .ytfix_hide{display:none} .ytfixback{position:absolute;left:0;top:0;right:0;height:100%;background:#eee} `; plane.appendChild (style); function AddLine () { const q = document.createElement ('div'); q.className = 'ytfix_line'; for (let i = 0, L = arguments.length; i < L; ++i) q.appendChild (arguments [i]); plane.appendChild (q); } let e1, e2; e1 = document.createElement ('b'); e1.appendChild (document.createTextNode ('YouTube Polymer Fixes: Settings')); AddLine (e1); if (fix_version) { e1 = document.createElement ('b'); e1.appendChild (document.createTextNode (`Version: ${fix_version}`)); AddLine (e1); } if (!saver) { e1 = document.createElement ('span'); e1.style = 'color:red'; e1.appendChild (document.createTextNode ('Cannot edit settings: no access to any storage.')); AddLine (e1); e1 = document.createElement ('span'); e1.appendChild (document.createTextNode ('If you are using Firefox, allow cookies for this site.')); AddLine (e1); } else { const ess = {}; function MakeDesc (desc) { const e = document.createElement ('span'); e.appendChild (document.createTextNode (desc)); return e; } function MakeBoolElement (nm) { const e = document.createElement ('input'); e.type = 'checkbox'; e.checked = settings [nm]; ess [nm] = e; return e; } function MakeListElement (nm, opts) { const e = document.createElement ('select'); e.className = 'ytfix_field'; ess [nm] = e; for (let i = 0, L = opts.length; i < L; ++i) { const o = document.createElement ('option'); o.appendChild (document.createTextNode (opts [i])); e.appendChild (o); } e.selectedIndex = settings [nm]; return e; } function MakeTextElement (nm) { const e = document.createElement ('input'); e.className = 'ytfix_field'; e.value = settings [nm]; ess [nm] = e; return e; } function MakeButton (text, click) { const e = document.createElement ('input'); e.type = 'button'; e.className = 'ytfix_button'; e.value = text; e.addEventListener ('click', click); return e; } AddLine (MakeBoolElement ("hide_guide"), MakeDesc ('Hide "Guide" menu when page opens')); AddLine (MakeBoolElement ("fix_removed_placeholder"), MakeDesc ('Make size of "Video removed" placeholder about the same as removed video description')); const tsm = MakeTextElement ("thumbnail_size_m"); tsm.className = settings.thumbnail_size == 5 ? 'ytfix_field' : 'ytfix_hide'; const tsi = MakeListElement ("thumbnail_size", ['default', '180px', '240px', '360px', '480px', 'manual']); tsi.addEventListener ('change', function () { ess.thumbnail_size_m.className = ess.thumbnail_size.selectedIndex == 5 ? 'ytfix_field' : 'ytfix_hide'; }); AddLine (MakeDesc ('Set thumbnails width for front page'), tsi, tsm); AddLine (MakeDesc ('Set thumbnails width for search page'), MakeListElement ("search_thumbnail", ['default', '240px', '360px'])); AddLine (MakeDesc ("Set player height in default mode"), MakeListElement ("default_player", ['default', '144px', '240px', '360px', '480px', '720px'])); AddLine (MakeDesc ("Set player height in theater mode"), MakeListElement ("theater_player", ['default', '144px', '240px', '360px', '480px', '720px'])); AddLine (MakeBoolElement ("hide_yt_suggested_blocks"), MakeDesc ('Hide suggestions blocks on main page (recommended playlists, latest posts, etc.)')); AddLine (MakeBoolElement ("clear_search"), MakeDesc ("Hide suggestions blocks in search (for you, people also watched, etc.)")); AddLine (MakeBoolElement ("unfix_header"), MakeDesc ("Unstick header bar from top of the screen")); AddLine (MakeDesc ("Align resized player into it's container (normal and theater modes)"), MakeListElement ("align_player", ['center', 'left', 'right'])); AddLine (MakeDesc ("Modify channels' pages behaviour"), MakeListElement ('channel_top', ['default', 'hide banner with scrolling', 'hide banner on load'])); AddLine (MakeBoolElement ('try_load_more'), MakeDesc ('Add button to try loading more content on pages with dynamic content load')); AddLine (MakeBoolElement ('unbound_video_title'), MakeDesc ('Remove size limit for video titles')); AddLine (MakeDesc ("Change YT logo target to https://www.youtube.com/..."), MakeTextElement ("logo_target")); AddLine (MakeBoolElement ("no_resume_time"), MakeDesc ('Remove resume time from the video links (&t=...)')); AddLine (MakeDesc ('Starting video quality'), MakeListElement ('video_quality', ['Auto (default)', '2160p (4K)', '1440p (HD)', '1080p (HD)', '720p', '480p', '360p', '240p', '144p'])); e1 = MakeButton ('Save settings and return to YouTube', function () { settings.hide_guide = ess.hide_guide.checked; settings.fix_removed_placeholder = ess.fix_removed_placeholder.checked; settings.thumbnail_size = ess.thumbnail_size.selectedIndex; if (settings.thumbnail_size == 5) { const v = ess.thumbnail_size_m.value; if (!/^\d+$/.test (v)) { alert ('Error: invalid value for thumbnails size'); return; } settings.thumbnail_size_m = parseInt (v); } settings.search_thumbnail = ess.search_thumbnail.selectedIndex; settings.default_player = ess.default_player.selectedIndex; settings.theater_player = ess.theater_player.selectedIndex; settings.hide_yt_suggested_blocks = ess.hide_yt_suggested_blocks.checked; settings.unfix_header = ess.unfix_header.checked; settings.align_player = ess.align_player.selectedIndex; settings.channel_top = ess.channel_top.selectedIndex; settings.logo_target = ess.logo_target.value; settings.clear_search = ess.clear_search.checked; settings.try_load_more = ess.try_load_more.checked; settings.unbound_video_title = ess.unbound_video_title.checked; settings.video_quality = ess.video_quality.selectedIndex; settings.no_resume_time = ess.no_resume_time.checked; saver (); alert ('Settings saved'); history.back (); }); e2 = MakeButton ('Return to YouTube without saving', function () { history.back (); }); AddLine (e1, e2); e1 = MakeButton ('Export settings', function () { const d = document.createElement ('a'); d.style.display = 'none'; d.setAttribute ('download', 'ytfix_settings.json'); d.setAttribute ('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent (JSON.stringify (settings))); document.body.appendChild (d); d.click (); document.body.removeChild (d); }); e2 = MakeButton ('Import settings', function () { const f = document.createElement ('input'); f.type = 'file'; f.style.display = 'none'; f.addEventListener ('change', function () { if (f.files.length != 1) return; const rdr = new FileReader (); rdr.addEventListener ('load', function () { try { settings = JSON.parse (rdr.result); saver (); alert ('Settings imported'); document.location.reload (); } catch (ex) { alert ('Error parsing settings\n' + ex); } }); rdr.addEventListener ('error', () => alert ('Error loading file\n' + rdr.error)); rdr.readAsText (f.files [0]); }); document.body.appendChild (f); f.click (); document.body.removeChild (f); }); AddLine (e1, e2); } let int = setInterval (function () { if (!document.body) return; document.body.appendChild (back); document.body.appendChild (plane); clearInterval (int); }, 1); console.log ('Settings page created'); return; } // apply settings let styles = ''; const inject_func = [], inject_ints = []; if (settings.hide_guide) { function HideGuideTimer (info) { if (info.act == 0 && document.location.toString () != info.url) // обнаружение смены адреса info.act = 1; if (info.act == 1) { // wait for sorp page load completion const Q = document.getElementsByTagName ('yt-page-navigation-progress'); if (!Q.length || !Q [0].hasAttribute ('hidden')) return; info.act = 2; } if (info.act == 2) { // wait for button and press it if necessary const guide_button = document.getElementById ('guide-button'); if (!guide_button) return; let tmp = guide_button.getElementsByTagName ('button'); if (!tmp.length) return; tmp = tmp [0]; if (!tmp.hasAttribute ('aria-pressed')) return; if (tmp.attributes ['aria-pressed'].value == 'true') guide_button.click (); else { info.url = document.location.toString (); info.act = 0; window.dispatchEvent (new Event ('resize')); } } } inject_func.push (HideGuideTimer); inject_ints.push ({ call: HideGuideTimer, params: [{ act: 2 }] }); } if (settings.fix_removed_placeholder) styles += 'paper-button.style-blue-text,tp-yt-paper-button.style-blue-text{padding:0!important}'; if (settings.thumbnail_size) styles += 'ytd-rich-item-renderer{width:' + [0, 180, 240, 360, 480, settings.thumbnail_size_m] [settings.thumbnail_size] + 'px!important}'; if (settings.hide_yt_suggested_blocks) styles += 'div#contents.ytd-rich-grid-renderer ytd-rich-section-renderer{display:none!important}'; if (settings.unfix_header) styles += ` div#masthead-container.ytd-app,ytd-mini-guide-renderer.ytd-app,app-drawer#guide{position:absolute!important} ytd-feed-filter-chip-bar-renderer{position:relative!important} div#chips-wrapper{position:absolute!important;top:0!important} `; if (settings.search_thumbnail) { const sz = [0, 240, 360] [settings.search_thumbnail] + 'px!important'; // min-width defaults to 240px, max-width defaults to 360px // sizes for: videos, playlists, channels, mixes styles += `ytd-video-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-video-renderer,ytd-playlist-renderer[use-prominent-thumbs] ytd-playlist-thumbnail.ytd-playlist-renderer,ytd-channel-renderer[use-prominent-thumbs] #avatar-section.ytd-channel-renderer,ytd-radio-renderer[use-prominent-thumbs] ytd-thumbnail.ytd-radio-renderer{min-width:${sz};max-width:${sz}}`; } if (settings.clear_search) styles += 'ytd-two-column-search-results-renderer ytd-shelf-renderer.style-scope.ytd-item-section-renderer,ytd-two-column-search-results-renderer ytd-horizontal-card-list-renderer.style-scope.ytd-item-section-renderer{display:none!important}'; styles += [ '#player-theater-container{margin-left:auto!important;margin-right:auto!important}', '#player-container-outer{margin-left:0!important}', '#player-container-outer{margin-right:0!important}#player-theater-container{margin-left:auto!important}', ] [settings.align_player]; const sizes = [0, 144, 240, 360, 480, 720]; const size_norm = sizes [settings.default_player]; if (size_norm) styles += ` ytd-watch-flexy{--ytd-watch-flexy-min-player-height:${size_norm}px!important;--ytd-watch-flexy-max-player-height:${size_norm}px!important;--ytd-watch-flexy-max-player-width:var(--ytd-watch-flexy-min-player-width)!important} #primary{min-width:calc(max(var(--ytd-watch-flexy-min-player-height)*16/9,var(--ytd-watch-flexy-min-player-width)))!important;max-width:calc(max(var(--ytd-watch-flexy-min-player-height)*16/9,var(--ytd-watch-flexy-min-player-width)))!important} `; const size_theater = sizes [settings.theater_player]; if (size_theater) styles += `ytd-watch-flexy:not([fullscreen])[theater] #player-theater-container{min-width:calc(${size_theater}px*var(--ytd-watch-flexy-width-ratio)/var(--ytd-watch-flexy-height-ratio))!important;max-width:calc(${size_theater}px*var(--ytd-watch-flexy-width-ratio)/var(--ytd-watch-flexy-height-ratio))!important;min-height:${size_theater}px!important;max-height:${size_theater}px!important;height:${size_theater}px!important}`; if (size_norm || size_theater) { function SetPlayerSize (sn, st) { const eq = document.getElementsByTagName ("ytd-watch-flexy"); if (!eq.length) return; const s = eq [0].hasAttribute ('theater') ? st : sn; if (!s) return; const ep = document.getElementById ("movie_player"); if (ep && ep.setInternalSize && ep.isFullscreen && ep.getPlayerSize && !ep.isFullscreen () && ep.getPlayerSize ().height != s) ep.setInternalSize (); } inject_func.push (SetPlayerSize); inject_ints.push ({ call: SetPlayerSize, params: [size_norm, size_theater] }); } if (settings.logo_target) { let url = settings.logo_target; if (url [0] != '/') url = '/' + url; url = document.location.origin + url; function SetLogoURL (url) { const l = document.querySelectorAll ('a#logo'); for (let i = l.length; --i >= 0; ) { const Q = l [i]; const D = Q.data; if (D && D.commandMetadata && Q.href != url) { Q.href = url; D.commandMetadata.webCommandMetadata.url = url; } } } inject_func.push (SetLogoURL); inject_ints.push ({ call: SetLogoURL, params: [url] }); } if (settings.channel_top) styles += 'app-header#header.style-scope.ytd-c4-tabbed-header-renderer{transform:none!important;position:absolute;left:0px!important;top:0px;margin-top:0px}'; if (settings.channel_top > 1) styles += ` div#contentContainer.style-scope.app-header-layout{padding-top:148px!important} div#contentContainer.style-scope.app-header{height:148px!important} div.banner-visible-area.style-scope.ytd-c4-tabbed-header-renderer{display:none!important} `; if (settings.try_load_more) { function TryLoadMore () { const l = document.querySelectorAll ('#show-more-button'); let i = l.length; if (--i >= 0 && l [i].hasAttribute ('hidden')) { l [i].removeAttribute ('hidden'); l [i].innerText = 'TRY LOAD MORE'; } while (--i >= 0) l [i].parentNode.removeChild (l [i]); } inject_func.push (TryLoadMore); inject_ints.push ({ call: TryLoadMore }); styles += '#show-more-button{color:var(--yt-spec-call-to-action);width:100%;text-align:center;border:1px solid;padding:1em;cursor:pointer}'; } if (settings.unbound_video_title) styles += '#video-title{max-height:none!important}'; if (settings.video_quality) { function TryQuality (quality, qq, ep) { return qq.includes (quality) && (ep.setPlaybackQualityRange (quality, quality) || true); } function UpdateVideoQuality (det, st) { const ep = document.getElementById ("movie_player"); if (!ep || !ep.getPreferredQuality || !ep.getAvailableQualityLevels || !ep.setPlaybackQualityRange || !ep.getVideoData || ep.getPreferredQuality () != 'auto') return; const vid = ep.getVideoData ().video_id; if (st.fail == vid) // данное видео уже обработано return; const qq = ep.getAvailableQualityLevels (); if (!qq || !qq.length) return; switch (det) { // intentional no breaks here case 1: if (TryQuality ('hd2160', qq, ep)) return; case 2: if (TryQuality ('hd1440', qq, ep)) return; case 3: if (TryQuality ('hd1080', qq, ep)) return; case 4: if (TryQuality ('hd720', qq, ep)) return; case 5: if (TryQuality ('large', qq, ep)) return; case 6: if (TryQuality ('medium', qq, ep)) return; case 7: if (TryQuality ('small', qq, ep)) return; case 8: if (TryQuality ('tiny', qq, ep)) return; } console.log ('Unknown video qualities in list: ', qq); st.fail = vid; }; inject_func.push (TryQuality); inject_func.push (UpdateVideoQuality); inject_ints.push ({ call: UpdateVideoQuality, params: [settings.video_quality, {}] }); } if (settings.no_resume_time) { styles += 'div.ytd-thumbnail-overlay-resume-playback-renderer{width:100%!important}'; function removeTimes () { const links = document.querySelectorAll ('a[href*="&t="]'); for (let i = links.length; --i >= 0; ) { const l = links [i]; l.href = l.href.replace (/&t=\d+s?/, ''); } } inject_func.push (removeTimes); inject_ints.push ({ call: removeTimes }); } // "settings" button // can't store created button: Polymer overrides it's content on soft reload leaving tags in place // but can store element that Polymer does not know how to deal with and just drops function createSettingsButton (fix_version, st) { if (st.mark && st.mark.parentNode) return; let toolBar = document.getElementsByTagName ('ytd-topbar-menu-button-renderer'); if (!toolBar.length) return; toolBar = toolBar [0]; if (!toolBar) return; toolBar = toolBar.parentNode; const sb = document.createElement ('ytd-topbar-menu-button-renderer'); // ytd-notification-topbar-button-renderer sb.className = 'style-scope ytd-masthead style-default'; // style-scope ytd-masthead notification-button-style-type-default sb.setAttribute ('use-keyboard-focused', ''); sb.setAttribute ('is-icon-button', ''); sb.setAttribute ('has-no-text', ''); toolBar.insertBefore (sb, toolBar.childNodes [0]); // div[id=notification-count][class=style-scope ytd-notification-topbar-button-renderer][innerHTML=...] const mark = document.createElement ('fix-settings-mark'); mark.style = 'display:none'; toolBar.insertBefore (mark, sb); // must be added to parent node of buttons in order to Polymer dropped it on soft reload st.mark = mark; const icb = document.createElement ('yt-icon-button'); icb.id = 'button'; icb.className = 'style-scope ytd-topbar-menu-button-renderer style-default'; const tt = document.createElement ('tp-yt-paper-tooltip'); tt.className = 'style-scope ytd-topbar-menu-button-renderer'; tt.setAttribute ('role', 'tooltip'); tt.setAttribute ('tabindex', '-1'); tt.style = 'right:auto;bottom:auto'; tt.appendChild (document.createTextNode ('YT fixes ' + fix_version)); // YT wraps content into DIV element const aa = document.createElement ('a'); aa.className = 'yt-simple-endpoint style-scope ytd-topbar-menu-button-renderer'; aa.setAttribute ('tabindex', '-1'); aa.href = '/fix-settings'; aa.appendChild (icb); aa.appendChild (tt); sb.getElementsByTagName ('div') [0].appendChild (aa); // created by YT scripts const bb = icb.getElementsByTagName ('button') [0]; // created by YT scripts bb.setAttribute ('aria-label', 'fixes settings'); const ic = document.createElement ('yt-icon'); ic.className = 'style-scope ytd-topbar-menu-button-renderer'; bb.appendChild (ic); const gpath = document.createElementNS ('http://www.w3.org/2000/svg', 'path'); gpath.className.baseVal = 'style-scope yt-icon'; gpath.setAttribute ('d', 'M1 20l6-6h2l11-11v-1l2-1 1 1-1 2h-1l-11 11v2l-6 6h-1l-2-2zM2 20v1l1 1h1l5-5v-2h-2zM13 15l2-2 8 8v1l-1 1h-1zM15 14l-1 1 7 7h1v-1zM9 11l2-2-2-2 1.5-3-3-3h-2l3 3-1.5 3-3 1.5-3-3v2l3 3 3-1.5zM9 10l-2-2 1-1 2 2z'); const svgg = document.createElementNS ('http://www.w3.org/2000/svg', 'g'); svgg.className.baseVal = 'style-scope yt-icon'; svgg.appendChild (gpath); const svg = document.createElementNS ('http://www.w3.org/2000/svg', 'svg'); svg.className.baseVal = 'style-scope yt-icon'; svg.setAttributeNS (null, 'viewBox', '0 0 24 24'); svg.setAttributeNS (null, 'preserveAspectRatio', 'xMidYMid meet'); svg.setAttribute ('focusable', 'false'); svg.setAttribute ('style', 'pointer-events: none; display: block; width: 100%; height: 100%;'); svg.appendChild (svgg); ic.appendChild (svg); // YT clears *ic } inject_func.push (createSettingsButton); inject_ints.push ({ call: createSettingsButton, params: [fix_version, {}] }); // styles function AddStyles () { if (styles.length == 0) return; if (!document.head) return setTimeout (AddStyles, 1); const style_element = document.createElement ('style'); style_element.setAttribute ('type', 'text/css'); style_element.setAttribute ('id', 'ytfixstyle'); style_element.innerHTML = styles; document.head.appendChild (style_element); } AddStyles (); // injection function InjectScripts () { if (inject_ints.length == 0) return; if (!document.head) return setTimeout (InjectScripts, 1); function InjectInterval () { for (let i = ints.length; --i >= 0; ) { const Q = ints [i]; try { Q.call.apply (this, Q.params); } catch (e) { } } } let ss = '(function () {\n'; for (let i = inject_func.length; --i >= 0; ) ss += `${inject_func [i]}\n`; ss += 'let ints = [\n'; for (let i = inject_ints.length; --i >= 0; ) { const Q = inject_ints [i]; ss += `{ call: ${Q.call.name}, params: ${JSON.stringify (Q.params || [])} },\n`; } ss += `];\n${InjectInterval}\nsetInterval (InjectInterval, 1000);\nconsole.log ("Fixes injected");\n}) ();`; const sse = document.createElement ('script'); sse.setAttribute ('id', 'ytfixscript'); sse.appendChild (document.createTextNode (ss)); document.head.appendChild (sse); } InjectScripts (); console.log ('Fixes loaded'); }) ();