您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Clicks specified buttons across tabs using the BroadcastChannel API.
当前为
// ==UserScript== // @name Click buttons across tabs // @namespace https://musicbrainz.org/user/chaban // @version 1.0 // @tag ai-created // @description Clicks specified buttons across tabs using the BroadcastChannel API. // @author chaban // @license MIT // @match *://*.musicbrainz.org/* // @match *://magicisrc.kepstin.ca/* // @match *://magicisrc-beta.kepstin.ca/* // @grant GM.info // @grant GM_registerMenuCommand // ==/UserScript== (function () { 'use strict'; /** * @typedef {Object} SiteConfig * @property {string|string[]} hostnames - A single hostname string or an array of hostname strings. * @property {string|string[]} paths - A single path string or an array of path strings (can be partial matches). * @property {string} channelName - The name of the BroadcastChannel to use for this site. * @property {string} messageTrigger - The message data that triggers the button click. * @property {string} buttonSelector - The CSS selector for the button to be clicked. * @property {string} menuCommandName - The name to display in the Tampermonkey/Greasemonkey menu. */ /** * Configuration for different websites and their button click settings. * @type {SiteConfig[]} */ const siteConfigurations = [ { hostnames: 'musicbrainz.org', paths: ['/edit', '/add-cover-art'], channelName: 'mb_edit_channel', messageTrigger: 'submit-edit', buttonSelector: 'button.submit.positive[type="submit"]', menuCommandName: 'MusicBrainz: Submit Edit (All Tabs)' }, { hostnames: ['magicisrc.kepstin.ca','magicisrc-beta.kepstin.ca'], paths: ['/'], channelName: 'magicisrc_submit_channel', messageTrigger: 'submit-isrcs', buttonSelector: '[onclick^="doSubmitISRCs"]', menuCommandName: 'MagicISRC: Submit ISRCs (All Tabs)' } ]; const scriptName = GM.info.script.name; /** * Sends a message to the specified BroadcastChannel. * @param {string} channelName * @param {string} message */ function sendMessageToChannel(channelName, message) { try { new BroadcastChannel(channelName).postMessage(message); console.log(`[${scriptName}] Sent message "${message}" to channel "${channelName}".`); } catch (error) { console.error(`[${scriptName}] Error sending message to channel "${channelName}":`, error); } } /** * Initializes the BroadcastChannel listener for the current site if a match is found. * Also registers a menu command if `GM_registerMenuCommand` is available. */ function initializeBroadcastChannelListener() { const currentHostname = location.hostname; const currentPathname = location.pathname; for (const config of siteConfigurations) { const hostnames = Array.isArray(config.hostnames) ? config.hostnames : [config.hostnames]; const paths = Array.isArray(config.paths) ? config.paths : [config.paths]; const hostnameMatches = hostnames.some(hostname => currentHostname.endsWith(hostname)); const pathMatches = paths.some(path => currentPathname.includes(path)); if (hostnameMatches && pathMatches) { try { const channel = new BroadcastChannel(config.channelName); channel.addEventListener('message', (event) => { if (event.data === config.messageTrigger) { const btn = document.querySelector(config.buttonSelector); if (btn) { btn.click(); console.log(`[${scriptName}][${scriptName}] Button clicked for selector "${config.buttonSelector}" on channel "${config.channelName}".`); } else { console.warn(`[${scriptName}] Button with selector "${config.buttonSelector}" not found.`); } } }); console.log(`[${scriptName}] Listener active for channel "${config.channelName}".`); } catch (error) { console.error(`[${scriptName}] Error initializing BroadcastChannel for "${config.channelName}":`, error); } if (typeof GM_registerMenuCommand !== 'undefined' && config.menuCommandName) { GM_registerMenuCommand(config.menuCommandName, () => { sendMessageToChannel(config.channelName, config.messageTrigger); }); console.log(`[${scriptName}] Registered menu command "${config.menuCommandName}".`); } else { console.warn(`[${scriptName}] Couldn't register menu command "${config.menuCommandName}".`) } // Only activate one listener and register one command per tab for the first matching configuration return; } } } initializeBroadcastChannelListener(); })();