- // ==UserScript==
- // @name My Free MP3+
- // @namespace http://tampermonkey.net/My Free MP3 Plus
- // @version 0.2.4
- // @description 解锁MyFreeMP3的QQ音乐、酷狗音乐、酷我音乐,过广告拦截器检测
- // @author PY-DNG
- // @match http*://tool.liumingye.cn/music_old/*
- // @match http*://tools.liumingye.cn/music_old/*
- // @connect 59.110.45.28
- // @connect kugou.com
- // @connect *
- // @grant GM_xmlhttpRequest
- // @run-at document-start
- // ==/UserScript==
-
- (function() {
- 'use strict';
-
- window.addEventListener('load', main_onload);
- main();
-
- function main() {
- // 过网页自带的广告拦截器检测
- bypassAdkillerDetector();
- }
-
- function main_onload() {
- // 解锁QQ音乐、酷狗音乐、酷我音乐
- unlockTencent();
-
- // 下载全部采用页面内下载
- downloadInPage();
- }
-
- // 解锁QQ音乐、酷狗音乐、酷我音乐函数
- function unlockTencent() {
- // 模拟双击
- const search_title = $('#search .home-title');
- const eDblclick = new Event('dblclick');
- search_title.dispatchEvent(eDblclick);
- // 去除双击事件
- const p = search_title.parentElement;
- const new_search_title = $CrE('div');
- new_search_title.className = search_title.className;
- new_search_title.innerHTML = search_title.innerHTML;
- p.removeChild(search_title);
- p.insertBefore(new_search_title, p.children[0]);
- }
-
- // Hook掉下载按钮实现全部下载均采用页面内下载方式(重写下载逻辑)
- function downloadInPage() {
- document.body.addEventListener('click', onclick, {capture: true});
-
- function onclick(e) {
- const elm = e.target;
- const parent = elm ? elm.parentElement : null;
- match(elm);
- match(parent);
-
- function match(elm) {
- const tag = elm.tagName.toUpperCase();
- const clList = [...elm.classList];
- if (tag === 'A' && clList.includes('download') || clList.includes('pic_download')) {
- e.stopPropagation();
- e.preventDefault();;
- download(elm);
- }
- }
- }
-
- function download(a) {
- const elm_data = a.parentElement.previousElementSibling;
- const url = elm_data.value;
- const name = $("#name").value;
- const pop_id = pop.download(name, 'download');
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- responseType: 'blob',
- onprogress: function(e) {
- e.lengthComputable /*&& c*/ && (pop.size(pop_id, bytesToSize(e.loaded) + " / " + bytesToSize(e.total)),
- pop.percent(pop_id, 100 * (e.loaded / e.total) >> 0))
- },
- onerror: function(e) {
- console.log(e);
- window.open(url);
- },
- onload: function(response) {
- const blob = response.response;
- const dataUrl = URL.createObjectURL(blob);
- const ext = getExtname(elm_data.id, blob.type.split(';')[0]);
- saveFile(dataUrl, `${name}.${ext}`);
- setTimeout(URL.revokeObjectURL.bind(URL, dataUrl), 1000);
- pop.finished(pop_id);
- setTimeout(pop.close.bind(pop, pop_id), 2000);
- }
- });
-
- function getExtname(...args) {
- const map = {
- url_dsd: "flac",
- url_flac: "flac",
- url_ape: "ape",
- url_320: "mp3",
- url_128: "mp3",
- url_m4a: "m4a",
- url_lrc: "lrc",
- 'image/png': 'png',
- 'image/jpg': 'jpg',
- 'image/gif': 'gif',
- 'image/bmp': 'bmp',
- 'image/jpeg': 'jpeg',
- 'image/webp': 'webp',
- 'image/tiff': 'tiff',
- 'image/vnd.microsoft.icon': 'ico',
- };
- return map[args.find(a => map[a])];
- }
-
- function bytesToSize(a) {
- if (0 === a)
- return "0 B";
- var b = 1024
- , c = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
- , d = Math.floor(Math.log(a) / Math.log(b));
- return (a / Math.pow(b, d)).toFixed(2) + " " + c[d]
- }
- }
- }
-
- // 过广告拦截器检测
- function bypassAdkillerDetector() {
- /*
- // 拦截广告拦截检测器的setTimeout延迟启动器
- // 优点:不用考虑#music_tool是否存在,不用反复执行;缺点:需要在setTimeout启动器注册(不可用)前执行,如果脚本加载缓慢,就来不及了
- const setTimeout = unsafeWindow.setTimeout;
- unsafeWindow.setTimeout = function(func, time) {
- if (func && func.toString().includes('$("#music_tool").html()')) {
- func = function() {};
- }
- setTimeout.call(this, func, time);
- }
- */
- /*
- // 拦截广告拦截检测器的innerHTML检测
- // 优点:对浏览器API没有影响,对DOM影响极小,在检测前执行即可;缺点:需要#music_tool存在,需要反复检测执行,影响性能,稳定性差
- const bypasser = () => {
- const elm = $('#music_tool');
- elm && Object.defineProperty($('#music_tool'), 'innerHTML', {get: () => '<iframe></iframe>'});
- };
- setTimeout(bypasser, 2000);
- bypasser();
- */
- // 在页面添加干扰元素
- // 优点:对浏览器API没有影响,对DOM几乎没有影响,在检测前执行即可,不用考虑#music_tool是否存在,不用反复执行;缺点:可能影响广告功能(乐
- document.body.firstChild.insertAdjacentHTML('beforebegin', '<ins id="music_tool" style="display: none !important;">sometext</ins>');
- }
-
- // Basic functions
- // querySelector
- function $() {
- switch(arguments.length) {
- case 2:
- return arguments[0].querySelector(arguments[1]);
- break;
- default:
- return document.querySelector(arguments[0]);
- }
- }
- // querySelectorAll
- function $All() {
- switch(arguments.length) {
- case 2:
- return arguments[0].querySelectorAll(arguments[1]);
- break;
- default:
- return document.querySelectorAll(arguments[0]);
- }
- }
- // createElement
- function $CrE() {
- switch(arguments.length) {
- case 2:
- return arguments[0].createElement(arguments[1]);
- break;
- default:
- return document.createElement(arguments[0]);
- }
- }
- // addEventListener
- function $AEL(...args) {
- const target = args.shift();
- target.addEventListener.apply(args);
- }
-
- // Save dataURL to file
- function saveFile(dataURL, filename) {
- const a = $CrE('a');
- a.href = dataURL;
- a.download = filename;
- a.click();
- }
- })();