// ==UserScript==
// @name GM Requests
// @description Imitating Python's Requests library based on GM_xmlHttpRequest.
// @version 0.0.2
// @author 大碗宽面wtw
// @homepage https://github.com/bigbowl-wtw/gm-requests/
// @supportURL https://github.com/bigbowl-wtw/gm-requests/issues
// @match *://*/*
// @grant GM_xmlhttpRequest
// @license MIT
// @namespace com.github.bigbowl-wtw
// ==/UserScript==
(function webpackUniversalModuleDefinition(root, factory) {
if (typeof exports === "object" && typeof module === "object") module.exports = factory(); else if (typeof define === "function" && define.amd) define([], factory); else if (typeof exports === "object") exports["requests"] = factory(); else root["requests"] = factory();
})(self, (() => (() => {
"use strict";
var __webpack_require__ = {};
(() => {
__webpack_require__.d = (exports, definition) => {
for (var key in definition) {
if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
Object.defineProperty(exports, key, {
enumerable: true,
get: definition[key]
});
}
}
};
})();
(() => {
__webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop);
})();
(() => {
__webpack_require__.r = exports => {
if (typeof Symbol !== "undefined" && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, {
value: "Module"
});
}
Object.defineProperty(exports, "__esModule", {
value: true
});
};
})();
var __webpack_exports__ = {};
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, {
Session: () => Session,
get: () => get,
post: () => post,
session: () => session
});
var ErrorStatus;
(function(ErrorStatus) {
ErrorStatus[ErrorStatus["BadRequest"] = 400] = "BadRequest";
ErrorStatus[ErrorStatus["Unauthorized"] = 401] = "Unauthorized";
ErrorStatus[ErrorStatus["Forbidden"] = 403] = "Forbidden";
ErrorStatus[ErrorStatus["NotFound"] = 404] = "NotFound";
ErrorStatus[ErrorStatus["MethodNotAllowed"] = 405] = "MethodNotAllowed";
ErrorStatus[ErrorStatus["RequestTimeout"] = 408] = "RequestTimeout";
ErrorStatus[ErrorStatus["TooManyRequests"] = 429] = "TooManyRequests";
ErrorStatus[ErrorStatus["InternalServerError"] = 500] = "InternalServerError";
ErrorStatus[ErrorStatus["BadGateway"] = 502] = "BadGateway";
ErrorStatus[ErrorStatus["ServiceUnavailable"] = 503] = "ServiceUnavailable";
})(ErrorStatus || (ErrorStatus = {}));
function utils_assign(target, ...rest) {
const __assign = Object.assign || function(t, ...others) {
for (let s, i = 0, n = others.length; i < n; i++) {
s = others[i];
for (const p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.call(this, target, ...rest);
}
function assignDeepCopy(target, ...rest) {
rest = rest.filter((r => r !== undefined));
utils_assign(target, ...rest);
return utils_assign.call(this, target, ...JSON.parse(JSON.stringify(rest)));
}
function bodyToString(data) {
if (Object.values(data).some((v => typeof v.toString !== "function"))) throw new TypeError("value must has `.toString`");
return Object.entries(data).map((([key, value]) => `${key}=${encodeURIComponent(value.toString())}`)).join("&");
}
class SimpleCookieJar {
get empty() {
return !Object.keys(this.cookies).length;
}
constructor(cookies) {
var _a;
this.never = new Set;
this.setCookies((_a = cookies) !== null && _a !== void 0 ? _a : {});
}
update(cookies) {
utils_assign(this.cookies, this.normalizeCookie(cookies));
}
updateFromString(cookieStringArray) {
if (typeof cookieStringArray === "string") cookieStringArray = [ cookieStringArray ];
this.update(cookieStringArray);
}
differenceUpdate(cookies) {
let cookieEntries;
if (Array.isArray(cookies)) cookieEntries = cookies.map(this.stringToEntry); else cookieEntries = Object.entries(isCookieJar(cookies) ? cookies.cookies : cookies);
const set = new Set(Object.keys(this.cookies));
cookieEntries = cookieEntries.filter((([name]) => !set.has(name)));
this.update(Object.fromEntries(cookieEntries));
}
deleteFromString(cookieStringArray) {
if (typeof cookieStringArray === "string") cookieStringArray = [ cookieStringArray ];
const names = cookieStringArray.map(this.stringToEntry).map((([name]) => name));
names.forEach((name => {
this.never.add(name);
delete this.cookies[name];
}));
}
setCookies(cookies) {
this.cookies = new Proxy(this.normalizeCookie(cookies), {
set: (target, name, value) => {
if (this.never.has(name)) return true;
target[name] = value;
return true;
}
});
}
toString() {
return Object.entries(this.cookies).map((([k, v]) => `${k}=${v}`)).join(";");
}
parseCookieString(cookieStrings) {
return Object.fromEntries(cookieStrings.map(this.stringToEntry));
}
normalizeCookie(cookies) {
if (Array.isArray(cookies)) return this.parseCookieString(cookies);
if (isCookieJar(cookies)) return cookies.cookies;
return cookies;
}
stringToEntry(cookieString) {
return cookieString.slice(0, cookieString.indexOf(";")).split("=");
}
}
function isCookieJar(obj) {
return typeof obj.update === "function";
}
var __rest = undefined && undefined.__rest || function(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
class Header {
constructor(headers) {
this.cookies = new SimpleCookieJar;
if (!headers) {
this.headers = {};
return;
}
const {cookie} = headers, others = __rest(headers, [ "cookie" ]);
this.headers = others;
if (cookie) {
this.cookies.update(cookie);
}
}
setFromString(headerString) {
const entrise = headerString.split("\r\n").map((kv => kv.split(":"))).map((([k, v]) => [ k.toLowerCase(), v.trim() ]));
for (const [name, value] of entrise) {
const header = this.headers[name];
if (header) {
if (typeof header === "string") this.headers[name] = [ header ];
this.headers[name].push(value);
} else {
this.headers[name] = value;
}
}
return this;
}
update(headers) {
if (isIHeader(headers)) {
this.cookies.update(headers.cookies);
this.update(headers.headers);
} else {
const _a = headers !== null && headers !== void 0 ? headers : {}, {cookie} = _a, others = __rest(_a, [ "cookie" ]);
utils_assign(this.headers, others);
if (cookie) {
this.cookies.update(cookie);
}
}
}
getHeaders() {
if (!Object.keys(this.headers).length) {
if (this.cookies.empty) return {};
return {
cookie: this.cookies.toString()
};
}
const headers = {};
for (const [name, value] of Object.entries(this.headers)) headers[name] = value.toString();
return Object.assign(Object.assign({}, headers), {
cookie: this.cookies.toString()
});
}
append(header, value) {
if (header === "cookie") this.cookies.update([ header ]); else if (!this[header]) this[header] = value; else if (!Array.isArray(header)) this[header] = [ value ].concat(this[header]); else this[header].concat(value);
}
get(name) {
return this.headers[name];
}
}
function isIHeader(obj) {
return typeof obj.update === "function";
}
var __awaiter = undefined && undefined.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P((function(resolve) {
resolve(value);
}));
}
return new (P || (P = Promise))((function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
}));
};
var session_rest = undefined && undefined.__rest || function(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
class Details {
constructor(url, method, options) {
this.pendings = [];
this.url = url;
this.method = method;
this.finalHeader = new Header;
if (options) {
const {query, json, data, cookie, auth, headers} = options, others = session_rest(options, [ "query", "json", "data", "cookie", "auth", "headers" ]);
this.query = query;
this.json = json;
this.data = data;
this.cookie = cookie;
this.auth = auth;
this.headers = headers;
this.others = others;
}
}
build(session) {
return __awaiter(this, void 0, void 0, (function*() {
this.buildURL().buildHeaderAndCookie(session).buildAuth(session);
this.pendings.concat(session.buildHooks.map((hook => hook.call(this, session))));
return this.toDetails();
}));
}
buildURL() {
this.parseQuery(this.query);
return this;
}
buildHeaderAndCookie(session) {
const finalCookie = this.finalHeader.cookies;
if (!session.cookies.empty) finalCookie.update(session.cookies);
if (this.cookie) finalCookie.update(this.cookie);
this.finalHeader.update(session.headers);
if (this.headers) this.finalHeader.update(this.headers);
return this;
}
buildAuth(session) {
var _a;
this.pendings.push((_a = session.auth) === null || _a === void 0 ? void 0 : _a.build(this.finalHeader));
return this;
}
buildBody() {
if (this.json) {
const contentType = "application/json";
this.finalHeader.update({
"Content-Type": contentType
});
const data = JSON.stringify(this.json);
this.finalData = data;
return this;
}
if (this.data) {
if (typeof this.data === "string") {
this.finalData = this.data;
return this;
}
if (this.data instanceof FormData) return this;
const contentType = "application/x-www-form-urlencoded";
this.finalHeader.update({
"Content-Type": contentType
});
this.finalData = bodyToString(this.data);
return this;
}
return this;
}
toDetails() {
return __awaiter(this, void 0, void 0, (function*() {
yield Promise.all(this.pendings);
const url = this.url.toString();
this.buildBody();
const details = Object.assign({
url,
method: this.method,
headers: this.finalHeader.getHeaders()
}, this.others);
if (this.finalData) details.data = this.finalData;
return details;
}));
}
parseQuery(query) {
let url;
if (typeof this.url === "string") url = new URL(this.url); else url = this.url;
if (query) Object.entries(query).filter((([_, v]) => typeof v === "string")).forEach((([k, v]) => url.searchParams.append(k, v.toString())));
this.url = url;
}
}
class Session {
constructor() {
this.buildHooks = [];
const headers = new Header;
Object.defineProperty(this, "headers", {
get: () => headers,
set(value) {
headers.update(value);
}
});
Object.defineProperty(this, "cookies", {
get: () => headers.cookies,
set(value) {
headers.cookies.setCookies(value);
}
});
}
get(url, options) {
return __awaiter(this, void 0, void 0, (function*() {
return this.request("GET", url, options);
}));
}
post(url, options) {
return __awaiter(this, void 0, void 0, (function*() {
return this.request("POST", url, options);
}));
}
request(method, url, options) {
return __awaiter(this, void 0, void 0, (function*() {
const details = new Details(url, method, options);
return new Promise(((resolve, reject) => {
if (!options.onload) {
details.others.onload = resp => {
if (!this.cookies.empty) {
const respHeaders = (new Header).setFromString(resp.responseHeaders);
this.cookies.deleteFromString(respHeaders["set-cookie"]);
}
if (resp.status === 200 && !(resp.status in ErrorStatus)) resolve((options === null || options === void 0 ? void 0 : options.responseType) ? resp.response : resp); else reject(resp);
};
}
if (!options.onerror) details.others.onerror = resp => reject(resp);
details.build(this).then((dtl => GM_xmlhttpRequest(dtl)));
}));
}));
}
registerBuildHook(hook) {
this.buildHooks.push(hook);
}
}
function get(url, query, options) {
return (new Session).get(url, Object.assign({
query
}, options));
}
function post(url, options) {
return (new Session).post(url, Object.assign({}, options));
}
function session() {
return new Session;
}
return __webpack_exports__;
})()));