wangguo1230 最近的时间轴更新
wangguo1230

wangguo1230

V2EX 第 589474 号会员,加入于 2022-07-30 12:49:09 +08:00
wangguo1230 最近回复了
第三步: 报名参加华为云微认证专场,这是我翻出来的可以和集证有礼一块做的任务,两个任务可以同时完成,已经做过的可以忽略。 这一步大家先忽略,任务奖励有冲突
@NotAProgrammer 不好意思,你是说的华为云的文档地址吗,还是这个脚本的
大家可以自己拼起来
// --- 开始执行防切屏 ---
log("Anti screen-switch script starting...");
patchAddEventListener(window, "window");
patchRemoveEventListener(window, "window");
patchAddEventListener(document, "document");
patchRemoveEventListener(document, "document");
spoofProperties(document, spoofedDocumentProperties, "document");
nullifyEventHandlers(document, eventHandlersToNullifyDocument, "document");
nullifyEventHandlers(window, eventHandlersToNullifyWindow, "window");
const observer = new MutationObserver((mutations, obs) => {
if (document.body) {
patchAddEventListener(document.body, "document.body");
patchRemoveEventListener(document.body, "document.body");
nullifyEventHandlers(document.body, ["onmouseleave", "onmouseout", "onblur", "onfocus"], "document.body");
obs.disconnect();
}
});
if (document.body) {
patchAddEventListener(document.body, "document.body");
patchRemoveEventListener(document.body, "document.body");
nullifyEventHandlers(document.body, ["onmouseleave", "onmouseout", "onblur", "onfocus"], "document.body");
} else {
observer.observe(document.documentElement || document, { childList: true, subtree: true });
}
log("Anti screen-switch script loaded. Monitoring active.");


// =========================================================================
// Part 2: 华为云考试题目复制器模块
// Code from "华为云考试题目复制器" script.
// It waits for the page to load the necessary elements and then adds the button.
// =========================================================================

/**
* 创建并添加“复制题目”按钮到页面上
*/
function addCopyButton() {
const headerRight = document.querySelector('.header .right');
if (headerRight && !document.getElementById('copy-questions-btn')) {
const button = document.createElement('button');
button.innerHTML = '📋 复制题目 (JSON)';
button.id = 'copy-questions-btn';

button.className = 'red'; // 使用一个现有 class 以匹配基本风格
button.style.backgroundColor = '#007d40';
button.style.borderColor = '#007d40';
button.style.marginRight = '10px';
button.style.color = 'white';
button.style.padding = '0 15px'; // 调整内边距以匹配其他按钮
button.style.lineHeight = '30px'; // 调整行高
button.style.height = '32px'; // 调整高度

button.addEventListener('click', extractAndCopyQuestions);

headerRight.insertBefore(button, headerRight.firstChild);
console.log('[题目复制器]: 按钮已添加。');
}
}

/**
* 提取页面所有题目信息并复制到剪贴板
*/
function extractAndCopyQuestions() {
console.log("[题目复制器]: 开始提取题目...");
const allQuestions = [];
const questionElements = document.querySelectorAll('.exam .exam-content');

if (questionElements.length === 0) {
alert('未找到任何题目。请确保考试页面已完全加载。');
return;
}

questionElements.forEach((el, index) => {
const questionObj = {
number: index + 1,
type: 'Unknown',
question: '',
points: 0,
options: []
};

const questionTextEl = el.querySelector('.the-exam-page-html');
if (!questionTextEl) return;

let fullText = questionTextEl.textContent.trim();
const pointMatch = fullText.match(/\((\d+)分\)|((\d+)分)/);
if (pointMatch) {
questionObj.points = parseInt(pointMatch[1] || pointMatch[2], 10);
fullText = fullText.replace(pointMatch[0], '').trim();
}
questionObj.question = fullText;

const radioGroup = el.querySelector('.el-radio-group');
const checkboxGroup = el.querySelector('.el-checkbox-group');

if (radioGroup) {
const options = Array.from(radioGroup.querySelectorAll('.el-radio__label > div')).map(div => div.textContent.trim());
questionObj.options = options;
if (options.length === 2 && (options.includes('正确') && options.includes('错误') || options.includes('true') && options.includes('false'))) {
questionObj.type = 'True/False';
} else {
questionObj.type = 'Single Choice';
}
} else if (checkboxGroup) {
const options = Array.from(checkboxGroup.querySelectorAll('.el-checkbox__label > div')).map(div => div.textContent.trim());
questionObj.options = options;
questionObj.type = 'Multiple Choice';
}

allQuestions.push(questionObj);
});

if (allQuestions.length > 0) {
const jsonOutput = JSON.stringify(allQuestions, null, 2);
GM_setClipboard(jsonOutput, 'text');

const btn = document.getElementById('copy-questions-btn');
if (btn) {
btn.textContent = `✅ 已复制 ${allQuestions.length} 题`;
setTimeout(() => {
btn.textContent = '📋 复制题目 (JSON)';
}, 3000);
}
} else {
alert('提取题目失败,未找到有效题目内容。');
}
}

