Better Hydro

Improve the Hydro interface with custom settings!

目前为 2024-08-22 提交的版本。查看 最新版本

// ==UserScript==
// @name         Better Hydro
// @namespace    http://tampermonkey.net/
// @version      2.5
// @description  Improve the Hydro interface with custom settings!
// @author       Cheerimy
// @match        *://hydro.ac/*
// @match        *://oiclass.com/*
// @match        *://www.oiclass.com/*
// @match        *://106.53.100.188:1000/*
// @icon         https://s21.ax1x.com/2024/08/22/pAi6KDP.png
// @grant        none
// @license GPLv3
// ==/UserScript==
(function() {
	'use strict';
	//Cookies 初始化函数
	function setCookieIfNotExists(name, value) {
		if (!document.cookie.split('; ').map(cookie => cookie.split('=')[0]).includes(name)) {
			document.cookie = `${name}=${encodeURIComponent(value)};path=/;expires=${new Date(Date.now()+365*24*60*60*1000).toUTCString()}`
		}
	}
	//获取 Cookies 模块
	function getCookie(name) {
		const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
		return match ? decodeURIComponent(match[2]) : null
	}
	//初始化 Cookies 模块
	function initCookies() {
		setCookieIfNotExists('browserupdateorg', 'pause');
		setCookieIfNotExists('background', 'https://api.imlazy.ink/mcapi/mcbg.php');
		setCookieIfNotExists('music', '//music.163.com/outchain/player?type=2&id=133567&auto=0&height=66');
		console.log('Cookies 模块加载成功!');
	}
	//处理 IDE 频率限制模块(Demo)
	function handleElement(element) {
		const initialHTML = element.innerHTML;
		const observer = new MutationObserver((mutationsList) => {
			for (const mutation of mutationsList) {
				if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
					const currentClass = mutation.target.className;
					if (currentClass.includes('disable')) {
						mutation.target.className = currentClass.replace('disable', 'enable');
						console.log('Class "disable" detected and changed to "enable".');

						// 更新 HTML 内容
						mutation.target.innerHTML = initialHTML;
						console.log('HTML updated to:', initialHTML);
					}
				}
			}
		});

		const config = {
			attributes: true,
			attributeFilter: ['class']
		};
		observer.observe(element, config);
	}
	//基本模块(欢迎栏与 UI 优化)
	function loadWelcomeMessage() {
		const username = Array.from(document.querySelectorAll('li[data-dropdown-target="#menu-nav-user"]')).map(item => item.querySelector('a')).find(link => link && link.textContent.trim() !== 'Language')?.textContent.trim() || 'Visitor';
		const panel = document.getElementById('panel');
		panel.style.backgroundImage = `url(${getCookie('background')})`;
		panel.style.backgroundSize = 'cover';
		panel.style.backgroundPosition = 'center';
		const style = document.createElement('style');
		style.textContent = `.section{border-radius:8px!important;opacity:0.75!important}.section:hover{opacity:1!important}.section__table-header{border-radius:8px 8px 0 0;opacity:0.75!important}.section__table-header:hover{opacity:1!important}`;
		document.head.append(style);
        const title=document.title;
        const name=title.split(" - ").pop().trim();
		const newHTML = `<div class="section visible"><div class="section__header"><h1 class="section__title">欢迎 ${username} 来到 ${name}!</h1><h1 class="section__title"style="text-align: end;">Let's Coding Now!</h1></div></div>`;
		const main = panel.querySelector('.main');
		const element = main.querySelector('div');
		element.insertAdjacentHTML('afterbegin', newHTML);
		console.log('基本模块加载成功!');
	}
	//音乐模块(播放音乐源音乐)
	function loadMusicPlayer() {
		const musicURL = getCookie('music');
		const musicHTML = `<div class="section side visible"><div class="section__header"><h1 class="section__title">一首歌曲</h1></div><div class="section__body typo"><iframe frameborder="no"border="0"marginwidth="0"marginheight="0"width="100%"height="86"src="${musicURL}"></iframe></div></div>`;
		const row = document.getElementById('panel').querySelector('.main').querySelector('.row');
		const divs = row.querySelectorAll(':scope > div');
		divs.forEach(div => {
			const className = div.className;
			if (className.includes('medium-3') && className.includes('columns')) {
				div.insertAdjacentHTML('afterbegin', musicHTML)
			}
		});
		console.log('音乐播放器加载成功!')
	}
	//个性化面板模块
	function loadSettingsPanel() {
		const settingDiv = document.createElement('div');
		settingDiv.id = 'setting';
		settingDiv.innerHTML = `<div class="section side visible"><div class="section__header"><h1 class="section__title">设置</h1></div><style>.input-group{display:flex;flex-direction:column;gap:10px;max-width:400px;margin:0 auto}.input-group label{font-size:14px;color:#333}.input-group input[type="text"]{padding:8px;font-size:14px;border:1px solid#ccc;border-radius:4px;width:100%;box-sizing:border-box}.input-group input[type="text"]::placeholder{color:#999}</style><div class="section__body typo"><div class="input-group"><label for="background-url">背景图片:</label><input type="text"id="background-url"placeholder="输入背景图片地址"><button id="save-background">保存背景</button><label for="music-url">音乐地址:</label><input type="text"id="music-url"placeholder="输入音乐播放器地址"><button id="save-music">保存音乐</button></div></div></div>`;
		const omnibarContent = document.getElementById('omnibar-content');
		omnibarContent.insertAdjacentElement('afterend', settingDiv);
		const setCookie = (name, value, days = 365) => {
			const expires = new Date(Date.now() + days * 24 * 60 * 60 * 1000).toUTCString();
			document.cookie = `${name}=${value};expires=${expires};path=/`
		};
		const saveInput = (inputId, cookieName) => {
			const input = document.getElementById(inputId);
			if (input) {
				setCookie(cookieName, input.value)
			} else {
				console.error(`Element#${inputId}not found`)
			}
		};
		document.getElementById('save-background').onclick = () => saveInput('background-url', 'background');
		document.getElementById('save-music').onclick = () => saveInput('music-url', 'music');
		console.log('个性化面板模块加载成功!')
	}
	//去除在线 IDE 提交频率限制模块
	function killidelimit() {
		const elements = document.querySelectorAll('.scratchpad__toolbar__submit');
		elements.forEach(handleElement);

		// 观察整个文档,以便检测未来添加的目标元素
		const observer = new MutationObserver((mutationsList) => {
			for (const mutation of mutationsList) {
				if (mutation.type === 'childList') {
					mutation.addedNodes.forEach((node) => {
						if (node.nodeType === 1) {
							// 如果节点是目标元素的后代,进行深度检查
							if (node.matches('.scratchpad__toolbar__item')) {
								handleElement(node);
							} else {
								// 深度检查子节点
								const descendantElements = node.querySelectorAll('.scratchpad__toolbar__item');
								descendantElements.forEach(handleElement);
							}
						}
					});
				}
			}
		});

		const config = {
			childList: true,
			subtree: true
		};
		observer.observe(document.body, config);
		console.log('IDE 优化模块开始运行!');
	}
	//尝试加载 Cookies 模块
	try {
		initCookies();
	} catch (error) {
		console.error('Cookies 模块加载失败,错误::', error);
	}
	//尝试加载基础模块
	try {
		loadWelcomeMessage();
	} catch (error) {
		console.error('基础模块加载失败,错误::', error);
	}
	//尝试加载音乐模块
	try {
		loadMusicPlayer();
	} catch (error) {
		console.error('音乐模块加载失败,错误::', error);
	}
	//尝试 IDE 优化模块
	try {
		killidelimit();
	} catch (error) {
		console.error('IDE 优化模块加载失败,错误::', error);
	}
	//尝试个性化面板面板模块
	setTimeout(function() {
		try {
			loadSettingsPanel();
		} catch (error) {
			console.error('个性化面板模块加载失败,错误::', error);
		}
	}, 2000);
})();