Skip to content

Instantly share code, notes, and snippets.

@remy
Last active February 3, 2024 11:30
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 remy/f7a1941a90ea3404a9a6a7384d420fd1 to your computer and use it in GitHub Desktop.
Save remy/f7a1941a90ea3404a9a6a7384d420fd1 to your computer and use it in GitHub Desktop.
Modifies Spotify to remove episodes, audiobooks, podcasts and shows.
rewriteFetch([
{
url: "/pathfinder/v1/query",
query: /operationName=home&/,
modify: {
json(data) {
const block = ["episodes", "audiobooks", "podcasts", "shows"];
data.data.home.sectionContainer.sections.items =
data.data.home.sectionContainer.sections.items.filter((res) => {
if (!res.data.title) return true;
if (!res.data.title.text) return true;
const needle = res.data.title.text.toLowerCase();
return !block.find((item) => needle.includes(item));
});
return data;
},
},
},
]);
// the following comes from https://github.com/remy/fetch-rewrite
/**
* @param {string} target
* @param {string | RegExp} matcher
* @returns {boolean}
*/
rewriteFetch.eqOrMatch = (target, matcher) => {
if (typeof matcher === 'string') {
if (matcher === '*') {
return true;
}
return matcher === target;
}
if (matcher instanceof RegExp) {
return matcher.test(target);
}
return false;
};
/**
*
* @param {import("./types").Rules} rules
* @param {URL} url
* @param {import("./types").FetchOptions} [options]
* @returns {import("./types").Rule | false}
*/
rewriteFetch.matcher = (rules, url, options = {}) => {
return (
rules.find((item) => {
let { path, query, origin, method } = item;
const tests = [
[origin, url.origin],
[method, options.method],
[path, url.pathname],
[query, url.search?.substring(1)],
];
for (let [test, target] of tests) {
if (test && !rewriteFetch.eqOrMatch(target, test)) {
return false;
}
}
return true;
}) || false
);
};
/**
* @param {import("./types").Rules} rules
*/
function rewriteFetch(rules) {
const $_fetch = fetch;
// hacky
if (!Array.isArray(rules)) {
rules = [rules];
}
// modify the global fetch
// eslint-disable-next-line no-global-assign
fetch = async (url, options = {}) => {
// if we're in a browser, then we can use the location origin
const execOrigin =
(typeof window !== 'undefined' && window.location.origin) || undefined;
if (typeof url === 'string') url = new URL(url, execOrigin);
// find the first matching rules based on origin, pathname, and query
const matched = rewriteFetch.matcher(rules, url, options);
if (!matched) {
return $_fetch(url, options);
}
if (matched.rewrite) {
// FIXME add support for rewrite options / modifying the entire request
if (typeof matched.rewrite === 'function') {
return matched.rewrite($_fetch, url, options);
}
return $_fetch(matched.rewrite, options);
}
const { modify } = matched;
const res = await $_fetch(url, options);
const rewrites = {};
for (let key in modify) {
if (key in res) {
// create a bound backup of the original function
rewrites[key] = res[key].bind(res);
// overwrite the original function with our own
res[key] = (...args) =>
rewrites[key](...args).then((res) => {
try {
return modify[key](res);
} catch (e) {
return res;
}
});
}
}
return res;
};
}
if (typeof module !== 'undefined') {
// eslint-disable-next-line no-undef
module.exports = rewriteFetch;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment