Website Status
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import { Client, Partials, GatewayIntentBits, ActivityType } from "discord.js";
|
||||
|
||||
import { DISCORD_TOKEN, DISCORD_USER_ID, DISCORD_GUILD_ID } from "$env/static/private";
|
||||
|
||||
class Bot {
|
||||
private client: Client;
|
||||
|
||||
// Normalize a discord.js Activity object into a simple POJO
|
||||
private mapActivity(a: any) {
|
||||
const type = typeof a.type === 'number' ? a.type : (ActivityType[a.type] ?? a.type);
|
||||
const application_id = a.applicationId ?? a.application_id ?? null;
|
||||
|
||||
const rawLarge = a.assets?.largeImage ?? a.assets?.large_image ?? null;
|
||||
const rawSmall = a.assets?.smallImage ?? a.assets?.small_image ?? null;
|
||||
|
||||
const formatAsset = (raw: string | null) => {
|
||||
if (!raw) return null;
|
||||
if (raw.startsWith('mp:external/')) {
|
||||
return `https://media.discordapp.net/${raw.replace(/^mp:/, '')}`;
|
||||
}
|
||||
if (/^https?:\/\//.test(raw)) return raw;
|
||||
if (application_id) return `https://cdn.discordapp.com/app-assets/${application_id}/${raw}.webp`;
|
||||
return raw;
|
||||
};
|
||||
|
||||
return {
|
||||
name: a.name ?? null,
|
||||
type,
|
||||
details: a.details ?? a.state ?? null,
|
||||
url: a.url ?? null,
|
||||
application_id,
|
||||
assets: {
|
||||
large_image: formatAsset(rawLarge),
|
||||
small_image: formatAsset(rawSmall)
|
||||
},
|
||||
emoji: a.emoji ? { id: a.emoji.id ?? null, animated: !!a.emoji.animated } : null
|
||||
};
|
||||
}
|
||||
|
||||
constructor() {
|
||||
// Need presence and members intents to read user presence/activity
|
||||
this.client = new Client({
|
||||
partials: [Partials.User],
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildMembers,
|
||||
GatewayIntentBits.GuildPresences
|
||||
]
|
||||
});
|
||||
|
||||
this.client.login(DISCORD_TOKEN).catch((error) => {
|
||||
console.error("Failed to login to Discord:", error);
|
||||
});
|
||||
|
||||
this.client.once("clientReady", async () => {
|
||||
console.log(`Logged in as ${this.client.user?.tag}`);
|
||||
});
|
||||
}
|
||||
|
||||
getClient(): Client {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up the user's presence specifically in the given guild.
|
||||
* Returns null if guild/member/presence not available.
|
||||
*/
|
||||
async getUserActivityInGuild(guildId: string = DISCORD_GUILD_ID, userId: string = DISCORD_USER_ID) {
|
||||
try {
|
||||
// Fetch guild from cache or API
|
||||
let guild = this.client.guilds.cache.get(guildId) || await this.client.guilds.fetch(guildId).catch(() => null);
|
||||
if (!guild) return null;
|
||||
|
||||
// Fetch member (will populate presence if available)
|
||||
const member = await guild.members.fetch(userId).catch(() => null);
|
||||
if (!member) return null;
|
||||
|
||||
const presence = member.presence;
|
||||
const user = member.user;
|
||||
|
||||
// Build avatar URL
|
||||
const avatarHash = user.avatar;
|
||||
const avatarUrl = avatarHash
|
||||
? `https://cdn.discordapp.com/avatars/${user.id}/${avatarHash}.${avatarHash.startsWith('a_') ? 'gif' : 'webp'}?size=128`
|
||||
: `https://cdn.discordapp.com/embed/avatars/${(BigInt(user.id) >> BigInt(22)) % BigInt(6)}.png`;
|
||||
|
||||
// Get guild/clan tag if available
|
||||
const guildTag = (user as any).primaryGuild?.tag ?? null;
|
||||
const guildTagBadgeImage = `https://cdn.discordapp.com/clan-badges/${(user as any).primaryGuild?.identityGuildId}/${(user as any).primaryGuild?.badge}.png?size=32`;
|
||||
|
||||
if (!presence) return { guildId, status: 'offline', activities: [], displayName: member.displayName, avatarUrl, guildTag, guildTagBadgeImage };
|
||||
|
||||
const status = presence.status;
|
||||
const activities = (presence.activities || []).map((a: any) => this.mapActivity(a));
|
||||
|
||||
return { guildId, status, activities, displayName: member.displayName, avatarUrl, guildTag, guildTagBadgeImage };
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const bot = new Bot();
|
||||
|
||||
// Re-export image helper for convenience
|
||||
export { fetchUserImages } from "./discord/fetchUserImages";
|
||||
Reference in New Issue
Block a user