Greasy Fork

Greasy Fork is available in English.

BgmSyncF

https://bgm.tv/group/topic/386575

当前为 2023-08-31 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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
// ==/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 = `
            <h3>${ realname }与全站的同步率</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>
        `;
			percentageBarDiv.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();
}());