Skip to content

Instantly share code, notes, and snippets.

@Yukaii
Last active March 10, 2023 05:38
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Yukaii/48801545e9cb2c1e7fb84ac39af112b2 to your computer and use it in GitHub Desktop.
Save Yukaii/48801545e9cb2c1e7fb84ac39af112b2 to your computer and use it in GitHub Desktop.
A Tampermonkey script to make YouTube dislike count back

(Deprecated) Make YouTube dislike count BACK!

Deprecated Attention

This script is no longer working. Please use https://chrome.google.com/webstore/detail/return-youtube-dislike/gebbhagfogifgggkldgodflihgfeippi instead, which is open sourced at https://github.com/Anarios/return-youtube-dislike.

Developers: If you’re using the YouTube API for dislikes, you will no longer have access to public dislike data beginning on December 13th ref: https://support.google.com/youtube/thread/134791097/update-to-youtube-dislike-counts?hl=en

スクリーンショット 2021-11-13 午後0 28 00

Installation

  1. Install Tampermoneky or Greasemonkey(Firefox) for your browser
  2. Click on this link to install.
  3. Go to Google Developer Console and generate new YouTube Data API key:
    1. Create a new project:
      スクリーンショット 2021-11-13 午後0 05 02
    2. Go to "API and Services", and enable YouTube Data API: スクリーンショット 2021-11-13 午後0 07 21 スクリーンショット 2021-11-13 午後0 08 24
    3. Create new API key credentials, and copy it for later use: スクリーンショット 2021-11-13 午後0 09 14
  4. Go to an YouTube video, it will prompt you to enter the key, paste it and hit enter スクリーンショット 2021-11-13 午後0 11 49
  5. And you will get dislike count back!
// ==UserScript==
// @name Make YouTube dislike count BACK!
// @namespace https://yukai.dev
// @version 0.3
// @description try to take over the world!
// @author Yukai Huang
// @include https://www.youtube.com/*
// @icon https://www.google.com/s2/favicons?domain=youtube.com
// @downloadURL https://gist.githubusercontent.com/Tajnymag/48801545e9cb2c1e7fb84ac39af112b2/raw/youtube-dislike-back.user.js
// @grant none
// ==/UserScript==
(function () {
function loadConfig() {
const ITEM_KEY = 'YOUTUBE_DISLIKE_COUNT_API_KEY';
const apiKey = window.localStorage.getItem(ITEM_KEY);
if (apiKey) {
return apiKey;
} else {
const key = prompt('Enter your youtube dislike count api key');
window.localStorage.setItem(ITEM_KEY, key);
return key;
}
}
function getVideoId() {
const params = new URLSearchParams(window.location.search);
const videoId = params.get('v') || '';
return videoId;
}
function cacheFn(fn) {
const cache = {};
return async function (...args) {
const key = args.join('-');
if (cache[key]) {
return cache[key];
} else {
const result = await Promise.resolve(fn(...args));
cache[key] = result;
return result;
}
};
}
async function fetchVideoStatistics(videoId) {
if (!videoId) {
return;
}
const key = loadConfig();
const params = new URLSearchParams({
part: 'statistics',
id: videoId,
key,
});
const { items = [] } = await fetch(
`https://www.googleapis.com/youtube/v3/videos?${params}`,
).then((res) => res.json());
if (items?.length === 0) {
return {};
}
const { likeCount: likeCountString, dislikeCount: dislikeCountString } =
items && items[0] && items[0].statistics;
const likeCount = parseInt(likeCountString, 10);
const dislikeCount = parseInt(dislikeCountString, 10);
return {
likeCount,
dislikeCount,
};
}
const fetchVideoStatisticsCached = cacheFn(fetchVideoStatistics);
async function getVideoStatistics() {
const videoId = getVideoId();
return fetchVideoStatisticsCached(videoId);
}
function formatCount(count) {
if (Math.log10(count) > 9) {
return `${Math.floor(count / 1000000)}M`;
} else if (Math.log10(count) > 6) {
return `${Math.floor(count / 1000)}K`;
} else {
return count;
}
}
function renderStatistics(likeCount, dislikeCount) {
const percentage = (likeCount / (likeCount + dislikeCount)) * 100;
const existingBar = document.querySelector(
'#sentiment.ytd-video-primary-info-renderer',
);
if (existingBar) {
existingBar.remove();
}
const barElement = document.createElement('div');
barElement.setAttribute('id', 'sentiment');
barElement.setAttribute('system-icons', '');
barElement.setAttribute('style', `width: 145px;`);
barElement.className = 'style-scope ytd-video-primary-info-renderer';
barElement.title = `${likeCount} / ${likeCount + dislikeCount}`;
barElement.innerHTML = `
<div id="container" class="style-scope ytd-sentiment-bar-renderer">
<div id="like-bar" class="style-scope ytd-sentiment-bar-renderer" style="width: ${percentage}%;"></div>
</div>`;
document
.querySelector('#menu-container.ytd-video-primary-info-renderer')
?.append(barElement);
const dislikeTextNode = document.querySelectorAll(
'#menu ytd-toggle-button-renderer yt-formatted-string',
)[1];
if (dislikeTextNode) {
dislikeTextNode.textContent = `${formatCount(dislikeCount)}`;
}
}
async function run() {
const { dislikeCount, likeCount } = await getVideoStatistics();
if (likeCount && dislikeCount) {
renderStatistics(likeCount, dislikeCount);
}
}
const menuSelector = '#menu';
new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.addedNodes.length > 0) {
const menu =
mutation.addedNodes[0].querySelector &&
mutation.addedNodes[0].querySelector(menuSelector);
if (menu) {
run();
}
}
});
}).observe(document.body, {
childList: true,
subtree: true,
});
new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
const menu = document.querySelector(menuSelector);
if (menu) {
run();
}
});
}).observe(document.querySelector('ytd-app'), {
attributes: true,
});
})();
@Yukaii
Copy link
Author

