Last active
April 11, 2023 19:21
-
-
Save rynomad/c2ceac925a9572bb3924b943968529d2 to your computer and use it in GitHub Desktop.
A ViolentMonkey userscript using BrokerClient
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name My Userscript | |
// @namespace http://example.com/ | |
// @version 1.0 | |
// @description A testrunner for VM userscripts | |
// @include * | |
// @grant GM.addStyle | |
// @grant GM.deleteValue | |
// @grant GM.getValue | |
// @grant GM.listValues | |
// @grant GM.setValue | |
// @grant GM.xmlHttpRequest | |
// @grant GM.notification | |
// @grant GM.openInTab | |
// @grant GM.getResourceUrl | |
// @grant GM.setClipboard | |
// @grant GM.info | |
// @grant GM.registerMenuCommand | |
// @grant GM.unregisterMenuCommand | |
// @grant GM.download | |
// @grant GM.getTab | |
// @grant GM.saveTab | |
// @grant GM.getTabs | |
// @grant GM.connect | |
// @grant GM.setIcon | |
// @grant GM.fetch | |
// @grant GM.communicator | |
// @inject-into content | |
// ==/UserScript== | |
(function() { | |
'use strict'; | |
function isUserscript(code) { | |
const regex = /\/\/\s?==UserScript==[\s\S]*\/\/\s?==\/UserScript==/; | |
return regex.test(code); | |
} | |
function getIncludePatterns(code) { | |
const regex = /\/\/\s?@(include|match)\s+(.*)/g; | |
const patterns = []; | |
let match; | |
while ((match = regex.exec(code)) !== null) { | |
patterns.push(match[2]); | |
} | |
return patterns; | |
} | |
function isMatchPattern(url, pattern) { | |
if (pattern.includes('*')) { | |
// Handle @include patterns with wildcards | |
const regex = new RegExp( | |
'^' + | |
pattern | |
.replace(/[-[\]{}()+!<=:?.\\^$|#\s,]/g, '\\$&') | |
.replace(/\*/g, '.*') | |
.replace(/\?/g, '.') + | |
'$' | |
); | |
return regex.test(url); | |
} else { | |
// Handle @match patterns | |
const matchPatternToRegExp = (pattern) => { | |
const escapeRegExp = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | |
return new RegExp( | |
'^' + | |
escapeRegExp(pattern) | |
.replace(/\\\*/g, '.*') | |
.replace(/\\\?/g, '.') + | |
'$' | |
); | |
}; | |
return matchPatternToRegExp(pattern).test(url); | |
} | |
} | |
function createIcon(iconType, onClick) { | |
const icon = document.createElement('div'); | |
icon.textContent = iconType === 'smiley' ? '😊' : '⚠️'; | |
icon.style.position = 'fixed'; | |
icon.style.top = '10px'; | |
icon.style.right = iconType === 'smiley' ? '50px' : '10px'; | |
icon.style.fontSize = '24px'; | |
icon.style.cursor = 'pointer'; | |
icon.style.zIndex = '99999'; | |
icon.addEventListener('click', onClick); | |
return icon; | |
} | |
function handleTestScript(code, sendResponse) { | |
console.log(code, location.href) | |
if (!isUserscript(code)) { | |
console.log('ignoring non-userscript', code) | |
return; | |
} | |
const includePatterns = getIncludePatterns(code); | |
if (!includePatterns.some((pattern) => isMatchPattern(location.href, pattern))) { | |
console.log('doesnt match page') | |
return; | |
} | |
try { | |
const executeScript = new Function('GM', code); | |
executeScript(GM); | |
const smileyIcon = createIcon('smiley', () => { | |
smileyIcon.remove(); | |
alertIcon.remove(); | |
sendResponse({ | |
success: true, | |
message: 'Script executed successfully.', | |
}); | |
}); | |
const alertIcon = createIcon('alert', () => { | |
smileyIcon.remove(); | |
alertIcon.remove(); | |
const userFeedback = prompt('Please describe the problem:'); | |
sendResponse({ | |
success: false, | |
message: userFeedback, | |
}); | |
}); | |
document.body.appendChild(smileyIcon); | |
document.body.appendChild(alertIcon); | |
} catch (error) { | |
console.log(error, code) | |
sendResponse({ | |
success: false, | |
message: error.message, | |
stackTrace: error.stack, | |
}); | |
} | |
} | |
const brokerClient = GM.communicator(); | |
brokerClient.registerHandler('TEST_SCRIPT', handleTestScript); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment