洛谷卷网监视器
C++
// ==UserScript==
// @name 卷王监视器(时间筛选版)
// @namespace https://greasyfork.org/zh-CN/users/1124544-sz-jinzikai
// @version 2.3
// @description 监控指定用户在特定时间内的做题记录
// @author sz_jinzikai
// @match https://www.luogu.com.cn/123
// @icon https://cdn.luogu.com.cn/upload/usericon/743373.png
// @grant none
// ==/UserScript==
var userlist = [1049425,886055, 1023865, 1081095, 643743, 1057868, 1055731, 1098988, 1059683, 1054396, 903392, 1472024, 1058204];
var displaylist = ["ZHL_myself","LBY", "XZY", "QMR", "WYT", "HSH", "GYC", "HJM", "QAS", "ZYM", "YSJ", "ZGR", "ZXY"];
var pages = 2; // 检查页数
var cd = 10000; // 检查间隔
// 时间选项配置(单位:毫秒)
var timeOptions = {
"24小时": 24 * 60 * 60 * 1000,
"一周": 7 * 24 * 60 * 60 * 1000,
"一个月": 30 * 24 * 60 * 60 * 1000,
"全部": 0
};
// 当前选择的时间范围
var currentTimeRange = timeOptions["24小时"];
var lastCheckTime = Date.now() - currentTimeRange;
function onSearch() {
var storeId = document.getElementById('store');
var rowsLength = storeId.rows.length;
var key = document.getElementById('key').value;
var timeFilter = document.getElementById('timeFilter').value;
for (var i = 1; i < rowsLength; i++) {
var searchText = storeId.rows[i].cells[0].innerHTML;
var recordTime = parseInt(storeId.rows[i].cells[3].getAttribute('data-timestamp'));
var now = Date.now();
var showRow = true;
// 用户名筛选
if (key != "*" && !searchText.match(key)) {
showRow = false;
}
// 时间筛选
if (timeFilter != "全部" && timeOptions[timeFilter] > 0) {
if (now - recordTime > timeOptions[timeFilter]) {
showRow = false;
}
}
storeId.rows[i].style.display = showRow ? '' : 'none';
}
}
function changeTimeRange() {
var timeFilter = document.getElementById('timeFilter');
currentTimeRange = timeOptions[timeFilter.value];
lastCheckTime = Date.now() - currentTimeRange;
// 重新筛选显示的内容
onSearch();
}
// 创建界面
var str = '<div style="margin-bottom: 10px;">';
str += '<select onchange="onSearch()" name="key" id="key" style="margin-right: 10px; padding: 5px;"><option value="*">全部用户</option>';
for (var i = 0; i < userlist.length; i++) {
str += '<option value="' + userlist[i] + '">' + displaylist[i] + '</option>';
}
str += '</select>';
str += '<select onchange="changeTimeRange()" name="timeFilter" id="timeFilter" style="padding: 5px;">';
for (var key in timeOptions) {
str += '<option value="' + key + '"' + (key === "24小时" ? ' selected' : '') + '>' + key + '</option>';
}
str += '</select>';
str += '</div>';
str += '<table id="store" style="white-space: nowrap; width: 100%; border-collapse: collapse;">';
str += '<tr style="background-color: #f2f2f2;">';
str += '<th style="padding: 8px; border: 1px solid #ddd;">用户</th>';
str += '<th style="padding: 8px; border: 1px solid #ddd;">题号</th>';
str += '<th style="padding: 8px; border: 1px solid #ddd;">标题</th>';
str += '<th style="padding: 8px; border: 1px solid #ddd;">提交时间</th>';
str += '</tr></table>';
document.body.innerHTML = "<h1 style='text-align:center;color:red;font-family:Microsoft Yahei'>卷王监视器 2.3</h1>";
document.body.innerHTML += "<p style='text-align:center;font-family:FangSong'>运筹首页之中,偷袭千里之外😜……时间范围可筛选</p><hr>" + str;
var colors = ['rgb(191, 191, 191)', 'rgb(254, 76, 97)', 'rgb(243, 156, 17)', 'rgb(255, 193, 22)', 'rgb(82, 196, 26)', 'rgb(52, 152, 219)', 'rgb(157, 61, 207)', 'rgb(14, 29, 105)'];
var name = "灰红橙黄绿蓝紫黑";
var lst = Array(userlist.length).fill(0);
var cnt = 0;
function formatTime(timestamp) {
var date = new Date(timestamp * 1000);
var now = new Date();
var diff = now - date;
// 如果是今天
if (date.toDateString() === now.toDateString()) {
return date.getHours().toString().padStart(2, '0') + ':' +
date.getMinutes().toString().padStart(2, '0');
}
// 如果是今年
else if (date.getFullYear() === now.getFullYear()) {
return (date.getMonth() + 1) + '-' + date.getDate();
}
// 其他
else {
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
}
}
function PARSE(First = false) {
cnt = (cnt + 1) % userlist.length;
var user = userlist[cnt];
for (var Pagenum = 1; Pagenum <= pages; Pagenum++) {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', 'https://www.luogu.com.cn/record/list?user=' + user + '&page=' + Pagenum, false);
httpRequest.send();
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
var content = httpRequest.responseText;
var patten = /decodeURIComponent\(".*?"\)/;
content = patten.exec(content)[0];
content = content.substr(20, content.length - 22);
content = JSON.parse(decodeURIComponent(content));
for (var i = Math.min(content.currentData.records.result.length - 1, 19); i >= 0; i--) {
var record = content.currentData.records.result[i];
// 只处理AC记录
if (record.status == 12 && record.id > lst[cnt]) {
var timestamp = record.submitTime;
var now = Date.now();
var recordTime = timestamp * 1000;
// 时间筛选:只显示在选定时间范围内的记录
if (currentTimeRange > 0 && (now - recordTime) > currentTimeRange) {
continue;
}
var prob = record.problem;
var col = colors[prob.difficulty];
var pid = prob.pid;
var title = prob.title;
// 添加记录到表格
document.getElementById('store').innerHTML +=
'<tr>' +
'<td style="padding: 8px; border: 1px solid #ddd;">' + displaylist[cnt] + '</td>' +
'<td style="padding: 8px; border: 1px solid #ddd;">' + pid + '</td>' +
'<td style="padding: 8px; border: 1px solid #ddd;">' +
'<a style="color:' + col + '; text-decoration: none;" href="https://www.luogu.com.cn/problem/' + pid + '" target="_blank">' +
title + '</a></td>' +
'<td style="padding: 8px; border: 1px solid #ddd;" data-timestamp="' + timestamp + '">' +
formatTime(timestamp) + '</td>' +
'</tr>';
// 如果不是初始化阶段,显示通知
if (!First) {
alert(displaylist[cnt] + " 刚刚卷了" + name[prob.difficulty] + "题 " + pid + " " + title);
}
lst[cnt] = record.id;
}
}
}
}
}
// 初始化:获取所有记录
for (var i = 0; i < userlist.length; i++) {
cnt = i;
PARSE(true);
}
// 设置定时器定期检查
window.setInterval(function() {
PARSE(false);
}, cd);
洛谷卷网监视器加强
C++
// ==UserScript==
// @name 卷王监视器(时间筛选版)
// @namespace https://greasyfork.org/zh-CN/users/1124544-sz-jinzikai
// @version 2.8
// @description 监控指定用户在特定时间内的做题记录(异步、可排序、不折叠、难度筛选、去重按钮)
// @author sz_jinzikai
// @match https://www.luogu.com.cn/123
// @icon https://cdn.luogu.com.cn/upload/usericon/743373.png
// @grant none
// ==/UserScript==
(function() {
'use strict';
// ---------- 配置 ----------
const userlist = [1049425, 886055, 1023865, 1081095, 643743, 1057868, 1055731, 1098988, 1059683, 1054396, 903392, 1472024, 1058204];
const displaylist = ["ZHL_myself", "LBY", "XZY", "QMR", "WYT", "HSH", "GYC", "HJM", "QAS", "ZYM", "YSJ", "ZGR", "ZXY"];
const pages = 1; // 检查页数
const cd = 3000; // 轮询间隔(毫秒)
// 时间选项:-1 今天内,其他固定毫秒数
const timeOptions = {
"今天内": -1,
"24小时": 24 * 60 * 60 * 1000,
"一周": 7 * 24 * 60 * 60 * 1000,
"一个月": 30 * 24 * 60 * 60 * 1000,
"全部": 0
};
// 难度选项
const difficultyOptions = [
{ name: "全部难度", value: -1 },
{ name: "灰", value: 0 },
{ name: "红", value: 1 },
{ name: "橙", value: 2 },
{ name: "黄", value: 3 },
{ name: "绿", value: 4 },
{ name: "蓝", value: 5 },
{ name: "紫", value: 6 },
{ name: "黑", value: 7 }
];
let currentTimeRange = timeOptions["今天内"];
let lastRecordId = Array(userlist.length).fill(0);
const colors = ['rgb(191,191,191)', 'rgb(254,76,97)', 'rgb(243,156,17)', 'rgb(255,193,22)', 'rgb(82,196,26)', 'rgb(52,152,219)', 'rgb(157,61,207)', 'rgb(14,29,105)'];
const difficultyNames = "灰红橙黄绿蓝紫黑";
// ---------- 辅助函数 ----------
function formatTime(timestamp) {
const date = new Date(timestamp * 1000);
const now = new Date();
if (date.toDateString() === now.toDateString()) {
return date.getHours().toString().padStart(2, '0') + ':' +
date.getMinutes().toString().padStart(2, '0');
} else if (date.getFullYear() === now.getFullYear()) {
return (date.getMonth() + 1) + '-' + date.getDate();
} else {
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
}
}
function getTodayMidnight() {
const d = new Date();
d.setHours(0, 0, 0, 0);
return d.getTime();
}
function isInTimeRange(recordTimeMs) {
if (currentTimeRange === -1) {
return recordTimeMs >= getTodayMidnight();
} else if (currentTimeRange === 0) {
return true;
} else {
return (Date.now() - recordTimeMs) <= currentTimeRange;
}
}
// ---------- 异步请求单个用户记录 ----------
function fetchUserRecords(userId, page = 1) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', `https://www.luogu.com.cn/record/list?user=${userId}&page=${page}`, true);
xhr.withCredentials = true;
xhr.onload = () => {
if (xhr.status === 200) {
try {
let raw = xhr.responseText;
const match = /decodeURIComponent\(".*?"\)/.exec(raw);
if (!match) return resolve([]);
let encoded = match[0];
encoded = encoded.substr(20, encoded.length - 22);
const data = JSON.parse(decodeURIComponent(encoded));
const records = data.currentData.records.result || [];
resolve(records);
} catch (e) {
reject(e);
}
} else {
reject(new Error(`HTTP ${xhr.status}`));
}
};
xhr.onerror = reject;
xhr.send();
});
}
// ---------- 处理新记录并添加到表格 ----------
async function processNewRecords(userId, userName, userIdx, isFirstRun = false) {
try {
const records = await fetchUserRecords(userId, 1);
for (let i = Math.min(records.length - 1, 19); i >= 0; i--) {
const rec = records[i];
if (rec.status === 12 && rec.id > lastRecordId[userIdx]) {
const submitTimeMs = rec.submitTime * 1000;
if (!isInTimeRange(submitTimeMs)) continue;
const tbody = document.getElementById('recordTableBody');
const row = tbody.insertRow(0);
row.setAttribute('data-user-idx', userIdx);
row.setAttribute('data-timestamp', rec.submitTime);
row.setAttribute('data-difficulty', rec.problem.difficulty);
row.innerHTML = `
<td class="user-cell">${userName}</td>
<td>${rec.problem.pid}</td>
<td><a style="color:${colors[rec.problem.difficulty]}" href="https://www.luogu.com.cn/problem/${rec.problem.pid}" target="_blank">${rec.problem.title}</a></td>
<td class="time-cell" data-timestamp="${rec.submitTime}">${formatTime(rec.submitTime)}</td>
`;
lastRecordId[userIdx] = rec.id;
if (!isFirstRun) {
alert(`${userName} 刚刚卷了 ${difficultyNames[rec.problem.difficulty]} 题 ${rec.problem.pid} ${rec.problem.title}`);
}
}
}
} catch (e) {
console.error(`获取用户 ${userName} 记录失败`, e);
}
}
// ---------- 初始化加载所有用户记录(并发) ----------
async function loadAllInitial() {
const tbody = document.getElementById('recordTableBody');
tbody.innerHTML = '<tr><td colspan="4" style="text-align:center; padding:30px;">⏳ 加载中,请稍候...</td></tr>';
const promises = userlist.map((id, idx) => processNewRecords(id, displaylist[idx], idx, true));
await Promise.all(promises);
filterTable();
}
// ---------- 轮询 ----------
let pollIndex = 0;
async function pollNextUser() {
const idx = pollIndex % userlist.length;
pollIndex++;
await processNewRecords(userlist[idx], displaylist[idx], idx, false);
filterTable();
}
// ---------- 筛选表格行(用户、时间、难度) ----------
function filterTable() {
const userSelect = document.getElementById('userSelect');
const timeSelect = document.getElementById('timeSelect');
const difficultySelect = document.getElementById('difficultySelect');
const difficultyAboveCheck = document.getElementById('difficultyAbove');
const selectedUser = userSelect.value;
const selectedTimeVal = parseInt(timeSelect.value, 10);
const selectedDiff = parseInt(difficultySelect.value, 10);
const isAbove = difficultyAboveCheck.checked;
const tbody = document.getElementById('recordTableBody');
const rows = tbody.getElementsByTagName('tr');
for (let row of rows) {
if (row.cells.length === 1 && row.cells[0].colSpan === 4) continue;
const userCell = row.cells[0].innerText;
const timestamp = parseInt(row.cells[3].getAttribute('data-timestamp'), 10) * 1000;
const difficulty = parseInt(row.getAttribute('data-difficulty'), 10);
let show = true;
if (selectedUser !== '*') {
const selectedIdx = userlist.indexOf(parseInt(selectedUser));
if (selectedIdx === -1 || userCell !== displaylist[selectedIdx]) show = false;
}
if (show && selectedTimeVal !== 0) {
if (selectedTimeVal === -1) {
if (timestamp < getTodayMidnight()) show = false;
} else {
if (Date.now() - timestamp > selectedTimeVal) show = false;
}
}
if (show && selectedDiff !== -1) {
if (isAbove) {
if (difficulty < selectedDiff) show = false;
} else {
if (difficulty !== selectedDiff) show = false;
}
}
row.style.display = show ? '' : 'none';
}
}
// ---------- 排序 ----------
function sortTableByUserAndTime() {
const tbody = document.getElementById('recordTableBody');
const rows = Array.from(tbody.getElementsByTagName('tr'));
const dataRows = rows.filter(r => r.cells.length === 4 && r.cells[0].colSpan !== 4);
const rowData = dataRows.map(row => {
const userCell = row.cells[0].innerText;
const userIdx = displaylist.indexOf(userCell);
const timestamp = parseInt(row.cells[3].getAttribute('data-timestamp'), 10);
return { row, userIdx, timestamp };
});
rowData.sort((a, b) => {
if (a.userIdx !== b.userIdx) return a.userIdx - b.userIdx;
return a.timestamp - b.timestamp;
});
tbody.innerHTML = '';
rowData.forEach(item => tbody.appendChild(item.row));
filterTable();
}
// ---------- 去重:同用户同题保留最新一条(时间戳最大)----------
function deduplicateTable() {
const tbody = document.getElementById('recordTableBody');
const rows = Array.from(tbody.getElementsByTagName('tr'));
const dataRows = rows.filter(r => r.cells.length === 4 && r.cells[0].colSpan !== 4);
// 使用 Map 记录每个用户+题号的最佳行(时间戳最大)
const bestRowMap = new Map(); // key: `${user}_${pid}`
dataRows.forEach(row => {
const user = row.cells[0].innerText;
const pid = row.cells[1].innerText;
const timestamp = parseInt(row.cells[3].getAttribute('data-timestamp'), 10); // 秒
const key = `${user}_${pid}`;
if (!bestRowMap.has(key) || timestamp > bestRowMap.get(key).timestamp) {
bestRowMap.set(key, { row, timestamp });
}
});
// 删除所有不在 bestRowMap 中的行
dataRows.forEach(row => {
const user = row.cells[0].innerText;
const pid = row.cells[1].innerText;
const key = `${user}_${pid}`;
if (bestRowMap.get(key).row !== row) {
row.remove();
}
});
// 重新应用筛选(可能因删除行而需要更新显示)
filterTable();
}
// ---------- 构建UI ----------
function buildUI() {
const style = document.createElement('style');
style.textContent = `
* { box-sizing: border-box; }
body {
font-family: 'Inter', 'Microsoft YaHei', sans-serif;
background: linear-gradient(145deg, #f0f4f8 0%, #e6ecf5 100%);
margin: 0;
min-height: 100vh;
padding: 24px;
}
.monitor-card {
max-width: 1400px;
margin: 0 auto;
background: rgba(255,255,255,0.8);
backdrop-filter: blur(10px);
border-radius: 28px;
box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
padding: 28px 32px;
border: 1px solid rgba(255,255,255,0.5);
}
h1 {
margin: 0 0 4px 0;
font-size: 32px;
font-weight: 700;
background: linear-gradient(135deg, #c44536, #e67e22);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: -0.5px;
}
.subhead {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 2px solid rgba(0,0,0,0.05);
padding-bottom: 18px;
margin-bottom: 20px;
color: #4a5568;
}
.subhead p {
margin: 0;
font-style: italic;
font-size: 15px;
}
.toolbar {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-bottom: 24px;
background: white;
padding: 16px 20px;
border-radius: 60px;
box-shadow: 0 4px 10px rgba(0,0,0,0.03);
align-items: center;
}
.toolbar select, .toolbar button {
padding: 8px 20px;
border: 1px solid #dde7f0;
border-radius: 40px;
background: white;
font-size: 14px;
font-weight: 500;
color: #1e293b;
cursor: pointer;
transition: all 0.2s;
outline: none;
}
.toolbar select {
min-width: 120px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%234b5563' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 12px center;
appearance: none;
}
.toolbar select:hover {
border-color: #94a3b8;
background-color: #f8fafc;
}
.toolbar button {
background: linear-gradient(145deg, #ffffff, #f1f5f9);
border: 1px solid #cbd5e1;
display: inline-flex;
align-items: center;
gap: 6px;
box-shadow: 0 2px 4px rgba(0,0,0,0.02);
}
.toolbar button:hover {
background: #e2e8f0;
border-color: #94a3b8;
transform: translateY(-1px);
}
.difficulty-wrapper {
display: flex;
align-items: center;
gap: 8px;
background: #f8fafc;
padding: 4px 12px 4px 8px;
border-radius: 40px;
border: 1px solid #dde7f0;
}
.difficulty-wrapper select {
min-width: 90px;
border: none;
background: transparent;
padding-left: 4px;
}
.difficulty-wrapper label {
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
color: #475569;
cursor: pointer;
white-space: nowrap;
}
.difficulty-wrapper input[type="checkbox"] {
width: 16px;
height: 16px;
cursor: pointer;
accent-color: #4ecdc4;
}
.table-container {
background: white;
border-radius: 20px;
overflow: hidden;
box-shadow: 0 8px 20px rgba(0,0,0,0.04);
border: 1px solid #eef2f6;
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th {
background: #f8fafd;
padding: 16px 12px;
font-weight: 600;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.8px;
color: #475569;
border-bottom: 2px solid #e2e8f0;
}
td {
padding: 14px 12px;
border-bottom: 1px solid #edf2f7;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
tbody tr:hover {
background: #f1f5f9;
}
tbody tr:nth-child(even) {
background-color: #fafcff;
}
.user-cell {
font-weight: 600;
color: #2563eb;
}
.time-cell {
color: #64748b;
font-family: 'JetBrains Mono', monospace;
}
td a {
text-decoration: none;
font-weight: 500;
}
td a:hover {
text-decoration: underline;
}
.footer {
text-align: right;
margin-top: 16px;
font-size: 13px;
color: #94a3b8;
}
`;
document.head.appendChild(style);
const container = document.createElement('div');
container.className = 'monitor-card';
container.innerHTML = `
<h1>📈 卷王监视器 2.8</h1>
<div class="subhead">
<p>⚡ 运筹首页之中,偷袭千里之外 · 默认今日内 · 难度筛选 · 去重按钮</p>
<span style="font-size:13px; background:#eef2ff; padding:4px 12px; border-radius:40px; color:#2563eb;">${userlist.length} 位卷王</span>
</div>
<div class="toolbar">
<select id="userSelect">
<option value="*">👥 全部用户</option>
${userlist.map((id, idx) => `<option value="${id}">👤 ${displaylist[idx]}</option>`).join('')}
</select>
<select id="timeSelect">
${Object.entries(timeOptions).map(([label, value]) =>
`<option value="${value}" ${label === '今天内' ? 'selected' : ''}>⏱️ ${label}</option>`
).join('')}
</select>
<div class="difficulty-wrapper">
<select id="difficultySelect">
${difficultyOptions.map(opt =>
`<option value="${opt.value}">🎯 ${opt.name}</option>`
).join('')}
</select>
<label>
<input type="checkbox" id="difficultyAbove"> 及以上
</label>
</div>
<button id="sortBtn"><span>🔀</span> 排序</button>
<button id="dedupBtn"><span>🧹</span> 去重(同人同题)</button>
</div>
<div class="table-container">
<table>
<thead>
<tr><th>用户</th><th>题号</th><th>标题</th><th>提交时间</th></tr>
</thead>
<tbody id="recordTableBody">
<tr><td colspan="4" style="text-align:center; padding:40px;">⏳ 初始化数据中...</td></tr>
</tbody>
</table>
</div>
<div class="footer">✨ 每 3 秒自动检查新记录 · 点击按钮手动整理</div>
`;
document.body.innerHTML = '';
document.body.appendChild(container);
}
// ---------- 事件绑定 ----------
function bindEvents() {
document.getElementById('userSelect').addEventListener('change', filterTable);
document.getElementById('timeSelect').addEventListener('change', function(e) {
currentTimeRange = parseInt(e.target.value, 10);
filterTable();
});
document.getElementById('difficultySelect').addEventListener('change', filterTable);
document.getElementById('difficultyAbove').addEventListener('change', filterTable);
document.getElementById('sortBtn').addEventListener('click', sortTableByUserAndTime);
document.getElementById('dedupBtn').addEventListener('click', deduplicateTable);
}
// ---------- 启动 ----------
(async function main() {
buildUI();
bindEvents();
await loadAllInitial();
setInterval(pollNextUser, cd);
})();
})();
洛谷复制专栏源码
C++
// ==UserScript==
// @name luogu-复制专栏源码
// @namespace http://tampermonkey.net/
// @version 1.1
// @description luogu 复制专栏源码
// @author JiaY19
// @match https://www.luogu.com/article/*
// @match https://www.luogu.com.cn/article/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=luogu.com.cn
// @grant none
// @license MIT
// @downloadURL https://update.greasyfork.org/scripts/489299/luogu-%E5%A4%8D%E5%88%B6%E4%B8%93%E6%A0%8F%E6%BA%90%E7%A0%81.user.js
// @updateURL https://update.greasyfork.org/scripts/489299/luogu-%E5%A4%8D%E5%88%B6%E4%B8%93%E6%A0%8F%E6%BA%90%E7%A0%81.meta.js
// ==/UserScript==
(function () {
'use strict';
const url = window.location.href;
async function clickBotton_blog() {
var x = document.querySelector("#lentille-context").text
var y = JSON.parse(x)
var z = y.data.article.content
navigator.clipboard.writeText(z);
};
if (url.includes("article")) {
document.onkeydown = function (e) {
if (e.keyCode == 67 && e.ctrlKey && e.altKey) {
clickBotton_blog();
alert("复制成功!");
}
}
}
// Your code here...
})();
bbc 卷网监视器
C++
// ==UserScript==
// @name 卷王监视器 - BBC OJ 最终版(弹窗提示+用户排序)
// @namespace https://greasyfork.org/zh-CN/users/1124544-sz_jinzikai
// @version 2.9-bbcoj-final
// @description 监控BBC OnlineJudge用户AC记录(异步轮询,颜色取自oiRankScore,弹窗提示,可手动按用户排序)
// @author sz_jinzikai
// @match http://bbcoj.cn/juan
// @grant none
// ==/UserScript==
// ========== 配置区域 ==========
var userlist = ["c23赵浩霖", "Asafish的MoonCake", "C23薛志渝", "Believe_in_Dreams", "qianqing", "Junly_JYukio", "iChen", "hjm0703", "C23钱安崧", "C23邹艺萌", "T7_Daniel", "C24朱冠如", "昕木"];
var displaylist = ["ZHL_myself","LBY", "XZY", "QMR", "WYT", "HSH", "GYC", "HJM", "QAS", "ZYM", "YSJ", "ZGR", "ZXY"];
var pages = 2; // 检查页数
var cd = 5000; // 每个用户处理间隔(毫秒)
// ========== 配置结束 ==========
// 时间选项(默认24小时)
var timeOptions = {
"24小时": 24 * 60 * 60 * 1000,
"一周": 7 * 24 * 60 * 60 * 1000,
"一个月": 30 * 24 * 60 * 60 * 1000,
"全部": 0
};
var currentTimeRange = timeOptions["24小时"];
// 颜色映射(索引0~7:灰红橙黄绿蓝紫黑)
var colors = ['rgb(191,191,191)', 'rgb(254,76,97)', 'rgb(243,156,17)', 'rgb(255,193,22)', 'rgb(82,196,26)', 'rgb(52,152,219)', 'rgb(157,61,207)', 'rgb(14,29,105)'];
var difficultyNames = ["灰","红","橙","黄","绿","蓝","紫","黑"]; // 用于弹窗
// 根据oiRankScore获取难度索引(服务器存储为 ×10 后的整数,如10,100,200...)
function getDifficultyIndex(oiRankScore) {
if (oiRankScore === undefined || oiRankScore === null) return 0;
switch (oiRankScore) {
case 10: return 0; // 暂无评定 (0.1分)
case 100: return 1; // 入门 (1分)
case 200: return 2; // 普及- (2分)
case 300: return 3; // 普及/提高- (3分)
case 500: return 4; // 普及+/提高 (5分)
case 700: return 5; // 提高+/省选- (7分)
case 1000: return 6; // 省选/NOI- (10分)
case 2000: return 7; // NOI/NOI+/CTSC (20分)
default: return 0;
}
}
// 记录每个用户的最新提交ID
var lst = Array(userlist.length).fill(0);
// ---------- 排序功能 ----------
function sortTableByUser() {
var table = document.getElementById('store');
var rows = Array.from(table.rows).slice(1); // 跳过表头
// 按照 displaylist 顺序排序
rows.sort(function(a, b) {
var userA = a.cells[0].innerText;
var userB = b.cells[0].innerText;
var indexA = displaylist.indexOf(userA);
var indexB = displaylist.indexOf(userB);
// 如果找不到(理论上不会),放在最后
if (indexA === -1) indexA = displaylist.length;
if (indexB === -1) indexB = displaylist.length;
return indexA - indexB;
});
// 重新添加行
for (var i = 0; i < rows.length; i++) {
table.appendChild(rows[i]);
}
}
// ---------- 美化样式 ----------
function injectStyles() {
var style = document.createElement('style');
style.textContent = `
body {
font-family: 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #f5f7fa;
}
h1 {
text-align: center;
background: linear-gradient(135deg, #ff6b6b, #4ecdc4);
color: white;
padding: 15px 0;
border-radius: 50px;
box-shadow: 0 4px 10px rgba(0,0,0,0.1);
font-weight: 400;
letter-spacing: 2px;
margin-top: 0;
}
.subtitle {
text-align: center;
color: #666;
font-style: italic;
margin: 5px 0 20px;
}
hr {
border: none;
height: 1px;
background: linear-gradient(to right, transparent, #ccc, transparent);
margin: 20px 0;
}
.filter-bar {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
flex-wrap: wrap;
}
select, button {
padding: 8px 16px;
border: 2px solid #e0e0e0;
border-radius: 30px;
font-size: 14px;
background-color: white;
cursor: pointer;
transition: all 0.3s;
outline: none;
min-width: 120px;
}
select:hover, button:hover {
border-color: #4ecdc4;
box-shadow: 0 2px 8px rgba(78, 205, 196, 0.2);
}
select:focus, button:focus {
border-color: #ff6b6b;
}
button {
background: #4ecdc4;
color: white;
border-color: #4ecdc4;
font-weight: 500;
}
button:hover {
background: #45b7ae;
}
table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
background-color: white;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 6px 20px rgba(0,0,0,0.08);
}
th {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
font-weight: 500;
padding: 14px 8px;
font-size: 16px;
letter-spacing: 0.5px;
}
td {
padding: 12px 8px;
border-bottom: 1px solid #f0f0f0;
color: #333;
font-size: 14px;
}
tr:last-child td {
border-bottom: none;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
tr:hover {
background-color: #f1f1f1;
transition: background-color 0.2s;
}
a {
text-decoration: none;
font-weight: 500;
transition: opacity 0.2s;
}
a:hover {
opacity: 0.8;
text-decoration: underline;
}
td:last-child {
font-family: 'Consolas', monospace;
color: #888;
}
td:nth-child(2) {
font-family: 'Consolas', monospace;
font-weight: 600;
}
`;
document.head.appendChild(style);
}
// ---------- 界面构建 ----------
function buildUI() {
injectStyles();
var str = '<h1>📊 BBC 卷王监视器 2.9</h1>';
str += '<p class="subtitle">异步轮巡 · 颜色取自 oiRankScore · 弹窗提示 · 可手动排序</p><hr>';
str += '<div class="filter-bar">';
str += '<select onchange="onSearch()" name="key" id="key">';
str += '<option value="*">👥 全部用户</option>';
for (var i = 0; i < userlist.length; i++) {
str += '<option value="' + userlist[i] + '">' + displaylist[i] + '</option>';
}
str += '</select>';
str += '<select onchange="changeTimeRange()" name="timeFilter" id="timeFilter">';
for (var key in timeOptions) {
str += '<option value="' + key + '"' + (key === "24小时" ? ' selected' : '') + '>' + key + '</option>';
}
str += '</select>';
str += '<button onclick="sortTableByUser()">🔤 按用户排序</button>';
str += '</div>';
str += '<table id="store">';
str += '<tr><th>用户</th><th>题号</th><th>标题</th><th>提交时间</th></tr>';
str += '</table>';
document.body.innerHTML = str;
}
// ---------- 工具函数 ----------
function formatTime(timestamp) {
var date = new Date(timestamp * 1000);
var now = new Date();
if (date.toDateString() === now.toDateString()) {
return date.getHours().toString().padStart(2, '0') + ':' + date.getMinutes().toString().padStart(2, '0');
} else if (date.getFullYear() === now.getFullYear()) {
return (date.getMonth() + 1) + '-' + date.getDate();
} else {
return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
}
}
function parseRecords(responseText) {
try {
var data = JSON.parse(responseText);
var records = data.data && data.data.records ? data.data.records : (data.records || []);
var result = [];
for (var i = 0; i < records.length; i++) {
var r = records[i];
if (r.status !== 0) continue;
var submitId = parseInt(r.submitId);
if (isNaN(submitId)) continue;
var timestamp = Math.floor(new Date(r.submitTime).getTime() / 1000);
var diffIndex = getDifficultyIndex(r.oiRankScore);
result.push({
id: submitId,
displayPid: r.displayPid,
title: r.title,
submitTime: timestamp,
diffIndex: diffIndex
});
}
return result;
} catch (e) {
console.error('解析失败', e);
return [];
}
}
function addRecordToTable(userDisplayName, record) {
var problemLink = 'http://bbcoj.cn/problem/' + record.displayPid;
var color = colors[record.diffIndex] || colors[0];
var row = '<tr>' +
'<td>' + userDisplayName + '</td>' +
'<td>' + record.displayPid + '</td>' +
'<td><a style="color:' + color + ';" href="' + problemLink + '" target="_blank">' + record.title + '</a></td>' +
'<td data-timestamp="' + record.submitTime + '">' + formatTime(record.submitTime) + '</td>' +
'</tr>';
document.getElementById('store').innerHTML += row;
}
// ---------- 搜索与筛选 ----------
window.onSearch = function() {
var storeId = document.getElementById('store');
var rowsLength = storeId.rows.length;
var key = document.getElementById('key').value;
var timeFilter = document.getElementById('timeFilter').value;
for (var i = 1; i < rowsLength; i++) {
var searchText = storeId.rows[i].cells[0].innerHTML;
var recordTime = parseInt(storeId.rows[i].cells[3].getAttribute('data-timestamp')) * 1000;
var now = Date.now();
var showRow = true;
if (key != "*" && !searchText.match(key)) showRow = false;
if (timeFilter != "全部" && timeOptions[timeFilter] > 0) {
if (now - recordTime > timeOptions[timeFilter]) showRow = false;
}
storeId.rows[i].style.display = showRow ? '' : 'none';
}
};
window.changeTimeRange = function() {
var timeFilter = document.getElementById('timeFilter');
currentTimeRange = timeOptions[timeFilter.value];
onSearch();
};
// 将排序函数暴露到全局
window.sortTableByUser = sortTableByUser;
// ---------- 核心异步轮询 ----------
var currentUserIndex = 0;
function processUser(userIndex, isFirst) {
var user = userlist[userIndex];
var displayName = displaylist[userIndex];
var page = 1;
function fetchPage() {
if (page > pages) {
scheduleNext(isFirst);
return;
}
var apiUrl = 'http://bbcoj.cn/api/get-submission-list?onlyMine=false&username=' + encodeURIComponent(user) +
'¤tPage=' + page + '&limit=15&completeProblemID=false';
var xhr = new XMLHttpRequest();
xhr.open('GET', apiUrl, true);
xhr.setRequestHeader('Accept', 'application/json');
xhr.onload = function() {
if (xhr.status === 200) {
var records = parseRecords(xhr.responseText);
for (var i = 0; i < records.length; i++) {
var rec = records[i];
if (rec.id > lst[userIndex]) {
var now = Date.now();
var recTime = rec.submitTime * 1000;
if (currentTimeRange > 0 && (now - recTime) > currentTimeRange) continue;
addRecordToTable(displayName, rec);
if (!isFirst) {
// 使用 alert 弹窗(与参考脚本一致)
alert(displayName + " 刚刚AC了" + difficultyNames[rec.diffIndex] + "题 " + rec.displayPid + " " + rec.title);
}
lst[userIndex] = rec.id;
}
}
}
page++;
fetchPage();
};
xhr.onerror = function() {
page++;
fetchPage();
};
xhr.send();
}
fetchPage();
}
function scheduleNext(isFirst) {
currentUserIndex = (currentUserIndex + 1) % userlist.length;
if (isFirst) {
processUser(currentUserIndex, true);
} else {
setTimeout(function() {
processUser(currentUserIndex, false);
}, cd);
}
}
// ---------- 启动 ----------
buildUI();
processUser(0, true);
防止 ctj
C++
// ==UserScript==
// @name 别看题解
// @namespace http://tampermonkey.net/
// @version 0.7.2.1
// @description 在你看洛谷题解的时候把自己挂到犇犇。
// @author 0x3b800001&Maxwell_dcc
// @match https://www.luogu.com.cn/*
// @icon https://cdn.luogu.com.cn/upload/usericon/3.png
// @grant GM_xmlhttpRequest
// @connect *
// @license GPL
// @downloadURL https://update.greasyfork.org/scripts/460792/%E5%88%AB%E7%9C%8B%E9%A2%98%E8%A7%A3.user.js
// @updateURL https://update.greasyfork.org/scripts/460792/%E5%88%AB%E7%9C%8B%E9%A2%98%E8%A7%A3.meta.js
// ==/UserScript==
function mstt(ms) {
ms = Number(ms);
let res = "";
res += String(Math.floor(ms / 86400000)) + "d ";
res += String(Math.floor(ms % 86400000 / 3600000)) + "h ";
res += String(Math.floor(ms % 3600000 / 60000)) + "min ";
res += String(Math.floor(ms % 60000 / 1000)) + "s";
return res;
}
(function () {
'use strict';
let f = () => {
if (localStorage["bktj-format"] == undefined) {
localStorage["bktj-format"] = "这个人在开题 bktjnumber bktjname 后 bktjtime 后看了题解\n\n 警钟长鸣。";
}
if (localStorage["bktj-times"] == undefined) {
localStorage["bktj-times"] = "2";
}
let lnk = window.location.href;
if (lnk == "https://www.luogu.com.cn/user/setting#preference") {
let r = prompt("格式(留空即为不变,具体使用方法见文档):");
if (r.length != 0) localStorage["bktj-format"] = r.replace(/\\n/g, "\n");
r = prompt("询问次数(留空即为不变,具体使用方法见文档):");
if (r.length != 0) localStorage["bktj-times"] = r;
if (confirm("是否清空重复挂 localStorage")) {
let tmp = localStorage;
for (let i = 0; i < localStorage.length; ++i) {
if (localStorage.key(i).indexOf("bktj-problemcache-") != -1) {
tmp.removeItem(localStorage.key(i));
}
}
localStorage = tmp;
}
} else if (lnk.indexOf("https://www.luogu.com.cn/problem/solution/") != -1) {
var name = (document.getElementsByClassName('lfe-h1'))[0].innerHTML;
let P = (name.split(' '))[0];
name = name.substring(P.length + 1, name.length).split(" 题解")[0];
console.log(P);
console.log(name);
GM_xmlhttpRequest({
url: "https://www.luogu.com.cn/problem/" + P + "?_contentOnly=1",
method: "GET",
onload: function (response) {
let rp = response.responseText;
let qwww = rp.split("recommendations")[0];
if (qwww.indexOf("\"submitted\":true") == -1) {
console.log("未通过");
let see = true;
for (let i = 1; i <= localStorage["bktj-times"]; ++i) {
if (!confirm("您尚未通过" + P + ",确认要看题解吗?")) {
see = false;
break;
}
}
if (see) {
if (localStorage["bktj-problemcache-" + P] == undefined) {
if (localStorage["bktj-opentime-" + P] == undefined) localStorage["bktj-opentime-" + P] = Date.now();
GM_xmlhttpRequest({
url: "https://www.luogu.com.cn/api/feed/postBenben",
headers: {
"content-type": "application/json",
"referer": "https://www.luogu.com.cn/",
"x-csrf-token": document.querySelector("meta[name=csrf-token]").content
},
data: JSON.stringify({
content: String(localStorage["bktj-format"])
.replace(/bktjnumber/g, P)
.replace(/bktjname/g, name)
.replace(/bktjtime/g, mstt(Date.now() - Number(localStorage["bktj-opentime-" + P])))
}),
method: "POST",
});
localStorage["bktj-problemcache-" + P] = 1;
} else {
console.log("已经挂过了");
}
} else {
document.getElementsByClassName("lfe-form-sz-middle")[0].click();
return;
}
} else {
console.log("已通过");
}
}
});
} else if (lnk.indexOf("https://www.luogu.com.cn/problem/") != -1) {
let nm = lnk.substring(33);
if (localStorage["bktj-opentime-" + nm] == undefined) {
localStorage["bktj-opentime-" + nm] = Date.now();
}
console.log(nm);
}
};
try {
setTimeout(f, 1000);
} catch (e) {
window.location.reload();
}
})();