Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add proxy for CosmosAsync calls #2846

Merged
merged 15 commits into from
Feb 20, 2024
80 changes: 80 additions & 0 deletions jsHelper/spicetifyWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,86 @@
Platform: {}
};

(function addProxyCosmos() {
if (!Spicetify.Player.origin?._cosmos) {
setTimeout(addProxyCosmos, 50);
return;
}

const corsProxyURL = "https://cors-proxy.ririxi.workers.dev/";
rxri marked this conversation as resolved.
Show resolved Hide resolved
const allowedMethodsMap = {
get: "get",
post: "post",
del: "delete",
put: "put",
patch: "patch"
};
const allowedMethodsSet = new Set(Object.keys(allowedMethodsMap));
const internalEndpoints = new Set(["sp:", "wg:"]);

const handler = {
// biome-ignore lint/complexity/useArrowFunction: <explanation>

Check warning on line 324 in jsHelper/spicetifyWrapper.js

View workflow job for this annotation

GitHub Actions / linter

Suppression comment is not being used

Check warning on line 324 in jsHelper/spicetifyWrapper.js

View workflow job for this annotation

GitHub Actions / linter

Suppression comment is not being used
afonsojramos marked this conversation as resolved.
Show resolved Hide resolved
get: function (target, prop, receiver) {
const internalFetch = Reflect.get(target, prop, receiver);

if (typeof internalFetch !== "function" || !allowedMethodsSet.has(prop) || Spicetify.Platform.version < "1.2.31") return internalFetch;

// biome-ignore lint/complexity/useArrowFunction: <explanation>
afonsojramos marked this conversation as resolved.
Show resolved Hide resolved
return async function (url, paramsOrBody) {
const urlObj = new URL(url);

const isWebAPI = urlObj.hostname === "api.spotify.com";
const isSpClientAPI = urlObj.hostname.includes(".spotify.com") && urlObj.hostname.includes("spclient");
const isInternalURL = internalEndpoints.has(urlObj.protocol);
// biome-ignore lint/style/noArguments: <explanation>
if (isInternalURL) return internalFetch.apply(this, arguments);

const shouldUseCORSProxy = !isWebAPI && !isSpClientAPI && !isInternalURL;

const method = allowedMethodsMap[prop.toLowerCase()];
const headers = {
"Content-Type": "application/json"
};

const options = {
method,
headers,
timeout: 1000 * 15
};

let finalURL = urlObj.toString();
if (paramsOrBody) {
if (method === "get") {
const params = new URLSearchParams(paramsOrBody);
finalURL += `?${params.toString()}`;
} else options.body = JSON.stringify(paramsOrBody);
}
if (shouldUseCORSProxy) finalURL = `${corsProxyURL}${finalURL}`;

const Authorization = `Bearer ${Spicetify.Platform.AuthorizationAPI._state.token.accessToken}`;
let injectedHeaders = {};
if (isWebAPI) injectedHeaders = { Authorization };
if (isSpClientAPI) {
injectedHeaders = {
Authorization,
"Spotify-App-Version": Spicetify.Platform.version,
"App-Platform": Spicetify.Platform.PlatformData.app_platform
};
}
Object.assign(options.headers, injectedHeaders);

try {
return fetch(finalURL, options).then(res => res.json());
rxri marked this conversation as resolved.
Show resolved Hide resolved
} catch (e) {
console.error(e);
}
};
}
};

Spicetify.Player.origin._cosmos = new Proxy(Spicetify.Player.origin._cosmos, handler);
})();

(function waitForPlatform() {
if (!Spicetify._platform) {
setTimeout(waitForPlatform, 50);
Expand Down