// ==UserScript==
// @name 查看Luogu中的文章、剪贴板、个人介绍
// @namespace http://tampermonkey.net/
// @version 0.2.5
// @description 查看Luogu中的文章、剪贴板、个人介绍
// @author Andy_hpy
// @match *://www.luogu.com.cn/*
// @match *://luogu.com.cn/*
// @grant GM_xmlhttpRequest
// @grant GM_cookie
// @grant GM_addStyle
// @grant GM_getResourceText
// @resource sweetalert2css https://cdn.jsdelivr.net/npm/sweetalert2@11.26.25/dist/sweetalert2.min.css
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11.26.25/dist/sweetalert2.min.js
// @require https://cdn.jsdelivr.net/npm/luogu-renderer@latest/dist/luogu-new-renderer.iife.min.js
// @run-at document-start
// @connect api.luogu.me
// @connect .luogu.com.cn
// @connect .luogu.com
// @license AGPL-3.0
// ==/UserScript==
async function pastePage() {
const addbtn = setInterval(async function () {
if (document.querySelector('div.card.padding-default > div.content-card-top') &&
!document.querySelector('button#update-btn')) {
if (document.querySelector('div.card.padding-default > div.content-card-top > div.actions')) {
document.querySelector('div.card.padding-default > div.content-card-top > div.actions').insertAdjacentHTML('beforeend', `
`);
} else {
document.querySelector('div.card.padding-default > div.content-card-top').insertAdjacentHTML('beforeend', `
`);
}
clearInterval(addbtn);
}
}, 500);
const override = setInterval(async function () {
if (document.querySelector('body > div')) {
clearInterval(override);
document.querySelector('body > div').style.visibility = 'hidden';
}
}, 10);
const id = location.href.split('/').pop();
const [pasteInfo, data] = await Promise.all([
getDataOnLuoguMe(`https://api.luogu.me/paste/query/${id}`),
fetchFeInjection(`https://www.luogu.com.cn/paste/`)
]);
if (pasteInfo.code === 404) {
const wait = setInterval(async function () {
if (document.querySelector('html')) {
clearInterval(wait);
if (document.querySelector('body > div > div.card > pre#url')) {
Swal.fire({
title: '内容未找到',
text: '该内容尚未被保存站收录,是否立即保存?',
icon: 'warning',
showCancelButton: true,
confirmButtonText: '保存',
cancelButtonText: '返回',
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
allowEscapeKey: false,
allowOutsideClick: false
}).then(async (result) => {
if (result.isConfirmed) {
const response = await savePaste(id);
Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 1000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
}).fire({
icon: "success",
title: "更新请求已提交"
});
const workId = response.data.workflowId;
if (response.code === 200) {
const wait = setInterval(async () => {
if ((await getWorkflow(workId)).code === 200) {
clearInterval(wait);
Swal.fire({
title: '保存成功',
icon: 'success',
confirmButtonText: '确定'
}).then(() => {
location.reload()
});
}
}, 500);
} else {
Swal.fire({
title: '保存失败',
text: '保存失败,请稍后再试',
icon: 'error',
confirmButtonText: '确定'
}).then(() => {
document.querySelector('body > div').style.visibility = '';
});
}
} else if (result.dismiss === Swal.DismissReason.cancel) {
history.back();
}
});
} else {
document.querySelector('body > div').style.display = '';
}
}
}, 500);
return;
}
const info = pasteInfo.data;
async function init() {
data.currentTemplate = "PasteShow";
content = info.content;
}
const [authorInfo,] = await Promise.all([
getUserInfo(info.authorId),
init()
]);
data.currentData = {
paste: {
id: id,
user: {
uid: authorInfo.uid,
avatar: authorInfo.avatar,
name: authorInfo.name,
slogan: authorInfo.slogan,
badge: authorInfo.badge,
isAdmin: authorInfo.isAdmin,
isBanned: authorInfo.isBanned,
color: authorInfo.color,
ccfLevel: authorInfo.ccfLevel,
xcpcLevel: authorInfo.xcpcLevel,
background: authorInfo.background,
verified: true
},
time: Math.floor(new Date(info.createdAt).getTime() / 1000),
public: true,
data: content
},
canEdit: false
};
function write() {
document.open();
document.write(`
云剪贴板 - Luogu Spilopelia
`);
document.close();
}
const wait = setInterval(async function () {
if (document.querySelector('html')) {
if (document.querySelector('body > div > div.card > pre#url')) {
write();
} else {
document.querySelector('body > div').style.visibility = '';
}
clearInterval(wait);
}
}, 500);
setInterval(async function () {
if ((document.querySelector('div.card.padding-default > div.content-card-top') &&
!document.querySelector('button#update-btn')) || document.querySelector('button#update-btn').disabled) {
if (document.querySelector('button#update-btn')) {
document.querySelector('button#update-btn').disabled = false;
} else if (document.querySelector('div.card.padding-default > div.content-card-top > div.actions')) {
document.querySelector('div.card.padding-default > div.content-card-top > div.actions').insertAdjacentHTML('beforeend', `
`);
} else {
document.querySelector('div.card.padding-default > div.content-card-top').insertAdjacentHTML('beforeend', `
`);
}
const btn = document.querySelector('button#update-btn');
btn.addEventListener('mouseover', async function (e) {
btn.style.backgroundColor = 'rgba(239, 114, 4, 0.75)';
btn.style.borderColor = 'rgba(239, 114, 4, 0.75)';
});
btn.addEventListener('mouseout', async function (e) {
btn.style.backgroundColor = 'rgb(239, 114, 4)';
btn.style.borderColor = 'rgb(239, 114, 4)';
});
btn.addEventListener('click', async function (e) {
btn.disabled = true;
const response = await savePaste(id);
Swal.mixin({
toast: true,
position: "top-end",
showConfirmButton: false,
timer: 1000,
timerProgressBar: true,
didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer;
toast.onmouseleave = Swal.resumeTimer;
}
}).fire({
icon: "success",
title: "更新请求已提交"
});
const workId = response.data.workflowId;
if (response.code === 200) {
const wait = setInterval(async () => {
if ((await getWorkflow(workId)).code === 200) {
clearInterval(wait);
Swal.fire({
title: '更新成功',
icon: 'success',
confirmButtonText: '确定'
}).then(() => {
location.reload()
});
btn.disabled = false;
}
}, 500);
} else {
Swal.fire({
title: '更新失败',
text: '更新失败,请稍后再试',
icon: 'error',
confirmButtonText: '确定'
});
btn.disabled = false;
}
});
}
}, 500);
}
async function addcss() {
GM_addStyle(GM_getResourceText('sweetalert2css'));
}
async function getUserInfo(uid) {
const response = await fetch(`https://www.luogu.com.cn/api/user/info/${uid}`);
const data = await response.json();
return data.user;
}
async function getDataOnLuoguMe(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
responseType: 'json',
onload: function (response) {
resolve(response.response);
},
onerror: function (error) {
reject(error);
}
});
});
}
async function needWaitMain() {
if (/^http[s]?:\/\/(www\.)?luogu\.com\.cn\/user\/\d+[^\/]*[^\/]*$/.test(location.href)) {
if (!document.querySelector('main > div.main > div.sidebar-container.reverse > div.main > div.l-card:nth-child(3)')) {
let data = await getUserInfo(location.href.split('/').pop());
console.debug(data.introduction);
if (data.introduction === "") data.introduction = '这个人很懒,什么都没写';
data = await LuoguNewRenderer.render(data.introduction);
document.querySelector('main > div.main > div.sidebar-container.reverse > div.main').insertAdjacentHTML('beforeend', `
`);
}
}
}
async function fetchFeInjection(url) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: url,
onload: function (res) {
const match = res.responseText.match(
/window\._feInjection\s*=\s*JSON\.parse\(decodeURIComponent\("([^"]+)"\)\)/
);
if (match) {
resolve(JSON.parse(decodeURIComponent(match[1])));
} else {
reject(new Error('无法解析 _feInjection'));
}
},
onerror: reject
});
});
}
async function getWorkflow(id) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: `https://api.luogu.me/workflow/query/${id}`,
onload: function (response) {
resolve(JSON.parse(response.response));
},
onerror: reject
});
});
}
async function savePaste(id) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: 'https://api.luogu.me/workflow/create/template/paste-save-pipeline',
redirect: "follow",
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
targetId: id
}),
onload: function (response) {
resolve(JSON.parse(response.response));
},
onerror: function (error) {
reject(error);
}
});
});
}
async function notNeedWaitMain() {
if (/^http[s]?:\/\/(www\.)?luogu\.com\.cn\/paste\/[0-9a-zA-Z]{8}[^\/]*$/.test(location.href)) {
pastePage();
}
}
notNeedWaitMain();
addcss();
const wait = setInterval(async function () {
if (document.querySelector('html') && LuoguNewRenderer) {
needWaitMain();
clearInterval(wait);
}
}, 500);