当洛谷比赛报名按钮出现时,会有 5s 倒计时,很烦人,本脚本可立即解除其禁用状态,方便报名。
// ==UserScript==
// @name 洛谷报名按钮解锁器 (Luogu Contest Button Unlocker)
// @namespace https://github.com/your-username/luogu-unlocker
// @version 1.1.1
// @description 当洛谷比赛报名按钮出现时,会有 5s 倒计时,很烦人,本脚本可立即解除其禁用状态,方便报名。
// @author Gemini
// @match https://www.luogu.com.cn/*
// @grant none
// @run-at document-end
// @license MIT
// ==/UserScript==
(function() {
'use strict';
const config = {
// 用于定位目标按钮的 CSS 选择器
buttonSelector: 'button.swal2-confirm.swal2-styled[disabled]',
// 用于识别倒计时文本的正则表达式
textRegex: /报名 \(\d+s\)/,
// 解锁后按钮应显示的最终文本
unlockedText: '报名',
// 用于标记已处理按钮的自定义属性,防止重复操作
processedMark: 'data-luogu-unlocker-processed'
};
/**
* 启用按钮并使用 MutationObserver "锁定" 其状态,防止被其他脚本修改。
* @param {HTMLElement} button - 需要锁定的按钮元素。
*/
const protectButton = (button) => {
console.log('[洛谷解锁器] 检测到目标按钮,开始处理...');
// 1. 立即修改按钮状态
button.disabled = false;
button.innerText = config.unlockedText;
// 2. 创建一个 "守护" Observer 来防止按钮被修改
const protector = new MutationObserver(() => {
// 当检测到按钮被修改时,立即将其恢复
// 先断开观察,避免我们自己的修改触发无限循环
protector.disconnect();
button.disabled = false;
button.innerText = config.unlockedText;
// 恢复原状后,重新开始观察
observe();
});
const observe = () => {
protector.observe(button, {
attributes: true, // 监视属性变化 (如 'disabled')
childList: true, // 监视子节点变化 (用于文本内容)
characterData: true, // 监视文本内容变化
subtree: true
});
};
observe();
console.log('[洛谷解锁器] 按钮保护已启动。');
// 3. (可选但推荐) 清理工作:当按钮从页面上消失时(例如弹窗关闭),停止观察以节省资源
const parent = button.parentNode;
if (parent) {
const removalObserver = new MutationObserver((mutations) => {
mutations.forEach(mutation => {
mutation.removedNodes.forEach(removedNode => {
if (removedNode === button) {
protector.disconnect();
removalObserver.disconnect();
console.log('[洛谷解锁器] 按钮已移除,保护程序停止。');
}
});
});
});
removalObserver.observe(parent, { childList: true });
}
};
/**
* 创建一个主 Observer,监视整个页面的 DOM 变化,以发现目标按钮的出现。
*/
const bodyObserver = new MutationObserver(() => {
const button = document.querySelector(config.buttonSelector);
// 检查按钮是否存在、是否包含倒计时文本、以及是否尚未被我们处理过
if (button && config.textRegex.test(button.innerText) && !button.hasAttribute(config.processedMark)) {
// 给按钮打上标记,防止重复执行
button.setAttribute(config.processedMark, 'true');
protectButton(button);
}
});
// 启动主 Observer,开始监视整个文档
bodyObserver.observe(document.body, {
childList: true,
subtree: true
});
console.log('[洛谷解锁器] 脚本已激活,正在等待报名按钮出现...');
})();