Skip to content

Instantly share code, notes, and snippets.

@Klaster1
Last active August 5, 2023 19:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Klaster1/fca96ffd47f7f1cfab76a54e66ce045b to your computer and use it in GitHub Desktop.
Save Klaster1/fca96ffd47f7f1cfab76a54e66ce045b to your computer and use it in GitHub Desktop.
Paint likes 🖌️🥰
// ==UserScript==
// @name Paint likes 🖌️🥰
// @description Like comments by pressing Shift while mouse curosor is over or hovering while Shift is down
// @version 1.2
// @grant none
// @match https://news.ycombinator.com/*
// @match https://www.youtube.com/*
// @match https://www.reddit.com/r/*/comments/*
// @match https://old.reddit.com/r/*/comments/*
// @icon data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🖌️</text></svg>
// @downloadURL https://gist.github.com/Klaster1/fca96ffd47f7f1cfab76a54e66ce045b/raw/paint-likes.user.js
// @updateURL https://gist.github.com/Klaster1/fca96ffd47f7f1cfab76a54e66ce045b/raw/paint-likes.user.js
// ==/UserScript==
/**
* @typedef {'youtube'|'hackernews'|'reddit-new'|'reddit-old'} WhereAmI
*/
/**
* @typedef {HTMLElement|undefined} LastHoveredElement
*/
/** @type {LastHoveredElement} */
let lastHoveredComment;
/**
* @returns {WhereAmI}
*/
const detectLocation = () => {
if (document.location.host.includes("ycombinator")) return "hackernews";
if (document.location.host.includes("youtube")) return "youtube";
if (document.location.host.includes("www.reddit.com")) return "reddit-new";
if (document.location.host.includes("old.reddit.com")) return "reddit-old";
};
/**
* @param {LastHoveredElement} target
* @return {void}
*/
const upvote = (target) => {
const location = detectLocation();
switch (location) {
case "youtube": {
target?.querySelector('button[aria-label^="Like this"]')?.click();
break;
}
case "hackernews": {
const upvoteButton = target?.querySelector("[id*=up]");
const upvoteButtonContainer = upvoteButton?.parentElement;
upvoteButtonContainer.style.animation = `0.15s 1 hn-arrow-disappear`;
upvoteButtonContainer.addEventListener(
"animationend",
() => {
upvoteButton?.click();
},
{ once: true }
);
break;
}
case "reddit-new": {
const isUpvoted = !!target.querySelector(".icon.icon-upvote_fill");
if (!isUpvoted)
target?.querySelector(`[data-click-id="upvote"]`)?.click();
break;
}
case "reddit-old": {
if (target)
[...target.children]
.find((el) => el.matches(".midcol.unvoted"))
?.querySelector(".arrow.up")
?.click();
break;
}
}
};
/**
* @param {HTMLElement} target
* @return {LastHoveredElement}
*/
const getLastHoveredElement = (target) => {
const location = detectLocation();
switch (location) {
case "youtube": {
return target.closest("ytd-comment-renderer");
}
case "hackernews": {
return target.closest(".athing");
}
case "reddit-new": {
return target.closest(".Comment");
}
case "reddit-old": {
return target.closest(".thing");
}
}
};
/**
* @param {string} styleText
* @returns {void}
*/
const injectStyles = (styleText) => {
const style = document.createElement("style");
style.textContent = styleText;
document.querySelector("head")?.appendChild(style);
};
document.addEventListener("mouseover", (e) => {
lastHoveredComment = getLastHoveredElement(e.target);
if (e.shiftKey) upvote(lastHoveredComment);
});
document.addEventListener("keydown", (e) => {
if (e.key === "Shift") upvote(lastHoveredComment);
});
injectStyles(`
@keyframes hn-arrow-disappear {
from {
transform: scale(1) translateY(0);
opacity: 1;
}
30% {
opacity: 0.3;
}
to {
transform: scale(2.5) translateY(-30px);
opacity: 0;
}
}
`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment