// ==UserScript== // @name YouTube Restore Dislike Counters // @version 1.0.0 // @description A userscript to restore the dislike counts on YouTube. Not 100% accurate all the time, but still pretty accurate. // @author syndiate // @match *://www.youtube.com/* // @run_at document_start // ==/UserScript== function numberWithCommas(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); } async function waitForElm(s) { while (!document.querySelector(s)) { await new Promise(r => requestAnimationFrame(r)) } return; } async function init() { var ytdapp = document.querySelector("ytd-app"); var data = ytdapp.data; if (data.page != 'watch') { return; } for (var p = 0, q = data.response.contents.twoColumnWatchNextResults.results.results.contents.length; p < q; p++) { if (typeof data.response.contents.twoColumnWatchNextResults.results.results.contents[p].videoPrimaryInfoRenderer !== 'undefined') { var vidroot = data.response.contents.twoColumnWatchNextResults.results.results.contents[p]; break; } } var likestatus = (function() { for (var i = 0, o = vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons.length; i < o; i++) { var currenderer = vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons[i]; if (currenderer.isToggled) { return currenderer.defaultIcon.iconType; } } return 'INDIFFERENT'; })(); var l = likestatus == 'LIKE' ? parseInt(vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons[0].toggleButtonRenderer.toggledText.accessibility.accessibilityData.label.replaceAll(/[^0-9]+/g, "")) : parseInt(vidroot.videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons[0].toggleButtonRenderer.defaultText.accessibility.accessibilityData.label.replaceAll(/[^0-9]+/g, "")); var r = data.playerResponse.videoDetails.averageRating; function calculateDislikes(l, r) { var d = Math.round(l*((5-r)/(r-1))); return d; } var dislikes = r != 0 ? await calculateDislikes(l, r) : 0; var dislikesfin = numberWithCommas(dislikes) var likesfin = numberWithCommas(l); // added bonus //spaghetti code var toplevelbuttonsroot = ytdapp.data.response.contents.twoColumnWatchNextResults.results.results.contents[p].videoPrimaryInfoRenderer.videoActions.menuRenderer.topLevelButtons; var likebutton = toplevelbuttonsroot[0].toggleButtonRenderer; var dislikebutton = toplevelbuttonsroot[1].toggleButtonRenderer; if (r != 0) { if (likestatus == 'LIKE') { likebutton.toggledText.simpleText = likesfin; likebutton.defaultText.simpleText = numberWithCommas(l - 1); } else { likebutton.defaultText.simpleText = likesfin; likebutton.toggledText.simpleText = numberWithCommas(l + 1); } } else { likebutton.defaultText.simpleText = '0'; likebutton.toggledText.simpleText = '1'; } if (likestatus == 'DISLIKE') { dislikebutton.toggledText.simpleText = dislikesfin; dislikebutton.defaultText.simpleText = numberWithCommas(dislikes - 1); dislikebutton.toggledText.accessibility = { "label": dislikesfin + (dislikes === 1 ? " dislike" : " dislikes") }; dislikebutton.defaultText.accessibility = { "label": numberWithCommas(dislikes - 1) + (dislikes - 1 === 1 ? " dislike" : " dislikes") } } else { dislikebutton.defaultText.simpleText = dislikesfin; dislikebutton.toggledText.simpleText = numberWithCommas(dislikes + 1); dislikebutton.defaultText.accessibility = { "label": dislikesfin + (dislikes === 1 ? " dislike" : " dislikes") }; dislikebutton.toggledText.accessibility = { "label": numberWithCommas(dislikes + 1) + (dislikes + 1 === 1 ? " dislike" : " dislikes") } } dislikebutton.accessibility = { "label": "dislike this video along with " + dislikesfin + (dislikes === 1 ? " other person" : " other people") }; dislikebutton.accessibilityData = { "accessibilityData": { "label": "dislike this video along with " + dislikesfin + (dislikes === 1 ? " other person" : " other people") } }; function calculateSentiment(l, d) { return (l / (l + d)) * 100; } function calculatePossibleSentiment(proposedLikeStatus, l, d) { var finalval; switch(proposedLikeStatus) { case "INDIFFERENT": if (r !== 0) { if (likestatus === 'LIKE') { finalval = calculateSentiment(l - 1, d); break; } else if (likestatus === 'DISLIKE') { finalval = calculateSentiment(l, d - 1); break; } else { finalval = calculateSentiment(l, d); break; } } else { finalval = 0; break; } case "LIKE": if (r !== 0) { if (likestatus === 'LIKE') { finalval = calculateSentiment(l, d); break; } else if (likestatus === 'DISLIKE') { finalval = calculateSentiment(l + 1, d - 1); break; } else { finalval = calculateSentiment(l + 1, d); break; } } else { finalval = 100; break; } case "DISLIKE": if (r !== 0) { if (likestatus === 'LIKE') { finalval = calculateSentiment(l - 1, d + 1); break; } else if (likestatus === 'DISLIKE') { finalval = calculateSentiment(l, d); break; } else { finalval = calculateSentiment(l, d + 1); break; } } else { finalval = 0; break; } } return finalval; } ytdapp.data.response.contents.twoColumnWatchNextResults.results.results.contents[p].videoPrimaryInfoRenderer.sentimentBar = { "sentimentBarRenderer": { "percentIfIndifferent": calculatePossibleSentiment("INDIFFERENT", l, dislikes), "percentIfLiked": calculatePossibleSentiment("LIKE", l, dislikes), "percentIfDisliked": calculatePossibleSentiment("DISLIKE", l, dislikes), "likeStatus": likestatus, "tooltip": likesfin + " / " + dislikesfin } } var primaryinfoelem = document.querySelector("ytd-video-primary-info-renderer"); var oldprimaryinfodata = primaryinfoelem.data; await (primaryinfoelem.data = {}); primaryinfoelem.data = oldprimaryinfodata; } waitForElm("ytd-app").then(() => init()); window.addEventListener('yt-page-data-updated', init, false);