BgmSyncF

Fetch and process data from API

目前为 2023-08-31 提交的版本。查看 最新版本

// ==UserScript==
// @name         BgmSyncF
// @version      0.1
// @namespace    https://jirehlov.com
// @description  Fetch and process data from API
// @include      /^https?:\/\/(bgm\.tv|chii\.in|bangumi\.tv)\/user/.+/
// @author       Jirehlov
// @grant        none
// @license      MIT
// ==/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);
		}
		if (/^\/anime\/list/.test(pathname)) {
			return pathname.match(/\/anime\/list\/(\w+)/).slice(1, 2).concat('subject');
		}
		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;
	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);
			}
		}
		console.log('Data fetched and stored in memory');
		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 && 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 (synchronizeDiv) {
			const syncRate = countBothAbove7 / countRateAbove7 * 100;
			const percentageBar = `
                <h3>本页用户与全站的同步率</h3><small class="hot">/ ${ countBothAbove7 }个共同喜好</small><p class="bar"><span class="percent_text rr">${ syncRate.toFixed(2) }%</span> <span class="percent" style="width:${ syncRate.toFixed(2) }%"></span> </p>
            `;
			synchronizeDiv.innerHTML += percentageBar;
		}
		console.log(`Number of items with rate >= 7: ${ countRateAbove7 }`);
		console.log(`Number of items with both rate and score >= 7: ${ countBothAbove7 }`);
		console.log(`Sync rate: ${ (countBothAbove7 / countRateAbove7).toFixed(2) }`);
	}
	function updateButtonText(offset) {
		if (buttonCounter < 5) {
			calculateButton.textContent = '计算中' + '.'.repeat(buttonCounter);
			buttonCounter++;
		} else {
			calculateButton.textContent = '计算中.';
			buttonCounter = 1;
		}
	}
	function addButton() {
		const link = document.createElement('a');
		link.href = 'javascript:void(0)';
		link.textContent = '计算全站同步率';
		link.className = 'chiiBtn';
		link.addEventListener('click', fetchAllData);
		const actionsDiv = document.querySelector('.nameSingle > .inner > .actions');
		actionsDiv.appendChild(link);
		calculateButton = link;	// Store the reference to the button
	}
	addButton();
}());

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址