mirror of
https://github.com/Alvin-Zilverstand/return-youtube-dislike.git
synced 2026-10-28 07:40:27 +01:00
Merge branch 'main' of https://github.com/Anarios/return-youtube-dislike
This commit is contained in:
@@ -1,387 +1,62 @@
|
||||
function RYD() {
|
||||
const LIKED_STATE = "LIKED_STATE";
|
||||
const DISLIKED_STATE = "DISLIKED_STATE";
|
||||
const NEUTRAL_STATE = "NEUTRAL_STATE";
|
||||
|
||||
let storedData = {
|
||||
likes: 0,
|
||||
dislikes: 0,
|
||||
previousState: NEUTRAL_STATE,
|
||||
};
|
||||
import {
|
||||
getButtons,
|
||||
getLikeButton,
|
||||
getDislikeButton,
|
||||
checkForSignInButton,
|
||||
} from "./src/buttons";
|
||||
import {
|
||||
isMobile,
|
||||
isVideoDisliked,
|
||||
isVideoLiked,
|
||||
getState,
|
||||
setState,
|
||||
setInitialState,
|
||||
setLikes,
|
||||
setDislikes,
|
||||
getLikeCountFromButton,
|
||||
LIKED_STATE,
|
||||
DISLIKED_STATE,
|
||||
NEUTRAL_STATE,
|
||||
} from "./src/state";
|
||||
import { numberFormat, getBrowser, getVideoId, isVideoLoaded, cLog } from "./src/utils";
|
||||
import { createRateBar } from "./src/bar";
|
||||
import { sendVideoIds, sendVote, likeClicked, dislikeClicked } from "./src/events"
|
||||
|
||||
function cLog(message, writer) {
|
||||
message = `[return youtube dislike]: ${message}`;
|
||||
if (writer) {
|
||||
writer(message);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
let storedData = {
|
||||
likes: 0,
|
||||
dislikes: 0,
|
||||
previousState: NEUTRAL_STATE,
|
||||
};
|
||||
|
||||
function isMobile() {
|
||||
return location.hostname == "m.youtube.com";
|
||||
}
|
||||
let jsInitChecktimer = null;
|
||||
|
||||
function getButtons() {
|
||||
if (isMobile()) {
|
||||
return document.querySelector(".slim-video-action-bar-actions");
|
||||
}
|
||||
// If Menu Element Is Displayed:
|
||||
if (document.getElementById("menu-container")?.offsetParent === null) {
|
||||
return document.querySelector(
|
||||
"ytd-menu-renderer.ytd-watch-metadata > div"
|
||||
);
|
||||
// If Menu Element Isnt Displayed:
|
||||
} else {
|
||||
return document
|
||||
.getElementById("menu-container")
|
||||
?.querySelector("#top-level-buttons-computed");
|
||||
}
|
||||
}
|
||||
|
||||
function getLikeButton() {
|
||||
return getButtons().children[0];
|
||||
}
|
||||
|
||||
function getDislikeButton() {
|
||||
return getButtons().children[1];
|
||||
}
|
||||
|
||||
function isVideoLiked() {
|
||||
if (isMobile()) {
|
||||
return (
|
||||
getLikeButton().querySelector("button").getAttribute("aria-label") ==
|
||||
"true"
|
||||
);
|
||||
}
|
||||
return getLikeButton().classList.contains("style-default-active");
|
||||
}
|
||||
|
||||
function isVideoDisliked() {
|
||||
if (isMobile()) {
|
||||
return (
|
||||
getDislikeButton().querySelector("button").getAttribute("aria-label") ==
|
||||
"true"
|
||||
);
|
||||
}
|
||||
return getDislikeButton().classList.contains("style-default-active");
|
||||
}
|
||||
|
||||
function checkForSignInButton() {
|
||||
if (
|
||||
document.querySelector(
|
||||
"a[href^='https://accounts.google.com/ServiceLogin']"
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getState() {
|
||||
if (isVideoLiked()) {
|
||||
return { current: LIKED_STATE, previous: storedData.previousState };
|
||||
}
|
||||
if (isVideoDisliked()) {
|
||||
return { current: DISLIKED_STATE, previous: storedData.previousState };
|
||||
}
|
||||
return { current: NEUTRAL_STATE, previous: storedData.previousState };
|
||||
}
|
||||
|
||||
//--- Sets The Likes And Dislikes Values ---//
|
||||
function setLikes(likesCount) {
|
||||
(getButtons().children[0].querySelector("#text")).innerText = likesCount;
|
||||
}
|
||||
|
||||
function setDislikes(dislikesCount) {
|
||||
if (isMobile()) {
|
||||
getButtons().children[1].querySelector(
|
||||
".button-renderer-text"
|
||||
).innerText = dislikesCount;
|
||||
return;
|
||||
}
|
||||
(getButtons().children[1].querySelector("#text").innerText) = dislikesCount;
|
||||
}
|
||||
|
||||
function getLikeCountFromButton() {
|
||||
let likesStr = getLikeButton()
|
||||
.querySelector("button")
|
||||
.getAttribute("aria-label")
|
||||
.replace(/\D/g, "");
|
||||
return likesStr.length > 0 ? parseInt(likesStr) : false;
|
||||
}
|
||||
|
||||
function processResponse(response) {
|
||||
const formattedDislike = numberFormat(response.dislikes);
|
||||
setDislikes(formattedDislike);
|
||||
storedData.dislikes = parseInt(response.dislikes);
|
||||
storedData.likes = getLikeCountFromButton() || parseInt(response.likes);
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
}
|
||||
|
||||
function setState() {
|
||||
storedData.previousState = isVideoDisliked()
|
||||
? DISLIKED_STATE
|
||||
: isVideoLiked()
|
||||
? LIKED_STATE
|
||||
: NEUTRAL_STATE;
|
||||
let statsSet = false;
|
||||
|
||||
RYDTools.getBrowser().runtime.sendMessage(
|
||||
{
|
||||
message: "set_state",
|
||||
videoId: getVideoId(window.location.href),
|
||||
state: getState().current,
|
||||
likeCount: getLikeCountFromButton() || null
|
||||
},
|
||||
function (response) {
|
||||
cLog("response from api:");
|
||||
cLog(JSON.stringify(response));
|
||||
if (response !== undefined && !("traceId" in response) && !statsSet) {
|
||||
processResponse(response);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function sendVote(vote) {
|
||||
RYDTools.getBrowser().runtime.sendMessage({
|
||||
message: "send_vote",
|
||||
vote: vote,
|
||||
videoId: getVideoId(window.location.href)
|
||||
});
|
||||
}
|
||||
|
||||
function likeClicked() {
|
||||
if (checkForSignInButton() === false) {
|
||||
if (storedData.previousState === DISLIKED_STATE) {
|
||||
sendVote(1);
|
||||
storedData.dislikes--;
|
||||
storedData.likes++;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
storedData.previousState = LIKED_STATE;
|
||||
} else if (storedData.previousState === NEUTRAL_STATE) {
|
||||
sendVote(1);
|
||||
storedData.likes++;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = LIKED_STATE;
|
||||
} else if ((storedData.previousState = LIKED_STATE)) {
|
||||
sendVote(0);
|
||||
storedData.likes--;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = NEUTRAL_STATE;
|
||||
function setEventListeners(evt) {
|
||||
function checkForJS_Finish() {
|
||||
if (getButtons()?.offsetParent && isVideoLoaded()) {
|
||||
clearInterval(jsInitChecktimer);
|
||||
jsInitChecktimer = null;
|
||||
const buttons = getButtons();
|
||||
if (!window.returnDislikeButtonlistenersSet) {
|
||||
buttons.children[0].addEventListener("click", () => likeClicked(storedData));
|
||||
buttons.children[1].addEventListener("click", () => dislikeClicked(storedData));
|
||||
window.returnDislikeButtonlistenersSet = true;
|
||||
}
|
||||
setInitialState(storedData);
|
||||
}
|
||||
}
|
||||
|
||||
function dislikeClicked() {
|
||||
if (checkForSignInButton() == false) {
|
||||
if (storedData.previousState === NEUTRAL_STATE) {
|
||||
sendVote(-1);
|
||||
storedData.dislikes++;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = DISLIKED_STATE;
|
||||
} else if (storedData.previousState === DISLIKED_STATE) {
|
||||
sendVote(0);
|
||||
storedData.dislikes--;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = NEUTRAL_STATE;
|
||||
} else if (storedData.previousState === LIKED_STATE) {
|
||||
sendVote(-1);
|
||||
storedData.likes--;
|
||||
storedData.dislikes++;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = DISLIKED_STATE;
|
||||
}
|
||||
}
|
||||
if (window.location.href.indexOf("watch?") >= 0) {
|
||||
jsInitChecktimer = setInterval(checkForJS_Finish, 111);
|
||||
}
|
||||
|
||||
function setInitialState() {
|
||||
setState();
|
||||
setTimeout(() => {
|
||||
sendVideoIds();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function getVideoId(url) {
|
||||
const urlObject = new URL(url);
|
||||
const pathname = urlObject.pathname;
|
||||
if (pathname.startsWith("/clip")) {
|
||||
return document.querySelector("meta[itemprop='videoId']").content;
|
||||
} else {
|
||||
return urlObject.searchParams.get("v");
|
||||
}
|
||||
}
|
||||
|
||||
function isVideoLoaded() {
|
||||
const videoId = getVideoId(window.location.href);
|
||||
return (
|
||||
document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !==
|
||||
null ||
|
||||
// mobile: no video-id attribute
|
||||
document.querySelector('#player[loading="false"]:not([hidden])') !== null
|
||||
);
|
||||
}
|
||||
|
||||
function roundDown(num) {
|
||||
if (num < 1000) return num;
|
||||
const int = Math.floor(Math.log10(num) - 2);
|
||||
const decimal = int + (int % 3 ? 1 : 0);
|
||||
const value = Math.floor(num / 10 ** decimal);
|
||||
return value * 10 ** decimal;
|
||||
}
|
||||
|
||||
function numberFormat(numberState) {
|
||||
let userLocales;
|
||||
try {
|
||||
userLocales = new URL(
|
||||
Array.from(document.querySelectorAll("head > link[rel='search']"))
|
||||
?.find((n) => n?.getAttribute("href")?.includes("?locale="))
|
||||
?.getAttribute("href")
|
||||
)?.searchParams?.get("locale");
|
||||
} catch {}
|
||||
const formatter = Intl.NumberFormat(
|
||||
document.documentElement.lang || userLocales || navigator.language,
|
||||
{
|
||||
notation: "compact",
|
||||
}
|
||||
);
|
||||
|
||||
return formatter.format(roundDown(numberState));
|
||||
}
|
||||
|
||||
let jsInitChecktimer = null;
|
||||
|
||||
function setEventListeners(evt) {
|
||||
function checkForJS_Finish() {
|
||||
if (getButtons()?.offsetParent && isVideoLoaded()) {
|
||||
clearInterval(jsInitChecktimer);
|
||||
jsInitChecktimer = null;
|
||||
const buttons = getButtons();
|
||||
if (!window.returnDislikeButtonlistenersSet) {
|
||||
buttons.children[0].addEventListener("click", likeClicked);
|
||||
buttons.children[1].addEventListener("click", dislikeClicked);
|
||||
window.returnDislikeButtonlistenersSet = true;
|
||||
}
|
||||
setInitialState();
|
||||
}
|
||||
}
|
||||
|
||||
if (window.location.href.indexOf("watch?") >= 0) {
|
||||
jsInitChecktimer = setInterval(checkForJS_Finish, 111);
|
||||
}
|
||||
}
|
||||
|
||||
function createRateBar(likes, dislikes) {
|
||||
let rateBar = document.getElementById("ryd-bar-container");
|
||||
|
||||
const widthPx =
|
||||
getButtons().children[0].clientWidth +
|
||||
getButtons().children[1].clientWidth +
|
||||
8;
|
||||
|
||||
const widthPercent =
|
||||
likes + dislikes > 0 ? (likes / (likes + dislikes)) * 100 : 50;
|
||||
|
||||
if (!rateBar) {
|
||||
(
|
||||
document.getElementById("menu-container") ||
|
||||
document.querySelector("ytm-slim-video-action-bar-renderer")
|
||||
).insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`
|
||||
<div class="ryd-tooltip" style="width: ${widthPx}px">
|
||||
<div class="ryd-tooltip-bar-container">
|
||||
<div
|
||||
id="ryd-bar-container"
|
||||
style="width: 100%; height: 2px;"
|
||||
>
|
||||
<div
|
||||
id="ryd-bar"
|
||||
style="width: ${widthPercent}%; height: 100%"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<tp-yt-paper-tooltip position="top" id="ryd-dislike-tooltip" class="style-scope ytd-sentiment-bar-renderer" role="tooltip" tabindex="-1">
|
||||
<!--css-build:shady-->${likes.toLocaleString()} / ${dislikes.toLocaleString()}
|
||||
</tp-yt-paper-tooltip>
|
||||
</div>
|
||||
`
|
||||
);
|
||||
} else {
|
||||
document.getElementById("ryd-bar-container").style.width = widthPx + "px";
|
||||
document.getElementById("ryd-bar").style.width = widthPercent + "%";
|
||||
|
||||
document.querySelector(
|
||||
"#ryd-dislike-tooltip > #tooltip"
|
||||
).innerHTML = `${likes.toLocaleString()} / ${dislikes.toLocaleString()}`;
|
||||
}
|
||||
}
|
||||
|
||||
function sendVideoIds() {
|
||||
let links = Array.from(
|
||||
document.getElementsByClassName(
|
||||
"yt-simple-endpoint ytd-compact-video-renderer"
|
||||
)
|
||||
).concat(
|
||||
Array.from(
|
||||
document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail")
|
||||
)
|
||||
);
|
||||
// Also try mobile
|
||||
if (links.length < 1)
|
||||
links = Array.from(
|
||||
document.querySelectorAll(
|
||||
".large-media-item-metadata > a, a.large-media-item-thumbnail-container"
|
||||
)
|
||||
);
|
||||
const ids = links
|
||||
.filter((x) => x.href && x.href.indexOf("/watch?v=") > 0)
|
||||
.map((x) => getVideoId(x.href));
|
||||
RYDTools.getBrowser().runtime.sendMessage({
|
||||
message: "send_links",
|
||||
videoIds: ids,
|
||||
});
|
||||
}
|
||||
|
||||
setEventListeners();
|
||||
|
||||
document.addEventListener("yt-navigate-finish", function (event) {
|
||||
if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
|
||||
window.returnDislikeButtonlistenersSet = false;
|
||||
setEventListeners();
|
||||
});
|
||||
|
||||
setTimeout(() => sendVideoIds(), 2500);
|
||||
|
||||
this.init = function () {};
|
||||
}
|
||||
|
||||
RYD.getInstance = function () {
|
||||
if (typeof RYD.instance == "undefined") RYD.instance = new RYD();
|
||||
return RYD.instance;
|
||||
};
|
||||
setEventListeners();
|
||||
|
||||
RYDTools = {};
|
||||
document.addEventListener("yt-navigate-finish", function (event) {
|
||||
if (jsInitChecktimer !== null) clearInterval(jsInitChecktimer);
|
||||
window.returnDislikeButtonlistenersSet = false;
|
||||
setEventListeners();
|
||||
});
|
||||
|
||||
RYDTools.getBrowser = function () {
|
||||
if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined") {
|
||||
return chrome;
|
||||
} else if (
|
||||
typeof browser !== "undefined" &&
|
||||
typeof browser.runtime !== "undefined"
|
||||
) {
|
||||
return browser;
|
||||
} else {
|
||||
console.log("browser is not supported");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
RYD.getInstance().init();
|
||||
setTimeout(() => sendVideoIds(), 2500);
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { getButtons } from "./buttons";
|
||||
|
||||
function createRateBar(likes, dislikes) {
|
||||
let rateBar = document.getElementById("ryd-bar-container");
|
||||
|
||||
const widthPx =
|
||||
getButtons().children[0].clientWidth +
|
||||
getButtons().children[1].clientWidth +
|
||||
8;
|
||||
|
||||
const widthPercent =
|
||||
likes + dislikes > 0 ? (likes / (likes + dislikes)) * 100 : 50;
|
||||
|
||||
if (!rateBar) {
|
||||
(
|
||||
document.getElementById("menu-container") ||
|
||||
document.querySelector("ytm-slim-video-action-bar-renderer")
|
||||
).insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`
|
||||
<div class="ryd-tooltip" style="width: ${widthPx}px">
|
||||
<div class="ryd-tooltip-bar-container">
|
||||
<div
|
||||
id="ryd-bar-container"
|
||||
style="width: 100%; height: 2px;"
|
||||
>
|
||||
<div
|
||||
id="ryd-bar"
|
||||
style="width: ${widthPercent}%; height: 100%"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<tp-yt-paper-tooltip position="top" id="ryd-dislike-tooltip" class="style-scope ytd-sentiment-bar-renderer" role="tooltip" tabindex="-1">
|
||||
<!--css-build:shady-->${likes.toLocaleString()} / ${dislikes.toLocaleString()}
|
||||
</tp-yt-paper-tooltip>
|
||||
</div>
|
||||
`
|
||||
);
|
||||
} else {
|
||||
document.getElementById("ryd-bar-container").style.width = widthPx + "px";
|
||||
document.getElementById("ryd-bar").style.width = widthPercent + "%";
|
||||
|
||||
document.querySelector(
|
||||
"#ryd-dislike-tooltip > #tooltip"
|
||||
).innerHTML = `${likes.toLocaleString()} / ${dislikes.toLocaleString()}`;
|
||||
}
|
||||
}
|
||||
|
||||
export { createRateBar };
|
||||
@@ -0,0 +1,43 @@
|
||||
import { isMobile } from "./state";
|
||||
|
||||
function getButtons() {
|
||||
if (isMobile()) {
|
||||
return document.querySelector(".slim-video-action-bar-actions");
|
||||
}
|
||||
//--- If Menu Element Is Displayed: ---//
|
||||
if (document.getElementById("menu-container")?.offsetParent === null) {
|
||||
return document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div");
|
||||
//--- If Menu Element Isnt Displayed: ---//
|
||||
} else {
|
||||
return document
|
||||
.getElementById("menu-container")
|
||||
?.querySelector("#top-level-buttons-computed");
|
||||
}
|
||||
}
|
||||
|
||||
function getLikeButton() {
|
||||
return getButtons().children[0];
|
||||
}
|
||||
|
||||
function getDislikeButton() {
|
||||
return getButtons().children[1];
|
||||
}
|
||||
|
||||
function checkForSignInButton() {
|
||||
if (
|
||||
document.querySelector(
|
||||
"a[href^='https://accounts.google.com/ServiceLogin']"
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
getButtons,
|
||||
getLikeButton,
|
||||
getDislikeButton,
|
||||
checkForSignInButton,
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
import { getBrowser, getVideoId, numberFormat } from "./utils"
|
||||
import { checkForSignInButton } from "./buttons"
|
||||
import { NEUTRAL_STATE, LIKED_STATE, DISLIKED_STATE, setDislikes } from "./state"
|
||||
import { createRateBar } from "./bar"
|
||||
|
||||
function sendVote(vote) {
|
||||
getBrowser().runtime.sendMessage({
|
||||
message: "send_vote",
|
||||
vote: vote,
|
||||
videoId: getVideoId(window.location.href),
|
||||
});
|
||||
}
|
||||
|
||||
function sendVideoIds() {
|
||||
let links = Array.from(
|
||||
document.getElementsByClassName(
|
||||
"yt-simple-endpoint ytd-compact-video-renderer"
|
||||
)
|
||||
).concat(
|
||||
Array.from(
|
||||
document.getElementsByClassName("yt-simple-endpoint ytd-thumbnail")
|
||||
)
|
||||
);
|
||||
// Also try mobile
|
||||
if (links.length < 1)
|
||||
links = Array.from(
|
||||
document.querySelectorAll(
|
||||
".large-media-item-metadata > a, a.large-media-item-thumbnail-container"
|
||||
)
|
||||
);
|
||||
const ids = links
|
||||
.filter((x) => x.href && x.href.indexOf("/watch?v=") > 0)
|
||||
.map((x) => getVideoId(x.href));
|
||||
getBrowser().runtime.sendMessage({
|
||||
message: "send_links",
|
||||
videoIds: ids,
|
||||
});
|
||||
}
|
||||
|
||||
function likeClicked(storedData) {
|
||||
if (checkForSignInButton() === false) {
|
||||
if (storedData.previousState === DISLIKED_STATE) {
|
||||
sendVote(1);
|
||||
storedData.dislikes--;
|
||||
storedData.likes++;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
storedData.previousState = LIKED_STATE;
|
||||
} else if (storedData.previousState === NEUTRAL_STATE) {
|
||||
sendVote(1);
|
||||
storedData.likes++;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = LIKED_STATE;
|
||||
} else if ((storedData.previousState = LIKED_STATE)) {
|
||||
sendVote(0);
|
||||
storedData.likes--;
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = NEUTRAL_STATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dislikeClicked(storedData) {
|
||||
if (checkForSignInButton() == false) {
|
||||
if (storedData.previousState === NEUTRAL_STATE) {
|
||||
sendVote(-1);
|
||||
storedData.dislikes++;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = DISLIKED_STATE;
|
||||
} else if (storedData.previousState === DISLIKED_STATE) {
|
||||
sendVote(0);
|
||||
storedData.dislikes--;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = NEUTRAL_STATE;
|
||||
} else if (storedData.previousState === LIKED_STATE) {
|
||||
sendVote(-1);
|
||||
storedData.likes--;
|
||||
storedData.dislikes++;
|
||||
setDislikes(numberFormat(storedData.dislikes));
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
storedData.previousState = DISLIKED_STATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { sendVote, sendVideoIds, likeClicked, dislikeClicked }
|
||||
@@ -0,0 +1,120 @@
|
||||
import { getLikeButton, getDislikeButton, getButtons } from "./buttons";
|
||||
import { createRateBar } from "./bar";
|
||||
import { getBrowser, getVideoId, cLog, numberFormat } from "./utils";
|
||||
import { sendVideoIds } from "./events";
|
||||
|
||||
const LIKED_STATE = "LIKED_STATE";
|
||||
const DISLIKED_STATE = "DISLIKED_STATE";
|
||||
const NEUTRAL_STATE = "NEUTRAL_STATE";
|
||||
|
||||
function isMobile() {
|
||||
return location.hostname == "m.youtube.com";
|
||||
}
|
||||
|
||||
function isVideoLiked() {
|
||||
if (isMobile()) {
|
||||
return (
|
||||
getLikeButton().querySelector("button").getAttribute("aria-label") ==
|
||||
"true"
|
||||
);
|
||||
}
|
||||
return getLikeButton().classList.contains("style-default-active");
|
||||
}
|
||||
|
||||
function isVideoDisliked() {
|
||||
if (isMobile()) {
|
||||
return (
|
||||
getDislikeButton().querySelector("button").getAttribute("aria-label") ==
|
||||
"true"
|
||||
);
|
||||
}
|
||||
return getDislikeButton().classList.contains("style-default-active");
|
||||
}
|
||||
|
||||
function getState(storedData) {
|
||||
if (isVideoLiked()) {
|
||||
return { current: LIKED_STATE, previous: storedData.previousState };
|
||||
}
|
||||
if (isVideoDisliked()) {
|
||||
return { current: DISLIKED_STATE, previous: storedData.previousState };
|
||||
}
|
||||
return { current: NEUTRAL_STATE, previous: storedData.previousState };
|
||||
}
|
||||
|
||||
//--- Sets The Likes And Dislikes Values ---//
|
||||
function setLikes(likesCount) {
|
||||
getButtons().children[0].querySelector("#text").innerText = likesCount;
|
||||
}
|
||||
|
||||
function setDislikes(dislikesCount) {
|
||||
if (isMobile()) {
|
||||
getButtons().children[1].querySelector(".button-renderer-text").innerText =
|
||||
dislikesCount;
|
||||
return;
|
||||
}
|
||||
getButtons().children[1].querySelector("#text").innerText = dislikesCount;
|
||||
}
|
||||
|
||||
function getLikeCountFromButton() {
|
||||
let likesStr = getLikeButton()
|
||||
.querySelector("button")
|
||||
.getAttribute("aria-label")
|
||||
.replace(/\D/g, "");
|
||||
return likesStr.length > 0 ? parseInt(likesStr) : false;
|
||||
}
|
||||
|
||||
function processResponse(response, storedData) {
|
||||
const formattedDislike = numberFormat(response.dislikes);
|
||||
setDislikes(formattedDislike);
|
||||
storedData.dislikes = parseInt(response.dislikes);
|
||||
storedData.likes = getLikeCountFromButton() || parseInt(response.likes);
|
||||
createRateBar(storedData.likes, storedData.dislikes);
|
||||
}
|
||||
|
||||
function setState(storedData) {
|
||||
storedData.previousState = isVideoDisliked()
|
||||
? DISLIKED_STATE
|
||||
: isVideoLiked()
|
||||
? LIKED_STATE
|
||||
: NEUTRAL_STATE;
|
||||
let statsSet = false;
|
||||
|
||||
getBrowser().runtime.sendMessage(
|
||||
{
|
||||
message: "set_state",
|
||||
videoId: getVideoId(window.location.href),
|
||||
state: getState(storedData).current,
|
||||
likeCount: getLikeCountFromButton() || null,
|
||||
},
|
||||
function (response) {
|
||||
cLog("response from api:");
|
||||
cLog(JSON.stringify(response));
|
||||
if (response !== undefined && !("traceId" in response) && !statsSet) {
|
||||
processResponse(response, storedData);
|
||||
} else {
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function setInitialState(storedData) {
|
||||
setState(storedData);
|
||||
setTimeout(() => {
|
||||
sendVideoIds();
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
export {
|
||||
isMobile,
|
||||
isVideoDisliked,
|
||||
isVideoLiked,
|
||||
getState,
|
||||
setState,
|
||||
setInitialState,
|
||||
setLikes,
|
||||
setDislikes,
|
||||
getLikeCountFromButton,
|
||||
LIKED_STATE,
|
||||
DISLIKED_STATE,
|
||||
NEUTRAL_STATE,
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
function roundDown(num) {
|
||||
if (num < 1000) return num;
|
||||
const int = Math.floor(Math.log10(num) - 2);
|
||||
const decimal = int + (int % 3 ? 1 : 0);
|
||||
const value = Math.floor(num / 10 ** decimal);
|
||||
return value * 10 ** decimal;
|
||||
}
|
||||
|
||||
function numberFormat(numberState) {
|
||||
let userLocales;
|
||||
try {
|
||||
userLocales = new URL(
|
||||
Array.from(document.querySelectorAll("head > link[rel='search']"))
|
||||
?.find((n) => n?.getAttribute("href")?.includes("?locale="))
|
||||
?.getAttribute("href")
|
||||
)?.searchParams?.get("locale");
|
||||
} catch {}
|
||||
const formatter = Intl.NumberFormat(
|
||||
document.documentElement.lang || userLocales || navigator.language,
|
||||
{
|
||||
notation: "compact",
|
||||
}
|
||||
);
|
||||
|
||||
return formatter.format(roundDown(numberState));
|
||||
}
|
||||
|
||||
function getBrowser() {
|
||||
if (typeof chrome !== "undefined" && typeof chrome.runtime !== "undefined") {
|
||||
return chrome;
|
||||
} else if (
|
||||
typeof browser !== "undefined" &&
|
||||
typeof browser.runtime !== "undefined"
|
||||
) {
|
||||
return browser;
|
||||
} else {
|
||||
console.log("browser is not supported");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getVideoId(url) {
|
||||
const urlObject = new URL(url);
|
||||
const pathname = urlObject.pathname;
|
||||
if (pathname.startsWith("/clip")) {
|
||||
return document.querySelector("meta[itemprop='videoId']").content;
|
||||
} else {
|
||||
return urlObject.searchParams.get("v");
|
||||
}
|
||||
}
|
||||
|
||||
function isVideoLoaded() {
|
||||
const videoId = getVideoId(window.location.href);
|
||||
return (
|
||||
document.querySelector(`ytd-watch-flexy[video-id='${videoId}']`) !== null ||
|
||||
// mobile: no video-id attribute
|
||||
document.querySelector('#player[loading="false"]:not([hidden])') !== null
|
||||
);
|
||||
}
|
||||
|
||||
function cLog(message, writer) {
|
||||
message = `[return youtube dislike]: ${message}`;
|
||||
if (writer) {
|
||||
writer(message);
|
||||
} else {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
export { numberFormat, getBrowser, getVideoId, isVideoLoaded, cLog }
|
||||
Reference in New Issue
Block a user