// ==UserScript==
// @name 复制/清除/推送页面Cookies到青龙面板
// @version 3.10
// @description 提供清除、复制Cookies以及推送到青龙面板的功能,首次使用需进行测试和配置
// @author 翼城
// @match *://*/*
// @run-at document-end
// @grant GM_registerMenuCommand
// @grant GM_unregisterMenuCommand
// @grant GM_setClipboard
// @grant GM_xmlhttpRequest
// @grant GM_cookie
// @namespace
// @license MIT
// @namespace
// @namespace
// @namespace
// ==/UserScript==
(function () {
"use strict";
let URL_HOST = localStorage.getItem("PANEL_URL_HOST") || "";
let Client_ID = localStorage.getItem("PANEL_Client_ID") || "";
let Client_Secret = localStorage.getItem("PANEL_Client_Secret") || "";
let isTested = localStorage.getItem("isTested") === "true";
let domain = window.location.hostname;
async function clearCookies() {
if (domain.split(".").length > 2) {
domain = "." + domain.split(".").slice(-2).join(".");
}
const cookieNames = document.cookie.match(/[^ =;]+(?=\=)/g) || [];
cookieNames.forEach((cookieName) => {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=${domain}`;
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=`;
});
}
async function clearAllCookies() {
await clearCookies();
alert("所有Cookie已被清除。");
}
async function copyCookiesToClipboard() {
const cookies = document.cookie;
GM_setClipboard(cookies);
alert("Cookie已复制到剪贴板。");
}
async function testConnectionToPanel() {
if (isTested) {
if (confirm("配置已通过测试,是否需要重置配置?")) {
resetPanelConfiguration();
} else {
return;
}
}
const configInput = prompt(
"请输入面板配置,格式为:(面板ip:端口|your_Client_ID|your_Client_Secret)",
`${URL_HOST}|${Client_ID}|${Client_Secret}`,
);
if (!configInput) {
alert("配置输入不能为空!");
return;
}
const configParts = configInput.split("|");
if (configParts.length !== 3) {
alert("输入格式不正确,请按格式:面板地址|Client_ID|Client_Secret");
return;
}
[URL_HOST, Client_ID, Client_Secret] = configParts;
try {
let rr = await GM_fetch({
method: "GET",
url: `${URL_HOST}/open/auth/token?client_id=${Client_ID}&client_secret=${Client_Secret}`,
headers: {
"content-type": "application/json",
},
});
if (rr.status === 200) {
let panel_token = JSON.parse(rr.responseText).data.token;
alert("面板连接成功,Token获取正常!");
localStorage.setItem("PANEL_URL_HOST", URL_HOST);
localStorage.setItem("PANEL_Client_ID", Client_ID);
localStorage.setItem("PANEL_Client_Secret", Client_Secret);
localStorage.setItem("isTested", "true");
isTested = true;
} else {
alert(`面板连接失败,状态码:${rr.status},错误信息:${rr.statusText}`);
}
} catch (error) {
alert("面板连接失败,请检查面板地址、Client_ID和Client_Secret是否正确!");
}
}
function resetPanelConfiguration() {
localStorage.removeItem("PANEL_URL_HOST");
localStorage.removeItem("PANEL_Client_ID");
localStorage.removeItem("PANEL_Client_Secret");
localStorage.removeItem("isTested");
URL_HOST = "";
Client_ID = "";
Client_Secret = "";
isTested = false;
alert("面板配置已重置,请重新进行配置!");
}
async function pushCookiesToPanel2() {
if (!isTested) {
alert("请先进行测试连接,以确保面板连接正常!");
return;
}
let ENV_NAME = prompt("请输入推送到面板的变量名", "COOKIES");
if (ENV_NAME === null) {
return;
}
if (!ENV_NAME) {
alert("变量名不能为空,请重新输入!");
return;
}
let collectedCookies = "";
let ready = setInterval(function () {
GM_cookie.list({}, function (cookies, error) {
if (!error) {
for (let i = 0; i < cookies.length; i++) {
collectedCookies += `${cookies[i].name}=${cookies[i].value};`;
}
if (collectedCookies !== "") {
clearInterval(ready);
getTokenAndPush(collectedCookies, ENV_NAME);
}
} else {
console.error("获取Cookie时出错:", error);
}
});
}, 1000);
}
async function getTokenAndPush(cookies, ENV_NAME) {
try {
let rr = await GM_fetch({
method: "GET",
url: `${URL_HOST}/open/auth/token?client_id=${Client_ID}&client_secret=${Client_Secret}`,
headers: {
"content-type": "application/json",
},
});
if (rr.status === 200) {
let panel_token = JSON.parse(rr.responseText).data.token;
let res = await GM_fetch({
method: "GET",
url: `${URL_HOST}/open/envs?searchValue=${ENV_NAME}`,
headers: {
"content-type": "application/json",
Authorization: `Bearer ${panel_token}`,
},
});
if (res.status === 200) {
let id = JSON.parse(res.responseText).data[0].id;
let ress = await GM_fetch({
method: "PUT",
url: `${URL_HOST}/open/envs`,
headers: {
"content-type": "application/json",
Authorization: `Bearer ${panel_token}`,
},
data: JSON.stringify({ id: id, name: ENV_NAME, value: cookies }),
});
if (ress.status === 200) {
alert("Cookie已成功推送到面板!");
} else {
alert(
`推送Cookie失败,状态码:${ress.status},错误信息:${ress.statusText}`,
);
console.error("推送Cookie失败:", ress);
}
} else {
alert(
`无法获取面板的环境变量列表,状态码:${res.status},错误信息:${res.statusText}`,
);
}
} else {
alert(
`无法获取面板Token,状态码:${rr.status},错误信息:${rr.statusText}`,
);
}
} catch (error) {
alert(
`大概率找不到变量名,确认青龙是否有。根据变量名自动创建功能,自己根据api写去吧!`,
);
}
}
async function splitAndSelectCookies() {
const cookies = document.cookie.split(";").map((cookie) => cookie.trim());
const container = document.createElement("div");
container.style.position = "fixed";
container.style.top = "20px";
container.style.right = "20px";
container.style.backgroundColor = "#ffffff";
container.style.border = "2px solid #ddd";
container.style.padding = "15px";
container.style.boxShadow = "0 0 10px rgba(0, 0, 0, 0.2)";
container.style.borderRadius = "8px";
container.style.zIndex = "10000";
container.style.maxHeight = "80vh";
container.style.overflowY = "auto";
// container.style.z-index = '10000';
const selectedCookies = new Set();
const pushButton = document.createElement("button");
pushButton.textContent = "推送Cookie到面板";
styleButton(pushButton, "#007bff", "#ffffff");
pushButton.onclick = () => {
const selectedCookieValue = Array.from(selectedCookies).join(";");
promptAndPushCookies(selectedCookieValue);
};
container.appendChild(pushButton);
const confirmButton = document.createElement("button");
confirmButton.textContent = "保留选定的Cookie";
styleButton(confirmButton, "#28a745", "#ffffff");
confirmButton.onclick = () => {
if (selectedCookies && selectedCookies.size == 0) {
alert("请至少选择一个Cookie进行保留!");
return;
}
const finalCookies = Array.from(selectedCookies).join(";");
GM_setClipboard(finalCookies);
alert("选定的Cookie已复制到剪贴板。");
document.body.removeChild(container);
};
container.appendChild(confirmButton);
const selectAllButton = document.createElement("button");
selectAllButton.textContent = "全选";
styleButton(selectAllButton, "#17a2b8", "#ffffff");
selectAllButton.onclick = () => {
cookies.forEach((cookie) => {
const button = document.getElementById(`cookie-button-${cookie}`);
if (button && !button.classList.contains("selected")) {
button.classList.add("selected");
selectedCookies.add(cookie);
updateButtonStyle(button);
}
});
};
container.appendChild(selectAllButton);
const toggleButton = document.createElement("button");
toggleButton.textContent = "反选";
styleButton(toggleButton, "#ffc107", "#ffffff");
toggleButton.onclick = () => {
cookies.forEach((cookie) => {
const button = document.getElementById(`cookie-button-${cookie}`);
if (button) {
button.classList.toggle("selected");
if (selectedCookies.has(cookie)) {
selectedCookies.delete(cookie);
} else {
selectedCookies.add(cookie);
}
updateButtonStyle(button);
}
});
};
container.appendChild(toggleButton);
const cancelButton = document.createElement("button");
cancelButton.textContent = "取消";
styleButton(cancelButton, "#dc3545", "#ffffff");
cancelButton.onclick = () => {
document.body.removeChild(container);
};
container.appendChild(cancelButton);
cookies.forEach((cookie) => {
const button = document.createElement("button");
button.textContent = cookie;
button.id = `cookie-button-${cookie}`;
button.style.display = "block";
button.style.marginBottom = "5px";
button.style.padding = "5px";
button.style.border = "1px solid #ccc";
button.style.backgroundColor = "#f0f0f0";
button.style.cursor = "pointer";
button.style.borderRadius = "5px";
button.onclick = () => {
button.classList.toggle("selected");
if (selectedCookies.has(cookie)) {
selectedCookies.delete(cookie);
} else {
selectedCookies.add(cookie);
}
updateButtonStyle(button);
};
updateButtonStyle(button);
container.appendChild(button);
});
document.body.appendChild(container);
}
async function updateButtonStyle(button) {
if (button.classList.contains("selected")) {
button.style.backgroundColor = "#cce5ff";
button.style.color = "#004085";
button.style.border = "1px solid #004085";
} else {
button.style.backgroundColor = "#f0f0f0";
button.style.color = "#000";
button.style.border = "1px solid #ccc";
}
}
async function styleButton(button, backgroundColor, color) {
button.style.display = "block";
button.style.marginBottom = "10px";
button.style.padding = "8px 12px";
button.style.border = "none";
button.style.backgroundColor = backgroundColor;
button.style.color = color;
button.style.cursor = "pointer";
button.style.borderRadius = "5px";
button.style.fontSize = "14px";
button.style.fontWeight = "bold";
button.style.boxShadow = "0 2px 4px rgba(0, 0, 0, 0.2)";
button.onmouseover = () => {
button.style.opacity = "0.8";
};
button.onmouseout = () => {
button.style.opacity = "1";
};
}
async function promptAndPushCookies(defaultCookieValue = "") {
if (!isTested) {
alert("请先进行测试连接,以确保面板连接正常!");
return;
}
const ENV_NAME = prompt("请输入推送到面板的变量名", "COOKIES");
const cookieValue = prompt(
"请输入推送到面板的 Cookie 值",
defaultCookieValue,
);
if (ENV_NAME === null || cookieValue === null) {
return;
}
if (!ENV_NAME || !cookieValue) {
alert("变量名 和 Cookie 值均不能为空,请重新输入!");
return;
}
getTokenAndPush(cookieValue, ENV_NAME);
}
/*GM_registerMenuCommand("清除所有Cookie", clearAllCookies);
GM_registerMenuCommand("复制Cookie到剪贴板", copyCookiesToClipboard);
GM_registerMenuCommand("青龙面板连接", testConnectionToPanel);
GM_registerMenuCommand("选择性ck推送", splitAndSelectCookies);
GM_registerMenuCommand('手动选择变量/值到面板', () => {
promptAndPushCookies();
});
GM_registerMenuCommand("推送全部ck到面板", pushCookiesToPanel2);
GM_registerMenuCommand("重置面板配置", resetPanelConfiguration);*/
if (window.self === window.top) {
// 仅在主页面上运行
const existingButton = document.getElementById("menuButton");
if (!existingButton) {
const style = document.createElement("style");
style.textContent = `
#customMenu {
position: fixed;
top: 50px;
right: 10px;
width: 220px;
background: #ffffff;
border: 1px solid #ddd;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
border-radius: 8px;
z-index: 10000;
display: none;
overflow: hidden;
transition: all 0.3s ease-in-out;
}
#customMenu button {
display: block;
width: 100%;
border: none;
background: #f9f9f9;
padding: 12px;
z-index: 10000;
cursor: pointer;
text-align: left;
font-size: 16px;
color: #333;
transition: background 0.2s, color 0.2s;
}
#customMenu button:hover {
background: #007bff;
color: #fff;
}
#menuButton {
position: fixed;
top: 10px;
right: 10px;
width: 120px;
height: 50px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
text-align: center;
line-height: 50px;
font-size: 16px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
z-index: 10000;
transition: all 0.2s ease-in-out;
}
`;
document.head.appendChild(style);
const menuButton = document.createElement("button");
menuButton.id = "menuButton";
menuButton.textContent = "CK管理菜单";
document.body.appendChild(menuButton);
const customMenu = document.createElement("div");
customMenu.id = "customMenu";
document.body.appendChild(customMenu);
const menuItems = [
{ name: "清除所有Cookie", action: clearAllCookies },
{ name: "复制Cookie到剪贴板", action: copyCookiesToClipboard },
{ name: "青龙面板连接", action: testConnectionToPanel },
{ name: "选择部分ck推送", action: splitAndSelectCookies },
{ name: "手动选择变量/值到面板", action: promptAndPushCookies },
{ name: "推送全部ck到面板", action: pushCookiesToPanel2 },
{ name: "替换cookie", action: replaceCookies },
{ name: "重置面板配置", action: resetPanelConfiguration },
];
menuItems.forEach((item) => {
const button = document.createElement("button");
button.textContent = item.name;
button.onclick = item.action;
customMenu.appendChild(button);
});
const isButtonHidden =
localStorage.getItem("menuButtonHidden") === "true";
if (isButtonHidden) {
menuButton.style.display = "none";
}
let isMenuVisible = false;
let menuCommandId = null;
function updateMenuCommand() {
const isHidden = menuButton.style.display === "none";
const statusSymbol = isHidden ? "❌" : "✅";
if (menuCommandId !== null) {
GM_unregisterMenuCommand(menuCommandId);
}
menuCommandId = GM_registerMenuCommand(
`${statusSymbol} 显示/隐藏 CK管理按钮`,
toggleMenuButton,
);
}
function toggleMenuButton() {
const isHidden = menuButton.style.display === "none";
menuButton.style.display = isHidden ? "block" : "none";
localStorage.setItem("menuButtonHidden", !isHidden);
isMenuVisible = !isHidden;
updateMenuCommand();
}
updateMenuCommand();
menuButton.onclick = () => {
isMenuVisible = !isMenuVisible;
customMenu.style.display = isMenuVisible ? "block" : "none";
updateMenuCommand();
};
document.addEventListener("click", (event) => {
if (
!menuButton.contains(event.target) &&
!customMenu.contains(event.target)
) {
isMenuVisible = false;
customMenu.style.display = "none";
updateMenuCommand();
}
});
let isDragging = false;
let offsetX, offsetY;
let dragStartTime;
const dragThreshold = 1000;
menuButton.addEventListener("mousedown", (event) => {
isDragging = true;
dragStartTime = Date.now();
offsetX = event.clientX - menuButton.getBoundingClientRect().left;
offsetY = event.clientY - menuButton.getBoundingClientRect().top;
});
document.addEventListener("mousemove", (event) => {
if (isDragging) {
const newLeft = event.clientX - offsetX;
const newTop = event.clientY - offsetY;
menuButton.style.left = `${newLeft}px`;
menuButton.style.top = `${newTop}px`;
}
});
document.addEventListener("mouseup", () => {
if (isDragging) {
isDragging = false;
const dragDuration = Date.now() - dragStartTime;
if (dragDuration < dragThreshold) {
menuButton.click();
}
snapToEdge();
}
});
menuButton.addEventListener("touchstart", (event) => {
isDragging = true;
dragStartTime = Date.now();
const touch = event.touches[0];
offsetX = touch.clientX - menuButton.getBoundingClientRect().left;
offsetY = touch.clientY - menuButton.getBoundingClientRect().top;
});
document.addEventListener("touchmove", (event) => {
if (isDragging) {
const touch = event.touches[0];
const newLeft = touch.clientX - offsetX;
const newTop = touch.clientY - offsetY;
menuButton.style.left = `${newLeft}px`;
menuButton.style.top = `${newTop}px`;
}
});
document.addEventListener("touchend", () => {
if (isDragging) {
isDragging = false;
const dragDuration = Date.now() - dragStartTime;
if (dragDuration < dragThreshold) {
menuButton.click();
}
snapToEdge();
}
});
async function snapToEdge() {
let newLeft;
let position = menuButton.getBoundingClientRect();
if (window.innerWidth - position.right > position.left) {
newLeft = 0;
} else {
newLeft = window.innerWidth - position.width;
}
menuButton.style.left = `${newLeft}px`;
menuButton.style.transition = "all 0.2s ease-in-out";
if (isMenuVisible) {
customMenu.style.display = "none";
isMenuVisible = false;
updateMenuCommand();
}
ensureVisibility();
}
function ensureVisibility() {
let position = menuButton.getBoundingClientRect();
if (
position.top < 0 ||
position.left < 0 ||
position.right > window.innerWidth ||
position.bottom > window.innerHeight
) {
menuButton.style.top = "10px";
menuButton.style.left = `${
window.innerWidth - menuButton.offsetWidth - 10
}px`;
}
}
ensureVisibility();
// const iframe = document.querySelector("iframe");
// iframe.onload = function () {
// const iframeDocument = iframe.contentWindow.document;
// const menuButton = iframeDocument.getElementById("menuButton");
// if (menuButton) {
// menuButton.parentNode.removeChild(menuButton);
// }
// };
async function parseCookieString(ck) {
return ck.split(";").map((e) => e.trim());
}
} else {
console.log("菜单按钮已存在,跳过创建。");
}
} else {
console.log("脚本在iframe内运行,跳过按钮创建。");
}
async function replaceCookies() {
let cookies = prompt("请输入cookie:");
cookies = await parseCookieString(cookies);
if (cookies) {
await clearCookies();
}
cookies.forEach((e) => {
document.cookie = e + ";domain=." + domain + ";path=/;";
});
location.reload();
}
async function GM_fetch(details) {
return new Promise((resolve, reject) => {
details.onload = (res) => resolve(res);
details.onerror = (res) => {
alert(`请求出错:${res.statusText || "未知错误"}`);
reject(res);
};
details.ontimeout = (res) => {
alert("请求超时!");
reject(res);
};
details.onabort = (res) => {
alert("请求被中止!");
reject(res);
};
GM_xmlhttpRequest(details);
});
}
})();