// ==UserScript==
// @name Youtube player keyboard controls
// @description Use play/pause/ArrowRight/ArrowLeft keyboard btns anywhere, but not only when youtube player is in focus. Additionaly use '[' and ']' keys to change playbackRate.
// @description set config.defaultPlaybackRate to your preferred youtube PlaybackRate (1.5 by default).
// @description set config.customStyles = true, to hide search bar by default. It will appear by mouse hover.
// @description set config.customStylesDarkTheme = true, to boost Youtube dark theme. You should turn on Dark Theme in Youtube settings first!
// @author termi1uc1@gmail.com
// @license MIT
// @version 0.13
// @include https://www.youtube.com/*
// @namespace https://greasyfork.org/users/174246
// ==/UserScript==
// https://greasyfork.org/ru/scripts/39372-youtube-player-keyboard-controls
/* globals AudioContext, ytplayer, KeyboardEvent, HTMLMediaElement, unescape, decodeURIComponent */
;(function(window) {
const config = {// Set your preferred value. It will be saved in localStorage.
playbackRateControls: undefined,// boolean, [default = true]
defaultPlaybackRate: 2,// number, [default = 1.5]
// Some custom styles to Youtube, including hiding search bar (It will appear by mouse hover).
// Set it to true, to turn it on.
customStyles: true,// boolean, [default = false]
// Boost Youtube Dark Theme. Set it to true, to turn it on.
customStylesDarkTheme: true,// boolean, [default = false]
customStylesDarkTheme_bottomContentOpacity: 0,// number, [default = 0.1]
};
append(config, _loadConfigLS('youtube_player_keyboard_controls_config'));
_saveConfigLS('youtube_player_keyboard_controls_config', config);
append(config, {// Default config
playbackRateControls: true,
defaultPlaybackRate: 1.5,
// Some custom styles to Youtube, including hiding search bar (It will appear by mouse hover).
customStyles: false,
// Boost Youtube Dark Theme
customStylesDarkTheme: false,
customStylesDarkTheme_bottomContentOpacity: 0.1,
// download doesn't work, after the latest youtube changes
downloadLinks: false,
});
if (config.defaultPlaybackRate) {
if (config.defaultPlaybackRate === 1) {
sessionStorage.removeItem("yt-player-playback-rate");
localStorage.removeItem("yt-player-playback-rate");
}
else {
const now = Date.now();
sessionStorage["yt-player-playback-rate"] = `{"data":"${config.defaultPlaybackRate}","creation":${now}}`;
localStorage["yt-player-playback-rate"] = `{"data":"${config.defaultPlaybackRate}","creation":${now}}`;
}
}
const defaultYoutubeMoviePlayerId = 'movie_player';
let youtubeMoviePlayerId;
/* TODO:: Volume more then 100%
let audioContext;
let audioContextSource;
let audioContextGain;
function getVolumeMoreThen100(videoElement, volumeValue) {
// TODO:: доделать
volumeValue = Math.max(10, volumeValue);
if (!audioContext) {
audioContext = new AudioContext();
}
audioContextSource = audioContext.createMediaElementSource(videoElement);
// create a gain node
audioContextGain = audioContext.createGain();
audioContextGain.gain.value = volumeValue; // double the volume
audioContextSource.connect(audioContextGain);
// connect the gain node to an output destination
audioContextGain.connect(audioContext.destination);
}
*/
const randStr = () => (Math.random() * 9e7 | 0).toString(36);
const getYoutubeMoviePlayerId = () => {
let youtubeMoviePlayerId = defaultYoutubeMoviePlayerId;
try {
if ( typeof ytplayer !== 'undefined' ) {
youtubeMoviePlayerId = ytplayer.config.attrs.id || defaultYoutubeMoviePlayerId;
}
}
catch(e) {
youtubeMoviePlayerId = defaultYoutubeMoviePlayerId;
}
return youtubeMoviePlayerId;
};
const isElemVisible = function($el) {
if (!$el) {
return false;
}
// check element visibility
if (typeof $el.getClientRects === 'function') {
const res = $el.getClientRects();
return !!(res && res.length);
}
// maybe visible
return true;
};
const detectYoutubePlayer = function() {
const visiblePlayersContainers = Array.from(document.querySelectorAll('#player')).filter(isElemVisible);
for (const $container of visiblePlayersContainers) {
const $player = $container.querySelector('[aria-label="YouTube Video Player"]');
if (isElemVisible($player)) {
return $player;
}
}
};
const checkAndResetMoviePlayer = function($moviePlayer) {
if (!$moviePlayer) {
youtubeMoviePlayerId = defaultYoutubeMoviePlayerId;
return document.getElementById(youtubeMoviePlayerId);
}
else if (!isElemVisible($moviePlayer)) {
if (youtubeMoviePlayerId === defaultYoutubeMoviePlayerId) {
$moviePlayer = detectYoutubePlayer();
if ($moviePlayer && $moviePlayer.id) {
youtubeMoviePlayerId = $moviePlayer.id;
}
}
else {
youtubeMoviePlayerId = defaultYoutubeMoviePlayerId;
return document.getElementById(youtubeMoviePlayerId);
}
}
return $moviePlayer;
};
const getYoutubePlayer = (getVideoEl = true) => {
if ( youtubeMoviePlayerId === void 0 ) {
youtubeMoviePlayerId = getYoutubeMoviePlayerId();
}
let $moviePlayer = checkAndResetMoviePlayer(document.getElementById(youtubeMoviePlayerId));
if ( !$moviePlayer ) {
if ( youtubeMoviePlayerId !== defaultYoutubeMoviePlayerId ) {
$moviePlayer = document.getElementById(defaultYoutubeMoviePlayerId);
}
if ( !$moviePlayer ) {
return null;
}
}
return getVideoEl
? $moviePlayer.querySelector('video')
: $moviePlayer
;
};
const getParrentByClassName = ($el, className, maxTopEls = 15) => {
if ( !$el ) {
return null;
}
let i = 0;
let child = $el;
for ( ; i < maxTopEls ; i++ ) {
if ( child.classList.contains(className) ) {
return child;
}
if ( !child.parentElement ) {
return null;
}
child = child.parentElement;
}
return null;
};
const isAdvVideoPlayer = $moviePlayer => {
if ( !$moviePlayer ) {
return false;
}
const $moviePlayerWrapper = getParrentByClassName($moviePlayer, 'html5-video-player', 5);
if ( $moviePlayerWrapper ) {
return $moviePlayerWrapper.classList.contains('ad-showing');
}
return false;
};
const isEditable = $el => {
return $el.tagName === 'INPUT'
|| $el.tagName === 'TEXTAREA'
|| ($el.hasAttribute('contenteditable') && $el.contentEditable !== 'false' && $el.contentEditable !== 'inherit');
};
const isVideoFullscreenElement = $el => {
const fullScreenElement = document["mozFullScreenElement"] || document["webkitFullscreenElement"] || document["webkitCurrentFullScreenElement"] || document.fullscreenElement;
const videoEl = fullScreenElement && fullScreenElement.querySelector('video');
return videoEl && $el.querySelector('video') !== videoEl && videoEl.tagName === 'VIDEO';
};
const removeElement = htmlElement => {
if (!htmlElement) {
return;
}
if (typeof htmlElement.remove === 'function') {
htmlElement.remove();
return;
}
if (htmlElement.parentNode) {
htmlElement.parentNode.removeChild(htmlElement);
}
};
const _checkParent = $el => {
if ( !$el ) {
return false;
}
let i = 0;
let hasParent = true;
let child = $el;
for ( ; i < 20 ; i++ ) {
if ( !child.parentElement ) {
hasParent = false;
break;
}
child = child.parentElement;
}
return hasParent;
};
let playbackTimer;
let playbackRateElId;
let $elPlaybackRate;
let playbackRateOnKeyDown = event => {
if (!config.playbackRateControls) {
return false;
}
const $moviePlayer = getYoutubePlayer(false);
if ( !$moviePlayer ) {
return false;
}
const {code, target} = event;
if ( code === 'BracketRight' || code === 'BracketLeft' ) {
if ( isEditable(target) ) {
return;
}
/*if ( !isVideoFullscreenElement(target) && (target == $moviePlayer || isEditable(target)) ) {
//console.log(' return ', 1)
return;
}
*/
if ( !playbackRateElId && $moviePlayer ) {
/*jshint bitwise: false*/
playbackRateElId = 'playbackRateText' + randStr();
/*jshint bitwise: true*/
$moviePlayer.insertAdjacentHTML('afterbegin', `<div id="${playbackRateElId}" style="position: absolute;
z-index: 9999999;
right: 20px;
top: 20px;
pointer-events: none;
display: block;
transition: opacity .5s;
opacity: 0;
color: yellow;
width: auto;
height: 48px;
line-height: 48px;
font-size: 48px;
text-align: center;
text-shadow: 1px 1px 4px #000;"></div>`);
$elPlaybackRate = document.getElementById(playbackRateElId);
}
else if ( !_checkParent($elPlaybackRate) ) {
// Unattachment element
$moviePlayer.insertAdjacentElement('afterbegin', $elPlaybackRate);
}
const $video = $moviePlayer.querySelector('video');
const {playbackRate} = $video;
let newPlaybackRate;
{
let delta = code === 'BracketLeft' ? -0.25 : 0.25;
if ( delta < 0 ) {
if ( playbackRate > 2 || playbackRate <= 1 ) {
delta = -0.1;
}
}
else {
if ( playbackRate >= 2 || playbackRate < 1 ) {
delta = 0.1;
}
}
newPlaybackRate = playbackRate + delta;
if ( newPlaybackRate < 0.5 ) {
newPlaybackRate = 0.5;
}
else if ( newPlaybackRate > 3.5 ) {
newPlaybackRate = 3.5;
}
// Округление до 2го знака после запятой
newPlaybackRate = parseFloat(newPlaybackRate.toFixed(2));
}
$video.playbackRate = newPlaybackRate;
$elPlaybackRate.textContent = 'x' + newPlaybackRate;
$elPlaybackRate.style.opacity = 1;
if ( playbackTimer ) {
clearTimeout(playbackTimer);
}
playbackTimer = setTimeout(() => {
playbackTimer = void 0;
$elPlaybackRate.style.opacity = 0;
}, 500);
return true;
}
};
if ( window.__onKey__ ) {
document.removeEventListener('keyup', window.__onKey__, true);
document.removeEventListener('keydown', window.__onKey__, true);
window.__onKey__ = void 0;
}
const isNeedMagicActionsForYoutubeFix = () => {
return String(HTMLMediaElement.prototype.play).indexOf('pauseVideo') !== -1;
};
let prevVideoElementUrl;
const fixPauseVideo = ($moviePlayer, $videoElement) => {
const youtubePlayerControls = $moviePlayer.querySelector('.ytp-chrome-controls');
if ( youtubePlayerControls && prevVideoElementUrl !== $videoElement.src ) {
prevVideoElementUrl = $videoElement.src;
youtubePlayerControls.click();
}
};
const sDoNotHandle = typeof Symbol === 'undefined' ? '__sDoNotHandle__' : Symbol('sDoNotHandle');
const onKey = event => {
if ( event[sDoNotHandle] ) {
return;
}
const $moviePlayer = getYoutubePlayer(false);
if ( !$moviePlayer ) {
return;
}
const {code, target, keyCode, charCode, which} = event;
if ( code === 'Space' || code === 'ArrowRight' || code === 'ArrowLeft' ) {
if ( !isVideoFullscreenElement(target) && (/*target == $moviePlayer || */isEditable(target)) ) {
//console.log(' return ', 1)
return;
}
const $videoElement = getYoutubePlayer(true);
if ( !$videoElement ) {
// something went wrong
console.warn('onKey: cant find youtube video element');
return;
}
if ( isAdvVideoPlayer($moviePlayer) ) {
// Проигрывается реклама
// TODO:: нужно сделать кастомную перемотку вперёд-назад и кнопку "Пропустить"
console.log('Youtube Adw mode');
}
const newEvent = new KeyboardEvent(event.type, event);
try {
if ( newEvent.keyCode !== keyCode ) {
Object.defineProperty(newEvent, 'keyCode', {value: keyCode, configurable: true, enumerable: true, writable: false});
}
}
catch(e){}
try {
if ( newEvent.charCode !== charCode ) {
Object.defineProperty(newEvent, 'charCode', {value: charCode, configurable: true, enumerable: true, writable: false});
}
}
catch(e){}
try {
if ( newEvent.which !== which ) {
Object.defineProperty(newEvent, 'which', {value: which, configurable: true, enumerable: true, writable: false});
}
}
catch(e){}
if ( $videoElement.paused && isNeedMagicActionsForYoutubeFix() ) {
fixPauseVideo($moviePlayer, $videoElement);
}
newEvent[sDoNotHandle] = true;
//console.log(' dispatchEvent ', 2, newEvent, event);
$videoElement.dispatchEvent(newEvent);
event.stopPropagation();
event.preventDefault();
}
else if ( event.type === 'keydown' ) {
if ( playbackRateOnKeyDown(event) ) {
event.stopPropagation();
event.preventDefault();
}
}
};
document.addEventListener('keyup', onKey, true);
document.addEventListener('keydown', onKey, true);
window.__onKey__ = onKey;
if (config.customStyles) {
if (config.customStylesDarkTheme) {
const autoBottomContentOpacityClassName = 'custom_abco_' + randStr();
const {customStylesDarkTheme_bottomContentOpacity = 1} = config;
if (customStylesDarkTheme_bottomContentOpacity !== 1) {
const toggleDocClass = () => {
document.documentElement.classList.toggle(autoBottomContentOpacityClassName, document.documentElement.scrollTop <= 0);
};
toggleDocClass();
document.addEventListener('scroll', toggleDocClass, { passive: true });
}
const styleText = `html, body, #content {
background: black !important;
}
ytd-app {
--yt-app-background: black !important;
--yt-spec-general-background-a: black !important;
}
#masthead-container.ytd-app {
background: black !important;
}
#container.ytd-masthead {
background: black !important;
}
#primary, #columns {
background: black !important;
--yt-endpoint-visited-color: #9c9c9c;
--yt-spec-call-to-action: #9c9c9c;
--ytd-video-primary-info-renderer-title-color: #9c9c9c;
--ytd-comment-text-color: #9c9c9c;
--yt-spec-text-primary: #9c9c9c;
--yt-spec-general-background-b: #1a1a1a !important;
--yt-spec-text-primary: #9c9c9c !important;
}
ytd-toggle-button-renderer.style-default-active[is-icon-button] {
color: #34624b;
}
#guide {
--app-drawer-content-container_-_background-color: #1a1a1a;
--yt-spec-brand-background-solid: #1a1a1a;
--yt-spec-text-primary: #9c9c9c;
}
.ytp-gradient-bottom,
.ytp-large-play-button {
display: none;
}
.ytp-cued-thumbnail-overlay {
display: none;
}
#watch-action-panels {
display: none;
}
.ytp-chrome-bottom {
opacity: 0;
transition: opacity .5s;
}
.ytp-chrome-bottom:hover {
opacity: 1;
}
ytd-watch-flexy[theater] #columns {
opacity: 1;
transition: opacity .5s;
}
.${autoBottomContentOpacityClassName} ytd-watch-flexy[theater] #columns {
opacity: ${customStylesDarkTheme_bottomContentOpacity};
}
.${autoBottomContentOpacityClassName} ytd-watch-flexy[theater] #columns:hover {
opacity: 1;
}
ytd-masthead {
opacity: 0;
transition: opacity .5s;
}
ytd-masthead:hover {
opacity: 1;
}
#masthead-positioner {
opacity: 0;
position: fixed;
z-index: 9999;
}
#masthead-positioner:hover {
opacity: 1;
}`;
const $parentEl = document.head || document.body || document.documentElement;
if ($parentEl) {
$parentEl.insertAdjacentHTML('afterbegin', `<style name="youtube-player-keyboard-controls_custom-styles">${styleText}</style>`);
}
}
else {
const styleText = `#watch-action-panels {
display: none;
}
.ytp-chrome-bottom {
opacity: 0;
}
.ytp-chrome-bottom:hover {
opacity: 1;
}
ytd-masthead {
opacity: 0;
}
ytd-masthead:hover {
opacity: 1;
transition: opacity .5s;
}
#masthead-positioner {
opacity: 0;
position: fixed;
z-index: 9999;
}
#masthead-positioner:hover {
opacity: 1;
}
`;
const $parentEl = document.head || document.body || document.documentElement;
if ($parentEl) {
$parentEl.insertAdjacentHTML('afterbegin', `<style name="youtube-player-keyboard-controls_custom-styles-simple">${styleText}</style>`);
}
}
}
function initDownloadLinks() {
let youTuubeDownloadInterval;
function setIntervalYD(interval = 5000) {
if (youTuubeDownloadInterval) {
clearInterval(youTuubeDownloadInterval);
}
youTuubeDownloadInterval = setInterval(function() {
const $moreActionsBtn = getMoreActionsBtn();
if ($moreActionsBtn) {
clearInterval(youTuubeDownloadInterval);
youTuubeDownloadInterval = void 0;
$moreActionsBtn.addEventListener('click', function() {
setTimeout(function() {
youtubedownloader_main(true);
}, 500);
setTimeout(function() {
youtubedownloader_main(true);
}, 5000);
}, false);
}
else {
youtubedownloader_main();
}
}, interval);
}
function getMoreActionsBtn() {
const $menuContainer = document.querySelector('#menu-container');
let $moreActionsBtn = null;
if ($menuContainer) {
$moreActionsBtn = $menuContainer.querySelector('[aria-label="More actions"]')
|| $menuContainer.querySelector('yt-icon-button > button')
|| $menuContainer.querySelector('#button')
|| $menuContainer.querySelector('.yt-icon-button')
|| null
;
}
return $moreActionsBtn;
}
let $historyManager;
let $dataHost;
function getYoutubeplayerConfig() {
let ytplayerConfig = null;
const historyState = history.state;
const historyEntryTime = historyState && historyState.entryTime;
if (!$historyManager) {
$historyManager = document.querySelector('#historyManager') || document.querySelector('yt-history-manager');
}
if (!$dataHost) {
$dataHost = $historyManager && $historyManager.dataHost || document.querySelector('ytd-app[is-watch-page]');
}
if ($dataHost && $dataHost.data) {
ytplayerConfig = $dataHost.data.player;
}
if (!ytplayerConfig) {
if ($historyManager && historyEntryTime && $historyManager["historySnapshotCache_"]) {
try {
const current_ytplayerConfig = $historyManager["USE_HISTORY_SNAPSHOT_CACHE_"]
? $historyManager["historySnapshotCache_"].get(historyEntryTime)
: $historyManager["historyEntryTimeToDataMap_"][a.entryTime]
;
if (current_ytplayerConfig) {
ytplayerConfig = current_ytplayerConfig;
}
}
catch(err) {
console.error(err);
}
}
}
return ytplayerConfig
|| (typeof ytplayer !== 'undefined'
? ((ytplayer || {})["config"] || {})
: { "args": {} }
)
;
}
function getListElement() {
return document.querySelector('paper-listbox#items');
}
function createElement(tagName, attributes, append) {
const element = document.createElement(tagName);
for (const attributeName in attributes) {
if (attributes.hasOwnProperty(attributeName)) {
if (typeof element[attributeName] !== 'undefined' && attributeName !== 'style' && attributeName !== 'type'/*FIX IE*/) {
element[attributeName] = attributes[attributeName];
}
else {
element.setAttribute(attributeName, attributes[attributeName]);
}
}
}
if (append && append.nodeType === 1/*append instanceof Element*/) {
append.appendChild(element);
}
return element;
}
function youtubedownloader_main(forceAttacheToMoreActionsBtn = false) {
const ytplayerConfig = getYoutubeplayerConfig();
const ytplayerVideoId = ytplayerConfig["args"] && ytplayerConfig["args"]["video_id"];
if (ytplayerVideoId) {
console.log("YouTube Downloader: Start");
const title = ytplayerConfig["args"]["title"];
const video = {
title,
title_encoded: encodeURIComponent(title.replace(/[\\~#%&*{}\/:<>?|"-]/g, "_")),
fmt: ytplayerConfig["args"]["url_encoded_fmt_stream_map"] + "," + ytplayerConfig["args"]["adaptive_fmts"],
id: ytplayerVideoId,
};
const textlang = {
button_text: "Download",
button_hover_text: "Download this video!",
};
removeElement(document.getElementById('watch-download-links'));
const linksContainer = createElement("div", { id: "watch-download-links" });
const links = video.fmt.split(",");
let useSignature = false;
console.log("YouTube Downloader: " + (links.length) + " links collected");
const parseParamFromLink = function(link, re) {
return (link.match(re) || [, ''])[1];
};
for (let i = 0 ; i < links.length ; i++) {
const link = links[i];
if (!link || link === 'undefined') {
continue;
}
const itag = parseInt(parseParamFromLink(link, /itag=([0-9]*)(?:&|$)/) || '0', 10) || void 0;
// TODO:: use signature instead of sig? // const signature = parseParamFromLink(link, /(?:^|&)signature=(.*?)(?:&|$)/);
const sig = parseParamFromLink(link, /(?:^|&)s=(.*?)(?:&|$)/);
const quality_label = parseParamFromLink(link, /quality_label=(.*?)(?:&|$)/) || parseParamFromLink(link, /(?:^|&)quality=(.*?)(?:&|$)/);
const size = parseParamFromLink(link, /(?:^|&)size=(.*?)(&|$)/);
const projection_type = parseParamFromLink(link, /(?:^|&)projection_type=(.*?)(&|$)/);
const url = /*unescape*/decodeURIComponent(parseParamFromLink(link, /url=(.*?)(?:&|$)/)) + (sig ? "&signature=" + sig : "") + "&title=" + video.title_encoded;
/*
(ytplayerConfig = ytplayer.config),(ytplayerConfig["args"]["url_encoded_fmt_stream_map"] + "," + ytplayerConfig["args"]["adaptive_fmts"]).split(",").map(link => { const parse = re=>(link.match(re)||[,''])[1]; let itag = parseInt(parse(/itag=([0-9]*)(?:&|$)/)||'0');let sig = parse(/(?:^|&)s=(.*?)(?:&|$)/);let type = decodeURIComponent(parse(/(?:^|&)type=(.*?)(&|$)/)); let mime = decodeURIComponent(parse(/(?:^|&)mime=(.*?)(&|$)/)); let quality_label = parse(/quality_label=(.*?)(?:&|$)/) || parse(/(?:^|&)quality=(.*?)(?:&|$)/); let size = parse(/(?:^|&)size=(.*?)(&|$)/); let projection_type = parse(/(?:^|&)projection_type=(.*?)(&|$)/); return {itag, sig, type, mime, quality_label, size, projection_type}; });
*/
if (sig) {
console.log("YouTube Downloader: Signature detected; aborting!", sig);
useSignature = true;
//linksContainer.innerHTML = "";
}
//console.log("links[" + i + "]: itag=" + itag + ";sig=" + sig + ';url=' + url);
let nAtext = "";
switch (itag) {
case 38: nAtext = "2160p(4K,MP4)"; break;
case 46: nAtext = "1080p(WebM)"; break;
case 37: nAtext = "1080p(MP4)"; break;
case 45: nAtext = "720p (WebM)"; break;
case 102: /*nAtext = "720p (WebM,3D)";*/ break;
case 22: nAtext = "720p (MP4)"; break;
case 84: /*nAtext = "720p (MP4,3D)";*/ break;
case 85: /*nAtext = "520p (MP4,3D)";*/ break;
case 35: nAtext = "480p (FLV)"; break;
case 44: nAtext = "480p (WebM)"; break;
case 34: nAtext = "360p (FLV)"; break;
case 18: nAtext = "360p (MP4)"; break;
case 82: /*nAtext = "360p (MP4,3D)";*/ break;
case 100: /*nAtext = "360p (WebM,3D)";*/ break;
case 101: /*nAtext = "360p (WebM,3D)";*/ break;
case 43: nAtext = "360p (WebM)"; break;
case 6: nAtext = "270p (FLV)"; break;
case 83: /*nAtext = "240p (MP4,3D)";*/ break;
case 36: nAtext = "240p (3GP)"; break;
case 5: nAtext = "240p (FLV)"; break;
case 395: /*nAtext = "240p (MP4, Video only)";*/ break;
case 17: nAtext = "144p (3GP)"; break;
case 278: /*nAtext = "144p (WebM,Video only)";*/ break;
case 264: /*nAtext = "4k(MP4,Video only)";*/ break;
case 138: /*nAtext = "4k+(MP4,Video only)";*/ break;
case 137: /*nAtext = "1080p(MP4,Video only)";*/ break;
case 136: /*nAtext = "720p(MP4,Video only)";*/ break;
case 135: /*nAtext = "480p(MP4,Video only)";*/ break;
case 134: /*nAtext = "360p(MP4,Video only)";*/ break;
case 133: /*nAtext = "240p(MP4,Video only)";*/ break;
case 160: /*nAtext = "144p(MP4,Video only)";*/ break;
case 394: /*nAtext = "144p(MP4,Video only ?)";*/ break;
case 248: /*nAtext = "1080p(WemM,Video only)";*/ break;
case 247: /*nAtext = "720p(WemM,Video only)";*/ break;
case 397: /*nAtext = "480p(?)";*/ break;
case 244: /*nAtext = "480p(WemM,Video only)";*/ break;
case 243: /*nAtext = "360p(WemM,Video only)";*/ break;
case 396: /*nAtext = "360p(?)";*/ break;
case 242: /*nAtext = "240p(WemM,Video only)";*/ break;
case 140: nAtext = "Audio(M4A)"; break;
case 249: /*nAtext = "Audio(WebM ?)";*/ break;
case 250: /*nAtext = "Audio(WebM ?)";*/ break;
case 251: /*nAtext = "Audio(WebM ?)";*/ break;
case 171: /*nAtext = "Audio(OGG)";*/ break;
case 298: /*nAtext = "720p60(MP4,Video only)";*/ break;
case 398: /*nAtext = "720p50(?)";*/ break;
case 299: /*nAtext = "1080p60(MP4,Video only)";*/ break;
case 302: /*nAtext = "720p60(WemM,Video only)";*/ break;
case 303: /*nAtext = "1080p60(WemM,Video only)";*/ break;
case 266: /*nAtext = "2160p(4K,MP4,Video only)";*/ break;
case 271: /*nAtext = "1440p(WemM,Video only)";*/ break;
case 272: /*nAtext = "2160p(4K,WemM,Video only)";*/ break;
case 313: /*nAtext = "2160p(4K,WemM,Video only)";*/ break;
default: {
console.warn("YouTube Downloader: Unknown itag: " + itag);
if (!itag) {
console.warn("YouTube Downloader: link: " + link);
}
break;
}
}
if (nAtext && !sig) {
createElement("a", {
href: url,
target: '_blank',
download: video.title_encoded,
innerHTML: nAtext,
}, linksContainer);
}
}
if(linksContainer.childNodes.length === 0){
createElement("a", {
href: "javascript:alert('This video cannot be downloaded')",
innerHTML: "Video download unavailable"
}, linksContainer);
}
let renderArea;
if (!forceAttacheToMoreActionsBtn && (renderArea = document.getElementById("watch7-secondary-actions"))) {//document.cookie="VISITOR_INFO1_LIVE=jZNC3DCddAk; path=/; domain=.youtube.com";window.location.reload();
createElement("div", { id: "action-panel-download" }, document.getElementById("watch7-action-panels"));
const dlb = createElement("button", {
className: "action-panel-trigger yt-uix-button",
type: "button",
onclick(e) {
const wdl = document.getElementById("watch-download-links").style;
if (wdl.display !== "block") {
wdl.display = "block";
this.classList.add("yt-uix-button-toggled");
}
else {
wdl.display = "none";
this.classList.remove("yt-uix-button-toggled");
}
wdl.top = (this.offsetTop + this.clientHeight + 7) + "px";
wdl.left = (this.offsetLeft + 1) + "px";
e.stopPropagation();
},
innerHTML: `<span class="yt-uix-button-content">${textlang.button_text}</span>`
});
const W7B0 = document.querySelector('#watch7-secondary-actions button:first-child');
W7B0.parentNode.insertBefore(dlb, W7B0.nextSibling);
document.getElementById("watch7-content").appendChild(linksContainer);
}
else if (!forceAttacheToMoreActionsBtn && (renderArea = document.getElementById("watch8-secondary-actions"))) {
createElement("div", { id: "action-panel-download" }, renderArea.parentNode);
const dls = createElement("span", { className : "ytd-dls" });
createElement("button", {
className: "yt-uix-button yt-uix-button-size-default yt-uix-button-opacity yt-uix-button-has-icon no-icon-markup action-panel-trigger yt-uix-tooltip",
type: "button",
title: textlang.button_hover_text,
"data-tooltip-text": textlang.button_hover_text,
onclick(e) {
const wdl = document.getElementById("watch-download-links").style;
if (wdl.display !== "block") {
wdl.display = "block";
this.classList.add("yt-uix-button-toggled");
}
else {
wdl.display = "none";
this.classList.remove("yt-uix-button-toggled");
}
wdl.top = (this.offsetTop + this.clientHeight + 7) + "px";
wdl.left = (this.offsetLeft + 1) + "px";
e.stopPropagation();
},
innerHTML: `<span class="yt-uix-button-content">${textlang.button_text}</span>`
}, dls);
const W7B0 = document.querySelector('#watch8-secondary-actions .yt-uix-menu');
W7B0.parentNode.insertBefore(dls, W7B0);
renderArea.appendChild(linksContainer);
}
else if (renderArea = getListElement()) {
renderArea.appendChild(linksContainer);
linksContainer.style.display = 'block';
linksContainer.childNodes.forEach(el => el.style.display = 'block');
}
else {
console.log("YouTube Downloader: Sem renderArea");
}
/*
//insert css
var ncss = document.createElement("style");
ncss.appendChild(document.createTextNode("#watch-download-links{width:90px;box-shadow:#999 0px 0px 3px 0px; border-bottom-left-radius:2px; border-bottom-right-radius:2px; background:#EBEBEB; overflow:hidden}#watch-download-links a{height:25px; width:82px;background:#FFF!important; line-height:25px; font-size:12px; padding:0 0 0 8px!important; display:inline-block; color:#000!important; text-decoration:none!important;}#watch-download-links a:hover{background:#EBEBEB!important;}#dl{float:left; padding:4px}#wdl{background:#FFF;border-radius:5px; border:1px solid #EAEAEA; font-family:Arial, Helvetica, sans-serif; font-size:12px; line-height:14px; margin:0px auto 10px auto; overflow:hidden; display:none; height:auto}#wdl a{padding:5px; color:#000; text-decoration:none; display:inline-block}#wdl a:hover{background:#333; color:#FFF}#watch-actions{height:auto!important}#watch-sidebar iframe{width:234px; height:60px; margin:10px 25px; border-radius:2px; box-shadow:0 0 20px rgba(0,0,0,.2)}"));
document.head.appendChild(ncss);
*/
}
}
setIntervalYD();
}
if (config.downloadLinks) {
initDownloadLinks();
}
function _loadConfigLS(key) {
const value = localStorage.getItem(key);
if (value) {
try {
return JSON.parse(value);
}
catch(e) {
//
}
}
return void 0;
}
function _saveConfigLS(key, value) {
if (value && typeof value === 'object') {
const _value = append({}, value);
if (Object.keys(_value).length > 0) {
localStorage.setItem(key, JSON.stringify(value));
}
}
}
function append(target, ...sources) {
if (target === void 0 || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
const _target = Object(target);
for (let j = 0, len2 = sources.length ; j < len2 ; j++ ) {
const source = sources[j];
if (!source) {
continue;
}
const keys = Object.keys(source);
for (let i = 0, len = keys.length ; i < len ; i++) {
const key = keys[i];
const sourceValue = source[key];
if (_target[key] === void 0 && sourceValue !== void 0) {
_target[key] = sourceValue;
}
}
}
return _target;
}
})(window);