// ==UserScript== // @name m3u8-downloader // @namespace https://github.com/Momo707577045/m3u8-downloader // @version 0.10.1 // @description https://github.com/Momo707577045/m3u8-downloader 配套插件 // @author Momo707577045 // @include * // @exclude http://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html // @exclude https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html // @exclude https://www.bilibili.com/* // @downloadURL https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/m3u8-downloader.user.js // @updateURL https://blog.luckly-mjw.cn/tool-show/m3u8-downloader/m3u8-downloader.user.js // @grant none // @run-at document-start // ==/UserScript== (function () { 'use strict'; var showMp4 = true var m3u8Target = '' var mp4Objs = [] var originXHR = window.XMLHttpRequest var windowOpen = window.open function ajax(options) { options = options || {}; let xhr = new originXHR(); if (options.type === 'file') { xhr.responseType = 'arraybuffer'; } xhr.onreadystatechange = function () { if (xhr.readyState === 4) { let status = xhr.status; if (status >= 200 && status < 300) { options.success && options.success(xhr.response); } else { options.fail && options.fail(status); } } }; xhr.open("GET", options.url, true); xhr.send(null); } // 普通下载 function downloadWithA(url, name) { const a = document.createElement('a') a.href = url a.download = name a.style.display = 'none' document.body.appendChild(a) a.click() a.remove() } // 检测 m3u8 链接的有效性 function checkM3u8Url(url) { ajax({ url, success: (fileStr) => { if (/(png|image|ts|jpg|mp4|jpeg|EXTINF)/.test(fileStr)) { appendDom() document.getElementById('m3u8-jump').style.display = 'block' document.getElementById('m3u8-close').style.display = 'block' document.getElementById('m3u8-append').style.display = 'block' const urlObj = new URL(url) urlObj.searchParams.append('title', getTitle()) m3u8Target = urlObj.href console.log('【m3u8】----------------------------------------') console.log(urlObj) console.log('http://blog.luckly-mjw.cn/tool-show/m3u8-downloader/index.html?source=' + m3u8Target) } } }) } // 定时器,检查 mp4 视频资源 function checkVideo() { let $videoList = document.getElementsByTagName('video') for (let i = 0, length = $videoList.length; i < length; i++) { const url = $videoList[i].currentSrc if (url.indexOf('.mp4') > 0 && !mp4Objs.find(mp4 => mp4.url === url)) { appendDom(); document.getElementById('mp4-show').style.display = 'block' mp4Objs.push({ url, fileName: url.slice(url.lastIndexOf('/') + 1).split('?')[0], }); } } setTimeout(checkVideo, 3000); } function resetAjax() { if (window._hadResetAjax) { // 如果已经重置过,则不再进入。解决开发时局部刷新导致重新加载问题 return } window._hadResetAjax = true var originOpen = originXHR.prototype.open window.XMLHttpRequest = function () { var realXHR = new originXHR() realXHR.open = function (method, url) { url.toString() && url.toString().indexOf('.m3u8') > 0 && checkM3u8Url(url.toString()) // if (url.toString() && url.toString().toLocaleLowerCase().indexOf('.mp4') > 0) { // appendDom(); // document.getElementById('mp4-show').style.display = 'block' // mp4Objs.push({ // url, // fileName: url.slice(url.lastIndexOf('/') + 1).split('?')[0], // }); // } originOpen.call(realXHR, method, url) } return realXHR } window.XMLHttpRequest.UNSENT = originXHR.UNSENT; window.XMLHttpRequest.OPENED = originXHR.OPENED; window.XMLHttpRequest.HEADERS_RECEIVED = originXHR.HEADERS_RECEIVED; window.XMLHttpRequest.LOADING = originXHR.LOADING; window.XMLHttpRequest.DONE = originXHR.DONE; window.XMLHttpRequest.prototype = originXHR.prototype; } // 获取顶部 window title,因可能存在跨域问题,故使用 try catch 进行保护 function getTitle() { let title = document.title; try { title = window.top.document.title } catch (error) { console.log(error) } return title } function appendDom() { if (document.getElementById('m3u8-download-dom')) { return } var domStr = `