diff --git a/53eb00aa300595b54d999e60d501f621ad4399918c568561f74b536b6f37c0ab.riv b/53eb00aa300595b54d999e60d501f621ad4399918c568561f74b536b6f37c0ab.riv deleted file mode 100644 index 132d22b..0000000 Binary files a/53eb00aa300595b54d999e60d501f621ad4399918c568561f74b536b6f37c0ab.riv and /dev/null differ diff --git a/88x31/index.html b/88x31/index.html index bb48f4e..26855c3 100644 --- a/88x31/index.html +++ b/88x31/index.html @@ -73,48 +73,48 @@
- Doughmination + Doughmination Git Gay - Made with Visual Studio Code - I dream in HTML - Valid HTML5 - Valid CSS - Keep the web free - No NFTs, no thanks - No WEBp + Made with Visual Studio Code + I dream in HTML + Valid HTML5 + Valid CSS + Keep the web free + No NFTs, no thanks + No WEBp - Made on GNU/Linux - Firefox - Anything but Chrome - Made on a Mac - WinRAR - Stop Microsoft - Made for dark mode + Made on GNU/Linux + Firefox + Anything but Chrome + Made on a Mac + WinRAR + Stop Microsoft + Made for dark mode - Powered by estrogen - Trans rights now - Queer pride + Powered by estrogen + Trans rights now + Queer pride Girls Now - Let boys wear skirts - I wear cute socks! + Let boys wear skirts + I wear cute socks! - No fascism, no bigotry - Melt ICE - Free Palestine - Slava Ukraini + No fascism, no bigotry + Melt ICE + Free Palestine + Slava Ukraini - Discord - Best viewed on desktop - Kill me now - Don't click here, no! - Minecraft + Discord + Best viewed on desktop + Kill me now + Don't click here, no! + Minecraft - Pokémon - Caramelldansen - Anime blink - This site is Miku approved - Anime tummy supporter - Bad Apple!! + Pokémon + Caramelldansen + Anime blink + This site is Miku approved + Anime tummy supporter + Bad Apple!!
diff --git a/assets/88x31/antifa.gif b/assets/88x31/antifa.gif deleted file mode 100644 index 0809cab..0000000 Binary files a/assets/88x31/antifa.gif and /dev/null differ diff --git a/assets/88x31/antifa.png b/assets/88x31/antifa.png new file mode 100644 index 0000000..e054682 Binary files /dev/null and b/assets/88x31/antifa.png differ diff --git a/assets/88x31/badapple.gif b/assets/88x31/badapple.gif deleted file mode 100644 index af20fa1..0000000 Binary files a/assets/88x31/badapple.gif and /dev/null differ diff --git a/assets/88x31/badapple.png b/assets/88x31/badapple.png new file mode 100644 index 0000000..fa48c62 Binary files /dev/null and b/assets/88x31/badapple.png differ diff --git a/assets/88x31/bestvieweddesktop.gif b/assets/88x31/bestvieweddesktop.gif deleted file mode 100644 index 06620c0..0000000 Binary files a/assets/88x31/bestvieweddesktop.gif and /dev/null differ diff --git a/assets/88x31/bestvieweddesktop.png b/assets/88x31/bestvieweddesktop.png new file mode 100644 index 0000000..68b0c78 Binary files /dev/null and b/assets/88x31/bestvieweddesktop.png differ diff --git a/assets/88x31/blink.gif b/assets/88x31/blink.gif deleted file mode 100644 index 2acde1c..0000000 Binary files a/assets/88x31/blink.gif and /dev/null differ diff --git a/assets/88x31/blink.png b/assets/88x31/blink.png new file mode 100644 index 0000000..9656324 Binary files /dev/null and b/assets/88x31/blink.png differ diff --git a/assets/88x31/caramelldansen.gif b/assets/88x31/caramelldansen.gif deleted file mode 100644 index a79c0a5..0000000 Binary files a/assets/88x31/caramelldansen.gif and /dev/null differ diff --git a/assets/88x31/caramelldansen.png b/assets/88x31/caramelldansen.png new file mode 100644 index 0000000..1907831 Binary files /dev/null and b/assets/88x31/caramelldansen.png differ diff --git a/assets/88x31/cutesocks.gif b/assets/88x31/cutesocks.gif deleted file mode 100644 index 69af349..0000000 Binary files a/assets/88x31/cutesocks.gif and /dev/null differ diff --git a/assets/88x31/cutesocks.png b/assets/88x31/cutesocks.png new file mode 100644 index 0000000..b770a7f Binary files /dev/null and b/assets/88x31/cutesocks.png differ diff --git a/assets/88x31/dark-mode.gif b/assets/88x31/dark-mode.gif deleted file mode 100644 index 3171661..0000000 Binary files a/assets/88x31/dark-mode.gif and /dev/null differ diff --git a/assets/88x31/dark-mode.png b/assets/88x31/dark-mode.png new file mode 100644 index 0000000..85cce60 Binary files /dev/null and b/assets/88x31/dark-mode.png differ diff --git a/assets/88x31/discord.gif b/assets/88x31/discord.gif deleted file mode 100644 index 8b8b457..0000000 Binary files a/assets/88x31/discord.gif and /dev/null differ diff --git a/assets/88x31/discord.png b/assets/88x31/discord.png new file mode 100644 index 0000000..b4c90af Binary files /dev/null and b/assets/88x31/discord.png differ diff --git a/assets/88x31/doughmination.gif b/assets/88x31/doughmination.gif deleted file mode 100644 index 20af87e..0000000 Binary files a/assets/88x31/doughmination.gif and /dev/null differ diff --git a/assets/88x31/doughmination.png b/assets/88x31/doughmination.png new file mode 100644 index 0000000..e5836fc Binary files /dev/null and b/assets/88x31/doughmination.png differ diff --git a/assets/88x31/estrogen.gif b/assets/88x31/estrogen.gif deleted file mode 100644 index 4c965dd..0000000 Binary files a/assets/88x31/estrogen.gif and /dev/null differ diff --git a/assets/88x31/estrogen.png b/assets/88x31/estrogen.png new file mode 100644 index 0000000..d587bdc Binary files /dev/null and b/assets/88x31/estrogen.png differ diff --git a/assets/88x31/firefox.gif b/assets/88x31/firefox.gif deleted file mode 100644 index 94621d5..0000000 Binary files a/assets/88x31/firefox.gif and /dev/null differ diff --git a/assets/88x31/firefox.png b/assets/88x31/firefox.png new file mode 100644 index 0000000..42a0b56 Binary files /dev/null and b/assets/88x31/firefox.png differ diff --git a/assets/88x31/htmldream.gif b/assets/88x31/htmldream.gif deleted file mode 100644 index 28fd2c2..0000000 Binary files a/assets/88x31/htmldream.gif and /dev/null differ diff --git a/assets/88x31/htmldream.png b/assets/88x31/htmldream.png new file mode 100644 index 0000000..e73739d Binary files /dev/null and b/assets/88x31/htmldream.png differ diff --git a/assets/88x31/killmenow.gif b/assets/88x31/killmenow.gif deleted file mode 100644 index 0dbe965..0000000 Binary files a/assets/88x31/killmenow.gif and /dev/null differ diff --git a/assets/88x31/killmenow.png b/assets/88x31/killmenow.png new file mode 100644 index 0000000..48391de Binary files /dev/null and b/assets/88x31/killmenow.png differ diff --git a/assets/88x31/linux.gif b/assets/88x31/linux.gif deleted file mode 100644 index 89e3562..0000000 Binary files a/assets/88x31/linux.gif and /dev/null differ diff --git a/assets/88x31/linux.png b/assets/88x31/linux.png new file mode 100644 index 0000000..709a67c Binary files /dev/null and b/assets/88x31/linux.png differ diff --git a/assets/88x31/macbutton.gif b/assets/88x31/macbutton.gif deleted file mode 100644 index 4292104..0000000 Binary files a/assets/88x31/macbutton.gif and /dev/null differ diff --git a/assets/88x31/macbutton.png b/assets/88x31/macbutton.png new file mode 100644 index 0000000..45fc12c Binary files /dev/null and b/assets/88x31/macbutton.png differ diff --git a/assets/88x31/meltice.gif b/assets/88x31/meltice.gif deleted file mode 100644 index 7e6df98..0000000 Binary files a/assets/88x31/meltice.gif and /dev/null differ diff --git a/assets/88x31/meltice.png b/assets/88x31/meltice.png new file mode 100644 index 0000000..501c974 Binary files /dev/null and b/assets/88x31/meltice.png differ diff --git a/assets/88x31/microslop.gif b/assets/88x31/microslop.gif deleted file mode 100644 index 61936c7..0000000 Binary files a/assets/88x31/microslop.gif and /dev/null differ diff --git a/assets/88x31/microslop.png b/assets/88x31/microslop.png new file mode 100644 index 0000000..6f6f81c Binary files /dev/null and b/assets/88x31/microslop.png differ diff --git a/assets/88x31/miku.gif b/assets/88x31/miku.gif deleted file mode 100644 index e61072d..0000000 Binary files a/assets/88x31/miku.gif and /dev/null differ diff --git a/assets/88x31/miku.png b/assets/88x31/miku.png new file mode 100644 index 0000000..3ffa06c Binary files /dev/null and b/assets/88x31/miku.png differ diff --git a/assets/88x31/minecraft.gif b/assets/88x31/minecraft.gif deleted file mode 100644 index a149b45..0000000 Binary files a/assets/88x31/minecraft.gif and /dev/null differ diff --git a/assets/88x31/minecraft.png b/assets/88x31/minecraft.png new file mode 100644 index 0000000..c27aad2 Binary files /dev/null and b/assets/88x31/minecraft.png differ diff --git a/assets/88x31/nft.gif b/assets/88x31/nft.gif deleted file mode 100644 index 12f48ab..0000000 Binary files a/assets/88x31/nft.gif and /dev/null differ diff --git a/assets/88x31/nft.png b/assets/88x31/nft.png new file mode 100644 index 0000000..1408e2a Binary files /dev/null and b/assets/88x31/nft.png differ diff --git a/assets/88x31/no-chrome.gif b/assets/88x31/no-chrome.gif deleted file mode 100644 index eabb7d8..0000000 Binary files a/assets/88x31/no-chrome.gif and /dev/null differ diff --git a/assets/88x31/no-chrome.png b/assets/88x31/no-chrome.png new file mode 100644 index 0000000..061f948 Binary files /dev/null and b/assets/88x31/no-chrome.png differ diff --git a/assets/88x31/no.gif b/assets/88x31/no.gif deleted file mode 100644 index 188b46c..0000000 Binary files a/assets/88x31/no.gif and /dev/null differ diff --git a/assets/88x31/no.png b/assets/88x31/no.png new file mode 100644 index 0000000..2653eb3 Binary files /dev/null and b/assets/88x31/no.png differ diff --git a/assets/88x31/noweb32.gif b/assets/88x31/noweb32.gif deleted file mode 100644 index 9485709..0000000 Binary files a/assets/88x31/noweb32.gif and /dev/null differ diff --git a/assets/88x31/noweb32.png b/assets/88x31/noweb32.png new file mode 100644 index 0000000..1bc510f Binary files /dev/null and b/assets/88x31/noweb32.png differ diff --git a/assets/88x31/nowebp.gif b/assets/88x31/nowebp.gif deleted file mode 100644 index e63f1f2..0000000 Binary files a/assets/88x31/nowebp.gif and /dev/null differ diff --git a/assets/88x31/nowebp.png b/assets/88x31/nowebp.png new file mode 100644 index 0000000..2e55df1 Binary files /dev/null and b/assets/88x31/nowebp.png differ diff --git a/assets/88x31/palestine.gif b/assets/88x31/palestine.gif deleted file mode 100644 index e58600b..0000000 Binary files a/assets/88x31/palestine.gif and /dev/null differ diff --git a/assets/88x31/palestine.png b/assets/88x31/palestine.png new file mode 100644 index 0000000..6a0fcc5 Binary files /dev/null and b/assets/88x31/palestine.png differ diff --git a/assets/88x31/pokemon.gif b/assets/88x31/pokemon.gif deleted file mode 100644 index 996001c..0000000 Binary files a/assets/88x31/pokemon.gif and /dev/null differ diff --git a/assets/88x31/pokemon.png b/assets/88x31/pokemon.png new file mode 100644 index 0000000..a4a229b Binary files /dev/null and b/assets/88x31/pokemon.png differ diff --git a/assets/88x31/queerpride.gif b/assets/88x31/queerpride.gif deleted file mode 100644 index 6749c9d..0000000 Binary files a/assets/88x31/queerpride.gif and /dev/null differ diff --git a/assets/88x31/queerpride.png b/assets/88x31/queerpride.png new file mode 100644 index 0000000..bf8b0e0 Binary files /dev/null and b/assets/88x31/queerpride.png differ diff --git a/assets/88x31/skirt.gif b/assets/88x31/skirt.gif deleted file mode 100644 index e2833dc..0000000 Binary files a/assets/88x31/skirt.gif and /dev/null differ diff --git a/assets/88x31/skirt.png b/assets/88x31/skirt.png new file mode 100644 index 0000000..fc7af69 Binary files /dev/null and b/assets/88x31/skirt.png differ diff --git a/assets/88x31/transnow.gif b/assets/88x31/transnow.gif deleted file mode 100644 index 7f705aa..0000000 Binary files a/assets/88x31/transnow.gif and /dev/null differ diff --git a/assets/88x31/transnow.png b/assets/88x31/transnow.png new file mode 100644 index 0000000..f310c33 Binary files /dev/null and b/assets/88x31/transnow.png differ diff --git a/assets/88x31/tummy.gif b/assets/88x31/tummy.gif deleted file mode 100644 index db75e06..0000000 Binary files a/assets/88x31/tummy.gif and /dev/null differ diff --git a/assets/88x31/tummy.png b/assets/88x31/tummy.png new file mode 100644 index 0000000..e221f18 Binary files /dev/null and b/assets/88x31/tummy.png differ diff --git a/assets/88x31/ukraine.gif b/assets/88x31/ukraine.gif deleted file mode 100644 index 501b734..0000000 Binary files a/assets/88x31/ukraine.gif and /dev/null differ diff --git a/assets/88x31/ukraine.png b/assets/88x31/ukraine.png new file mode 100644 index 0000000..c3e6c34 Binary files /dev/null and b/assets/88x31/ukraine.png differ diff --git a/assets/88x31/underwearisforloser.gif b/assets/88x31/underwearisforloser.gif deleted file mode 100644 index 7b3584a..0000000 Binary files a/assets/88x31/underwearisforloser.gif and /dev/null differ diff --git a/assets/88x31/underwearisforloser.png b/assets/88x31/underwearisforloser.png new file mode 100644 index 0000000..559b3eb Binary files /dev/null and b/assets/88x31/underwearisforloser.png differ diff --git a/assets/88x31/valid-css.gif b/assets/88x31/valid-css.gif deleted file mode 100644 index 020c75a..0000000 Binary files a/assets/88x31/valid-css.gif and /dev/null differ diff --git a/assets/88x31/valid-css.png b/assets/88x31/valid-css.png new file mode 100644 index 0000000..af6cd55 Binary files /dev/null and b/assets/88x31/valid-css.png differ diff --git a/assets/88x31/valid-html5.gif b/assets/88x31/valid-html5.gif deleted file mode 100644 index 5cf8da1..0000000 Binary files a/assets/88x31/valid-html5.gif and /dev/null differ diff --git a/assets/88x31/valid-html5.png b/assets/88x31/valid-html5.png new file mode 100644 index 0000000..c081906 Binary files /dev/null and b/assets/88x31/valid-html5.png differ diff --git a/assets/88x31/vscbutton.gif b/assets/88x31/vscbutton.gif deleted file mode 100644 index 8a4cad2..0000000 Binary files a/assets/88x31/vscbutton.gif and /dev/null differ diff --git a/assets/88x31/vscbutton.png b/assets/88x31/vscbutton.png new file mode 100644 index 0000000..e474b42 Binary files /dev/null and b/assets/88x31/vscbutton.png differ diff --git a/assets/88x31/winrar4.gif b/assets/88x31/winrar4.gif deleted file mode 100644 index bb5761d..0000000 Binary files a/assets/88x31/winrar4.gif and /dev/null differ diff --git a/assets/88x31/winrar4.png b/assets/88x31/winrar4.png new file mode 100644 index 0000000..4e65425 Binary files /dev/null and b/assets/88x31/winrar4.png differ diff --git a/js/music.js b/js/music.js index 2246dde..12a52e5 100644 --- a/js/music.js +++ b/js/music.js @@ -517,31 +517,95 @@ } // Last.fm stopped serving artist images — every artist returns the same - // placeholder star — so we pull them from Deezer. Deezer's REST API blocks - // CORS, but its JSONP mode (output=jsonp) doesn't. Resolves to a picture URL - // (or "" when there's no match / it fails). - function deezerArtistImg(name) { - return new Promise(function (resolve) { - if (!name) { resolve(""); return; } - var cb = "__dz_" + Math.random().toString(36).slice(2); - var s = document.createElement("script"); - var done = false; - function finish(url) { - if (done) return; - done = true; - try { delete window[cb]; s.remove(); } catch (e) { /* no-op */ } - resolve(url || ""); + // placeholder star. Spotify has the photos, but its catalog API needs an + // OAuth token (and a client secret we can't ship in a static page). So we + // take the keyless route: MusicBrainz maps an artist name → their linked + // Spotify page, then Spotify's own oEmbed hands back that page's picture. + // No API key, no token, no third-party cookies. Resolves to a picture URL + // (or "" when there's no confident match). Results are cached in + // localStorage, so repeat visits are instant and we stay gentle on the APIs. + const MB_ROOT = "https://musicbrainz.org/ws/2"; + const ART_CACHE_PREFIX = "cstupidcat:artimg:"; + const ART_TTL_HIT = 30 * 864e5; // remember a found photo for 30 days + const ART_TTL_MISS = 3 * 864e5; // retry a miss after 3 days + + // MusicBrainz asks anonymous clients for ~1 request/second, so funnel every + // MB call through a one-at-a-time queue spaced ~1.1s apart. + let mbChain = Promise.resolve(); + function mbFetch(url) { + const run = mbChain.then(() => + fetch(url, { headers: { Accept: "application/json" } }) + .then((r) => (r.ok ? r.json() : null)) + .catch(() => null) + ); + const gap = () => new Promise((r) => setTimeout(r, 1100)); + mbChain = run.then(gap, gap); // pace the next call whether this one won or lost + return run; + } + + function artCacheGet(name) { + try { + const raw = localStorage.getItem(ART_CACHE_PREFIX + name.toLowerCase()); + if (!raw) return undefined; + const hit = JSON.parse(raw); + const ttl = hit.url ? ART_TTL_HIT : ART_TTL_MISS; + if (Date.now() - hit.ts > ttl) return undefined; // stale → re-resolve + return hit.url || ""; + } catch (e) { return undefined; } + } + function artCacheSet(name, url) { + try { + localStorage.setItem(ART_CACHE_PREFIX + name.toLowerCase(), + JSON.stringify({ url: url || "", ts: Date.now() })); + } catch (e) { /* storage full / disabled — just skip caching */ } + } + + // name → MusicBrainz artist MBID, but only when we're confident it's the + // right act: an exact (case-insensitive) name match or a strong search score. + async function mbArtistId(name) { + const q = encodeURIComponent('artist:"' + name.replace(/"/g, " ") + '"'); + const data = await mbFetch(MB_ROOT + "/artist?query=" + q + "&limit=1&fmt=json"); + const a = data && data.artists && data.artists[0]; + if (!a) return ""; + const same = (a.name || "").toLowerCase() === name.toLowerCase(); + return (same || a.score >= 90) ? a.id : ""; + } + // MBID → the artist's linked Spotify page (via MusicBrainz URL relationships) + async function mbSpotifyUrl(mbid) { + const data = await mbFetch(MB_ROOT + "/artist/" + mbid + "?inc=url-rels&fmt=json"); + const rels = (data && data.relations) || []; + for (const r of rels) { + const u = r && r.url && r.url.resource; + if (u && u.indexOf("open.spotify.com/artist") !== -1) return u; + } + return ""; + } + // Spotify page → its photo, via Spotify's public (keyless, CORS-open) oEmbed + async function spotifyOembedImg(spotifyUrl) { + try { + const res = await fetch("https://open.spotify.com/oembed?url=" + + encodeURIComponent(spotifyUrl)); + if (!res.ok) return ""; + const data = await res.json(); + return data.thumbnail_url || ""; + } catch (e) { return ""; } + } + + // Public resolver used by loadTop(): artist name → picture URL ("" on miss). + async function artistImg(name) { + if (!name) return ""; + const cached = artCacheGet(name); + if (cached !== undefined) return cached; // fresh hit or fresh miss + let url = ""; + try { + const mbid = await mbArtistId(name); + if (mbid) { + const sp = await mbSpotifyUrl(mbid); + if (sp) url = await spotifyOembedImg(sp); } - window[cb] = function (data) { - var a = data && data.data && data.data[0]; - finish(a ? (a.picture_medium || a.picture || "") : ""); - }; - s.onerror = function () { finish(""); }; - s.src = "https://api.deezer.com/search/artist?q=" + encodeURIComponent(name) + - "&limit=1&output=jsonp&callback=" + cb; - document.head.appendChild(s); - setTimeout(function () { finish(""); }, 6000); - }); + } catch (e) { url = ""; } + artCacheSet(name, url); + return url; } async function loadTop() { @@ -561,10 +625,10 @@ '' + esc(a.playcount) + " plays" + "" + "").join("") + ""; - // chips are already visible — fill in the artist images as Deezer answers + // chips are already visible — fill in the artist images as they resolve const chips = topBox.querySelectorAll(".top-chip"); arr.forEach((a, i) => { - deezerArtistImg(a.name).then((url) => { + artistImg(a.name).then((url) => { if (!url) return; const slot = chips[i] && chips[i].querySelector(".top-art"); if (!slot) return;