My Free MP3+

解锁MyFreeMP3的QQ音乐、酷狗音乐、酷我音乐,过广告拦截器检测

目前为 2022-12-02 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name My Free MP3+
  3. // @namespace http://tampermonkey.net/My Free MP3 Plus
  4. // @version 0.2.4
  5. // @description 解锁MyFreeMP3的QQ音乐、酷狗音乐、酷我音乐,过广告拦截器检测
  6. // @author PY-DNG
  7. // @match http*://tool.liumingye.cn/music_old/*
  8. // @match http*://tools.liumingye.cn/music_old/*
  9. // @connect 59.110.45.28
  10. // @connect kugou.com
  11. // @connect *
  12. // @grant GM_xmlhttpRequest
  13. // @run-at document-start
  14. // ==/UserScript==
  15.  
  16. (function() {
  17. 'use strict';
  18.  
  19. window.addEventListener('load', main_onload);
  20. main();
  21.  
  22. function main() {
  23. // 过网页自带的广告拦截器检测
  24. bypassAdkillerDetector();
  25. }
  26.  
  27. function main_onload() {
  28. // 解锁QQ音乐、酷狗音乐、酷我音乐
  29. unlockTencent();
  30.  
  31. // 下载全部采用页面内下载
  32. downloadInPage();
  33. }
  34.  
  35. // 解锁QQ音乐、酷狗音乐、酷我音乐函数
  36. function unlockTencent() {
  37. // 模拟双击
  38. const search_title = $('#search .home-title');
  39. const eDblclick = new Event('dblclick');
  40. search_title.dispatchEvent(eDblclick);
  41. // 去除双击事件
  42. const p = search_title.parentElement;
  43. const new_search_title = $CrE('div');
  44. new_search_title.className = search_title.className;
  45. new_search_title.innerHTML = search_title.innerHTML;
  46. p.removeChild(search_title);
  47. p.insertBefore(new_search_title, p.children[0]);
  48. }
  49.  
  50. // Hook掉下载按钮实现全部下载均采用页面内下载方式(重写下载逻辑)
  51. function downloadInPage() {
  52. document.body.addEventListener('click', onclick, {capture: true});
  53.  
  54. function onclick(e) {
  55. const elm = e.target;
  56. const parent = elm ? elm.parentElement : null;
  57. match(elm);
  58. match(parent);
  59.  
  60. function match(elm) {
  61. const tag = elm.tagName.toUpperCase();
  62. const clList = [...elm.classList];
  63. if (tag === 'A' && clList.includes('download') || clList.includes('pic_download')) {
  64. e.stopPropagation();
  65. e.preventDefault();;
  66. download(elm);
  67. }
  68. }
  69. }
  70.  
  71. function download(a) {
  72. const elm_data = a.parentElement.previousElementSibling;
  73. const url = elm_data.value;
  74. const name = $("#name").value;
  75. const pop_id = pop.download(name, 'download');
  76. GM_xmlhttpRequest({
  77. method: 'GET',
  78. url: url,
  79. responseType: 'blob',
  80. onprogress: function(e) {
  81. e.lengthComputable /*&& c*/ && (pop.size(pop_id, bytesToSize(e.loaded) + " / " + bytesToSize(e.total)),
  82. pop.percent(pop_id, 100 * (e.loaded / e.total) >> 0))
  83. },
  84. onerror: function(e) {
  85. console.log(e);
  86. window.open(url);
  87. },
  88. onload: function(response) {
  89. const blob = response.response;
  90. const dataUrl = URL.createObjectURL(blob);
  91. const ext = getExtname(elm_data.id, blob.type.split(';')[0]);
  92. saveFile(dataUrl, `${name}.${ext}`);
  93. setTimeout(URL.revokeObjectURL.bind(URL, dataUrl), 1000);
  94. pop.finished(pop_id);
  95. setTimeout(pop.close.bind(pop, pop_id), 2000);
  96. }
  97. });
  98.  
  99. function getExtname(...args) {
  100. const map = {
  101. url_dsd: "flac",
  102. url_flac: "flac",
  103. url_ape: "ape",
  104. url_320: "mp3",
  105. url_128: "mp3",
  106. url_m4a: "m4a",
  107. url_lrc: "lrc",
  108. 'image/png': 'png',
  109. 'image/jpg': 'jpg',
  110. 'image/gif': 'gif',
  111. 'image/bmp': 'bmp',
  112. 'image/jpeg': 'jpeg',
  113. 'image/webp': 'webp',
  114. 'image/tiff': 'tiff',
  115. 'image/vnd.microsoft.icon': 'ico',
  116. };
  117. return map[args.find(a => map[a])];
  118. }
  119.  
  120. function bytesToSize(a) {
  121. if (0 === a)
  122. return "0 B";
  123. var b = 1024
  124. , c = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
  125. , d = Math.floor(Math.log(a) / Math.log(b));
  126. return (a / Math.pow(b, d)).toFixed(2) + " " + c[d]
  127. }
  128. }
  129. }
  130.  
  131. // 过广告拦截器检测
  132. function bypassAdkillerDetector() {
  133. /*
  134. // 拦截广告拦截检测器的setTimeout延迟启动器
  135. // 优点:不用考虑#music_tool是否存在,不用反复执行;缺点:需要在setTimeout启动器注册(不可用)前执行,如果脚本加载缓慢,就来不及了
  136. const setTimeout = unsafeWindow.setTimeout;
  137. unsafeWindow.setTimeout = function(func, time) {
  138. if (func && func.toString().includes('$("#music_tool").html()')) {
  139. func = function() {};
  140. }
  141. setTimeout.call(this, func, time);
  142. }
  143. */
  144. /*
  145. // 拦截广告拦截检测器的innerHTML检测
  146. // 优点:对浏览器API没有影响,对DOM影响极小,在检测前执行即可;缺点:需要#music_tool存在,需要反复检测执行,影响性能,稳定性差
  147. const bypasser = () => {
  148. const elm = $('#music_tool');
  149. elm && Object.defineProperty($('#music_tool'), 'innerHTML', {get: () => '<iframe></iframe>'});
  150. };
  151. setTimeout(bypasser, 2000);
  152. bypasser();
  153. */
  154. // 在页面添加干扰元素
  155. // 优点:对浏览器API没有影响,对DOM几乎没有影响,在检测前执行即可,不用考虑#music_tool是否存在,不用反复执行;缺点:可能影响广告功能(乐
  156. document.body.firstChild.insertAdjacentHTML('beforebegin', '<ins id="music_tool" style="display: none !important;">sometext</ins>');
  157. }
  158.  
  159. // Basic functions
  160. // querySelector
  161. function $() {
  162. switch(arguments.length) {
  163. case 2:
  164. return arguments[0].querySelector(arguments[1]);
  165. break;
  166. default:
  167. return document.querySelector(arguments[0]);
  168. }
  169. }
  170. // querySelectorAll
  171. function $All() {
  172. switch(arguments.length) {
  173. case 2:
  174. return arguments[0].querySelectorAll(arguments[1]);
  175. break;
  176. default:
  177. return document.querySelectorAll(arguments[0]);
  178. }
  179. }
  180. // createElement
  181. function $CrE() {
  182. switch(arguments.length) {
  183. case 2:
  184. return arguments[0].createElement(arguments[1]);
  185. break;
  186. default:
  187. return document.createElement(arguments[0]);
  188. }
  189. }
  190. // addEventListener
  191. function $AEL(...args) {
  192. const target = args.shift();
  193. target.addEventListener.apply(args);
  194. }
  195.  
  196. // Save dataURL to file
  197. function saveFile(dataURL, filename) {
  198. const a = $CrE('a');
  199. a.href = dataURL;
  200. a.download = filename;
  201. a.click();
  202. }
  203. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址