feat: message structure

This commit is contained in:
Yuzu 2022-06-22 19:53:39 -05:00
parent 781ef10e8c
commit 5083ce45a5
10 changed files with 180 additions and 22 deletions

View File

@ -0,0 +1 @@
export * from "./MessageRelated.ts";

View File

@ -0,0 +1,18 @@
import type { DiscordMessage, DiscordReady } from "../vendor/external.ts";
import type { Session } from "../session/Session.ts";
import { Message } from "../structures/Message.ts";
type Handler<T> = (...args: [ Session, number, T ]) => void;
// TODO: move this lol
export const READY: Handler<DiscordReady> = (session, shardId, payload) => {
session.emit("ready", shardId, payload);
};
export const MESSAGE_CREATE: Handler<DiscordMessage> = (session, _shardId, message) => {
session.emit("messageCreate", new Message(session, message));
};
export const raw: Handler<unknown> = (session, shardId, data) => {
session.emit("raw", data, shardId);
}

View File

2
mod.ts
View File

@ -1,5 +1,3 @@
export * from "./session/mod.ts";
export * from "./util/mod.ts";
export * from "./structures/mod.ts";
export * from "./vendor/external.ts";
export * from "./handlers/mod.ts";

View File

@ -1,9 +1,10 @@
import type { DiscordGatewayPayload, DiscordMessage, DiscordReady, Shard } from "../vendor/external.ts";
import type { DiscordGatewayPayload, DiscordReady, Shard } from "../vendor/external.ts";
import type { Message } from "../structures/Message.ts";
export type DiscordRawEventHandler = (shard: Shard, data: DiscordGatewayPayload) => unknown;
export interface Events {
ready(payload: DiscordReady, shardId: number): unknown;
messageCreate(message: DiscordMessage): unknown;
ready(shardId: number, payload: DiscordReady): unknown;
messageCreate(message: Message): unknown;
raw(data: DiscordGatewayPayload, shardId: number): unknown;
}

View File

