// ==UserScript==
// @name 海角视频
// @namespace http://tampermonkey.net/
// @version 2.0.0
// @description 目前可以浏览海角社区需要付费的VIP视频
// @author yota
// @license MIT
// @match https://tools.thatwind.com/tool*
// @match https://*/post/details*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @run-at document-start
// @grant unsafeWindow
// @grant GM_download
// @grant GM_openInTab
// @grant GM_xmlhttpRequest
// @connect *
// @require https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.6.0.min.js
// ==/UserScript==
var parseHost = "http://185.217.108.170:9001";
var testHost = "http://localhost:8080";
var isDev = false;
function getParseHost() {
if (isDev) {
return testHost;
} else {
return parseHost;
}
}
function appendBtnByAsia() {
$("body").append(
" <div id='parseBtnByAsia'; style='right: 15px;width: 60px;height: 40px;font-size: 15px;border-radius:5%; bottom: 400px;background: #056B00;color:#ffffff;overflow: hidden;z-index: 2000;position: fixed;padding:5px;text-align:center;'>解析视频</div>"
);
var parseBtn = document.getElementById("parseBtnByAsia"); // 解析按钮
parseBtn.addEventListener("click", function (e) {
setBtnText("正在解析...");
getParseText()
.then((result) => {
if (!result) {
alert("没有需要解析的视频");
return "";
}
let data = {
url: btoa(window.location.href),
host: btoa(getHost()),
pid: getQueryString("pid"),
};
openTab(data, result);
console.log(result);
})
.finally(() => {
setBtnText("解析视频");
});
});
}
function setBtnText(text) {
var parseBtn = document.getElementById("parseBtnByAsia"); // 解析按钮
parseBtn.innerText = text;
}
function openTab(data, m3u8) {
let host = getParseHost();
let queryStr = objectToQueryString(data);
let copyOpen = window.open(`${host}/dplayer${queryStr}`, "_blank");
// 监听 message 的变化
window.addEventListener("message", (e) => {
if (e.origin === host) {
let postDataStr = e.data;
let postData = JSON.parse(postDataStr);
if ((postData.pid = data.pid)) {
data.m3u8 = m3u8;
let jsonStr = JSON.stringify(data);
let msg = copyOpen.postMessage(jsonStr, host); // 此时才给 B 传输信息
}
}
});
}
function objectToQueryString(obj) {
return (
"?" +
Object.keys(obj)
.map(
(key) => `${encodeURIComponent(key)}=${encodeURIComponent(obj[key])}`
)
.join("&")
);
}
function storeAndOpen(data) {
let largeData = JSON.stringify(data);
// 存储数据到IndexedDB
var openRequest = indexedDB.open("TempDataDB", 1);
openRequest.onupgradeneeded = function (e) {
var db = e.target.result;
var store = db.createObjectStore("data", { keyPath: "id" });
};
openRequest.onsuccess = function (e) {
var db = e.target.result;
var tx = db.transaction("data", "readwrite");
var store = tx.objectStore("data");
var request = store.add({ id: 1, data: largeData });
request.onsuccess = function (e) {
// 数据存储成功,可以打开新标签页了
// 打开一个新的标签页,并传递数据
window.open(`http://185.217.108.170:9001/?type = 001}`, "_blank");
};
};
openRequest.onerror = function (e) {
console.error("Database error:", e.target.errorCode);
};
}
var parseText = "";
async function getParseText() {
let prefix = getPrefix();
if (!prefix) {
return "";
}
let video = await getVideo();
if (!video) {
return;
}
let remoteUrl = video.remoteUrl;
let host = getHost();
let res = await fetch(host + remoteUrl, {
method: "get",
});
let m3u8 = await res.text();
console.log(m3u8);
parseText = prefix + "----" + m3u8;
return parseText;
}
function getPrefix() {
let pt = document.getElementsByClassName("preview-title")[0];
if (!pt) {
return "";
}
let vd = pt.getElementsByClassName("video-div")[0];
if (vd) {
let innerText = pt.innerText;
return innerText;
}
if (!vd) {
vd = pt.firstElementChild || pt.firstChild;
if (vd) {
let innerText = vd.innerText;
return innerText;
}
}
return "";
}
async function getVideo() {
let body = await getTopic();
let attachments = body.attachments;
if (!attachments || attachments.length <= 0) {
return;
}
var video;
for (let attachment of attachments) {
if (attachment.category == "video") {
video = attachment;
}
}
return video;
}
async function getTopic() {
let pid = getQueryString("pid");
let host = getHost();
let path = "/api/topic/" + pid;
let res = await fetch(host + path, {
method: "get",
});
let resultText = await res.text();
let jsonObj = JSON.parse(resultText, `utf-8`);
let data = jsonObj.data;
let body = JSON.parse(decode(data));
return body;
}
function decode(s) {
return atob(atob(atob(s)));
}
function getHost() {
var href = window.location.href;
let index = href.indexOf("/post/details"); // 找到逗号的索引
let host = href.substring(0, index); // 截取左边的字符串
return host;
}
function appendBtn() {
$("body").append(
" <div id='parseBtn'; style='right: 15px;width: 60px;height: 40px;font-size: 15px;border-radius:5%; bottom: 400px;background: #056B00;color:#ffffff;overflow: hidden;z-index: 2000;position: fixed;padding:5px;text-align:center;'>解析视频</div>"
);
var parseBtn = document.getElementById("parseBtn"); // 解析按钮
parseBtn.addEventListener("click", function (e) {
var pid = getQueryString("pid");
if (!pid) {
alert("没有可解析的资源");
return;
}
parseVideo(pid)
.then(
(result) => {
console.log(result);
if (!result || !result.endsWith("m3u8")) {
throw new Error("解析失败");
}
let url = `http://185.217.108.170:9001/#${result}`;
window.open(url, "_blank");
},
(reason) => {
alert(reason);
}
)
.catch((reason) => {
alert(reason);
});
});
}
function parseVideo(pid) {
var url = `http://www.djyun.icu/api/hjjx?id=${pid}`;
var p = new Promise((resolve, reject) => {
setTimeout(() => {
//异步请求
resolve(reqByCROS(url, "GET", null));
}, 10);
});
return p;
}
function reqByCROS(url, req_type, data) {
console.log("请求开始");
var p = new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: req_type,
url: url,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
},
data: data,
onload: function (response) {
console.log("解析成功");
let text = response.responseText;
resolve(text);
},
onerror: function (response) {
reject("请求失败");
},
});
});
return p;
}
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg); //获取url中"?"符后的字符串并正则匹配
var context = "";
if (r != null) context = r[2];
reg = null;
r = null;
return context == null || context == "" || context == "undefined"
? ""
: context;
}
(function () {
"use strict";
// appendBtn();
appendBtnByAsia();
})();