阻止 多#国 网站在学习过程中因错误减少用户的血量,通过拦截并阻止相关的“remove-heart”请求。
// ==UserScript== // @name 多#国阻止血量减少 // @name:en DuoLingo Prevent Remove Heart // @name:vi DuoLingo Ngăn Chặn Mất Tim // @name:fr DuoLingo Empêcher la Perte de Cœurs // @name:es DuoLingo Evitar la Pérdida de Corazones // @name:de DuoLingo Verhindern des Herzverlusts // @name:it DuoLingo Impedire la Perdita di Cuori // @name:ja DuoLingo ハート減少防止 // @name:ko DuoLingo 하트 감소 방지 // @name:ru DuoLingo Предотвращение Потери Сердец // @namespace https://space.bilibili.com/1569275826 // @match *://*.duolingo.com/* // @match *://*.duolingo.cn/* // @version 0.0.6 // @description 阻止 多#国 网站在学习过程中因错误减少用户的血量,通过拦截并阻止相关的“remove-heart”请求。 // @description:en Prevent the Duolingo website from reducing the number of hearts for users during the learning process by intercepting and blocking related "remove-heart" request. // @description:vi Ngăn chặn trang web Duolingo giảm số lượng trái tim của người dùng trong quá trình học tập bằng cách chặn các yêu cầu "remove-heart" liên quan. // @description:fr Empêchez le site Web de Duolingo de réduire le nombre de cœurs des utilisateurs pendant le processus d'apprentissage en interceptant et en bloquant les requêtes "remove-heart" associées. // @description:es Evita que el sitio web de Duolingo reduzca la cantidad de corazones de los usuarios durante el proceso de aprendizaje al interceptar y bloquear las solicitudes "remove-heart" relacionadas. // @description:de Verhindern Sie, dass die Duolingo-Website die Anzahl der Herzen der Benutzer während des Lernprozesses verringert, indem Sie verwandte "remove-heart"-Anfragen abfangen und blockieren. // @description:it Impedisci al sito web di Duolingo di ridurre il numero di cuori degli utenti durante il processo di apprendimento intercettando e bloccando le richieste "remove-heart" correlate. // @description:ja Duolingoのウェブサイトが学習プロセス中にユーザーのハートを減らすのを防ぐため、"remove-heart"リクエストを傍受してブロックします。 // @description:ko Duolingo 웹사이트가 학습 과정에서 사용자의 하트를 줄이는 것을 방지하기 위해 관련 "remove-heart" 요청을 가로채고 차단합니다. // @description:ru Предотвратите уменьшение количества сердец у пользователей на сайте Duolingo в процессе обучения, перехватывая и блокируя связанные запросы "remove-heart". // @author 深海云霁 // @license MIT // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // ==/UserScript== (function () { "use strict"; // 获取用户 UUID function getUUID() { const match = document.cookie.match( new RegExp("(^| )logged_out_uuid=([^;]+)") ); return match ? match[2] : undefined; } // 获取用户血量 (后端) async function getUserHeartFromBackend() { const uuid = getUUID(); const url = `/2017-06-30/users/${uuid}?fields=health&_=${Date.now()}`; const response = await fetch(url, { method: "GET", credentials: "include", }); return response.json(); } // 获取用户血量 (前端) function getUserHeartFromFrontend() { const spanElement = document.querySelector(".xb7v_") || document.querySelector("._1ceMn"); return spanElement?.textContent ? +spanElement.textContent : undefined; } // 检查血量是否一致 async function checkHeartConsistency() { const backendHearts = await getUserHeartFromBackend(); const frontendHearts = getUserHeartFromFrontend(); if ( frontendHearts !== undefined && backendHearts?.health?.hearts !== frontendHearts && window.confirm( navigator.language.toUpperCase() === "ZH-CN" ? "检测到血量不一致,是否刷新页面?" : "Detected inconsistent health, refresh the page?" ) ) { window.location.reload(); } } // 阻止 remove-heart 请求 function blockRemoveHeart() { const originalFetch = window.fetch; window.fetch = function (...args) { const [url] = args; if (typeof url === "string" && url.includes("remove-heart")) { return Promise.resolve(new Response(null, { status: 200 })); } return originalFetch.apply(this, args); }; } // 监听 pathname 变化 function watchPathname() { const originalPushState = history.pushState; let isLearning = false; history.pushState = function (state, title, url) { originalPushState.apply(history, arguments); if (url.startsWith("/lesson")) { isLearning = true; } else if (isLearning) { isLearning = false; checkHeartConsistency(); } }; } // 初始化 function init() { blockRemoveHeart(); watchPathname(); } init(); })();