ow
This commit is contained in:
1 parent
ac0112b4a3
commit
90bb20e75f
24 files changed
+2722
No files matched your search
@@ -0,0 +1,144 @@
|
||||
// 资源嗅探脚本:在安装页面播放器脚本之前接管 fetch / XMLHttpRequest / createObjectURL,
|
||||
// 把真正被下载的媒体地址(mp4 / m3u8 等)回报给宿主程序,用于"下载视频"按钮。
|
||||
(function () {
|
||||
if (window.__mediaSniffInstalled) return;
|
||||
window.__mediaSniffInstalled = true;
|
||||
|
||||
window.__mediaUrls = [];
|
||||
window.__m3u8Blobs = [];
|
||||
|
||||
var MEDIA_EXT =
|
||||
/\.(mp4|flv|m3u8|mpd|mkv|mov|m4v|webm|f4v|3gp|mpg|mpeg|ts)(\?|#|$)/i;
|
||||
var PLAIN_EXT =
|
||||
/\.(jpg|jpeg|png|gif|webp|ico|svg|bmp|css|js|json|woff2?|ttf|map|txt)(\?|#|$)/i;
|
||||
|
||||
function isMediaUrl(u) {
|
||||
if (!u) return false;
|
||||
u = String(u);
|
||||
if (u.indexOf("blob:") === 0 || u.indexOf("data:") === 0) return false;
|
||||
if (PLAIN_EXT.test(u)) return false;
|
||||
return MEDIA_EXT.test(u) || /\/(video|vod|playback|media)[\/-]/i.test(u);
|
||||
}
|
||||
|
||||
function absUrl(u) {
|
||||
try {
|
||||
return new URL(String(u), location.href).href;
|
||||
} catch (e) {
|
||||
return String(u);
|
||||
}
|
||||
}
|
||||
|
||||
function post(msg) {
|
||||
try {
|
||||
if (
|
||||
window.chrome &&
|
||||
window.chrome.webview &&
|
||||
window.chrome.webview.postMessage
|
||||
) {
|
||||
window.chrome.webview.postMessage(JSON.stringify(msg));
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function remember(text) {
|
||||
if (!text || typeof text !== "string") return;
|
||||
if (text.indexOf("#EXTM3U") < 0) return;
|
||||
if (window.__m3u8Blobs.indexOf(text) >= 0) return;
|
||||
window.__m3u8Blobs.push(text);
|
||||
post({ type: "hlsText", text: text });
|
||||
}
|
||||
|
||||
function report(u) {
|
||||
try {
|
||||
var full = absUrl(u);
|
||||
if (!isMediaUrl(full)) return;
|
||||
if (window.__mediaUrls.indexOf(full) >= 0) return;
|
||||
window.__mediaUrls.push(full);
|
||||
// base 是发出这个请求的文档地址:播放器常在跨域 iframe 里,
|
||||
// 宿主必须用它当 Referer,用顶层页面地址会被防盗链判为非法来源
|
||||
post({ type: "media", url: full, base: location.href });
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
window.__reportMedia = report;
|
||||
window.__rememberHlsText = remember;
|
||||
|
||||
// 抖音等站点会用 atob(base64) 把播放地址还原出来,这里顺手抓一份解码结果
|
||||
try {
|
||||
var origAtob = window.atob;
|
||||
if (origAtob) {
|
||||
window.atob = function (s) {
|
||||
var r = origAtob.apply(this, arguments);
|
||||
try {
|
||||
if (r && typeof r === "string") {
|
||||
if (r.indexOf("#EXTM3U") >= 0) remember(r);
|
||||
else if (isMediaUrl(r)) report(r);
|
||||
}
|
||||
} catch (e) {}
|
||||
return r;
|
||||
};
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
var origFetch = window.fetch;
|
||||
if (origFetch) {
|
||||
window.fetch = function (input, init) {
|
||||
try {
|
||||
var u =
|
||||
typeof input === "string" || input instanceof URL
|
||||
? input
|
||||
: input && input.url;
|
||||
if (u) report(u);
|
||||
} catch (e) {}
|
||||
return origFetch.apply(this, arguments);
|
||||
};
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
var xhrOpen = XMLHttpRequest.prototype.open;
|
||||
var xhrSend = XMLHttpRequest.prototype.send;
|
||||
XMLHttpRequest.prototype.open = function (method, u) {
|
||||
try {
|
||||
if (u) report(u);
|
||||
} catch (e) {}
|
||||
return xhrOpen.apply(this, arguments);
|
||||
};
|
||||
XMLHttpRequest.prototype.send = function () {
|
||||
var xhr = this;
|
||||
try {
|
||||
xhr.addEventListener("load", function () {
|
||||
try {
|
||||
if (xhr.responseType === "" || xhr.responseType === "text") {
|
||||
remember(xhr.responseText);
|
||||
} else if (
|
||||
xhr.responseType === "blob" &&
|
||||
xhr.response &&
|
||||
xhr.response.text
|
||||
) {
|
||||
xhr.response.text().then(remember);
|
||||
}
|
||||
} catch (e) {}
|
||||
});
|
||||
} catch (e) {}
|
||||
return xhrSend.apply(this, arguments);
|
||||
};
|
||||
} catch (e) {}
|
||||
|
||||
// MSE 播放时 video.src 只能是 blob:,抓不到 http 地址,所以靠上面的分片嗅探兜底;
|
||||
// 这里额外记录 createObjectURL 的调用,方便识别"确实在用 MSE"。
|
||||
try {
|
||||
var ocu = window.URL && window.URL.createObjectURL;
|
||||
if (ocu) {
|
||||
window.URL.createObjectURL = function (obj) {
|
||||
var u = ocu.apply(this, arguments);
|
||||
try {
|
||||
window.__usesMse = true;
|
||||
if (obj && typeof obj.text === "function") obj.text().then(remember);
|
||||
} catch (e) {}
|
||||
return u;
|
||||
};
|
||||
}
|
||||
} catch (e) {}
|
||||
})();
|
||||
Reference in new issue
Block a user