您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
默认关闭回收功能,徽章按类型排序,保存/还原徽章顺序,勋章一键续期,勋章收益统计功能
当前为
// ==UserScript== // @name GM论坛勋章百宝箱 // @namespace http://tampermonkey.net/ // @version 1.25 // @description 默认关闭回收功能,徽章按类型排序,保存/还原徽章顺序,勋章一键续期,勋章收益统计功能 // @match https://www.gamemale.com/wodexunzhang-showxunzhang.html?action=my // @grant GM_addStyle // @license MIT // ==/UserScript== // TODO所有勋章一键续,剧情勋章一键续期 // 1.25版本测试自动更新情况 (function () { 'use strict'; // 徽章按类型排序和顺序调整 // 如果想改动默认顺序就改这里 const orderList = ['游戏男从', '真人男从', '女从', '装备', '资产', '宠物', '板块', '天赋', '赠礼', '咒术', '剧情', '其他'] let categoriesData = {} // 从我的日志里,把最新的勋章分类数据拿过来 fetchBlogArticle().then(articleArray => { categoriesData = articleArray; // 此处直接复制粘贴代码不想思考了 let result = { "游戏男从(10)": "", "真人男从(8)": "", "女从(4)": "", "装备(11)": "", "资产(16)": "", "宠物(7)": "", "板块(4)": "", "天赋(4)": "", "赠礼": "", "咒术": "", "剧情": "", "其他": "" }; let categories = { "youxi": "游戏男从(10)", "zhenren": "真人男从(8)", "Maid": "女从(4)", "Equip": "装备(11)", "Asset": "资产(16)", "Pet": "宠物(7)", "Forum": "板块(4)", "Skill": "天赋(4)", "Gift": "赠礼", "Spell": "咒术", "Plot": "剧情" }; let myblok = document.getElementsByClassName("myblok"); for (let blok of myblok) { let regex = /alt="(.+?)"/; let matches = blok.innerHTML.match(regex) if (matches) { let match = matches[1]; let found = false; for (let key in categories) { if (categoriesData[key].indexOf(match) >= 0) { result[categories[key]] += match + ","; found = true; break; } } if (!found) { result["其他"] += match + ","; } } } let txt = "" for (let key in result) { txt += key + " : (" + (result[key].split(",").length - 1) + ") " + result[key].slice(0, -1) + "<br>" } function qiwang(pattern) { let myblok = document.getElementsByClassName("myblok") let result = { "金币": 0, "血液": 0, "咒术": 0, "知识": 0, "旅程": 0, "堕落": 0, "灵魂": 0 }; for (let blok of myblok) { if (blok.innerText.indexOf("已寄售") > 0) { continue } let regex = /几率 (\d+)%/i; let matches = blok.innerText.match(regex) // let nameRegex=/\t(.+?)\n/; // let nameMatch=blok.innerText.replaceAll(" ","").match(nameRegex) if (matches) { let prob = matches[1] let symbols = Array.from(blok.innerText.matchAll(pattern), m => m[2]); let isSame = symbols.every(function (element) { return element === symbols[0]; }); // console.log(nameMatch[1]+isSame) matches = blok.innerText.matchAll(pattern); for (let match of matches) { let score = prob / 100 * parseInt(match[2] + match[3]) result[match[1]] = Number((result[match[1]] + score).toFixed(4)); } } } return result } function getCoin() { let coin = 0; let myblok = document.getElementsByClassName("myblok") for (let blok of myblok) { let regex = /金币\s+(\d+)寄售/i; let matches = blok.innerText.match(regex) if (matches) { coin += parseInt(matches[1]) } } return coin } function showValid() { let myblok = document.getElementsByClassName("myblok") for (let blok of myblok) { let regex = /\s+(.+?分)\d{1,2}秒有效期/i; let matches = blok.innerText.match(regex) if (matches) { let newP = document.createElement("p"); let newContent = document.createTextNode(matches[1]); newP.appendChild(newContent); blok.firstElementChild.appendChild(newP) } } } let huiPattern = /回帖\s+(.+?) ([+-])(\d+)/gi let huiResult = qiwang(huiPattern) let hui = "回帖期望 " for (let key in huiResult) { hui += key + ":" + huiResult[key] + " " } let faPattern = /发帖\s+(.+?) ([+-])(\d+)/gi let faResult = qiwang(faPattern) let fa = "发帖期望 " for (let key in faResult) { fa += key + ":" + faResult[key] + " " } let coin = "寄售最大价格总和:" + getCoin() // document.head.innerHTML += '<style>.myfldiv {display:flex;flex-wrap:wrap;align-items:flex-start;}</style>'; // 找到元素并更新其内容 var badgeOrderElement = document.querySelector(".badge-order"); if (badgeOrderElement) { badgeOrderElement.innerHTML = "<p>" + hui + "<br>" + fa + "<br>" + coin + "<br><br>" + txt +"</p>"; } showValid() }) const linkList = { "游戏男从": "youxi", "真人男从": "zhenren", "女从": "Maid", "装备": "Equip", "资产": "Asset", "宠物": "Pet", "板块": "Forum", "天赋": "Skill", "赠礼": "Gift", "咒术": "Spell", "剧情": "Plot", "其他": "other" } // 创建一个新的div元素用于管理徽章 const badgeManagerDiv = document.createElement('div'); badgeManagerDiv.className = 'badge-manager'; badgeManagerDiv.innerHTML = '<h2>徽章管理</h2><p>这里可以管理您的徽章。</p><div class="badge-manager-button"><div>'; const badgeOrderDiv = document.createElement('div'); badgeOrderDiv.className = 'badge-order'; badgeOrderDiv.innerHTML = '正在计算您拥有的徽章类型和价值,请稍等。。。' // 获取目标div并在其前面插入新创建的div const targetDiv = document.querySelector('.my_fenlei'); targetDiv.parentNode.insertBefore(badgeManagerDiv, targetDiv); badgeManagerDiv.appendChild(badgeOrderDiv) // targetDiv.parentNode.insertBefore(badgeOrderDiv, badgeManagerDiv); // 在这里添加您的自定义样式 const customStyles = ` .badge-manager { background-color: #f0f0f0; /* 背景颜色 */ padding: 10px; /* 内边距 */ margin-bottom: 10px; /* 底部外边距 */ border: 1px solid #ccc; /* 边框 */ font-family: Arial, sans-serif; /* 字体 */ color: #333; /* 字体颜色 */ } .badge-manager h2 { margin: 0; /* 去掉默认的外边距 */ font-size: 18px; /* 标题字体大小 */ color: #007BFF; /* 标题颜色 */ } .badge-manager p { margin: 5px 0; } .custom-button { padding: 5px 10px; margin-right: 5px; background-color: #007BFF; /* 按钮背景颜色 */ color: white; /* 字体颜色 */ border: none; /* 去掉默认边框 */ border-radius: 5px; /* 圆角 */ cursor: pointer; /* 鼠标悬停时显示手型 */ } .custom-button:hover { background-color: #0056b3; /* 悬停时的背景颜色 */ } `; // 使用GM_addStyle函数将样式插入到页面中 GM_addStyle(customStyles); // 添加功能按钮 function createLink(label, onClickMethod) { const button = document.createElement('button'); button.className = 'custom-button'; button.textContent = label; button.onclick = (event) => { event.preventDefault(); // 阻止默认行为 onClickMethod(); // 调用自定义方法 }; // 将链接添加到页面的 body 中 const my_biaoti = document.querySelector('.badge-manager-button') my_biaoti.appendChild(button); } // 默认关闭回收功能 // @params hide none是隐藏 block是显示 createLink('显示/隐藏回收按钮', setHuiShou) setHuiShou('init') function setHuiShou(init) { document.querySelectorAll('button.pn').forEach(element => { if (element.innerText == '回收') { // 初始化干掉 if (init) { element.style.display = "none"; element.parentElement.style.display = "none"; } else { // 检查元素的display属性 if (element.style.display === "none" || getComputedStyle(element).display === "none") { // 如果是none,则显示元素和其父元素 element.style.display = "inline"; element.parentElement.style.display = "inline"; // 显示父元素 // alert('回收按钮已显示') } else { // 否则隐藏元素和其父元素 element.style.display = "none"; element.parentElement.style.display = "none"; // 隐藏父元素 // alert('回收按钮已隐藏') } } } }) } // 勋章排序 createLink('按照类型排序', kindOrder) function kindOrder() { // 获取所有匹配的元素 const elements = document.querySelectorAll('.my_fenlei .myblok'); const elementsArray = Array.from(elements); // 使用 map 函数处理每个元素 const xunzhangList = elementsArray.map(myBlock => { const key = myBlock.getAttribute('key'); const nameElement = myBlock.querySelector('p b'); // 找到包含名称的 <b> 标签 const name = nameElement ? nameElement.textContent : ''; return { [name]: key } }) // 使用 reduce 合并字典 const mergedDict = xunzhangList.reduce((acc, curr) => { return { ...acc, ...curr }; }, {}); // 填补未知的勋章 const mergedDictKey = Object.keys(mergedDict) const allCategoriesData = Object.values(categoriesData).flat(); categoriesData.other = findUniqueValues(mergedDictKey, allCategoriesData) function findUniqueValues(a, b) { // 将数组 b 转换为一个 Set,以提高查找效率 const setB = new Set(b); // 过滤出在 a 中且不在 b 中的值 const uniqueValues = a.filter(value => !setB.has(value)); return uniqueValues; } const previousInput = localStorage.getItem('sortInput') || orderList.join(' '); // 弹出输入框,默认值为之前的内容 const userInput = prompt("您正在进行一键排序,是否需要修改排序顺序(用空格分隔):", previousInput); // 如果用户输入了内容 if (userInput !== null) { // 保存到 localStorage localStorage.setItem('sortInput', userInput); // 将输入的内容转换为数组并进行排序 const sortedArray = userInput.split(' ').map(item => item.trim()); const order1 = sortedArray.map(e => categoriesData[linkList[e]]) const order2 = [].concat(...order1); const result = order2.map(key => mergedDict[key]).filter(value => value !== undefined); postOrder(result) // 输出排序后的结果 // alert("排序后的结果:\n" + sortedArray.join(', ')); } } //新增按钮保存/还原勋章顺序 createLink('保存勋章顺序', saveKeysOrder) createLink('还原勋章顺序', loadKeysOrder) // 保存勋章顺序 function saveArrayToLocalStorage(key, array) { localStorage.setItem(key, JSON.stringify(array)); } // 从本地存储获取数组 function getArrayFromLocalStorage(key) { const storedArray = localStorage.getItem(key); return storedArray ? JSON.parse(storedArray) : null; } // 从本地存储删除数组 function removeArrayFromLocalStorage(key) { localStorage.removeItem(key); } // 获取所有具有指定类名的div元素 function getKeysFromDivs(className) { // 使用querySelectorAll获取所有带有该类的div const divs = document.querySelectorAll(`div.${className}`); // 提取每个div的key属性并返回数组 const keys = Array.from(divs).map(div => div.getAttribute('key')); return keys.join(','); } // 保存勋章顺序 function saveKeysOrder() { const keys = getKeysFromDivs('myblok') saveArrayToLocalStorage('keyOrder', keys) alert('保存成功') } function loadKeysOrder() { const keys = getArrayFromLocalStorage('keyOrder') postOrder(keys) } function postOrder(newOrder) { const url = 'https://www.gamemale.com/plugin.php?id=wodexunzhang:showxunzhang' // 创建FormData对象 const formData = new FormData(); const data = { newOrder, action: 'newOrder' } // 将数据添加到formData for (const key in data) { if (data.hasOwnProperty(key)) { formData.append(key, data[key]); } } // 使用fetch发送POST请求 fetch(url, { method: 'POST', body: formData, }) .then(response => { // alert('还原勋章顺序成功,点击确认后刷新页面') location.reload() if (!response.ok) { throw new Error('Network response was not ok'); } // return response.json(); // 或根据需要返回其他格式 }) .then(data => { console.log('Success:', data); }) .catch(error => { console.error('Error:', error); }); } // 勋章一键续期 // 疑似存在扣了咒术不会增加时长的bug,暂停开发。似乎是编号的问题,再观察一下 oneClickRenew() function oneClickRenew() { // 获取所有的按钮元素 const buttons = document.querySelectorAll('button.pn'); buttons.forEach(button => { // 检查onclick属性是否包含'可续期' if (button.innerText == '可续期') { // 创建新的一键续期按钮 const newButton = document.createElement('button'); const userMedalid = button.getAttribute('onclick').match(/\d+/g)[0] const titleElement = button.closest('.myimg').querySelector('p[title]'); const name = titleElement.getAttribute('title'); newButton.type = 'button'; newButton.className = 'pn'; newButton.innerHTML = '<em>一键续期</em>'; newButton.onclick = function () { // 弹出提示框询问续期多少次 const times = prompt(`您正在为【${name}】一键续期,请输入续期次数:`, "1"); const count = parseInt(times); // 判断输入是否合法 if (isNaN(count) || count <= 0) { alert("请输入有效的次数!"); return; } repeatRequest(count, 5000, userMedalid); }; // 创建一个<p>标签来包裹新按钮 const p = document.createElement('p'); p.appendChild(newButton); // 将<p>标签插入到原按钮的父元素的父元素后面,并紧贴 button.parentNode.insertAdjacentElement('afterend', p); } }); function postRenew(userMedalid) { if (!userMedalid) return const url = 'https://www.gamemale.com/plugin.php?id=wodexunzhang:showxunzhang' // 创建FormData对象 const formData = new FormData(); const formhash = document.querySelector('input[name="formhash"]').value const data = { formhash, action: 'xuqi', jishoujiage: '', userMedalid } // 将数据添加到formData for (const key in data) { if (data.hasOwnProperty(key)) { formData.append(key, data[key]); } } return fetch(url, { method: 'POST', body: formData, }) } // 模拟网络请求的函数 async function makeRequest(userMedalid) { try { // 假设这是一个真实的 API URL const response = await postRenew(userMedalid) // if (!response.ok) { // throw new Error('网络请求失败'); // } const data = await response.text(); console.log("请求已发送:", data); // 打印响应数据 return data; // 返回请求结果 } catch (error) { console.error('请求出错:', error); throw error; // 抛出错误以供调用者处理 } } // 显示提示信息的函数 function showMessage(message) { const messageDiv = document.createElement('div'); messageDiv.textContent = message; messageDiv.style.position = 'fixed'; messageDiv.style.top = '10px'; messageDiv.style.right = '10px'; messageDiv.style.backgroundColor = '#4caf50'; // 绿色背景 messageDiv.style.color = 'white'; messageDiv.style.padding = '10px'; messageDiv.style.zIndex = '1000'; document.body.appendChild(messageDiv); // 自动消失 setTimeout(() => { document.body.removeChild(messageDiv); }, 3000); // 3秒后消失 } // 重复请求的函数 async function repeatRequest(times, interval, userMedalid) { for (let i = 0; i < times; i++) { try { const result = await makeRequest(userMedalid); // 等待请求完成 showMessage(`共需${times}次,已经请求 ${i + 1} 次`); } catch (error) { showMessage(`请求 ${i + 1} 失败: ${error.message}`); } // 等待间隔 if (i < times - 1) { await new Promise(resolve => setTimeout(resolve, interval)); // 等待间隔 } } showMessage('一键续期已完成,3秒后刷新页面'); setTimeout(() => { location.reload() }, 3000); // 3秒后消失 // console.log("所有请求已完成"); } } // 新增从日志里获取勋章分类的函数 async function fetchBlogArticle() { const url = 'https://www.gamemale.com/home.php?mod=space&uid=723150&do=blog&quickforward=1&id=111238'; try { const response = await fetch(url); if (!response.ok) { throw new Error('网络错误:' + response.status); } const html = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); // 假设 blog_article 是一个 id 或者 class const articleElement = doc.querySelector('#blog_article'); // 根据实际情况调整选择器 if (articleElement) { const articleText = articleElement.textContent || articleElement.innerText; // 尝试解析为 JSON try { const articleArray = JSON.parse(articleText); return articleArray; } catch (jsonError) { console.error("无法解析为 JSON:", jsonError); return []; // 返回空数组或处理错误的逻辑 } } else { console.log('未找到 blog_article 元素'); return []; // 返回空数组或处理未找到元素的逻辑 } } catch (error) { console.error('发生错误:', error); return []; // 返回空数组或处理错误的逻辑 } } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址