Yukaii commented Nov 12, 2021

總之先把那條加回來了:

スクリーンショット 2021-11-13 午前0 01 49

TODOs

  • Real count
  • documentation

@bosedipankar
Copy link

Awesome Dude ...

@DS2902
Copy link

DS2902 commented Nov 14, 2021

A window appeared for add the API, switched to another tab, created an API. I returned back to the youtube page, but there is no window for add the API and it does not appear anymore. Reinstalling the script doesn't help.

@LostWD
Copy link

LostWD commented Nov 14, 2021

no window for add the API(

@b159732000
Copy link

Awesome, it works!

@jericjan
Copy link

jericjan commented Nov 23, 2021

Hell yeah, my dude!

EDIT: Oof, just read the note.

@Yukaii
Copy link
Author

Yukaii commented Nov 23, 2021

https://www.reddit.com/r/youtube/comments/qtyn45/i_coded_a_userscript_to_restore_the_dislike/

There's a thread on reddit that provides more native way for fetching dislike count. However, we'll still not sure if the data will be gone after someday. I recommend use that script instead.

@jericjan
Copy link

Thanks. Good to know.

@peterzam
Copy link

peterzam commented Nov 25, 2021

formatCount function has error and I found this ->

function formatCount(num) {
  const lookup = [
    { value: 1, symbol: "" },
    { value: 1e3, symbol: "k" },
    { value: 1e6, symbol: "M" },
  ];
  const rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
  var item = lookup.slice().reverse().find(function(item) {
    return num >= item.value;
  });
  return item ? (num / item.value).toFixed(2).replace(rx, "$1") + item.symbol : "0";
}

source : https://stackoverflow.com/a/9462382

@Aeplexi
Copy link

Aeplexi commented Dec 5, 2021

Nice

@Yukaii
Copy link
Author

Yukaii commented Dec 14, 2021

Update: YouTube now removes dislike data completely 😭 None of the solutions would work...

@Korb
Copy link

Korb commented Mar 8, 2022

Update: YouTube now removes dislike data completely 😭 None of the solutions would work...

Please add information about this to the very beginning of the READMD.md.

@Yukaii
Copy link
Author

Yukaii commented Mar 9, 2022

@Korb Thanks for bumping this up, I've added an alternative solution in the README.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment