Repository navigation
Expand file tree
/
Copy pathcreditsClickCopy-load.js
More file actions
59 lines (51 loc) · 2.32 KB
/
Copy pathcreditsClickCopy-load.js
File metadata and controls
59 lines (51 loc) · 2.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
(async () => {
const SOURCES = [
{ name: "GitHub raw", url: "https://raw.githubusercontent.com/Balint2201/creditsClickCopy/refs/heads/main/creditsClickCopy.js" },
{ name: "jsDelivr", url: "https://cdn.jsdelivr.net/gh/Balint2201/creditsClickCopy@main/creditsClickCopy.js" },
];
const FETCH_TIMEOUT_MS = 10000;
const SPICETIFY_TIMEOUT_MS = 15000;
/** Spicetify can run extensions before Platform exists; the extension reads it on load. */
async function waitForSpicetify() {
const deadline = Date.now() + SPICETIFY_TIMEOUT_MS;
while (Date.now() < deadline) {
if (window.Spicetify?.Platform && window.Spicetify?.LocalStorage) return true;
await new Promise(resolve => setTimeout(resolve, 100));
}
return false;
}
async function fetchSource(url) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
try {
const response = await fetch(`${url}?t=${Date.now()}`, { cache: "no-store", signal: controller.signal });
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const code = await response.text();
if (!code.trim()) throw new Error("empty response");
return code;
} finally {
clearTimeout(timer);
}
}
function evaluate(code) {
// The sourceURL keeps the file addressable in DevTools instead of showing up
// as an anonymous <script>.
const source = `${code}\n//# sourceURL=creditsClickCopy.js`;
const script = document.createElement("script");
script.textContent = source;
(document.head || document.documentElement).appendChild(script);
script.remove();
if (!window.creditsClickCopy) throw new Error("script ran but did not register window.creditsClickCopy");
}
await waitForSpicetify();
for (const source of SOURCES) {
try {
evaluate(await fetchSource(source.url));
console.log(`[creditsClickCopy] Loaded from ${source.name}.`);
return;
} catch (error) {
console.warn(`[creditsClickCopy] ${source.name} failed:`, error);
}
}
console.error("[creditsClickCopy] Every source failed — the extension is not running.");
})();