// 由于脚本在 document-start 运行,DOM 此时尚未构建完成。
// 我们必须等待 DOM 加载完毕后才能查找按钮容器。
// 使用定时器轮询是可靠的方法。
const checkInterval = setInterval(() => {
const headerRight = document.querySelector('.header .right');
if (headerRight) {
clearInterval(checkInterval);
addCopyButton();
}
}, 500);

})();
// ==UserScript==
// @name 华为云考试助手 (复制题目+防切屏)
// @namespace http://tampermonkey.net/
// @version 2.0
// @description 在华为云微认证考试页面添加一个按钮,用于一键复制所有题目为 JSON 格式,并集成防切屏检测功能。
// @author linuxdo
// @match https://connect.huaweicloud.com/courses/exam*
// @run-at document-start
// @grant GM_addStyle
// @grant GM_setClipboard
// @grant unsafeWindow
// @license MIT
// ==/UserScript==

(function() {
'use strict';

// =========================================================================
// Part 1: 通用阻止切屏检测模块
// Code from "通用阻止切屏检测" script to prevent focus/visibility tracking.
// This part runs at document-start to patch browser APIs immediately.
// =========================================================================
const window = unsafeWindow; // 使用原始 window 对象

// 黑名单事件,这些事件的监听器将被阻止
const blackListedEvents = new Set([
"visibilitychange", "blur", "focus", "pagehide", "freeze", "resume",
"mouseleave", "mouseout"
]);

// 白名单属性,这些属性在 document 对象上将被伪造
const spoofedDocumentProperties = {
hidden: { value: false, configurable: true },
mozHidden: { value: false, configurable: true },
msHidden: { value: false, configurable: true },
webkitHidden: { value: false, configurable: true },
visibilityState: { value: "visible", configurable: true },
hasFocus: { value: () => true, configurable: true }
};

// 需要清空/置空的事件处理器属性 (on-event handlers)
const eventHandlersToNullifyDocument = [
"onvisibilitychange", "onblur", "onfocus", "onmouseleave", "onmouseout",
"onpagehide", "onfreeze", "onresume"
];

const eventHandlersToNullifyWindow = [
"onblur", "onfocus", "onpagehide", "onpageshow", "onfreeze", "onresume",
"onmouseleave", "onmouseout"
];

const isDebug = false; // 设置为 true 以启用调试日志
const scriptPrefix = "[防切屏检测]";
const log = console.log.bind(console, `%c${scriptPrefix}`, 'color: #4CAF50; font-weight: bold;');
const warn = console.warn.bind(console, `%c${scriptPrefix}`, 'color: #FFC107; font-weight: bold;');
const error = console.error.bind(console, `%c${scriptPrefix}`, 'color: #F44336; font-weight: bold;');
const debug = isDebug ? log : () => {};

function patchToString(modifiedFunction, originalFunction) {
if (typeof modifiedFunction !== 'function' || typeof originalFunction !== 'function') return;
try {
modifiedFunction.toString = () => Function.prototype.toString.call(originalFunction);
} catch (e) {
error("patchToString failed:", e, "for function:", originalFunction.name);
}
}

function patchAddEventListener(targetObject, objectName) {
if (!targetObject || typeof targetObject.addEventListener !== 'function') return;
const originalAddEventListener = targetObject.addEventListener;
targetObject.addEventListener = function(type, listener, optionsOrCapture) {
if (blackListedEvents.has(type.toLowerCase())) {
log(`BLOCKED ${objectName}.addEventListener: ${type}`);
return undefined;
}
return originalAddEventListener.call(this, type, listener, optionsOrCapture);
};
patchToString(targetObject.addEventListener, originalAddEventListener);
}

function patchRemoveEventListener(targetObject, objectName) {
if (!targetObject || typeof targetObject.removeEventListener !== 'function') return;
const originalRemoveEventListener = targetObject.removeEventListener;
targetObject.removeEventListener = function(type, listener, optionsOrCapture) {
return originalRemoveEventListener.call(this, type, listener, optionsOrCapture);
};
patchToString(targetObject.removeEventListener, originalRemoveEventListener);
}

function spoofProperties(targetObject, propertiesToSpoof, objectName) {
if (!targetObject) return;
for (const prop in propertiesToSpoof) {
if (Object.prototype.hasOwnProperty.call(propertiesToSpoof, prop)) {
try {
Object.defineProperty(targetObject, prop, propertiesToSpoof[prop]);
} catch (e) {
error(`Failed to spoof ${objectName}.${prop}:`, e);
}
}
}
}

function nullifyEventHandlers(targetObject, eventHandlerNames, objectName) {
if (!targetObject) return;
eventHandlerNames.forEach(handlerName => {
try {
Object.defineProperty(targetObject, handlerName, {
get: () => undefined,
set: () => { log(`Attempt to set ${objectName}.${handlerName} blocked.`); },
configurable: true
});
} catch (e) {
error(`Failed to nullify ${objectName}.${handlerName}:`, e);
}
});
}
wangguo1230
几秒前
考试大家可以把手机打开,和大模型聊天来输入问题,获取到答案,或者可以用油猴脚本,我想把脚本放到这里面,但是放不开了
@ChengLuffy 我现在升级最新的了,好像是云盘同步导致的
@leconio 我关了好几次机了,都不行,我发现好像是我的 iCloud 云盘同步的事情
关于   ·   帮助文档   ·   自助推广系统   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   820 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 19ms · UTC 21:04 · PVG 05:04 · LAX 14:04 · JFK 17:04
Developed with CodeLauncher
♥ Do have faith in what you're doing.