Enables keyboard shortcuts to like/dislike a video on YouTube.
当前为
// ==UserScript==
// @name YouTube Like/Dislike Shortcut
// @name:pt-BR Atalhos Gostei/Não Gostei no YouTube
// @namespace will64gamer
// @author will64gamer
// @description Enables keyboard shortcuts to like/dislike a video on YouTube.
// @description:pt-BR Cria atalhos para os botões gostei/não gostei em um vídeo no YouTube.
// @match *://*.youtube.com/*
// @license MIT
// @version 4.0
// ==/UserScript==
// You can change the codes to whichever keys you want to use for liking, disliking, and opening or writing comments on Shorts.
const codeLike = "NumpadAdd";
const codeDislike = "NumpadSubtract";
const codeComments = "NumpadMultiply";
const codeWrite = "NumpadDivide";
// If you want the shortcut to be triggered only when holding ctrl, alt, or shift, change this value from 0 to 1, 2, or 3, respectively.
const combination = 0;
// Change this to 0 if you don't want the sound alert. 1 only triggers the alert on regular videos, 2 triggers it on Shorts as well.
const alertPlays = 2;
// You can change the sound for the alert by using your own audio file URL or base64 encoded data.
const alertSound = new Audio(`
data:audio/mp3; base64,
//OEZAAAAAAAAAAAAAAAAAAAAAAAWGluZwAAAA8AAAAKAAAH+AAaGhoaGhoaGhoaSUlJSUlJSUlJSWBgYGBgYGBgYGCBgYGBgYGBgYGBnJycnJycnJycnLa2tra2tra2trbOzs7Ozs7Ozs7O5eXl5eXl5eXl5fz8/Pz8/Pz8/Pz///////////8AAAA5TEFNRTMuOTlyAm4AAAAALCAAABRGJAPnTgAARgAAB/hJttFsAAAAAAAAAAAAAAAAAAAA//OEZAANof9pLKCUAY3YAhYxQBAAkkkkklIIGMYxjGNgAAAAAAhjGMYxjyEIQhOpznO/yEI3n/9anOQhCEJznOd//6n/v/t//9iEIQn///b5CEOc5znOc4cDgcDhCEIQ5znf/5zkIQhCEIQ5znOc7///OcOAIAAAAAKMcPhwOBwAAKAwAhgR/Lv/l/8oCBz8oCAIYIfUGP/B8P1AmH/4Jg/9QIGS4Pg+8Tv+CEhy5//8EJc/8EAQBAMKmtiKd8UK//O0ZAYcKhNZjcfQAI/ABk2TgRAAUJQAABMIBAO4fS4hxkCN43dZrk5SC/CncCkRYZbm65Mjmi5SHepJaI5wyxDRzRWv/mReIsOkUCOH/6h8jKigSHCthcRDUF+tlosbnUBwhfwQ4NXCdhjSIoENLgbgMFl6yDzgaMFAboWTdE1SnVEyLNFbCghcw5NvX7erR8ZkUCOULiFBDpFajtIqMqFjIhMFvwYmD9RBV9Zj3evr/Vq/C30U4UYcY5xDhcxDSIkNKxDwbRAXtAbiKA0FGdIiOb0CkZWatJRigRwCUQK6g+xqc+ul26KIz4SNEaZJv6PIIMZAACYUmq9NtnZ+j7ELbYfo2PkeW97GJbSyTpUz6rnWm7GMYlt9LFfJyt+E2PWoYTBGCaehZhb/poxiqlddddbWgKQ/iThcUNigkbtOJKWU1yA1JG60JzC4RhVT//N0ZCARNf1NLuTQAYpQBkCxwAAATQZqKJqYmqNFSzyKLHUE0Kklosquk6j7Ok65w3NThk7f/ozhNCbgBTQEmQnY2ZFX1/Wr/7Io+pI6itFeuipLS1t6KXdSVKqrdn7K2b6v///6P7v/1KQWYmaIlMDEPQNgHCw0R6XTI1cbKRAmj///9/stUm59G9W7Q2ndo/3r7bW7OQZ6N0ytLqKbckNIWRf6nftT//OUZAASQf85LRq6vorYAkpSCAAAEskr19RAR+4Y8JFBJBmKqo+nGoGZDZkyhPMzN798XlyyPv98n3VfXdbJKc3Ouza1Jf61PWxuxHhqkDKKbA0GBAtNIkYlapFlJXSd3dFv//X1o1LstakatLWzWqPrVZJX1sp6noqSUkjqd1zq1LVU7IqS3Z779v9/5u9v8e3IjDtRnoENmmvm6BsQhdm3T1rS6hNyDauOYpiNudWxLX3aLUe33epxdD3nmK/q7V9X/v1tt9X/eur//3avrcX9agpTZdZmAIZzhFc11MZsRFlkEjWooWHpIFzBPxnD//OEZB0RIfs1LRh1eowYAjzSAAAAoyHhCWVwokRgpL5Q/q2aKVpTh//9BNApjOAhBIGKJmBgkABjEgxInzSz9nSsrbv/7VqZVejbX1dttTLVrmVVSNBalnVpU1JrUvUtJdJakZsyT1IU7qdd7Kb//nU1E8YjHFYCgJAaCJBDqBjmGJQEPvZ/V/1bkOQnpTbpkfI6DeykX+v0ZhfJV9uplFpAi80ZhltlM4WbT//S1jlilQ7lHfbYQOA/s61hgYmB//OEZA4OjfE3Lhh1iIuwAj2QCES4VPbAQb6jxRJe6o2SQnlcYHJSFEY7zmNay6EnfKPJqjNPR//9d2MyGD0BiZDgoWUTVBHUlam3b6O3b6Fk1rZrMpdv0VK9nQ/dd6Leg7WddmU7VUL9Gjt9b///9tkTAfhconF0Lm8SyDMKMI7ruvivqt/v9lanxWx3t5sUs/R//18VWl+2mlKz2PYriiV7lOMr/+6mhwsqEril2ubApH/BqYyThOlvSN4k5m3d//N0ZBUOve81Lhpl0ooYBkJSCAAAJ+E7k2H18MNrz3xPtzoSlkmxef/v3uHvdUcadcN91vb+vRH0F+wGQjuLqSKS0tf8t3//0zvR72T1yIy2WfbRGlTM5ncr6lWREPZzuVbIqN+rU0dP/5WteIiRjAIoi+z1+NVJQFiwcJbE1XJW727yP+ZXR10/+q+69Hf0f9/yf91P/J+iitHu//rqFdMktKAgXBQY//N0ZAkNAfMq3Q4n0gsoBj40CEQACsIuqpd/Zg1DCmWszG4CAtPangvrWGJLp///qQZ+uFUQdUjrX/17lIEHNx3F1V1tr/U77f6zTVNsc/RUurfarWa6bUe7c11Z11NvvnOtDkp9Uq06rc3f/7Z2hcHI8ctOpuvvUgQrUDLF3Xp7BjEqR5JSGudYebZ7vrcv/66bZJD6//Td/z3/+6Ge300lsKViiZpk//N0ZAcM5e0UJAmi0oxABhgAAAAANKUuU1Wm+VpjP/Vu8rUo/N5Slo6lMoCyGM/Wi1SWts6MKgHUAHQSxKmRkfRRR1o6Lf/+pVMY2hjVYpUf1K11YyGMpQolvoZ6v6GMZH1m1ClK3Xqxv/+Y31CgJfRQESiK1B35Vx7wVyx79TyUS8q7/kannolGDip2d/laZY926w1PVhrptlXcqd/xLBp8O5Y99CpM//MUZAEAAAC8AAQAAAAAAWgAAAAAQU1F
`);
// Change this value if you want to change the volume percentage of the alert from its default 50%.
const volumePercentage = 50;
// /\/\/\ Settings /\/\/\
// ------------------------------
// \/\/\/ Code \/\/\/
let isShort = false, rendererId = 0, shortsArray = [];
let tag, like, dislike, buttons, sLike, sDislike, comments, closeComments, textbox, initialRefresh;
alertSound.volume = volumePercentage/100;
const observer = new MutationObserver(findButtons);
addEventListener('yt-page-data-updated', reset);
addEventListener('popstate', reset);
function reset() {
isVideo = /^\/watch/.test(location.pathname);
isShort = /^\/shorts/.test(location.pathname);
if (isVideo||isShort) {
removeEventListener("keydown", press);
like = null; dislike = null; sLike = null; sDislike = null; comments = null; closeComments = null; textbox = null;
observer.observe(document.documentElement, {childList: true, subtree: true});
findButtons();
} else {initialRefresh = true;}
}
function findButtons() {
if ((like && dislike) || (sLike && sDislike && comments)) {
addEventListener("keydown", press);
observer.disconnect();
let currentURL = location.href, first = true;
if (isShort) {
let shortInterval = setInterval(() => {
if (first) {
checkId(location.href);
first = false;
}
if (location.href !== currentURL) {
clearInterval(shortInterval);
currentURL = location.href;
if(!checkId(location.href)){rendererId++;}
reset();
}
}, 400);
} else if (isVideo) {initialRefresh = true;}
}
if (isShort) {
if (initialRefresh) {
initialRefresh = false;
location.reload();
}
buttons = document?.getElementsByTagName('ytd-reel-video-renderer')[rendererId]
?.getElementsByClassName("overlay style-scope ytd-reel-video-renderer")[0]?.firstElementChild
?.getElementsByClassName("action-container style-scope ytd-reel-player-overlay-renderer")[0]
?.firstElementChild?.querySelectorAll('button');
if(buttons) {
sLike = buttons[0];
sDislike = buttons[1];
comments = buttons[2];
}
} else {
like = document?.getElementsByTagName("like-button-view-model")[0]?.firstElementChild?.firstElementChild?.firstElementChild;
dislike = document?.getElementsByTagName("dislike-button-view-model")[0]?.firstElementChild?.firstElementChild?.firstElementChild;
}
}
function openComments() {
comments.click();
let closeCommentsInterval = setInterval(() => {
if (!closeComments) {
closeComments = document?.getElementById("visibility-button")?.getElementsByTagName('button')[0];
} else {
clearInterval(closeCommentsInterval);
}
}, 300);
}
function press(e) {
if (e.target.getAttribute("contenteditable") === "true") {return;}
tag = e.target.tagName.toLowerCase();
if (tag === "input" || tag === "textarea") {return;}
switch (combination) {
case 1:
if (!e.ctrlKey) {return;}
break;
case 2:
if (!e.altKey) {return;}
break;
case 3:
if (!e.shiftKey) {return;}
break;
}
switch (e.code) {
case codeComments:
if (comments) {
if (closeComments) {
closeComments.click();
closeComments = null;
} else {
openComments();
}
}
break;
case codeWrite:
if (textbox) {
openComments();
setTimeout(() => {
textbox.click();
}, 100);
} else if (comments) {
openComments();
let textboxInterval = setInterval(() => {
if (!textbox) {
textbox = document.getElementById("simplebox-placeholder");
} else {
textbox.focus();
clearInterval(textboxInterval);
}
}, 300);
}
break;
case codeLike:
if (like) {
if (alertPlays !== 0) {alert(like);}
like.click();
}
else if (sLike) {
if (alertPlays === 2) {alert(sLike);}
sLike.click();
}
break;
case codeDislike:
if (dislike) {dislike.click();}
else if (sDislike) {sDislike.click();}
break;
}
}
function checkId(href) {
for(let i = 0; i < shortsArray.length; i++) {
if (href === shortsArray[i]) {
rendererId = i;
return true;
}
}
shortsArray.push(href);
return false;
}
function alert(likeTag) {
if (likeTag.getAttribute("aria-pressed") === "false") {
alertSound.play();
}
}