// ==UserScript== // @name BgmSyncF // @version 0.2.2 // @namespace https://jirehlov.com // @description https://bgm.tv/group/topic/386575 // @include /^https?:\/\/(bgm\.tv|chii\.in|bangumi\.tv)\/user/.+/ // @author Jirehlov // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; // Check if the current page is under /user/username const isUserPage = /^\/user\/[^/]+$/.test(window.location.pathname); if (!isUserPage) { return; // Stop script execution if not on the user page } const limit = 50; let guess = 1000000; let totalItems = 0; const allData = []; let calculateButton; let buttonCounter = 0; const [username, page = '', subpage = ''] = (() => { const {pathname} = window.location; if (/^\/user/.test(pathname)) { return pathname.match(/\/user\/(\w+)\/?(\w+)?\/?(\w+)?/).slice(1, 4); } return [ '', '', '' ]; })(); if (!username) { throw new Error('Username is not detected'); } let countBothAbove7 = 0; let countRateAbove7 = 0; let subject_type = [ 1, 2, 3, 4, 6 ]; let subject_type_index = 0; let percentageBarDiv = null; const nameDiv = document.querySelector('.name'); const realname = nameDiv.querySelector('a').textContent; async function fetchData(offset, userAgent, cookie) { const url = `https://api.bgm.tv/v0/users/${ username }/collections?subject_type=${ subject_type[subject_type_index] }&type=2&limit=${ limit }&offset=${ offset }`; const headers = { 'Accept': 'application/json', 'User-Agent': userAgent, 'Cookie': cookie }; const response = await fetch(url, { headers }); const data = await response.json(); return data; } async function fetchAllData() { const userAgent = window.navigator.userAgent; const cookie = document.cookie; // Update button text to indicate calculation progress calculateButton.textContent = '计算中...'; for (let i = 0; i < subject_type.length; i++) { subject_type_index = i; const initialData = await fetchData(guess, userAgent, cookie); if ('description' in initialData && initialData.description.includes('equal to')) { totalItems = parseInt(initialData.description.split('equal to ')[1]); console.log(`Updated totalItems to: ${ totalItems }`); } for (let offset = 0; offset < totalItems; offset += limit) { const data = await fetchData(offset, userAgent, cookie); allData.push(...data.data); console.log(`Fetched ${ offset + 1 }-${ offset + limit } items...`); // Update button text with cyclic progress dots updateButtonText(offset); } } for (const item of allData) { const rate = parseFloat(item.rate || 0); const score = parseFloat(item.subject && item.subject.score !== undefined ? item.subject.score : 0); if (rate >= 7 || rate === 0) { countRateAbove7++; } if ((rate >= 7 || rate === 0) && score >= 7) { countBothAbove7++; } } // Update button text to indicate calculation is complete calculateButton.textContent = '计算全站同步率'; // Add userSynchronize div if not present let synchronizeDiv = document.querySelector('.userSynchronize'); if (!synchronizeDiv) { const userBoxDiv = document.querySelector('.user_box.clearit'); if (userBoxDiv) { synchronizeDiv = document.createElement('div'); synchronizeDiv.className = 'userSynchronize'; userBoxDiv.appendChild(synchronizeDiv); } } // Add the percentage bar directly to the existing userSynchronize div if (!percentageBarDiv) { const synchronizeDiv = document.querySelector('.userSynchronize'); if (synchronizeDiv) { percentageBarDiv = document.createElement('div'); synchronizeDiv.appendChild(percentageBarDiv); } } if (percentageBarDiv) { let syncRate = 0; if (countRateAbove7 > 0) { syncRate = countBothAbove7 / countRateAbove7 * 100; } const percentageBar = `