feacture: Builders

fix: fmt
This commit is contained in:
socram03 2022-07-04 19:34:55 -04:00
parent 9a5a25c2d5
commit 35ec425916
18 changed files with 296 additions and 64 deletions

View File

@ -1,7 +1,7 @@
{
"fmt": {
"files": {
"exclude": "vendor"
"exclude": ["vendor"]
},
"options": {
"indentWidth": 4,

View File

@ -1,17 +1,16 @@
import type {
DiscordChannel,
DiscordChannelPinsUpdate,
DiscordEmoji,
DiscordGuild,
DiscordGuildBanAddRemove,
DiscordGuildEmojisUpdate,
DiscordGuildMemberAdd,
DiscordGuildMemberRemove,
DiscordGuildMemberUpdate,
DiscordGuildBanAddRemove,
DiscordGuildEmojisUpdate,
DiscordGuildRoleCreate,
DiscordGuildRoleUpdate,
DiscordGuildRoleDelete,
DiscordUser,
DiscordEmoji,
DiscordGuildRoleUpdate,
DiscordInteraction,
DiscordMemberWithUser,
DiscordMessage,
@ -25,7 +24,8 @@ import type {
// DiscordThreadMemberUpdate,
// DiscordThreadMembersUpdate,
DiscordThreadListSync,
DiscordWebhookUpdate
DiscordUser,
DiscordWebhookUpdate,
} from "../vendor/external.ts";
import type { Snowflake } from "../util/Snowflake.ts";
import type { Session } from "../session/Session.ts";
@ -37,7 +37,7 @@ import ThreadMember from "../structures/ThreadMember.ts";
import Member from "../structures/Member.ts";
import Message from "../structures/Message.ts";
import User from "../structures/User.ts";
import Guild from "../structures/guilds/Guild.ts";
import Guild from "../structures/guilds/Guild.ts";
import Interaction from "../structures/interactions/Interaction.ts";
export type RawHandler<T> = (...args: [Session, number, T]) => void;
@ -90,20 +90,20 @@ export const GUILD_BAN_REMOVE: RawHandler<DiscordGuildBanAddRemove> = (session,
};
export const GUILD_EMOJIS_UPDATE: RawHandler<DiscordGuildEmojisUpdate> = (session, _shardId, data) => {
session.emit("guildEmojisUpdate", { guildId: data.guild_id, emojis: data.emojis})
session.emit("guildEmojisUpdate", { guildId: data.guild_id, emojis: data.emojis });
};
export const GUILD_ROLE_CREATE: RawHandler<DiscordGuildRoleCreate> = (session, _shardId, data) => {
session.emit("guildRoleCreate", { guildId: data.guild_id, role: data.role });
}
};
export const GUILD_ROLE_UPDATE: RawHandler<DiscordGuildRoleUpdate> = (session, _shardId, data) => {
session.emit("guildRoleUpdate", { guildId: data.guild_id, role: data.role });
}
};
export const GUILD_ROLE_DELETE: RawHandler<DiscordGuildRoleDelete> = (session, _shardId, data) => {
session.emit("guildRoleDelete", { guildId: data.guild_id, roleId: data.role_id });
}
};
export const INTERACTION_CREATE: RawHandler<DiscordInteraction> = (session, _shardId, interaction) => {
session.unrepliedInteractions.add(BigInt(interaction.id));
@ -164,7 +164,7 @@ export const CHANNEL_PINS_UPDATE: RawHandler<DiscordChannelPinsUpdate> = (sessio
};
export const WEBHOOKS_UPDATE: RawHandler<DiscordWebhookUpdate> = (session, _shardId, webhook) => {
session.emit("webhooksUpdate", { guildId: webhook.guild_id, channelId: webhook.channel_id })
session.emit("webhooksUpdate", { guildId: webhook.guild_id, channelId: webhook.channel_id });
};
/*

5
mod.ts
View File

@ -36,6 +36,11 @@ export * from "./structures/guilds/Guild.ts";
export * from "./structures/guilds/InviteGuild.ts";
export * from "./structures/builders/EmbedBuilder.ts";
export * from "./structures/builders/InputTextComponentBuilder.ts";
export * from "./structures/builders/MessageActionRow.ts";
export * from "./structures/builders/MessageButton.ts";
export * from "./structures/builders/MessageSelectMenu.ts";
export * from "./structures/builders/SelectMenuOptionBuilder.ts";
export * from "./structures/interactions/Interaction.ts";

View File

@ -6,8 +6,8 @@ import type {
DiscordMessage,
DiscordUser,
FileContent,
MessageTypes,
MessageActivityTypes,
MessageTypes,
} from "../vendor/external.ts";
import type { Component } from "./components/Component.ts";
import type { GetReactions } from "../util/Routes.ts";
@ -181,7 +181,6 @@ export class Message implements Model {
return this.editedTimestamp;
}
get url() {
return `https://discord.com/channels/${this.guildId ?? "@me"}/${this.channelId}/${this.id}`;
}

View File

@ -5,7 +5,7 @@ import Emoji from "./Emoji.ts";
/**
* Represents a reaction
* @link https://discord.com/developers/docs/resources/channel#reaction-object
* */
*/
export class MessageReaction {
constructor(session: Session, data: DiscordReaction) {
this.session = session;

View File

@ -39,15 +39,15 @@ export class StageInstance implements Model {
discoverableDisabled: boolean;
guildScheduledEventId: Snowflake;
async edit(options: { topic?: string, privacyLevel?: PrivacyLevels }) {
async edit(options: { topic?: string; privacyLevel?: PrivacyLevels }) {
const stageInstance = await this.session.rest.runMethod<DiscordStageInstance>(
this.session.rest,
"PATCH",
Routes.STAGE_INSTANCE(this.id),
{
topic: options.topic,
privacy_level: options.privacyLevel
}
privacy_level: options.privacyLevel,
},
);
return new StageInstance(this.session, stageInstance);

View File

@ -0,0 +1,49 @@
import { DiscordInputTextComponent, MessageComponentTypes, TextStyles } from "../../vendor/external.ts";
export class InputTextBuilder {
constructor() {
this.#data = {} as DiscordInputTextComponent;
this.type = 4;
}
#data: DiscordInputTextComponent;
type: MessageComponentTypes.InputText;
setStyle(style: TextStyles) {
this.#data.style = style;
return this;
}
setLabel(label: string) {
this.#data.label = label;
return this;
}
setPlaceholder(placeholder: string) {
this.#data.placeholder = placeholder;
return this;
}
setLength(max?: number, min?: number) {
this.#data.max_length = max;
this.#data.min_length = min;
return this;
}
setCustomId(id: string) {
this.#data.custom_id = id;
return this;
}
setValue(value: string) {
this.#data.value = value;
return this;
}
setRequired(required = true) {
this.#data.required = required;
return this;
}
toJSON() {
return { ...this.#data };
}
}

View File

@ -0,0 +1,29 @@
import { MessageComponentTypes } from "../../vendor/external.ts";
import { AnyComponentBuilder } from "../../util/builders.ts";
export class ActionRowBuilder<T extends AnyComponentBuilder> {
constructor() {
this.components = [] as T[];
this.type = 1;
}
components: T[];
type: MessageComponentTypes.ActionRow;
addComponents(...components: T[]) {
this.components.push(...components);
return this;
}
setComponents(...components: T[]) {
this.components.splice(
0,
this.components.length,
...components,
);
return this;
}
toJSON() {
return { type: this.type, components: this.components.map((c) => c.toJSON()) };
}
}

View File

@ -0,0 +1,44 @@
import { ButtonStyles, type DiscordButtonComponent, MessageComponentTypes } from "../../vendor/external.ts";
import { ComponentEmoji } from "../../util/builders.ts";
export class ButtonBuilder {
constructor() {
this.#data = {} as DiscordButtonComponent;
this.type = 2;
}
#data: DiscordButtonComponent;
type: MessageComponentTypes.Button;
setStyle(style: ButtonStyles) {
this.#data.style = style;
return this;
}
setLabel(label: string) {
this.#data.label = label;
return this;
}
setCustomId(id: string) {
this.#data.custom_id = id;
return this;
}
setEmoji(emoji: ComponentEmoji) {
this.#data.emoji = emoji;
return this;
}
setDisabled(disabled = true) {
this.#data.disabled = disabled;
return this;
}
setURL(url: string) {
this.#data.url = url;
return this;
}
toJSON(): DiscordButtonComponent {
return { ...this.#data };
}
}

View File

@ -0,0 +1,53 @@
import { type DiscordSelectMenuComponent, MessageComponentTypes } from "../../vendor/external.ts";
import { SelectMenuOptionBuilder } from "./SelectMenuOptionBuilder.ts";
export class SelectMenuBuilder {
constructor() {
this.#data = {} as DiscordSelectMenuComponent;
this.type = 3;
this.options = [];
}
#data: DiscordSelectMenuComponent;
type: MessageComponentTypes.SelectMenu;
options: SelectMenuOptionBuilder[];
setPlaceholder(placeholder: string) {
this.#data.placeholder = placeholder;
return this;
}
setValues(max?: number, min?: number) {
this.#data.max_values = max;
this.#data.min_values = min;
return this;
}
setDisabled(disabled = true) {
this.#data.disabled = disabled;
return this;
}
setCustomId(id: string) {
this.#data.custom_id = id;
return this;
}
setOptions(...options: SelectMenuOptionBuilder[]) {
this.options.splice(
0,
this.options.length,
...options,
);
return this;
}
addOptions(...options: SelectMenuOptionBuilder[]) {
this.options.push(
...options,
);
}
toJSON() {
return { ...this.#data, options: this.options.map((option) => option.toJSON()) };
}
}

View File

@ -0,0 +1,38 @@
import type { DiscordSelectOption } from "../../vendor/external.ts";
import type { ComponentEmoji } from "../../util/builders.ts";
export class SelectMenuOptionBuilder {
constructor() {
this.#data = {} as DiscordSelectOption;
}
#data: DiscordSelectOption;
setLabel(label: string) {
this.#data.label = label;
return this;
}
setValue(value: string) {
this.#data.value = value;
return this;
}
setDescription(description: string) {
this.#data.description = description;
return this;
}
setDefault(Default = true) {
this.#data.default = Default;
return this;
}
setEmoji(emoji: ComponentEmoji) {
this.#data.emoji = emoji;
return this;
}
toJSON() {
return { ...this.#data };
}
}

View File

@ -1,7 +1,12 @@
import type { Model } from "../Base.ts";
import type { Snowflake } from "../../util/Snowflake.ts";
import type { Session } from "../../session/Session.ts";
import type { ChannelTypes, DiscordChannel, DiscordInviteMetadata, DiscordListArchivedThreads } from "../../vendor/external.ts";
import type {
ChannelTypes,
DiscordChannel,
DiscordInviteMetadata,
DiscordListArchivedThreads,
} from "../../vendor/external.ts";
import type { ListArchivedThreads } from "../../util/Routes.ts";
import BaseChannel from "./BaseChannel.ts";
import ThreadChannel from "./ThreadChannel.ts";
@ -25,7 +30,7 @@ export interface ThreadCreateOptions {
/**
* Represents the option object to create a thread channel from a message
* @link https://discord.com/developers/docs/resources/channel#start-thread-from-message
* */
*/
export interface ThreadCreateOptions {
name: string;
autoArchiveDuration?: 60 | 1440 | 4320 | 10080;
@ -59,7 +64,6 @@ export class GuildChannel extends BaseChannel implements Model {
return invites.map((invite) => new Invite(this.session, invite));
}
async getArchivedThreads(options: ListArchivedThreads & { type: "public" | "private" | "privateJoinedThreads" }) {
let func: (channelId: Snowflake, options: ListArchivedThreads) => string;
@ -78,7 +82,7 @@ export class GuildChannel extends BaseChannel implements Model {
const { threads, members, has_more } = await this.session.rest.runMethod<DiscordListArchivedThreads>(
this.session.rest,
"GET",
func(this.id, options)
func(this.id, options),
);
return {

View File

@ -88,27 +88,27 @@ export class TextChannel {
* Mixin
*/
static applyTo(klass: Function, ignore: Array<keyof TextChannel> = []) {
const methods: Array<keyof TextChannel> = [
"fetchPins",
"createInvite",
"fetchMessages",
"sendTyping",
"pinMessage",
"unpinMessage",
"addReaction",
"removeReaction",
"nukeReactions",
"fetchPins",
"sendMessage",
"editMessage",
"createWebhook",
];
const methods: Array<keyof TextChannel> = [
"fetchPins",
"createInvite",
"fetchMessages",
"sendTyping",
"pinMessage",
"unpinMessage",
"addReaction",
"removeReaction",
"nukeReactions",
"fetchPins",
"sendMessage",
"editMessage",
"createWebhook",
];
for (const method of methods) {
if (ignore.includes(method)) continue;
for (const method of methods) {
if (ignore.includes(method)) continue;
klass.prototype[method] = TextChannel.prototype[method];
}
klass.prototype[method] = TextChannel.prototype[method];
}
}
async fetchPins(): Promise<Message[] | []> {

View File

@ -6,14 +6,14 @@ import type {
DiscordEmoji,
DiscordGuild,
DiscordInviteMetadata,
DiscordMemberWithUser,
DiscordRole,
DiscordListActiveThreads,
GuildFeatures,
SystemChannelFlags,
MakeRequired,
VideoQualityModes,
DiscordMemberWithUser,
DiscordOverwrite,
DiscordRole,
GuildFeatures,
MakeRequired,
SystemChannelFlags,
VideoQualityModes,
} from "../../vendor/external.ts";
import type { GetInvite } from "../../util/Routes.ts";
import {
@ -136,7 +136,7 @@ export interface GuildCreateOptionsChannel {
/**
* @link https://discord.com/developers/docs/resources/guild#create-guild
* */
*/
export interface GuildCreateOptions {
name: string;
afkChannelId?: Snowflake;
@ -167,7 +167,7 @@ export interface GuildCreateOptions {
/**
* @link https://discord.com/developers/docs/resources/guild#modify-guild-json-params
* */
*/
export interface GuildEditOptions extends Omit<GuildCreateOptions, "roles" | "channels"> {
ownerId?: Snowflake;
splashURL?: string;
@ -473,7 +473,7 @@ export class Guild extends BaseGuild implements Model {
const { threads, members } = await this.session.rest.runMethod<DiscordListActiveThreads>(
this.session.rest,
"GET",
Routes.THREAD_ACTIVE(this.id)
Routes.THREAD_ACTIVE(this.id),
);
return {
@ -488,13 +488,13 @@ export class Guild extends BaseGuild implements Model {
/***
* Makes the bot leave the guild
* */
*/
async leave() {
}
/***
* Deletes a guild
* */
*/
async delete() {
await this.session.rest.runMethod<undefined>(
this.session.rest,
@ -507,7 +507,7 @@ export class Guild extends BaseGuild implements Model {
* Creates a guild and returns its data, the bot joins the guild
* This was modified from discord.js to make it compatible
* precondition: Bot should be in less than 10 servers
* */
*/
static async create(session: Session, options: GuildCreateOptions) {
const guild = await session.rest.runMethod<DiscordGuild>(session.rest, "POST", Routes.GUILDS(), {
name: options.name,
@ -549,7 +549,7 @@ export class Guild extends BaseGuild implements Model {
/**
* Edits a guild and returns its data
* */
*/
async edit(session: Session, options: GuildEditOptions) {
const guild = await session.rest.runMethod<DiscordGuild>(session.rest, "PATCH", Routes.GUILDS(), {
name: options.name,

View File

@ -7,7 +7,8 @@ if (!token) {
throw new Error("Please provide a token");
}
const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages | GatewayIntents.GuildMembers | GatewayIntents.GuildBans
const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages |
GatewayIntents.GuildMembers | GatewayIntents.GuildBans;
const session = new Session({ token, intents });
session.on("ready", (payload) => {

View File

@ -233,7 +233,6 @@ export function CHANNEL_WEBHOOKS(channelId: Snowflake) {
return `/channels/${channelId}/webhooks`;
}
export function THREAD_START_PUBLIC(channelId: Snowflake, messageId: Snowflake) {
return `/channels/${channelId}/messages/${messageId}/threads`;
}
@ -271,8 +270,8 @@ export function THREAD_ARCHIVED_PUBLIC(channelId: Snowflake, options?: ListArchi
let url = `/channels/${channelId}/threads/archived/public?`;
if (options) {
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
if (options.limit) url += `&limit=${options.limit}`;
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
if (options.limit) url += `&limit=${options.limit}`;
}
return url;
@ -293,8 +292,8 @@ export function THREAD_ARCHIVED_PRIVATE_JOINED(channelId: Snowflake, options?: L
let url = `/channels/${channelId}/users/@me/threads/archived/private?`;
if (options) {
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
if (options.limit) url += `&limit=${options.limit}`;
if (options.before) url += `before=${new Date(options.before).toISOString()}`;
if (options.limit) url += `&limit=${options.limit}`;
}
return url;

9
util/builders.ts Normal file
View File

@ -0,0 +1,9 @@
import { ButtonBuilder, InputTextBuilder, SelectMenuBuilder } from "../mod.ts";
import { Snowflake } from "./Snowflake.ts";
export type AnyComponentBuilder = InputTextBuilder | SelectMenuBuilder | ButtonBuilder;
export type ComponentEmoji = {
id: Snowflake;
name: string;
animated?: boolean;
};

View File

@ -1171,6 +1171,8 @@ export interface DiscordSelectMenuComponent {
max_values?: number;
/** The choices! Maximum of 25 items. */
options: DiscordSelectOption[];
/** Whether or not this select menu is disabled */
disabled?: boolean;
}
export interface DiscordSelectOption {