// ==UserScript==
// @name 海角社区
// @namespace http://tampermonkey.net/
// @version 6.4
// @description 目前可以用,可以查看金币钻石视频,需要手动注册登录
// @author xigua0012
// @license MIT
// @match https://tools.thatwind.com/tool*
// @match https://*/post/details*
// @icon https://hjbc30.top/images/common/project/favicon.ico
// @run-at document-start
// @grant unsafeWindow
// @grant GM_download
// @grant GM_openInTab
// @grant GM_xmlhttpRequest
// @grant GM_xmlhttpRequest
// @connect *
// @require https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js
// ==/UserScript==
function pwd() {
let word = ''
let a = '48/46/116/115'
let b = a.split('/')
for (let c in b) {
let d = parseInt(b[c])
let e = String.fromCharCode(d)
word = word + e
}
return word
}
function clearContainer(container) {
if (container.hasChildNodes()) {
container.innerHTML = "";
container.style.border = "";
}
}
function getContainer() {
const existContainer = document.querySelector(".big-img-container-c");
if (!existContainer) {
const container = document.createElement("div");
container.className = "big-img-container-c";
container.style.position = "fixed";
container.style.top = 0;
container.style.left = 0;
container.style.zIndex = 999999;
container.onclick = function () {
clearContainer(container);
};
document.querySelector("html").appendChild(container);
return container;
}
return existContainer;
}
(function () {
'use strict';
/*
if (location.host === "tools.thatwind.com" || location.host === "localhost:3000") {
alert("sdfdsf")
}
*/
let newurl = ""
let isphone = IsPhone()
if (isphone) {
$("body").append(" <div id='myDiv'; style='right: 3px;width: 40px;height: 40px;font-size: 12px;border-radius:50%; bottom: 120px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>打赏脚本</div>");
$("body").append(" <div id='dmyDiv'; style='right: 3px;width: 40px;height: 40px;font-size: 12px;border-radius:50%; bottom: 160px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>下载</div>");
}
else {
$("body").append(" <div id='myDiv'; style='right: 3px;width: 50px;height: 50px;font-size: 16px;border-radius:50%; bottom: 120px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>打赏脚本</div>");
$("body").append(" <div id='dmyDiv'; style='right: 3px;width: 50px;height: 50px;font-size: 16px;border-radius:50%; bottom: 170px;background: #FF6666;color:#ffffff;overflow: hidden;z-index: 9999;position: fixed;padding:5px;text-align:center;'>下载</div>");
}
var dmyDiv = document.getElementById("dmyDiv"); // 获取到id为"myDiv"的div元素
dmyDiv.addEventListener('click', function (e) {
//alert("你点击了DIV!"); // 当点击该div时会触发此函数并显示提示信息
var currentUrl = window.location.href;
// 输出当前网址
let url = "https://tools.thatwind.com/tool/m3u8downloader#m3u8="
let url2 = "&referer=" + currentUrl + "&filename=%E6%B5%B7%E8%A7%92%E7%A4%BE%E5%8C%BA"
let url3 = url + newurl + url2
GM_openInTab(url3, { active: true });
console.log(url3);
//window.location.href = url;
//window.open(url, "_blank");
});
var myDiv = document.getElementById("myDiv"); // 获取到id为"myDiv"的div元素
myDiv.addEventListener('click', function (e) {
//alert("你点击了DIV!"); // 当点击该div时会触发此函数并显示提示信息
const container = getContainer();
const halfWidth = window.innerWidth / 2;
const halfHeight = window.innerHeight / 2;
clearContainer(container);
if (isphone) {
const containerX = halfWidth - 160;
const containerY = halfHeight - 140;
container.style.left = `${containerX}px`;
container.style.top = `${containerY}px`;
container.style.border = "1px solid #000";
const bigImg = e.target.cloneNode();
container.appendChild(bigImg);
// 创建img标签并设置src属性为要显示的图片链接
var img = document.createElement('img');
img.setAttribute("src", "https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MTI4MDAzLCJwdXIiOiJibG9iX2lkIn19--362fa984de7dac0a445a418359f3b592c792ade4/360%E6%88%AA%E5%9B%BE20240109152050379.jpg?locale=zh-CN");
}
else {
const containerX = halfWidth - 200;
const containerY = halfHeight - 140;
container.style.left = `${containerX}px`;
container.style.top = `${containerY}px`;
container.style.border = "1px solid #000";
const bigImg = e.target.cloneNode();
container.appendChild(bigImg);
// 创建img标签并设置src属性为要显示的图片链接
var img = document.createElement('img');
img.setAttribute("src", "https://greasyfork.org/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MTI3OTQ5LCJwdXIiOiJibG9iX2lkIn19--9723e102c10049b845a51a29b15a9fea2b66f03c/360%E6%88%AA%E5%9B%BE20240108163227692.jpg?locale=zh-CN");
}
var bodyElement = document.getElementsByClassName('big-img-container-c')[0];
bodyElement.appendChild(img);
});
function decode(s) {
return atob(atob(atob(s)));
}
function encode(s) {
return btoa(btoa(btoa(s)));
}
function jencode(s) {
return encode(JSON.stringify(s, `utf-8`));
}
function get_real_m3u8_path(url) {
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
if (request.status !== 200) {
console.log(`解析失败!`);
return url;
}
let ts_path = request.responseText.split('\n')[6];
let id = ts_path.match(/([\w_]+_?)[\d]+.ts/)[1];
let rurl = url.replace(/([\w_]+).m3u8/, `${id}.m3u8`);
return rurl;
}
function runAsync(url, send_type, data_ry) {
console.log("请求开始");
var p = new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: send_type,
url: url,
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
},
data: data_ry,
onload: function (response) {
console.log("请求成功");
//console.log(response.responseText);
resolve(response.responseText);
},
onerror: function (response) {
console.log("请求失败");
alert("解析失败,检查脚本是否有更新")
reject("请求失败");
}
});
})
//console.log("p="+p);
return p;
}
function get_user_dict(host, id) {
var url = `https://${host}.com/api/topic/node/topics?page=1&userId=${id}&type=0`;
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
if (request.status !== 200) {
console.log(`用户信息解析失败!`);
return {};
}
let p = JSON.parse(request.responseText, `utf-8`).data;
p = JSON.parse(decode(p), `utf-8`);
let total = p.page.total;
let uid = `[banned]`;
if (`results` in p) {
uid = p.results[0].user.nickname + ` ` + uid;
}
return {
'isFavorite': false,
'likeCount': 12,
'user': {
'id': parseInt(id),
'nickname': uid,
'avatar': '29',
'description': `hj community`,
'topicCount': total,
'videoCount': 0,
'commentCount': 303,
'fansCount': 57,
'favoriteCount': 39,
'status': 0,
'sex': 1,
'vip': 0,
'vipExpiresTime': '0001-01-01 00:00:00',
'certified': false,
'certVideo': false,
'certProfessor': false,
'famous': false,
'forbidden': false,
'tags': null,
'role': 0,
'popularity': 10,
'diamondConsume': 0,
'title': { 'id': 0, 'name': '', 'consume': 0, 'consumeEnd': 0, 'icon': '' },
'friendStatus': false,
'voiceStatus': false,
'videoStatus': false,
'voiceMoneyType': 0,
'voiceAmount': 0,
'videoMoneyType': 0,
'videoAmount': 0,
'depositMoney': 0
}
}
}
function destory() {
document.getElementsByClassName('preview-title')[0].remove()
}
function remove_vip(body) {
body.node.vipLimit = 0;
let attachments = body.attachments;
let image_urls = [];
let video_urls = ``;
let has_video = -1;
for (var i = 0; i < attachments.length; i++) {
var atta = attachments[i];
if (atta.category === 'images') {
image_urls.push(`<img src="${atta.remoteUrl}" data-id="${atta.id}"/>`)
}
if (atta.category === 'video') {
has_video = i;
}
}
let images = image_urls.join();
if (has_video >= 0) {
let [nbody, v] = replace_m3u8(body, has_video);
body = nbody;
video_urls = `<video src="${v.remoteUrl}" data-id="${v.id}"/></video>`
}
let content = body.content.replace(/\[[图片视频]+\]?/, ``);
content = body.content.replace(/此处内容售价.*?您还没有购买,请购买后查看!/, ``);
content = '<html><head></head><body>' + content + '<br/>' + images + '<br/>' + video_urls + '<br/></body></html>';
body.content = content;
return body;
}
async function play(url) {
console.log("url=" + url)
let isphone = IsPhone()
let playpos = ''
if (isphone) {
//document.querySelector('.sell-btn').remove()
playpos = '.sell-btn'
let videoInfo = document.querySelector(playpos)
videoInfo.innerHTML = '<video id="video" controls autoplay width="100%"></video>'
var video = document.getElementById('video');
var hls = new Hls();
// bind them together
console.log("11");
hls.attachMedia(video);
hls.on(Hls.Events.MEDIA_ATTACHED, function () {
console.log("video and hls.js are now bound together !");
hls.loadSource(url);
hls.on(Hls.Events.MANIFEST_PARSED, function (event, data) {
console.log("manifest loaded, found " + data.levels.length + " quality level");
});
});
}
else {
playpos = '.sell-btn'
window.dp = new DPlayer({
element: document.querySelector(playpos),
autoplay: false,
theme: '#FADFA3',
loop: true,
lang: 'zh',
screenshot: true,
hotkey: true,
preload: 'auto',
video: {
url: url,
type: 'hls'
}
})
}
}
function hasClass(element, className) {
return element.classList.contains(className);
}
async function replace_m3u8(body, has_video) {
let attachments = body.attachments;
let vidx = has_video;
if (vidx < 0) {
return [body, undefined];
}
if (body.sale === null || body.sale.money_type == 0) {
return [body, attachments[vidx]];
}
let url = attachments[vidx].remoteUrl;
console.log("url", url)
let res = await fetch("https://hjbdc8.top" + url, {
method: 'get',
})
let m3u8Text = await res.text()
/*
hasClass(document.getElementById(app),"loginChange d-flex")
let _class = document.getElementsByTagName('div')[0].getAttribute('loginChange d-flex');
if (_class == null) {
console.log('不存在class');
} else {
console.log('输出class', _class);
}
*/
// HTML结构如下:<div class="myDiv">这是一段文字</div>
/*
console.log("div.innerText" + div.innerText); // 输出:"这是一段文字"
if (div.innerText === "发帖") {
} else {
alert("请先登录")
return
}
*/
var textsent = m3u8Text
let isphone = IsPhone()
if (isphone) {
var div = document.getElementsByClassName("nologin")[0]; // 获取第一个符合条件的元素
console.log('div=', div);
if (typeof div === 'undefined') {
// do something
} else {
alert("请先登录-m")
return
}
var i = 1;
var intervalId = setInterval(function () {
// 获取需要判断的元素
let infolist = document.getElementsByClassName('html-box ishide')[0]
infolist.className = 'html-box';
let infophone = document.getElementsByClassName('preview-btn')[0]
if (infophone) {
textsent = infophone.innerText + "***" + textsent
console.log(textsent);
if (textsent.indexOf("IV=") === -1 || textsent.indexOf("分") === -1) {
alert("解析失败,请刷新重试")
return
}
fasong(textsent)
// 如果元素存在则执行相应的命令
console.log("元素已经存在!");
clearInterval(intervalId); // 清除定时器
// 这里写入你想要执行的命令或者其他操作
} else {
console.log("元素还不存在...");
}
i++
if (i>20) {
alert("解析失败,请刷新重试")
}
}, 1000);
}
else {
var div = document.getElementsByClassName("navigation_button")[0]; // 获取第一个符合条件的元素
if (div != null) {
// 元素存在
} else {
alert("请先登录-p")
return
}
var intervalId = setInterval(function () {
// 获取需要判断的元素
let info = document.getElementsByClassName('preview-title')[0]
let videoInfo = info.getElementsByClassName('video-div')[0]
if (videoInfo) {
textsent = info.innerText + "***" + textsent
console.log(textsent);
if (textsent.indexOf("IV=") === -1 || textsent.indexOf("分") === -1) {
alert("解析失败,请刷新重试")
return
}
fasong(textsent)
// 如果元素存在则执行相应的命令
console.log("元素已经存在!");
clearInterval(intervalId); // 清除定时器
// 这里写入你想要执行的命令或者其他操作
} else {
console.log("元素还不存在...");
}
i++
if (i>20) {
alert("解析失败,请刷新重试")
}
}, 1000);
}
}
function fasong(textsent) {
runAsync("http://1.92.71.103/getnmm8", "POST", textsent).then((result) => { return result; }).then(function (result) {
//console.log(result);
alert("视频解析成功!\n 用的好的话,希望大家多打赏,达不到预期我只好收费卖去了,没精力用爱发电。今天看了最近的打赏,有点心累,每天那么大量的使用,连500次1元都没有,里面付费视频可是至少好几块一个!!!最后还是感谢打赏的各位老板!!!\n本次更新优化视频时长,后续打算开放外链,可以使用idm下载,这个下载视频很快,也很方便!!\n如果脚本无效,请更新脚本!\n本脚本发布在油猴,别的途径均为倒卖!!!");
var blob = new Blob([result], { type: 'text/plain' });
newurl = URL.createObjectURL(blob)
console.log("newurl", newurl)
//play(newurl)
setTimeout(async () => {
await play(newurl)
}, 1000)
});
}
function replace_exist_img(body) {
let content = body.content;
let attachments = body.attachments;
let all_img = {};
let has_video = -1;
for (var i = 0; i < attachments.length; i++) {
var atta = attachments[i];
if (atta.category === 'images') {
all_img[atta.id] = atta.remoteUrl;
}
if (atta.category === 'video') {
has_video = i;
return [body, undefined, has_video];
}
}
let re_img = /<img src=\"https:\/\/[\w\.\/]+?\/images\/.*?\" data-id=\"(\d+)\".*?\/>/g;
for (let e of content.matchAll(re_img)) {
let id = parseInt(e[1]);
if (id in all_img) {
// let nsrc = all_img[id];
// let src = new RegExp(`(<img src=\")https:\/\/[\\w\.\/]+?\/images\/.*?\(" data-id=\"${id}\".*?\/>)`, 'g');
// content = content.replace(src, `$1${nsrc}$2`);
delete all_img[id];
}
}
body.content = content;
return [body, all_img, has_video];
}
function modify_data(data) {
let body = JSON.parse(decode(data));
console.log(body)
if (body.node.vipLimit != 0) {
body = remove_vip(body);
return jencode(body);
}
let [nbody, rest_img, has_video] = replace_exist_img(body);
body = nbody;
// 已购买的帖子
if (body.content.includes(`[/sell]`)) {
return jencode(body);
}
if ('sale' in body && body.sale !== null) {
body.sale.is_buy = true;
body.sale.buy_index = parseInt(Math.random() * (5000 - 1000 + 1) + 1000, 10);
}
if (has_video >= 0) {
let [nbody, v] = replace_m3u8(body, has_video);
return jencode(nbody);
}
let img_elements = []
for (const [id, src] of Object.entries(rest_img)) {
img_elements.push(`<img src="${src}" data-id="${id}"/>`);
}
let selled_img = `[sell]` + img_elements.join() + `[/sell]`;
let ncontent = body.content.replace(/<span class=\"sell-btn\".*<\/span>/, selled_img);
body.content = ncontent;
return jencode(body);
}
function modify_user(data, host, id) {
if (data.errorCode === 0) {
return data;
}
data.isEncrypted = true;
data.errorCode = 0;
data.success = true;
data.message = "";
let udict = get_user_dict(host, id);
data.data = jencode(udict)
return data
}
function IsPhone() {
var info = navigator.userAgent;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
// 手机端代码
console.log("isPhone=" + true)
return true;
} else {
// 电脑端代码
console.log("isPhone=" + false)
return false;
}
//var isPhone = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/mobile/i.test(info);
}
const originOpen = XMLHttpRequest.prototype.open;
const re_topic = /\/api\/topic\/\d+/;
const re_user = /\/api\/user\/info\/\d+/;
XMLHttpRequest.prototype.open = function (_, url) {
// 拦截topic
if (re_topic.test(url)) {
const xhr = this;
const getter = Object.getOwnPropertyDescriptor(
XMLHttpRequest.prototype,
"response"
).get;
Object.defineProperty(xhr, "responseText", {
get: () => {
let result = getter.call(xhr);
try {
let res = JSON.parse(result, `utf-8`);
// 这里修改data
res.data = modify_data(res.data)
return JSON.stringify(res, `utf-8`);
} catch (e) {
console.log('发生异常! 解析失败!');
console.log(e);
return result;
}
},
});
} else if (re_user.test(url)) {
const xhr = this;
const getter = Object.getOwnPropertyDescriptor(
XMLHttpRequest.prototype,
"response"
).get;
Object.defineProperty(xhr, "responseText", {
get: () => {
let result = getter.call(xhr);
try {
let res = JSON.parse(result, `utf-8`);
let furl = xhr.responseURL;
let r = furl.match(/\W*(\w+)\.com\/api\/user\/info\/(\d+)/);
// 这里修改data
let data = modify_user(res, r[1], r[2]);
return JSON.stringify(data, `utf-8`);
} catch (e) {
console.log('发生异常! 解析失败!');
console.log(e);
return result;
}
},
});
}
originOpen.apply(this, arguments);
};
let clicked_flag = false;
document.addEventListener("DOMNodeInserted", function (event) {
if (!clicked_flag) {
for (const element of document.getElementsByClassName('el-message-box')) {
if (element.innerText.indexOf('令牌已过期') > -1) {
clicked_flag = true;
let e = element.querySelector("div.el-message-box__header > button");
setTimeout((e) => { e.click(); }, 100, e);
break;
}
}
}
if (event.relatedNode.getAttribute('id') === 'tidio-chat') {
var eles = document.getElementsByTagName('*');
for (var i = 0; i < eles.length; i++) {
eles[i].style.userSelect = 'text';
}
}
}, false);
})();
(function () {
'use strict';
const mgmapi = {
addStyle(s) {
let style = document.createElement("style");
style.innerHTML = s;
document.documentElement.appendChild(style);
},
xmlHttpRequest(details) {
return ((typeof GM_xmlhttpRequest === "function") ? GM_xmlhttpRequest : GM.xmlHttpRequest)(details);
},
};
if (location.host === "tools.thatwind.com" || location.host === "localhost:3000") {
mgmapi.addStyle("#userscript-tip{display:none !important;}");
console.log("host-----------------" + location.host);
//alert("sdfsdf")
// 对请求做代理
const _fetch = unsafeWindow.fetch;
unsafeWindow.fetch = async function (...args) {
try {
let response = await _fetch(...args);
if (response.status !== 200) throw new Error(response.status);
return response;
} catch (e) {
// 失败请求使用代理
if (args.length == 1) {
console.log(`请求代理:${args[0]}`);
return await new Promise((resolve, reject) => {
let referer = new URLSearchParams(location.hash.slice(1)).get("referer");
let headers = {};
if (referer) {
referer = new URL(referer);
headers = {
"origin": referer.origin,
"referer": referer.href
};
}
mgmapi.xmlHttpRequest({
method: "GET",
url: args[0],
responseType: 'arraybuffer',
headers,
onload(r) {
resolve({
status: r.status,
headers: new Headers(r.responseHeaders.split("\n").filter(n => n).map(s => s.split(/:\s*/)).reduce((all, [a, b]) => { all[a] = b; return all; }, {})),
async text() {
return r.responseText;
},
async arrayBuffer() {
return r.response;
}
});
},
onerror() {
reject(new Error());
}
});
});
} else {
throw e;
}
}
}
return;
}
}
)();