// ==UserScript== // @name 多设备微软积分上传 // @namespace AoJnnn // @description 上传微软必应积分存储到文本数据库 // @version 1.0.2 // @author AoJnnn // @grant GM_xmlhttpRequest // @grant GM_log // @grant GM_getValue // @connect bing.com // @connect textdb.online // @connect api.textdb.online // @license wtfpl // @crontab * 07-23 once * * // ==/UserScript== /* ==UserConfig== TextDB: APIKey: title: 文本数据库KEY description: API Key(6-60位,0-9a-zA-Z-_) type: text default: "" min: 6 max: 60 url: title: 数据库url:textdb.online/你的key default: "数据库不加密,请使用稍微复杂key (此栏不填)" ==/UserConfig== */ function getRewardsInfo() { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ url: "https://rewards.bing.com", onload(resp) { if (resp.status === 200) { resolve(resp); } else { reject(`请求失败,状态码:${resp.status}`); } }, onerror(e) { reject(`请求错误:${e}`); } }); }); } function getSubstring(inputStr, startStr, endStr) { const startIndex = inputStr.indexOf(startStr); if (startIndex === -1) return null; const endIndex = inputStr.indexOf(endStr, startIndex + startStr.length); if (endIndex === -1) return null; return inputStr.substring(startIndex + startStr.length, endIndex); } async function updateTextDB(apiKey, dataLine) { try { // 获取现有数据 const existingData = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", url: `https://textdb.online/${encodeURIComponent(apiKey)}`, onload(resp) { if (resp.status === 200) { resolve(resp.responseText); } else if (resp.status === 404) { resolve(""); // 新数据库 } else { reject(`获取数据失败:${resp.status}`); } }, onerror: (e) => reject(e) }); }); // 构建新数据 const newValue = existingData ? `${existingData}\n${dataLine}` : dataLine; // 更新数据库 const updateResult = await new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: "https://api.textdb.online/update/", headers: { "Content-Type": "application/x-www-form-urlencoded" }, data: `key=${encodeURIComponent(apiKey)}&value=${encodeURIComponent(newValue)}`, onload(resp) { try { resolve(JSON.parse(resp.responseText)); } catch(e) { reject("响应解析失败"); } }, onerror: (e) => reject(e) }); }); if (updateResult.status === 1) { GM_log(`数据存储成功:${updateResult.data.url}`); } else { GM_log("数据存储失败"); } } catch (error) { GM_log(`数据库操作失败:${error}`); } } (() => { getRewardsInfo().then(async resp => { const data = resp.responseText; const dashboard = JSON.parse(getSubstring(data, "var dashboard = ", ";\r")); // 解析邮箱 const parser = new DOMParser(); const doc = parser.parseFromString(resp.responseText, "text/html"); const targetDiv = doc.getElementById("mectrl_currentAccount_secondary"); const accountInfo = targetDiv?.textContent?.trim(); // 获取积分数据 const availablePoints = dashboard.userStatus.availablePoints; const dailyPoints = dashboard.userStatus.counters.dailyPoint[0]?.pointProgress; const apiKey = GM_getValue("TextDB.APIKey", ""); // 验证数据有效性 if (!accountInfo || !dailyPoints || !availablePoints || !apiKey) { const missing = []; if (!accountInfo) missing.push("邮箱"); if (!dailyPoints) missing.push("今日积分"); if (!availablePoints) missing.push("可用积分"); if (!apiKey) missing.push("API Key"); GM_log(`缺少必要数据:${missing.join(", ")},请检查key或者登录情况`); return; } // 构建新格式数据行 const date = new Date().toLocaleDateString("zh-CN", { year: 'numeric', month: '2-digit', day: '2-digit', timeZone: "Asia/Shanghai" }).replace(/\//g, '-'); const dataLine = `[${date}][${accountInfo}][${dailyPoints}]${availablePoints}`; // 格式修改点 // 更新数据库 await updateTextDB(apiKey, dataLine); }).catch(error => { GM_log(`获取积分失败:${error}`); }); })();