GM Fetch

A fetch API of GM_xmlhttpRequest

This script should not be not be installed directly. It is a library for other scripts to include with the meta directive // @require https://update.greasyfork.org/scripts/472236/1868041/GM%20Fetch.js

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

// ==UserScript==
// @name         GM Fetch
// @namespace    https://github.com/Sec-ant
// @version      1.2.5
// @author       Ze-Zheng Wu
// @description  A fetch API for GM_xmlhttpRequest / GM.xmlHttpRequest
// @license      MIT
// @homepage     https://github.com/Sec-ant/gm-fetch
// @homepageURL  https://github.com/Sec-ant/gm-fetch
// @source       https://github.com/Sec-ant/gm-fetch.git
// @supportURL   https://github.com/Sec-ant/gm-fetch/issues
// @downloadURL  https://fastly.jsdelivr.net/npm/@sec-ant/gm-fetch@latest/dist/gm-fetch.user.js
// @updateURL    https://fastly.jsdelivr.net/npm/@sec-ant/gm-fetch@latest/dist/gm-fetch.meta.js
// @match        *://*/*
// @grant        GM.xmlHttpRequest
// @grant        GM_xmlhttpRequest
// ==/UserScript==

(function() {
	"use strict";
	var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
	__commonJSMin(((exports, module) => {
		(function(global, factory) {
			typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define([], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, global.gmFetch = factory());
		})(exports, function() {
			function getGmXhr() {
				if (typeof GM_xmlhttpRequest === "function") return GM_xmlhttpRequest;
				if (typeof GM !== "undefined" && typeof GM.xmlHttpRequest === "function") return GM.xmlHttpRequest;
			}
			function parseHeaders(rawHeaders) {
				const headers = new Headers();
				const preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, " ");
				for (const line of preProcessedHeaders.split(/\r?\n/)) {
					const parts = line.split(":");
					const key = parts.shift()?.trim();
					if (key) {
						const value = parts.join(":").trim();
						try {
							headers.append(key, value);
						} catch (error) {
							console.warn(`Response ${error.message}`);
						}
					}
				}
				return headers;
			}
			var gmFetch = async (input, init) => {
				const gmXhr = getGmXhr();
				if (!gmXhr) throw new DOMException("GM_xmlhttpRequest or GM.xmlHttpRequest is not granted.", "NotFoundError");
				const request = new Request(input, init);
				if (request.signal.aborted) throw new DOMException("Network request aborted.", "AbortError");
				const data = await request.blob();
				const headers = Object.fromEntries(request.headers);
				new Headers(init?.headers).forEach((value, key) => {
					headers[key] = value;
				});
				return new Promise((resolve, reject) => {
					let settled = false;
					const responseBlobPromise = new Promise((resolveBlob) => {
						const { abort } = gmXhr({
							method: request.method.toUpperCase(),
							url: request.url || location.href,
							headers,
							data: data.size ? data : void 0,
							redirect: request.redirect,
							binary: true,
							nocache: request.cache === "no-store",
							revalidate: request.cache === "reload",
							timeout: 3e5,
							responseType: gmXhr.RESPONSE_TYPE_STREAM ?? "blob",
							overrideMimeType: request.headers.get("Content-Type") ?? void 0,
							anonymous: request.credentials === "omit",
							onload: ({ response: responseBody }) => {
								if (settled) {
									resolveBlob(null);
									return;
								}
								resolveBlob(responseBody);
							},
							async onreadystatechange({ readyState, responseHeaders, status, statusText, finalUrl, response: responseBody }) {
								if (readyState === XMLHttpRequest.DONE) request.signal.removeEventListener("abort", abort);
								else if (readyState !== XMLHttpRequest.HEADERS_RECEIVED) return;
								if (settled) {
									resolveBlob(null);
									return;
								}
								const parsedHeaders = parseHeaders(responseHeaders);
								const redirected = request.url !== finalUrl;
								const response = new Response(responseBody instanceof ReadableStream ? responseBody : await responseBlobPromise, {
									headers: parsedHeaders,
									status,
									statusText
								});
								Object.defineProperties(response, {
									url: { value: finalUrl },
									type: { value: "basic" },
									...response.redirected !== redirected ? { redirected: { value: redirected } } : {},
									...parsedHeaders.has("set-cookie") || parsedHeaders.has("set-cookie2") ? { headers: { value: parsedHeaders } } : {}
								});
								resolve(response);
								settled = true;
							},
							onerror: ({ statusText, error }) => {
								reject(new TypeError(statusText || error || "Network request failed."));
								resolveBlob(null);
							},
							ontimeout() {
								reject(new TypeError("Network request timeout."));
								resolveBlob(null);
							},
							onabort() {
								reject(new DOMException("Network request aborted.", "AbortError"));
								resolveBlob(null);
							}
						});
						request.signal.addEventListener("abort", abort);
					});
				});
			};
			return gmFetch;
		});
	}))();
})();