c.stupid.cat/js/friends.js

138 lines
5.4 KiB
JavaScript

(function friends() {
"use strict";
// Each friend is rendered as a full — but smaller — presence card, built by
// the shared factory in discord.js (window.PresenceCard). Cards pull live
// presence (status, activity, badges, banner, bio, connections, wishlist…)
// from the same Doughmination Restful API the /discord card uses.
// NOTE: discord.js must be loaded BEFORE this file (see cool-people/index.html).
var FRIENDS = [
{
title: "Fiancée",
members: [
{ name: "Aria", tier: "wife", discordId: "1305215902685597797", link: null }
]
},
{
title: "Close Friends",
members: [
{ name: "Lilly", tier: "close", discordId: "908055723659898902", link: null },
{ name: "Ria", tier: "close", discordId: "1513506390088618145", link: null },
{ name: "Camilla", tier: "close", discordId: "1110542429838397471", link: "https://cammy-the-cat.com" },
{ name: "Saphie", tier: "close", discordId: "527709099186716673", link: null },
{ name: "Ari", tier: "close", discordId: "1474568910736199825", link: "https://a.stupid.cat" }
]
},
{
title: "Friends",
members: [
{ name: "Fin", tier: "friend", discordId: "867818211574808607", link: null },
{ name: "Meme", tier: "friend", discordId: "812998699667161098", link: null },
{ name: "N", tier: "friend", discordId: "639399972407869450", link: null },
{ name: "Lylla", tier: "friend", discordId: "1009889543878611016", link: null },
{ name: "Simon", tier: "friend", discordId: "758466783354814514", link: null }
]
},
{
title: "Other Peeps",
subtitle: "You can request to be added here!",
members: [
{ name: "furi", tier: "known", discordId: "781445370177126401", link: "https://furina.is-a.dev"},
{ name: "pokemon", tier: "known", discordId: "784443338627612673", link: "https://devmatei.com/" }
]
},
{
title: "Alts",
subtitle: "My other accounts, dead or alive",
members: [
{ name: "J", img: "/assets/alts/j.png", tier: "active-alt", discordId: "1500197577336033301", link: null},
{ name: "Uzi", img: "/assets/alts/uzi.png", tier: "active-alt", discordId: "526626867973849123", link: null },
{ name: "clovetwilight3", img: "/assets/alts/clovetwilight3.png", tier: "dead-alt", discordId: null, link: null },
{ name: "estrogenhrt", img: "/assets/alts/estrogenhrt.png", tier: "dead-alt", discordId: null, link: null },
{ name: "Clove <3", img: "/assets/alts/clove.png", tier: "dead-alt", discordId: "1125844710511104030", link: null},
{ name: "Clove ⛤", img: "/assets/alts/butterfly.png", tier: "dead-alt", discordId: "514994021970739201", link: null },
{ name: "Mrow", img: "/assets/alts/mrow.png", tier: "dead-alt", discordId: "219480349053288450", link: null }
]
}
];
var FRIEND_POLL_MS = 60000; // re-poll each live friend once a minute
var root = document.getElementById("friends-root");
if (!root) return;
// title → URL-safe anchor id, e.g. "Close Friends" -> "close-friends"
function slugify(str) {
return String(str == null ? "" : str)
.toLowerCase()
.trim()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
}
var make = window.PresenceCard;
if (typeof make !== "function") {
console.error("friends.js: window.PresenceCard is missing — load /js/discord.js before /js/friends.js");
}
// ---- render ---------------------------------------------------------
FRIENDS.forEach(function (group) {
var section = document.createElement("section");
section.className = "section";
section.id = slugify(group.title); // anchor target, e.g. #alts
var h2 = document.createElement("h2");
h2.className = "section-title";
h2.textContent = group.title;
section.appendChild(h2);
if (group.subtitle) {
var sub = document.createElement("p");
sub.className = "section-subtitle";
sub.textContent = group.subtitle;
section.appendChild(sub);
}
var grid = document.createElement("div");
grid.className = "friend-grid";
group.members.forEach(function (m) {
// placeholder slot — the factory replaces it with the finished card
var slot = document.createElement("div");
grid.appendChild(slot);
if (typeof make === "function") {
make({
mount: slot,
userId: m.discordId || null, // null → static placeholder card (dead alts)
mini: true, // smaller styling + keeps page accent local
pollMs: FRIEND_POLL_MS,
tier: m.tier || null,
link: m.link || null,
fallbackName: m.name, // shown instantly + kept if the API has no data
fallbackImg: m.img || null
});
} else {
// hard fallback: at least show the name if the factory didn't load
slot.className = "presence-card is-mini" + (m.tier ? " tier-" + m.tier : "");
slot.dataset.status = "offline";
slot.textContent = m.name;
}
});
section.appendChild(grid);
root.appendChild(section);
});
// ---- jump to anchor (sections are built after page load) ------------
function scrollToHash() {
var id = (location.hash || "").slice(1);
if (!id) return;
var target = document.getElementById(id);
if (target) target.scrollIntoView();
}
scrollToHash();
window.addEventListener("hashchange", scrollToHash);
})();