NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Youtube Like/Dislike and Skip Ad Keyboard Shortcuts
// @namespace youtube
// @include https://www.youtube.com/*
// @description Keybindings: "[" to like, "]" to dislike, and "S" to skip pre-video or banner ads. Browser notifications can be toggled via the menu.
// @version 1.5
// @grant GM_notification
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @run-at document-end
// @icon https://www.google.com/s2/favicons?domain=youtube.com&sz=128
// @updateURL https://openuserjs.org/meta/nascent/Youtube_likedislike_video_and_skip_ad_keyboard_shortcuts.meta.js
// @license GPL-3.0-or-later
// ==/UserScript==
/*jshint esversion: 6 */
(function () {
"use strict";
// Retrieve the saved setting; if not set, default to true.
let browserNotifications = GM_getValue("browserNotifications", true);
// Menu command for toggling browser notifications.
function toggleBrowserNotifications() {
browserNotifications = !browserNotifications;
GM_setValue("browserNotifications", browserNotifications);
alert(`Browser notifications are now ${browserNotifications ? "enabled" : "disabled"}.`);
}
GM_registerMenuCommand("Toggle Browser Notifications", toggleBrowserNotifications);
let onVideoPage = false,
skipAd = null,
skipBannerAd = null,
like = null,
dislike = null;
function findButtons() {
// Only run on video watch pages.
if (!/^\/watch/.test(location.pathname)) {
onVideoPage = false;
return;
}
onVideoPage = true;
// Find the skip ad buttons.
skipAd = document.querySelector(".ytp-ad-skip-button");
skipBannerAd = document.querySelector(".ytp-ad-overlay-close-button");
// Find the Like/Dislike buttons by custom element tags.
like = document.querySelector("like-button-view-model button");
dislike = document.querySelector("dislike-button-view-model button");
// Fallback: Use attribute selectors if necessary.
if (!like) {
like = document.querySelector('button[aria-label*="like this video"]');
}
if (!dislike) {
dislike = document.querySelector('button[aria-label^="Dislike this video"]');
}
}
// Initial search.
findButtons();
// Watch for DOM changes (AJAX navigation on YouTube).
const observer = new MutationObserver(findButtons);
observer.observe(document.documentElement, { childList: true, subtree: true });
// Listen for keydown events.
window.addEventListener("keydown", (e) => {
if (!onVideoPage) {
return;
}
// Avoid interfering with input fields or editable content.
const tag = e.target.tagName.toLowerCase();
if (e.target.isContentEditable || tag === "input" || tag === "textarea") {
return;
}
// "[" key to toggle like.
if (e.code === "BracketLeft" && like) {
like.click();
if (browserNotifications && typeof GM_notification !== "undefined") {
const action =
like.getAttribute("aria-pressed") === "true"
? "Video Liked"
: "Like Removed";
GM_notification({ title: "YouTube", text: action, silent: true, timeout: 2500 });
}
}
// "]" key to toggle dislike.
else if (e.code === "BracketRight" && dislike) {
dislike.click();
if (browserNotifications && typeof GM_notification !== "undefined") {
const action =
dislike.getAttribute("aria-pressed") === "true"
? "Video Disliked"
: "Dislike Removed";
GM_notification({ title: "YouTube", text: action, silent: true, timeout: 2500 });
}
}
// "S" key to skip ads.
else if (e.code === "KeyS") {
if (skipAd) {
skipAd.click();
} else if (skipBannerAd) {
skipBannerAd.click();
}
}
});
})();