Skip to content

Commit

Permalink
feat: modified discord i/o in the core package
Browse files Browse the repository at this point in the history
  • Loading branch information
PoulavBhowmick03 committed Jan 28, 2025
1 parent 0bc8420 commit 910079b
Showing 1 changed file with 206 additions and 5 deletions.
211 changes: 206 additions & 5 deletions packages/core/src/core/io/discord.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { Client, Events, GatewayIntentBits, Partials, User } from "discord.js";
import {
Client,
GatewayIntentBits,
Events,
Message,
ChannelType,
Partials,
TextChannel,
GuildMember,
} from "discord.js";
import type { JSONSchemaType } from "ajv";
import { Logger } from "../../core/logger";
import { LogLevel } from "../types";
Expand All @@ -19,6 +28,40 @@ export interface EventCallbacks {
messageCreate?: (bot: any, message: any) => void;
}

export interface ReactionData {
emoji: string;
messageId: string;
userId: string;
}

export interface GuildMemberData {
userId: string;
username: string;
action: "join" | "leave";
}

export interface VoiceStateData {
guildId?: string;
userId: string;
channelId: string;
action: "join" | "leave" | "move";
}

export interface RoleData {
guildId: string;
userId: string;
roleId: string;
action: "add" | "remove";
}

export interface ChannelData {
guildId: string;
action: "create" | "delete";
name?: string;
type?: ChannelType;
channelId?: string;
}

// Schema for message output validation
export const messageSchema: JSONSchemaType<MessageData> = {
type: "object",
Expand All @@ -34,6 +77,7 @@ export const messageSchema: JSONSchemaType<MessageData> = {

export class DiscordClient {
private client: Client;
private isInitialized: boolean = false;
private logger: Logger;

constructor(
Expand Down Expand Up @@ -63,7 +107,9 @@ export class DiscordClient {
if (eventCallbacks.messageCreate) {
this.client.on(Events.MessageCreate, (message) => {
if (eventCallbacks.messageCreate) {
eventCallbacks.messageCreate(this.client.user, message);
if (this.client?.user) {
eventCallbacks.messageCreate(this.client.user, message);
}
}
});
}
Expand All @@ -79,11 +125,47 @@ export class DiscordClient {
}

public destroy() {
this.client.destroy();
this.client?.destroy();
}

/**
* Create an input that monitors messages
*/
public createMessageInput(interval: number = 60000, channelId?: string) {
return {
name: `discord_messages_${channelId || "all"}`,
handler: async () => {
return this.monitorMessages(channelId);
},
response: {
type: "string",
content: "string",
metadata: "object",
},
interval,
};
}

/**
* Create an output for sending messages
* Create an output for monitoring joining or leaving of guild members
*/
public createGuildMemberInput() {
return {
name: "discord_guild_members",
handler: async () => {
return this.monitorGuildMembers();
},
response: {
type: "string",
userId: "string",
username: "string",
action: "string",
},
};
}

/**
* Create an output for sending messages to a channel
*/
public createMessageOutput() {
return {
Expand All @@ -99,6 +181,77 @@ export class DiscordClient {
};
}

private async monitorMessages(channelId?: string): Promise<MessageData[]> {
try {
this.logger.debug(
"DiscordClient.monitorMessages",
"Monitoring messages",
{ channelId }
);

const messages: Message[] = [];

if (channelId) {
// Fetch the channel and validate it
const channel = await this.client?.channels.fetch(channelId);
if (!channel || !channel.isTextBased()) {
throw new Error(
"Invalid channel or channel is not text-based"
);
}

const textChannel = channel as TextChannel;

// Create a promise that resolves when the message collector ends
const collectedMessages = await new Promise<Message[]>(
(resolve) => {
const messageCollector =
textChannel.createMessageCollector({
time: 60000, // Collect messages for 60 seconds
});

messageCollector.on("collect", (message) => {
messages.push(message);
});

messageCollector.on("end", () => {
this.logger.debug(
"DiscordClient.monitorMessages",
"Collected messages",
{ count: messages.length }
);
resolve(messages); // Resolve the promise with the collected messages
});
}
);

return collectedMessages.map(this.formatMessageData);
} else {
// Handle global message collection (no specific channel)
return new Promise<MessageData[]>((resolve) => {
const messageHandler = (message: Message) => {
messages.push(message);
};

this.client?.on("messageCreate", messageHandler);

// Optionally, you can add a timeout or condition to stop listening
setTimeout(() => {
this.client?.off("messageCreate", messageHandler); // Stop listening
resolve(messages.map(this.formatMessageData)); // Resolve with collected messages
}, 60000); // Stop after 60 seconds
});
}
} catch (error) {
this.logger.error(
"DiscordClient.monitorMessages",
"Error monitoring messages",
{ error }
);
throw error;
}
}

private async sendMessage(data: MessageData) {
try {
this.logger.info(
Expand Down Expand Up @@ -147,14 +300,62 @@ export class DiscordClient {
throw error;
}
}

private async monitorGuildMembers(): Promise<GuildMemberData> {
return new Promise((resolve, reject) => {
try {
this.logger.debug(
"DiscordClient.monitorGuildMembers",
"Monitoring guild members"
);

const handleMemberEvent = (
member: GuildMember,
action: "join" | "leave"
) => {
const memberData: GuildMemberData = {
userId: member.id,
username: member.user.username,
action,
};
resolve(memberData);
};

this.client?.on("guildMemberAdd", (member) =>
handleMemberEvent(member as GuildMember, "join")
);
this.client?.on("guildMemberRemove", (member) =>
handleMemberEvent(member as GuildMember, "leave")
);
} catch (error) {
this.logger.error(
"DiscordClient.monitorGuildMembers",
"Error monitoring guild members",
{ error }
);
reject(error);
}
});
}
private formatMessageData(message: Message): MessageData {
return {
content: message.content,
channelId: message.channel.id,
sendBy: message.author.id,
};
}
}

// Example usage:
/*
const discord = new DiscordClient({
discord_token: "M..."
discord_token: process.env.DISCORD_TOKEN || "",
});
// Register inputs
core.createMessageInput("CHANNEL_ID");
core.createGuildMemberInput();
// Register output
core.registerOutput(discord.createMessageOutput());
*/

0 comments on commit 910079b

Please sign in to comment.