Greasy Fork is available in English.
Get information from Greasy Fork and do actions in it.
Questo script non dovrebbe essere installato direttamente. È una libreria per altri script da includere con la chiave // @require https://update.greasyfork.org/scripts/445697/1747795/Greasy%20Fork%20API.js
// ==UserScript== // @name Greasy Fork API // @namespace - // @version 3.0.0 // @description Get data from Greasy Fork, or do actions on Greasy Fork // @author NotYou // @license LGPL-3.0 // @connect greasyfork.org // @connect sleazyfork.org // @grant GM.xmlHttpRequest // @grant GM.openInTab // @require https://unpkg.com/[email protected]/lib/index.umd.js // ==/UserScript== !function (z) { 'use strict'; class Types { static IdStringFormat = z.union([ z.number().int().positive(), z.string().regex(/^(?!0)\d+$/) ]) static QueryFormat = z.string().trim().optional() static PageFormat = z.number().int().optional() static FilterLocaleFormat = z.boolean().optional() static get ScriptsQuerySchema() { return z.object({ q: this.QueryFormat, page: this.PageFormat, filter_locale: this.FilterLocaleFormat, sort: z.union([ z.literal('total_installs'), z.literal('ratings'), z.literal('created'), z.literal('updated'), z.literal('name'), ]).optional() }) } static get ScriptSetsQuerySchema() { return this.ScriptsQuerySchema.extend({ set: this.IdStringFormat }) } static get LibrariesQuerySchema() { return z.object({ q: this.QueryFormat, page: this.PageFormat, filter_locale: this.FilterLocaleFormat, sort: z.union([ z.literal('created'), z.literal('updated'), z.literal('name') ]).optional() }) } static get UsersQuerySchema() { return z.object({ q: this.QueryFormat, page: this.PageFormat, sort: z.union([ z.literal('name'), z.literal('daily_installs'), z.literal('total_installs'), z.literal('ratings'), z.literal('scripts'), z.literal('created_scripts'), z.literal('updated_scripts'), ]).optional(), author: z.boolean().optional() }) } static GetResponseSchema = z.object({ params: z.array( z.tuple([ z.custom(value => value instanceof z.ZodSchema), z.any() ]) ), getUrl: z.function() .args(z.any().array()) .returns(z.string()), type: z.union([ z.literal('json'), z.literal('text') ]) }) static get InstallSchema() { return z.object({ id: this.IdStringFormat, type: z.union([z.literal('js'), z.literal('css')]).optional().default('js') }) } } class GreasyFork { constructor(isSleazyfork = false) { if (isSleazyfork) { this.hostname = 'api.sleazyfork.org' } else { this.hostname = 'api.greasyfork.org' } } Types = Types _formatZodError(zodError) { if (!(zodError instanceof z.ZodError)) { throw new Error('Provided value is not a ZodError') } const formatIssue = issue => { return `${issue.code}${issue.path.length ? ` "${issue.path.join('.')}"` : ''}: ${issue.message}` } return zodError.issues.map(formatIssue).join('\n\n') } _getUrl(path) { return 'https://' + this.hostname + '/' + path } _request(path, options = {}) { return new Promise((resolve, reject) => { GM.xmlHttpRequest({ url: this._getUrl(path), anonymous: true, onload: response => { if (response.status === 200) { resolve(response) } }, onerror: reject, ...options }) }) } _getTextData(path) { return this._request(path) .then(response => response.responseText) } _getJSONData(path) { return this._request(path, { responseType: 'json' }) .then(response => response.response) } _dataToSearchParams(data) { for (const key in data) { const value = data[key] if (typeof value === 'boolean') { data[key] = value ? 1 : 0 } else if (typeof value === 'undefined' || value === null) { delete data[key] } } return '?' + new URLSearchParams(data).toString() } _getResponse(options) { const result = this.Types.GetResponseSchema.safeParse(options) if (!result.success) { throw new Error(this._formatZodError(result.error)) } const results = options.params.map(([schema, param]) => schema.safeParse(param)) const unsuccessfulResult = results.find(result => !result.success) if (unsuccessfulResult) { throw new Error(this._formatZodError(unsuccessfulResult.error)) } const data = results.map(result => result.data) const url = options.getUrl(data) if (options.type === 'json') { return this._getJSONData(url) } else if (options.type === 'text') { return this._getTextData(url) } } get script() { return { getData: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}.json`, type: 'json' }), getCode: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}/code/script.js`, type: 'text' }), getMeta: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}/code/script.meta.js`, type: 'text' }), getHistory: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}/versions.json`, type: 'json' }), getStats: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}/stats.json`, type: 'json' }), getStatsCsv: id => this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `scripts/${id}/stats.json`, type: 'text' }) } } getScripts(options = {}) { return this._getResponse({ params: [ [this.Types.ScriptsQuerySchema, options] ], getUrl: ([options]) => 'scripts.json' + this._dataToSearchParams(options), type: 'json' }) } getScriptSet(options = {}) { return this._getResponse({ params: [ [this.Types.ScriptSetsQuerySchema, options] ], getUrl: ([options]) => 'scripts.json' + this._dataToSearchParams(options), type: 'json' }) } getLibraries(options = {}) { return this._getResponse({ params: [ [this.Types.LibrariesQuerySchema, options] ], getUrl: ([options]) => 'scripts/libraries.json' + this._dataToSearchParams(options), type: 'json' }) } getUserData(id) { return this._getResponse({ params: [ [this.Types.IdStringFormat, id] ], getUrl: ([id]) => `users/${id}.json`, type: 'json' }) } getUsers(options = {}) { return this._getResponse({ params: [ [this.Types.UsersQuerySchema, options] ], getUrl: ([options]) => 'users.json' + this._dataToSearchParams(options), type: 'json' }) } signOut() { return this._request('/users/sign_out') } installUserScript(options) { const result = this.Types.InstallSchema.safeParse(options) if (!result.success) { throw new Error(this._formatZodError(result.error)) } options = result.data const url = this._getUrl(`scripts/${options.id}/code/userscript.user.${options.type}`) GM.openInTab(url, { active: true }) } } window.GreasyFork = GreasyFork }(Zod)