您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
You can easily remove unwanted plays from your listening history
// ==UserScript== // @name LastFM: History Cleanup // @name:ru LastFM: Очистка истории // @description You can easily remove unwanted plays from your listening history // @description:ru Позволяет легко удалять нежелательные воспроизведения из истории прослушивания // @namespace lastfm-chartlist-cleanup // @version 0.1.1 // @license WTFPL // @author askornot // @match https://www.last.fm/*/user/* // @grant unsafeWindow // @homepageURL https://greasyfork.org/ru/scripts/479773-lastfm-history-cleanup/ // @supportURL https://greasyfork.org/ru/scripts/479773-lastfm-history-cleanup/feedback // @compatible chrome Violentmonkey 2.16.0 // @compatible firefox Violentmonkey 2.16.0 // @compatible firefox Greasemonkey 4.11 // ==/UserScript== !(function (W, D) { 'use strict'; const clone = function (row) { const love = row.querySelector('.chartlist-loved div'); const remove = row.querySelector('li:nth-child(7) form'); if (love === null || remove === null) return; const a = love.cloneNode(true); const b = remove.cloneNode(true); const text = b.lastElementChild.textContent; if (text) { b.lastElementChild.title = text.trim(); b.lastElementChild.textContent = ''; } while (a.attributes.length > 0) { a.removeAttribute(a.attributes[0].name); } b.lastElementChild.style.background = 'transparent'; a.replaceChild(b, a.lastElementChild); row.insertBefore(a, row.lastElementChild); }; const content = { 'text/html; charset=utf-8': function (id, fn) { return Object.assign(D.createElement('script'), { id: id, textContent: `document.querySelectorAll('.chartlist-row') .forEach(Function('row', \`return ${fn.toString()}\`)()); document.scripts.namedItem(${id}).remove();`, }).outerHTML; }, }; const responseText = Object.getOwnPropertyDescriptor( XMLHttpRequest.prototype, 'responseText', ); Object.defineProperty(W.XMLHttpRequest.prototype, 'responseText', { get() { const res = responseText.get.apply(this, arguments); if (this.readyState === XMLHttpRequest.DONE) { const type = this.getResponseHeader('content-type'); if (type === null) return res; const fn = content[type]; if (fn) return res + fn(Math.random(), clone); } return res; }, }); D.querySelectorAll('.chartlist-row').forEach(clone); })(unsafeWindow || window, document);