@ -1,12 +1,7 @@
import type {
DiscordGatewayPayload,
DiscordGetGatewayBot,
DiscordMessage,
DiscordReady,
GatewayBot,
GatewayDispatchEventNames,
GatewayIntents,
Shard,
} from "../vendor/external.ts";
import { EventEmitter, Routes, Snowflake } from "../util/mod.ts";
@ -15,6 +10,8 @@ import type { DiscordRawEventHandler, Events } from "./Events.ts";
import { createGatewayManager, createRestManager } from "../vendor/external.ts";
import * as Actions from "../handlers/HandlerManager.ts";
export interface RestOptions {
secretKey?: string;
applicationId?: Snowflake;
@ -48,11 +45,14 @@ export class Session extends EventEmitter {
this.options = options;
const defHandler: DiscordRawEventHandler = (shard, data) => {
this.emit("raw", data, shard.id);
Actions.raw(this, shard.id, data);
if (!data.t) return;
if (!data.t) {
return;
}
this.emit(data.t as GatewayDispatchEventNames, data, shard.id);
// deno-lint-ignore no-explicit-any
Actions[data.t as keyof typeof Actions]?.(this, shard.id, data.d as any);
};
this.rest = createRestManager({
@ -75,31 +75,25 @@ export class Session extends EventEmitter {
// TODO: set botId in Session.botId or something
}
/** TODO: move this */
static #toSnakeCase(str: string) {
// probably not a fast implementation
return str.replace(/[A-Z]/g, (char) => "_" + char.toLowerCase());
}
override on(event: "ready", func: Events["ready"]): this;
override on(event: "messageCreate", func: Events["messageCreate"]): this;
override on(event: "raw", func: Events["raw"]): this;
override on(event: keyof Events, func: Events[keyof Events]): this {
return super.on(Session.#toSnakeCase(event).toUpperCase(), func);
return super.on(event, func);
}
override off(event: "ready", func: Events["ready"]): this;
override off(event: "messageCreate", func: Events["messageCreate"]): this;
override off(event: "raw", func: Events["raw"]): this;
override off(event: keyof Events, func: Events[keyof Events]): this {
return super.off(Session.#toSnakeCase(event).toUpperCase(), func);
return super.off(event, func);
}
override once(event: "ready", func: Events["ready"]): this;
override once(event: "messageCreate", func: Events["messageCreate"]): this;
override once(event: "raw", func: Events["raw"]): this;
override once(event: keyof Events, func: Events[keyof Events]): this {
return super.once(Session.#toSnakeCase(event).toUpperCase(), func);
return super.once(event, func);
}
async start() {

12
structures/Base.ts Normal file
View File

@ -0,0 +1,12 @@
import type { Snowflake } from "../util/mod.ts";
import type { Session } from "../session/mod.ts";
/**
* Represents a Discord data model
* */
export interface Base {
/** id of the model */
id: Snowflake;
/** reference to the client that instantiated the model */
session: Session;
}

94
structures/Message.ts Normal file
View File

@ -0,0 +1,94 @@
import type { Base } from "./Base.ts";
import type { Snowflake } from "../util/Snowflake.ts";
import type { Session } from "../session/mod.ts";
import type { DiscordMessage, AllowedMentionsTypes } from "../vendor/external.ts";
import { Routes } from "../util/mod.ts";
/**
* @link https://discord.com/developers/docs/resources/channel#allowed-mentions-object
* */
export interface AllowedMentions {
parse?: AllowedMentionsTypes[];
repliedUser?: boolean;
roles?: Snowflake[];
users?: Snowflake[];
}
/**
* @link https://discord.com/developers/docs/resources/channel#edit-message-json-params
* */
export interface EditMessage {
content?: string;
allowedMentions?: AllowedMentions;
}
/**
* @link https://discord.com/developers/docs/resources/channel#create-message-json-params
* */
export interface CreateMessage {
content?: string;
allowedMentions?: AllowedMentions;
}
/**
* Represents a message
* @link https://discord.com/developers/docs/resources/channel#message-object
* */
export class Message implements Base {
constructor(session: Session, data: DiscordMessage) {
this.session = session;
this.id = data.id;
this.channelId = data.channel_id;
}
/** the session that instantiated the message */
session: Session;
/** the id of the message */
id: Snowflake;
/** the id of the channel where the message was sent */
channelId: Snowflake;
/** Edits the current message */
async edit({ content, allowedMentions }: EditMessage): Promise<Message> {
const message = await this.session.rest.runMethod(
this.session.rest,
"POST",
Routes.CHANNEL_MESSAGE(this.id, this.channelId),
{
content,
allowed_mentions: {
parse: allowedMentions?.parse,
roles: allowedMentions?.roles,
users: allowedMentions?.users,
replied_user: allowedMentions?.repliedUser,
},
}
);
return message;
}
/** Responds directly in the channel the message was sent */
async respond({ content, allowedMentions }: CreateMessage): Promise<Message> {
const message = await this.session.rest.runMethod(
this.session.rest,
"POST",
Routes.CHANNEL_MESSAGES(this.channelId),
{
content,
allowed_mentions: {
parse: allowedMentions?.parse,
roles: allowedMentions?.roles,
users: allowedMentions?.users,
replied_user: allowedMentions?.repliedUser,
},
}
);
return message;
}
}

View File

View File

@ -1,3 +1,43 @@
import type { Snowflake } from "./Snowflake.ts";
export function GATEWAY_BOT() {
return "/gateway/bot";
}
export interface GetMessagesOptions {
limit?: number;
}
export interface GetMessagesOptions {
around?: Snowflake;
limit?: number;
}
export interface GetMessagesOptions {
before?: Snowflake;
limit?: number;
}
export interface GetMessagesOptions {
after?: Snowflake;
limit?: number;
}
/** used to send messages */
export function CHANNEL_MESSAGES(channelId: Snowflake, options?: GetMessagesOptions) {
let url = `/channels/${channelId}/messages?`;
if (options) {
if ("after" in options && options.after) url += `after=${options.after}`;
if ("before" in options && options.before) url += `&before=${options.before}`;
if ("around" in options && options.around) url += `&around=${options.around}`;
if ("limit" in options && options.limit) url += `&limit=${options.limit}`;
}
return url;
}
/** used to edit messages */
export function CHANNEL_MESSAGE(channelId: Snowflake, messageId: Snowflake) {
return `/channels/${channelId}/messages/${messageId}`;
}