diff --git a/.env.example b/.env.example index 21aae90..25f8efe 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,6 @@ PORT=8080 REDIS_URL=redis://username:password@localhost:6379 REDIS_TTL=3600 # seconds + +# if you wish to get discord badges +DISCORD_TOKEN=discord_bot_token diff --git a/README.md b/README.md index ab230e9..5084653 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,9 @@ REDIS_URL=redis://username:password@localhost:6379 # Value is in seconds REDIS_TTL=3600 + +#only use this if you want to show discord badges +DISCORD_TOKEN=discord_bot_token ``` ## Endpoint diff --git a/config/discordBadges.ts b/config/discordBadges.ts new file mode 100644 index 0000000..7e0e258 --- /dev/null +++ b/config/discordBadges.ts @@ -0,0 +1,87 @@ +export const discordBadges = { + // User badges + HYPESQUAD: 2 << 2, + HYPESQUAD_ONLINE_HOUSE_1: 2 << 6, + HYPESQUAD_ONLINE_HOUSE_2: 2 << 7, + HYPESQUAD_ONLINE_HOUSE_3: 2 << 8, + + STAFF: 2 << 0, + PARTNER: 2 << 1, + CERTIFIED_MODERATOR: 2 << 18, + + VERIFIED_DEVELOPER: 2 << 17, + ACTIVE_DEVELOPER: 2 << 22, + + PREMIUM_EARLY_SUPPORTER: 2 << 9, + + BUG_HUNTER_LEVEL_1: 2 << 3, + BUG_HUNTER_LEVEL_2: 2 << 14, + + // Bot badges + SUPPORTS_COMMANDS: 2 << 23, + USES_AUTOMOD: 2 << 24, +}; + +export const discordBadgeDetails = { + HYPESQUAD: { + tooltip: "HypeSquad Events", + icon: "/public/badges/discord/HYPESQUAD.svg", + }, + HYPESQUAD_ONLINE_HOUSE_1: { + tooltip: "HypeSquad Bravery", + icon: "/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_1.svg", + }, + HYPESQUAD_ONLINE_HOUSE_2: { + tooltip: "HypeSquad Brilliance", + icon: "/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_2.svg", + }, + HYPESQUAD_ONLINE_HOUSE_3: { + tooltip: "HypeSquad Balance", + icon: "/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_3.svg", + }, + + STAFF: { + tooltip: "Discord Staff", + icon: "/public/badges/discord/STAFF.svg", + }, + PARTNER: { + tooltip: "Discord Partner", + icon: "/public/badges/discord/PARTNER.svg", + }, + CERTIFIED_MODERATOR: { + tooltip: "Certified Moderator", + icon: "/public/badges/discord/CERTIFIED_MODERATOR.svg", + }, + + VERIFIED_DEVELOPER: { + tooltip: "Verified Bot Developer", + icon: "/public/badges/discord/VERIFIED_DEVELOPER.svg", + }, + ACTIVE_DEVELOPER: { + tooltip: "Active Developer", + icon: "/public/badges/discord/ACTIVE_DEVELOPER.svg", + }, + + PREMIUM_EARLY_SUPPORTER: { + tooltip: "Premium Early Supporter", + icon: "/public/badges/discord/PREMIUM_EARLY_SUPPORTER.svg", + }, + + BUG_HUNTER_LEVEL_1: { + tooltip: "Bug Hunter (Level 1)", + icon: "/public/badges/discord/BUG_HUNTER_LEVEL_1.svg", + }, + BUG_HUNTER_LEVEL_2: { + tooltip: "Bug Hunter (Level 2)", + icon: "/public/badges/discord/BUG_HUNTER_LEVEL_2.svg", + }, + + SUPPORTS_COMMANDS: { + tooltip: "Supports Commands", + icon: "/public/badges/discord/SUPPORTS_COMMANDS.svg", + }, + USES_AUTOMOD: { + tooltip: "Uses AutoMod", + icon: "/public/badges/discord/USES_AUTOMOD.svg", + }, +}; diff --git a/config/environment.ts b/config/environment.ts index 7591352..6b056d6 100644 --- a/config/environment.ts +++ b/config/environment.ts @@ -34,4 +34,10 @@ export const badgeServices: badgeURLMap[] = [ `https://raw.githubusercontent.com/enmity-mod/badges/main/data/${id}.json`, }), }, + { + service: "Discord", + url: (userId: string) => `https://discord.com/api/v10/users/${userId}`, + }, ]; + +export const botToken: string | undefined = process.env.DISCORD_TOKEN; diff --git a/public/badges/discord/ACTIVE_DEVELOPER.svg b/public/badges/discord/ACTIVE_DEVELOPER.svg new file mode 100644 index 0000000..80aa677 --- /dev/null +++ b/public/badges/discord/ACTIVE_DEVELOPER.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/public/badges/discord/BUG_HUNTER_LEVEL_1.svg b/public/badges/discord/BUG_HUNTER_LEVEL_1.svg new file mode 100644 index 0000000..ca75a4e --- /dev/null +++ b/public/badges/discord/BUG_HUNTER_LEVEL_1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/BUG_HUNTER_LEVEL_2.svg b/public/badges/discord/BUG_HUNTER_LEVEL_2.svg new file mode 100644 index 0000000..1c80182 --- /dev/null +++ b/public/badges/discord/BUG_HUNTER_LEVEL_2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/CERTIFIED_MODERATOR.svg b/public/badges/discord/CERTIFIED_MODERATOR.svg new file mode 100644 index 0000000..6f634b2 --- /dev/null +++ b/public/badges/discord/CERTIFIED_MODERATOR.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/HYPESQUAD.svg b/public/badges/discord/HYPESQUAD.svg new file mode 100644 index 0000000..85bec04 --- /dev/null +++ b/public/badges/discord/HYPESQUAD.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_1.svg b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_1.svg new file mode 100644 index 0000000..91fd024 --- /dev/null +++ b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_2.svg b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_2.svg new file mode 100644 index 0000000..d0713bb --- /dev/null +++ b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_3.svg b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_3.svg new file mode 100644 index 0000000..01e4805 --- /dev/null +++ b/public/badges/discord/HYPESQUAD_ONLINE_HOUSE_3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/NITRO.svg b/public/badges/discord/NITRO.svg new file mode 100644 index 0000000..98b54ab --- /dev/null +++ b/public/badges/discord/NITRO.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/PARTNER.svg b/public/badges/discord/PARTNER.svg new file mode 100644 index 0000000..35facaf --- /dev/null +++ b/public/badges/discord/PARTNER.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/PREMIUM_EARLY_SUPPORTER.svg b/public/badges/discord/PREMIUM_EARLY_SUPPORTER.svg new file mode 100644 index 0000000..8cd0cda --- /dev/null +++ b/public/badges/discord/PREMIUM_EARLY_SUPPORTER.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/STAFF.svg b/public/badges/discord/STAFF.svg new file mode 100644 index 0000000..d65b724 --- /dev/null +++ b/public/badges/discord/STAFF.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/SUPPORTS_COMMANDS.svg b/public/badges/discord/SUPPORTS_COMMANDS.svg new file mode 100644 index 0000000..55e0c7b --- /dev/null +++ b/public/badges/discord/SUPPORTS_COMMANDS.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/badges/discord/USES_AUTOMOD.svg b/public/badges/discord/USES_AUTOMOD.svg new file mode 100644 index 0000000..e220934 --- /dev/null +++ b/public/badges/discord/USES_AUTOMOD.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/badges/discord/VERIFIED_DEVELOPER.svg b/public/badges/discord/VERIFIED_DEVELOPER.svg new file mode 100644 index 0000000..4ec174f --- /dev/null +++ b/public/badges/discord/VERIFIED_DEVELOPER.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/helpers/badges.ts b/src/helpers/badges.ts index fb0208b..68d5ce4 100644 --- a/src/helpers/badges.ts +++ b/src/helpers/badges.ts @@ -1,10 +1,12 @@ -import { badgeServices, redisTtl } from "@config/environment"; +import { discordBadgeDetails, discordBadges } from "@config/discordBadges"; +import { badgeServices, botToken, redisTtl } from "@config/environment"; import { fetch, redis } from "bun"; export async function fetchBadges( userId: string, services: string[], options?: FetchBadgesOptions, + request?: Request, ): Promise { const { nocache = false, separated = false } = options ?? {}; const results: Record = {}; @@ -127,6 +129,38 @@ export async function fetchBadges( ); break; } + + case "discord": { + if (!botToken) break; + + const res = await fetch(url as string, { + headers: { + Authorization: `Bot ${botToken}`, + }, + }); + if (!res.ok) break; + + const data = await res.json(); + + if (data.avatar.startsWith("a_")) { + result.push({ + tooltip: "Discord Nitro", + badge: `${request ? new URL(request.url).origin : ""}/public/badges/discord/NITRO.svg`, + }); + } + + for (const [flag, bitwise] of Object.entries(discordBadges)) { + if (data.flags & bitwise) { + const badge = + discordBadgeDetails[flag as keyof typeof discordBadgeDetails]; + result.push({ + tooltip: badge.tooltip, + badge: `${request ? new URL(request.url).origin : ""}${badge.icon}`, + }); + } + } + break; + } } if (result.length > 0) { diff --git a/src/routes/[id].ts b/src/routes/[id].ts index af6a621..4b8421e 100644 --- a/src/routes/[id].ts +++ b/src/routes/[id].ts @@ -58,10 +58,15 @@ async function handler(request: ExtendedRequest): Promise { validServices = badgeServices.map((b) => b.service); } - const badges: BadgeResult = await fetchBadges(userId, validServices, { - nocache: cache !== "true", - separated: seperated === "true", - }); + const badges: BadgeResult = await fetchBadges( + userId, + validServices, + { + nocache: cache !== "true", + separated: seperated === "true", + }, + request, + ); if (badges instanceof Error) { return Response.json(