您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display and interact with dislikes on YouTube videos
// ==UserScript== // @name Return YouTube Dislike // @namespace http://tampermonkey.net/ // @version 3.1 // @description Display and interact with dislikes on YouTube videos // @author MrBlankCoding // @match https://www.youtube.com/** // @match *://*.youtube.com/* // @match *://www.youtube.com/watch** // @license MIT // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @run-at document-end // @connect returnyoutubedislikeapi.com // ==/UserScript== (function() { 'use strict'; const styles = ` .dislike-count { display: inline-flex; align-items: center; margin-left: 6px; font-size: 14px; font-family: "YouTube Sans", Roboto, sans-serif; transition: all 0.2s ease; } .dislike-active { color: #ff0000 !important; font-weight: 500; } .dislike-count-wrapper { display: flex; align-items: center; gap: 4px; } .dislike-animation { animation: pulse 0.3s ease-in-out; } @keyframes pulse { 0% { transform: scale(1); } 50% { transform: scale(1.2); } 100% { transform: scale(1); } } .yt-spec-button-shape-next__icon { transition: opacity 0.2s ease; } `; // Add styles to document const styleSheet = document.createElement("style"); styleSheet.textContent = styles; document.head.appendChild(styleSheet); // Store disliked videos const getDislikedVideos = () => GM_getValue('dislikedVideos', {}); const setDislikedVideos = (videos) => GM_setValue('dislikedVideos', videos); let originalIconHTML = null; window.addEventListener('yt-navigate-finish', fetchDislikeData); function fetchDislikeData() { const videoId = new URL(window.location.href).searchParams.get("v"); if (!videoId) return; const apiUrl = `https://returnyoutubedislikeapi.com/votes?videoId=${videoId}`; GM_xmlhttpRequest({ method: "GET", url: apiUrl, onload: function(response) { try { const data = JSON.parse(response.responseText); if (data && data.dislikes !== undefined) { displayDislikeCount(data.dislikes, videoId); setupStateChangeListeners(videoId); } } catch (error) { console.error('Error parsing API response:', error); } }, onerror: function(error) { console.error('Error fetching data from API:', error); } }); } function displayDislikeCount(dislikes, videoId) { const dislikeButton = document.querySelector('dislike-button-view-model'); if (!dislikeButton) return; const button = dislikeButton.querySelector('button'); if (!button) return; // Store original icon if not already stored const iconElement = button.querySelector('.yt-spec-button-shape-next__icon'); if (iconElement && !originalIconHTML) { originalIconHTML = iconElement.innerHTML; } // Remove any existing dislike count const existingCount = button.querySelector('.dislike-count'); if (existingCount) { existingCount.remove(); } // Create wrapper for better organization const wrapper = document.createElement('div'); wrapper.className = 'dislike-count-wrapper'; // Create dislike count element const dislikeCountElement = document.createElement('span'); dislikeCountElement.className = 'dislike-count'; dislikeCountElement.innerText = roundNumber(dislikes); // Check if video is disliked const dislikedVideos = getDislikedVideos(); if (dislikedVideos[videoId]) { dislikeCountElement.classList.add('dislike-active'); if (iconElement) { iconElement.style.opacity = '0'; } } wrapper.appendChild(dislikeCountElement); button.appendChild(wrapper); // Add click handler button.addEventListener('click', () => handleDislikeClick(videoId, dislikeCountElement, dislikes)); } function setupStateChangeListeners(videoId) { // Watch for like button clicks to reset dislike state const likeButton = document.querySelector('like-button-view-model button'); if (likeButton) { likeButton.addEventListener('click', () => { const dislikedVideos = getDislikedVideos(); if (dislikedVideos[videoId]) { delete dislikedVideos[videoId]; setDislikedVideos(dislikedVideos); resetDislikeUI(); } }); } } function handleDislikeClick(videoId, countElement, currentDislikes) { const dislikedVideos = getDislikedVideos(); const isDisliked = dislikedVideos[videoId]; if (isDisliked) { // Undislike delete dislikedVideos[videoId]; resetDislikeUI(); } else { // New dislike dislikedVideos[videoId] = true; countElement.classList.add('dislike-active'); countElement.classList.add('dislike-animation'); const iconElement = document.querySelector('.yt-spec-button-shape-next__icon'); if (iconElement) { iconElement.style.opacity = '0'; } // Remove animation class after it completes setTimeout(() => { countElement.classList.remove('dislike-animation'); }, 300); } setDislikedVideos(dislikedVideos); } function resetDislikeUI() { const countElement = document.querySelector('.dislike-count'); const iconElement = document.querySelector('.yt-spec-button-shape-next__icon'); if (countElement) { countElement.classList.remove('dislike-active'); } if (iconElement && originalIconHTML) { iconElement.style.opacity = '1'; iconElement.innerHTML = originalIconHTML; } } function roundNumber(num) { if (num >= 1000000) { return (num / 1000000).toFixed(1) + "M"; } else if (num >= 1000) { return (num / 1000).toFixed(1) + "K"; } return num.toLocaleString(); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址