您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Get information from Greasy Fork and do actions in it.
当前为
此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.greatest.deepsurf.us/scripts/445697/1237548/Greasy%20Fork%20API.js
// ==UserScript== // @name Greasy Fork API // @namespace - // @version 2.0.0 // @description Get information from Greasy Fork and do actions in it. // @author NotYou // @license LGPL-3.0 // @connect greatest.deepsurf.us // @grant GM_xmlhttpRequest // @grant GM_openInTab // ==/UserScript== class GreasyFork { constructor() { if(location.host === 'greatest.deepsurf.us' || location.host === 'sleazyfork.org') { this.host = location.host return } throw new Error('Invalid instance initialization location, host is not valid.') } static get INVALID_ARGUMENT_ERROR() { return 'Argument "{0}" is not valid' } static get PARSING_ERROR() { return 'Unexpected parsing error, "{0}"' } static get INVALID_PAGE_ERROR() { return 'Current page is not valid' } static __format(str, ...args) { let result = str for (let i = 0; i < args.length; i++) { const arg = args[i] result = result.replace(new RegExp(`\\{${i}\\}`, 'g'), arg) } return result } static __isId(id) { return typeof id === 'string' && /^\d+$/.test(id) } static get languages() { return [ 'ar', 'bg', 'cs', 'da', 'de', 'el', 'en', 'eo', 'es', 'fi', 'fr', 'fr-CA', 'he', 'hu', 'id', 'it', 'ja', 'ka', 'ko', 'nb', 'nl', 'pl', 'pt-BR', 'ro', 'ru', 'sk', 'sr', 'sv', 'th', 'tr', 'uk', 'ug', 'vi', 'zh-CN', 'zh-TW' ] } static get version() { return '2.0.0' } static parseScriptNode(node) { if (!(node instanceof HTMLElement) || !node.dataset.scriptId) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'node')) } const { scriptId, scriptName, scriptAuthors, scriptDailyInstalls, scriptTotalInstalls, scriptRatingScore, scriptCreatedDate, scriptUpdatedDate, scriptType, scriptVersion, sensitive, scriptLanguage, cssAvailableAsJs } = node.dataset const ratingsNode = node.querySelector('dd.script-list-ratings') let ratings = {} if(ratingsNode) { const ratingsGood = Number(ratingsNode.querySelector('.good-rating-count').textContent) const ratingsOk = Number(ratingsNode.querySelector('.ok-rating-count').textContent) const ratingsBad = Number(ratingsNode.querySelector('.bad-rating-count').textContent) ratings = { ratingsGood, ratingsOk, ratingsBad } } return Object.assign({ scriptId, scriptName, scriptAuthors: JSON.parse(scriptAuthors), scriptDailyInstalls: Number(scriptDailyInstalls), scriptTotalInstalls: Number(scriptTotalInstalls), scriptRatingScore: Number(scriptRatingScore), scriptCreatedDate, scriptUpdatedDate, scriptType, scriptVersion, sensitive: sensitive === 'true', scriptLanguage, cssAvailableAsJs: cssAvailableAsJs === 'true', node }, ratings) } static parseScriptMetadata(code) { if (typeof code !== 'string') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'code')) } const reScriptMetadata = /\/\/ ==UserScript==\n(.*?[\s\S]+)\n\/\/ ==\/UserScript==/ const matched = code.match(reScriptMetadata) if (!Boolean(matched)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'code')) } const metadataResponse = {} const metadata = matched[1] const metadataChunks = metadata.split('\n') for (let i = 0; i < metadataChunks.length; i++) { const metadataChunk = metadataChunks[i] try { const { metaKey, metaValue } = metadataChunk.match(/\/\/ @(?<metaKey>[a-zA-Z\-\d\:]+)\s+(?<metaValue>.+)/).groups metadataResponse[metaKey] = metaValue } catch(error) { throw new Error(GreasyFork.__format(GreasyFork.PARSING_ERROR, error)) } } return metadataResponse } static getScriptData(id) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts/${id}.json`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { return rej(err) } }) }) } static getScriptCode(id) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts/${id}/code/userscript.user.js`, onload: response => { const code = response.responseText return res(code) }, onerror: err => { return rej(err) } }) }) } static getScriptHistory(id) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts/${id}/versions.json`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { return rej(err) } }) }) } static getScriptStats(id) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts/${id}/stats.json`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { return rej(err) } }) }) } static getScriptSet(id, page = 1) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } if (typeof page !== 'number') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'page')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts.json?set=${id}&page=${page}&filter_locale=0`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { return rej(err) } }) }) } static getUserData(id) { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/users/${id}.json`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { return rej(err) } }) }) } static searchScripts(query, page = 1) { if (typeof query !== 'string') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'query')) } if (typeof page !== 'number') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'page')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/scripts.json?q=${query}&page=${page}`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { console.error(err) return rej([]) } }) }) } static searchUsers(query, page = 1) { if (typeof query !== 'string') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'query')) } if (typeof page !== 'number') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'page')) } return new Promise((res, rej) => { GM_xmlhttpRequest({ url: `https://greatest.deepsurf.us/users.json?q=${query}&page=${page}`, onload: response => { const data = JSON.parse(response.responseText) return res(data) }, onerror: err => { console.error(err) return rej([]) } }) }) } static installScript(id, type = 'js') { if (!GreasyFork.__isId(id)) { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'id')) } if (type !== 'js' && type !== 'css') { throw new Error(GreasyFork.__format(GreasyFork.INVALID_ARGUMENT_ERROR, 'type')) } const URL = `https://greatest.deepsurf.us/scripts/${id}/code/userscript.user.${type}` GM_openInTab(URL) } listScripts() { const scriptList = document.querySelector('.script-list') if (scriptList === null) { throw new Error(GreasyFork.INVALID_PAGE_ERROR) } const userScripts = scriptList.querySelectorAll('[data-script-id]') const result = [] const typeMap = { 'browse-script-list': 'browse', 'user-script-list': 'user' } const type = typeMap[scriptList.id] || 'unknown' for (let i = 0; i < userScripts.length; i++) { const userScript = userScripts[i] result.push( GreasyFork.parseScriptNode(userScript) ) } return { type, list: result } } signOut() { GM_xmlhttpRequest({ url: `https://${this.host}/users/sign_out` }) } }