Skip to content

Instantly share code, notes, and snippets.

@nskazki
Last active December 20, 2023 21:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nskazki/e230a8692c860f4da6c5343d0d83429d to your computer and use it in GitHub Desktop.
Save nskazki/e230a8692c860f4da6c5343d0d83429d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Better Directus
// @namespace http://tampermonkey.net/
// @version 2023-12-20
// @description try to take over the world!
// @author You
// @match https://gleam.directus.app/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=directus.app
// @grant none
// ==/UserScript==
(function() {
'use strict';
window.XMLHttpRequestQueues = [Promise.resolve(), Promise.resolve(), Promise.resolve(), Promise.resolve()]
window.XMLHttpRequestOrig = XMLHttpRequest
window.XMLHttpRequest = function() {
// proxies don't work with xhr.onloadend = callback
const inst = new window.XMLHttpRequestOrig()
const methods = ['open', 'setRequestHeader', 'addEventListener', 'abort']
const getters = ['upload', 'response', 'status', 'statusText', 'readyState', 'responseURL']
const setters = ['timeout', 'responseType', 'withCredentials', ]
const send = 'send'
const callbacks = ['onabort', 'onerror', 'ontimeout', 'onloadend']
const responseText = 'responseText'
const proxy = {}
let resolve = null
let finilized = false
Object.defineProperties(proxy, methods.reduce((res, name) => {
return { ...res, [name]: { value: proxyMethod, enumerable: true } }
function proxyMethod() {
return inst[name].apply(inst, arguments)
}
}, {}))
Object.defineProperties(proxy, getters.reduce((res, name) => {
return { ...res, [name]: { get: proxyGetter, enumerable: true } }
function proxyGetter() {
return inst[name]
}
}, {}))
Object.defineProperties(proxy, setters.reduce((res, name) => {
return { ...res, [name]: { set: proxySetter, enumerable: true } }
function proxySetter(value) {
inst[name] = value
}
}, {}))
Object.defineProperty(proxy, responseText, {
enumerable: true,
get() {
const text = inst[responseText]
const json = tryParsing(text)
if (json === undefined) {
return text
} else if (json.data?.expires) {
json.data.expires = 60_000
console.info('patched the expiry data in', json)
return JSON.stringify(json)
} else {
console.info('recieved', json)
return text
}
}
})
Object.defineProperty(proxy, send, {
enumerable: true,
value(...args) {
if (finilized) {
return
}
const queue = window.XMLHttpRequestQueues.shift().finally(() => {
return new Promise((res) => {
resolve = res
inst[send].apply(inst, args)
})
})
window.XMLHttpRequestQueues.push(queue)
}
})
Object.defineProperties(proxy, callbacks.reduce((res, name) => {
return { ...res, [name]: { set: callbackProxy, enumerable: true } }
function callbackProxy(value) {
inst[name] = (...args) => {
if (resolve) {
resolve()
}
finilized = true
value(...args)
}
}
}, {}))
return proxy
function tryParsing(data) {
try {
return JSON.parse(data)
} catch {
return undefined
}
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment