巴哈姆特動畫瘋小幫手:封面圖 & 自動開始 & 留言連結 & 彈幕熱圖

幫巴哈姆特動畫瘋加上封面 & 自動播放 & 留言區的直連連結 & 彈幕熱圖

当前为 2023-05-20 提交的版本,查看 最新版本

// ==UserScript==
// @name         巴哈姆特動畫瘋小幫手:封面圖 & 自動開始 & 留言連結 & 彈幕熱圖
// @namespace    http://tampermonkey.net/
// @version      1.3.5
// @description  幫巴哈姆特動畫瘋加上封面 & 自動播放 & 留言區的直連連結 & 彈幕熱圖
// @author       Rplus
// @match        https://ani.gamer.com.tw/animeVideo.php?sn=*
// @license      WTFPL
// @grant        GM_registerMenuCommand
// @grant        GM.setValue
// @grant        GM.getValue
// ==/UserScript==

(async function() {
	let options = await GM.getValue('options');
	if (!options) {
		options = {
			cover: true,
			autostart: true,
			permalink: true,
			heatmap: true,
			heatmapVisibility: true,
		};
		GM.setValue('options', options);
	};

	let optionsText = {
		cover: '封面圖',
		autostart: '自動開始',
		permalink: '留言連結',
		heatmap: '彈幕熱圖',
	};

	function triggerConfig(type) {
		options[type] = !options[type];
		GM.setValue('options', options);
	}

	GM_registerMenuCommand(getMenuText('cover'), () => triggerConfig('cover'), 'C');
	GM_registerMenuCommand(getMenuText('autostart'), () => triggerConfig('autostart'), 'A');
	GM_registerMenuCommand(getMenuText('permalink'), () => triggerConfig('permalink'), 'P');
	GM_registerMenuCommand(getMenuText('heatmap'), () => triggerConfig('heatmap'), 'H');

	function getMenuText(type) {
		return `${options[type] ? '✅ 已啟用' : '❎ 已停用'}:${optionsText[type]}`;
	}

	window.addEventListener('load', init);

	function init() {
		if (options.cover) {
			// insert poster
			document.querySelector('h1')?.insertAdjacentHTML('afterbegin', `
				<a href="${unsafeWindow.animefun.poster}">
					<img src="${unsafeWindow.animefun.poster}" style="float: left; height: 2em; margin-top: 4px; margin-right: 8px;" />
				</a>`);

			// insert published time
			let timeTag = document.querySelector('.anime_info_detail p');
			let time = timeTag?.textContent.split(':')?.[1];
			if (time) {
				timeTag.textContent += ` (${getRelatedDays(time)}天前)`;
			}
		}

		// latest duration
		// animefun.breakPoint.breakPoint

		if (options.autostart) {
			// auto start when it is not comment permalink
			if (location.search.indexOf('pcid') === -1) {
				checkReady();
			}
		}

		// observer comments to add permalink
		if (options.permalink) {
			let ob = new MutationObserver(checkCmtBoxBeMore);
			ob.observe(document.getElementById('w-post-box'), {
				childList: true,
				subtree: true,
			});
		}

		// danmu heatmap
		if (options.heatmap) {
			danmuHelper();
		}
	}

	function getRelatedDays(time = new Date()) {
		return ((new Date() - new Date(time))/(1000*60*60*24)).toFixed();
	}

	function checkReady() {
		setTimeout(() => {
			console.log(111, unsafeWindow.adult);
			if (unsafeWindow.AnimeRoute && unsafeWindow.adult && unsafeWindow.animefun) {
				unsafeWindow.adult.click();
			} else {
				checkReady();
			}
		}, 1000)
	}

	function genCmtLinks() {
		[...document.querySelectorAll('span.reply_time')].forEach(node => {
			let a = node.nextElementSibling;
			if (node.querySelector('a') || !a) {
				return;
			}
			let config = JSON.parse(a.dataset?.tippyMenuComment);
			let qs = new URLSearchParams({
				sn: new URLSearchParams(location.search).get('sn'),
				pcid: config.pid || config.cid,
			});
			if (config.pid) {
				qs.append('cid', config.cid);
			}
			let url = `https://ani.gamer.com.tw/animeVideo.php?` + qs.toString()
			node.innerHTML = `<a href="${url}"># ${node.textContent}</a>`
		});
	}

	function checkCmtBoxBeMore(mutations) {
		console.log('checkCmtBoxBeMore');
		genCmtLinks();
		// mutations.forEach((mutation) => {
		// 	console.log('checkCmtBoxBeMore mutation');
		// 	console.log(222, 'checkCmtBoxsBeMore', mutation.target.querySelectorAll('.c-reply__item').length);
		// });
	}

	function danmuHelper() {
		jQuery.ajax({
			url: '/ajax/danmuGet.php',
			data: {
				sn: animefun.videoSn
			},
			method: 'POST',
			dataType: 'json',
		})
		.then(data => {
			let danmu = {};
			danmu.length = data.length;
			danmu.duration = data[danmu.length - 1].time;
			danmu.byTime = data;
			// danmu.byUser = data.reduce((all, i) => {
			// 	let uid = i.userid;
			// 	if (!all[uid]) { all[uid] = []; }
			// 	all[uid].push(i);
			// 	return all;
			// }, {});

			danmuAnal(danmu);
		})
	}

	function danmuAnal(danmu) {
		document.querySelector('#ani-tab-content-2 .ani-setting-item').insertAdjacentHTML('afterend', `
			<div class="ani-setting-item ani-flex">
				<div class="ani-setting-label">彈幕熱圖</div>
				<div class="ani-set-flex-right">
					<div class="ani-checkbox">
						<label class="ani-checkbox__label">
							<input type="checkbox" id="danmu-heatmap-ckbox" ${options.heatmapVisibility ? 'checked' : ''} />
							<div class="ani-checkbox__button"></div>
						</label>
					</div>
				</div>
			</div>
		`);

		document.querySelector('#danmu-heatmap-ckbox').addEventListener('change', (e) => {
			document.querySelector('.danmu-heatmap').hidden = !e.target.checked;
			triggerConfig('heatmapVisibility');
		});

		// heatmap
		let dots = `<div class="danmu-heatmap" ${options.heatmapVisibility ? '' : 'hidden'}>` + danmu.byTime.map(i => {
			return `<i data-time="${i.time / 10}" style="--l: ${i.time / danmu.duration}" title="${i.text}"></i>`;
		}).join('') + '</div>';
		let dots_style = `<style>
			.danmu-heatmap {
				position: absolute;
				left: 0;
				right: 0;
				top: 100%;
				z-index: 1;
				height: 1em;
				overflow: hidden;
				background-color: #000;
			}
			.danmu-heatmap i {
				position: absolute;
				left: calc(var(--l, 1) * 100%);
				width: 0.5em;
				height: 1em;
				background: #fff;
				opacity: var(--dh-op, ${danmu.length > 1000 ? 0.05 : 0.1});
			}
			.danmu-heatmap i:hover {
				opacity: .8;
				background: #ff0;
			}
		</style>`;
		let videoframe = document.querySelector('.videoframe');
		videoframe.style.position = 'relative';
		videoframe.insertAdjacentHTML('beforeend', dots + dots_style);

		videoframe.querySelector('.danmu-heatmap').addEventListener('click', (e) => {
			if (e.target.tagName !== 'I') { return; }
			jumpVideoTime(+e.target.dataset?.time);
		})
	}

	function jumpVideoTime(time = 0) {
		document.getElementById('ani_video_html5_api').currentTime = time;
	}
})();

QingJ © 2025

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