From ffbe8b5987ccd88f6c2d04beab2944959490e15d Mon Sep 17 00:00:00 2001 From: Rory& Date: Fri, 19 Dec 2025 23:14:21 +0100 Subject: [PATCH] Implement widget --- assets/public/widget.html | 152 ++++++++++++++++++ src/api/Server.ts | 2 +- .../routes/guilds/#guild_id/widget.json.ts | 18 ++- 3 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 assets/public/widget.html diff --git a/assets/public/widget.html b/assets/public/widget.html new file mode 100644 index 000000000..a03f4b368 --- /dev/null +++ b/assets/public/widget.html @@ -0,0 +1,152 @@ + + + + + + + + Spacebar Widget + + + + + + + + + + + +
+
+ Spacebar Logo + + Unknown + users online + +
+
+
+

Online users

+
+
+
+ + + \ No newline at end of file diff --git a/src/api/Server.ts b/src/api/Server.ts index f81898e81..9cc1820f3 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -115,8 +115,8 @@ export class SpacebarServer extends Server { app.use("/imageproxy/:hash/:size/:url", ImageProxy); app.get("/", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html"))); - app.get("/verify-email", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "verify.html"))); + app.get("/widget", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "widget.html"))); app.get("/_spacebar/api/schemas.json", (req, res) => { res.sendFile(path.join(ASSETS_FOLDER, "schemas.json")); diff --git a/src/api/routes/guilds/#guild_id/widget.json.ts b/src/api/routes/guilds/#guild_id/widget.json.ts index 8f41417a8..dea8f29f1 100644 --- a/src/api/routes/guilds/#guild_id/widget.json.ts +++ b/src/api/routes/guilds/#guild_id/widget.json.ts @@ -17,7 +17,7 @@ */ import { randomString, route } from "@spacebar/api"; -import { Channel, DiscordApiErrors, Guild, Invite, Member, Permissions } from "@spacebar/util"; +import { Channel, Config, DiscordApiErrors, Guild, Invite, Member, Permissions } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router: Router = Router({ mergeParams: true }); @@ -99,7 +99,17 @@ router.get( // Fetch members // TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file) - const members = await Member.find({ where: { guild_id: guild_id } }); + const members = await Member.find({ where: { guild_id: guild_id }, relations: { user: { sessions: true } } }); + const memberData = members.map((x) => { + return { + id: x.id, + username: x.user.username, + discriminator: x.user.discriminator, + avatar: x.user.avatar, + status: "online", // TODO + avatar_url: x.user.avatar ? `${Config.get().cdn.endpointPublic}/avatars/${x.id}/${x.user.avatar}.png` : undefined, + }; + }); // Construct object to respond with const data = { @@ -107,8 +117,8 @@ router.get( name: guild.name, instant_invite: invite?.code, channels: channels, - members: members, - presence_count: guild.presence_count, + members: memberData, + presence_count: guild.presence_count || members.filter((m) => m.user.sessions.filter((s) => (s.last_seen?.getTime() ?? 0) > Date.now() - 1000 * 60)).length, }; res.set("Cache-Control", "public, max-age=300");